diff --git a/README.md b/README.md index 0798dc32..cda9dea9 100644 --- a/README.md +++ b/README.md @@ -255,6 +255,7 @@ jobs: | **Input** | **Description** | **Default** | |--------------------------------------|--------------------------------------------------------------------------------------------------------|---------------------------------| | `Path` | Path to where tests are located or a configuration file. | *(none)* | +| `ReportAsJson` | Output generated reports in JSON format in addition to the configured format through Pester. | `true` | | `Run_Path` | Directories/files to be searched for tests. | *(none)* | | `Run_ExcludePath` | Directories/files to exclude from the run. | *(none)* | | `Run_ScriptBlock` | ScriptBlocks containing tests to be executed. | *(none)* | diff --git a/action.yml b/action.yml index 6d621398..546ac0ac 100644 --- a/action.yml +++ b/action.yml @@ -10,6 +10,11 @@ inputs: description: | Path to where tests are located or a configuration file. required: false + ReportAsJson: + description: | + Output generated reports in JSON format in addition to the configured format through Pester. + required: false + default: 'true' Run_Path: description: | Directories to be searched for tests, paths directly to test files, or combination of both. @@ -267,6 +272,8 @@ runs: shell: pwsh continue-on-error: true working-directory: ${{ inputs.WorkingDirectory }} + env: + PSMODULE_INVOKE_PESTER_INPUT_ReportAsJson: ${{ inputs.ReportAsJson }} id: test run: ${{ github.action_path }}/scripts/main.ps1 @@ -276,6 +283,8 @@ runs: with: name: ${{ steps.test.outputs.TestSuiteName }}-TestResults path: ${{ steps.test.outputs.TestResultOutputPath }} + retention-days: 1 + if-no-files-found: error - name: Upload code coverage report - [${{ steps.test.outputs.TestSuiteName }}-CodeCoverage] uses: actions/upload-artifact@v4 @@ -283,6 +292,8 @@ runs: with: name: ${{ steps.test.outputs.TestSuiteName }}-CodeCoverage path: ${{ steps.test.outputs.CodeCoverageOutputPath }} + retention-days: 1 + if-no-files-found: error - name: Status shell: pwsh diff --git a/scripts/Helpers.psm1 b/scripts/Helpers.psm1 index 405bc219..27869606 100644 --- a/scripts/Helpers.psm1 +++ b/scripts/Helpers.psm1 @@ -384,7 +384,7 @@ function New-PesterConfigurationHashtable { $result } -filter Convert-PesterConfigurationToHashtable { +filter ConvertFrom-PesterConfiguration { <# .SYNOPSIS Converts a PesterConfiguration object into a hashtable containing only modified settings. @@ -396,7 +396,7 @@ filter Convert-PesterConfigurationToHashtable { When the -IncludeDefaults switch is provided, it includes settings that have not been modified, outputting their default values. .EXAMPLE - New-PesterConfiguration | Convert-PesterConfigurationToHashtable | Format-Hashtable + New-PesterConfiguration | ConvertFrom-PesterConfiguration -AsHashtable | Format-Hashtable Output: ```powershell @@ -475,7 +475,7 @@ filter Convert-PesterConfigurationToHashtable { .EXAMPLE $config = New-PesterConfiguration $config.Run.PassThru = $true - Convert-PesterConfigurationToHashtable -PesterConfiguration $config -OnlyModified | Format-Hashtable + ConvertFrom-PesterConfiguration -PesterConfiguration $config -OnlyModified -AsHashtable | Format-Hashtable Output: ```powershell @@ -504,33 +504,57 @@ filter Convert-PesterConfigurationToHashtable { # Include default values in the output hashtable. [Parameter()] - [switch] $OnlyModified + [switch] $OnlyModified, + + # Output as a hashtable + [Parameter()] + [switch] $AsHashtable ) # Prepare the output hashtable $result = @{} # Iterate over each top-level category (Run, Filter, etc.) - foreach ($category in $PesterConfiguration.PSObject.Properties.Name) { - $categoryObj = $PesterConfiguration.$category + foreach ($category in $PesterConfiguration.PSObject.Properties) { + $categoryName = $category.Name + $categoryValue = $category.Value $subHash = @{} # Iterate over each setting within the category - foreach ($settingName in $categoryObj.PSObject.Properties.Name) { - if ($OnlyModified) { - if ($setting.IsModified) { - $subHash[$settingName] = $setting.Value + foreach ($setting in $categoryValue.PSObject.Properties) { + $settingName = $setting.Name + $settingValue = $setting.Value + $settingValue = $OnlyModified ? $settingValue.Value : ($settingValue.IsModified ? $settingValue.Value : $settingValue.Default) + Write-Verbose "[$categoryName] [$settingName] = $settingValue" -Verbose + if ($categoryName -eq 'Run' -and $settingName -eq 'Container') { + Write-Verbose ($settingValue | ConvertTo-Json -Depth 1 | Out-String) -Verbose + $containers = [System.Collections.Generic.List[object]]::new() + foreach ($container in $settingValue) { + $containers.Add( + [pscustomobject]@{ + Path = $container.Item.FullName + Data = $container.Data + } + ) } + $subHash[$settingName] = $containers } else { - $subHash[$settingName] = if ($setting.IsModified) { $setting.Value } else { $setting.Default } + $subHash[$settingName] = $settingValue } } # Add the category sub-hashtable to the result even if empty, to preserve structure. - $result[$category] = $subHash + if ($AsHashtable) { + $result[$categoryName] = $subHash + } else { + $result[$categoryName] = [pscustomobject]$subHash + } } - return $result + if ($AsHashtable) { + return $result + } + return [PSCustomObject]$result } filter Clear-PesterConfigurationEmptyValue { @@ -639,38 +663,142 @@ filter Get-PesterTestTree { Mandatory, ValueFromPipeline )] - [object] $InputObject + [object] $InputObject, + + # Path to this node. + [Parameter()] + [string[]] $Path ) + $children = [System.Collections.Generic.List[object]]::new() Write-Verbose "Processing object of type: $($InputObject.GetType().Name)" switch ($InputObject.GetType().Name) { 'Run' { - $inputObject | Add-Member -MemberType NoteProperty -Name Depth -Value 0 - $inputObject | Add-Member -MemberType NoteProperty -Name ItemType -Value 'TestSuite' - $inputObject | Add-Member -MemberType NoteProperty -Name Name -Value $($testResults.Configuration.TestResult.TestSuiteName.Value) -Force - $inputObject | Add-Member -MemberType NoteProperty -Name Children -Value $inputObject.Containers - $inputObject - $inputObject.Containers | Get-PesterTestTree + $Name = $InputObject.Configuration.TestResult.TestSuiteName.Value + $childPath = @($Path, $Name) + $children.Add(($InputObject.Containers | Get-PesterTestTree -Path $childPath)) + $configuration = $InputObject.Configuration | ConvertFrom-PesterConfiguration + [pscustomobject]@{ + Depth = 0 + ItemType = 'TestSuite' + Name = $Name + Path = @() + Children = $children + Result = $InputObject.Result + FailedCount = $InputObject.FailedCount + FailedBlocksCount = $InputObject.FailedBlocksCount + FailedContainersCount = $InputObject.FailedContainersCount + PassedCount = $InputObject.PassedCount + SkippedCount = $InputObject.SkippedCount + InconclusiveCount = $InputObject.InconclusiveCount + NotRunCount = $InputObject.NotRunCount + TotalCount = $InputObject.TotalCount + Executed = $InputObject.Executed + ExecutedAt = $InputObject.ExecutedAt + Version = $InputObject.Version + PSVersion = $InputObject.PSVersion + Plugins = $InputObject.Plugins + PluginConfiguration = $InputObject.PluginConfiguration + PluginData = $InputObject.PluginData + Configuration = $configuration + Duration = [int64]$InputObject.Duration.Ticks + DiscoveryDuration = [int64]$InputObject.DiscoveryDuration.Ticks + UserDuration = [int64]$InputObject.UserDuration.Ticks + FrameworkDuration = [int64]$InputObject.FrameworkDuration.Ticks + } } 'Container' { - $inputObject | Add-Member -MemberType NoteProperty -Name Depth -Value 1 - $inputObject | Add-Member -MemberType NoteProperty -Name ItemType -Value 'Container' - $inputObject | Add-Member -MemberType NoteProperty -Name Name -Value ((Split-Path $InputObject.Name -Leaf) -replace '.Tests.ps1') -Force - $inputObject | Add-Member -MemberType NoteProperty -Name Children -Value $InputObject.Blocks - $inputObject - $InputObject.Blocks | Get-PesterTestTree + $Name = (Split-Path $InputObject.Name -Leaf) -replace '.Tests.ps1' + $childPath = @($Path, $Name) + $children.Add(($InputObject.Blocks | Get-PesterTestTree -Path $childPath)) + [pscustomobject]@{ + Depth = 1 + ItemType = 'Container' + Name = $Name + Path = $Path + Children = $children + Result = $InputObject.Result + FailedCount = $InputObject.FailedCount + FailedBlocksCount = $InputObject.FailedBlocksCount + FailedContainersCount = $InputObject.FailedContainersCount + PassedCount = $InputObject.PassedCount + SkippedCount = $InputObject.SkippedCount + InconclusiveCount = $InputObject.InconclusiveCount + NotRunCount = $InputObject.NotRunCount + TotalCount = $InputObject.TotalCount + Executed = $InputObject.Executed + ExecutedAt = $InputObject.ExecutedAt + Version = $InputObject.Version + PSVersion = $InputObject.PSVersion + Plugins = $InputObject.Plugins + PluginConfiguration = $InputObject.PluginConfiguration + PluginData = $InputObject.PluginData + Duration = [int64]$InputObject.Duration.Ticks + DiscoveryDuration = [int64]$InputObject.DiscoveryDuration.Ticks + UserDuration = [int64]$InputObject.UserDuration.Ticks + FrameworkDuration = [int64]$InputObject.FrameworkDuration.Ticks + } } 'Block' { - $inputObject | Add-Member -MemberType NoteProperty -Name Depth -Value ($InputObject.Path.Count + 1) - $inputObject | Add-Member -MemberType NoteProperty -Name Name -Value ($InputObject.ExpandedName) -Force - $inputObject | Add-Member -MemberType NoteProperty -Name Children -Value $InputObject.Order - $inputObject - $InputObject.Order | Get-PesterTestTree + $Name = ($InputObject.ExpandedName) + $childPath = @($Path, $Name) + $children.Add(($InputObject.Order | Get-PesterTestTree -Path $childPath)) + [pscustomobject]@{ + Depth = ($InputObject.Path.Count + 1) + ItemType = $InputObject.ItemType + Name = $Name + Path = $Path + Children = $children + Result = $InputObject.Result + FailedCount = $InputObject.FailedCount + FailedBlocksCount = $InputObject.FailedBlocksCount + FailedContainersCount = $InputObject.FailedContainersCount + PassedCount = $InputObject.PassedCount + SkippedCount = $InputObject.SkippedCount + InconclusiveCount = $InputObject.InconclusiveCount + NotRunCount = $InputObject.NotRunCount + TotalCount = $InputObject.TotalCount + Executed = $InputObject.Executed + ExecutedAt = $InputObject.ExecutedAt + Version = $InputObject.Version + PSVersion = $InputObject.PSVersion + Plugins = $InputObject.Plugins + PluginConfiguration = $InputObject.PluginConfiguration + PluginData = $InputObject.PluginData + Duration = [int64]$InputObject.Duration.Ticks + DiscoveryDuration = [int64]$InputObject.DiscoveryDuration.Ticks + UserDuration = [int64]$InputObject.UserDuration.Ticks + FrameworkDuration = [int64]$InputObject.FrameworkDuration.Ticks + } } 'Test' { - $inputObject | Add-Member -MemberType NoteProperty -Name Depth -Value ($InputObject.Path.Count + 1) - $inputObject | Add-Member -MemberType NoteProperty -Name Name -Value ($InputObject.ExpandedName) -Force - $inputObject + $Name = ($InputObject.ExpandedName) + [pscustomobject]@{ + Depth = ($InputObject.Path.Count + 1) + ItemType = $InputObject.ItemType + Name = $Name + Path = $Path + Result = $InputObject.Result + FailedCount = $InputObject.FailedCount + FailedBlocksCount = $InputObject.FailedBlocksCount + FailedContainersCount = $InputObject.FailedContainersCount + PassedCount = $InputObject.PassedCount + SkippedCount = $InputObject.SkippedCount + InconclusiveCount = $InputObject.InconclusiveCount + NotRunCount = $InputObject.NotRunCount + TotalCount = $InputObject.TotalCount + Executed = $InputObject.Executed + ExecutedAt = $InputObject.ExecutedAt + Version = $InputObject.Version + PSVersion = $InputObject.PSVersion + Plugins = $InputObject.Plugins + PluginConfiguration = $InputObject.PluginConfiguration + PluginData = $InputObject.PluginData + Duration = [int64]$InputObject.Duration.Ticks + DiscoveryDuration = [int64]$InputObject.DiscoveryDuration.Ticks + UserDuration = [int64]$InputObject.UserDuration.Ticks + FrameworkDuration = [int64]$InputObject.FrameworkDuration.Ticks + } } default { Write-Error "Unknown object type: [$($InputObject.GetType().Name)]" @@ -853,7 +981,7 @@ filter Set-PesterReportConfigurationSummary { [Pester.Run] $TestResults ) - $configurationHashtable = $TestResults.Configuration | Convert-PesterConfigurationToHashtable | Format-Hashtable + $configurationHashtable = $TestResults.Configuration | ConvertFrom-PesterConfiguration -AsHashtable | Format-Hashtable Details 'Configuration' { CodeBlock 'pwsh' { diff --git a/scripts/init.ps1 b/scripts/init.ps1 index ea7cafb6..0bba1f0e 100644 --- a/scripts/init.ps1 +++ b/scripts/init.ps1 @@ -176,7 +176,7 @@ LogGroup 'Init - Export containers' { Write-Output "Containers from configuration: [$($existingContainers.Count)]" foreach ($existingContainer in $existingContainers) { Write-Output "Processing container [$existingContainer]" - $containers += $existingContainer | Convert-PesterConfigurationToHashtable + $containers += $existingContainer | ConvertTo-Hashtable } } Write-Output "Containers from configuration: [$($containers.Count)]" @@ -223,8 +223,8 @@ LogGroup 'Init - Export containers' { LogGroup 'Init - Export configuration' { $artifactName = $configuration.TestResult.TestSuiteName ?? 'Pester' - $configuration.TestResult.OutputPath = "$pwd/test_reports/$artifactName-TestResult-Report.xml" - $configuration.CodeCoverage.OutputPath = "$pwd/test_reports/$artifactName-CodeCoverage-Report.xml" + $configuration.TestResult.OutputPath = "$pwd/TestResult/$artifactName-TestResult-Report.xml" + $configuration.CodeCoverage.OutputPath = "$pwd/CodeCoverage/$artifactName-CodeCoverage-Report.xml" $configuration.Run.PassThru = $true Format-Hashtable -Hashtable $configuration diff --git a/scripts/main.ps1 b/scripts/main.ps1 index fdb99199..51d32736 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -85,18 +85,32 @@ LogGroup 'Eval - Test results summary' { } LogGroup 'Eval - Set outputs' { - Set-GitHubOutput -Name 'TestSuiteName' -Value $testResults.Configuration.TestResult.TestSuiteName.Value - Set-GitHubOutput -Name 'TestResultEnabled' -Value $testResults.Configuration.TestResult.Enabled.Value - Set-GitHubOutput -Name 'TestResultOutputPath' -Value $testResults.Configuration.TestResult.OutputPath.Value - Set-GitHubOutput -Name 'CodeCoverageEnabled' -Value $testResults.Configuration.CodeCoverage.Enabled.Value - Set-GitHubOutput -Name 'CodeCoverageOutputPath' -Value $testResults.Configuration.CodeCoverage.OutputPath.Value + $testResultOutputFolderPath = $testResults.Configuration.TestResult.OutputPath.Value | Split-Path -Parent + $codeCoverageOutputFolderPath = $testResults.Configuration.CodeCoverage.OutputPath.Value | Split-Path -Parent [pscustomobject]@{ TestSuiteName = $testResults.Configuration.TestResult.TestSuiteName.Value TestResultEnabled = $testResults.Configuration.TestResult.Enabled.Value - TestResultOutputPath = $testResults.Configuration.TestResult.OutputPath.Value + TestResultOutputPath = $testResultOutputFolderPath CodeCoverageEnabled = $testResults.Configuration.CodeCoverage.Enabled.Value - CodeCoverageOutputPath = $testResults.Configuration.CodeCoverage.OutputPath.Value + CodeCoverageOutputPath = $codeCoverageOutputFolderPath } | Format-List | Out-String + Set-GitHubOutput -Name 'TestSuiteName' -Value $testResults.Configuration.TestResult.TestSuiteName.Value + Set-GitHubOutput -Name 'TestResultEnabled' -Value $testResults.Configuration.TestResult.Enabled.Value + Set-GitHubOutput -Name 'TestResultOutputPath' -Value $testResultOutputFolderPath + Set-GitHubOutput -Name 'CodeCoverageEnabled' -Value $testResults.Configuration.CodeCoverage.Enabled.Value + Set-GitHubOutput -Name 'CodeCoverageOutputPath' -Value $codeCoverageOutputFolderPath + + if ($env:PSMODULE_INVOKE_PESTER_INPUT_ReportAsJson -eq 'true' -and $testResults.Configuration.TestResult.Enabled.Value) { + $jsonOutputPath = $testResults.Configuration.TestResult.OutputPath.Value -Replace '\.xml$', '.json' + Write-Output "Exporting test results to [$jsonOutputPath]" + $testResults | Get-PesterTestTree | ConvertTo-Json -Depth 100 -Compress | Out-File -FilePath $jsonOutputPath + } + + if ($env:PSMODULE_INVOKE_PESTER_INPUT_ReportAsJson -eq 'true' -and $testResults.Configuration.CodeCoverage.Enabled.Value) { + $jsonOutputPath = $testResults.Configuration.CodeCoverage.OutputPath.Value -Replace '\.xml$', '.json' + Write-Output "Exporting code coverage results to [$jsonOutputPath]" + $testResults.CodeCoverage | ConvertTo-Json -Depth 100 -Compress | Out-File -FilePath $jsonOutputPath + } } LogGroup 'Exit' { diff --git a/tests/1-Simple/Emoji.Tests.ps1 b/tests/1-Simple/Emoji.Tests.ps1 index 2e6e3b19..8ca4d811 100644 --- a/tests/1-Simple/Emoji.Tests.ps1 +++ b/tests/1-Simple/Emoji.Tests.ps1 @@ -10,39 +10,17 @@ param() BeforeAll { - $script:emojis = @( - @{ Name = 'apple'; Symbol = '🍎'; Kind = 'Fruit' } - @{ Name = 'beaming face with smiling eyes'; Symbol = '😁'; Kind = 'Face' } - @{ Name = 'cactus'; Symbol = '🌵'; Kind = 'Plant' } - @{ Name = 'giraffe'; Symbol = '🦒'; Kind = 'Animal' } - @{ Name = 'pencil'; Symbol = '✏️'; Kind = 'Item' } - @{ Name = 'penguin'; Symbol = '🐧'; Kind = 'Animal' } - @{ Name = 'pensive'; Symbol = '😔'; Kind = 'Face' } - @{ Name = 'slightly smiling face'; Symbol = '🙂'; Kind = 'Face' } - @{ Name = 'smiling face with smiling eyes'; Symbol = '😊'; Kind = 'Face' } - ) | ForEach-Object { [PSCustomObject]$_ } - - function Get-Emoji { - <# - .SYNOPSIS - Get emoji by name. - #> - [CmdletBinding()] - param( - [string]$Name = '*' - ) - $script:emojis | Where-Object Name -Like $Name | ForEach-Object Symbol - } + . $PSCommandPath.Replace('.Tests.ps1', '.ps1') } Describe 'Get-Emoji' { Context 'Lookup by whole name' { It 'Returns 🌵 (cactus)' { - Get-Emoji -Name cactus | Should -Be '🌵' + (Get-Emoji -Name cactus).Symbol | Should -Be '🌵' } It 'Returns 🦒 (giraffe)' { - Get-Emoji -Name giraffe | Should -Be '🦒' + Get-Emoji -Name giraffe -Property Symbol | Should -Be '🦒' } } @@ -52,15 +30,15 @@ Describe 'Get-Emoji' { $penEmojis = Get-Emoji -Name pen* } It 'Returns ✏️ (pencil)' { - $penEmojis | Should -Contain '✏️' + $penEmojis.Symbol | Should -Contain '✏️' } It 'Returns 🐧 (penguin)' { - $penEmojis | Should -Contain '🐧' + $penEmojis.Kind | Should -Contain 'Animal' } It 'Returns 😔 (pensive)' { - $penEmojis | Should -Contain '😔' + $penEmojis.Name | Should -Contain 'pensive' } } @@ -70,15 +48,15 @@ Describe 'Get-Emoji' { } It 'Returns 🙂 (slightly smiling face)' { - $smilingEmojis | Should -Contain '🙂' + $smilingEmojis.Symbol | Should -Contain '🙂' } It 'Returns 😁 (beaming face with smiling eyes)' { - $smilingEmojis | Should -Contain '😁' + $smilingEmojis.Kind | Should -Contain 'Face' } It 'Returns 😊 (smiling face with smiling eyes)' { - $smilingEmojis | Should -Contain '😊' + $smilingEmojis.Name | Should -Contain 'smiling face with smiling eyes' } } } diff --git a/tests/1-Simple/Emoji.ps1 b/tests/1-Simple/Emoji.ps1 new file mode 100644 index 00000000..9df3de66 --- /dev/null +++ b/tests/1-Simple/Emoji.ps1 @@ -0,0 +1,40 @@ +$script:emojis = @( + @{ Name = 'apple'; Symbol = '🍎'; Kind = 'Fruit' } + @{ Name = 'beaming face with smiling eyes'; Symbol = '😁'; Kind = 'Face' } + @{ Name = 'cactus'; Symbol = '🌵'; Kind = 'Plant' } + @{ Name = 'giraffe'; Symbol = '🦒'; Kind = 'Animal' } + @{ Name = 'pencil'; Symbol = '✏️'; Kind = 'Item' } + @{ Name = 'penguin'; Symbol = '🐧'; Kind = 'Animal' } + @{ Name = 'pensive'; Symbol = '😔'; Kind = 'Face' } + @{ Name = 'slightly smiling face'; Symbol = '🙂'; Kind = 'Face' } + @{ Name = 'smiling face with smiling eyes'; Symbol = '😊'; Kind = 'Face' } +) | ForEach-Object { [PSCustomObject]$_ } + +function Get-Emoji { + <# + .SYNOPSIS + Get emoji by name. + #> + [CmdletBinding()] + param( + [string] $Name = '*', + [string] $Property + ) + if ($Property) { + $script:emojis | Where-Object Name -Like $Name | ForEach-Object $Property + } else { + $script:emojis | Where-Object Name -Like $Name + } +} + +function Get-EmojiByKind { + <# + .SYNOPSIS + Get emoji by kind. + #> + [CmdletBinding()] + param( + [string] $Kind + ) + $script:emojis | Where-Object Kind -eq $Kind +} diff --git a/tests/2-Standard/Emoji.Configuration.ps1 b/tests/2-Standard/Emoji.Configuration.ps1 index d91b1e1b..d09052b1 100644 --- a/tests/2-Standard/Emoji.Configuration.ps1 +++ b/tests/2-Standard/Emoji.Configuration.ps1 @@ -1,13 +1,16 @@ @{ - Run = @{ + Run = @{ Path = $PSScriptRoot PassThru = $true } - TestResult = @{ + TestResult = @{ Enabled = $true TestSuiteName = 'Standard' } - Output = @{ + CodeCoverage = @{ + Enabled = $true + } + Output = @{ CIFormat = 'Auto' StackTraceVerbosity = 'Filtered' Verbosity = 'Detailed' diff --git a/tests/2-Standard/Emoji.Tests.ps1 b/tests/2-Standard/Emoji.Tests.ps1 index 7e984bc6..4960cdef 100644 --- a/tests/2-Standard/Emoji.Tests.ps1 +++ b/tests/2-Standard/Emoji.Tests.ps1 @@ -21,48 +21,47 @@ Describe 'Emoji' { Describe 'Get-Emoji' { Context 'Lookup by whole name' { It 'Returns 🌵 (cactus)' { - Get-Emoji -Name cactus | Should -Be '🌵' + (Get-Emoji -Name cactus).Symbol | Should -Be '🌵' } It 'Returns 🦒 (giraffe)' { - Get-Emoji -Name giraffe | Should -Be '🦒' + Get-Emoji -Name giraffe -Property Symbol | Should -Be '🦒' } } Context 'Lookup by wildcard' { Context 'by prefix' { BeforeAll { - $script:emojis = Get-Emoji -Name pen* + $penEmojis = Get-Emoji -Name pen* } - It 'Returns ✏️ (pencil)' { - $script:emojis | Should -Contain '✏️' + $penEmojis.Symbol | Should -Contain '✏️' } It 'Returns 🐧 (penguin)' { - $script:emojis | Should -Contain '🐧' + $penEmojis.Kind | Should -Contain 'Animal' } It 'Returns 😔 (pensive)' { - $script:emojis | Should -Contain '😔' + $penEmojis.Name | Should -Contain 'pensive' } } Context 'by contains' { BeforeAll { - $script:emojis = Get-Emoji -Name *smiling* + $smilingEmojis = Get-Emoji -Name *smiling* } It 'Returns 🙂 (slightly smiling face)' { - $script:emojis | Should -Contain '🙂' + $smilingEmojis.Symbol | Should -Contain '🙂' } It 'Returns 😁 (beaming face with smiling eyes)' { - $script:emojis | Should -Contain '😁' + $smilingEmojis.Kind | Should -Contain 'Face' } It 'Returns 😊 (smiling face with smiling eyes)' { - $script:emojis | Should -Contain '😊' + $smilingEmojis.Name | Should -Contain 'smiling face with smiling eyes' } } } diff --git a/tests/2-Standard/Emoji.psm1 b/tests/2-Standard/Emoji.psm1 index 12996f98..2929ff24 100644 --- a/tests/2-Standard/Emoji.psm1 +++ b/tests/2-Standard/Emoji.psm1 @@ -17,7 +17,24 @@ function Get-Emoji { #> [CmdletBinding()] param( - [string]$Name = '*' + [string] $Name = '*', + [string] $Property ) - $script:emojis | Where-Object Name -Like $Name | ForEach-Object Symbol + if ($Property) { + $script:emojis | Where-Object Name -Like $Name | ForEach-Object $Property + } else { + $script:emojis | Where-Object Name -Like $Name + } +} + +function Get-EmojiByKind { + <# + .SYNOPSIS + Get emoji by kind. + #> + [CmdletBinding()] + param( + [string] $Kind + ) + $script:emojis | Where-Object Kind -EQ $Kind } diff --git a/tests/3-Advanced/Emoji/Emoji.Tests.ps1 b/tests/3-Advanced/Emoji/Emoji.Tests.ps1 index 7e984bc6..4960cdef 100644 --- a/tests/3-Advanced/Emoji/Emoji.Tests.ps1 +++ b/tests/3-Advanced/Emoji/Emoji.Tests.ps1 @@ -21,48 +21,47 @@ Describe 'Emoji' { Describe 'Get-Emoji' { Context 'Lookup by whole name' { It 'Returns 🌵 (cactus)' { - Get-Emoji -Name cactus | Should -Be '🌵' + (Get-Emoji -Name cactus).Symbol | Should -Be '🌵' } It 'Returns 🦒 (giraffe)' { - Get-Emoji -Name giraffe | Should -Be '🦒' + Get-Emoji -Name giraffe -Property Symbol | Should -Be '🦒' } } Context 'Lookup by wildcard' { Context 'by prefix' { BeforeAll { - $script:emojis = Get-Emoji -Name pen* + $penEmojis = Get-Emoji -Name pen* } - It 'Returns ✏️ (pencil)' { - $script:emojis | Should -Contain '✏️' + $penEmojis.Symbol | Should -Contain '✏️' } It 'Returns 🐧 (penguin)' { - $script:emojis | Should -Contain '🐧' + $penEmojis.Kind | Should -Contain 'Animal' } It 'Returns 😔 (pensive)' { - $script:emojis | Should -Contain '😔' + $penEmojis.Name | Should -Contain 'pensive' } } Context 'by contains' { BeforeAll { - $script:emojis = Get-Emoji -Name *smiling* + $smilingEmojis = Get-Emoji -Name *smiling* } It 'Returns 🙂 (slightly smiling face)' { - $script:emojis | Should -Contain '🙂' + $smilingEmojis.Symbol | Should -Contain '🙂' } It 'Returns 😁 (beaming face with smiling eyes)' { - $script:emojis | Should -Contain '😁' + $smilingEmojis.Kind | Should -Contain 'Face' } It 'Returns 😊 (smiling face with smiling eyes)' { - $script:emojis | Should -Contain '😊' + $smilingEmojis.Name | Should -Contain 'smiling face with smiling eyes' } } } diff --git a/tests/3-Advanced/Emoji/Emoji.psm1 b/tests/3-Advanced/Emoji/Emoji.psm1 index 12996f98..2929ff24 100644 --- a/tests/3-Advanced/Emoji/Emoji.psm1 +++ b/tests/3-Advanced/Emoji/Emoji.psm1 @@ -17,7 +17,24 @@ function Get-Emoji { #> [CmdletBinding()] param( - [string]$Name = '*' + [string] $Name = '*', + [string] $Property ) - $script:emojis | Where-Object Name -Like $Name | ForEach-Object Symbol + if ($Property) { + $script:emojis | Where-Object Name -Like $Name | ForEach-Object $Property + } else { + $script:emojis | Where-Object Name -Like $Name + } +} + +function Get-EmojiByKind { + <# + .SYNOPSIS + Get emoji by kind. + #> + [CmdletBinding()] + param( + [string] $Kind + ) + $script:emojis | Where-Object Kind -EQ $Kind }