lib/rules/marketplace/marketplace_publication_required/marketplace_publication_required.Tests.ps1

#############################################################################
# Tests for marketplace_publication_required rule
#############################################################################

BeforeAll {
    . "$PSScriptRoot/../../../StateModel.ps1"
    . "$PSScriptRoot/../../../ValidationRules.ps1"
    . "$PSScriptRoot/../../../VersionParser.ps1"
    . "$PSScriptRoot/../MarketplaceRulesHelper.ps1"
    . "$PSScriptRoot/marketplace_publication_required.ps1"
}

AfterAll {
    # No cleanup needed - Pester handles mock cleanup
}

Describe "marketplace_publication_required" {
    Context "Rule Properties" {
        It "should have correct name" {
            $Rule_MarketplacePublicationRequired.Name | Should -Be "marketplace_publication_required"
        }
        
        It "should have correct category" {
            $Rule_MarketplacePublicationRequired.Category | Should -Be "marketplace"
        }
        
        It "should have high priority (runs late)" {
            $Rule_MarketplacePublicationRequired.Priority | Should -BeGreaterOrEqual 40
        }
    }
    
    Context "Condition" {
        It "should return empty when check-marketplace is none" {
            $state = [RepositoryState]::new()
            $config = @{ 'check-marketplace' = 'none' }
            
            $result = & $Rule_MarketplacePublicationRequired.Condition $state $config
            
            $result | Should -BeNullOrEmpty
        }
        
        It "should return empty when marketplace metadata is invalid" {
            $state = [RepositoryState]::new()
            $state.MarketplaceMetadata = [MarketplaceMetadata]::new()  # All invalid
            $config = @{ 'check-marketplace' = 'error' }
            
            $result = & $Rule_MarketplacePublicationRequired.Condition $state $config
            
            $result | Should -BeNullOrEmpty
        }
        
        It "should return empty when no latest release exists" {
            $state = [RepositoryState]::new()
            
            # Valid metadata
            $metadata = [MarketplaceMetadata]::new()
            $metadata.ActionFileExists = $true
            $metadata.HasName = $true
            $metadata.HasDescription = $true
            $metadata.HasBrandingIcon = $true
            $metadata.HasBrandingColor = $true
            $metadata.ReadmeExists = $true
            $state.MarketplaceMetadata = $metadata
            
            # No releases
            $state.Releases = @()
            
            $config = @{ 'check-marketplace' = 'error' }
            
            $result = & $Rule_MarketplacePublicationRequired.Condition $state $config
            
            $result | Should -BeNullOrEmpty
        }
        
        It "should return latest release when metadata is valid and latest release exists" {
            $state = [RepositoryState]::new()
            
            # Valid metadata
            $metadata = [MarketplaceMetadata]::new()
            $metadata.ActionFileExists = $true
            $metadata.HasName = $true
            $metadata.HasDescription = $true
            $metadata.HasBrandingIcon = $true
            $metadata.HasBrandingColor = $true
            $metadata.ReadmeExists = $true
            $state.MarketplaceMetadata = $metadata
            
            # Create a release marked as latest
            $releaseData = [PSCustomObject]@{
                tag_name = "v1.0.0"
                id = 123
                draft = $false
                prerelease = $false
                html_url = "https://github.com/owner/repo/releases/tag/v1.0.0"
                target_commitish = "abc123"
                is_latest = $true
                immutable = $true
            }
            $release = [ReleaseInfo]::new($releaseData)
            $state.Releases = @($release)
            
            $config = @{ 'check-marketplace' = 'error' }
            
            $result = & $Rule_MarketplacePublicationRequired.Condition $state $config
            
            $result | Should -Not -BeNullOrEmpty
            $result.Count | Should -Be 1
            $result[0].TagName | Should -Be "v1.0.0"
        }
    }
    
    Context "Check" {
        It "should return true when metadata has no name (skip check)" {
            $state = [RepositoryState]::new()
            $state.MarketplaceMetadata = [MarketplaceMetadata]::new()  # HasName = false
            
            $releaseData = [PSCustomObject]@{
                tag_name = "v1.0.0"
                id = 123
                draft = $false
                prerelease = $false
                html_url = "https://github.com/owner/repo/releases/tag/v1.0.0"
                target_commitish = "abc123"
                is_latest = $true
            }
            $release = [ReleaseInfo]::new($releaseData)
            $config = @{ 'check-marketplace' = 'error' }
            
            $result = & $Rule_MarketplacePublicationRequired.Check $release $state $config
            
            # Should skip check when no name available
            $result | Should -Be $true
        }
        
        It "should return true when version is published to marketplace" {
            # Mock Test-MarketplaceVersionPublished to return published
            Mock -CommandName Test-MarketplaceVersionPublished -MockWith {
                param($ActionName, $Version, $ServerUrl)
                return [PSCustomObject]@{
                    IsPublished = $true
                    MarketplaceUrl = "https://github.com/marketplace/actions/test-action?version=$Version"
                    Error = $null
                }
            }
            
            $state = [RepositoryState]::new()
            $state.ServerUrl = "https://github.com"
            
            # Valid metadata with ALL required fields
            $metadata = [MarketplaceMetadata]::new()
            $metadata.ActionFileExists = $true
            $metadata.ActionFilePath = "action.yaml"
            $metadata.HasName = $true
            $metadata.Name = "Test Action"
            $metadata.HasDescription = $true
            $metadata.Description = "Test description"
            $metadata.HasBrandingIcon = $true
            $metadata.BrandingIcon = "check"
            $metadata.HasBrandingColor = $true
            $metadata.BrandingColor = "blue"
            $metadata.ReadmeExists = $true
            $state.MarketplaceMetadata = $metadata
            
            $releaseData = [PSCustomObject]@{
                tag_name = "v1.0.9"
                id = 123
                draft = $false
                prerelease = $false
                html_url = "https://github.com/owner/repo/releases/tag/v1.0.9"
                target_commitish = "abc123"
                is_latest = $true
            }
            $release = [ReleaseInfo]::new($releaseData)
            $config = @{ 'check-marketplace' = 'error' }
            
            $result = & $Rule_MarketplacePublicationRequired.Check $release $state $config
            
            $result | Should -Be $true
        }
        
        It "should return false when version is not published to marketplace" {
            # Mock Test-MarketplaceVersionPublished to return NOT published
            Mock -CommandName Test-MarketplaceVersionPublished -MockWith {
                param($ActionName, $Version, $ServerUrl)
                return [PSCustomObject]@{
                    IsPublished = $false
                    MarketplaceUrl = "https://github.com/marketplace/actions/test-action?version=$Version"
                    Error = $null
                }
            }
            
            $state = [RepositoryState]::new()
            $state.ServerUrl = "https://github.com"
            
            # Valid metadata with ALL required fields
            $metadata = [MarketplaceMetadata]::new()
            $metadata.ActionFileExists = $true
            $metadata.ActionFilePath = "action.yaml"
            $metadata.HasName = $true
            $metadata.Name = "Test Action"
            $metadata.HasDescription = $true
            $metadata.Description = "Test description"
            $metadata.HasBrandingIcon = $true
            $metadata.BrandingIcon = "check"
            $metadata.HasBrandingColor = $true
            $metadata.BrandingColor = "blue"
            $metadata.ReadmeExists = $true
            $state.MarketplaceMetadata = $metadata
            
            $releaseData = [PSCustomObject]@{
                tag_name = "v1.0.9"
                id = 123
                draft = $false
                prerelease = $false
                html_url = "https://github.com/owner/repo/releases/tag/v1.0.9"
                target_commitish = "abc123"
                is_latest = $true
            }
            $release = [ReleaseInfo]::new($releaseData)
            $config = @{ 'check-marketplace' = 'error' }
            
            $result = & $Rule_MarketplacePublicationRequired.Check $release $state $config
            
            $result | Should -Be $false
        }
        
        It "should return true when marketplace check has error (avoid false positives)" {
            # Mock Test-MarketplaceVersionPublished to return an error
            Mock -CommandName Test-MarketplaceVersionPublished -MockWith {
                param($ActionName, $Version, $ServerUrl)
                return [PSCustomObject]@{
                    IsPublished = $false
                    MarketplaceUrl = "https://github.com/marketplace/actions/test-action?version=$Version"
                    Error = "Network connection error"
                }
            }
            
            $state = [RepositoryState]::new()
            $state.ServerUrl = "https://github.com"
            
            # Valid metadata with ALL required fields
            $metadata = [MarketplaceMetadata]::new()
            $metadata.ActionFileExists = $true
            $metadata.ActionFilePath = "action.yaml"
            $metadata.HasName = $true
            $metadata.Name = "Test Action"
            $metadata.HasDescription = $true
            $metadata.Description = "Test description"
            $metadata.HasBrandingIcon = $true
            $metadata.BrandingIcon = "check"
            $metadata.HasBrandingColor = $true
            $metadata.BrandingColor = "blue"
            $metadata.ReadmeExists = $true
            $state.MarketplaceMetadata = $metadata
            
            $releaseData = [PSCustomObject]@{
                tag_name = "v1.0.0"
                id = 123
                draft = $false
                prerelease = $false
                html_url = "https://github.com/owner/repo/releases/tag/v1.0.0"
                target_commitish = "abc123"
                is_latest = $true
            }
            $release = [ReleaseInfo]::new($releaseData)
            $config = @{ 'check-marketplace' = 'error' }
            
            $result = & $Rule_MarketplacePublicationRequired.Check $release $state $config
            
            # Should return true to avoid false positives on errors
            $result | Should -Be $true
        }
    }
}