Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed Azure DevOps pipeline conditions that were preventing DSC resource
integration tests from running when they should by removing incorrect quotes
around boolean values.
- `SqlAgentAlert`
- Minor fix in `source/Classes/020.SqlAgentAlert.ps1` to correct `ExcludeDscProperties`
formatting (added missing delimiter).

### Added

Expand Down Expand Up @@ -57,6 +60,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Refactored GitHub Copilot workflow setup to be module-agnostic via MODULE_NAME
environment variable, includes full-history detection, uses idempotent .NET
tool install, and adds Linux dependency handling ([issue #2127](https://github.com/dsccommunity/SqlServerDsc/issues/2127)).
- `SqlAgentAlert`
- Added additional unit tests covering MessageId-based alerts, the hidden
`Modify()` method behavior, and `AssertProperties()` validation scenarios.
- Module now outputs a verbose message instead of a warning when the SMO
dependency module is missing during import to work around a DSC v3 issue.
- VS Code tasks configuration was improved to support AI.
Expand Down
2 changes: 1 addition & 1 deletion source/Classes/020.SqlAgentAlert.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ class SqlAgentAlert : SqlResourceBase
$this.ExcludeDscProperties = @(
'InstanceName',
'ServerName',
'Credential'
'Credential',
'Name'
)
}
Expand Down
222 changes: 166 additions & 56 deletions tests/Unit/Classes/SqlAgentAlert.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -124,21 +124,17 @@ Describe 'SqlAgentAlert' -Tag 'SqlAgentAlert' {
}

Context 'When using the Get() method' {
BeforeAll {
InModuleScope -ScriptBlock {
$script:mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server'
It 'Should return current state when alert exists' {
Mock -CommandName 'Get-SqlDscAgentAlert' -MockWith {
$script:mockAlertObject = New-Object -TypeName 'PSCustomObject'
$script:mockAlertObject | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestAlert'
$script:mockAlertObject | Add-Member -MemberType 'NoteProperty' -Name 'Severity' -Value 16
# MessageId is not set when using Severity-based alerts

return $script:mockAlertObject
}
}

It 'Should return current state when alert exists' {
InModuleScope -ScriptBlock {
Mock -CommandName 'Get-SqlDscAgentAlert' -MockWith {
return $script:mockAlertObject
}
$script:mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server'

$instance = [SqlAgentAlert] @{
Name = 'TestAlert'
Expand All @@ -159,10 +155,12 @@ Describe 'SqlAgentAlert' -Tag 'SqlAgentAlert' {
}

It 'Should return absent state when alert does not exist' {
Mock -CommandName 'Get-SqlDscAgentAlert' -MockWith {
return $null
}

InModuleScope -ScriptBlock {
Mock -CommandName 'Get-SqlDscAgentAlert' -MockWith {
return $null
}
$script:mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server'

$instance = [SqlAgentAlert] @{
Name = 'TestAlert'
Expand All @@ -180,6 +178,38 @@ Describe 'SqlAgentAlert' -Tag 'SqlAgentAlert' {
$result.Ensure | Should -Be 'Absent'
}
}

It 'Should return current state when alert exists with MessageId' {
Mock -CommandName 'Get-SqlDscAgentAlert' -MockWith {
$script:mockAlertObjectWithMessageId = New-Object -TypeName 'PSCustomObject'
$script:mockAlertObjectWithMessageId | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestAlert'
$script:mockAlertObjectWithMessageId | Add-Member -MemberType 'NoteProperty' -Name 'Severity' -Value 0
$script:mockAlertObjectWithMessageId | Add-Member -MemberType 'NoteProperty' -Name 'MessageId' -Value 50001

return $script:mockAlertObjectWithMessageId
}

InModuleScope -ScriptBlock {
$script:mockServerObject = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Server'

$instance = [SqlAgentAlert] @{
Name = 'TestAlert'
InstanceName = 'MSSQLSERVER'
MessageId = 50002
} |
Add-Member -Force -MemberType 'ScriptMethod' -Name 'GetServerObject' -Value {
return $script:mockServerObject
} -PassThru

$result = $instance.Get()

$result | Should -Not -BeNullOrEmpty
$result.Name | Should -Be 'TestAlert'
$result.Ensure | Should -Be 'Present'
$result.MessageId | Should -Be 50001
$result.Severity | Should -BeNullOrEmpty
}
}
}

Context 'When using the Test() method' {
Expand All @@ -190,16 +220,16 @@ Describe 'SqlAgentAlert' -Tag 'SqlAgentAlert' {
}

It 'Should return true when alert exists and is in desired state' {
Mock -CommandName 'Get-SqlDscAgentAlert' -MockWith {
return $script:mockAlertObject
}

InModuleScope -ScriptBlock {
$script:mockAlertObject = New-Object -TypeName 'PSCustomObject'
$script:mockAlertObject | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestAlert'
$script:mockAlertObject | Add-Member -MemberType 'NoteProperty' -Name 'Severity' -Value 16
$script:mockAlertObject | Add-Member -MemberType 'NoteProperty' -Name 'MessageId' -Value 0

Mock -CommandName 'Get-SqlDscAgentAlert' -MockWith {
return $script:mockAlertObject
}

$instance = [SqlAgentAlert] @{
Name = 'TestAlert'
InstanceName = 'MSSQLSERVER'
Expand All @@ -217,11 +247,9 @@ Describe 'SqlAgentAlert' -Tag 'SqlAgentAlert' {
}

It 'Should return false when alert does not exist but should be present' {
InModuleScope -ScriptBlock {
Mock -CommandName 'Get-SqlDscAgentAlert' -MockWith {
return $null
}
Mock -CommandName 'Get-SqlDscAgentAlert'

InModuleScope -ScriptBlock {
$instance = [SqlAgentAlert] @{
Name = 'TestAlert'
InstanceName = 'MSSQLSERVER'
Expand Down Expand Up @@ -269,6 +297,27 @@ Describe 'SqlAgentAlert' -Tag 'SqlAgentAlert' {
Should -Invoke -CommandName 'Remove-SqlDscAgentAlert' -Exactly -Times 0 -Scope It
}
}

It 'Should create alert with MessageId' {
InModuleScope -ScriptBlock {
$instance = [SqlAgentAlert] @{
Name = 'TestAlert'
InstanceName = 'MSSQLSERVER'
Ensure = 'Present'
MessageId = 50001
} |
Add-Member -Force -MemberType 'ScriptMethod' -Name 'GetServerObject' -Value {
return $script:mockServerObject
} -PassThru

$null = $instance.Set()

Should -Invoke -CommandName 'New-SqlDscAgentAlert' -ParameterFilter {
$MessageId -eq 50001
} -Exactly -Times 1 -Scope It
Should -Invoke -CommandName 'Remove-SqlDscAgentAlert' -Exactly -Times 0 -Scope It
}
}
}

Context 'When it exists and Ensure is Absent' {
Expand Down Expand Up @@ -320,18 +369,79 @@ Describe 'SqlAgentAlert' -Tag 'SqlAgentAlert' {
Mock -CommandName 'Set-SqlDscAgentAlert'
}

Context 'When Ensure is Present and alert exists' {
It 'Should update alert when Severity property differs' {

Context 'When Ensure is Present and alert does not exist' {
BeforeAll {
Mock -CommandName 'Get-SqlDscAgentAlert'
}

It 'Should create alert with Severity' {
InModuleScope -ScriptBlock {
$instance = [SqlAgentAlert] @{
Name = 'TestAlert'
InstanceName = 'MSSQLSERVER'
Ensure = 'Present'
Severity = 16
} |
Add-Member -Force -MemberType 'ScriptMethod' -Name 'GetServerObject' -Value {
return $script:mockServerObject
} -PassThru

$properties = @{
Severity = 16
}

$null = $instance.Modify($properties)

Should -Invoke -CommandName 'Get-SqlDscAgentAlert' -Exactly -Times 1 -Scope It
Should -Invoke -CommandName 'New-SqlDscAgentAlert' -ParameterFilter {
$Severity -eq 16
} -Exactly -Times 1 -Scope It
Should -Invoke -CommandName 'Set-SqlDscAgentAlert' -Exactly -Times 0 -Scope It
Should -Invoke -CommandName 'Remove-SqlDscAgentAlert' -Exactly -Times 0 -Scope It
}
}

It 'Should create alert with MessageId' {
InModuleScope -ScriptBlock {
Mock -CommandName 'Get-SqlDscAgentAlert' -MockWith {
$mockAlertObject = New-Object -TypeName 'PSCustomObject'
$mockAlertObject | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestAlert'
$mockAlertObject | Add-Member -MemberType 'NoteProperty' -Name 'Severity' -Value 10
$mockAlertObject | Add-Member -MemberType 'NoteProperty' -Name 'MessageId' -Value 0
$instance = [SqlAgentAlert] @{
Name = 'TestAlert'
InstanceName = 'MSSQLSERVER'
Ensure = 'Present'
MessageId = 50001
} |
Add-Member -Force -MemberType 'ScriptMethod' -Name 'GetServerObject' -Value {
return $script:mockServerObject
} -PassThru

return $mockAlertObject
$properties = @{
MessageId = 50001
}

$null = $instance.Modify($properties)

Should -Invoke -CommandName 'Get-SqlDscAgentAlert' -Exactly -Times 1 -Scope It
Should -Invoke -CommandName 'New-SqlDscAgentAlert' -ParameterFilter {
$MessageId -eq 50001
} -Exactly -Times 1 -Scope It
Should -Invoke -CommandName 'Set-SqlDscAgentAlert' -Exactly -Times 0 -Scope It
Should -Invoke -CommandName 'Remove-SqlDscAgentAlert' -Exactly -Times 0 -Scope It
}
}
}

Context 'When Ensure is Present and alert exists' {
It 'Should update alert when Severity property differs' {
Mock -CommandName 'Get-SqlDscAgentAlert' -MockWith {
$mockAlertObject = New-Object -TypeName 'PSCustomObject'
$mockAlertObject | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestAlert'
$mockAlertObject | Add-Member -MemberType 'NoteProperty' -Name 'Severity' -Value 10
$mockAlertObject | Add-Member -MemberType 'NoteProperty' -Name 'MessageId' -Value 0

return $mockAlertObject
}

InModuleScope -ScriptBlock {
$instance = [SqlAgentAlert] @{
Name = 'TestAlert'
InstanceName = 'MSSQLSERVER'
Expand Down Expand Up @@ -359,16 +469,16 @@ Describe 'SqlAgentAlert' -Tag 'SqlAgentAlert' {
}

It 'Should update alert when MessageId property differs' {
InModuleScope -ScriptBlock {
Mock -CommandName 'Get-SqlDscAgentAlert' -MockWith {
$mockAlertObject = New-Object -TypeName 'PSCustomObject'
$mockAlertObject | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestAlert'
$mockAlertObject | Add-Member -MemberType 'NoteProperty' -Name 'Severity' -Value 0
$mockAlertObject | Add-Member -MemberType 'NoteProperty' -Name 'MessageId' -Value 50001
Mock -CommandName 'Get-SqlDscAgentAlert' -MockWith {
$mockAlertObject = New-Object -TypeName 'PSCustomObject'
$mockAlertObject | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestAlert'
$mockAlertObject | Add-Member -MemberType 'NoteProperty' -Name 'Severity' -Value 0
$mockAlertObject | Add-Member -MemberType 'NoteProperty' -Name 'MessageId' -Value 50001

return $mockAlertObject
}
return $mockAlertObject
}

InModuleScope -ScriptBlock {
$instance = [SqlAgentAlert] @{
Name = 'TestAlert'
InstanceName = 'MSSQLSERVER'
Expand Down Expand Up @@ -396,16 +506,16 @@ Describe 'SqlAgentAlert' -Tag 'SqlAgentAlert' {
}

It 'Should not update alert when no properties differ' {
InModuleScope -ScriptBlock {
Mock -CommandName 'Get-SqlDscAgentAlert' -MockWith {
$mockAlertObject = New-Object -TypeName 'PSCustomObject'
$mockAlertObject | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestAlert'
$mockAlertObject | Add-Member -MemberType 'NoteProperty' -Name 'Severity' -Value 16
$mockAlertObject | Add-Member -MemberType 'NoteProperty' -Name 'MessageId' -Value 0
Mock -CommandName 'Get-SqlDscAgentAlert' -MockWith {
$mockAlertObject = New-Object -TypeName 'PSCustomObject'
$mockAlertObject | Add-Member -MemberType 'NoteProperty' -Name 'Name' -Value 'TestAlert'
$mockAlertObject | Add-Member -MemberType 'NoteProperty' -Name 'Severity' -Value 16
$mockAlertObject | Add-Member -MemberType 'NoteProperty' -Name 'MessageId' -Value 0

return $mockAlertObject
}
return $mockAlertObject
}

InModuleScope -ScriptBlock {
$instance = [SqlAgentAlert] @{
Name = 'TestAlert'
InstanceName = 'MSSQLSERVER'
Expand Down Expand Up @@ -568,10 +678,12 @@ Describe 'SqlAgentAlert' -Tag 'SqlAgentAlert' {
}

Context 'When Ensure is Present' {
BeforeAll {
Mock -CommandName 'Assert-BoundParameter'
}

It 'Should call Assert-BoundParameter to validate at least one of Severity or MessageId is specified' {
InModuleScope -ScriptBlock {
Mock -CommandName 'Assert-BoundParameter' -MockWith { }

$properties = @{
Name = 'TestAlert'
Ensure = 'Present'
Expand All @@ -591,8 +703,6 @@ Describe 'SqlAgentAlert' -Tag 'SqlAgentAlert' {

It 'Should call Assert-BoundParameter to validate Severity and MessageId are mutually exclusive' {
InModuleScope -ScriptBlock {
Mock -CommandName 'Assert-BoundParameter' -MockWith { }

$properties = @{
Name = 'TestAlert'
Ensure = 'Present'
Expand All @@ -613,9 +723,9 @@ Describe 'SqlAgentAlert' -Tag 'SqlAgentAlert' {

Context 'When Ensure is Absent' {
It 'Should call Assert-BoundParameter to validate Severity and MessageId are not allowed' {
InModuleScope -ScriptBlock {
Mock -CommandName 'Assert-BoundParameter' -MockWith { }
Mock -CommandName 'Assert-BoundParameter'

InModuleScope -ScriptBlock {
$properties = @{
Name = 'TestAlert'
Ensure = 'Absent'
Expand All @@ -633,14 +743,14 @@ Describe 'SqlAgentAlert' -Tag 'SqlAgentAlert' {
}

It 'Should call Assert-BoundParameter with correct parameters when Severity is specified' {
InModuleScope -ScriptBlock {
Mock -CommandName 'Assert-BoundParameter' -MockWith {
# Simulate the Assert-BoundParameter throwing an exception for NotAllowed parameters
if ($NotAllowedList -and ($BoundParameterList.ContainsKey('Severity') -or $BoundParameterList.ContainsKey('MessageId'))) {
throw 'Parameter validation failed'
}
Mock -CommandName 'Assert-BoundParameter' -MockWith {
# Simulate the Assert-BoundParameter throwing an exception for NotAllowed parameters
if ($NotAllowedList -and ($BoundParameterList.ContainsKey('Severity') -or $BoundParameterList.ContainsKey('MessageId'))) {
throw 'Parameter validation failed'
}
}

InModuleScope -ScriptBlock {
$properties = @{
Name = 'TestAlert'
Ensure = 'Absent'
Expand Down
Loading