Tests/GenXdev.FileSystem/Write-JsonFileAtomic.Tests.ps1

Pester\Describe 'Write-JsonFileAtomic' {

    Pester\BeforeAll {
        $Script:testRoot = GenXdev\Expand-Path `
            "$($env:TEMP)\GenXdev.JsonFile.Tests\" -CreateDirectory
        Microsoft.PowerShell.Management\Push-Location `
            -LiteralPath ($Script:testRoot)
    }

    Pester\AfterAll {
        GenXdev\Remove-AllItems $Script:testRoot -DeleteFolder
    }

    Pester\BeforeEach {
        $Script:testFile = "$Script:testRoot\json-atomic-test.json"
        if (Microsoft.PowerShell.Management\Test-Path ($Script:testFile)) {
            Microsoft.PowerShell.Management\Remove-Item ($Script:testFile) -Force
        }
    }

    Pester\It 'Writes a Hashtable as indented JSON' {
        GenXdev\Write-JsonFileAtomic -FilePath ($Script:testFile) `
            -Data @{ name = 'test'; value = 42 }
        $Script:testFile | Pester\Should -Exist
        $result = Microsoft.PowerShell.Management\Get-Content `
            -LiteralPath ($Script:testFile) -Raw |
            Microsoft.PowerShell.Utility\ConvertFrom-Json
        $result.name | Pester\Should -Be 'test'
        $result.value | Pester\Should -Be 42
    }

    Pester\It 'Writes a PSCustomObject as JSON' {
        $obj = [PSCustomObject]@{
            Name   = 'Test'
            Age    = 30
            Active = $true
        }
        GenXdev\Write-JsonFileAtomic -FilePath ($Script:testFile) -Data $obj
        $result = Microsoft.PowerShell.Management\Get-Content `
            -LiteralPath ($Script:testFile) -Raw |
            Microsoft.PowerShell.Utility\ConvertFrom-Json
        $result.Name | Pester\Should -Be 'Test'
        $result.Age | Pester\Should -Be 30
        $result.Active | Pester\Should -BeTrue
    }

    Pester\It 'Writes nested objects with depth control' {
        $nested = [PSCustomObject]@{
            Level1 = [PSCustomObject]@{
                Level2 = [PSCustomObject]@{
                    Value = 'deep'
                }
            }
        }
        GenXdev\Write-JsonFileAtomic -FilePath ($Script:testFile) `
            -Data $nested -Depth 10
        $result = Microsoft.PowerShell.Management\Get-Content `
            -LiteralPath ($Script:testFile) -Raw |
            Microsoft.PowerShell.Utility\ConvertFrom-Json
        $result.Level1.Level2.Value | Pester\Should -Be 'deep'
    }

    Pester\It 'Produces Compress JSON with -Compress' {
        GenXdev\Write-JsonFileAtomic -FilePath ($Script:testFile) `
            -Data @{ a = 1; b = 2 } -Compress
        $raw = Microsoft.PowerShell.Management\Get-Content `
            -LiteralPath ($Script:testFile) -Raw
        # Compress JSON has no line breaks
        $raw -match '\r?\n' | Pester\Should -BeFalse
        $result = $raw | Microsoft.PowerShell.Utility\ConvertFrom-Json
        $result.a | Pester\Should -Be 1
        $result.b | Pester\Should -Be 2
    }

    Pester\It 'Debounce coalesces rapid writes to last object' {
        1..30 | Microsoft.PowerShell.Core\ForEach-Object {
            GenXdev\Write-JsonFileAtomic -FilePath ($Script:testFile) `
                -Data @{ iteration = $_; ts = Microsoft.PowerShell.Utility\Get-Date } `
                -DebounceMs 5000
        }
        Microsoft.PowerShell.Utility\Start-Sleep -Seconds 7
        $result = Microsoft.PowerShell.Management\Get-Content `
            -LiteralPath ($Script:testFile) -Raw |
            Microsoft.PowerShell.Utility\ConvertFrom-Json
        $result.iteration | Pester\Should -Be 30
    }

    Pester\It 'Retries with MaxRetries and RetryDelayMs' {
        GenXdev\Write-JsonFileAtomic -FilePath ($Script:testFile) `
            -Data @{ status = 'ok' } -MaxRetries 10 -RetryDelayMs 100
        $result = Microsoft.PowerShell.Management\Get-Content `
            -LiteralPath ($Script:testFile) -Raw |
            Microsoft.PowerShell.Utility\ConvertFrom-Json
        $result.status | Pester\Should -Be 'ok'
    }

    Pester\It 'Handles empty hashtable' {
        GenXdev\Write-JsonFileAtomic -FilePath ($Script:testFile) -Data @{ }
        $raw = Microsoft.PowerShell.Management\Get-Content `
            -LiteralPath ($Script:testFile) -Raw
        # Empty hashtable serializes to {}
        $raw -replace '\s' | Pester\Should -Be '{}'
    }
}