Repository navigation
test(#20): behavioral tests for LoadMonitor/NotificationManager/SchedulerManager/NetworkThrottle - #60
Conversation
…ulerManager/NetworkThrottle Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Warning Review limit reached
More reviews will be available in 52 minutes and 57 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughAdds Pester coverage for LoadMonitor, NetworkThrottle, NotificationManager, and SchedulerManager, plus a shared fake ChangesShared Test Doubles
LoadMonitor Behavioral Coverage
NetworkThrottle Behavioral Coverage
NotificationManager Behavioral Coverage
SchedulerManager Behavioral Coverage
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
Adds substantial Pester behavioral coverage for several previously under-tested modules, validating key behavior while mocking infrastructure boundaries so the suite can run on GitHub-hosted Windows CI.
Changes:
- Adds a full SchedulerManager behavioral suite covering task construction, overwrite/WhatIf behavior, legacy-credential warning, and status/update paths.
- Adds NotificationManager behavioral tests covering Discord payload construction, per-type gating, 429 Retry-After handling, and “never throw” transport-failure contract.
- Adds NetworkThrottle behavioral tests for Copy-SEBThrottled strategy selection (BITS/robocopy/Copy-Item) and for BITS transfer wrappers (start/status/stop).
- Adds LoadMonitor behavioral tests for metrics shaping, threshold verdicts, fail-open behavior, and defer/skip wait mechanics.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| Tests/SchedulerManager/SchedulerManager.Tests.ps1 | Adds behavioral tests for scheduled task creation/update/status logic with fully mocked ScheduledTasks boundary. |
| Tests/NotificationManager/NotificationManager.Tests.ps1 | Adds behavioral tests for Discord embed/payload construction, gating, retry logic, and non-blocking failure behavior. |
| Tests/NetworkThrottle/Copy-SEBThrottled.Tests.ps1 | Adds behavioral tests for Copy-SEBThrottled strategy selection and robocopy/BITS/Copy-Item dispatch behavior. |
| Tests/NetworkThrottle/BitsTransfer.Tests.ps1 | Adds behavioral tests for Start/Get/Stop BITS wrapper functions with mocked BitsTransfer cmdlets. |
| Tests/LoadMonitor/LoadMonitor.Tests.ps1 | Adds behavioral tests for node load/metrics evaluation and deterministic wait/defer behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # A minimal stand-in for the PS7 HttpResponseException shape the 429 handler inspects: | ||
| # $_.Exception.Response.StatusCode (int-castable) | ||
| # $_.Exception.Response.Headers.TryGetValues('Retry-After', [ref]$out) | ||
| class FakeRespHeaders { | ||
| [object]$RetryAfter = $null | ||
| [bool] TryGetValues([string]$name, [ref]$values) { | ||
| if ($name -eq 'Retry-After') { $values.Value = @('2'); return $true } | ||
| return $false | ||
| } | ||
| } | ||
| class FakeResponse { | ||
| [int]$StatusCode | ||
| [FakeRespHeaders]$Headers = [FakeRespHeaders]::new() | ||
| } | ||
| class FakeHttpException : System.Exception { | ||
| [FakeResponse]$Response | ||
| FakeHttpException([string]$message, [int]$code) : base($message) { | ||
| $this.Response = [FakeResponse]::new() | ||
| $this.Response.StatusCode = $code | ||
| } | ||
| } | ||
| # Expose to test bodies (classes are discovery-scoped; stash factories on script scope). | ||
| function New-FakeHttpException { param([int]$Code) [FakeHttpException]::new("HTTP $Code", $Code) } | ||
|
|
| BeforeAll { | ||
| $repoRoot = (Resolve-Path "$PSScriptRoot/../..").Path | ||
| Import-Module "$repoRoot/SEBackup.psd1" -Force -DisableNameChecking 3>$null | ||
|
|
||
| # Stop-SEBTransfer passes the job to Remove-BitsTransfer -BitsJob, whose parameter is the strict | ||
| # type [Management.BitsJob[]]; a PSCustomObject would not bind (its mock would be skipped). So the | ||
| # double is a real (uninitialized) BitsJob -- which has no public ctor -- with the handful of | ||
| # members the functions read shadowed via Add-Member. It binds to -BitsJob AND reads back our | ||
| # values; Get-BitsTransfer (mocked) just hands this object back, so no real BITS state is touched. | ||
| function New-FakeBitsJob { |
| # Behavioral tests for the SchedulerManager module (issue #20). Previously only the function-existence | ||
| # contract ran; this suite exercises the Task Scheduler action/trigger/principal construction, the | ||
| # S4U "run whether logged on or not" principal, the legacy-credential warning, the status mapping, and | ||
| # the update paths -- WITHOUT writing anything to the real Windows Task Scheduler. |
…itive inline assert; credential-path coverage; shared doubles (review) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018ugmSicjxrV6S86B1GEnVZ
| # Behavioral tests for the SchedulerManager module (issue #20). Previously only the function-existence | ||
| # contract ran; this suite exercises the Task Scheduler action/trigger/principal construction, the | ||
| # S4U "run whether logged on or not" principal, the legacy-credential warning, the status mapping, and | ||
| # the update paths -- WITHOUT writing anything to the real Windows Task Scheduler. |
| if ($PSBoundParameters.ContainsKey('Name')) { | ||
| $session | Add-Member -Force -MemberType ScriptProperty -Name Name ` | ||
| -Value ([scriptblock]::Create("'$Name'")) | ||
| } |
| if ($PSBoundParameters.ContainsKey('Target')) { | ||
| $session | Add-Member -Force -MemberType ScriptProperty -Name ComputerName ` | ||
| -Value ([scriptblock]::Create("'$Target'")) | ||
| } |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@Tests/LoadMonitor/LoadMonitor.Tests.ps1`:
- Around line 339-353: The test in Wait-SEBNodeLoad only verifies that
Start-Sleep was called, so it can still pass even if defer_poll_interval_seconds
is ignored and the default interval is used. Update the LoadMonitor.Tests.ps1
case for Wait-SEBNodeLoad to assert the actual Start-Sleep argument/parameter
value, ensuring the legacy defer_* config keys are truly read; keep the existing
mock setup and add a parameter check tied to the sleep call.
In `@Tests/NetworkThrottle/BitsTransfer.Tests.ps1`:
- Around line 33-34: The test helper in New-FakeBitsJob is using the concrete
Microsoft.BackgroundIntelligentTransfer.Management.BitsJob type, which can break
when the BitsTransfer module is mocked and the assembly is not loaded. Update
New-FakeBitsJob in BitsTransfer.Tests.ps1 to return a mockable fake object such
as a PSCustomObject that satisfies the Get-BitsTransfer and Remove-BitsTransfer
test expectations, and remove the dependency on
[Microsoft.BackgroundIntelligentTransfer.Management.BitsJob] so the mocked
Import-Module path works reliably.
In `@Tests/SchedulerManager/SchedulerManager.Tests.ps1`:
- Around line 193-196: The current WhatIf test for Register-SEBScheduledTask
only verifies Register-ScheduledTask is skipped, but it does not cover the
existing-task overwrite path where Unregister-ScheduledTask may still run before
the ShouldProcess gate. Update the test in SchedulerManager.Tests.ps1 within the
Register-SEBScheduledTask WhatIf case to mock an existing task and assert both
Unregister-ScheduledTask and Register-ScheduledTask are invoked 0 times when
-WhatIf is used, so the behavior is covered for task replacement as well.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 5b29ae05-dadc-4639-807c-74592a426033
📒 Files selected for processing (6)
Tests/LoadMonitor/LoadMonitor.Tests.ps1Tests/NetworkThrottle/BitsTransfer.Tests.ps1Tests/NetworkThrottle/Copy-SEBThrottled.Tests.ps1Tests/NotificationManager/NotificationManager.Tests.ps1Tests/SchedulerManager/SchedulerManager.Tests.ps1Tests/_TestHelpers/Test-Doubles.ps1
| It 'honors the legacy defer_* config keys (defer_poll_interval_seconds / defer_wait_minutes)' { | ||
| # The shipped names are check_interval_seconds / max_backoff_minutes; the older defer_* names | ||
| # must still be accepted so existing operator configs keep working. We assert the loop still | ||
| # polls + sleeps under ONLY the legacy keys (proving they were read, not ignored). | ||
| $script:legPoll = 0 | ||
| Mock Start-Sleep -ModuleName LoadMonitor {} | ||
| Mock Test-SEBNodeLoad -ModuleName LoadMonitor { | ||
| $script:legPoll++ | ||
| [PSCustomObject]@{ CanProceed = ($script:legPoll -ge 2); PlayerCount = 0; CpuPercent = 50; AvailableMemoryMB = 4000; Reasons = @() } | ||
| } | ||
| $gc = @{ load_awareness = @{ enabled = $true; on_high_load = 'defer'; defer_poll_interval_seconds = 45; defer_wait_minutes = 30 } } | ||
| $r = Wait-SEBNodeLoad -Session (New-FakeSession) -InstanceConfig @{} -GlobalConfig $gc | ||
| $r.CanProceed | Should -BeTrue | ||
| $r.PollCount | Should -Be 2 | ||
| Should -Invoke Start-Sleep -ModuleName LoadMonitor -Times 1 -Exactly |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Assert the legacy poll interval value, not just that a sleep happened.
This test still passes if defer_poll_interval_seconds is ignored and Wait-SEBNodeLoad falls back to the default interval, because it only checks the sleep count. Add a Start-Sleep parameter assertion so the legacy key is actually exercised.
Suggested assertion
- Should -Invoke Start-Sleep -ModuleName LoadMonitor -Times 1 -Exactly
+ Should -Invoke Start-Sleep -ModuleName LoadMonitor -Times 1 -Exactly -ParameterFilter {
+ $Seconds -eq 45
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| It 'honors the legacy defer_* config keys (defer_poll_interval_seconds / defer_wait_minutes)' { | |
| # The shipped names are check_interval_seconds / max_backoff_minutes; the older defer_* names | |
| # must still be accepted so existing operator configs keep working. We assert the loop still | |
| # polls + sleeps under ONLY the legacy keys (proving they were read, not ignored). | |
| $script:legPoll = 0 | |
| Mock Start-Sleep -ModuleName LoadMonitor {} | |
| Mock Test-SEBNodeLoad -ModuleName LoadMonitor { | |
| $script:legPoll++ | |
| [PSCustomObject]@{ CanProceed = ($script:legPoll -ge 2); PlayerCount = 0; CpuPercent = 50; AvailableMemoryMB = 4000; Reasons = @() } | |
| } | |
| $gc = @{ load_awareness = @{ enabled = $true; on_high_load = 'defer'; defer_poll_interval_seconds = 45; defer_wait_minutes = 30 } } | |
| $r = Wait-SEBNodeLoad -Session (New-FakeSession) -InstanceConfig @{} -GlobalConfig $gc | |
| $r.CanProceed | Should -BeTrue | |
| $r.PollCount | Should -Be 2 | |
| Should -Invoke Start-Sleep -ModuleName LoadMonitor -Times 1 -Exactly | |
| It 'honors the legacy defer_* config keys (defer_poll_interval_seconds / defer_wait_minutes)' { | |
| # The shipped names are check_interval_seconds / max_backoff_minutes; the older defer_* names | |
| # must still be accepted so existing operator configs keep working. We assert the loop still | |
| # polls + sleeps under ONLY the legacy keys (proving they were read, not ignored). | |
| $script:legPoll = 0 | |
| Mock Start-Sleep -ModuleName LoadMonitor {} | |
| Mock Test-SEBNodeLoad -ModuleName LoadMonitor { | |
| $script:legPoll++ | |
| [PSCustomObject]@{ CanProceed = ($script:legPoll -ge 2); PlayerCount = 0; CpuPercent = 50; AvailableMemoryMB = 4000; Reasons = @() } | |
| } | |
| $gc = @{ load_awareness = @{ enabled = $true; on_high_load = 'defer'; defer_poll_interval_seconds = 45; defer_wait_minutes = 30 } } | |
| $r = Wait-SEBNodeLoad -Session (New-FakeSession) -InstanceConfig @{} -GlobalConfig $gc | |
| $r.CanProceed | Should -BeTrue | |
| $r.PollCount | Should -Be 2 | |
| Should -Invoke Start-Sleep -ModuleName LoadMonitor -Times 1 -Exactly -ParameterFilter { | |
| $Seconds -eq 45 | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@Tests/LoadMonitor/LoadMonitor.Tests.ps1` around lines 339 - 353, The test in
Wait-SEBNodeLoad only verifies that Start-Sleep was called, so it can still pass
even if defer_poll_interval_seconds is ignored and the default interval is used.
Update the LoadMonitor.Tests.ps1 case for Wait-SEBNodeLoad to assert the actual
Start-Sleep argument/parameter value, ensuring the legacy defer_* config keys
are truly read; keep the existing mock setup and add a parameter check tied to
the sleep call.
| $j = [System.Runtime.Serialization.FormatterServices]::GetUninitializedObject( | ||
| [Microsoft.BackgroundIntelligentTransfer.Management.BitsJob]) |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Locate the CI workflow runner OS and whether BitsTransfer is imported anywhere before these tests.
fd -e yml -e yaml . .github 2>/dev/null | xargs -r rg -nC2 'runs-on|pwsh|Invoke-Pester'
rg -nP 'Import-Module\s+.*BitsTransfer' --glob '!Tests/**'Repository: SandboxServers/SEBackup
Length of output: 520
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the test file and surrounding mocks.
file='Tests/NetworkThrottle/BitsTransfer.Tests.ps1'
wc -l "$file"
cat -n "$file" | sed -n '1,220p'
# Find any BitsTransfer imports/usages in tests and module code.
rg -n --hidden --glob '!**/.git/**' 'BitsTransfer|Microsoft\.BackgroundIntelligentTransfer\.Management\.BitsJob|New-FakeBitsJob|GetUninitializedObject' .
# Check whether CI/build scripts import BitsTransfer explicitly.
rg -n --hidden --glob '!**/.git/**' 'Import-Module\s+BitsTransfer|BitsTransfer' .github build.ps1 *.ps1 Modules TestsRepository: SandboxServers/SEBackup
Length of output: 37578
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# If the test file is small enough, inspect relevant lines with context around the mocked scope.
sed -n '1,220p' Tests/NetworkThrottle/BitsTransfer.Tests.ps1Repository: SandboxServers/SEBackup
Length of output: 9958
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the test file and surrounding mocks.
file='Tests/NetworkThrottle/BitsTransfer.Tests.ps1'
wc -l "$file"
cat -n "$file" | sed -n '1,220p'
# Find any BitsTransfer imports/usages in tests and module code.
rg -n --hidden --glob '!**/.git/**' 'BitsTransfer|Microsoft\.BackgroundIntelligentTransfer\.Management\.BitsJob|New-FakeBitsJob|GetUninitializedObject' .
# Check whether CI/build scripts import BitsTransfer explicitly.
rg -n --hidden --glob '!**/.git/**' 'Import-Module\s+BitsTransfer|BitsTransfer' .github build.ps1 *.ps1 Modules TestsRepository: SandboxServers/SEBackup
Length of output: 37578
🌐 Web query:
BitsTransfer module Microsoft.BackgroundIntelligentTransfer.Management.BitsJob PowerShell 7 Windows-latest type resolution Import-Module mocked
💡 Result:
The BitsTransfer module is not natively compatible with PowerShell 7 because it relies on Windows PowerShell 5.1-specific components [1][2]. When you import BitsTransfer in PowerShell 7 (using -UseWindowsPowerShell), the system employs implicit remoting [3][4]. This process creates a hidden Windows PowerShell 5.1 background session to run the cmdlets, serializing the data sent to and from your PowerShell 7 session [3][5]. A significant technical limitation arises from this serialization: the Microsoft.BackgroundIntelligentTransfer.Management.BitsJob objects returned by cmdlets like Get-BitsTransfer are converted into "deserialized" objects [4][6][7]. Consequently, when you attempt to pass these deserialized objects to other BITS cmdlets (e.g., Suspend-BitsTransfer or Resume-BitsTransfer) in PowerShell 7, the commands fail to resolve the type, throwing errors such as: "Cannot convert the... value of type Deserialized.Microsoft.BackgroundIntelligentTransfer.Management.BitsJob to type Microsoft.BackgroundIntelligentTransfer.Management.BitsJob" [6][7]. To work around this limitation when mocking or scripting in PowerShell 7, consider the following strategies: 1. Run the entire logic within a single script block inside the remote PSSession using Invoke-Command, ensuring that objects are not serialized between the background session and your local session [6][7]. 2. If you are mocking for unit testing, avoid attempting to instantiate the real BitsJob type in PowerShell 7. Instead, mock the command output by returning a custom object (PSCustomObject) that simulates the necessary properties, or use a PSSession-based approach to isolate the interaction with the actual module [6][7]. Top results: [3][4][6][7][8]
Citations:
- 1: https://tfl09.blogspot.com/2019/08/many-things-go-well-with-powershell-7.html
- 2: https://www.techtarget.com/searchwindowsserver/tip/Windows-Compatibility-module-expands-PowerShell-Core-reach
- 3: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_windows_powershell_compatibility?view=powershell-7.6
- 4: https://yobyot.com/powershell/powershell-7-module-compatibility/2020/03/10/
- 5: https://petri.com/using-windows-powershell-modules-in-powershell-7/
- 6: [Bug] Suspend/Resume/Complete-BitsTransfer Parameter issue PowerShell/PowerShell#15553
- 7: BitsJob object can't be used by BITS-functions PowerShell/PowerShell#14948
- 8: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/import-module?view=powershell-7.6
Use a mockable fake instead of the concrete BitsJob type. New-FakeBitsJob depends on [Microsoft.BackgroundIntelligentTransfer.Management.BitsJob], but a mocked Import-Module BitsTransfer does not load that assembly, so this can fail on CI before the BITS paths run. A PSCustomObject double is enough for the mocked Get-BitsTransfer/Remove-BitsTransfer calls.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@Tests/NetworkThrottle/BitsTransfer.Tests.ps1` around lines 33 - 34, The test
helper in New-FakeBitsJob is using the concrete
Microsoft.BackgroundIntelligentTransfer.Management.BitsJob type, which can break
when the BitsTransfer module is mocked and the assembly is not loaded. Update
New-FakeBitsJob in BitsTransfer.Tests.ps1 to return a mockable fake object such
as a PSCustomObject that satisfies the Get-BitsTransfer and Remove-BitsTransfer
test expectations, and remove the dependency on
[Microsoft.BackgroundIntelligentTransfer.Management.BitsJob] so the mocked
Import-Module path works reliably.
| It 'honors -WhatIf: it does NOT call Register-ScheduledTask' { | ||
| Register-SEBScheduledTask -GlobalConfig $script:gc -WhatIf 3>$null | Out-Null | ||
| Should -Invoke Register-ScheduledTask -ModuleName SchedulerManager -Times 0 -Exactly | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Expand the -WhatIf case to cover existing-task overwrite.
This assertion only proves Register-ScheduledTask is skipped. It misses the dangerous path where an existing task is still deleted: Register-SEBScheduledTask currently calls Unregister-ScheduledTask before its ShouldProcess gate. Add an existing-task mock here and assert both unregister and register stay at 0 under -WhatIf.
Suggested test adjustment
It 'honors -WhatIf: it does NOT call Register-ScheduledTask' {
+ Mock Get-ScheduledTask -ModuleName SchedulerManager { [PSCustomObject]@{ TaskName = 'SEBackup-Scheduled' } }
Register-SEBScheduledTask -GlobalConfig $script:gc -WhatIf 3>$null | Out-Null
+ Should -Invoke Unregister-ScheduledTask -ModuleName SchedulerManager -Times 0 -Exactly
Should -Invoke Register-ScheduledTask -ModuleName SchedulerManager -Times 0 -Exactly
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| It 'honors -WhatIf: it does NOT call Register-ScheduledTask' { | |
| Register-SEBScheduledTask -GlobalConfig $script:gc -WhatIf 3>$null | Out-Null | |
| Should -Invoke Register-ScheduledTask -ModuleName SchedulerManager -Times 0 -Exactly | |
| } | |
| It 'honors -WhatIf: it does NOT call Register-ScheduledTask' { | |
| Mock Get-ScheduledTask -ModuleName SchedulerManager { [PSCustomObject]@{ TaskName = 'SEBackup-Scheduled' } } | |
| Register-SEBScheduledTask -GlobalConfig $script:gc -WhatIf 3>$null | Out-Null | |
| Should -Invoke Unregister-ScheduledTask -ModuleName SchedulerManager -Times 0 -Exactly | |
| Should -Invoke Register-ScheduledTask -ModuleName SchedulerManager -Times 0 -Exactly | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@Tests/SchedulerManager/SchedulerManager.Tests.ps1` around lines 193 - 196,
The current WhatIf test for Register-SEBScheduledTask only verifies
Register-ScheduledTask is skipped, but it does not cover the existing-task
overwrite path where Unregister-ScheduledTask may still run before the
ShouldProcess gate. Update the test in SchedulerManager.Tests.ps1 within the
Register-SEBScheduledTask WhatIf case to mock an existing task and assert both
Unregister-ScheduledTask and Register-ScheduledTask are invoked 0 times when
-WhatIf is used, so the behavior is covered for task replacement as well.
…-built scriptblock) (Copilot R2)
|
Note on #20 acceptance: MetricsCollector (Get-SEBDiskSpace / Get-SEBTrendIndicator / Get-SEBHealthSummary) is covered in the companion PR #59. #20's named modules were split across this PR (LoadMonitor / NotificationManager / SchedulerManager / NetworkThrottle) and #59 (MetricsCollector). Together #59 + #60 satisfy #20's acceptance. |
Implements #20 — behavioral tests for the four near-zero-coverage modules, mocking every infra boundary (WinRM/VSS/scheduled-tasks/BITS/network) so they run on GitHub-hosted CI. 107 new tests; no Integration-tagged escapes; build.ps1 BUILD OK.
Coverage before → after
Highlights
Test-SEBNodeLoadunder/at/over verdicts (CPU/mem/players),max_player_count=0sentinel, fail-open on CIM error, disabled short-circuit;Wait-SEBNodeLoadpoll/sleep mechanics proven deterministically (mockedStart-Sleep, exact counts — no real waiting).on_*gating, Success/Warning/Failure derivation.pwsh -File … -Allaction, Once+RepetitionInterval trigger, legacy.cred.xmlwarning,-WhatIf; status state-mapping + ISO-8601 interval parse. Doubles are real client-onlyCimInstances of the correct MSFT class.Copy-SEBThrottledstrategies (BITS-Low, robocopy/IPGfrom Mbps, Copy-Item fallback), exit-code 0–7 vs ≥8, async/priority/credential paths.Closes #20.
🤖 Generated with Claude Code
Summary by CodeRabbit