tests/PowerCraft.Release.Tests.ps1
|
BeforeAll { $ModulePath = Join-Path $PSScriptRoot '..' 'PowerCraft.Release.psd1' Import-Module $ModulePath -Force } Describe 'Get-SemanticVersion (via module internals)' { # Access private function through module scope BeforeAll { $module = Get-Module PowerCraft.Release $getSemVer = & $module { Get-Command Get-SemanticVersion } } It 'Parses simple version' { $result = & $module { Get-SemanticVersion -Version '1.2.3' } $result.Major | Should -Be 1 $result.Minor | Should -Be 2 $result.Patch | Should -Be 3 $result.PreRelease | Should -BeNullOrEmpty $result.HasVPrefix | Should -BeFalse } It 'Parses version with v prefix' { $result = & $module { Get-SemanticVersion -Version 'v2.0.1' } $result.Major | Should -Be 2 $result.Minor | Should -Be 0 $result.Patch | Should -Be 1 $result.HasVPrefix | Should -BeTrue } It 'Parses pre-release version' { $result = & $module { Get-SemanticVersion -Version 'v1.0.0-beta.1' } $result.Major | Should -Be 1 $result.PreRelease | Should -Be 'beta.1' } It 'Parses version with build metadata' { $result = & $module { Get-SemanticVersion -Version '1.0.0+build.123' } $result.Build | Should -Be 'build.123' } It 'Throws on invalid version' { { & $module { Get-SemanticVersion -Version 'not-a-version' } } | Should -Throw } It 'Throws on partial version' { { & $module { Get-SemanticVersion -Version '1.2' } } | Should -Throw } } Describe 'Get-ProjectType (via module internals)' { BeforeAll { $module = Get-Module PowerCraft.Release } It 'Detects PowerShell module from .psd1' { $testDir = Join-Path $TestDrive 'ps-project' New-Item -ItemType Directory -Path $testDir -Force | Out-Null '@{ ModuleVersion = "1.0.0" }' | Set-Content (Join-Path $testDir 'Test.psd1') $result = & $module { param($p) Get-ProjectType -Path $p } $testDir $result.Type | Should -Be 'PowerShell' $result.FileName | Should -Be 'Test.psd1' } It 'Detects .NET project from .csproj' { $testDir = Join-Path $TestDrive 'dotnet-project' New-Item -ItemType Directory -Path $testDir -Force | Out-Null '<Project><PropertyGroup><Version>1.0.0</Version></PropertyGroup></Project>' | Set-Content (Join-Path $testDir 'App.csproj') $result = & $module { param($p) Get-ProjectType -Path $p } $testDir $result.Type | Should -Be 'DotNet' } It 'Detects Node.js from package.json' { $testDir = Join-Path $TestDrive 'node-project' New-Item -ItemType Directory -Path $testDir -Force | Out-Null '{"name":"test","version":"1.0.0"}' | Set-Content (Join-Path $testDir 'package.json') $result = & $module { param($p) Get-ProjectType -Path $p } $testDir $result.Type | Should -Be 'Node' } It 'Detects Python from pyproject.toml' { $testDir = Join-Path $TestDrive 'py-project' New-Item -ItemType Directory -Path $testDir -Force | Out-Null '[project]', 'version = "1.0.0"' | Set-Content (Join-Path $testDir 'pyproject.toml') $result = & $module { param($p) Get-ProjectType -Path $p } $testDir $result.Type | Should -Be 'Python' } It 'Returns Unknown when no project files found' { $testDir = Join-Path $TestDrive 'empty-project' New-Item -ItemType Directory -Path $testDir -Force | Out-Null $result = & $module { param($p) Get-ProjectType -Path $p } $testDir $result.Type | Should -Be 'Unknown' } It 'Respects priority: .psd1 over .csproj' { $testDir = Join-Path $TestDrive 'mixed-project' New-Item -ItemType Directory -Path $testDir -Force | Out-Null '@{ ModuleVersion = "1.0.0" }' | Set-Content (Join-Path $testDir 'Test.psd1') '<Project></Project>' | Set-Content (Join-Path $testDir 'App.csproj') $result = & $module { param($p) Get-ProjectType -Path $p } $testDir $result.Type | Should -Be 'PowerShell' } } Describe 'Get-PCProjectVersion' { It 'Reads version from PowerShell manifest' { $testDir = Join-Path $TestDrive 'ps-version' New-Item -ItemType Directory -Path $testDir -Force | Out-Null @" @{ ModuleVersion = '2.5.1' RootModule = 'Test.psm1' } "@ | Set-Content (Join-Path $testDir 'Test.psd1') $result = Get-PCProjectVersion -Path $testDir $result.Version | Should -Be '2.5.1' $result.Parsed.Major | Should -Be 2 $result.Parsed.Minor | Should -Be 5 $result.Parsed.Patch | Should -Be 1 $result.ProjectType.Type | Should -Be 'PowerShell' } It 'Reads version from .csproj' { $testDir = Join-Path $TestDrive 'dotnet-version' New-Item -ItemType Directory -Path $testDir -Force | Out-Null @" <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <Version>3.1.4</Version> </PropertyGroup> </Project> "@ | Set-Content (Join-Path $testDir 'App.csproj') $result = Get-PCProjectVersion -Path $testDir $result.Version | Should -Be '3.1.4' $result.Parsed.Major | Should -Be 3 } It 'Reads version from package.json' { $testDir = Join-Path $TestDrive 'node-version' New-Item -ItemType Directory -Path $testDir -Force | Out-Null '{"name":"my-app","version":"0.9.2"}' | Set-Content (Join-Path $testDir 'package.json') $result = Get-PCProjectVersion -Path $testDir $result.Version | Should -Be '0.9.2' } It 'Reads version from pyproject.toml' { $testDir = Join-Path $TestDrive 'py-version' New-Item -ItemType Directory -Path $testDir -Force | Out-Null @" [project] name = "mypackage" version = "1.4.0" "@ | Set-Content (Join-Path $testDir 'pyproject.toml') $result = Get-PCProjectVersion -Path $testDir $result.Version | Should -Be '1.4.0' } It 'Throws when no project type detected' { $testDir = Join-Path $TestDrive 'no-project' New-Item -ItemType Directory -Path $testDir -Force | Out-Null { Get-PCProjectVersion -Path $testDir } | Should -Throw '*No recognized project type*' } } Describe 'Set-PCProjectVersion' { It 'Updates version in PowerShell manifest' { $testDir = Join-Path $TestDrive 'ps-set' New-Item -ItemType Directory -Path $testDir -Force | Out-Null @" @{ ModuleVersion = '1.0.0' RootModule = 'Test.psm1' } "@ | Set-Content (Join-Path $testDir 'Test.psd1') Set-PCProjectVersion -Version '1.1.0' -Path $testDir $result = Get-PCProjectVersion -Path $testDir $result.Version | Should -Be '1.1.0' } It 'Updates version in package.json' { $testDir = Join-Path $TestDrive 'node-set' New-Item -ItemType Directory -Path $testDir -Force | Out-Null '{"name":"app","version":"1.0.0"}' | Set-Content (Join-Path $testDir 'package.json') Set-PCProjectVersion -Version '2.0.0' -Path $testDir $pkg = Get-Content (Join-Path $testDir 'package.json') -Raw | ConvertFrom-Json $pkg.version | Should -Be '2.0.0' } It 'Updates version in pyproject.toml' { $testDir = Join-Path $TestDrive 'py-set' New-Item -ItemType Directory -Path $testDir -Force | Out-Null @" [project] name = "mypackage" version = "1.0.0" description = "A test" "@ | Set-Content (Join-Path $testDir 'pyproject.toml') Set-PCProjectVersion -Version '1.2.0' -Path $testDir $content = Get-Content (Join-Path $testDir 'pyproject.toml') -Raw $content | Should -Match 'version = "1.2.0"' } It 'Strips v prefix before writing' { $testDir = Join-Path $TestDrive 'ps-vprefix' New-Item -ItemType Directory -Path $testDir -Force | Out-Null "@{ ModuleVersion = '1.0.0'; RootModule = 'T.psm1' }" | Set-Content (Join-Path $testDir 'T.psd1') Set-PCProjectVersion -Version 'v3.0.0' -Path $testDir $result = Get-PCProjectVersion -Path $testDir $result.Version | Should -Be '3.0.0' } It 'Rejects invalid version format' { $testDir = Join-Path $TestDrive 'ps-invalid' New-Item -ItemType Directory -Path $testDir -Force | Out-Null "@{ ModuleVersion = '1.0.0'; RootModule = 'T.psm1' }" | Set-Content (Join-Path $testDir 'T.psd1') { Set-PCProjectVersion -Version 'bad' -Path $testDir } | Should -Throw } } Describe 'Get-PCNextVersion' { It 'Increments patch' { $testDir = Join-Path $TestDrive 'next-patch' New-Item -ItemType Directory -Path $testDir -Force | Out-Null "@{ ModuleVersion = '1.2.3'; RootModule = 'T.psm1' }" | Set-Content (Join-Path $testDir 'T.psd1') $result = Get-PCNextVersion -IncrementType Patch -Path $testDir $result | Should -Be '1.2.4' } It 'Increments minor and resets patch' { $testDir = Join-Path $TestDrive 'next-minor' New-Item -ItemType Directory -Path $testDir -Force | Out-Null "@{ ModuleVersion = '1.2.3'; RootModule = 'T.psm1' }" | Set-Content (Join-Path $testDir 'T.psd1') $result = Get-PCNextVersion -IncrementType Minor -Path $testDir $result | Should -Be '1.3.0' } It 'Increments major and resets minor+patch' { $testDir = Join-Path $TestDrive 'next-major' New-Item -ItemType Directory -Path $testDir -Force | Out-Null "@{ ModuleVersion = '1.2.3'; RootModule = 'T.psm1' }" | Set-Content (Join-Path $testDir 'T.psd1') $result = Get-PCNextVersion -IncrementType Major -Path $testDir $result | Should -Be '2.0.0' } It 'Works with explicit CurrentVersion parameter' { $result = Get-PCNextVersion -IncrementType Patch -CurrentVersion 'v5.0.9' $result | Should -Be '5.0.10' } It 'Works with version without v prefix' { $result = Get-PCNextVersion -IncrementType Minor -CurrentVersion '2.1.0' $result | Should -Be '2.2.0' } } Describe 'Test-PCReleaseReady' { It 'Fails when not in a git repository' { $testDir = Join-Path $TestDrive 'no-git' New-Item -ItemType Directory -Path $testDir -Force | Out-Null "@{ ModuleVersion = '1.0.0'; RootModule = 'T.psm1' }" | Set-Content (Join-Path $testDir 'T.psd1') $result = Test-PCReleaseReady -Path $testDir $result.Pass | Should -BeFalse $result.Errors | Should -Contain 'Not in a git repository' } Context 'In a git repository' { BeforeAll { $testDir = Join-Path $TestDrive 'git-ready' New-Item -ItemType Directory -Path $testDir -Force | Out-Null Push-Location $testDir git init --quiet git config user.email "test@test.com" git config user.name "Test" "@{ ModuleVersion = '1.0.0'; RootModule = 'T.psm1' }" | Set-Content (Join-Path $testDir 'T.psd1') git add -A git commit -m "init" --quiet } AfterAll { Pop-Location } It 'Detects uncommitted changes' { "change" | Set-Content (Join-Path $testDir 'dirty.txt') $result = Test-PCReleaseReady -Path $testDir $result.Pass | Should -BeFalse $result.Errors | Should -Contain 'Working directory has uncommitted changes' Remove-Item (Join-Path $testDir 'dirty.txt') } It 'Passes when clean on default branch' { # Rename branch to main git branch -m main 2>$null $result = Test-PCReleaseReady -Path $testDir # May warn about remote but should pass other checks $gitRepoCheck = $result.Checks | Where-Object { $_.Check -eq 'Git Repository' } $gitRepoCheck.Status | Should -Be 'PASS' } It 'Fails when on wrong branch' { git checkout -b feature/test --quiet $result = Test-PCReleaseReady -Path $testDir -RequireBranch @('main') $branchCheck = $result.Checks | Where-Object { $_.Check -eq 'Branch' } $branchCheck.Status | Should -Be 'FAIL' git checkout main --quiet git branch -D feature/test --quiet 2>$null } } } Describe 'Publish-PCRelease' { It 'DryRun shows plan without making changes' { $testDir = Join-Path $TestDrive 'release-dry' New-Item -ItemType Directory -Path $testDir -Force | Out-Null Push-Location $testDir try { git init --quiet git config user.email "test@test.com" git config user.name "Test" "@{ ModuleVersion = '1.0.0'; RootModule = 'T.psm1' }" | Set-Content 'T.psd1' git add -A git commit -m "init" --quiet git branch -m main $result = Publish-PCRelease -IncrementType Patch -DryRun -Path $testDir $result.Status | Should -Be 'DryRun' $result.Version | Should -Be '1.0.1' $result.Tag | Should -Be 'v1.0.1' # Version should NOT have changed $current = Get-PCProjectVersion -Path $testDir $current.Version | Should -Be '1.0.0' } finally { Pop-Location } } } |