Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,18 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## Unreleased
## [0.3.0] 2025-05-29

### Added

- Added the ability to scroll the preview pane on the right.
- A "... more" line will show if you need to scroll.
- This will give a warning if a panel can't completely rendered.
- There is a known issue that you can "scroll past" the last item, but the
last item will still render. You will need to scroll back up an equivalent
number of times. This will be future Gilbert's problem.

### Changed

- Move test result breakdown chart to Preview pane.

Expand Down
3 changes: 0 additions & 3 deletions PesterExplorer/Classes/classA.ps1

This file was deleted.

32 changes: 16 additions & 16 deletions PesterExplorer/PesterExplorer.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,25 @@
RootModule = 'PesterExplorer.psm1'

# Version number of this module.
ModuleVersion = '0.2.0'
ModuleVersion = '0.3.0'

# Supported PSEditions
# CompatiblePSEditions = @()

# ID used to uniquely identify this module
GUID = '1b8311c2-23fd-4a4c-90de-e17cfc306b04'
GUID = '1b8311c2-23fd-4a4c-90de-e17cfc306b04'

# Author of this module
Author = 'Gilbert Sanchez'
Author = 'Gilbert Sanchez'

# Company or vendor of this module
CompanyName = 'HeyItsGilbert'
CompanyName = 'HeyItsGilbert'

# Copyright statement for this module
Copyright = '(c) Gilbert Sanchez. All rights reserved.'
Copyright = '(c) Gilbert Sanchez. All rights reserved.'

# Description of the functionality provided by this module
Description = 'A TUI to explore Pester results.'
Description = 'A TUI to explore Pester results.'

# Minimum version of the PowerShell engine required by this module
PowerShellVersion = '7.0'
Expand All @@ -51,13 +51,13 @@
# ProcessorArchitecture = ''

