tests/general/Build-MaesterModule.Tests.ps1

BeforeAll {
    $script:BuildScriptPath = Resolve-Path "$PSScriptRoot/../../../build/Build-MaesterModule.ps1"
    $script:RepoRoot = (Resolve-Path "$PSScriptRoot/../../..").Path

    function Write-TestFileContent {
        param (
            [Parameter(Mandatory)]
            [string] $Path,

            [Parameter(Mandatory)]
            [string] $Content
        )

        $Utf8Bom = [System.Text.UTF8Encoding]::new($true)
        [System.IO.File]::WriteAllText($Path, $Content, $Utf8Bom)
    }

    function Initialize-BuildFixture {
        param (
            [Parameter()]
            [switch] $WithPublicParseError
        )

        $FixtureRoot = Join-Path $script:RepoRoot ".tmp-maester-build-tests-$([guid]::NewGuid())"
        $SourceRoot = Join-Path $FixtureRoot 'powershell'
        $TestsRoot = Join-Path $FixtureRoot 'tests'
        $OutputRoot = Join-Path $FixtureRoot 'module'

        $null = New-Item -Path (Join-Path $SourceRoot 'public/example') -ItemType Directory -Force
        $null = New-Item -Path (Join-Path $SourceRoot 'internal/orca/nested') -ItemType Directory -Force
        $null = New-Item -Path (Join-Path $SourceRoot 'assets') -ItemType Directory -Force
        $null = New-Item -Path $TestsRoot -ItemType Directory -Force

        $PublicFunctionContent = if ($WithPublicParseError) {
            @'
function Get-TestThing {
'@

        } else {
            @'
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')]
param(
    [string] $Unused
)
function Get-TestThing {
    [CmdletBinding()]
    param()
 
    return 'ok'
}
'@

        }

        Write-TestFileContent -Path (Join-Path $SourceRoot 'public/example/Get-TestThing.ps1') -Content $PublicFunctionContent
        Write-TestFileContent -Path (Join-Path $SourceRoot 'internal/Get-InternalThing.ps1') -Content @'
function Get-InternalThing {
    return 'internal'
}
'@

        Write-TestFileContent -Path (Join-Path $SourceRoot 'internal/orca/orcaClass.psm1') -Content @'
class ORCACheck {
}
'@

        Write-TestFileContent -Path (Join-Path $SourceRoot 'internal/orca/nested/check-ORCA999.ps1') -Content @'
# Generated by test fixture
using module ".\orcaClass.psm1"
param(
    [string] $Unused
)
class ORCA999 : ORCACheck {
}
'@

        Write-TestFileContent -Path (Join-Path $SourceRoot 'Maester.Format.ps1xml') -Content @'
<Configuration>
  <ViewDefinitions>
  </ViewDefinitions>
</Configuration>
'@

        Write-TestFileContent -Path (Join-Path $TestsRoot 'Sample.Tests.ps1') -Content @'
Describe 'Sample' {
    It 'passes' {
        $true | Should -BeTrue
    }
}
'@


        New-ModuleManifest `
            -Path (Join-Path $SourceRoot 'Maester.psd1') `
            -RootModule 'Maester.psm1' `
            -ModuleVersion '0.0.1' `
            -Guid ([guid]::NewGuid()) `
            -Author 'Maester' `
            -CompanyName 'Maester' `
            -AliasesToExport @('mt') `
            -FormatsToProcess @('Maester.Format.ps1xml')

        [pscustomobject]@{
            FixtureRoot = $FixtureRoot
            SourceRoot = $SourceRoot
            TestsRoot = $TestsRoot
            OutputRoot = $OutputRoot
        }
    }
}

AfterAll {
    Get-ChildItem -Path $script:RepoRoot -Directory -Filter '.tmp-maester-build-tests-*' |
        Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
}

Describe 'Build-MaesterModule' {
    Context 'When source parsing fails' {
        It 'stops with a parse error before producing output' {
            $Fixture = Initialize-BuildFixture -WithPublicParseError

            try {
                {
                    & $script:BuildScriptPath `
                        -SourceRoot $Fixture.SourceRoot `
                        -TestsRoot $Fixture.TestsRoot `
                        -OutputRoot $Fixture.OutputRoot *> $null
                } | Should -Throw -ExpectedMessage '*Parse error in*Get-TestThing.ps1*'
            } finally {
                Remove-Item -LiteralPath $Fixture.FixtureRoot -Recurse -Force -ErrorAction SilentlyContinue
            }
        }
    }

    Context 'When building a valid fixture' {
        It 'strips file-level preambles, recurses ORCA checks, and writes parseable outputs' {
            $Fixture = Initialize-BuildFixture

            try {
                & $script:BuildScriptPath `
                    -SourceRoot $Fixture.SourceRoot `
                    -TestsRoot $Fixture.TestsRoot `
                    -OutputRoot $Fixture.OutputRoot *> $null

                $OutputPsm1 = Join-Path $Fixture.OutputRoot 'Maester.psm1'
                $OutputOrcaClasses = Join-Path $Fixture.OutputRoot 'OrcaClasses.ps1'
                $OutputManifest = Join-Path $Fixture.OutputRoot 'Maester.psd1'

                $OutputPsm1 | Should -Exist
                $OutputOrcaClasses | Should -Exist
                $OutputManifest | Should -Exist

                $Psm1Content = Get-Content -Path $OutputPsm1 -Raw
                $OrcaContent = Get-Content -Path $OutputOrcaClasses -Raw
                $Manifest = Import-PowerShellDataFile -Path $OutputManifest

                $Psm1Content | Should -Match 'function Get-TestThing'
                $Psm1Content | Should -Not -Match '\$Unused'
                $OrcaContent | Should -Match 'class ORCA999 : ORCACheck'
                $OrcaContent | Should -Not -Match 'using module'
                $Manifest.FunctionsToExport | Should -Contain 'Get-TestThing'
                $Manifest.ScriptsToProcess | Should -Contain 'OrcaClasses.ps1'
            } finally {
                Remove-Item -LiteralPath $Fixture.FixtureRoot -Recurse -Force -ErrorAction SilentlyContinue
            }
        }
    }
}