public/WinOS/Deploy-OSDCloud.Tests.ps1
|
BeforeAll { $moduleRoot = Join-Path $PSScriptRoot '..\..' $testModule = New-Module -Name DiskParameterDeploymentTests -ArgumentList $moduleRoot -ScriptBlock { param ($ModuleRoot) . "$ModuleRoot\public\WinOS\Deploy-OSDCloud.ps1" . "$ModuleRoot\private\Initialize-DeployOSDCloud.ps1" . "$ModuleRoot\private\Update-OSDCloudCoreCatalogOS.ps1" . "$ModuleRoot\private\core-license\Get-OSDCoreLicense.ps1" . "$ModuleRoot\private\core-license\Test-OSDCoreLicense.ps1" . "$ModuleRoot\private\core\Convert-KeyboardLayoutToLanguageCode.ps1" function Get-OSDCloudWorkflowRuntimeParameter { [CmdletBinding()] param ($ModuleBase, $WorkflowName, $ProcessorArchitecture) $parameters = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new() $attributes = [System.Collections.ObjectModel.Collection[System.Attribute]]::new() $attributes.Add([System.Management.Automation.ParameterAttribute]::new()) $parameters.Add('OSLanguageCode', [System.Management.Automation.RuntimeDefinedParameter]::new('OSLanguageCode', [string], $attributes)) return $parameters } function Initialize-OSDCoreLicense { [CmdletBinding()] param () } function Initialize-OSDCoreDevice { [CmdletBinding()] param () } function Invoke-OSDCloudWorkflowTask { [CmdletBinding()] param () } function Invoke-OSDCloudWorkflowUI { [CmdletBinding()] param ($WorkflowName) } } Import-Module $testModule $originalDevice = $global:OSDCoreDevice $originalDeploy = $global:OSDCloudDeploy $originalLicense = $global:OSDCoreLicense } AfterAll { Remove-Module DiskParameterDeploymentTests $global:OSDCoreDevice = $originalDevice $global:OSDCloudDeploy = $originalDeploy $global:OSDCoreLicense = $originalLicense } Describe 'Deploy-OSDCloud disk parameters' { BeforeEach { $global:OSDCoreDevice = [pscustomobject]@{ OSDManufacturer = 'HP'; OSDModel = 'Test'; OSDProduct = 'Test' ProcessorArchitecture = 'amd64'; KeyboardLayout = $null } $global:OSDCoreLicense = [pscustomobject]@{ IsRegistered = $true } $global:OSDCloudDeploy = [pscustomobject]@{ TimeStart = $null } Mock Get-OSDCoreLicense { if ($global:OSDCoreLicense.IsIncognito -ne $true) { [pscustomobject]@{ IsValid = $true } } } -ModuleName DiskParameterDeploymentTests Mock Convert-KeyboardLayoutToLanguageCode { 'fr-FR' } -ModuleName DiskParameterDeploymentTests Mock Initialize-OSDCoreLicense {} -ModuleName DiskParameterDeploymentTests Mock Initialize-OSDCoreDevice {} -ModuleName DiskParameterDeploymentTests Mock Initialize-DeployOSDCloud {} -ModuleName DiskParameterDeploymentTests Mock Invoke-OSDCloudWorkflowTask {} -ModuleName DiskParameterDeploymentTests Mock Invoke-OSDCloudWorkflowUI {} -ModuleName DiskParameterDeploymentTests Mock Export-Clixml {} -ModuleName DiskParameterDeploymentTests Mock Out-File {} -ModuleName DiskParameterDeploymentTests Mock Test-Path { $true } -ModuleName DiskParameterDeploymentTests Mock Remove-Item {} -ModuleName DiskParameterDeploymentTests Mock Write-Host {} -ModuleName DiskParameterDeploymentTests Mock Out-Host {} -ModuleName DiskParameterDeploymentTests } It 'forwards all explicit disk parameters for CLI and GUI launches: CLI=<CLI>' -TestCases @( @{ CLI = $true } @{ CLI = $false } ) { param ($CLI) Deploy-OSDCloud -CLI:$CLI -DiskNumber 0 -DiskLabelOS Windows -DiskLabelRecovery WinRE ` -DiskSizeSystem 1GB -DiskSizeOS 32GB -DiskSizeRecovery 3GB Should -Invoke Initialize-DeployOSDCloud -ModuleName DiskParameterDeploymentTests -Times 1 -Exactly -ParameterFilter { $DiskNumber -eq 0 -and $DiskLabelOS -eq 'Windows' -and $DiskLabelRecovery -eq 'WinRE' -and $DiskSizeSystem -eq 1GB -and $DiskSizeOS -eq 32GB -and $DiskSizeRecovery -eq 3GB } } It 'does not bind omitted disk parameters in the initializer' { Deploy-OSDCloud -CLI Should -Invoke Initialize-DeployOSDCloud -ModuleName DiskParameterDeploymentTests -Times 1 -Exactly -ParameterFilter { -not $PesterBoundParameters.ContainsKey('DiskSizeOS') -and -not $PesterBoundParameters.ContainsKey('DiskLabelOS') -and -not $PesterBoundParameters.ContainsKey('DiskSizeSystem') -and -not $PesterBoundParameters.ContainsKey('DiskSizeRecovery') } } It 'forces unregistered state before device and deployment initialization: CLI=<CLI>' -TestCases @( @{ CLI = $true } @{ CLI = $false } ) { param ($CLI) $savedLicense = [pscustomobject]@{ Email = 'test@example.invalid'; LicenseGuid = 'test-license' } Mock Initialize-OSDCoreLicense { $global:OSDCoreLicense = [pscustomobject]@{ IsRegistered = $true; License = $savedLicense } } -ModuleName DiskParameterDeploymentTests Mock Initialize-OSDCoreDevice { $global:OSDCoreLicense.IsRegistered | Should -BeFalse $global:OSDCoreLicense.IsRegistered = $true } -ModuleName DiskParameterDeploymentTests Mock Initialize-DeployOSDCloud { $global:OSDCoreLicense.IsRegistered | Should -BeFalse } -ModuleName DiskParameterDeploymentTests Deploy-OSDCloud -CLI:$CLI -Incognito $global:OSDCoreLicense.IsRegistered | Should -BeFalse $global:OSDCoreLicense.License | Should -Be $savedLicense Should -Invoke Initialize-OSDCoreLicense -ModuleName DiskParameterDeploymentTests -Times 1 -Exactly Should -Invoke Initialize-DeployOSDCloud -ModuleName DiskParameterDeploymentTests -Times 1 -Exactly } It 'reloads normal registration on the next launch without Incognito' { Mock Initialize-OSDCoreLicense { $global:OSDCoreLicense = [pscustomobject]@{ IsRegistered = $true } } -ModuleName DiskParameterDeploymentTests Deploy-OSDCloud -CLI -Incognito $global:OSDCoreLicense.IsRegistered | Should -BeFalse $global:OSDCoreLicense.IsIncognito | Should -BeTrue Deploy-OSDCloud -CLI $global:OSDCoreLicense.IsRegistered | Should -BeTrue $global:OSDCoreLicense.IsIncognito | Should -BeFalse Should -Invoke Initialize-OSDCoreLicense -ModuleName DiskParameterDeploymentTests -Times 2 -Exactly } It 'does not override normal registration when Incognito is explicitly false' { Deploy-OSDCloud -CLI -Incognito:$false $global:OSDCoreLicense.IsRegistered | Should -BeTrue $global:OSDCoreLicense.IsIncognito | Should -BeFalse } It 'skips real OS catalog updates with no discovery during Incognito: CLI=<CLI>' -TestCases @( @{ CLI = $true } @{ CLI = $false } ) { param ($CLI) Mock Invoke-RestMethod { throw 'Unexpected catalog request' } -ModuleName DiskParameterDeploymentTests Mock Invoke-WebRequest { throw 'Unexpected catalog download' } -ModuleName DiskParameterDeploymentTests Mock Get-Volume { throw 'Unexpected USB discovery' } -ModuleName DiskParameterDeploymentTests Mock Get-ChildItem { throw 'Unexpected license/catalog discovery' } -ModuleName DiskParameterDeploymentTests Mock Initialize-DeployOSDCloud { $global:OSDCoreLicense.IsIncognito | Should -BeTrue Get-OSDCoreLicense | Should -BeNullOrEmpty Update-OSDCloudCoreCatalogOS | Should -BeNullOrEmpty } -ModuleName DiskParameterDeploymentTests Deploy-OSDCloud -CLI:$CLI -Incognito -WarningVariable warnings @($warnings).Count | Should -Be 0 Should -Invoke Initialize-DeployOSDCloud -ModuleName DiskParameterDeploymentTests -Times 1 -Exactly Should -Invoke Invoke-RestMethod -ModuleName DiskParameterDeploymentTests -Times 0 -Exactly Should -Invoke Invoke-WebRequest -ModuleName DiskParameterDeploymentTests -Times 0 -Exactly Should -Invoke Get-Volume -ModuleName DiskParameterDeploymentTests -Times 0 -Exactly Should -Invoke Get-ChildItem -ModuleName DiskParameterDeploymentTests -Times 0 -Exactly Should -Invoke Write-Host -ModuleName DiskParameterDeploymentTests -Times 0 -Exactly -ParameterFilter { $Object -like '*updating the OS catalog*' -or $Object -like '*OS catalog saved to*' } } It 'skips registered keyboard language conversion in Incognito mode' { $global:OSDCoreDevice.KeyboardLayout = '00000409' Deploy-OSDCloud -CLI -Incognito Should -Invoke Initialize-DeployOSDCloud -ModuleName DiskParameterDeploymentTests -Times 1 -Exactly -ParameterFilter { $OSLanguageCode -eq 'en-US' } Should -Invoke Convert-KeyboardLayoutToLanguageCode -ModuleName DiskParameterDeploymentTests -Times 0 -Exactly } It 'infers language with a valid unregistered license: CLI=<CLI>, override=<Override>' -TestCases @( @{ CLI = $true; Override = $false } @{ CLI = $false; Override = $false } @{ CLI = $true; Override = $true } @{ CLI = $false; Override = $true } ) { param ($CLI, $Override) $global:OSDCoreLicense.IsRegistered = $false $global:OSDCoreDevice.KeyboardLayout = '0000040C' $parameters = @{ CLI = $CLI } if ($Override) { $parameters.KeyboardLayout = '0000040C' } Deploy-OSDCloud @parameters -WarningVariable warnings @($warnings).Count | Should -Be 0 Should -Invoke Convert-KeyboardLayoutToLanguageCode -ModuleName DiskParameterDeploymentTests -Times 1 -Exactly -ParameterFilter { $KeyboardLayout -eq '0000040C' -and $FallbackLanguageCode -eq 'en-US' } Should -Invoke Initialize-DeployOSDCloud -ModuleName DiskParameterDeploymentTests -Times 1 -Exactly -ParameterFilter { $OSLanguageCode -eq 'fr-FR' } Should -Invoke Write-Host -ModuleName DiskParameterDeploymentTests -Times 1 -Exactly -ParameterFilter { $Object -like '*has set the OSLanguageCode to fr-FR*' } } It 'quietly skips registered language inference for <Case>: CLI=<CLI>' -TestCases @( @{ CLI = $true; Case = 'missing' } @{ CLI = $false; Case = 'missing' } @{ CLI = $true; Case = 'invalid' } @{ CLI = $false; Case = 'invalid' } @{ CLI = $true; Case = 'registration only' } @{ CLI = $false; Case = 'registration only' } @{ CLI = $true; Case = 'failed lookup' } @{ CLI = $false; Case = 'failed lookup' } ) { param ($CLI, $Case) $global:OSDCoreDevice.KeyboardLayout = '0000040C' Mock Get-OSDCoreLicense { switch ($Case) { 'missing' { $null } 'invalid' { [pscustomobject]@{ IsValid = $false } } 'registration only' { [pscustomobject]@{ IsRegistered = $true } } 'failed lookup' { throw 'synthetic-private-license-data' } } } -ModuleName DiskParameterDeploymentTests $output = @(Deploy-OSDCloud -CLI:$CLI -KeyboardLayout '0000040C' -Verbose -WarningVariable warnings 4>&1 3>&1 2>&1) @($warnings).Count | Should -Be 0 @($output | Where-Object { $_ -is [System.Management.Automation.ErrorRecord] }).Count | Should -Be 0 "$output" | Should -Not -Match 'synthetic-private-license-data' Should -Invoke Convert-KeyboardLayoutToLanguageCode -ModuleName DiskParameterDeploymentTests -Times 0 -Exactly Should -Invoke Initialize-DeployOSDCloud -ModuleName DiskParameterDeploymentTests -Times 1 -Exactly -ParameterFilter { $OSLanguageCode -eq 'en-US' } Should -Invoke Write-Host -ModuleName DiskParameterDeploymentTests -Times 0 -Exactly -ParameterFilter { $Object -like '*has set the OSLanguageCode*' } } It 'preserves explicit language selection without checking a license: CLI=<CLI>' -TestCases @( @{ CLI = $true } @{ CLI = $false } ) { param ($CLI) $global:OSDCoreDevice.KeyboardLayout = '0000040C' Mock Get-OSDCoreLicense { throw 'Unexpected license lookup' } -ModuleName DiskParameterDeploymentTests Deploy-OSDCloud -CLI:$CLI -OSLanguageCode 'de-de' -KeyboardLayout '0000040C' Should -Invoke Get-OSDCoreLicense -ModuleName DiskParameterDeploymentTests -Times 0 -Exactly Should -Invoke Convert-KeyboardLayoutToLanguageCode -ModuleName DiskParameterDeploymentTests -Times 0 -Exactly Should -Invoke Initialize-DeployOSDCloud -ModuleName DiskParameterDeploymentTests -Times 1 -Exactly -ParameterFilter { $OSLanguageCode -eq 'de-de' } } It 'keeps en-US when the keyboard layout is unavailable with a valid license' { Deploy-OSDCloud -CLI Should -Invoke Convert-KeyboardLayoutToLanguageCode -ModuleName DiskParameterDeploymentTests -Times 0 -Exactly Should -Invoke Initialize-DeployOSDCloud -ModuleName DiskParameterDeploymentTests -Times 1 -Exactly -ParameterFilter { $OSLanguageCode -eq 'en-US' } } It 'surfaces licensed conversion failures instead of silently using a fallback' { $global:OSDCoreDevice.KeyboardLayout = '0000040C' Mock Convert-KeyboardLayoutToLanguageCode { throw 'Synthetic conversion failure' } -ModuleName DiskParameterDeploymentTests { Deploy-OSDCloud -CLI } | Should -Throw '*Synthetic conversion failure*' Should -Invoke Initialize-DeployOSDCloud -ModuleName DiskParameterDeploymentTests -Times 0 -Exactly } It 'documents every new parameter in the bundled external help' { [xml]$helpXml = Get-Content -LiteralPath "$moduleRoot\en-US\OSDCloud-help.xml" -Raw $namespaces = [System.Xml.XmlNamespaceManager]::new($helpXml.NameTable) $namespaces.AddNamespace('command', 'http://schemas.microsoft.com/maml/dev/command/2004/10') $namespaces.AddNamespace('maml', 'http://schemas.microsoft.com/maml/2004/10') $deployHelp = $helpXml.SelectSingleNode("//command:command[command:details/command:name='Deploy-OSDCloud']", $namespaces) $description = $deployHelp.SelectSingleNode('maml:description', $namespaces).InnerText $description | Should -Match 'valid Recast license.*Test-OSDCoreLicense.*IsValid = true' $description | Should -Not -Match 'require Initialize-OSDCoreLicense to report IsRegistered' foreach ($name in 'Incognito', 'DiskLabelOS', 'DiskLabelRecovery', 'DiskSizeSystem', 'DiskSizeOS', 'DiskSizeRecovery') { $deployHelp.SelectNodes("command:parameters/command:parameter[maml:name='$name']", $namespaces).Count | Should -Be 1 $deployHelp.SelectNodes("command:syntax/command:syntaxItem/command:parameter[maml:name='$name']", $namespaces).Count | Should -Be 1 } } It 'rejects invalid public input before initialization: <Name>' -TestCases @( @{ Name = 'DiskLabelOS'; Value = ' ' } @{ Name = 'DiskLabelRecovery'; Value = "bad`nlabel" } @{ Name = 'DiskSizeSystem'; Value = 99MB } @{ Name = 'DiskSizeOS'; Value = 0 } @{ Name = 'DiskSizeOS'; Value = 32GB - 1 } @{ Name = 'DiskSizeRecovery'; Value = 349MB } ) { param ($Name, $Value) $parameters = @{ $Name = $Value } { Deploy-OSDCloud -CLI @parameters } | Should -Throw Should -Invoke Initialize-DeployOSDCloud -ModuleName DiskParameterDeploymentTests -Times 0 -Exactly } } |