lib/rules/version_tracking/minor_branch_missing/minor_branch_missing.Tests.ps1
|
############################################################################# # Tests for Rule: minor_branch_missing ############################################################################# BeforeAll { . "$PSScriptRoot/../../../StateModel.ps1" . "$PSScriptRoot/../../../ValidationRules.ps1" . "$PSScriptRoot/../../../RemediationActions.ps1" . "$PSScriptRoot/minor_branch_missing.ps1" } Describe "minor_branch_missing" { Context "Condition - AppliesWhen floating-versions-use is branches and check-minor-version is enabled" { It "should return missing minor when patch exists but minor branch doesn't" { $state = [RepositoryState]::new() $state.Tags += [VersionRef]::new("v1.0.0", "refs/tags/v1.0.0", "abc123", "tag") # No v1.0 branch $state.IgnoreVersions = @() $config = @{ 'floating-versions-use' = 'branches' 'check-minor-version' = 'error' } $result = & $Rule_MinorBranchMissing.Condition $state $config $result.Count | Should -Be 1 $result[0].Major | Should -Be 1 $result[0].Minor | Should -Be 0 } It "should not return minor when minor branch exists" { $state = [RepositoryState]::new() $state.Branches += [VersionRef]::new("v1.0", "refs/heads/v1.0", "abc123", "branch") $state.Tags += [VersionRef]::new("v1.0.0", "refs/tags/v1.0.0", "abc123", "tag") $state.IgnoreVersions = @() $config = @{ 'floating-versions-use' = 'branches' 'check-minor-version' = 'error' } $result = & $Rule_MinorBranchMissing.Condition $state $config $result.Count | Should -Be 0 } It "should return empty when floating-versions-use is 'tags'" { $state = [RepositoryState]::new() $state.Tags += [VersionRef]::new("v1.0.0", "refs/tags/v1.0.0", "abc123", "tag") # No v1.0 branch $state.IgnoreVersions = @() $config = @{ 'floating-versions-use' = 'tags' 'check-minor-version' = 'error' } $result = & $Rule_MinorBranchMissing.Condition $state $config $result.Count | Should -Be 0 } It "should return empty when check-minor-version is 'none'" { $state = [RepositoryState]::new() $state.Tags += [VersionRef]::new("v1.0.0", "refs/tags/v1.0.0", "abc123", "tag") # No v1.0 branch $state.IgnoreVersions = @() $config = @{ 'floating-versions-use' = 'branches' 'check-minor-version' = 'none' } $result = & $Rule_MinorBranchMissing.Condition $state $config $result.Count | Should -Be 0 } It "should return empty when no patches exist" { $state = [RepositoryState]::new() # No patch versions at all $state.IgnoreVersions = @() $config = @{ 'floating-versions-use' = 'branches' 'check-minor-version' = 'error' } $result = & $Rule_MinorBranchMissing.Condition $state $config $result.Count | Should -Be 0 } It "should return multiple missing minors" { $state = [RepositoryState]::new() $state.Tags += [VersionRef]::new("v1.0.0", "refs/tags/v1.0.0", "abc123", "tag") $state.Tags += [VersionRef]::new("v1.1.0", "refs/tags/v1.1.0", "def456", "tag") $state.Tags += [VersionRef]::new("v2.0.0", "refs/tags/v2.0.0", "ghi789", "tag") # No v1.0, v1.1, or v2.0 branches $state.IgnoreVersions = @() $config = @{ 'floating-versions-use' = 'branches' 'check-minor-version' = 'error' } $result = & $Rule_MinorBranchMissing.Condition $state $config $result.Count | Should -Be 3 } It "should skip ignored patch versions" { $state = [RepositoryState]::new() $ignored = [VersionRef]::new("v1.0.0", "refs/tags/v1.0.0", "abc123", "tag") $ignored.IsIgnored = $true $state.Tags += $ignored $state.IgnoreVersions = @("v1.0.0") $config = @{ 'floating-versions-use' = 'branches' 'check-minor-version' = 'error' } $result = & $Rule_MinorBranchMissing.Condition $state $config $result.Count | Should -Be 0 } It "should NOT return missing minor when only prerelease patches exist in that series and ignore-preview-releases is true" { # This test demonstrates the bug where Condition returns a missing minor branch # even though the only patches in that minor series are prereleases. $state = [RepositoryState]::new() # v1.0.0 is stable $state.Tags += [VersionRef]::new("v1.0.0", "refs/tags/v1.0.0", "stable123", "tag") # v1.0 branch exists $state.Branches += [VersionRef]::new("v1.0", "refs/heads/v1.0", "stable123", "branch") # v1 branch exists $state.Branches += [VersionRef]::new("v1", "refs/heads/v1", "stable123", "branch") # v1.1.0 exists but is a prerelease $state.Tags += [VersionRef]::new("v1.1.0", "refs/tags/v1.1.0", "preview456", "tag") $state.IgnoreVersions = @() # Mark v1.1.0 as prerelease via ReleaseInfo $prereleaseData = [PSCustomObject]@{ tag_name = "v1.1.0" id = 2 draft = $false prerelease = $true html_url = "https://github.com/test/test/releases/tag/v1.1.0" target_commitish = "preview456" immutable = $false } $state.Releases += [ReleaseInfo]::new($prereleaseData) $config = @{ 'floating-versions-use' = 'branches' 'check-minor-version' = 'error' 'ignore-preview-releases' = $true } $result = & $Rule_MinorBranchMissing.Condition $state $config # Should NOT return missing minor when only prerelease patches exist # because prereleases are filtered out when ignore-preview-releases is true $result.Count | Should -Be 0 } It "should find patches from both tags and branches" { $state = [RepositoryState]::new() $state.Tags += [VersionRef]::new("v1.0.0", "refs/tags/v1.0.0", "abc123", "tag") $state.Branches += [VersionRef]::new("v2.0.0", "refs/heads/v2.0.0", "def456", "branch") # No v1.0 or v2.0 branches $state.IgnoreVersions = @() $config = @{ 'floating-versions-use' = 'branches' 'check-minor-version' = 'error' } $result = & $Rule_MinorBranchMissing.Condition $state $config $result.Count | Should -Be 2 } It "should handle multiple patches in same minor series correctly" { $state = [RepositoryState]::new() $state.Tags += [VersionRef]::new("v1.0.0", "refs/tags/v1.0.0", "abc123", "tag") $state.Tags += [VersionRef]::new("v1.0.1", "refs/tags/v1.0.1", "abc124", "tag") $state.Tags += [VersionRef]::new("v1.0.2", "refs/tags/v1.0.2", "abc125", "tag") # No v1.0 branch $state.IgnoreVersions = @() $config = @{ 'floating-versions-use' = 'branches' 'check-minor-version' = 'error' } $result = & $Rule_MinorBranchMissing.Condition $state $config # Should only report v1.0 once despite multiple patches $result.Count | Should -Be 1 $result[0].Major | Should -Be 1 $result[0].Minor | Should -Be 0 } } Context "CreateIssue" { It "should create issue with correct details" { $state = [RepositoryState]::new() $state.Tags += [VersionRef]::new("v1.0.0", "refs/tags/v1.0.0", "abc123", "tag") $state.IgnoreVersions = @() $item = [PSCustomObject]@{ Major = 1; Minor = 0 } $config = @{ 'ignore-preview-releases' = $true 'check-minor-version' = 'error' } $issue = & $Rule_MinorBranchMissing.CreateIssue $item $state $config $issue.Type | Should -Be "missing_minor_version" $issue.Severity | Should -Be "error" $issue.Version | Should -Be "v1.0" $issue.RemediationAction | Should -Not -BeNullOrEmpty $issue.RemediationAction.GetType().Name | Should -Be "CreateBranchAction" } It "should create warning severity when check-minor-version is warning" { $state = [RepositoryState]::new() $state.Tags += [VersionRef]::new("v1.0.0", "refs/tags/v1.0.0", "abc123", "tag") $state.IgnoreVersions = @() $item = [PSCustomObject]@{ Major = 1; Minor = 0 } $config = @{ 'ignore-preview-releases' = $true 'check-minor-version' = 'warning' } $issue = & $Rule_MinorBranchMissing.CreateIssue $item $state $config $issue.Severity | Should -Be "warning" } It "should configure CreateBranchAction with highest patch SHA in minor series" { $state = [RepositoryState]::new() $state.Tags += [VersionRef]::new("v2.1.0", "refs/tags/v2.1.0", "old123", "tag") $state.Tags += [VersionRef]::new("v2.1.1", "refs/tags/v2.1.1", "new456", "tag") $state.IgnoreVersions = @() $item = [PSCustomObject]@{ Major = 2; Minor = 1 } $config = @{ 'ignore-preview-releases' = $true 'check-minor-version' = 'error' } $issue = & $Rule_MinorBranchMissing.CreateIssue $item $state $config $issue.RemediationAction.BranchName | Should -Be "v2.1" $issue.RemediationAction.Sha | Should -Be "new456" } } Context "Prerelease Filtering" { It "should use non-prerelease SHA in CreateIssue when ignore-preview-releases is true" { $state = [RepositoryState]::new() # v1.0.0 is stable $state.Tags += [VersionRef]::new("v1.0.0", "refs/tags/v1.0.0", "stable123", "tag") # v1.0.1 is prerelease (higher version in same minor series but should be excluded) $state.Tags += [VersionRef]::new("v1.0.1", "refs/tags/v1.0.1", "prerel456", "tag") $state.IgnoreVersions = @() # Mark v1.0.1 as prerelease via ReleaseInfo $prereleaseData = [PSCustomObject]@{ tag_name = "v1.0.1" id = 2 draft = $false prerelease = $true html_url = "https://github.com/test/test/releases/tag/v1.0.1" target_commitish = "prerel456" immutable = $false } $state.Releases += [ReleaseInfo]::new($prereleaseData) $item = [PSCustomObject]@{ Major = 1; Minor = 0 } $config = @{ 'ignore-preview-releases' = $true 'check-minor-version' = 'error' } $issue = & $Rule_MinorBranchMissing.CreateIssue $item $state $config # Should use SHA from v1.0.0 (stable), not v1.0.1 (prerelease) $issue.ExpectedSha | Should -Be "stable123" } It "should use prerelease SHA in CreateIssue when ignore-preview-releases is false" { $state = [RepositoryState]::new() # v1.0.0 is stable $state.Tags += [VersionRef]::new("v1.0.0", "refs/tags/v1.0.0", "stable123", "tag") # v1.0.1 is prerelease (should be included) $state.Tags += [VersionRef]::new("v1.0.1", "refs/tags/v1.0.1", "prerel456", "tag") $state.IgnoreVersions = @() # Mark v1.0.1 as prerelease via ReleaseInfo $prereleaseData = [PSCustomObject]@{ tag_name = "v1.0.1" id = 2 draft = $false prerelease = $true html_url = "https://github.com/test/test/releases/tag/v1.0.1" target_commitish = "prerel456" immutable = $false } $state.Releases += [ReleaseInfo]::new($prereleaseData) $item = [PSCustomObject]@{ Major = 1; Minor = 0 } $config = @{ 'ignore-preview-releases' = $false 'check-minor-version' = 'error' } $issue = & $Rule_MinorBranchMissing.CreateIssue $item $state $config # Should use SHA from v1.0.1 (prerelease included) $issue.ExpectedSha | Should -Be "prerel456" } } } |