Tests/New-GitWorktree.Tests.ps1

BeforeAll {
    Import-Module "$PSScriptRoot\..\GittHelpers.psd1" -Force
}

Describe 'New-GitWorktree' {
    BeforeEach {
        Mock Get-GitRoot       { return $TestDrive } -ModuleName GittHelpers
        Mock Get-WorktreeList  { return @() }        -ModuleName GittHelpers
        Mock Get-GitAuthorSlug { return 'snkemp' }   -ModuleName GittHelpers
        Mock git {
            $global:LASTEXITCODE = 0
            if ($args -contains 'symbolic-ref') { return 'main' }
            if ($args -contains 'worktree' -and $args -contains '-b') {
                $bIdx = [array]::IndexOf($args, '-b')
                if ($bIdx -ge 0) { $script:BranchCreated = $args[$bIdx + 1] }
            }
        } -ModuleName GittHelpers
        Mock New-Item { } -ModuleName GittHelpers
    }

    It 'Uses feature/ prefix for -Feature parameter set' {
        { New-GitWorktree -Feature 'login' -WhatIf } | Should -Not -Throw
    }

    It 'Includes author segment in dev-path branches (feature)' {
        $script:BranchCreated = $null
        New-GitWorktree -Feature 'login' -Confirm:$false
        $script:BranchCreated | Should -Be 'feature/snkemp/login'
    }

    It 'Includes author segment in dev-path branches (bug)' {
        $script:BranchCreated = $null
        New-GitWorktree -Bug 'null-ref' -Confirm:$false
        $script:BranchCreated | Should -Be 'bug/snkemp/null-ref'
    }

    It 'Includes author segment in dev-path branches (temp)' {
        $script:BranchCreated = $null
        New-GitWorktree -Temp 'experiment' -Confirm:$false
        $script:BranchCreated | Should -Be 'temp/snkemp/experiment'
    }

    It 'Does NOT include author segment for hotfix (prod path)' {
        $script:BranchCreated = $null
        New-GitWorktree -Hotfix '2.1.1' -Confirm:$false
        $script:BranchCreated | Should -Be 'hotfix/2.1.1'
    }

    It 'Does NOT include author segment for release (prod path)' {
        $script:BranchCreated = $null
        New-GitWorktree -Release '3.0.0' -Confirm:$false
        $script:BranchCreated | Should -Be 'release/3.0.0'
    }

    It 'Suppresses author with -NoAuthor on dev paths' {
        $script:BranchCreated = $null
        New-GitWorktree -Feature 'login' -NoAuthor -Confirm:$false
        $script:BranchCreated | Should -Be 'feature/login'
    }

    It 'Builds correct branch name from -Hotfix and version (dots preserved)' {
        $slug = & (Get-Module GittHelpers) { ConvertTo-SafeBranchName '2.1.1' }
        $slug | Should -Be '2.1.1'
    }

    It 'Appends description slug to branch name' {
        $slug = & (Get-Module GittHelpers) {
            $n = ConvertTo-SafeBranchName 'login'
            $d = ConvertTo-SafeBranchName 'Add OAuth login'
            "$n-$d"
        }
        $slug | Should -Be 'login-add-oauth-login'
    }

    It 'Throws when no source branch can be found' {
        Mock git { $global:LASTEXITCODE = 1; return $null } -ModuleName GittHelpers
        { New-GitWorktree -Feature 'x' -SourceBranch 'nonexistent' } | Should -Throw
    }
}

Describe 'New-GitWorktree parameter sets' {
    It 'All branch-type parameters are in distinct parameter sets' {
        $cmd  = Get-Command New-GitWorktree
        $sets = $cmd.ParameterSets | Select-Object -ExpandProperty Name
        $sets | Should -Contain 'Feature'
        $sets | Should -Contain 'Hotfix'
        $sets | Should -Contain 'Release'
        $sets | Should -Contain 'Bug'
        $sets | Should -Contain 'Temp'
    }
}

Describe 'Get-GitAuthorSlug' {
    AfterEach {
        $env:GIT_USER_SHORTNAME = $null
    }

    It 'Prefers $env:GIT_USER_SHORTNAME over everything else' {
        $env:GIT_USER_SHORTNAME = 'myshortname'
        Mock git { $global:LASTEXITCODE = 0; return 'Other Name' } -ModuleName GittHelpers

        $result = & (Get-Module GittHelpers) { Get-GitAuthorSlug }
        $result | Should -Be 'myshortname'
    }

    It 'Slugifies $env:GIT_USER_SHORTNAME' {
        $env:GIT_USER_SHORTNAME = 'Spencer Kemp'
        Mock git { $global:LASTEXITCODE = 0 } -ModuleName GittHelpers

        $result = & (Get-Module GittHelpers) { Get-GitAuthorSlug }
        $result | Should -Be 'spencer-kemp'
    }

    It 'Falls back to git user.name when GIT_USER_SHORTNAME is not set' {
        $env:GIT_USER_SHORTNAME = $null
        Mock git {
            $global:LASTEXITCODE = 0
            if ($args -contains 'user.name') { return 'snkemp' }
        } -ModuleName GittHelpers

        $result = & (Get-Module GittHelpers) { Get-GitAuthorSlug }
        $result | Should -Be 'snkemp'
    }

    It 'Falls back to $env:USERNAME when both other sources are empty' {
        $env:GIT_USER_SHORTNAME = $null
        Mock git { $global:LASTEXITCODE = 0; return $null } -ModuleName GittHelpers

        $result = & (Get-Module GittHelpers) { Get-GitAuthorSlug }
        $expected = $env:USERNAME.ToLowerInvariant() -replace '[^\w\-\.]+', '-'
        $result | Should -Be $expected
    }
}