Tests/EAI/EAISdt.Tests.ps1
|
BeforeAll { if ($Module) { $script:DevModuleName = Import-Module $Module -Force -PassThru | Select-Object -ExpandProperty Name } else { $devModule = Join-Path $PSScriptRoot '..' '..' 'Dev.Logic.Monitor.psd1' $script:DevModuleName = Import-Module $devModule -Force -PassThru | Select-Object -ExpandProperty Name } } Describe 'Get-EAISdt' { BeforeEach { Disconnect-EAIAccount Connect-EAIAccount -EdwinOrg 'myorg' -ClientId 'client' -ClientSecret 'secret' -SkipCredValidation InModuleScope -ModuleName $script:DevModuleName { $Script:EAIAuth.AccessToken = 'test-token' | ConvertTo-SecureString -AsPlainText -Force $Script:EAIAuth.TokenExpiresAt = (Get-Date).ToUniversalTime().AddHours(1) } } It 'Requires an active Edwin connection' { Disconnect-EAIAccount { Get-EAISdt -ErrorAction Stop } | Should -Throw } It 'Retrieves scheduled downtimes from Edwin' { InModuleScope -ModuleName $script:DevModuleName { Mock Invoke-EAIRestMethod { param($Headers) $script:capturedHeaders = $Headers return @( [PSCustomObject]@{ scheduleId = 'schedule-1' name = 'Maintenance window' } [PSCustomObject]@{ scheduleId = 'schedule-2' name = 'Change freeze' } ) } $results = Get-EAISdt Should -Invoke Invoke-EAIRestMethod -Times 1 -ParameterFilter { $Uri -eq 'https://myorg.dexda.ai/action/sdt' -and $Method -eq 'GET' } $script:capturedHeaders.Authorization | Should -Be 'Bearer test-token' $results.Count | Should -Be 2 $results[0].name | Should -Be 'Maintenance window' $results[0].PSObject.TypeNames[0] | Should -Be 'Edwin.SDT' } } It 'Retrieves a single schedule by ID' { InModuleScope -ModuleName $script:DevModuleName { Mock Invoke-EAIRestMethod { return [PSCustomObject]@{ scheduleId = '6d18821f-8f3c-48ca-8331-3e4c8d77cac3' name = 'Maintenance window' } } $result = Get-EAISdt -Id '6d18821f-8f3c-48ca-8331-3e4c8d77cac3' Should -Invoke Invoke-EAIRestMethod -Times 1 -ParameterFilter { $Uri -eq 'https://myorg.dexda.ai/action/sdt/6d18821f-8f3c-48ca-8331-3e4c8d77cac3' -and $Method -eq 'GET' } $result.scheduleId | Should -Be '6d18821f-8f3c-48ca-8331-3e4c8d77cac3' $result.PSObject.TypeNames[0] | Should -Be 'Edwin.SDT' } } It 'Returns an empty array when Edwin has no schedules' { InModuleScope -ModuleName $script:DevModuleName { Mock Invoke-EAIRestMethod { return @() } $results = Get-EAISdt @($results).Count | Should -Be 0 } } } Describe 'New-EAISdt' { BeforeEach { Disconnect-EAIAccount Connect-EAIAccount -EdwinOrg 'myorg' -ClientId 'client' -ClientSecret 'secret' -SkipCredValidation InModuleScope -ModuleName $script:DevModuleName { $Script:EAIAuth.AccessToken = 'test-token' | ConvertTo-SecureString -AsPlainText -Force $Script:EAIAuth.TokenExpiresAt = (Get-Date).ToUniversalTime().AddHours(1) } } It 'Posts a create payload to /action/sdt' { InModuleScope -ModuleName $script:DevModuleName { $filter = [PSCustomObject]@{ schemaName = 'filterCondition' schemaVersion = '4' expression = @{ AND = @() } } Mock Invoke-EAIRestMethod { return $null } New-EAISdt -Name 'Maintenance' -Duration 60 -Filter $filter -Confirm:$false Should -Invoke Invoke-EAIRestMethod -Times 1 -ParameterFilter { $Uri -eq 'https://myorg.dexda.ai/action/sdt' -and $Method -eq 'POST' -and $Body -match '"name":"Maintenance"' -and $Body -match '"enabled":"ENABLED"' } } } It 'Merges wizard output before creating' { InModuleScope -ModuleName $script:DevModuleName { Mock Invoke-EAISdtCmdletWizard { return @{ Name = 'Wizard schedule' Filter = [PSCustomObject]@{ schemaName = 'filterCondition' schemaVersion = '4' expression = @{ AND = @() } } Duration = 45 } } Mock Invoke-EAIRestMethod { return $null } New-EAISdt -ScheduleWizard -Confirm:$false Should -Invoke Invoke-EAIRestMethod -Times 1 -ParameterFilter { $Body -match '"name":"Wizard schedule"' -and $Body -match '"duration":"PT45M"' } } } } Describe 'Set-EAISdt' { BeforeEach { Disconnect-EAIAccount Connect-EAIAccount -EdwinOrg 'myorg' -ClientId 'client' -ClientSecret 'secret' -SkipCredValidation InModuleScope -ModuleName $script:DevModuleName { $Script:EAIAuth.AccessToken = 'test-token' | ConvertTo-SecureString -AsPlainText -Force $Script:EAIAuth.TokenExpiresAt = (Get-Date).ToUniversalTime().AddHours(1) } } It 'Posts disable metadata to update/metadata' { InModuleScope -ModuleName $script:DevModuleName { $existing = [PSCustomObject]@{ name = 'Maintenance window' description = 'Patch window' enabled = 'ENABLED' timezone = 'America/New_York' startTime = '2026-07-21T12:00:00' duration = 'PT1H' filter = [PSCustomObject]@{ schemaName = 'filterCondition' schemaVersion = '4' expression = @{ AND = @() } } recurrencePattern = [PSCustomObject]@{ downtimeScheduleType = 'ONE_TIME' frequency = 'DAILY' } } Mock Get-EAISdt { return $existing } Mock Invoke-EAIRestMethod { return $null } Set-EAISdt -Id '6d18821f-8f3c-48ca-8331-3e4c8d77cac3' -Enabled:$false -Confirm:$false Should -Invoke Get-EAISdt -Times 1 -ParameterFilter { $Id -eq '6d18821f-8f3c-48ca-8331-3e4c8d77cac3' } Should -Invoke Invoke-EAIRestMethod -Times 1 -ParameterFilter { $Uri -eq 'https://myorg.dexda.ai/action/sdt/6d18821f-8f3c-48ca-8331-3e4c8d77cac3/update/metadata' -and $Method -eq 'POST' -and $Body -match '"enabled":"DISABLED"' -and $Body -match '"name":"Maintenance window"' -and $Body -match '"description":"Patch window"' } } } It 'Accepts piped Edwin.SDT objects by scheduleId' { InModuleScope -ModuleName $script:DevModuleName { Mock Invoke-EAIRestMethod { return $null } $schedule = Add-ObjectTypeInfo -InputObject ([PSCustomObject]@{ scheduleId = '6d18821f-8f3c-48ca-8331-3e4c8d77cac3' name = 'Maintenance window' description = 'Patch window' enabled = 'ENABLED' timezone = 'America/New_York' startTime = '2026-07-21T12:00:00' duration = 'PT1H' filter = [PSCustomObject]@{ schemaName = 'filterCondition' schemaVersion = '4' expression = @{ AND = @() } } recurrencePattern = [PSCustomObject]@{ downtimeScheduleType = 'ONE_TIME' frequency = 'DAILY' } }) -TypeName 'Edwin.SDT' $schedule | Set-EAISdt -Enabled:$false -Confirm:$false Should -Invoke Invoke-EAIRestMethod -Times 1 -ParameterFilter { $Uri -eq 'https://myorg.dexda.ai/action/sdt/6d18821f-8f3c-48ca-8331-3e4c8d77cac3/update/metadata' -and $Body -match '"name":"Maintenance window"' } } } It 'Routes filter and recurrence updates to separate endpoints' { InModuleScope -ModuleName $script:DevModuleName { $filter = [PSCustomObject]@{ schemaName = 'filterCondition' schemaVersion = '4' expression = @{ AND = @() } } $existing = [PSCustomObject]@{ scheduleId = '6d18821f-8f3c-48ca-8331-3e4c8d77cac3' name = 'Weekly window' description = 'Original' enabled = 'ENABLED' timezone = 'America/New_York' startTime = '2026-07-02T13:07:00' duration = 'PT1H' filter = [PSCustomObject]@{ schemaName = 'filterCondition' schemaVersion = '4' expression = @{ AND = @() } } recurrencePattern = [PSCustomObject]@{ downtimeScheduleType = 'RECURRING' frequency = 'WEEKLY' weekDays = @('Monday') } } Mock Get-EAISdt { return $existing } Mock Invoke-EAIRestMethod { return $null } Set-EAISdt -Id '6d18821f-8f3c-48ca-8331-3e4c8d77cac3' ` -Description 'Updated' ` -Filter $filter ` -WeekDay Monday, Thursday ` -Confirm:$false Should -Invoke Invoke-EAIRestMethod -Times 1 -ParameterFilter { $Uri -like '*/update/metadata' -and $Body -match '"description":"Updated"' } Should -Invoke Invoke-EAIRestMethod -Times 1 -ParameterFilter { $Uri -like '*/update/filter' -and $Body -match '"newFilter"' } Should -Invoke Invoke-EAIRestMethod -Times 1 -ParameterFilter { $Uri -like '*/update/recurrence' -and $Body -match '"newPattern"' } } } } |