Tests/Invoke-GitInit.Tests.ps1

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

Describe 'Invoke-GitInit' {
    BeforeEach {
        $script:GitCalls = [System.Collections.Generic.List[string]]::new()
        Mock git {
            $script:GitCalls.Add($args -join ' ')
            $global:LASTEXITCODE = 0
        } -ModuleName GittHelpers
        Mock Remove-Item { } -ModuleName GittHelpers
    }

    It 'Does not throw in WhatIf mode' {
        { Invoke-GitInit -Name 'myrepo' -Destination $TestDrive -WhatIf } | Should -Not -Throw
    }

    It 'Calls git init for the temporary repo' {
        Invoke-GitInit -Name 'myrepo' -Destination $TestDrive -SkipSafeDirectory -Confirm:$false
        $script:GitCalls | Where-Object { $_ -match '^init ' } | Should -Not -BeNullOrEmpty
    }

    It 'Calls git clone --bare' {
        Invoke-GitInit -Name 'myrepo' -Destination $TestDrive -SkipSafeDirectory -Confirm:$false
        $script:GitCalls | Where-Object { $_ -match 'clone --bare' } | Should -Not -BeNullOrEmpty
    }

    It 'Returns the bare repo path' {
        $result = Invoke-GitInit -Name 'myrepo' -Destination $TestDrive -SkipSafeDirectory -Confirm:$false
        $result | Should -Be (Join-Path $TestDrive 'myrepo.git')
    }

    It 'Does not configure remote when -RemoteUrl is not provided' {
        Invoke-GitInit -Name 'myrepo' -Destination $TestDrive -SkipSafeDirectory -Confirm:$false
        $script:GitCalls | Where-Object { $_ -match 'remote add origin' } | Should -BeNullOrEmpty
    }

    It 'Pushes and configures remote origin when -RemoteUrl is provided' {
        $url = 'https://github.com/user/myrepo'
        Invoke-GitInit -Name 'myrepo' -Destination $TestDrive -RemoteUrl $url -SkipSafeDirectory -Confirm:$false
        $script:GitCalls | Where-Object { $_ -match 'remote add origin' } | Should -Not -BeNullOrEmpty
        $script:GitCalls | Where-Object { $_ -match "clone --bare $url" } | Should -Not -BeNullOrEmpty
    }

    It 'Applies recommended git config unless -SkipGitConfig is set' {
        Invoke-GitInit -Name 'myrepo' -Destination $TestDrive -SkipSafeDirectory -Confirm:$false
        $script:GitCalls | Where-Object { $_ -match 'core.longpaths' } | Should -Not -BeNullOrEmpty
    }

    It 'Skips git config when -SkipGitConfig is set' {
        Invoke-GitInit -Name 'myrepo' -Destination $TestDrive -SkipSafeDirectory -SkipGitConfig -Confirm:$false
        $script:GitCalls | Where-Object { $_ -match 'core.longpaths' } | Should -BeNullOrEmpty
    }
}

Describe 'Invoke-Gitt init dispatch' {
    It 'init subcommand calls Invoke-GitInit' {
        Mock Invoke-GitInit { } -ModuleName GittHelpers
        Invoke-Gitt init 'myrepo'
        Should -Invoke Invoke-GitInit -Times 1 -ModuleName GittHelpers
    }
}

Describe 'Get-DefaultBranch' {
    It 'Returns configured init.defaultBranch when set' {
        Mock git {
            $global:LASTEXITCODE = 0
            return 'develop'
        } -ModuleName GittHelpers

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

    It 'Prefers master over main when no config is set' {
        Mock git {
            $global:LASTEXITCODE = 1
            if ($args -contains 'branch' -and ($args -join ' ') -match 'master') { return 'master' }
        } -ModuleName GittHelpers

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

    It 'Falls back to main when master does not exist' {
        $script:BranchListCount = 0
        Mock git {
            # First call is config (fails), subsequent are branch --list
            if ($args -contains 'config') { $global:LASTEXITCODE = 1; return $null }
            $global:LASTEXITCODE = 0
            $script:BranchListCount++
            if ($script:BranchListCount -eq 1) { return $null }  # master not found
            return 'main'                                          # main found
        } -ModuleName GittHelpers

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

    It 'Returns master as hard fallback when nothing is found' {
        Mock git { $global:LASTEXITCODE = 1; return $null } -ModuleName GittHelpers

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