# Modules that must be imported into the global environment prior to importing this module
RequiredModules = @(
RequiredModules = @(
@{
ModuleName = 'Pester'
ModuleName = 'Pester'
ModuleVersion = '5.0.0'
},
@{
ModuleName = 'PwshSpectreConsole'
ModuleName = 'PwshSpectreConsole'
ModuleVersion = '2.3.0'
}
)
Expand All @@ -81,13 +81,13 @@
FunctionsToExport = '*'

# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
CmdletsToExport = '*'
CmdletsToExport = '*'

# Variables to export from this module
VariablesToExport = '*'

# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
AliasesToExport = '*'
AliasesToExport = '*'

# DSC resources to export from this module
# DscResourcesToExport = @()
Expand All @@ -99,12 +99,12 @@
# FileList = @()

# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
PrivateData = @{
PrivateData = @{

PSData = @{

# Tags applied to this module. These help with module discovery in online galleries.
Tags = @(
Tags = @(
'Windows',
'Linux',
'macOS',
Expand All @@ -116,13 +116,13 @@
)

# A URL to the license for this module.
LicenseUri = 'https://github.com/HeyItsGilbert/PesterExplorer/blob/main/LICENSE'
LicenseUri = 'https://github.com/HeyItsGilbert/PesterExplorer/blob/main/LICENSE'

# A URL to the main website for this project.
ProjectUri = 'https://github.com/HeyItsGilbert/PesterExplorer'
ProjectUri = 'https://github.com/HeyItsGilbert/PesterExplorer'

# A URL to an icon representing this module.
IconUri = 'https://raw.githubusercontent.com/HeyItsGilbert/PesterExplorer/main/images/icon.png'
IconUri = 'https://raw.githubusercontent.com/HeyItsGilbert/PesterExplorer/main/images/icon.png'

# ReleaseNotes of this module
ReleaseNotes = 'https://github.com/HeyItsGilbert/PesterExplorer/blob/main/CHANGELOG.md'
Expand Down
6 changes: 3 additions & 3 deletions PesterExplorer/PesterExplorer.psm1
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#require -Module PwshSpectreConsole
# Dot source public/private functions
$classes = @(Get-ChildItem -Path (Join-Path -Path $PSScriptRoot -ChildPath 'Classes/*.ps1') -Recurse -ErrorAction Stop)
$public = @(Get-ChildItem -Path (Join-Path -Path $PSScriptRoot -ChildPath 'Public/*.ps1') -Recurse -ErrorAction Stop)
$public = @(Get-ChildItem -Path (Join-Path -Path $PSScriptRoot -ChildPath 'Public/*.ps1') -Recurse -ErrorAction Stop)
$private = @(Get-ChildItem -Path (Join-Path -Path $PSScriptRoot -ChildPath 'Private/*.ps1') -Recurse -ErrorAction Stop)
foreach ($import in @($classes + $public + $private)) {
foreach ($import in @($public + $private)) {
try {
. $import.FullName
} catch {
Expand Down
11 changes: 9 additions & 2 deletions PesterExplorer/Private/Get-ListPanel.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,15 @@ function Get-ListPanel {
[array]
$List,
[string]
$SelectedItem
$SelectedItem,
[string]$SelectedPane = "list"
)
$paneColor = if($SelectedPane -ne "list") {
# If the selected pane is not preview, return an empty panel
"blue"
} else {
"white"
}
$unselectedStyle = @{
RootColor = [Spectre.Console.Color]::Grey
SeparatorColor = [Spectre.Console.Color]::Grey
Expand Down Expand Up @@ -82,5 +89,5 @@ function Get-ListPanel {
}
$results |
Format-SpectreRows |
Format-SpectrePanel -Header "[white]List[/]" -Expand
Format-SpectrePanel -Header "[white]List[/]" -Expand -Color $paneColor
}
121 changes: 99 additions & 22 deletions PesterExplorer/Private/Get-PreviewPanel.ps1
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# spell-checker:ignore Renderable
function Get-PreviewPanel {
<#
.SYNOPSIS
Expand Down Expand Up @@ -47,104 +48,180 @@ function Get-PreviewPanel {
#>
[CmdletBinding()]
param (
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[hashtable]
$Items,
[Parameter(Mandatory)]
[string]
$SelectedItem
$SelectedItem,
$ScrollPosition = 0,
[Parameter()]
[ValidateNotNull()]
$PreviewHeight,
[Parameter()]
[ValidateNotNull()]
$PreviewWidth,
[string]$SelectedPane = "list"
)
Write-Debug "Get-PreviewPanel called with SelectedItem: $SelectedItem, ScrollPosition: $ScrollPosition"
$paneColor = if($SelectedPane -ne "preview") {
# If the selected pane is not preview, return an empty panel
"blue"
} else {
"white"
}
if($SelectedItem -like "*..") {
$formatSpectreAlignedSplat = @{
HorizontalAlignment = 'Center'
VerticalAlignment = 'Middle'
}
return "[grey]Please select an item.[/]" |
Format-SpectreAligned @formatSpectreAlignedSplat |
Format-SpectrePanel -Header "[white]Preview[/]" -Expand
Format-SpectrePanel -Header "[white]Preview[/]" -Expand -Color $paneColor
}
$object = $Items.Item($SelectedItem)
$result = @()
$results = @()
# SelectedItem can be a few different types:
# - A Pester object (Run, Container, Block, Test)

#region Breakdown
# Skip if the object is null or they are all zero.
if (
$null -ne $object.PassedCount -and
$null -ne $object.InconclusiveCount -and
$null -ne $object.SkippedCount -and
$null -ne $object.FailedCount -and
(
$object.PassedCount +
$object.InconclusiveCount +
$object.SkippedCount +
$object.FailedCount
[int]$object.PassedCount +
[int]$object.InconclusiveCount +
[int]$object.SkippedCount +
[int]$object.FailedCount
) -gt 0
) {
Write-Debug "Adding breakdown chart for $($object.Name)"
$data = @()
$data += New-SpectreChartItem -Label "Passed" -Value ($object.PassedCount) -Color "Green"
$data += New-SpectreChartItem -Label "Failed" -Value ($object.FailedCount) -Color "Red"
$data += New-SpectreChartItem -Label "Inconclusive" -Value ($object.InconclusiveCount) -Color "Grey"
$data += New-SpectreChartItem -Label "Skipped" -Value ($object.SkippedCount) -Color "Yellow"
$result += Format-SpectreBreakdownChart -Data $data
$results += Format-SpectreBreakdownChart -Data $data
}
#endregion Breakdown

# For Tests Let's print some more details
if ($object.GetType().Name -eq "Test") {
Write-Debug "Selected item is a Test: $($object.Name)"
$formatSpectrePanelSplat = @{
Header = "Test Result"
Border = "Rounded"
Color = "White"
}
$result += $object.Result |
$results += $object.Result |
Format-SpectrePanel @formatSpectrePanelSplat
# Show the code tested
$formatSpectrePanelSplat = @{
Header = "Test Code"
Border = "Rounded"
Color = "White"
}
$result += $object.ScriptBlock |
$results += $object.ScriptBlock |
Get-SpectreEscapedText |
Format-SpectrePanel @formatSpectrePanelSplat
} else {
Write-Debug "Selected item is a Pester object: $($object.Name)"
$data = Format-PesterTreeHash -Object $object
Write-Debug $($data|ConvertTo-Json -Depth 10)
$formatSpectrePanelSplat = @{
Header = "Results"
Border = "Rounded"
Color = "White"
}
$result += Format-SpectreTree -Data $data |
$results += Format-SpectreTree -Data $data |
Format-SpectrePanel @formatSpectrePanelSplat
}

if($null -ne $object.StandardOutput){
Write-Debug "Adding standard output for $($object.Name)"
$formatSpectrePanelSplat = @{
Header = "Standard Output"
Border = "Ascii"
Color = "White"
}
$result += $object.StandardOutput |
$results += $object.StandardOutput |
Get-SpectreEscapedText |
Format-SpectrePanel @formatSpectrePanelSplat

}

# Print errors if they exist.
if($object.ErrorRecord.Count -gt 0) {
Write-Debug "Adding error records for $($object.Name)"
$errorRecords = @()
$object.ErrorRecord | ForEach-Object {
$errorRecords += $_ |
Format-SpectreException -ExceptionFormat ShortenEverything
}
$formatSpectrePanelSplat = @{
Header = "Errors"
Border = "Rounded"
Color = "Red"
}
$result += $errorRecords |
Format-SpectreRows |
$results += $errorRecords | Format-SpectreRows | Format-SpectrePanel -Header "Errors" -Border "Rounded" -Color "Red"
}

$formatSpectrePanelSplat = @{
Header = "[white]Preview[/]"
Color = $paneColor
Height = $PreviewHeight
Width = $PreviewWidth
Expand = $true
}

if($scrollPosition -ge $results.Count) {
# If the scroll position is greater than the number of items,
# reset it to the last item
Write-Debug "Resetting ScrollPosition to last item."
$scrollPosition = $results.Count - 1
}
# If the scroll position is out of bounds, reset it
if ($scrollPosition -lt 0) {
Write-Debug "Resetting ScrollPosition to 0."
$scrollPosition = 0
}

if($results.Count -eq 0) {
# If there are no results, return an empty panel
return "[grey]No results to display.[/]" |
Format-SpectreAligned -HorizontalAlignment Center -VerticalAlignment Middle |
Format-SpectrePanel @formatSpectrePanelSplat
} else {
Write-Debug "Reducing Preview List: $($results.Count), ScrollPosition: $scrollPosition"

# Determine the height of each item in the results
$totalHeight = 3
$reducedList = @()
if($ScrollPosition -ne 0) {
# If the scroll position is not zero, add a "back" item
$reducedList += "[grey]...[/]"
}
for ($i = $scrollPosition; $i -le $array.Count; $i++) {
$itemHeight = Get-SpectreRenderableSize $results[$i]
$totalHeight += $itemHeight.Height
if ($totalHeight -gt $PreviewHeight) {
if($i -eq $scrollPosition) {
# If the first item already exceeds the height, stop here
Write-Debug "First item exceeds preview height. Stopping."
$reducedList += ":police_car_light:The next item is too large to display! Please resize your terminal.:police_car_light:" |
Format-SpectreAligned -HorizontalAlignment Center -VerticalAlignment Middle |
Format-SpectrePanel -Header ":police_car_light: [red]Warning[/]" -Color 'red' -Border Double
break
}
# If the total height exceeds the preview height, stop adding items
Write-Debug "Total height exceeded preview height. Stopping at item $i."
$reducedList += "[blue]...more.[/] [grey]Switch to Panel and scroll with keys.[/]"
break
}
$reducedList += $results[$i]
}
}

return $result |
Format-SpectreGrid |
Format-SpectrePanel -Header "[white]Preview[/]" -Expand
return $reducedList | Format-SpectreRows |
Format-SpectrePanel @formatSpectrePanelSplat
#Format-ScrollableSpectrePanel @formatScrollableSpectrePanelSplat
}
4 changes: 3 additions & 1 deletion PesterExplorer/Private/Get-ShortcutKeyPanel.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@ function Get-ShortcutKeyPanel {
[CmdletBinding()]
$shortcutKeys = @(
"Up, Down - Navigate",
"Home, End - Jump to Top/Bottom",
"PageUp, PageDown - Scroll",
"Enter - Explore",
"Tab - Switch Panel",
"Esc - Back",
"Ctrl+C - Exit"
# TODO: Add a key to jump to the test
)
$formatSpectreAlignedSplat = @{
HorizontalAlignment = 'Center'
Expand Down
Loading
Loading