Repository: PowerShell/PowerShell
File: test/powershell/Modules/Microsoft.PowerShell.Utility/ConvertTo-Json.Tests.ps1 (PowerShell)

Code before:
    #region Comprehensive Scalar Type Tests (Phase 1)
    # Test coverage for ConvertTo-Json scalar serialization
    # Covers: Pipeline vs InputObject, ETS vs no ETS, all primitive and special types

    Context 'Primitive scalar types' {
        It 'Should serialize <TypeName> value <Value> correctly' -TestCases @(
            # Integer types
            @{ TypeName = 'int'; Value = 42; Expected = '42' }
            @{ TypeName = 'int'; Value = -42; Expected = '-42' }
            @{ TypeName = 'int'; Value = 0; Expected = '0' }
            @{ TypeName = 'int'; Value = [int]::MaxValue; Expected = '2147483647' }
            @{ TypeName = 'int'; Value = [int]::MinValue; Expected = '-2147483648' }
            @{ TypeName = 'long'; Value = 9223372036854775807L; Expected = '9223372036854775807' }
            @{ TypeName = 'long'; Value = -9223372036854775808L; Expected = '-9223372036854775808' }
            # Floating-point types
            @{ TypeName = 'double'; Value = 3.14159; Expected = '3.14159' }
            @{ TypeName = 'double'; Value = -3.14159; Expected = '-3.14159' }
            @{ TypeName = 'double'; Value = 0.0; Expected = '0.0' }
            @{ TypeName = 'float'; Value = [float]3.14; Expected = '3.14' }
            @{ TypeName = 'decimal'; Value = 123.456d; Expected = '123.456' }
            # Boolean
            @{ TypeName = 'bool'; Value = $true; Expected = 'true' }
            @{ TypeName = 'bool'; Value = $false; Expected = 'false' }
        ) {
            param($TypeName, $Value, $Expected)
            $Value | ConvertTo-Json -Compress | Should -BeExactly $Expected
        }
    }

    Context 'String scalar types' {
        It 'Should serialize string <Description> correctly' -TestCases @(
            @{ Description = 'regular'; Value = 'hello'; Expected = '"hello"' }
            @{ Description = 'empty'; Value = ''; Expected = '""' }
            @{ Description = 'with spaces'; Value = 'hello world'; Expected = '"hello world"' }
            @{ Description = 'with newline'; Value = "line1`nline2"; Expected = '"line1\nline2"' }
            @{ Description = 'with tab'; Value = "col1`tcol2"; Expected = '"col1\tcol2"' }
            @{ Description = 'with quotes'; Value = 'say "hello"'; Expected = '"say \"hello\""' }
            @{ Description = 'with backslash'; Value = 'c:\path'; Expected = '"c:\\path"' }
            @{ Description = 'unicode'; Value = '日本語'; Expected = '"日本語"' }
            @{ Description = 'emoji'; Value = '😀'; Expected = '"😀"' }
        ) {
            param($Description, $Value, $Expected)
            $Value | ConvertTo-Json -Compress | Should -BeExactly $Expected
        }
    }

    Context 'DateTime and related types' {
        It 'Should serialize DateTime with UTC kind' {
            $dt = [DateTime]::new(2024, 6, 15, 10, 30, 0, [DateTimeKind]::Utc)
            $json = $dt | ConvertTo-Json -Compress
            $json | Should -BeExactly '"2024-06-15T10:30:00Z"'

Review comment (suggestion):
It is possible to add ETS to these types. Here and below I'd add second check for ETS too. (For string and Datetime that ETS properties are ignored.)

Also I'd put pipeline check here too to reduce common test count.

Code after:
    #region Comprehensive Scalar Type Tests (Phase 1)
    # Test coverage for ConvertTo-Json scalar serialization
    # Covers: Pipeline vs InputObject, ETS vs no ETS, all primitive and special types

    Context 'Primitive scalar types' {
        It 'Should serialize <TypeName> value <Value> correctly via Pipeline and InputObject' -TestCases @(
            # Byte types
            @{ TypeName = 'byte'; Value = [byte]0; Expected = '0' }
            @{ TypeName = 'byte'; Value = [byte]255; Expected = '255' }
            @{ TypeName = 'sbyte'; Value = [sbyte]-128; Expected = '-128' }
            @{ TypeName = 'sbyte'; Value = [sbyte]127; Expected = '127' }
            # Short types
            @{ TypeName = 'short'; Value = [short]-32768; Expected = '-32768' }
            @{ TypeName = 'short'; Value = [short]32767; Expected = '32767' }
            @{ TypeName = 'ushort'; Value = [ushort]0; Expected = '0' }
            @{ TypeName = 'ushort'; Value = [ushort]65535; Expected = '65535' }
            # Integer types
            @{ TypeName = 'int'; Value = 42; Expected = '42' }
            @{ TypeName = 'int'; Value = -42; Expected = '-42' }
            @{ TypeName = 'int'; Value = 0; Expected = '0' }
            @{ TypeName = 'int'; Value = [int]::MaxValue; Expected = '2147483647' }
            @{ TypeName = 'int'; Value = [int]::MinValue; Expected = '-2147483648' }
            @{ TypeName = 'uint'; Value = [uint]0; Expected = '0' }
            @{ TypeName = 'uint'; Value = [uint]::MaxValue; Expected = '4294967295' }
            # Long types
            @{ TypeName = 'long'; Value = [long]::MaxValue; Expected = '9223372036854775807' }
            @{ TypeName = 'long'; Value = [long]::MinValue; Expected = '-9223372036854775808' }
            @{ TypeName = 'ulong'; Value = [ulong]0; Expected = '0' }
            @{ TypeName = 'ulong'; Value = [ulong]::MaxValue; Expected = '18446744073709551615' }
            # Floating-point types
            @{ TypeName = 'float'; Value = [float]3.14; Expected = '3.14' }
            @{ TypeName = 'float'; Value = [float]::NaN; Expected = '"NaN"' }
            @{ TypeName = 'float'; Value = [float]::PositiveInfinity; Expected = '"Infinity"' }
            @{ TypeName = 'float'; Value = [float]::NegativeInfinity; Expected = '"-Infinity"' }
            @{ TypeName = 'double'; Value = 3.14159; Expected = '3.14159' }
            @{ TypeName = 'double'; Value = -3.14159; Expected = '-3.14159' }
            @{ TypeName = 'double'; Value = 0.0; Expected = '0.0' }
            @{ TypeName = 'double'; Value = [double]::NaN; Expected = '"NaN"' }
            @{ TypeName = 'double'; Value = [double]::PositiveInfinity; Expected = '"Infinity"' }
            @{ TypeName = 'double'; Value = [double]::NegativeInfinity; Expected = '"-Infinity"' }
            @{ TypeName = 'decimal'; Value = 123.456d; Expected = '123.456' }
            # BigInteger
            @{ TypeName = 'BigInteger'; Value = 18446744073709551615n; Expected = '18446744073709551615' }
            # Boolean
            @{ TypeName = 'bool'; Value = $true; Expected = 'true' }
            @{ TypeName = 'bool'; Value = $false; Expected = 'false' }
            # Null
            @{ TypeName = 'null'; Value = $null; Expected = 'null' }
        ) {
            param($TypeName, $Value, $Expected)
            $jsonPipeline = $Value | ConvertTo-Json -Compress