Tests/Tests-NewGradientColorArray.ps1
|
#Requires -Modules Pester BeforeAll { # Import the module $ModuleRoot = Split-Path -Parent $PSScriptRoot Import-Module "$ModuleRoot\PSWriteColorEX.psd1" -Force # Dot-source the class file and private function for testing . "$ModuleRoot\Classes\PSColorStyle.ps1" . "$ModuleRoot\Private\New-GradientColorArray.ps1" } Describe 'New-GradientColorArray' -Tag 'Unit', 'Function', 'Gradient' { Context 'Basic Functionality' { It 'Generates gradient array' { $result = New-GradientColorArray -Colors @('Red', 'Blue') -Steps 10 -Mode TrueColor $result | Should -Not -BeNullOrEmpty $result.Count | Should -Be 10 } It 'Accepts color names' { $result = New-GradientColorArray -Colors @('Red', 'Green', 'Blue') -Steps 5 -Mode TrueColor $result.Count | Should -Be 5 } It 'Accepts hex colors' { $result = New-GradientColorArray -Colors @('#FF0000', '#0000FF') -Steps 10 -Mode TrueColor $result.Count | Should -Be 10 } It 'Accepts RGB arrays' { $result = New-GradientColorArray -Colors @(@(255, 0, 0), @(0, 0, 255)) -Steps 10 -Mode TrueColor $result.Count | Should -Be 10 } It 'Accepts mixed color formats' { $result = New-GradientColorArray -Colors @('Red', '#00FF00', @(0, 0, 255)) -Steps 10 -Mode TrueColor $result.Count | Should -Be 10 } } Context 'Parameter Validation' { It 'Requires at least 2 colors' { { New-GradientColorArray -Colors @('Red') -Steps 10 -Mode TrueColor } | Should -Throw } It 'Accepts exactly 2 colors' { { New-GradientColorArray -Colors @('Red', 'Blue') -Steps 10 -Mode TrueColor } | Should -Not -Throw } It 'Accepts more than 2 colors' { { New-GradientColorArray -Colors @('Red', 'Green', 'Blue', 'Yellow') -Steps 20 -Mode TrueColor } | Should -Not -Throw } It 'Requires Steps parameter' { { New-GradientColorArray -Colors @('Red', 'Blue') -Mode TrueColor } | Should -Throw } It 'Requires Mode parameter' { { New-GradientColorArray -Colors @('Red', 'Blue') -Steps 10 } | Should -Throw } It 'Accepts TrueColor mode' { { New-GradientColorArray -Colors @('Red', 'Blue') -Steps 10 -Mode TrueColor } | Should -Not -Throw } It 'Accepts ANSI8 mode' { { New-GradientColorArray -Colors @('Red', 'Blue') -Steps 10 -Mode ANSI8 } | Should -Not -Throw } It 'Rejects invalid mode' { { New-GradientColorArray -Colors @('Red', 'Blue') -Steps 10 -Mode ANSI4 } | Should -Throw } It 'Requires positive Steps value' { { New-GradientColorArray -Colors @('Red', 'Blue') -Steps 0 -Mode TrueColor } | Should -Throw } } Context 'TrueColor Mode Output' { It 'Returns RGB arrays in TrueColor mode' { $result = New-GradientColorArray -Colors @('Red', 'Blue') -Steps 5 -Mode TrueColor foreach ($color in $result) { $color.Count | Should -Be 3 } } It 'First color matches start color' { $result = New-GradientColorArray -Colors @(@(255, 0, 0), @(0, 0, 255)) -Steps 10 -Mode TrueColor $result[0][0] | Should -Be 255 $result[0][1] | Should -Be 0 $result[0][2] | Should -Be 0 } It 'Last color matches end color' { $result = New-GradientColorArray -Colors @(@(255, 0, 0), @(0, 0, 255)) -Steps 10 -Mode TrueColor $result[9][0] | Should -Be 0 $result[9][1] | Should -Be 0 $result[9][2] | Should -Be 255 } It 'Middle colors are interpolated' { $result = New-GradientColorArray -Colors @(@(0, 0, 0), @(100, 100, 100)) -Steps 3 -Mode TrueColor # Middle value should be approximately 50 $result[1][0] | Should -BeGreaterOrEqual 45 $result[1][0] | Should -BeLessOrEqual 55 } It 'RGB values stay within 0-255 range' { $result = New-GradientColorArray -Colors @('Red', 'Blue', 'Green') -Steps 20 -Mode TrueColor foreach ($color in $result) { $color[0] | Should -BeGreaterOrEqual 0 $color[0] | Should -BeLessOrEqual 255 $color[1] | Should -BeGreaterOrEqual 0 $color[1] | Should -BeLessOrEqual 255 $color[2] | Should -BeGreaterOrEqual 0 $color[2] | Should -BeLessOrEqual 255 } } } Context 'ANSI8 Mode Output' { It 'Returns ANSI8 codes in ANSI8 mode' { $result = New-GradientColorArray -Colors @('Red', 'Blue') -Steps 5 -Mode ANSI8 foreach ($code in $result) { $code | Should -BeOfType [int] $code | Should -BeGreaterOrEqual 0 $code | Should -BeLessOrEqual 255 } } It 'Generates correct number of codes' { $result = New-GradientColorArray -Colors @('Red', 'Green') -Steps 15 -Mode ANSI8 $result.Count | Should -Be 15 } It 'All codes are within ANSI8 range' { $result = New-GradientColorArray -Colors @('#FF0000', '#00FF00', '#0000FF') -Steps 30 -Mode ANSI8 foreach ($code in $result) { $code | Should -BeGreaterOrEqual 0 $code | Should -BeLessOrEqual 255 } } } Context 'Two-Color Gradient (Optimized Path)' { It 'Handles simple two-color gradient' { $result = New-GradientColorArray -Colors @('Red', 'Blue') -Steps 10 -Mode TrueColor $result.Count | Should -Be 10 } It 'Interpolates smoothly between two colors' { $result = New-GradientColorArray -Colors @(@(0, 0, 0), @(100, 0, 0)) -Steps 11 -Mode TrueColor # Check that red channel increases gradually for ($i = 0; $i -lt $result.Count - 1; $i++) { $result[$i + 1][0] | Should -BeGreaterOrEqual $result[$i][0] } } It 'Handles minimum steps (1)' { $result = New-GradientColorArray -Colors @('Red', 'Blue') -Steps 1 -Mode TrueColor $result.Count | Should -Be 1 $result[0] | Should -Not -BeNullOrEmpty } It 'Handles two identical colors' { $result = New-GradientColorArray -Colors @(@(100, 100, 100), @(100, 100, 100)) -Steps 5 -Mode TrueColor foreach ($color in $result) { $color[0] | Should -Be 100 $color[1] | Should -Be 100 $color[2] | Should -Be 100 } } } Context 'Multi-Stop Gradient (3+ Colors)' { It 'Handles three-color gradient' { $result = New-GradientColorArray -Colors @('Red', 'Green', 'Blue') -Steps 15 -Mode TrueColor $result.Count | Should -Be 15 } It 'Handles four-color gradient' { $result = New-GradientColorArray -Colors @('Red', 'Yellow', 'Green', 'Blue') -Steps 20 -Mode TrueColor $result.Count | Should -Be 20 } It 'Handles five-color gradient' { $result = New-GradientColorArray -Colors @('Red', 'Orange', 'Yellow', 'Green', 'Blue') -Steps 25 -Mode TrueColor $result.Count | Should -Be 25 } It 'Distributes colors evenly across waypoints' { $result = New-GradientColorArray -Colors @(@(255, 0, 0), @(0, 255, 0), @(0, 0, 255)) -Steps 9 -Mode TrueColor # First waypoint (Red) $result[0][0] | Should -Be 255 # Last waypoint (Blue) $result[8][2] | Should -Be 255 } It 'Creates smooth transitions between waypoints' { $result = New-GradientColorArray -Colors @('Black', 'Gray', 'White') -Steps 21 -Mode TrueColor # Should gradually increase from black to white $result[0][0] | Should -BeLessOrEqual $result[10][0] $result[10][0] | Should -BeLessOrEqual $result[20][0] } } Context 'Color Format Handling' { It 'Converts hex colors to RGB' { $result = New-GradientColorArray -Colors @('#FF0000', '#0000FF') -Steps 5 -Mode TrueColor $result[0][0] | Should -Be 255 # Red $result[4][2] | Should -Be 255 # Blue } It 'Converts color names to RGB' { $result = New-GradientColorArray -Colors @('Red', 'Blue') -Steps 5 -Mode TrueColor $result[0] | Should -Not -BeNullOrEmpty $result[0].Count | Should -Be 3 } It 'Handles 0x prefix hex colors' { $result = New-GradientColorArray -Colors @('0xFF0000', '0x0000FF') -Steps 5 -Mode TrueColor $result.Count | Should -Be 5 } It 'Clamps RGB values to 0-255 range' { # Test with already valid values $result = New-GradientColorArray -Colors @(@(255, 255, 255), @(0, 0, 0)) -Steps 5 -Mode TrueColor foreach ($color in $result) { $color[0] | Should -BeGreaterOrEqual 0 $color[0] | Should -BeLessOrEqual 255 } } It 'Handles invalid color names gracefully' { # Should fall back to gray or handle gracefully { New-GradientColorArray -Colors @('InvalidColor', 'Blue') -Steps 5 -Mode TrueColor } | Should -Not -Throw } } Context 'Edge Cases' { It 'Handles single step' { $result = New-GradientColorArray -Colors @('Red', 'Blue') -Steps 1 -Mode TrueColor $result.Count | Should -Be 1 } It 'Handles large number of steps' { $result = New-GradientColorArray -Colors @('Red', 'Blue') -Steps 1000 -Mode TrueColor $result.Count | Should -Be 1000 } It 'Handles very small RGB values' { $result = New-GradientColorArray -Colors @(@(1, 1, 1), @(2, 2, 2)) -Steps 5 -Mode TrueColor $result.Count | Should -Be 5 } It 'Handles very large RGB values' { $result = New-GradientColorArray -Colors @(@(254, 254, 254), @(255, 255, 255)) -Steps 5 -Mode TrueColor $result.Count | Should -Be 5 } It 'Handles black to white gradient' { $result = New-GradientColorArray -Colors @('Black', 'White') -Steps 11 -Mode TrueColor $result[0][0] | Should -Be 0 $result[10][0] | Should -Be 255 } It 'Handles white to black gradient (reverse)' { $result = New-GradientColorArray -Colors @('White', 'Black') -Steps 11 -Mode TrueColor $result[0][0] | Should -Be 255 $result[10][0] | Should -Be 0 } } Context 'Performance and Optimization' { It 'Uses List instead of array concatenation' { # Should complete quickly even with many steps $start = Get-Date $result = New-GradientColorArray -Colors @('Red', 'Blue') -Steps 1000 -Mode TrueColor $duration = (Get-Date) - $start $duration.TotalMilliseconds | Should -BeLessThan 100 } It 'Caches color conversions' { # Multiple calls with same colors should be consistent $result1 = New-GradientColorArray -Colors @('Red', 'Blue') -Steps 10 -Mode TrueColor $result2 = New-GradientColorArray -Colors @('Red', 'Blue') -Steps 10 -Mode TrueColor for ($i = 0; $i -lt 10; $i++) { $result1[$i][0] | Should -Be $result2[$i][0] $result1[$i][1] | Should -Be $result2[$i][1] $result1[$i][2] | Should -Be $result2[$i][2] } } It 'Handles command availability checks efficiently' { # Should not fail if color conversion functions are available { New-GradientColorArray -Colors @('Red', 'Blue') -Steps 10 -Mode TrueColor } | Should -Not -Throw } } Context 'Consistency and Reproducibility' { It 'Returns same results for same input' { $result1 = New-GradientColorArray -Colors @('Red', 'Green', 'Blue') -Steps 20 -Mode TrueColor $result2 = New-GradientColorArray -Colors @('Red', 'Green', 'Blue') -Steps 20 -Mode TrueColor $result1.Count | Should -Be $result2.Count for ($i = 0; $i -lt $result1.Count; $i++) { $result1[$i][0] | Should -Be $result2[$i][0] $result1[$i][1] | Should -Be $result2[$i][1] $result1[$i][2] | Should -Be $result2[$i][2] } } It 'TrueColor and ANSI8 return same count' { $resultTC = New-GradientColorArray -Colors @('Red', 'Blue') -Steps 15 -Mode TrueColor $resultA8 = New-GradientColorArray -Colors @('Red', 'Blue') -Steps 15 -Mode ANSI8 $resultTC.Count | Should -Be $resultA8.Count } } Context 'Rainbow Gradients' { It 'Creates full spectrum rainbow' { $result = New-GradientColorArray -Colors @('Red', 'Orange', 'Yellow', 'Green', 'Cyan', 'Blue', 'Magenta') -Steps 70 -Mode TrueColor $result.Count | Should -Be 70 } It 'Creates custom rainbow' { $result = New-GradientColorArray -Colors @('#FF0000', '#FF8000', '#FFFF00', '#00FF00', '#0000FF') -Steps 50 -Mode TrueColor $result.Count | Should -Be 50 } } Context 'Fallback Behavior' { It 'Returns gray when color table not available and color invalid' { # This tests graceful degradation $result = New-GradientColorArray -Colors @('Red', 'Blue') -Steps 5 -Mode TrueColor $result | Should -Not -BeNullOrEmpty } It 'Returns grayscale ANSI8 code (7) when conversion fails' { # Should handle gracefully $result = New-GradientColorArray -Colors @('Red', 'Blue') -Steps 5 -Mode ANSI8 $result | Should -Not -BeNullOrEmpty } } } |