Tests/Set-DotEnvValue.Tests.ps1

BeforeAll {

    Set-StrictMode -Version "Latest"

    . "$PSScriptRoot\..\Source\ConvertFrom-DotEnv.ps1"
    . "$PSScriptRoot\..\Source\Set-DotEnvValue.ps1"

}

Describe "Set-DotEnvValue" {

    Context "When the file does not exist" {

        It "Creates the file with the key=value line" {

            $path = Join-Path -Path $TestDrive -ChildPath "missing.env"

            Set-DotEnvValue -Path $path -Name "TOOLBOX_DATA" -Value "new-value"

            Get-Content -Path $path | Should -Contain "TOOLBOX_DATA=new-value"

        }

    }

    Context "When the file exists" {

        BeforeEach {

            $script:testEnvPath = Join-Path -Path $TestDrive -ChildPath "test.env"

            @(
                "# comment line"
                "TOOLBOX_DATA=old-value"
                "OTHER_KEY=other value"
            ) | Set-Content -Path $testEnvPath

        }

        It "Replaces the value in place when the key already exists" {

            Set-DotEnvValue -Path $testEnvPath -Name "TOOLBOX_DATA" -Value "new-value"

            $content = Get-Content -Path $testEnvPath

            $content | Should -Contain "TOOLBOX_DATA=new-value"
            $content | Should -Not -Contain "TOOLBOX_DATA=old-value"

        }

        It "Preserves other lines when replacing an existing key" {

            Set-DotEnvValue -Path $testEnvPath -Name "TOOLBOX_DATA" -Value "new-value"

            $content = Get-Content -Path $testEnvPath

            $content | Should -Contain "# comment line"
            $content | Should -Contain "OTHER_KEY=other value"

        }

        It "Appends a new line when the key does not exist" {

            Set-DotEnvValue -Path $testEnvPath -Name "NEW_KEY" -Value "new-value"

            $content = Get-Content -Path $testEnvPath

            $content | Should -Contain "NEW_KEY=new-value"
            $content | Should -Contain "TOOLBOX_DATA=old-value"

        }

        It "Accepts a non-string object as the value" {

            Set-DotEnvValue -Path $testEnvPath -Name "NEW_KEY" -Value 123

            Get-Content -Path $testEnvPath | Should -Contain "NEW_KEY=123"

        }

        It "Accepts Name and Value from the pipeline by property name" {

            [pscustomobject]@{ Name = "TOOLBOX_DATA"; Value = "new-value" } | Set-DotEnvValue -Path $testEnvPath

            Get-Content -Path $testEnvPath | Should -Contain "TOOLBOX_DATA=new-value"

        }

    }

    Context "Under -WhatIf" {

        It "Does not create the file" {

            $path = Join-Path -Path $TestDrive -ChildPath "whatif.env"

            Set-DotEnvValue -Path $path -Name "TOOLBOX_DATA" -Value "new-value" -WhatIf

            Test-Path -Path $path | Should -BeFalse

        }

        It "Does not modify an existing file" {

            $path = Join-Path -Path $TestDrive -ChildPath "whatif-existing.env"

            "TOOLBOX_DATA=old-value" | Set-Content -Path $path

            Set-DotEnvValue -Path $path -Name "TOOLBOX_DATA" -Value "new-value" -WhatIf

            Get-Content -Path $path | Should -Contain "TOOLBOX_DATA=old-value"

        }

    }

    Context "Using -Text instead of -Name/-Value" {

        BeforeEach {

            $script:testEnvPath = Join-Path -Path $TestDrive -ChildPath "test.env"

            "TOOLBOX_DATA=old-value" | Set-Content -Path $testEnvPath

        }

        It "Sets the key from a KEY=VALUE formatted string" {

            Set-DotEnvValue -Path $testEnvPath -Text "TOOLBOX_DATA=new-value"

            Get-Content -Path $testEnvPath | Should -Contain "TOOLBOX_DATA=new-value"

        }

        It "Throws when the text is not in KEY=VALUE format" {

            { Set-DotEnvValue -Path $testEnvPath -Text "not a key value line" } | Should -Throw

        }

        It "Accepts a KEY=VALUE formatted string from the pipeline" {

            "TOOLBOX_DATA=new-value" | Set-DotEnvValue -Path $testEnvPath

            Get-Content -Path $testEnvPath | Should -Contain "TOOLBOX_DATA=new-value"

        }

    }

}