mirror of
https://github.com/GoodOlClint/PSProxmoxVE.git
synced 2026-07-26 07:58:14 +00:00
test: add Pester cmdlet unit tests across OS and PS version matrix
18 Pester 5 test files covering parameter validation, pipeline support, -WhatIf behavior, ShouldProcess/ConfirmImpact attributes, and session requirement enforcement for all cmdlet groups. Fully mocked — no network calls. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,246 @@
|
||||
#Requires -Module Pester
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Pester 5 tests for cloud-init cmdlets:
|
||||
Get-PveCloudInitConfig, Set-PveCloudInitConfig, Invoke-PveCloudInitRegenerate.
|
||||
|
||||
All tests are fully offline — no live Proxmox VE target is required.
|
||||
If a cmdlet is not yet compiled the test is marked Skipped.
|
||||
|
||||
Cloud-Init cmdlets operate on an existing QEMU VM's cloud-init drive.
|
||||
The configuration fields map to the PveCloudInitConfig model:
|
||||
CiUser, CiPassword, SshKeys, IpConfig0..3, Nameserver,
|
||||
Searchdomain, CiCustom.
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
|
||||
$script:Availability = @{}
|
||||
foreach ($name in @('Get-PveCloudInitConfig', 'Set-PveCloudInitConfig',
|
||||
'Invoke-PveCloudInitRegenerate')) {
|
||||
$script:Availability[$name] = $null -ne (Get-Command $name -ErrorAction SilentlyContinue)
|
||||
}
|
||||
|
||||
function Skip-IfMissing([string]$Name) {
|
||||
if (-not $script:Availability[$Name]) {
|
||||
Set-ItResult -Skipped -Because "$Name is not yet implemented in this build"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Manifest contract
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Cloud-Init cmdlets — manifest declarations' {
|
||||
BeforeAll {
|
||||
$manifestPath = Join-Path $moduleRoot 'PSProxmoxVE.psd1'
|
||||
$script:Manifest = if (Test-Path $manifestPath) { Import-PowerShellDataFile $manifestPath } else { $null }
|
||||
}
|
||||
|
||||
foreach ($cmdName in @('Get-PveCloudInitConfig', 'Set-PveCloudInitConfig',
|
||||
'Invoke-PveCloudInitRegenerate')) {
|
||||
It "$cmdName should be declared in CmdletsToExport" {
|
||||
if ($null -eq $script:Manifest) { Set-ItResult -Skipped -Because 'Manifest not found'; return }
|
||||
$script:Manifest.CmdletsToExport | Should -Contain $cmdName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Get-PveCloudInitConfig
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Get-PveCloudInitConfig' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'Get-PveCloudInitConfig' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'Get-PveCloudInitConfig'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should be a CmdletInfo (binary cmdlet)' {
|
||||
Skip-IfMissing 'Get-PveCloudInitConfig'
|
||||
$script:Cmd.CommandType | Should -Be 'Cmdlet'
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Parameter metadata' {
|
||||
It 'Node should be Mandatory' {
|
||||
Skip-IfMissing 'Get-PveCloudInitConfig'
|
||||
$isMandatory = $script:Cmd.Parameters['Node'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'VmId should be Mandatory' {
|
||||
Skip-IfMissing 'Get-PveCloudInitConfig'
|
||||
$isMandatory = $script:Cmd.Parameters['VmId'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should have Session parameter' {
|
||||
Skip-IfMissing 'Get-PveCloudInitConfig'
|
||||
$script:Cmd.Parameters.ContainsKey('Session') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active' {
|
||||
Skip-IfMissing 'Get-PveCloudInitConfig'
|
||||
{ Get-PveCloudInitConfig -Node 'pve-node1' -VmId 100 -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Set-PveCloudInitConfig
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Set-PveCloudInitConfig' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'Set-PveCloudInitConfig' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'Set-PveCloudInitConfig'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'ShouldProcess support' {
|
||||
It 'Should support WhatIf' {
|
||||
Skip-IfMissing 'Set-PveCloudInitConfig'
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Required parameters' {
|
||||
It 'Node should be Mandatory' {
|
||||
Skip-IfMissing 'Set-PveCloudInitConfig'
|
||||
$isMandatory = $script:Cmd.Parameters['Node'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'VmId should be Mandatory' {
|
||||
Skip-IfMissing 'Set-PveCloudInitConfig'
|
||||
$isMandatory = $script:Cmd.Parameters['VmId'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Optional cloud-init configuration parameters' {
|
||||
It 'Should have CiUser parameter' {
|
||||
Skip-IfMissing 'Set-PveCloudInitConfig'
|
||||
$script:Cmd.Parameters.ContainsKey('CiUser') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have CiPassword parameter (SecureString or plain-text)' {
|
||||
Skip-IfMissing 'Set-PveCloudInitConfig'
|
||||
$hasPassword = $script:Cmd.Parameters.ContainsKey('CiPassword') -or
|
||||
$script:Cmd.Parameters.ContainsKey('Password')
|
||||
$hasPassword | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have SshKeys parameter' {
|
||||
Skip-IfMissing 'Set-PveCloudInitConfig'
|
||||
$hasSsh = $script:Cmd.Parameters.ContainsKey('SshKeys') -or
|
||||
$script:Cmd.Parameters.ContainsKey('SshPublicKey')
|
||||
$hasSsh | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have IpConfig0 parameter' {
|
||||
Skip-IfMissing 'Set-PveCloudInitConfig'
|
||||
$script:Cmd.Parameters.ContainsKey('IpConfig0') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Nameserver parameter' {
|
||||
Skip-IfMissing 'Set-PveCloudInitConfig'
|
||||
$script:Cmd.Parameters.ContainsKey('Nameserver') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Searchdomain parameter' {
|
||||
Skip-IfMissing 'Set-PveCloudInitConfig'
|
||||
$script:Cmd.Parameters.ContainsKey('Searchdomain') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active (without -WhatIf)' {
|
||||
Skip-IfMissing 'Set-PveCloudInitConfig'
|
||||
{ Set-PveCloudInitConfig -Node 'pve-node1' -VmId 100 -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Invoke-PveCloudInitRegenerate
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Invoke-PveCloudInitRegenerate' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'Invoke-PveCloudInitRegenerate' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'Invoke-PveCloudInitRegenerate'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'ShouldProcess support' {
|
||||
It 'Should support WhatIf' {
|
||||
Skip-IfMissing 'Invoke-PveCloudInitRegenerate'
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Required parameters' {
|
||||
It 'Node should be Mandatory' {
|
||||
Skip-IfMissing 'Invoke-PveCloudInitRegenerate'
|
||||
$isMandatory = $script:Cmd.Parameters['Node'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'VmId should be Mandatory' {
|
||||
Skip-IfMissing 'Invoke-PveCloudInitRegenerate'
|
||||
$isMandatory = $script:Cmd.Parameters['VmId'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Optional parameters' {
|
||||
It 'Should have Wait switch parameter' {
|
||||
Skip-IfMissing 'Invoke-PveCloudInitRegenerate'
|
||||
$script:Cmd.Parameters.ContainsKey('Wait') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active (without -WhatIf)' {
|
||||
Skip-IfMissing 'Invoke-PveCloudInitRegenerate'
|
||||
{ Invoke-PveCloudInitRegenerate -Node 'pve-node1' -VmId 100 -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
#Requires -Module Pester
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Pester 5 tests for Connect-PveServer.
|
||||
All tests are fully offline — no live Proxmox VE target is required.
|
||||
The suite validates parameter metadata and parameter-set enforcement, which
|
||||
are enforced by PowerShell itself and do not require a real HTTP call.
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
# Resolve the built DLL relative to the repository root.
|
||||
# Adjust the path if your build output directory differs.
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
}
|
||||
|
||||
Describe 'Connect-PveServer' {
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Get-Command 'Connect-PveServer' -ErrorAction SilentlyContinue |
|
||||
Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should be a CmdletInfo (binary cmdlet)' {
|
||||
(Get-Command 'Connect-PveServer').CommandType | Should -Be 'Cmdlet'
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Parameter validation — missing required parameters' {
|
||||
It 'Should throw when Server is omitted entirely' {
|
||||
{ Connect-PveServer -ErrorAction Stop } | Should -Throw
|
||||
}
|
||||
|
||||
It 'Should throw when Server is provided but neither Credential nor ApiToken is supplied' {
|
||||
# Both parameter sets require one of Credential/ApiToken; omitting both is an error.
|
||||
{ Connect-PveServer -Server 'pve.example.com' -ErrorAction Stop } | Should -Throw
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Parameter validation — mutually exclusive parameter sets' {
|
||||
It 'Should not allow both Credential and ApiToken together' {
|
||||
$securePass = ConvertTo-SecureString 'hunter2' -AsPlainText -Force
|
||||
$cred = [System.Management.Automation.PSCredential]::new('root@pam', $securePass)
|
||||
{
|
||||
Connect-PveServer `
|
||||
-Server 'pve.example.com' `
|
||||
-Credential $cred `
|
||||
-ApiToken 'root@pam!mytoken=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' `
|
||||
-ErrorAction Stop
|
||||
} | Should -Throw
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Parameter metadata' {
|
||||
BeforeAll {
|
||||
$script:Cmd = Get-Command 'Connect-PveServer'
|
||||
}
|
||||
|
||||
It 'Should have a Server parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('Server') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should declare Server as Mandatory' {
|
||||
$serverParam = $script:Cmd.Parameters['Server']
|
||||
$isMandatory = $serverParam.ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory } |
|
||||
Select-Object -First 1
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should have a Port parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('Port') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Port should default to 8006' {
|
||||
# Verify default via the static default-value metadata on the parameter.
|
||||
$portParam = $script:Cmd.Parameters['Port']
|
||||
$portParam | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should have a Credential parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('Credential') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have an ApiToken parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('ApiToken') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have a SkipCertificateCheck switch parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('SkipCertificateCheck') | Should -BeTrue
|
||||
$script:Cmd.Parameters['SkipCertificateCheck'].ParameterType |
|
||||
Should -Be ([System.Management.Automation.SwitchParameter])
|
||||
}
|
||||
|
||||
It 'Should have a PassThru switch parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('PassThru') | Should -BeTrue
|
||||
$script:Cmd.Parameters['PassThru'].ParameterType |
|
||||
Should -Be ([System.Management.Automation.SwitchParameter])
|
||||
}
|
||||
|
||||
It 'Credential and ApiToken should belong to different parameter sets' {
|
||||
$credSets = $script:Cmd.Parameters['Credential'].ParameterSets.Keys
|
||||
$tokenSets = $script:Cmd.Parameters['ApiToken'].ParameterSets.Keys
|
||||
$overlap = $credSets | Where-Object { $tokenSets -contains $_ }
|
||||
$overlap | Should -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
#Requires -Module Pester
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Pester 5 tests for Disconnect-PveServer.
|
||||
All tests are fully offline — no live Proxmox VE target is required.
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
}
|
||||
|
||||
Describe 'Disconnect-PveServer' {
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Get-Command 'Disconnect-PveServer' -ErrorAction SilentlyContinue |
|
||||
Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should be a CmdletInfo (binary cmdlet)' {
|
||||
(Get-Command 'Disconnect-PveServer').CommandType | Should -Be 'Cmdlet'
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Parameter metadata' {
|
||||
BeforeAll {
|
||||
$script:Cmd = Get-Command 'Disconnect-PveServer'
|
||||
}
|
||||
|
||||
It 'Should support ShouldProcess (have WhatIf and Confirm parameters)' {
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
$script:Cmd.Parameters.ContainsKey('Confirm') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should declare ConfirmImpact Low (no explicit -Confirm needed for normal use)' {
|
||||
# SupportsShouldProcess is reflected as WhatIf/Confirm parameters.
|
||||
# ConfirmImpact=Low means PowerShell will not auto-prompt; just verify the
|
||||
# attribute is present by confirming ShouldProcess support is enabled.
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Behaviour when no session is active' {
|
||||
It 'Should run without error and emit a warning when no session exists' {
|
||||
# Ensure module state has no active session by disconnecting first (may already be null).
|
||||
# Disconnect-PveServer should emit a warning, not throw.
|
||||
{ Disconnect-PveServer -ErrorAction Stop } | Should -Not -Throw
|
||||
}
|
||||
}
|
||||
|
||||
Context 'WhatIf support' {
|
||||
It 'Should accept -WhatIf without throwing' {
|
||||
{ Disconnect-PveServer -WhatIf -ErrorAction Stop } | Should -Not -Throw
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
#Requires -Module Pester
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Pester 5 tests for Test-PveConnection.
|
||||
All tests are fully offline — no live Proxmox VE target is required.
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
}
|
||||
|
||||
Describe 'Test-PveConnection' {
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Get-Command 'Test-PveConnection' -ErrorAction SilentlyContinue |
|
||||
Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should be a CmdletInfo (binary cmdlet)' {
|
||||
(Get-Command 'Test-PveConnection').CommandType | Should -Be 'Cmdlet'
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Parameter metadata' {
|
||||
BeforeAll {
|
||||
$script:Cmd = Get-Command 'Test-PveConnection'
|
||||
}
|
||||
|
||||
It 'Should have a Detailed switch parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('Detailed') | Should -BeTrue
|
||||
$script:Cmd.Parameters['Detailed'].ParameterType |
|
||||
Should -Be ([System.Management.Automation.SwitchParameter])
|
||||
}
|
||||
|
||||
It 'Detailed should not be Mandatory' {
|
||||
$detailed = $script:Cmd.Parameters['Detailed']
|
||||
$isMandatory = $detailed.ParameterSets.Values | Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Behaviour without an active session' {
|
||||
It 'Should return $false when no session is active (default mode)' {
|
||||
$result = Test-PveConnection
|
||||
$result | Should -BeFalse
|
||||
}
|
||||
|
||||
It 'Should return nothing when -Detailed is specified and no session is active' {
|
||||
$result = Test-PveConnection -Detailed
|
||||
$result | Should -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should not throw when called with no arguments and no session' {
|
||||
{ Test-PveConnection -ErrorAction Stop } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Should not throw when called with -Detailed and no session' {
|
||||
{ Test-PveConnection -Detailed -ErrorAction Stop } | Should -Not -Throw
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Output type contract' {
|
||||
It 'Default output is a boolean' {
|
||||
$result = Test-PveConnection
|
||||
$result | Should -BeOfType [bool]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,314 @@
|
||||
#Requires -Module Pester
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Pester 5 tests for container lifecycle cmdlets:
|
||||
New-PveContainer, Remove-PveContainer,
|
||||
Start-PveContainer, Stop-PveContainer, Restart-PveContainer.
|
||||
|
||||
All tests are fully offline — no live Proxmox VE target is required.
|
||||
If a cmdlet is not yet compiled into the DLL the test is marked Skipped.
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
|
||||
# Pre-calculate availability for each cmdlet.
|
||||
$script:Availability = @{}
|
||||
foreach ($name in @('New-PveContainer', 'Remove-PveContainer',
|
||||
'Start-PveContainer', 'Stop-PveContainer',
|
||||
'Restart-PveContainer',
|
||||
'Get-PveContainerConfig', 'Set-PveContainerConfig',
|
||||
'Copy-PveContainer')) {
|
||||
$script:Availability[$name] = $null -ne (Get-Command $name -ErrorAction SilentlyContinue)
|
||||
}
|
||||
|
||||
function Skip-IfMissing([string]$Name) {
|
||||
if (-not $script:Availability[$Name]) {
|
||||
Set-ItResult -Skipped -Because "$Name is not yet implemented in this build"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# New-PveContainer
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'New-PveContainer' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'New-PveContainer' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'New-PveContainer'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'ShouldProcess support' {
|
||||
It 'Should support WhatIf' {
|
||||
Skip-IfMissing 'New-PveContainer'
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Required parameters' {
|
||||
It 'Node should be Mandatory' {
|
||||
Skip-IfMissing 'New-PveContainer'
|
||||
$isMandatory = $script:Cmd.Parameters['Node'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should throw when Node is omitted' {
|
||||
Skip-IfMissing 'New-PveContainer'
|
||||
{ New-PveContainer -ErrorAction Stop } | Should -Throw
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Optional parameters' {
|
||||
It 'Should have Wait switch parameter' {
|
||||
Skip-IfMissing 'New-PveContainer'
|
||||
$script:Cmd.Parameters.ContainsKey('Wait') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Session parameter' {
|
||||
Skip-IfMissing 'New-PveContainer'
|
||||
$script:Cmd.Parameters.ContainsKey('Session') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active (without -WhatIf)' {
|
||||
Skip-IfMissing 'New-PveContainer'
|
||||
{ New-PveContainer -Node 'pve-node1' -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Remove-PveContainer
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Remove-PveContainer' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'Remove-PveContainer' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'Remove-PveContainer'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'ShouldProcess / ConfirmImpact' {
|
||||
It 'Should support WhatIf' {
|
||||
Skip-IfMissing 'Remove-PveContainer'
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should declare ConfirmImpact High' {
|
||||
Skip-IfMissing 'Remove-PveContainer'
|
||||
$attr = $script:Cmd.ImplementingType.GetCustomAttributes(
|
||||
[System.Management.Automation.CmdletAttribute], $false) |
|
||||
Select-Object -First 1
|
||||
$attr.ConfirmImpact | Should -Be ([System.Management.Automation.ConfirmImpact]::High)
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Required parameters' {
|
||||
It 'Node should be Mandatory' {
|
||||
Skip-IfMissing 'Remove-PveContainer'
|
||||
$isMandatory = $script:Cmd.Parameters['Node'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'VmId should be Mandatory' {
|
||||
Skip-IfMissing 'Remove-PveContainer'
|
||||
$isMandatory = $script:Cmd.Parameters['VmId'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Optional parameters' {
|
||||
It 'Should have Purge switch parameter' {
|
||||
Skip-IfMissing 'Remove-PveContainer'
|
||||
$script:Cmd.Parameters.ContainsKey('Purge') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Wait switch parameter' {
|
||||
Skip-IfMissing 'Remove-PveContainer'
|
||||
$script:Cmd.Parameters.ContainsKey('Wait') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active (without -WhatIf)' {
|
||||
Skip-IfMissing 'Remove-PveContainer'
|
||||
{ Remove-PveContainer -Node 'pve-node1' -VmId 200 -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
|
||||
It 'Should not throw with -WhatIf' {
|
||||
Skip-IfMissing 'Remove-PveContainer'
|
||||
{ Remove-PveContainer -Node 'pve-node1' -VmId 200 -WhatIf -ErrorAction Stop } |
|
||||
Should -Not -Throw
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Start-PveContainer
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Start-PveContainer' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'Start-PveContainer' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'Start-PveContainer'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Parameter metadata' {
|
||||
It 'Node should be Mandatory' {
|
||||
Skip-IfMissing 'Start-PveContainer'
|
||||
$isMandatory = $script:Cmd.Parameters['Node'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'VmId should be Mandatory' {
|
||||
Skip-IfMissing 'Start-PveContainer'
|
||||
$isMandatory = $script:Cmd.Parameters['VmId'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should have Wait switch parameter' {
|
||||
Skip-IfMissing 'Start-PveContainer'
|
||||
$script:Cmd.Parameters.ContainsKey('Wait') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should support ShouldProcess' {
|
||||
Skip-IfMissing 'Start-PveContainer'
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active' {
|
||||
Skip-IfMissing 'Start-PveContainer'
|
||||
{ Start-PveContainer -Node 'pve-node1' -VmId 200 -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Stop-PveContainer
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Stop-PveContainer' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'Stop-PveContainer' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'Stop-PveContainer'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Parameter metadata' {
|
||||
It 'Node should be Mandatory' {
|
||||
Skip-IfMissing 'Stop-PveContainer'
|
||||
$isMandatory = $script:Cmd.Parameters['Node'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'VmId should be Mandatory' {
|
||||
Skip-IfMissing 'Stop-PveContainer'
|
||||
$isMandatory = $script:Cmd.Parameters['VmId'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should have Wait switch parameter' {
|
||||
Skip-IfMissing 'Stop-PveContainer'
|
||||
$script:Cmd.Parameters.ContainsKey('Wait') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should support ShouldProcess' {
|
||||
Skip-IfMissing 'Stop-PveContainer'
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active' {
|
||||
Skip-IfMissing 'Stop-PveContainer'
|
||||
{ Stop-PveContainer -Node 'pve-node1' -VmId 200 -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Restart-PveContainer
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Restart-PveContainer' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'Restart-PveContainer' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'Restart-PveContainer'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Parameter metadata' {
|
||||
It 'Node should be Mandatory' {
|
||||
Skip-IfMissing 'Restart-PveContainer'
|
||||
$isMandatory = $script:Cmd.Parameters['Node'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'VmId should be Mandatory' {
|
||||
Skip-IfMissing 'Restart-PveContainer'
|
||||
$isMandatory = $script:Cmd.Parameters['VmId'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should support ShouldProcess' {
|
||||
Skip-IfMissing 'Restart-PveContainer'
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active' {
|
||||
Skip-IfMissing 'Restart-PveContainer'
|
||||
{ Restart-PveContainer -Node 'pve-node1' -VmId 200 -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
#Requires -Module Pester
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Pester 5 tests for Get-PveContainer.
|
||||
All tests are fully offline — no live Proxmox VE target is required.
|
||||
|
||||
Get-PveContainer mirrors the design of Get-PveVm for LXC containers.
|
||||
If the cmdlet is not yet implemented (dll compiled without it), tests
|
||||
that depend on invocation are marked Skipped rather than Failed.
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
|
||||
$script:CmdExists = $null -ne (Get-Command 'Get-PveContainer' -ErrorAction SilentlyContinue)
|
||||
}
|
||||
|
||||
Describe 'Get-PveContainer' {
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Get-PveContainer should be listed in the module manifest CmdletsToExport' {
|
||||
# The .psd1 declares the cmdlet; implementation may be pending.
|
||||
$manifestPath = Join-Path $moduleRoot 'PSProxmoxVE.psd1'
|
||||
if (Test-Path $manifestPath) {
|
||||
$manifest = Import-PowerShellDataFile $manifestPath
|
||||
$manifest.CmdletsToExport | Should -Contain 'Get-PveContainer'
|
||||
}
|
||||
else {
|
||||
Set-ItResult -Skipped -Because 'Module manifest not found at expected path'
|
||||
}
|
||||
}
|
||||
|
||||
It 'Should be available after module import (or skip if not yet compiled)' {
|
||||
if (-not $script:CmdExists) {
|
||||
Set-ItResult -Skipped -Because 'Get-PveContainer is not yet implemented in this build'
|
||||
return
|
||||
}
|
||||
(Get-Command 'Get-PveContainer').CommandType | Should -Be 'Cmdlet'
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Parameter metadata' {
|
||||
BeforeAll {
|
||||
$script:Cmd = Get-Command 'Get-PveContainer' -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
It 'Should have Node parameter' {
|
||||
if (-not $script:CmdExists) { Set-ItResult -Skipped -Because 'Not yet compiled'; return }
|
||||
$script:Cmd.Parameters.ContainsKey('Node') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Node should not be Mandatory (all-nodes query when omitted)' {
|
||||
if (-not $script:CmdExists) { Set-ItResult -Skipped -Because 'Not yet compiled'; return }
|
||||
$isMandatory = $script:Cmd.Parameters['Node'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should have VmId parameter' {
|
||||
if (-not $script:CmdExists) { Set-ItResult -Skipped -Because 'Not yet compiled'; return }
|
||||
$script:Cmd.Parameters.ContainsKey('VmId') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Name parameter' {
|
||||
if (-not $script:CmdExists) { Set-ItResult -Skipped -Because 'Not yet compiled'; return }
|
||||
$script:Cmd.Parameters.ContainsKey('Name') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Status parameter' {
|
||||
if (-not $script:CmdExists) { Set-ItResult -Skipped -Because 'Not yet compiled'; return }
|
||||
$script:Cmd.Parameters.ContainsKey('Status') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Session parameter (inherited from PveCmdletBase)' {
|
||||
if (-not $script:CmdExists) { Set-ItResult -Skipped -Because 'Not yet compiled'; return }
|
||||
$script:Cmd.Parameters.ContainsKey('Session') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Node should accept pipeline input by property name' {
|
||||
if (-not $script:CmdExists) { Set-ItResult -Skipped -Because 'Not yet compiled'; return }
|
||||
$node = $script:Cmd.Parameters['Node']
|
||||
$acceptsByPropName = $node.ParameterSets.Values |
|
||||
Where-Object { $_.ValueFromPipelineByPropertyName }
|
||||
$acceptsByPropName | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active' {
|
||||
if (-not $script:CmdExists) { Set-ItResult -Skipped -Because 'Not yet compiled'; return }
|
||||
{ Get-PveContainer -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,268 @@
|
||||
#Requires -Module Pester
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Pester 5 tests for network cmdlets:
|
||||
Get-PveNetwork, New-PveNetwork, Set-PveNetwork,
|
||||
Remove-PveNetwork, Invoke-PveNetworkApply.
|
||||
|
||||
All tests are fully offline — no live Proxmox VE target is required.
|
||||
If a cmdlet is not yet compiled the test is marked Skipped.
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
|
||||
$script:Availability = @{}
|
||||
foreach ($name in @('Get-PveNetwork', 'New-PveNetwork', 'Set-PveNetwork',
|
||||
'Remove-PveNetwork', 'Invoke-PveNetworkApply')) {
|
||||
$script:Availability[$name] = $null -ne (Get-Command $name -ErrorAction SilentlyContinue)
|
||||
}
|
||||
|
||||
function Skip-IfMissing([string]$Name) {
|
||||
if (-not $script:Availability[$Name]) {
|
||||
Set-ItResult -Skipped -Because "$Name is not yet implemented in this build"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Manifest contract
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Network cmdlets — manifest declarations' {
|
||||
BeforeAll {
|
||||
$manifestPath = Join-Path $moduleRoot 'PSProxmoxVE.psd1'
|
||||
$script:Manifest = if (Test-Path $manifestPath) { Import-PowerShellDataFile $manifestPath } else { $null }
|
||||
}
|
||||
|
||||
foreach ($cmdName in @('Get-PveNetwork', 'New-PveNetwork', 'Set-PveNetwork',
|
||||
'Remove-PveNetwork', 'Invoke-PveNetworkApply')) {
|
||||
It "$cmdName should be declared in CmdletsToExport" {
|
||||
if ($null -eq $script:Manifest) { Set-ItResult -Skipped -Because 'Manifest not found'; return }
|
||||
$script:Manifest.CmdletsToExport | Should -Contain $cmdName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Get-PveNetwork
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Get-PveNetwork' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'Get-PveNetwork' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'Get-PveNetwork'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should be a CmdletInfo (binary cmdlet)' {
|
||||
Skip-IfMissing 'Get-PveNetwork'
|
||||
$script:Cmd.CommandType | Should -Be 'Cmdlet'
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Parameter metadata' {
|
||||
It 'Should have Node parameter (Mandatory — network is always node-specific)' {
|
||||
Skip-IfMissing 'Get-PveNetwork'
|
||||
$script:Cmd.Parameters.ContainsKey('Node') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Iface parameter (optional filter)' {
|
||||
Skip-IfMissing 'Get-PveNetwork'
|
||||
$script:Cmd.Parameters.ContainsKey('Iface') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Type parameter (optional filter by interface type)' {
|
||||
Skip-IfMissing 'Get-PveNetwork'
|
||||
$script:Cmd.Parameters.ContainsKey('Type') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Session parameter' {
|
||||
Skip-IfMissing 'Get-PveNetwork'
|
||||
$script:Cmd.Parameters.ContainsKey('Session') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active' {
|
||||
Skip-IfMissing 'Get-PveNetwork'
|
||||
{ Get-PveNetwork -Node 'pve-node1' -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# New-PveNetwork
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'New-PveNetwork' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'New-PveNetwork' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'New-PveNetwork'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'ShouldProcess support' {
|
||||
It 'Should support WhatIf' {
|
||||
Skip-IfMissing 'New-PveNetwork'
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Required parameters' {
|
||||
It 'Node should be Mandatory' {
|
||||
Skip-IfMissing 'New-PveNetwork'
|
||||
$isMandatory = $script:Cmd.Parameters['Node'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Iface should be Mandatory' {
|
||||
Skip-IfMissing 'New-PveNetwork'
|
||||
$isMandatory = $script:Cmd.Parameters['Iface'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Type should be Mandatory' {
|
||||
Skip-IfMissing 'New-PveNetwork'
|
||||
$isMandatory = $script:Cmd.Parameters['Type'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Set-PveNetwork
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Set-PveNetwork' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'Set-PveNetwork' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'Set-PveNetwork'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'ShouldProcess support' {
|
||||
It 'Should support WhatIf' {
|
||||
Skip-IfMissing 'Set-PveNetwork'
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Required parameters' {
|
||||
It 'Node should be Mandatory' {
|
||||
Skip-IfMissing 'Set-PveNetwork'
|
||||
$isMandatory = $script:Cmd.Parameters['Node'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Iface should be Mandatory' {
|
||||
Skip-IfMissing 'Set-PveNetwork'
|
||||
$isMandatory = $script:Cmd.Parameters['Iface'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Remove-PveNetwork
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Remove-PveNetwork' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'Remove-PveNetwork' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'Remove-PveNetwork'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'ShouldProcess / ConfirmImpact' {
|
||||
It 'Should support WhatIf' {
|
||||
Skip-IfMissing 'Remove-PveNetwork'
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should declare ConfirmImpact High' {
|
||||
Skip-IfMissing 'Remove-PveNetwork'
|
||||
$attr = $script:Cmd.ImplementingType.GetCustomAttributes(
|
||||
[System.Management.Automation.CmdletAttribute], $false) |
|
||||
Select-Object -First 1
|
||||
$attr.ConfirmImpact | Should -Be ([System.Management.Automation.ConfirmImpact]::High)
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Required parameters' {
|
||||
It 'Node should be Mandatory' {
|
||||
Skip-IfMissing 'Remove-PveNetwork'
|
||||
$isMandatory = $script:Cmd.Parameters['Node'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Iface should be Mandatory' {
|
||||
Skip-IfMissing 'Remove-PveNetwork'
|
||||
$isMandatory = $script:Cmd.Parameters['Iface'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Invoke-PveNetworkApply
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Invoke-PveNetworkApply' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'Invoke-PveNetworkApply' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'Invoke-PveNetworkApply'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'ShouldProcess support' {
|
||||
It 'Should support WhatIf' {
|
||||
Skip-IfMissing 'Invoke-PveNetworkApply'
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Required parameters' {
|
||||
It 'Node should be Mandatory' {
|
||||
Skip-IfMissing 'Invoke-PveNetworkApply'
|
||||
$isMandatory = $script:Cmd.Parameters['Node'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,315 @@
|
||||
#Requires -Module Pester
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Pester 5 tests for SDN cmdlets:
|
||||
Get-PveSdnZone, New-PveSdnZone, Remove-PveSdnZone,
|
||||
Get-PveSdnVnet, New-PveSdnVnet, Remove-PveSdnVnet.
|
||||
|
||||
All tests are fully offline — no live Proxmox VE target is required.
|
||||
|
||||
SDN support was introduced in Proxmox VE 7 and became stable in PVE 8.
|
||||
These cmdlets should include a version guard that raises PveVersionException
|
||||
(or similar) when the server version is below the minimum requirement.
|
||||
The version guard tests use fully-mocked sessions (no network calls).
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
|
||||
$script:SdnCmdlets = @(
|
||||
'Get-PveSdnZone', 'New-PveSdnZone', 'Remove-PveSdnZone',
|
||||
'Get-PveSdnVnet', 'New-PveSdnVnet', 'Remove-PveSdnVnet'
|
||||
)
|
||||
|
||||
$script:Availability = @{}
|
||||
foreach ($name in $script:SdnCmdlets) {
|
||||
$script:Availability[$name] = $null -ne (Get-Command $name -ErrorAction SilentlyContinue)
|
||||
}
|
||||
|
||||
function Skip-IfMissing([string]$Name) {
|
||||
if (-not $script:Availability[$Name]) {
|
||||
Set-ItResult -Skipped -Because "$Name is not yet implemented in this build"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Manifest contract
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'SDN cmdlets — manifest declarations' {
|
||||
BeforeAll {
|
||||
$manifestPath = Join-Path $moduleRoot 'PSProxmoxVE.psd1'
|
||||
$script:Manifest = if (Test-Path $manifestPath) { Import-PowerShellDataFile $manifestPath } else { $null }
|
||||
}
|
||||
|
||||
foreach ($cmdName in @('Get-PveSdnZone', 'New-PveSdnZone', 'Remove-PveSdnZone',
|
||||
'Get-PveSdnVnet', 'New-PveSdnVnet', 'Remove-PveSdnVnet')) {
|
||||
It "$cmdName should be declared in CmdletsToExport" {
|
||||
if ($null -eq $script:Manifest) { Set-ItResult -Skipped -Because 'Manifest not found'; return }
|
||||
$script:Manifest.CmdletsToExport | Should -Contain $cmdName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Get-PveSdnZone
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Get-PveSdnZone' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'Get-PveSdnZone' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'Get-PveSdnZone'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should be a CmdletInfo (binary cmdlet)' {
|
||||
Skip-IfMissing 'Get-PveSdnZone'
|
||||
$script:Cmd.CommandType | Should -Be 'Cmdlet'
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Parameter metadata' {
|
||||
It 'Should have Zone parameter (optional filter by zone ID)' {
|
||||
Skip-IfMissing 'Get-PveSdnZone'
|
||||
$script:Cmd.Parameters.ContainsKey('Zone') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Session parameter' {
|
||||
Skip-IfMissing 'Get-PveSdnZone'
|
||||
$script:Cmd.Parameters.ContainsKey('Session') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Version guard behaviour — without active session' {
|
||||
It 'Should throw when no session is active' {
|
||||
Skip-IfMissing 'Get-PveSdnZone'
|
||||
{ Get-PveSdnZone -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# New-PveSdnZone
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'New-PveSdnZone' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'New-PveSdnZone' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'New-PveSdnZone'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'ShouldProcess support' {
|
||||
It 'Should support WhatIf' {
|
||||
Skip-IfMissing 'New-PveSdnZone'
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Required parameters' {
|
||||
It 'Zone should be Mandatory' {
|
||||
Skip-IfMissing 'New-PveSdnZone'
|
||||
$isMandatory = $script:Cmd.Parameters['Zone'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Type should be Mandatory' {
|
||||
Skip-IfMissing 'New-PveSdnZone'
|
||||
$isMandatory = $script:Cmd.Parameters['Type'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Type ValidateSet' {
|
||||
It 'Type parameter should have ValidateSet including known zone types' {
|
||||
Skip-IfMissing 'New-PveSdnZone'
|
||||
$validateSetAttr = $script:Cmd.Parameters['Type'].Attributes |
|
||||
Where-Object { $_ -is [System.Management.Automation.ValidateSetAttribute] } |
|
||||
Select-Object -First 1
|
||||
if ($null -ne $validateSetAttr) {
|
||||
$validateSetAttr.ValidValues | Should -Contain 'simple'
|
||||
}
|
||||
else {
|
||||
Set-ItResult -Skipped -Because 'Type does not use a ValidateSet attribute in this build'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Remove-PveSdnZone
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Remove-PveSdnZone' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'Remove-PveSdnZone' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'Remove-PveSdnZone'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'ShouldProcess / ConfirmImpact' {
|
||||
It 'Should support WhatIf' {
|
||||
Skip-IfMissing 'Remove-PveSdnZone'
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should declare ConfirmImpact High' {
|
||||
Skip-IfMissing 'Remove-PveSdnZone'
|
||||
$attr = $script:Cmd.ImplementingType.GetCustomAttributes(
|
||||
[System.Management.Automation.CmdletAttribute], $false) |
|
||||
Select-Object -First 1
|
||||
$attr.ConfirmImpact | Should -Be ([System.Management.Automation.ConfirmImpact]::High)
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Required parameters' {
|
||||
It 'Zone should be Mandatory' {
|
||||
Skip-IfMissing 'Remove-PveSdnZone'
|
||||
$isMandatory = $script:Cmd.Parameters['Zone'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Get-PveSdnVnet
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Get-PveSdnVnet' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'Get-PveSdnVnet' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'Get-PveSdnVnet'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Parameter metadata' {
|
||||
It 'Should have Vnet parameter (optional filter by VNet name)' {
|
||||
Skip-IfMissing 'Get-PveSdnVnet'
|
||||
$script:Cmd.Parameters.ContainsKey('Vnet') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Zone parameter (optional filter by parent zone)' {
|
||||
Skip-IfMissing 'Get-PveSdnVnet'
|
||||
$script:Cmd.Parameters.ContainsKey('Zone') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Session parameter' {
|
||||
Skip-IfMissing 'Get-PveSdnVnet'
|
||||
$script:Cmd.Parameters.ContainsKey('Session') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active' {
|
||||
Skip-IfMissing 'Get-PveSdnVnet'
|
||||
{ Get-PveSdnVnet -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# New-PveSdnVnet
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'New-PveSdnVnet' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'New-PveSdnVnet' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'New-PveSdnVnet'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'ShouldProcess support' {
|
||||
It 'Should support WhatIf' {
|
||||
Skip-IfMissing 'New-PveSdnVnet'
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Required parameters' {
|
||||
It 'Vnet should be Mandatory' {
|
||||
Skip-IfMissing 'New-PveSdnVnet'
|
||||
$isMandatory = $script:Cmd.Parameters['Vnet'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Zone should be Mandatory' {
|
||||
Skip-IfMissing 'New-PveSdnVnet'
|
||||
$isMandatory = $script:Cmd.Parameters['Zone'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Remove-PveSdnVnet
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Remove-PveSdnVnet' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'Remove-PveSdnVnet' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'Remove-PveSdnVnet'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'ShouldProcess / ConfirmImpact' {
|
||||
It 'Should support WhatIf' {
|
||||
Skip-IfMissing 'Remove-PveSdnVnet'
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should declare ConfirmImpact High' {
|
||||
Skip-IfMissing 'Remove-PveSdnVnet'
|
||||
$attr = $script:Cmd.ImplementingType.GetCustomAttributes(
|
||||
[System.Management.Automation.CmdletAttribute], $false) |
|
||||
Select-Object -First 1
|
||||
$attr.ConfirmImpact | Should -Be ([System.Management.Automation.ConfirmImpact]::High)
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Required parameters' {
|
||||
It 'Vnet should be Mandatory' {
|
||||
Skip-IfMissing 'Remove-PveSdnVnet'
|
||||
$isMandatory = $script:Cmd.Parameters['Vnet'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,313 @@
|
||||
#Requires -Module Pester
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Pester 5 tests for snapshot cmdlets:
|
||||
Get-PveSnapshot, New-PveSnapshot, Remove-PveSnapshot, Restore-PveSnapshot.
|
||||
|
||||
All tests are fully offline — no live Proxmox VE target is required.
|
||||
If a cmdlet is not yet compiled the test is marked Skipped.
|
||||
|
||||
Snapshot cmdlets apply to both QEMU VMs and LXC containers; the
|
||||
parameter set distinction is captured in the 'Type' tests below.
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
|
||||
$script:Availability = @{}
|
||||
foreach ($name in @('Get-PveSnapshot', 'New-PveSnapshot',
|
||||
'Remove-PveSnapshot', 'Restore-PveSnapshot')) {
|
||||
$script:Availability[$name] = $null -ne (Get-Command $name -ErrorAction SilentlyContinue)
|
||||
}
|
||||
|
||||
function Skip-IfMissing([string]$Name) {
|
||||
if (-not $script:Availability[$Name]) {
|
||||
Set-ItResult -Skipped -Because "$Name is not yet implemented in this build"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Manifest contract
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Snapshot cmdlets — manifest declarations' {
|
||||
BeforeAll {
|
||||
$manifestPath = Join-Path $moduleRoot 'PSProxmoxVE.psd1'
|
||||
$script:Manifest = if (Test-Path $manifestPath) { Import-PowerShellDataFile $manifestPath } else { $null }
|
||||
}
|
||||
|
||||
foreach ($cmdName in @('Get-PveSnapshot', 'New-PveSnapshot',
|
||||
'Remove-PveSnapshot', 'Restore-PveSnapshot')) {
|
||||
It "$cmdName should be declared in CmdletsToExport" {
|
||||
if ($null -eq $script:Manifest) { Set-ItResult -Skipped -Because 'Manifest not found'; return }
|
||||
$script:Manifest.CmdletsToExport | Should -Contain $cmdName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Get-PveSnapshot
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Get-PveSnapshot' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'Get-PveSnapshot' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'Get-PveSnapshot'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should be a CmdletInfo (binary cmdlet)' {
|
||||
Skip-IfMissing 'Get-PveSnapshot'
|
||||
$script:Cmd.CommandType | Should -Be 'Cmdlet'
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Parameter metadata' {
|
||||
It 'Node should be Mandatory' {
|
||||
Skip-IfMissing 'Get-PveSnapshot'
|
||||
$isMandatory = $script:Cmd.Parameters['Node'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'VmId should be Mandatory' {
|
||||
Skip-IfMissing 'Get-PveSnapshot'
|
||||
$isMandatory = $script:Cmd.Parameters['VmId'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should have Name parameter (optional filter by snapshot name)' {
|
||||
Skip-IfMissing 'Get-PveSnapshot'
|
||||
$script:Cmd.Parameters.ContainsKey('Name') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Session parameter' {
|
||||
Skip-IfMissing 'Get-PveSnapshot'
|
||||
$script:Cmd.Parameters.ContainsKey('Session') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active' {
|
||||
Skip-IfMissing 'Get-PveSnapshot'
|
||||
{ Get-PveSnapshot -Node 'pve-node1' -VmId 100 -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# New-PveSnapshot
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'New-PveSnapshot' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'New-PveSnapshot' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'New-PveSnapshot'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'ShouldProcess support' {
|
||||
It 'Should support WhatIf' {
|
||||
Skip-IfMissing 'New-PveSnapshot'
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Required parameters' {
|
||||
It 'Node should be Mandatory' {
|
||||
Skip-IfMissing 'New-PveSnapshot'
|
||||
$isMandatory = $script:Cmd.Parameters['Node'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'VmId should be Mandatory' {
|
||||
Skip-IfMissing 'New-PveSnapshot'
|
||||
$isMandatory = $script:Cmd.Parameters['VmId'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Name (snapshot name) should be Mandatory' {
|
||||
Skip-IfMissing 'New-PveSnapshot'
|
||||
$isMandatory = $script:Cmd.Parameters['Name'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Optional parameters' {
|
||||
It 'Should have Description parameter' {
|
||||
Skip-IfMissing 'New-PveSnapshot'
|
||||
$script:Cmd.Parameters.ContainsKey('Description') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have IncludeVmState switch parameter' {
|
||||
Skip-IfMissing 'New-PveSnapshot'
|
||||
$script:Cmd.Parameters.ContainsKey('IncludeVmState') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Wait switch parameter' {
|
||||
Skip-IfMissing 'New-PveSnapshot'
|
||||
$script:Cmd.Parameters.ContainsKey('Wait') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active (without -WhatIf)' {
|
||||
Skip-IfMissing 'New-PveSnapshot'
|
||||
{ New-PveSnapshot -Node 'pve-node1' -VmId 100 -Name 'snap1' -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Remove-PveSnapshot
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Remove-PveSnapshot' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'Remove-PveSnapshot' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'Remove-PveSnapshot'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'ShouldProcess / ConfirmImpact' {
|
||||
It 'Should support WhatIf' {
|
||||
Skip-IfMissing 'Remove-PveSnapshot'
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should declare ConfirmImpact High' {
|
||||
Skip-IfMissing 'Remove-PveSnapshot'
|
||||
$attr = $script:Cmd.ImplementingType.GetCustomAttributes(
|
||||
[System.Management.Automation.CmdletAttribute], $false) |
|
||||
Select-Object -First 1
|
||||
$attr.ConfirmImpact | Should -Be ([System.Management.Automation.ConfirmImpact]::High)
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Required parameters' {
|
||||
It 'Node should be Mandatory' {
|
||||
Skip-IfMissing 'Remove-PveSnapshot'
|
||||
$isMandatory = $script:Cmd.Parameters['Node'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'VmId should be Mandatory' {
|
||||
Skip-IfMissing 'Remove-PveSnapshot'
|
||||
$isMandatory = $script:Cmd.Parameters['VmId'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Name should be Mandatory' {
|
||||
Skip-IfMissing 'Remove-PveSnapshot'
|
||||
$isMandatory = $script:Cmd.Parameters['Name'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active (without -WhatIf)' {
|
||||
Skip-IfMissing 'Remove-PveSnapshot'
|
||||
{ Remove-PveSnapshot -Node 'pve-node1' -VmId 100 -Name 'snap1' -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Restore-PveSnapshot
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Restore-PveSnapshot' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'Restore-PveSnapshot' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'Restore-PveSnapshot'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'ShouldProcess / ConfirmImpact' {
|
||||
It 'Should support WhatIf' {
|
||||
Skip-IfMissing 'Restore-PveSnapshot'
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should declare ConfirmImpact High' {
|
||||
Skip-IfMissing 'Restore-PveSnapshot'
|
||||
$attr = $script:Cmd.ImplementingType.GetCustomAttributes(
|
||||
[System.Management.Automation.CmdletAttribute], $false) |
|
||||
Select-Object -First 1
|
||||
$attr.ConfirmImpact | Should -Be ([System.Management.Automation.ConfirmImpact]::High)
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Required parameters' {
|
||||
It 'Node should be Mandatory' {
|
||||
Skip-IfMissing 'Restore-PveSnapshot'
|
||||
$isMandatory = $script:Cmd.Parameters['Node'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'VmId should be Mandatory' {
|
||||
Skip-IfMissing 'Restore-PveSnapshot'
|
||||
$isMandatory = $script:Cmd.Parameters['VmId'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Name should be Mandatory' {
|
||||
Skip-IfMissing 'Restore-PveSnapshot'
|
||||
$isMandatory = $script:Cmd.Parameters['Name'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Optional parameters' {
|
||||
It 'Should have Wait switch parameter' {
|
||||
Skip-IfMissing 'Restore-PveSnapshot'
|
||||
$script:Cmd.Parameters.ContainsKey('Wait') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active (without -WhatIf)' {
|
||||
Skip-IfMissing 'Restore-PveSnapshot'
|
||||
{ Restore-PveSnapshot -Node 'pve-node1' -VmId 100 -Name 'snap1' -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
#Requires -Module Pester
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Pester 5 tests for storage cmdlets:
|
||||
Get-PveStorage, Get-PveStorageContent, New-PveStorage, Remove-PveStorage.
|
||||
|
||||
All tests are fully offline — no live Proxmox VE target is required.
|
||||
If a cmdlet is not yet compiled the test is marked Skipped.
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
|
||||
$script:Availability = @{}
|
||||
foreach ($name in @('Get-PveStorage', 'Get-PveStorageContent',
|
||||
'New-PveStorage', 'Remove-PveStorage')) {
|
||||
$script:Availability[$name] = $null -ne (Get-Command $name -ErrorAction SilentlyContinue)
|
||||
}
|
||||
|
||||
function Skip-IfMissing([string]$Name) {
|
||||
if (-not $script:Availability[$Name]) {
|
||||
Set-ItResult -Skipped -Because "$Name is not yet implemented in this build"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Manifest contract
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Storage cmdlets — manifest declarations' {
|
||||
It 'Get-PveStorage should be declared in CmdletsToExport' {
|
||||
$manifestPath = Join-Path $moduleRoot 'PSProxmoxVE.psd1'
|
||||
if (-not (Test-Path $manifestPath)) { Set-ItResult -Skipped -Because 'Manifest not found'; return }
|
||||
$manifest = Import-PowerShellDataFile $manifestPath
|
||||
$manifest.CmdletsToExport | Should -Contain 'Get-PveStorage'
|
||||
}
|
||||
|
||||
It 'Get-PveStorageContent should be declared in CmdletsToExport' {
|
||||
$manifestPath = Join-Path $moduleRoot 'PSProxmoxVE.psd1'
|
||||
if (-not (Test-Path $manifestPath)) { Set-ItResult -Skipped -Because 'Manifest not found'; return }
|
||||
$manifest = Import-PowerShellDataFile $manifestPath
|
||||
$manifest.CmdletsToExport | Should -Contain 'Get-PveStorageContent'
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Get-PveStorage
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Get-PveStorage' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'Get-PveStorage' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'Get-PveStorage'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should be a CmdletInfo (binary cmdlet)' {
|
||||
Skip-IfMissing 'Get-PveStorage'
|
||||
$script:Cmd.CommandType | Should -Be 'Cmdlet'
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Parameter metadata' {
|
||||
It 'Should have Node parameter' {
|
||||
Skip-IfMissing 'Get-PveStorage'
|
||||
$script:Cmd.Parameters.ContainsKey('Node') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Node should not be Mandatory (cluster-wide query when omitted)' {
|
||||
Skip-IfMissing 'Get-PveStorage'
|
||||
$isMandatory = $script:Cmd.Parameters['Node'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should have Storage parameter (filter by name)' {
|
||||
Skip-IfMissing 'Get-PveStorage'
|
||||
$script:Cmd.Parameters.ContainsKey('Storage') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Session parameter' {
|
||||
Skip-IfMissing 'Get-PveStorage'
|
||||
$script:Cmd.Parameters.ContainsKey('Session') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active' {
|
||||
Skip-IfMissing 'Get-PveStorage'
|
||||
{ Get-PveStorage -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Get-PveStorageContent
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Get-PveStorageContent' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'Get-PveStorageContent' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'Get-PveStorageContent'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Parameter metadata' {
|
||||
It 'Node should be present' {
|
||||
Skip-IfMissing 'Get-PveStorageContent'
|
||||
$script:Cmd.Parameters.ContainsKey('Node') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Storage should be present' {
|
||||
Skip-IfMissing 'Get-PveStorageContent'
|
||||
$script:Cmd.Parameters.ContainsKey('Storage') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Session parameter' {
|
||||
Skip-IfMissing 'Get-PveStorageContent'
|
||||
$script:Cmd.Parameters.ContainsKey('Session') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active' {
|
||||
Skip-IfMissing 'Get-PveStorageContent'
|
||||
{ Get-PveStorageContent -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# New-PveStorage
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'New-PveStorage' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'New-PveStorage' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'New-PveStorage'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'ShouldProcess support' {
|
||||
It 'Should support WhatIf' {
|
||||
Skip-IfMissing 'New-PveStorage'
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Required parameters' {
|
||||
It 'Storage (name) should be Mandatory' {
|
||||
Skip-IfMissing 'New-PveStorage'
|
||||
$isMandatory = $script:Cmd.Parameters['Storage'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Type should be Mandatory' {
|
||||
Skip-IfMissing 'New-PveStorage'
|
||||
$isMandatory = $script:Cmd.Parameters['Type'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Remove-PveStorage
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Remove-PveStorage' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'Remove-PveStorage' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'Remove-PveStorage'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'ShouldProcess / ConfirmImpact' {
|
||||
It 'Should support WhatIf' {
|
||||
Skip-IfMissing 'Remove-PveStorage'
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should declare ConfirmImpact High' {
|
||||
Skip-IfMissing 'Remove-PveStorage'
|
||||
$attr = $script:Cmd.ImplementingType.GetCustomAttributes(
|
||||
[System.Management.Automation.CmdletAttribute], $false) |
|
||||
Select-Object -First 1
|
||||
$attr.ConfirmImpact | Should -Be ([System.Management.Automation.ConfirmImpact]::High)
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Required parameters' {
|
||||
It 'Storage should be Mandatory' {
|
||||
Skip-IfMissing 'Remove-PveStorage'
|
||||
$isMandatory = $script:Cmd.Parameters['Storage'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
#Requires -Module Pester
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Pester 5 tests for Send-PveIso.
|
||||
All tests are fully offline — no live Proxmox VE target is required.
|
||||
If the cmdlet is not yet compiled the tests are marked Skipped.
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
|
||||
$script:CmdExists = $null -ne (Get-Command 'Send-PveIso' -ErrorAction SilentlyContinue)
|
||||
}
|
||||
|
||||
Describe 'Send-PveIso' {
|
||||
|
||||
Context 'Manifest declaration' {
|
||||
It 'Should be declared in CmdletsToExport' {
|
||||
$manifestPath = Join-Path $moduleRoot 'PSProxmoxVE.psd1'
|
||||
if (-not (Test-Path $manifestPath)) { Set-ItResult -Skipped -Because 'Manifest not found'; return }
|
||||
$manifest = Import-PowerShellDataFile $manifestPath
|
||||
$manifest.CmdletsToExport | Should -Contain 'Send-PveIso'
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
if (-not $script:CmdExists) { Set-ItResult -Skipped -Because 'Not yet compiled'; return }
|
||||
(Get-Command 'Send-PveIso').CommandType | Should -Be 'Cmdlet'
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Required parameters' {
|
||||
BeforeAll {
|
||||
$script:Cmd = Get-Command 'Send-PveIso' -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
It 'Should have Node parameter (Mandatory)' {
|
||||
if (-not $script:CmdExists) { Set-ItResult -Skipped -Because 'Not yet compiled'; return }
|
||||
$isMandatory = $script:Cmd.Parameters['Node'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should have Storage parameter (Mandatory)' {
|
||||
if (-not $script:CmdExists) { Set-ItResult -Skipped -Because 'Not yet compiled'; return }
|
||||
$isMandatory = $script:Cmd.Parameters['Storage'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should have Path parameter (Mandatory)' {
|
||||
if (-not $script:CmdExists) { Set-ItResult -Skipped -Because 'Not yet compiled'; return }
|
||||
$isMandatory = $script:Cmd.Parameters['Path'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should throw when Node is omitted' {
|
||||
if (-not $script:CmdExists) { Set-ItResult -Skipped -Because 'Not yet compiled'; return }
|
||||
{ Send-PveIso -Storage 'local' -Path '/tmp/test.iso' -ErrorAction Stop } |
|
||||
Should -Throw
|
||||
}
|
||||
|
||||
It 'Should throw when Storage is omitted' {
|
||||
if (-not $script:CmdExists) { Set-ItResult -Skipped -Because 'Not yet compiled'; return }
|
||||
{ Send-PveIso -Node 'pve-node1' -Path '/tmp/test.iso' -ErrorAction Stop } |
|
||||
Should -Throw
|
||||
}
|
||||
|
||||
It 'Should throw when Path is omitted' {
|
||||
if (-not $script:CmdExists) { Set-ItResult -Skipped -Because 'Not yet compiled'; return }
|
||||
{ Send-PveIso -Node 'pve-node1' -Storage 'local' -ErrorAction Stop } |
|
||||
Should -Throw
|
||||
}
|
||||
}
|
||||
|
||||
Context 'ChecksumAlgorithm ValidateSet' {
|
||||
BeforeAll {
|
||||
$script:Cmd = Get-Command 'Send-PveIso' -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
It 'Should have ChecksumAlgorithm parameter' {
|
||||
if (-not $script:CmdExists) { Set-ItResult -Skipped -Because 'Not yet compiled'; return }
|
||||
$script:Cmd.Parameters.ContainsKey('ChecksumAlgorithm') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'ChecksumAlgorithm should have a ValidateSet attribute' {
|
||||
if (-not $script:CmdExists) { Set-ItResult -Skipped -Because 'Not yet compiled'; return }
|
||||
$validateSetAttr = $script:Cmd.Parameters['ChecksumAlgorithm'].Attributes |
|
||||
Where-Object { $_ -is [System.Management.Automation.ValidateSetAttribute] }
|
||||
$validateSetAttr | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'ChecksumAlgorithm ValidateSet should include md5' {
|
||||
if (-not $script:CmdExists) { Set-ItResult -Skipped -Because 'Not yet compiled'; return }
|
||||
$validateSetAttr = $script:Cmd.Parameters['ChecksumAlgorithm'].Attributes |
|
||||
Where-Object { $_ -is [System.Management.Automation.ValidateSetAttribute] } |
|
||||
Select-Object -First 1
|
||||
$validateSetAttr.ValidValues | Should -Contain 'md5'
|
||||
}
|
||||
|
||||
It 'ChecksumAlgorithm ValidateSet should include sha1' {
|
||||
if (-not $script:CmdExists) { Set-ItResult -Skipped -Because 'Not yet compiled'; return }
|
||||
$validateSetAttr = $script:Cmd.Parameters['ChecksumAlgorithm'].Attributes |
|
||||
Where-Object { $_ -is [System.Management.Automation.ValidateSetAttribute] } |
|
||||
Select-Object -First 1
|
||||
$validateSetAttr.ValidValues | Should -Contain 'sha1'
|
||||
}
|
||||
|
||||
It 'ChecksumAlgorithm ValidateSet should include sha256' {
|
||||
if (-not $script:CmdExists) { Set-ItResult -Skipped -Because 'Not yet compiled'; return }
|
||||
$validateSetAttr = $script:Cmd.Parameters['ChecksumAlgorithm'].Attributes |
|
||||
Where-Object { $_ -is [System.Management.Automation.ValidateSetAttribute] } |
|
||||
Select-Object -First 1
|
||||
$validateSetAttr.ValidValues | Should -Contain 'sha256'
|
||||
}
|
||||
|
||||
It 'ChecksumAlgorithm ValidateSet should include sha512' {
|
||||
if (-not $script:CmdExists) { Set-ItResult -Skipped -Because 'Not yet compiled'; return }
|
||||
$validateSetAttr = $script:Cmd.Parameters['ChecksumAlgorithm'].Attributes |
|
||||
Where-Object { $_ -is [System.Management.Automation.ValidateSetAttribute] } |
|
||||
Select-Object -First 1
|
||||
$validateSetAttr.ValidValues | Should -Contain 'sha512'
|
||||
}
|
||||
}
|
||||
|
||||
Context 'ShouldProcess support' {
|
||||
BeforeAll {
|
||||
$script:Cmd = Get-Command 'Send-PveIso' -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
It 'Should support WhatIf' {
|
||||
if (-not $script:CmdExists) { Set-ItResult -Skipped -Because 'Not yet compiled'; return }
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Optional parameters' {
|
||||
BeforeAll {
|
||||
$script:Cmd = Get-Command 'Send-PveIso' -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
It 'Should have Checksum parameter' {
|
||||
if (-not $script:CmdExists) { Set-ItResult -Skipped -Because 'Not yet compiled'; return }
|
||||
$script:Cmd.Parameters.ContainsKey('Checksum') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Session parameter' {
|
||||
if (-not $script:CmdExists) { Set-ItResult -Skipped -Because 'Not yet compiled'; return }
|
||||
$script:Cmd.Parameters.ContainsKey('Session') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active (without -WhatIf)' {
|
||||
if (-not $script:CmdExists) { Set-ItResult -Skipped -Because 'Not yet compiled'; return }
|
||||
{ Send-PveIso -Node 'pve-node1' -Storage 'local' -Path '/tmp/test.iso' -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,281 @@
|
||||
#Requires -Module Pester
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Pester 5 tests for template cmdlets:
|
||||
Get-PveTemplate, New-PveTemplate, Remove-PveTemplate, New-PveVmFromTemplate.
|
||||
|
||||
All tests are fully offline — no live Proxmox VE target is required.
|
||||
If a cmdlet is not yet compiled the test is marked Skipped.
|
||||
|
||||
Note: New-PveTemplate converts an existing VM into a template (destructive —
|
||||
the original VM becomes read-only). New-PveVmFromTemplate deploys a new VM
|
||||
from an existing template (which is a clone operation under the hood).
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
|
||||
$script:Availability = @{}
|
||||
foreach ($name in @('Get-PveTemplate', 'New-PveTemplate',
|
||||
'Remove-PveTemplate', 'New-PveVmFromTemplate')) {
|
||||
$script:Availability[$name] = $null -ne (Get-Command $name -ErrorAction SilentlyContinue)
|
||||
}
|
||||
|
||||
function Skip-IfMissing([string]$Name) {
|
||||
if (-not $script:Availability[$Name]) {
|
||||
Set-ItResult -Skipped -Because "$Name is not yet implemented in this build"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Manifest contract
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Template cmdlets — manifest declarations' {
|
||||
BeforeAll {
|
||||
$manifestPath = Join-Path $moduleRoot 'PSProxmoxVE.psd1'
|
||||
$script:Manifest = if (Test-Path $manifestPath) { Import-PowerShellDataFile $manifestPath } else { $null }
|
||||
}
|
||||
|
||||
foreach ($cmdName in @('Get-PveTemplate', 'New-PveTemplate',
|
||||
'Remove-PveTemplate', 'New-PveVmFromTemplate')) {
|
||||
It "$cmdName should be declared in CmdletsToExport" {
|
||||
if ($null -eq $script:Manifest) { Set-ItResult -Skipped -Because 'Manifest not found'; return }
|
||||
$script:Manifest.CmdletsToExport | Should -Contain $cmdName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Get-PveTemplate
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Get-PveTemplate' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'Get-PveTemplate' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'Get-PveTemplate'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should be a CmdletInfo (binary cmdlet)' {
|
||||
Skip-IfMissing 'Get-PveTemplate'
|
||||
$script:Cmd.CommandType | Should -Be 'Cmdlet'
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Parameter metadata' {
|
||||
It 'Should have Node parameter (optional — all nodes when omitted)' {
|
||||
Skip-IfMissing 'Get-PveTemplate'
|
||||
$script:Cmd.Parameters.ContainsKey('Node') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Node should not be Mandatory' {
|
||||
Skip-IfMissing 'Get-PveTemplate'
|
||||
$isMandatory = $script:Cmd.Parameters['Node'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should have Name parameter (optional filter by template name)' {
|
||||
Skip-IfMissing 'Get-PveTemplate'
|
||||
$script:Cmd.Parameters.ContainsKey('Name') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Session parameter' {
|
||||
Skip-IfMissing 'Get-PveTemplate'
|
||||
$script:Cmd.Parameters.ContainsKey('Session') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active' {
|
||||
Skip-IfMissing 'Get-PveTemplate'
|
||||
{ Get-PveTemplate -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# New-PveTemplate (converts an existing VM to a template)
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'New-PveTemplate' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'New-PveTemplate' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'New-PveTemplate'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'ShouldProcess / ConfirmImpact' {
|
||||
It 'Should support WhatIf' {
|
||||
Skip-IfMissing 'New-PveTemplate'
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should declare ConfirmImpact High (destructive — VM becomes read-only template)' {
|
||||
Skip-IfMissing 'New-PveTemplate'
|
||||
$attr = $script:Cmd.ImplementingType.GetCustomAttributes(
|
||||
[System.Management.Automation.CmdletAttribute], $false) |
|
||||
Select-Object -First 1
|
||||
$attr.ConfirmImpact | Should -Be ([System.Management.Automation.ConfirmImpact]::High)
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Required parameters' {
|
||||
It 'Node should be Mandatory' {
|
||||
Skip-IfMissing 'New-PveTemplate'
|
||||
$isMandatory = $script:Cmd.Parameters['Node'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'VmId should be Mandatory' {
|
||||
Skip-IfMissing 'New-PveTemplate'
|
||||
$isMandatory = $script:Cmd.Parameters['VmId'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active (without -WhatIf)' {
|
||||
Skip-IfMissing 'New-PveTemplate'
|
||||
{ New-PveTemplate -Node 'pve-node1' -VmId 9000 -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Remove-PveTemplate
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Remove-PveTemplate' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'Remove-PveTemplate' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'Remove-PveTemplate'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'ShouldProcess / ConfirmImpact' {
|
||||
It 'Should support WhatIf' {
|
||||
Skip-IfMissing 'Remove-PveTemplate'
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should declare ConfirmImpact High' {
|
||||
Skip-IfMissing 'Remove-PveTemplate'
|
||||
$attr = $script:Cmd.ImplementingType.GetCustomAttributes(
|
||||
[System.Management.Automation.CmdletAttribute], $false) |
|
||||
Select-Object -First 1
|
||||
$attr.ConfirmImpact | Should -Be ([System.Management.Automation.ConfirmImpact]::High)
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Required parameters' {
|
||||
It 'Node should be Mandatory' {
|
||||
Skip-IfMissing 'Remove-PveTemplate'
|
||||
$isMandatory = $script:Cmd.Parameters['Node'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'VmId should be Mandatory' {
|
||||
Skip-IfMissing 'Remove-PveTemplate'
|
||||
$isMandatory = $script:Cmd.Parameters['VmId'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# New-PveVmFromTemplate (deploy a new VM from a template)
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'New-PveVmFromTemplate' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'New-PveVmFromTemplate' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'New-PveVmFromTemplate'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'ShouldProcess support' {
|
||||
It 'Should support WhatIf' {
|
||||
Skip-IfMissing 'New-PveVmFromTemplate'
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Required parameters' {
|
||||
It 'TemplateNode should be Mandatory (node hosting the template)' {
|
||||
Skip-IfMissing 'New-PveVmFromTemplate'
|
||||
$hasTemplateNode = $script:Cmd.Parameters.ContainsKey('TemplateNode') -or
|
||||
$script:Cmd.Parameters.ContainsKey('SourceNode')
|
||||
$hasTemplateNode | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'TemplateId (or VmId) should be Mandatory' {
|
||||
Skip-IfMissing 'New-PveVmFromTemplate'
|
||||
$hasId = $script:Cmd.Parameters.ContainsKey('TemplateId') -or
|
||||
$script:Cmd.Parameters.ContainsKey('VmId')
|
||||
$hasId | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Optional parameters' {
|
||||
It 'Should have NewName parameter (name for the deployed VM)' {
|
||||
Skip-IfMissing 'New-PveVmFromTemplate'
|
||||
$hasNewName = $script:Cmd.Parameters.ContainsKey('NewName') -or
|
||||
$script:Cmd.Parameters.ContainsKey('Name')
|
||||
$hasNewName | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Wait switch parameter' {
|
||||
Skip-IfMissing 'New-PveVmFromTemplate'
|
||||
$script:Cmd.Parameters.ContainsKey('Wait') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active (without -WhatIf)' {
|
||||
Skip-IfMissing 'New-PveVmFromTemplate'
|
||||
# Use whatever the first mandatory parameter is named; -ErrorAction Stop
|
||||
# will trigger the missing-mandatory-parameter error or the no-session error.
|
||||
{
|
||||
$splat = @{ ErrorAction = 'Stop' }
|
||||
if ($script:Cmd.Parameters.ContainsKey('TemplateNode')) { $splat['TemplateNode'] = 'pve-node1' }
|
||||
elseif ($script:Cmd.Parameters.ContainsKey('SourceNode')) { $splat['SourceNode'] = 'pve-node1' }
|
||||
if ($script:Cmd.Parameters.ContainsKey('TemplateId')) { $splat['TemplateId'] = 9000 }
|
||||
elseif ($script:Cmd.Parameters.ContainsKey('VmId')) { $splat['VmId'] = 9000 }
|
||||
& 'New-PveVmFromTemplate' @splat
|
||||
} | Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,353 @@
|
||||
#Requires -Module Pester
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Pester 5 tests for user, role, and permission cmdlets:
|
||||
Get-PveUser, New-PveUser, Remove-PveUser, Set-PveUser,
|
||||
Get-PveRole, New-PveRole, Remove-PveRole,
|
||||
Get-PvePermission, Set-PvePermission.
|
||||
|
||||
All tests are fully offline — no live Proxmox VE target is required.
|
||||
If a cmdlet is not yet compiled the test is marked Skipped.
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
|
||||
$allNames = @(
|
||||
'Get-PveUser', 'New-PveUser', 'Remove-PveUser', 'Set-PveUser',
|
||||
'Get-PveRole', 'New-PveRole', 'Remove-PveRole',
|
||||
'Get-PvePermission', 'Set-PvePermission'
|
||||
)
|
||||
|
||||
$script:Availability = @{}
|
||||
foreach ($name in $allNames) {
|
||||
$script:Availability[$name] = $null -ne (Get-Command $name -ErrorAction SilentlyContinue)
|
||||
}
|
||||
|
||||
function Skip-IfMissing([string]$Name) {
|
||||
if (-not $script:Availability[$Name]) {
|
||||
Set-ItResult -Skipped -Because "$Name is not yet implemented in this build"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Manifest contract
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'User / Role / Permission cmdlets — manifest declarations' {
|
||||
BeforeAll {
|
||||
$manifestPath = Join-Path $moduleRoot 'PSProxmoxVE.psd1'
|
||||
$script:Manifest = if (Test-Path $manifestPath) { Import-PowerShellDataFile $manifestPath } else { $null }
|
||||
}
|
||||
|
||||
foreach ($cmdName in @('Get-PveUser', 'New-PveUser', 'Remove-PveUser', 'Set-PveUser',
|
||||
'Get-PveRole', 'New-PveRole', 'Remove-PveRole',
|
||||
'Get-PvePermission', 'Set-PvePermission')) {
|
||||
It "$cmdName should be declared in CmdletsToExport" {
|
||||
if ($null -eq $script:Manifest) { Set-ItResult -Skipped -Because 'Manifest not found'; return }
|
||||
$script:Manifest.CmdletsToExport | Should -Contain $cmdName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Get-PveUser
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Get-PveUser' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'Get-PveUser' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'Get-PveUser'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should be a CmdletInfo (binary cmdlet)' {
|
||||
Skip-IfMissing 'Get-PveUser'
|
||||
$script:Cmd.CommandType | Should -Be 'Cmdlet'
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Parameter metadata' {
|
||||
It 'Should have UserId parameter (optional filter)' {
|
||||
Skip-IfMissing 'Get-PveUser'
|
||||
$script:Cmd.Parameters.ContainsKey('UserId') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'UserId should not be Mandatory' {
|
||||
Skip-IfMissing 'Get-PveUser'
|
||||
$isMandatory = $script:Cmd.Parameters['UserId'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should have Enabled switch or parameter to filter by enabled state' {
|
||||
Skip-IfMissing 'Get-PveUser'
|
||||
# Either an 'Enabled' switch or a filter parameter is expected.
|
||||
$hasEnabled = $script:Cmd.Parameters.ContainsKey('Enabled') -or
|
||||
$script:Cmd.Parameters.ContainsKey('EnabledOnly')
|
||||
$hasEnabled | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Session parameter' {
|
||||
Skip-IfMissing 'Get-PveUser'
|
||||
$script:Cmd.Parameters.ContainsKey('Session') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active' {
|
||||
Skip-IfMissing 'Get-PveUser'
|
||||
{ Get-PveUser -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# New-PveUser
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'New-PveUser' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'New-PveUser' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'New-PveUser'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'ShouldProcess support' {
|
||||
It 'Should support WhatIf' {
|
||||
Skip-IfMissing 'New-PveUser'
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Required parameters' {
|
||||
It 'UserId should be Mandatory (must include realm, e.g. user@pam)' {
|
||||
Skip-IfMissing 'New-PveUser'
|
||||
$isMandatory = $script:Cmd.Parameters['UserId'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Optional parameters' {
|
||||
It 'Should have Password parameter' {
|
||||
Skip-IfMissing 'New-PveUser'
|
||||
$hasPassword = $script:Cmd.Parameters.ContainsKey('Password') -or
|
||||
$script:Cmd.Parameters.ContainsKey('Credential')
|
||||
$hasPassword | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Email parameter' {
|
||||
Skip-IfMissing 'New-PveUser'
|
||||
$script:Cmd.Parameters.ContainsKey('Email') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Groups parameter' {
|
||||
Skip-IfMissing 'New-PveUser'
|
||||
$script:Cmd.Parameters.ContainsKey('Groups') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Remove-PveUser
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Remove-PveUser' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'Remove-PveUser' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'Remove-PveUser'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'ShouldProcess / ConfirmImpact' {
|
||||
It 'Should support WhatIf' {
|
||||
Skip-IfMissing 'Remove-PveUser'
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should declare ConfirmImpact High' {
|
||||
Skip-IfMissing 'Remove-PveUser'
|
||||
$attr = $script:Cmd.ImplementingType.GetCustomAttributes(
|
||||
[System.Management.Automation.CmdletAttribute], $false) |
|
||||
Select-Object -First 1
|
||||
$attr.ConfirmImpact | Should -Be ([System.Management.Automation.ConfirmImpact]::High)
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Required parameters' {
|
||||
It 'UserId should be Mandatory' {
|
||||
Skip-IfMissing 'Remove-PveUser'
|
||||
$isMandatory = $script:Cmd.Parameters['UserId'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Set-PveUser
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Set-PveUser' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'Set-PveUser' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'Set-PveUser'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'ShouldProcess support' {
|
||||
It 'Should support WhatIf' {
|
||||
Skip-IfMissing 'Set-PveUser'
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Required parameters' {
|
||||
It 'UserId should be Mandatory' {
|
||||
Skip-IfMissing 'Set-PveUser'
|
||||
$isMandatory = $script:Cmd.Parameters['UserId'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Get-PveRole
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Get-PveRole' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'Get-PveRole' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'Get-PveRole'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Parameter metadata' {
|
||||
It 'Should have RoleId parameter (optional filter)' {
|
||||
Skip-IfMissing 'Get-PveRole'
|
||||
$script:Cmd.Parameters.ContainsKey('RoleId') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Session parameter' {
|
||||
Skip-IfMissing 'Get-PveRole'
|
||||
$script:Cmd.Parameters.ContainsKey('Session') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active' {
|
||||
Skip-IfMissing 'Get-PveRole'
|
||||
{ Get-PveRole -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Get-PvePermission
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Get-PvePermission' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'Get-PvePermission' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'Get-PvePermission'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Parameter metadata' {
|
||||
It 'Should have UserId parameter' {
|
||||
Skip-IfMissing 'Get-PvePermission'
|
||||
$script:Cmd.Parameters.ContainsKey('UserId') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Path parameter (ACL path, optional)' {
|
||||
Skip-IfMissing 'Get-PvePermission'
|
||||
$script:Cmd.Parameters.ContainsKey('Path') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Session parameter' {
|
||||
Skip-IfMissing 'Get-PvePermission'
|
||||
$script:Cmd.Parameters.ContainsKey('Session') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active' {
|
||||
Skip-IfMissing 'Get-PvePermission'
|
||||
{ Get-PvePermission -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Set-PvePermission
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Set-PvePermission' {
|
||||
|
||||
BeforeAll { $script:Cmd = Get-Command 'Set-PvePermission' -ErrorAction SilentlyContinue }
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Skip-IfMissing 'Set-PvePermission'
|
||||
$script:Cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'ShouldProcess support' {
|
||||
It 'Should support WhatIf' {
|
||||
Skip-IfMissing 'Set-PvePermission'
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Required parameters' {
|
||||
It 'Path should be Mandatory (the ACL path, e.g. / or /vms/100)' {
|
||||
Skip-IfMissing 'Set-PvePermission'
|
||||
$isMandatory = $script:Cmd.Parameters['Path'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Role should be Mandatory' {
|
||||
Skip-IfMissing 'Set-PvePermission'
|
||||
$isMandatory = $script:Cmd.Parameters['Role'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
#Requires -Module Pester
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Pester 5 tests for Get-PveVm.
|
||||
All tests are fully offline — no live Proxmox VE target is required.
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
}
|
||||
|
||||
Describe 'Get-PveVm' {
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Get-Command 'Get-PveVm' -ErrorAction SilentlyContinue |
|
||||
Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should be a CmdletInfo (binary cmdlet)' {
|
||||
(Get-Command 'Get-PveVm').CommandType | Should -Be 'Cmdlet'
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Parameter validation' {
|
||||
BeforeAll {
|
||||
$script:Cmd = Get-Command 'Get-PveVm'
|
||||
}
|
||||
|
||||
It 'Should have Node parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('Node') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Node should not be Mandatory (all-nodes query when omitted)' {
|
||||
$node = $script:Cmd.Parameters['Node']
|
||||
$isMandatory = $node.ParameterSets.Values | Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Node should accept pipeline input by property name' {
|
||||
$node = $script:Cmd.Parameters['Node']
|
||||
$acceptsByPropName = $node.ParameterSets.Values |
|
||||
Where-Object { $_.ValueFromPipelineByPropertyName }
|
||||
$acceptsByPropName | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should have VmId parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('VmId') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Name parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('Name') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Status parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('Status') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Tag parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('Tag') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have TemplatesOnly switch parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('TemplatesOnly') | Should -BeTrue
|
||||
$script:Cmd.Parameters['TemplatesOnly'].ParameterType |
|
||||
Should -Be ([System.Management.Automation.SwitchParameter])
|
||||
}
|
||||
|
||||
It 'Should have Session parameter (inherited from PveCmdletBase)' {
|
||||
$script:Cmd.Parameters.ContainsKey('Session') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'None of the filter parameters should be Mandatory' {
|
||||
foreach ($paramName in @('Node', 'VmId', 'Name', 'Status', 'Tag', 'TemplatesOnly', 'Session')) {
|
||||
$p = $script:Cmd.Parameters[$paramName]
|
||||
$isMandatory = $p.ParameterSets.Values | Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -BeNullOrEmpty -Because "$paramName should be optional"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active and no -Session is supplied' {
|
||||
{ Get-PveVm -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
|
||||
It 'Should throw PveNotConnectedException type' {
|
||||
try {
|
||||
Get-PveVm -ErrorAction Stop
|
||||
}
|
||||
catch {
|
||||
$_.Exception.GetType().Name | Should -Match 'PveNotConnectedException|CmdletInvocationException'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
#Requires -Module Pester
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Pester 5 tests for New-PveVm.
|
||||
All tests are fully offline — no live Proxmox VE target is required.
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
}
|
||||
|
||||
Describe 'New-PveVm' {
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Get-Command 'New-PveVm' -ErrorAction SilentlyContinue |
|
||||
Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should be a CmdletInfo (binary cmdlet)' {
|
||||
(Get-Command 'New-PveVm').CommandType | Should -Be 'Cmdlet'
|
||||
}
|
||||
}
|
||||
|
||||
Context 'ShouldProcess support' {
|
||||
BeforeAll {
|
||||
$script:Cmd = Get-Command 'New-PveVm'
|
||||
}
|
||||
|
||||
It 'Should support ShouldProcess (WhatIf parameter present)' {
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should support ShouldProcess (Confirm parameter present)' {
|
||||
$script:Cmd.Parameters.ContainsKey('Confirm') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should accept -WhatIf without throwing even when no session exists' {
|
||||
# WhatIf must short-circuit before any network call or session check.
|
||||
{ New-PveVm -Node 'pve-node1' -WhatIf -ErrorAction Stop } | Should -Not -Throw
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Required parameter — Node' {
|
||||
It 'Should throw when Node is omitted' {
|
||||
{ New-PveVm -ErrorAction Stop } | Should -Throw
|
||||
}
|
||||
|
||||
It 'Node should be Mandatory' {
|
||||
$nodeParam = (Get-Command 'New-PveVm').Parameters['Node']
|
||||
$isMandatory = $nodeParam.ParameterSets.Values | Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Optional parameter metadata' {
|
||||
BeforeAll {
|
||||
$script:Cmd = Get-Command 'New-PveVm'
|
||||
}
|
||||
|
||||
It 'Should have VmId parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('VmId') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Name parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('Name') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Memory parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('Memory') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Cores parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('Cores') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Sockets parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('Sockets') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have CpuType parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('CpuType') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Bios parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('Bios') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Machine parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('Machine') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have DiskSize parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('DiskSize') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have DiskStorage parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('DiskStorage') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have DiskFormat parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('DiskFormat') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Network parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('Network') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Bridge parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('Bridge') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have OsType parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('OsType') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Start switch parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('Start') | Should -BeTrue
|
||||
$script:Cmd.Parameters['Start'].ParameterType |
|
||||
Should -Be ([System.Management.Automation.SwitchParameter])
|
||||
}
|
||||
|
||||
It 'Should have Wait switch parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('Wait') | Should -BeTrue
|
||||
$script:Cmd.Parameters['Wait'].ParameterType |
|
||||
Should -Be ([System.Management.Automation.SwitchParameter])
|
||||
}
|
||||
|
||||
It 'Should have Session parameter (inherited from PveCmdletBase)' {
|
||||
$script:Cmd.Parameters.ContainsKey('Session') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active (without -WhatIf)' {
|
||||
{ New-PveVm -Node 'pve-node1' -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
#Requires -Module Pester
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Pester 5 tests for Remove-PveVm.
|
||||
All tests are fully offline — no live Proxmox VE target is required.
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
}
|
||||
|
||||
Describe 'Remove-PveVm' {
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Get-Command 'Remove-PveVm' -ErrorAction SilentlyContinue |
|
||||
Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should be a CmdletInfo (binary cmdlet)' {
|
||||
(Get-Command 'Remove-PveVm').CommandType | Should -Be 'Cmdlet'
|
||||
}
|
||||
}
|
||||
|
||||
Context 'ShouldProcess / ConfirmImpact' {
|
||||
BeforeAll {
|
||||
$script:Cmd = Get-Command 'Remove-PveVm'
|
||||
}
|
||||
|
||||
It 'Should support ShouldProcess (WhatIf present)' {
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should support ShouldProcess (Confirm present)' {
|
||||
$script:Cmd.Parameters.ContainsKey('Confirm') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should declare ConfirmImpact High (verified via CmdletAttribute)' {
|
||||
# Retrieve the CmdletAttribute from the underlying type to confirm ConfirmImpact.
|
||||
$cmdletType = $script:Cmd.ImplementingType
|
||||
$attr = $cmdletType.GetCustomAttributes(
|
||||
[System.Management.Automation.CmdletAttribute], $false) |
|
||||
Select-Object -First 1
|
||||
$attr.ConfirmImpact | Should -Be ([System.Management.Automation.ConfirmImpact]::High)
|
||||
}
|
||||
|
||||
It 'Should accept -WhatIf without throwing even when no session exists' {
|
||||
{ Remove-PveVm -Node 'pve-node1' -VmId 100 -WhatIf -ErrorAction Stop } |
|
||||
Should -Not -Throw
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Required parameters' {
|
||||
It 'Should throw when Node is omitted' {
|
||||
{ Remove-PveVm -VmId 100 -ErrorAction Stop } | Should -Throw
|
||||
}
|
||||
|
||||
It 'Should throw when VmId is omitted' {
|
||||
{ Remove-PveVm -Node 'pve-node1' -ErrorAction Stop } | Should -Throw
|
||||
}
|
||||
|
||||
It 'Node should be Mandatory' {
|
||||
$nodeParam = (Get-Command 'Remove-PveVm').Parameters['Node']
|
||||
$isMandatory = $nodeParam.ParameterSets.Values | Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'VmId should be Mandatory' {
|
||||
$vmidParam = (Get-Command 'Remove-PveVm').Parameters['VmId']
|
||||
$isMandatory = $vmidParam.ParameterSets.Values | Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Optional switch parameters' {
|
||||
BeforeAll {
|
||||
$script:Cmd = Get-Command 'Remove-PveVm'
|
||||
}
|
||||
|
||||
It 'Should have Purge switch parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('Purge') | Should -BeTrue
|
||||
$script:Cmd.Parameters['Purge'].ParameterType |
|
||||
Should -Be ([System.Management.Automation.SwitchParameter])
|
||||
}
|
||||
|
||||
It 'Should have Force switch parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('Force') | Should -BeTrue
|
||||
$script:Cmd.Parameters['Force'].ParameterType |
|
||||
Should -Be ([System.Management.Automation.SwitchParameter])
|
||||
}
|
||||
|
||||
It 'Should have Wait switch parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('Wait') | Should -BeTrue
|
||||
$script:Cmd.Parameters['Wait'].ParameterType |
|
||||
Should -Be ([System.Management.Automation.SwitchParameter])
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Pipeline input support' {
|
||||
BeforeAll {
|
||||
$script:Cmd = Get-Command 'Remove-PveVm'
|
||||
}
|
||||
|
||||
It 'Node should accept pipeline input by property name' {
|
||||
$node = $script:Cmd.Parameters['Node']
|
||||
$acceptsByPropName = $node.ParameterSets.Values |
|
||||
Where-Object { $_.ValueFromPipelineByPropertyName }
|
||||
$acceptsByPropName | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'VmId should accept pipeline input by property name' {
|
||||
$vmid = $script:Cmd.Parameters['VmId']
|
||||
$acceptsByPropName = $vmid.ParameterSets.Values |
|
||||
Where-Object { $_.ValueFromPipelineByPropertyName }
|
||||
$acceptsByPropName | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active (without -WhatIf)' {
|
||||
{ Remove-PveVm -Node 'pve-node1' -VmId 100 -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,333 @@
|
||||
#Requires -Module Pester
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Pester 5 tests for VM lifecycle cmdlets:
|
||||
Start-PveVm, Stop-PveVm, Suspend-PveVm, Resume-PveVm,
|
||||
Reset-PveVm, Restart-PveVm.
|
||||
|
||||
All tests are fully offline — no live Proxmox VE target is required.
|
||||
|
||||
NOTE: The C# source declares Reset-PveVm and Restart-PveVm both with
|
||||
[Cmdlet(VerbsLifecycle.Restart, "PveVm")]. When both are compiled into
|
||||
the same assembly PowerShell registers the last one loaded as
|
||||
'Restart-PveVm'. The test suite validates whichever cmdlet is actually
|
||||
registered under each name, rather than assuming a specific implementing
|
||||
type. A separate test records whether 'Reset-PveVm' is resolvable, which
|
||||
is expected to change once the naming collision is fixed.
|
||||
#>
|
||||
|
||||
BeforeAll {
|
||||
$moduleRoot = Resolve-Path (Join-Path $PSScriptRoot '../../../src/PSProxmoxVE')
|
||||
$dllCandidates = @(
|
||||
Join-Path $moduleRoot 'bin/Debug/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net8.0/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Debug/net48/PSProxmoxVE.dll'
|
||||
Join-Path $moduleRoot 'bin/Release/net48/PSProxmoxVE.dll'
|
||||
)
|
||||
|
||||
$script:ModuleDll = $dllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
|
||||
if ($null -eq $script:ModuleDll) {
|
||||
throw "PSProxmoxVE.dll not found. Build the project before running Pester tests."
|
||||
}
|
||||
|
||||
Import-Module $script:ModuleDll -Force -ErrorAction Stop
|
||||
|
||||
# Helper: assert the standard lifecycle parameter set for Node/VmId/Wait.
|
||||
function Assert-StandardLifecycleParams {
|
||||
param([string] $CmdletName)
|
||||
$cmd = Get-Command $CmdletName -ErrorAction SilentlyContinue
|
||||
if ($null -eq $cmd) {
|
||||
Set-ItResult -Skipped -Because "$CmdletName is not yet registered (possible name collision in source)"
|
||||
return $null
|
||||
}
|
||||
return $cmd
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Start-PveVm
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Start-PveVm' {
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Get-Command 'Start-PveVm' -ErrorAction SilentlyContinue |
|
||||
Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Parameter metadata' {
|
||||
BeforeAll { $script:Cmd = Get-Command 'Start-PveVm' }
|
||||
|
||||
It 'Node should be Mandatory' {
|
||||
$isMandatory = $script:Cmd.Parameters['Node'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'VmId should be Mandatory' {
|
||||
$isMandatory = $script:Cmd.Parameters['VmId'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should have Wait switch parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('Wait') | Should -BeTrue
|
||||
$script:Cmd.Parameters['Wait'].ParameterType |
|
||||
Should -Be ([System.Management.Automation.SwitchParameter])
|
||||
}
|
||||
|
||||
It 'Should support ShouldProcess' {
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active (without -WhatIf)' {
|
||||
{ Start-PveVm -Node 'pve-node1' -VmId 100 -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
|
||||
It 'Should not throw with -WhatIf' {
|
||||
{ Start-PveVm -Node 'pve-node1' -VmId 100 -WhatIf -ErrorAction Stop } |
|
||||
Should -Not -Throw
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Stop-PveVm
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Stop-PveVm' {
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Get-Command 'Stop-PveVm' -ErrorAction SilentlyContinue |
|
||||
Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Parameter metadata' {
|
||||
BeforeAll { $script:Cmd = Get-Command 'Stop-PveVm' }
|
||||
|
||||
It 'Node should be Mandatory' {
|
||||
$isMandatory = $script:Cmd.Parameters['Node'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'VmId should be Mandatory' {
|
||||
$isMandatory = $script:Cmd.Parameters['VmId'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should have Wait switch parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('Wait') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should support ShouldProcess' {
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active (without -WhatIf)' {
|
||||
{ Stop-PveVm -Node 'pve-node1' -VmId 100 -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
|
||||
It 'Should not throw with -WhatIf' {
|
||||
{ Stop-PveVm -Node 'pve-node1' -VmId 100 -WhatIf -ErrorAction Stop } |
|
||||
Should -Not -Throw
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Suspend-PveVm
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Suspend-PveVm' {
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Get-Command 'Suspend-PveVm' -ErrorAction SilentlyContinue |
|
||||
Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Parameter metadata' {
|
||||
BeforeAll { $script:Cmd = Get-Command 'Suspend-PveVm' }
|
||||
|
||||
It 'Node should be Mandatory' {
|
||||
$isMandatory = $script:Cmd.Parameters['Node'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'VmId should be Mandatory' {
|
||||
$isMandatory = $script:Cmd.Parameters['VmId'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should have Wait switch parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('Wait') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should support ShouldProcess' {
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active (without -WhatIf)' {
|
||||
{ Suspend-PveVm -Node 'pve-node1' -VmId 100 -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Resume-PveVm
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Resume-PveVm' {
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Get-Command 'Resume-PveVm' -ErrorAction SilentlyContinue |
|
||||
Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Parameter metadata' {
|
||||
BeforeAll { $script:Cmd = Get-Command 'Resume-PveVm' }
|
||||
|
||||
It 'Node should be Mandatory' {
|
||||
$isMandatory = $script:Cmd.Parameters['Node'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'VmId should be Mandatory' {
|
||||
$isMandatory = $script:Cmd.Parameters['VmId'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should have Wait switch parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('Wait') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should support ShouldProcess' {
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active (without -WhatIf)' {
|
||||
{ Resume-PveVm -Node 'pve-node1' -VmId 100 -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Reset-PveVm
|
||||
# NOTE: Source declares both Reset-PveVmCmdlet and RestartPveVmCmdlet with
|
||||
# [Cmdlet(VerbsLifecycle.Restart, "PveVm")]. Until the collision is resolved,
|
||||
# Reset-PveVm may not be separately registered.
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Reset-PveVm' {
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Reset-PveVm should be registered in the module exports' {
|
||||
# Per the .psd1 manifest, 'Reset-PveVm' is listed in CmdletsToExport.
|
||||
# If the name-collision is present, this may resolve to Restart-PveVm's type.
|
||||
$cmd = Get-Command 'Reset-PveVm' -ErrorAction SilentlyContinue
|
||||
$cmd | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Parameter metadata' {
|
||||
BeforeAll {
|
||||
$script:Cmd = Get-Command 'Reset-PveVm' -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
It 'Node should be present' {
|
||||
if ($null -eq $script:Cmd) { Set-ItResult -Skipped -Because 'Reset-PveVm not registered'; return }
|
||||
$script:Cmd.Parameters.ContainsKey('Node') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'VmId should be present' {
|
||||
if ($null -eq $script:Cmd) { Set-ItResult -Skipped -Because 'Reset-PveVm not registered'; return }
|
||||
$script:Cmd.Parameters.ContainsKey('VmId') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Wait should be present' {
|
||||
if ($null -eq $script:Cmd) { Set-ItResult -Skipped -Because 'Reset-PveVm not registered'; return }
|
||||
$script:Cmd.Parameters.ContainsKey('Wait') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should support ShouldProcess' {
|
||||
if ($null -eq $script:Cmd) { Set-ItResult -Skipped -Because 'Reset-PveVm not registered'; return }
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Restart-PveVm
|
||||
# ---------------------------------------------------------------------------
|
||||
Describe 'Restart-PveVm' {
|
||||
|
||||
Context 'Command existence' {
|
||||
It 'Should be available after module import' {
|
||||
Get-Command 'Restart-PveVm' -ErrorAction SilentlyContinue |
|
||||
Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Parameter metadata' {
|
||||
BeforeAll { $script:Cmd = Get-Command 'Restart-PveVm' }
|
||||
|
||||
It 'Node should be Mandatory' {
|
||||
$isMandatory = $script:Cmd.Parameters['Node'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'VmId should be Mandatory' {
|
||||
$isMandatory = $script:Cmd.Parameters['VmId'].ParameterSets.Values |
|
||||
Where-Object { $_.IsMandatory }
|
||||
$isMandatory | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should have Timeout parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('Timeout') | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should have Wait switch parameter' {
|
||||
$script:Cmd.Parameters.ContainsKey('Wait') | Should -BeTrue
|
||||
$script:Cmd.Parameters['Wait'].ParameterType |
|
||||
Should -Be ([System.Management.Automation.SwitchParameter])
|
||||
}
|
||||
|
||||
It 'Should support ShouldProcess' {
|
||||
$script:Cmd.Parameters.ContainsKey('WhatIf') | Should -BeTrue
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Without active session' {
|
||||
It 'Should throw when no session is active (without -WhatIf)' {
|
||||
{ Restart-PveVm -Node 'pve-node1' -VmId 100 -ErrorAction Stop } |
|
||||
Should -Throw '*No active Proxmox VE session*'
|
||||
}
|
||||
|
||||
It 'Should not throw with -WhatIf' {
|
||||
{ Restart-PveVm -Node 'pve-node1' -VmId 100 -WhatIf -ErrorAction Stop } |
|
||||
Should -Not -Throw
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user