From 8a6c4f83613d3612b345fbebcea9ce5940d6af00 Mon Sep 17 00:00:00 2001 From: Mike Madeja Date: Thu, 24 Sep 2026 17:44:45 -0500 Subject: [PATCH 1/4] feat: add Invoke-PiHoleFlushLogs Implements POST /action/flush/logs, one of the two remaining "Actions" gaps from the API coverage audit. Flushes the DNS log file and purges the most recent 24 hours of query history from both the database and FTL's internal memory. The other gap, POST /action/flush/arp, is deprecated by Pi-hole itself in favor of /action/flush/network ("Deprecated! Use '/action/flush/network' instead."), which the module already implements via Invoke-PiHoleFlushNetwork - so it's intentionally not being added as a separate function. Also fixed a copy-paste bug found along the way: Invoke-PiHoleFlushNetwork's .DESCRIPTION described flushing a log file, which is what this new function actually does, not what flushing the network table does. Verified against a real Pi-hole v6 server: formatted output, RawOutput, and bad-password error handling. Added a dedicated integration test file. README regenerated. Co-Authored-By: Claude Sonnet 5 --- PiHoleShell/PiHoleShell.psm1 | 2 +- .../Public/Actions/Invoke-PiHoleFlushLogs.ps1 | 71 +++++++++++++++++++ .../Actions/Invoke-PiHoleFlushNetwork.ps1 | 2 +- README.md | 1 + ...voke-PiHoleFlushLogs.Integration.Tests.ps1 | 46 ++++++++++++ 5 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 PiHoleShell/Public/Actions/Invoke-PiHoleFlushLogs.ps1 create mode 100644 tests/Invoke-PiHoleFlushLogs.Integration.Tests.ps1 diff --git a/PiHoleShell/PiHoleShell.psm1 b/PiHoleShell/PiHoleShell.psm1 index 92b77e2..001e1ec 100644 --- a/PiHoleShell/PiHoleShell.psm1 +++ b/PiHoleShell/PiHoleShell.psm1 @@ -16,7 +16,7 @@ foreach ($File in $PrivateFunctions) { Export-ModuleMember -Function @( #Actions - 'Update-PiHoleActionsGravity', 'Invoke-PiHoleFlushNetwork', 'Restart-PiHoleDnsService' ` + 'Update-PiHoleActionsGravity', 'Invoke-PiHoleFlushNetwork', 'Invoke-PiHoleFlushLogs', 'Restart-PiHoleDnsService' ` #Authentication 'Remove-PiHoleCurrentAuthSession' , 'Get-PiHoleCurrentAuthSession', 'Remove-PiHoleAuthSession', ` #GroupManagement diff --git a/PiHoleShell/Public/Actions/Invoke-PiHoleFlushLogs.ps1 b/PiHoleShell/Public/Actions/Invoke-PiHoleFlushLogs.ps1 new file mode 100644 index 0000000..ec03eb8 --- /dev/null +++ b/PiHoleShell/Public/Actions/Invoke-PiHoleFlushLogs.ps1 @@ -0,0 +1,71 @@ +function Invoke-PiHoleFlushLogs { + <# +.SYNOPSIS +Flushes the DNS logs + +.DESCRIPTION +Flushes the Pi-hole DNS logs. This empties the DNS log file and purges the most recent 24 +hours of query history from both the long-term database and FTL's internal memory. + +.PARAMETER PiHoleServer +The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" + +.PARAMETER Password +The API Password you generated from your PiHole server + +.PARAMETER IgnoreSsl +Set to $true to skip SSL certificate validation + +.PARAMETER RawOutput +This will dump the response instead of the formatted object + +.EXAMPLE +Invoke-PiHoleFlushLogs -PiHoleServer "http://pihole.domain.com:8080" -Password "your-app-password" + #> + [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#post-/action/flush/logs')] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Flushes PiHole logs')] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "", Justification = "Logs matches the Pi-hole API's own endpoint name, /action/flush/logs")] + param ( + [Parameter(Mandatory = $true)] + [System.URI]$PiHoleServer, + [Parameter(Mandatory = $true)] + [string]$Password, + [bool]$IgnoreSsl = $false, + [bool]$RawOutput = $false + ) + + try { + $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl + + $Params = @{ + Headers = @{sid = $($Sid) } + Uri = "$($PiHoleServer.OriginalString)/api/action/flush/logs" + Method = "Post" + ContentType = "application/json" + SkipCertificateCheck = $IgnoreSsl + } + + $Response = Invoke-RestMethod @Params + + if ($RawOutput) { + Write-Output $Response + } + else { + $Object = [PSCustomObject]@{ + Status = "Flushed" + } + Write-Output $Object + } + } + + catch { + Write-Error -Message $_.Exception.Message + } + + finally { + if ($Sid) { + Remove-PiHoleCurrentAuthSession -PiHoleServer $PiHoleServer -Sid $Sid -IgnoreSsl $IgnoreSsl + } + } +} diff --git a/PiHoleShell/Public/Actions/Invoke-PiHoleFlushNetwork.ps1 b/PiHoleShell/Public/Actions/Invoke-PiHoleFlushNetwork.ps1 index 2c47c34..d361243 100644 --- a/PiHoleShell/Public/Actions/Invoke-PiHoleFlushNetwork.ps1 +++ b/PiHoleShell/Public/Actions/Invoke-PiHoleFlushNetwork.ps1 @@ -4,7 +4,7 @@ function Invoke-PiHoleFlushNetwork { Flushes the network table. This includes removing both all known devices and their associated addresses. .DESCRIPTION -Flushes the Pi-hole log file (/var/log/pihole/pihole.log). +Flushes Pi-hole's network table, removing all known devices and their associated addresses. .PARAMETER PiHoleServer The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" diff --git a/README.md b/README.md index 7180dec..2a7c11a 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,7 @@ Functions marked 🚧 are still under active development — signatures and outp | Function | Description | |---|---| +| `Invoke-PiHoleFlushLogs` | Flushes the DNS logs | | `Invoke-PiHoleFlushNetwork` | Flushes the network table. This includes removing both all known devices and their associated addresses. | | `Restart-PiHoleDnsService` | Restarts the pihole-FTL service | | `Update-PiHoleActionsGravity` | Update Pi-hole's adlists by running pihole -g | diff --git a/tests/Invoke-PiHoleFlushLogs.Integration.Tests.ps1 b/tests/Invoke-PiHoleFlushLogs.Integration.Tests.ps1 new file mode 100644 index 0000000..9a31e06 --- /dev/null +++ b/tests/Invoke-PiHoleFlushLogs.Integration.Tests.ps1 @@ -0,0 +1,46 @@ +# Requires -Module Pester +# +# Integration tests that call a REAL Pi-hole server. Configure tests/IntegrationConfig.local.ps1 +# (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically +# if that file is missing. + +# Config availability must be known at discovery time so the -Skip parameter on each It block +# (evaluated during discovery, before BeforeAll runs) sees the correct value. +$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') + +Describe 'Invoke-PiHoleFlushLogs (Integration)' -Tag 'Integration' { + BeforeAll { + Import-Module .\PiHoleShell\PiHoleShell.psm1 -Force + + # Recomputed here (not read from the discovery-time $script:ConfigAvailable above) because + # Pester runs discovery and run in separate scopes, so BeforeAll cannot see that value. + $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + if (Test-Path $configPath) { + . $configPath + $script:PiHoleServer = $PiHoleServer + $script:PiHoleToken = $PiHoleToken + $script:PiHoleIgnoreSsl = $PiHoleIgnoreSsl + } + } + + It 'flushes the DNS logs and returns a formatted status' -Skip:(-not $script:ConfigAvailable) { + $result = Invoke-PiHoleFlushLogs -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl + $result | Format-List | Out-String | Write-Host + + $result | Should -Not -BeNullOrEmpty + $result.Status | Should -Be 'Flushed' + } + + It 'returns the raw API response when RawOutput is set' -Skip:(-not $script:ConfigAvailable) { + $result = Invoke-PiHoleFlushLogs -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl -RawOutput $true + $result | Format-List | Out-String | Write-Host + + $result.status | Should -Be 'success' + } + + It 'errors when given a bad password' -Skip:(-not $script:ConfigAvailable) { + $result = Invoke-PiHoleFlushLogs -PiHoleServer $script:PiHoleServer -Password 'definitely-not-the-real-token' -IgnoreSsl $script:PiHoleIgnoreSsl -ErrorVariable errOut -ErrorAction SilentlyContinue + + $errOut | Should -Not -BeNullOrEmpty + } +} From 2c5d53f6d03fcf9f8467ebc683808f48ac5fcfd3 Mon Sep 17 00:00:00 2001 From: Mike Madeja Date: Thu, 24 Sep 2026 17:57:43 -0500 Subject: [PATCH 2/4] chore: reorg tests to mirror module structure, scope CI to changed files Moves every per-function test file from a flat tests/ directory into tests//, mirroring PiHoleShell/Public// exactly (e.g. PiHoleShell/Public/Actions/Invoke-PiHoleFlushNetwork.ps1 now pairs with tests/Actions/Invoke-PiHoleFlushNetwork.Integration.Tests.ps1). Shared support files (IntegrationConfig.example.ps1, IntegrationConfig.local.ps1, Initialize-PiHoleTestData.ps1) stay at tests/ root since they don't belong to any single function. Updated every moved file's $PSScriptRoot-relative path lookups for those shared files accordingly (Pester still discovers tests recursively by default, so no path change was needed on the Pester side). This mirroring is what makes the second change straightforward: the Azure DevOps pipeline now scopes PR builds to only the test file(s) matching whatever PiHoleShell/Public//.ps1 files actually changed, instead of always running the entire suite (which includes many real-server integration tests that individually take 10-40+ seconds). Direct pushes to develop/main still always run the full suite. On a PR build, anything that isn't a clean 1:1 function-to-test-file match falls back to the full suite rather than risk silently skipping coverage: changes to Private/ files, PiHoleShell.psm1/.psd1, the shared Request-PiHoleAuth helper (used by every function), the shared test helpers, or a failure computing the diff itself. Changed test files run directly; non-code changes (README, workflows, tools/) are ignored. Verified the scoping logic locally against real git diffs before trusting it in CI, and re-ran a representative slice of the moved integration tests against the real Pi-hole server to confirm the path fixes work end-to-end. Co-Authored-By: Claude Sonnet 5 --- azuredevops-pihole-pester-tests.yml | 67 ++++++++++++++++++- ...e-PiHoleFlushNetwork.Integration.Tests.ps1 | 4 +- ...art-PiHoleDnsService.Integration.Tests.ps1 | 4 +- ...PiHoleActionsGravity.Integration.Tests.ps1 | 4 +- ...leCurrentAuthSession.Integration.Tests.ps1 | 4 +- .../Get-PiHoleConfig.Integration.Tests.ps1 | 4 +- ...oleDnsBlockingStatus.Integration.Tests.ps1 | 4 +- .../Set-PiHoleDnsBlocking.Tests.ps1 | 0 .../Get-PiHoleInfoHost.Integration.Tests.ps1 | 4 +- ...et-PiHoleInfoMessage.Integration.Tests.ps1 | 4 +- .../Get-PiHoleGroup.Integration.Tests.ps1 | 4 +- .../New-PiHoleGroup.Integration.Tests.ps1 | 4 +- .../Remove-PiHoleGroup.Integration.Tests.ps1 | 4 +- .../Update-PiHoleGroup.Integration.Tests.ps1 | 4 +- .../Get-PiHoleHistory.Integration.Tests.ps1 | 6 +- ...-PiHoleHistoryClient.Integration.Tests.ps1 | 6 +- ...iHoleHistoryDatabase.Integration.Tests.ps1 | 4 +- ...istoryDatabaseClient.Integration.Tests.ps1 | 4 +- .../Add-PiHoleList.Integration.Tests.ps1 | 4 +- .../Get-PiHoleList.Integration.Tests.ps1 | 4 +- .../Remove-PiHoleList.Integration.Tests.ps1 | 4 +- ...atsDatabaseQueryType.Integration.Tests.ps1 | 6 +- ...StatsDatabaseSummary.Integration.Tests.ps1 | 6 +- ...atsDatabaseTopClient.Integration.Tests.ps1 | 6 +- ...atsDatabaseTopDomain.Integration.Tests.ps1 | 6 +- ...tatsDatabaseUpstream.Integration.Tests.ps1 | 6 +- ...tatsQuerySuggestions.Integration.Tests.ps1 | 6 +- ...PiHoleStatsQueryType.Integration.Tests.ps1 | 6 +- ...leStatsRecentBlocked.Integration.Tests.ps1 | 6 +- ...t-PiHoleStatsSummary.Integration.Tests.ps1 | 6 +- ...PiHoleStatsTopClient.Integration.Tests.ps1 | 6 +- ...PiHoleStatsTopDomain.Integration.Tests.ps1 | 6 +- ...-PiHoleStatsUpstream.Integration.Tests.ps1 | 6 +- .../Get-PiHolePadd.Integration.Tests.ps1 | 6 +- 34 files changed, 145 insertions(+), 80 deletions(-) rename tests/{ => Actions}/Invoke-PiHoleFlushNetwork.Integration.Tests.ps1 (90%) rename tests/{ => Actions}/Restart-PiHoleDnsService.Integration.Tests.ps1 (91%) rename tests/{ => Actions}/Update-PiHoleActionsGravity.Integration.Tests.ps1 (92%) rename tests/{ => Authentication}/Get-PiHoleCurrentAuthSession.Integration.Tests.ps1 (89%) rename tests/{ => Config}/Get-PiHoleConfig.Integration.Tests.ps1 (89%) rename tests/{ => DnsControl}/Get-PiHoleDnsBlockingStatus.Integration.Tests.ps1 (89%) rename tests/{ => DnsControl}/Set-PiHoleDnsBlocking.Tests.ps1 (100%) rename tests/{ => FTLInformation}/Get-PiHoleInfoHost.Integration.Tests.ps1 (89%) rename tests/{ => FTLInformation}/Get-PiHoleInfoMessage.Integration.Tests.ps1 (89%) rename tests/{ => GroupManagement}/Get-PiHoleGroup.Integration.Tests.ps1 (89%) rename tests/{ => GroupManagement}/New-PiHoleGroup.Integration.Tests.ps1 (94%) rename tests/{ => GroupManagement}/Remove-PiHoleGroup.Integration.Tests.ps1 (95%) rename tests/{ => GroupManagement}/Update-PiHoleGroup.Integration.Tests.ps1 (96%) rename tests/{ => History}/Get-PiHoleHistory.Integration.Tests.ps1 (84%) rename tests/{ => History}/Get-PiHoleHistoryClient.Integration.Tests.ps1 (85%) rename tests/{ => History}/Get-PiHoleHistoryDatabase.Integration.Tests.ps1 (92%) rename tests/{ => History}/Get-PiHoleHistoryDatabaseClient.Integration.Tests.ps1 (92%) rename tests/{ => ListManagement}/Add-PiHoleList.Integration.Tests.ps1 (95%) rename tests/{ => ListManagement}/Get-PiHoleList.Integration.Tests.ps1 (88%) rename tests/{ => ListManagement}/Remove-PiHoleList.Integration.Tests.ps1 (94%) rename tests/{ => Metrics}/Get-PiHoleStatsDatabaseQueryType.Integration.Tests.ps1 (89%) rename tests/{ => Metrics}/Get-PiHoleStatsDatabaseSummary.Integration.Tests.ps1 (89%) rename tests/{ => Metrics}/Get-PiHoleStatsDatabaseTopClient.Integration.Tests.ps1 (88%) rename tests/{ => Metrics}/Get-PiHoleStatsDatabaseTopDomain.Integration.Tests.ps1 (88%) rename tests/{ => Metrics}/Get-PiHoleStatsDatabaseUpstream.Integration.Tests.ps1 (89%) rename tests/{ => Metrics}/Get-PiHoleStatsQuerySuggestions.Integration.Tests.ps1 (87%) rename tests/{ => Metrics}/Get-PiHoleStatsQueryType.Integration.Tests.ps1 (85%) rename tests/{ => Metrics}/Get-PiHoleStatsRecentBlocked.Integration.Tests.ps1 (85%) rename tests/{ => Metrics}/Get-PiHoleStatsSummary.Integration.Tests.ps1 (86%) rename tests/{ => Metrics}/Get-PiHoleStatsTopClient.Integration.Tests.ps1 (84%) rename tests/{ => Metrics}/Get-PiHoleStatsTopDomain.Integration.Tests.ps1 (84%) rename tests/{ => Metrics}/Get-PiHoleStatsUpstream.Integration.Tests.ps1 (85%) rename tests/{ => Padd}/Get-PiHolePadd.Integration.Tests.ps1 (84%) diff --git a/azuredevops-pihole-pester-tests.yml b/azuredevops-pihole-pester-tests.yml index f38567b..8c31543 100644 --- a/azuredevops-pihole-pester-tests.yml +++ b/azuredevops-pihole-pester-tests.yml @@ -46,14 +46,79 @@ steps: - pwsh: | Import-Module Pester -MinimumVersion 5.0.0 -Force + # On a PR build, scope the run to tests for the files that actually changed - tests/ mirrors + # PiHoleShell/Public// 1:1, so a changed function maps directly to its test file(s). + # Any ambiguity (shared/private code, module manifest, shared test helpers, or the diff itself + # failing) falls back to the full suite rather than risk silently skipping real coverage. + # Direct pushes to develop/main (not PR builds) always run the full suite. + $runFullSuite = $true + $testPaths = [System.Collections.Generic.List[string]]::new() + + if ($env:BUILD_REASON -eq 'PullRequest') { + try { + $targetBranch = $env:SYSTEM_PULLREQUEST_TARGETBRANCH -replace '^refs/heads/', '' + git fetch origin $targetBranch --quiet + if ($LASTEXITCODE -ne 0) { throw "git fetch failed for '$targetBranch'" } + + $changedFiles = git diff --name-only "origin/$targetBranch...HEAD" + if ($LASTEXITCODE -ne 0) { throw "git diff failed against 'origin/$targetBranch'" } + + if ($changedFiles) { + $runFullSuite = $false + + foreach ($file in $changedFiles) { + if ($runFullSuite) { break } + + if ($file -match '^PiHoleShell/Private/' -or + $file -eq 'PiHoleShell/PiHoleShell.psm1' -or + $file -eq 'PiHoleShell/PiHoleShell.psd1' -or + $file -eq 'PiHoleShell/Public/Authentication/Request-PiHoleAuth.ps1' -or + $file -eq 'tests/Initialize-PiHoleTestData.ps1' -or + $file -eq 'tests/IntegrationConfig.example.ps1') { + Write-Host "Shared/core file changed ($file) - running the full suite" + $runFullSuite = $true + } + elseif ($file -match '^PiHoleShell/Public/([^/]+)/([^/]+)\.ps1$') { + $category = $Matches[1] + $function = $Matches[2] + $testDir = "tests/$category" + if (Test-Path $testDir) { + Get-ChildItem -Path $testDir -Filter "$function.*Tests.ps1" | ForEach-Object { + $testPaths.Add($_.FullName) + } + } + } + elseif ($file -match '^tests/.*\.Tests\.ps1$' -and (Test-Path $file)) { + $testPaths.Add((Resolve-Path $file).Path) + } + # Anything else (README, workflows, tools/, etc.) has no test impact - ignored. + } + } + } + catch { + Write-Warning "Could not compute changed-file test scope, falling back to the full suite: $($_.Exception.Message)" + $runFullSuite = $true + } + } + $config = New-PesterConfiguration - $config.Run.Path = './tests' $config.Run.Exit = $true $config.Output.Verbosity = 'Detailed' $config.TestResult.Enabled = $true $config.TestResult.OutputFormat = 'NUnitXml' $config.TestResult.OutputPath = '$(testResultsFile)' + $testPaths = $testPaths | Select-Object -Unique + if ($runFullSuite -or $testPaths.Count -eq 0) { + Write-Host "Running the full test suite" + $config.Run.Path = './tests' + } + else { + Write-Host "Running scoped tests for changed files:" + $testPaths | ForEach-Object { Write-Host " $_" } + $config.Run.Path = $testPaths + } + Invoke-Pester -Configuration $config displayName: 'Run Pester tests' workingDirectory: '$(System.DefaultWorkingDirectory)' diff --git a/tests/Invoke-PiHoleFlushNetwork.Integration.Tests.ps1 b/tests/Actions/Invoke-PiHoleFlushNetwork.Integration.Tests.ps1 similarity index 90% rename from tests/Invoke-PiHoleFlushNetwork.Integration.Tests.ps1 rename to tests/Actions/Invoke-PiHoleFlushNetwork.Integration.Tests.ps1 index c461e9a..7e191cb 100644 --- a/tests/Invoke-PiHoleFlushNetwork.Integration.Tests.ps1 +++ b/tests/Actions/Invoke-PiHoleFlushNetwork.Integration.Tests.ps1 @@ -6,7 +6,7 @@ # Config availability must be known at discovery time so the -Skip parameter on each It block # (evaluated during discovery, before BeforeAll runs) sees the correct value. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Invoke-PiHoleFlushNetwork (Integration)' -Tag 'Integration' { BeforeAll { @@ -14,7 +14,7 @@ Describe 'Invoke-PiHoleFlushNetwork (Integration)' -Tag 'Integration' { # Recomputed here (not read from the discovery-time $script:ConfigAvailable above) because # Pester runs discovery and run in separate scopes, so BeforeAll cannot see that value. - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer diff --git a/tests/Restart-PiHoleDnsService.Integration.Tests.ps1 b/tests/Actions/Restart-PiHoleDnsService.Integration.Tests.ps1 similarity index 91% rename from tests/Restart-PiHoleDnsService.Integration.Tests.ps1 rename to tests/Actions/Restart-PiHoleDnsService.Integration.Tests.ps1 index 90f4a3f..e2ecd8e 100644 --- a/tests/Restart-PiHoleDnsService.Integration.Tests.ps1 +++ b/tests/Actions/Restart-PiHoleDnsService.Integration.Tests.ps1 @@ -9,7 +9,7 @@ # Config availability must be known at discovery time so the -Skip parameter on each It block # (evaluated during discovery, before BeforeAll runs) sees the correct value. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Restart-PiHoleDnsService (Integration)' -Tag 'Integration' { BeforeAll { @@ -17,7 +17,7 @@ Describe 'Restart-PiHoleDnsService (Integration)' -Tag 'Integration' { # Recomputed here (not read from the discovery-time $script:ConfigAvailable above) because # Pester runs discovery and run in separate scopes, so BeforeAll cannot see that value. - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer diff --git a/tests/Update-PiHoleActionsGravity.Integration.Tests.ps1 b/tests/Actions/Update-PiHoleActionsGravity.Integration.Tests.ps1 similarity index 92% rename from tests/Update-PiHoleActionsGravity.Integration.Tests.ps1 rename to tests/Actions/Update-PiHoleActionsGravity.Integration.Tests.ps1 index ca0aaa8..da81455 100644 --- a/tests/Update-PiHoleActionsGravity.Integration.Tests.ps1 +++ b/tests/Actions/Update-PiHoleActionsGravity.Integration.Tests.ps1 @@ -9,7 +9,7 @@ # Config availability must be known at discovery time so the -Skip parameter on each It block # (evaluated during discovery, before BeforeAll runs) sees the correct value. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Update-PiHoleActionsGravity (Integration)' -Tag 'Integration' { BeforeAll { @@ -17,7 +17,7 @@ Describe 'Update-PiHoleActionsGravity (Integration)' -Tag 'Integration' { # Recomputed here (not read from the discovery-time $script:ConfigAvailable above) because # Pester runs discovery and run in separate scopes, so BeforeAll cannot see that value. - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer diff --git a/tests/Get-PiHoleCurrentAuthSession.Integration.Tests.ps1 b/tests/Authentication/Get-PiHoleCurrentAuthSession.Integration.Tests.ps1 similarity index 89% rename from tests/Get-PiHoleCurrentAuthSession.Integration.Tests.ps1 rename to tests/Authentication/Get-PiHoleCurrentAuthSession.Integration.Tests.ps1 index 64f29d4..ad41887 100644 --- a/tests/Get-PiHoleCurrentAuthSession.Integration.Tests.ps1 +++ b/tests/Authentication/Get-PiHoleCurrentAuthSession.Integration.Tests.ps1 @@ -4,13 +4,13 @@ # (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically # if that file is missing. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Get-PiHoleCurrentAuthSession (Integration)' -Tag 'Integration' { BeforeAll { Import-Module .\PiHoleShell\PiHoleShell.psm1 -Force - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer diff --git a/tests/Get-PiHoleConfig.Integration.Tests.ps1 b/tests/Config/Get-PiHoleConfig.Integration.Tests.ps1 similarity index 89% rename from tests/Get-PiHoleConfig.Integration.Tests.ps1 rename to tests/Config/Get-PiHoleConfig.Integration.Tests.ps1 index 0f6dc74..4461c04 100644 --- a/tests/Get-PiHoleConfig.Integration.Tests.ps1 +++ b/tests/Config/Get-PiHoleConfig.Integration.Tests.ps1 @@ -4,13 +4,13 @@ # (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically # if that file is missing. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Get-PiHoleConfig (Integration)' -Tag 'Integration' { BeforeAll { Import-Module .\PiHoleShell\PiHoleShell.psm1 -Force - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer diff --git a/tests/Get-PiHoleDnsBlockingStatus.Integration.Tests.ps1 b/tests/DnsControl/Get-PiHoleDnsBlockingStatus.Integration.Tests.ps1 similarity index 89% rename from tests/Get-PiHoleDnsBlockingStatus.Integration.Tests.ps1 rename to tests/DnsControl/Get-PiHoleDnsBlockingStatus.Integration.Tests.ps1 index 23592c1..8b8d75a 100644 --- a/tests/Get-PiHoleDnsBlockingStatus.Integration.Tests.ps1 +++ b/tests/DnsControl/Get-PiHoleDnsBlockingStatus.Integration.Tests.ps1 @@ -4,13 +4,13 @@ # (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically # if that file is missing. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Get-PiHoleDnsBlockingStatus (Integration)' -Tag 'Integration' { BeforeAll { Import-Module .\PiHoleShell\PiHoleShell.psm1 -Force - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer diff --git a/tests/Set-PiHoleDnsBlocking.Tests.ps1 b/tests/DnsControl/Set-PiHoleDnsBlocking.Tests.ps1 similarity index 100% rename from tests/Set-PiHoleDnsBlocking.Tests.ps1 rename to tests/DnsControl/Set-PiHoleDnsBlocking.Tests.ps1 diff --git a/tests/Get-PiHoleInfoHost.Integration.Tests.ps1 b/tests/FTLInformation/Get-PiHoleInfoHost.Integration.Tests.ps1 similarity index 89% rename from tests/Get-PiHoleInfoHost.Integration.Tests.ps1 rename to tests/FTLInformation/Get-PiHoleInfoHost.Integration.Tests.ps1 index 3ca7e8a..5d4a7f4 100644 --- a/tests/Get-PiHoleInfoHost.Integration.Tests.ps1 +++ b/tests/FTLInformation/Get-PiHoleInfoHost.Integration.Tests.ps1 @@ -4,13 +4,13 @@ # (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically # if that file is missing. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Get-PiHoleInfoHost (Integration)' -Tag 'Integration' { BeforeAll { Import-Module .\PiHoleShell\PiHoleShell.psm1 -Force - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer diff --git a/tests/Get-PiHoleInfoMessage.Integration.Tests.ps1 b/tests/FTLInformation/Get-PiHoleInfoMessage.Integration.Tests.ps1 similarity index 89% rename from tests/Get-PiHoleInfoMessage.Integration.Tests.ps1 rename to tests/FTLInformation/Get-PiHoleInfoMessage.Integration.Tests.ps1 index 4acc18f..d95e2ba 100644 --- a/tests/Get-PiHoleInfoMessage.Integration.Tests.ps1 +++ b/tests/FTLInformation/Get-PiHoleInfoMessage.Integration.Tests.ps1 @@ -4,13 +4,13 @@ # (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically # if that file is missing. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Get-PiHoleInfoMessage (Integration)' -Tag 'Integration' { BeforeAll { Import-Module .\PiHoleShell\PiHoleShell.psm1 -Force - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer diff --git a/tests/Get-PiHoleGroup.Integration.Tests.ps1 b/tests/GroupManagement/Get-PiHoleGroup.Integration.Tests.ps1 similarity index 89% rename from tests/Get-PiHoleGroup.Integration.Tests.ps1 rename to tests/GroupManagement/Get-PiHoleGroup.Integration.Tests.ps1 index 89c564f..28094b1 100644 --- a/tests/Get-PiHoleGroup.Integration.Tests.ps1 +++ b/tests/GroupManagement/Get-PiHoleGroup.Integration.Tests.ps1 @@ -4,13 +4,13 @@ # (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically # if that file is missing. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Get-PiHoleGroup (Integration)' -Tag 'Integration' { BeforeAll { Import-Module .\PiHoleShell\PiHoleShell.psm1 -Force - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer diff --git a/tests/New-PiHoleGroup.Integration.Tests.ps1 b/tests/GroupManagement/New-PiHoleGroup.Integration.Tests.ps1 similarity index 94% rename from tests/New-PiHoleGroup.Integration.Tests.ps1 rename to tests/GroupManagement/New-PiHoleGroup.Integration.Tests.ps1 index bd9740d..486b332 100644 --- a/tests/New-PiHoleGroup.Integration.Tests.ps1 +++ b/tests/GroupManagement/New-PiHoleGroup.Integration.Tests.ps1 @@ -4,7 +4,7 @@ # (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically # if that file is missing. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'New-PiHoleGroup (Integration)' -Tag 'Integration' { BeforeAll { @@ -12,7 +12,7 @@ Describe 'New-PiHoleGroup (Integration)' -Tag 'Integration' { $script:TestGroupName = 'PesterGroup' - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer diff --git a/tests/Remove-PiHoleGroup.Integration.Tests.ps1 b/tests/GroupManagement/Remove-PiHoleGroup.Integration.Tests.ps1 similarity index 95% rename from tests/Remove-PiHoleGroup.Integration.Tests.ps1 rename to tests/GroupManagement/Remove-PiHoleGroup.Integration.Tests.ps1 index cacc416..5bb76e8 100644 --- a/tests/Remove-PiHoleGroup.Integration.Tests.ps1 +++ b/tests/GroupManagement/Remove-PiHoleGroup.Integration.Tests.ps1 @@ -4,7 +4,7 @@ # (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically # if that file is missing. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Remove-PiHoleGroup (Integration)' -Tag 'Integration' { BeforeAll { @@ -12,7 +12,7 @@ Describe 'Remove-PiHoleGroup (Integration)' -Tag 'Integration' { $script:TestGroupName = 'PesterGroup' - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer diff --git a/tests/Update-PiHoleGroup.Integration.Tests.ps1 b/tests/GroupManagement/Update-PiHoleGroup.Integration.Tests.ps1 similarity index 96% rename from tests/Update-PiHoleGroup.Integration.Tests.ps1 rename to tests/GroupManagement/Update-PiHoleGroup.Integration.Tests.ps1 index a802039..2dd526c 100644 --- a/tests/Update-PiHoleGroup.Integration.Tests.ps1 +++ b/tests/GroupManagement/Update-PiHoleGroup.Integration.Tests.ps1 @@ -4,7 +4,7 @@ # (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically # if that file is missing. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Update-PiHoleGroup (Integration)' -Tag 'Integration' { BeforeAll { @@ -12,7 +12,7 @@ Describe 'Update-PiHoleGroup (Integration)' -Tag 'Integration' { $script:TestGroupName = 'PesterGroup' - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer diff --git a/tests/Get-PiHoleHistory.Integration.Tests.ps1 b/tests/History/Get-PiHoleHistory.Integration.Tests.ps1 similarity index 84% rename from tests/Get-PiHoleHistory.Integration.Tests.ps1 rename to tests/History/Get-PiHoleHistory.Integration.Tests.ps1 index f37a0ad..aef611b 100644 --- a/tests/Get-PiHoleHistory.Integration.Tests.ps1 +++ b/tests/History/Get-PiHoleHistory.Integration.Tests.ps1 @@ -4,13 +4,13 @@ # (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically # if that file is missing. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Get-PiHoleHistory (Integration)' -Tag 'Integration' { BeforeAll { Import-Module .\PiHoleShell\PiHoleShell.psm1 -Force - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer @@ -18,7 +18,7 @@ Describe 'Get-PiHoleHistory (Integration)' -Tag 'Integration' { $script:PiHoleIgnoreSsl = $PiHoleIgnoreSsl # Generates some real query traffic so live history isn't all zero/empty. - & (Join-Path $PSScriptRoot 'Initialize-PiHoleTestData.ps1') -DnsServer $PiHoleServer.Host + & (Join-Path (Split-Path $PSScriptRoot -Parent) 'Initialize-PiHoleTestData.ps1') -DnsServer $PiHoleServer.Host } } diff --git a/tests/Get-PiHoleHistoryClient.Integration.Tests.ps1 b/tests/History/Get-PiHoleHistoryClient.Integration.Tests.ps1 similarity index 85% rename from tests/Get-PiHoleHistoryClient.Integration.Tests.ps1 rename to tests/History/Get-PiHoleHistoryClient.Integration.Tests.ps1 index ae95ddc..d49f002 100644 --- a/tests/Get-PiHoleHistoryClient.Integration.Tests.ps1 +++ b/tests/History/Get-PiHoleHistoryClient.Integration.Tests.ps1 @@ -4,13 +4,13 @@ # (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically # if that file is missing. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Get-PiHoleHistoryClient (Integration)' -Tag 'Integration' { BeforeAll { Import-Module .\PiHoleShell\PiHoleShell.psm1 -Force - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer @@ -18,7 +18,7 @@ Describe 'Get-PiHoleHistoryClient (Integration)' -Tag 'Integration' { $script:PiHoleIgnoreSsl = $PiHoleIgnoreSsl # Generates some real query traffic so live client history isn't all zero/empty. - & (Join-Path $PSScriptRoot 'Initialize-PiHoleTestData.ps1') -DnsServer $PiHoleServer.Host + & (Join-Path (Split-Path $PSScriptRoot -Parent) 'Initialize-PiHoleTestData.ps1') -DnsServer $PiHoleServer.Host } } diff --git a/tests/Get-PiHoleHistoryDatabase.Integration.Tests.ps1 b/tests/History/Get-PiHoleHistoryDatabase.Integration.Tests.ps1 similarity index 92% rename from tests/Get-PiHoleHistoryDatabase.Integration.Tests.ps1 rename to tests/History/Get-PiHoleHistoryDatabase.Integration.Tests.ps1 index f036dbc..6cc19b8 100644 --- a/tests/Get-PiHoleHistoryDatabase.Integration.Tests.ps1 +++ b/tests/History/Get-PiHoleHistoryDatabase.Integration.Tests.ps1 @@ -4,13 +4,13 @@ # (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically # if that file is missing. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Get-PiHoleHistoryDatabase (Integration)' -Tag 'Integration' { BeforeAll { Import-Module .\PiHoleShell\PiHoleShell.psm1 -Force - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer diff --git a/tests/Get-PiHoleHistoryDatabaseClient.Integration.Tests.ps1 b/tests/History/Get-PiHoleHistoryDatabaseClient.Integration.Tests.ps1 similarity index 92% rename from tests/Get-PiHoleHistoryDatabaseClient.Integration.Tests.ps1 rename to tests/History/Get-PiHoleHistoryDatabaseClient.Integration.Tests.ps1 index d9f14e9..173e188 100644 --- a/tests/Get-PiHoleHistoryDatabaseClient.Integration.Tests.ps1 +++ b/tests/History/Get-PiHoleHistoryDatabaseClient.Integration.Tests.ps1 @@ -4,13 +4,13 @@ # (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically # if that file is missing. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Get-PiHoleHistoryDatabaseClient (Integration)' -Tag 'Integration' { BeforeAll { Import-Module .\PiHoleShell\PiHoleShell.psm1 -Force - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer diff --git a/tests/Add-PiHoleList.Integration.Tests.ps1 b/tests/ListManagement/Add-PiHoleList.Integration.Tests.ps1 similarity index 95% rename from tests/Add-PiHoleList.Integration.Tests.ps1 rename to tests/ListManagement/Add-PiHoleList.Integration.Tests.ps1 index da428c5..e63ed8f 100644 --- a/tests/Add-PiHoleList.Integration.Tests.ps1 +++ b/tests/ListManagement/Add-PiHoleList.Integration.Tests.ps1 @@ -4,7 +4,7 @@ # (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically # if that file is missing. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Add-PiHoleList (Integration)' -Tag 'Integration' { BeforeAll { @@ -12,7 +12,7 @@ Describe 'Add-PiHoleList (Integration)' -Tag 'Integration' { $script:TestListAddress = 'https://blocklistproject.github.io/Lists/alt-version/ransomware-nl.txt' - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer diff --git a/tests/Get-PiHoleList.Integration.Tests.ps1 b/tests/ListManagement/Get-PiHoleList.Integration.Tests.ps1 similarity index 88% rename from tests/Get-PiHoleList.Integration.Tests.ps1 rename to tests/ListManagement/Get-PiHoleList.Integration.Tests.ps1 index cfe219f..d1af439 100644 --- a/tests/Get-PiHoleList.Integration.Tests.ps1 +++ b/tests/ListManagement/Get-PiHoleList.Integration.Tests.ps1 @@ -4,13 +4,13 @@ # (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically # if that file is missing. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Get-PiHoleList (Integration)' -Tag 'Integration' { BeforeAll { Import-Module .\PiHoleShell\PiHoleShell.psm1 -Force - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer diff --git a/tests/Remove-PiHoleList.Integration.Tests.ps1 b/tests/ListManagement/Remove-PiHoleList.Integration.Tests.ps1 similarity index 94% rename from tests/Remove-PiHoleList.Integration.Tests.ps1 rename to tests/ListManagement/Remove-PiHoleList.Integration.Tests.ps1 index d49ea9e..9f54269 100644 --- a/tests/Remove-PiHoleList.Integration.Tests.ps1 +++ b/tests/ListManagement/Remove-PiHoleList.Integration.Tests.ps1 @@ -4,7 +4,7 @@ # (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically # if that file is missing. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Remove-PiHoleList (Integration)' -Tag 'Integration' { BeforeAll { @@ -12,7 +12,7 @@ Describe 'Remove-PiHoleList (Integration)' -Tag 'Integration' { $script:TestListAddress = 'https://blocklistproject.github.io/Lists/alt-version/ransomware-nl.txt' - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer diff --git a/tests/Get-PiHoleStatsDatabaseQueryType.Integration.Tests.ps1 b/tests/Metrics/Get-PiHoleStatsDatabaseQueryType.Integration.Tests.ps1 similarity index 89% rename from tests/Get-PiHoleStatsDatabaseQueryType.Integration.Tests.ps1 rename to tests/Metrics/Get-PiHoleStatsDatabaseQueryType.Integration.Tests.ps1 index 6bcc515..ecad36e 100644 --- a/tests/Get-PiHoleStatsDatabaseQueryType.Integration.Tests.ps1 +++ b/tests/Metrics/Get-PiHoleStatsDatabaseQueryType.Integration.Tests.ps1 @@ -4,13 +4,13 @@ # (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically # if that file is missing. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Get-PiHoleStatsDatabaseQueryType (Integration)' -Tag 'Integration' { BeforeAll { Import-Module .\PiHoleShell\PiHoleShell.psm1 -Force - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer @@ -20,7 +20,7 @@ Describe 'Get-PiHoleStatsDatabaseQueryType (Integration)' -Tag 'Integration' { # Generates some real query traffic. Live stats reflect it immediately; the on-disk # database stats this file tests only reflect it once FTL's periodic flush runs, so # this mainly helps build up real history across repeated runs, not this run's own data. - & (Join-Path $PSScriptRoot 'Initialize-PiHoleTestData.ps1') -DnsServer $PiHoleServer.Host + & (Join-Path (Split-Path $PSScriptRoot -Parent) 'Initialize-PiHoleTestData.ps1') -DnsServer $PiHoleServer.Host } # The API rejects from=0 (epoch) with a 400, so use a recent, valid window instead. diff --git a/tests/Get-PiHoleStatsDatabaseSummary.Integration.Tests.ps1 b/tests/Metrics/Get-PiHoleStatsDatabaseSummary.Integration.Tests.ps1 similarity index 89% rename from tests/Get-PiHoleStatsDatabaseSummary.Integration.Tests.ps1 rename to tests/Metrics/Get-PiHoleStatsDatabaseSummary.Integration.Tests.ps1 index 4027ca6..6bd62e7 100644 --- a/tests/Get-PiHoleStatsDatabaseSummary.Integration.Tests.ps1 +++ b/tests/Metrics/Get-PiHoleStatsDatabaseSummary.Integration.Tests.ps1 @@ -4,13 +4,13 @@ # (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically # if that file is missing. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Get-PiHoleStatsDatabaseSummary (Integration)' -Tag 'Integration' { BeforeAll { Import-Module .\PiHoleShell\PiHoleShell.psm1 -Force - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer @@ -20,7 +20,7 @@ Describe 'Get-PiHoleStatsDatabaseSummary (Integration)' -Tag 'Integration' { # Generates some real query traffic. Live stats reflect it immediately; the on-disk # database stats this file tests only reflect it once FTL's periodic flush runs, so # this mainly helps build up real history across repeated runs, not this run's own data. - & (Join-Path $PSScriptRoot 'Initialize-PiHoleTestData.ps1') -DnsServer $PiHoleServer.Host + & (Join-Path (Split-Path $PSScriptRoot -Parent) 'Initialize-PiHoleTestData.ps1') -DnsServer $PiHoleServer.Host } # The API rejects from=0 (epoch) with a 400, so use a recent, valid window instead. diff --git a/tests/Get-PiHoleStatsDatabaseTopClient.Integration.Tests.ps1 b/tests/Metrics/Get-PiHoleStatsDatabaseTopClient.Integration.Tests.ps1 similarity index 88% rename from tests/Get-PiHoleStatsDatabaseTopClient.Integration.Tests.ps1 rename to tests/Metrics/Get-PiHoleStatsDatabaseTopClient.Integration.Tests.ps1 index 9d7120f..01e83d4 100644 --- a/tests/Get-PiHoleStatsDatabaseTopClient.Integration.Tests.ps1 +++ b/tests/Metrics/Get-PiHoleStatsDatabaseTopClient.Integration.Tests.ps1 @@ -4,13 +4,13 @@ # (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically # if that file is missing. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Get-PiHoleStatsDatabaseTopClient (Integration)' -Tag 'Integration' { BeforeAll { Import-Module .\PiHoleShell\PiHoleShell.psm1 -Force - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer @@ -20,7 +20,7 @@ Describe 'Get-PiHoleStatsDatabaseTopClient (Integration)' -Tag 'Integration' { # Generates some real query traffic. Live stats reflect it immediately; the on-disk # database stats this file tests only reflect it once FTL's periodic flush runs, so # this mainly helps build up real history across repeated runs, not this run's own data. - & (Join-Path $PSScriptRoot 'Initialize-PiHoleTestData.ps1') -DnsServer $PiHoleServer.Host + & (Join-Path (Split-Path $PSScriptRoot -Parent) 'Initialize-PiHoleTestData.ps1') -DnsServer $PiHoleServer.Host } # The API rejects from=0 (epoch) with a 400, so use a recent, valid window instead. diff --git a/tests/Get-PiHoleStatsDatabaseTopDomain.Integration.Tests.ps1 b/tests/Metrics/Get-PiHoleStatsDatabaseTopDomain.Integration.Tests.ps1 similarity index 88% rename from tests/Get-PiHoleStatsDatabaseTopDomain.Integration.Tests.ps1 rename to tests/Metrics/Get-PiHoleStatsDatabaseTopDomain.Integration.Tests.ps1 index 42b34ee..0f867d3 100644 --- a/tests/Get-PiHoleStatsDatabaseTopDomain.Integration.Tests.ps1 +++ b/tests/Metrics/Get-PiHoleStatsDatabaseTopDomain.Integration.Tests.ps1 @@ -4,13 +4,13 @@ # (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically # if that file is missing. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Get-PiHoleStatsDatabaseTopDomain (Integration)' -Tag 'Integration' { BeforeAll { Import-Module .\PiHoleShell\PiHoleShell.psm1 -Force - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer @@ -20,7 +20,7 @@ Describe 'Get-PiHoleStatsDatabaseTopDomain (Integration)' -Tag 'Integration' { # Generates some real query traffic. Live stats reflect it immediately; the on-disk # database stats this file tests only reflect it once FTL's periodic flush runs, so # this mainly helps build up real history across repeated runs, not this run's own data. - & (Join-Path $PSScriptRoot 'Initialize-PiHoleTestData.ps1') -DnsServer $PiHoleServer.Host + & (Join-Path (Split-Path $PSScriptRoot -Parent) 'Initialize-PiHoleTestData.ps1') -DnsServer $PiHoleServer.Host } # The API rejects from=0 (epoch) with a 400, so use a recent, valid window instead. diff --git a/tests/Get-PiHoleStatsDatabaseUpstream.Integration.Tests.ps1 b/tests/Metrics/Get-PiHoleStatsDatabaseUpstream.Integration.Tests.ps1 similarity index 89% rename from tests/Get-PiHoleStatsDatabaseUpstream.Integration.Tests.ps1 rename to tests/Metrics/Get-PiHoleStatsDatabaseUpstream.Integration.Tests.ps1 index 83ba3ac..0bad028 100644 --- a/tests/Get-PiHoleStatsDatabaseUpstream.Integration.Tests.ps1 +++ b/tests/Metrics/Get-PiHoleStatsDatabaseUpstream.Integration.Tests.ps1 @@ -4,13 +4,13 @@ # (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically # if that file is missing. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Get-PiHoleStatsDatabaseUpstream (Integration)' -Tag 'Integration' { BeforeAll { Import-Module .\PiHoleShell\PiHoleShell.psm1 -Force - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer @@ -20,7 +20,7 @@ Describe 'Get-PiHoleStatsDatabaseUpstream (Integration)' -Tag 'Integration' { # Generates some real query traffic. Live stats reflect it immediately; the on-disk # database stats this file tests only reflect it once FTL's periodic flush runs, so # this mainly helps build up real history across repeated runs, not this run's own data. - & (Join-Path $PSScriptRoot 'Initialize-PiHoleTestData.ps1') -DnsServer $PiHoleServer.Host + & (Join-Path (Split-Path $PSScriptRoot -Parent) 'Initialize-PiHoleTestData.ps1') -DnsServer $PiHoleServer.Host } # The API rejects from=0 (epoch) with a 400, so use a recent, valid window instead. diff --git a/tests/Get-PiHoleStatsQuerySuggestions.Integration.Tests.ps1 b/tests/Metrics/Get-PiHoleStatsQuerySuggestions.Integration.Tests.ps1 similarity index 87% rename from tests/Get-PiHoleStatsQuerySuggestions.Integration.Tests.ps1 rename to tests/Metrics/Get-PiHoleStatsQuerySuggestions.Integration.Tests.ps1 index 7ae2124..8a0b0b8 100644 --- a/tests/Get-PiHoleStatsQuerySuggestions.Integration.Tests.ps1 +++ b/tests/Metrics/Get-PiHoleStatsQuerySuggestions.Integration.Tests.ps1 @@ -6,7 +6,7 @@ # Config availability must be known at discovery time so the -Skip parameter on each It block # (evaluated during discovery, before BeforeAll runs) sees the correct value. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Get-PiHoleStatsQuerySuggestions (Integration)' -Tag 'Integration' { BeforeAll { @@ -14,7 +14,7 @@ Describe 'Get-PiHoleStatsQuerySuggestions (Integration)' -Tag 'Integration' { # Recomputed here (not read from the discovery-time $script:ConfigAvailable above) because # Pester runs discovery and run in separate scopes, so BeforeAll cannot see that value. - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer @@ -22,7 +22,7 @@ Describe 'Get-PiHoleStatsQuerySuggestions (Integration)' -Tag 'Integration' { $script:PiHoleIgnoreSsl = $PiHoleIgnoreSsl # Generates some real query traffic so live stats aren't all zero/empty. - & (Join-Path $PSScriptRoot 'Initialize-PiHoleTestData.ps1') -DnsServer $PiHoleServer.Host + & (Join-Path (Split-Path $PSScriptRoot -Parent) 'Initialize-PiHoleTestData.ps1') -DnsServer $PiHoleServer.Host } } diff --git a/tests/Get-PiHoleStatsQueryType.Integration.Tests.ps1 b/tests/Metrics/Get-PiHoleStatsQueryType.Integration.Tests.ps1 similarity index 85% rename from tests/Get-PiHoleStatsQueryType.Integration.Tests.ps1 rename to tests/Metrics/Get-PiHoleStatsQueryType.Integration.Tests.ps1 index 07cbbf4..b4e43ef 100644 --- a/tests/Get-PiHoleStatsQueryType.Integration.Tests.ps1 +++ b/tests/Metrics/Get-PiHoleStatsQueryType.Integration.Tests.ps1 @@ -4,13 +4,13 @@ # (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically # if that file is missing. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Get-PiHoleStatsQueryType (Integration)' -Tag 'Integration' { BeforeAll { Import-Module .\PiHoleShell\PiHoleShell.psm1 -Force - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer @@ -18,7 +18,7 @@ Describe 'Get-PiHoleStatsQueryType (Integration)' -Tag 'Integration' { $script:PiHoleIgnoreSsl = $PiHoleIgnoreSsl # Generates some real query traffic so live stats aren't all zero/empty. - & (Join-Path $PSScriptRoot 'Initialize-PiHoleTestData.ps1') -DnsServer $PiHoleServer.Host + & (Join-Path (Split-Path $PSScriptRoot -Parent) 'Initialize-PiHoleTestData.ps1') -DnsServer $PiHoleServer.Host } } diff --git a/tests/Get-PiHoleStatsRecentBlocked.Integration.Tests.ps1 b/tests/Metrics/Get-PiHoleStatsRecentBlocked.Integration.Tests.ps1 similarity index 85% rename from tests/Get-PiHoleStatsRecentBlocked.Integration.Tests.ps1 rename to tests/Metrics/Get-PiHoleStatsRecentBlocked.Integration.Tests.ps1 index 7e9958a..58f456e 100644 --- a/tests/Get-PiHoleStatsRecentBlocked.Integration.Tests.ps1 +++ b/tests/Metrics/Get-PiHoleStatsRecentBlocked.Integration.Tests.ps1 @@ -4,13 +4,13 @@ # (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically # if that file is missing. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Get-PiHoleStatsRecentBlocked (Integration)' -Tag 'Integration' { BeforeAll { Import-Module .\PiHoleShell\PiHoleShell.psm1 -Force - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer @@ -19,7 +19,7 @@ Describe 'Get-PiHoleStatsRecentBlocked (Integration)' -Tag 'Integration' { # Generates some real query traffic (including known ad/tracker domains that get # blocked) so this function has something recent to report. - & (Join-Path $PSScriptRoot 'Initialize-PiHoleTestData.ps1') -DnsServer $PiHoleServer.Host + & (Join-Path (Split-Path $PSScriptRoot -Parent) 'Initialize-PiHoleTestData.ps1') -DnsServer $PiHoleServer.Host } } diff --git a/tests/Get-PiHoleStatsSummary.Integration.Tests.ps1 b/tests/Metrics/Get-PiHoleStatsSummary.Integration.Tests.ps1 similarity index 86% rename from tests/Get-PiHoleStatsSummary.Integration.Tests.ps1 rename to tests/Metrics/Get-PiHoleStatsSummary.Integration.Tests.ps1 index dbd0004..e193d1c 100644 --- a/tests/Get-PiHoleStatsSummary.Integration.Tests.ps1 +++ b/tests/Metrics/Get-PiHoleStatsSummary.Integration.Tests.ps1 @@ -4,13 +4,13 @@ # (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically # if that file is missing. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Get-PiHoleStatsSummary (Integration)' -Tag 'Integration' { BeforeAll { Import-Module .\PiHoleShell\PiHoleShell.psm1 -Force - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer @@ -18,7 +18,7 @@ Describe 'Get-PiHoleStatsSummary (Integration)' -Tag 'Integration' { $script:PiHoleIgnoreSsl = $PiHoleIgnoreSsl # Generates some real query traffic so live stats aren't all zero/empty. - & (Join-Path $PSScriptRoot 'Initialize-PiHoleTestData.ps1') -DnsServer $PiHoleServer.Host + & (Join-Path (Split-Path $PSScriptRoot -Parent) 'Initialize-PiHoleTestData.ps1') -DnsServer $PiHoleServer.Host } } diff --git a/tests/Get-PiHoleStatsTopClient.Integration.Tests.ps1 b/tests/Metrics/Get-PiHoleStatsTopClient.Integration.Tests.ps1 similarity index 84% rename from tests/Get-PiHoleStatsTopClient.Integration.Tests.ps1 rename to tests/Metrics/Get-PiHoleStatsTopClient.Integration.Tests.ps1 index 7f8fc67..c617ad6 100644 --- a/tests/Get-PiHoleStatsTopClient.Integration.Tests.ps1 +++ b/tests/Metrics/Get-PiHoleStatsTopClient.Integration.Tests.ps1 @@ -4,13 +4,13 @@ # (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically # if that file is missing. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Get-PiHoleStatsTopClient (Integration)' -Tag 'Integration' { BeforeAll { Import-Module .\PiHoleShell\PiHoleShell.psm1 -Force - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer @@ -18,7 +18,7 @@ Describe 'Get-PiHoleStatsTopClient (Integration)' -Tag 'Integration' { $script:PiHoleIgnoreSsl = $PiHoleIgnoreSsl # Generates some real query traffic so live stats aren't all zero/empty. - & (Join-Path $PSScriptRoot 'Initialize-PiHoleTestData.ps1') -DnsServer $PiHoleServer.Host + & (Join-Path (Split-Path $PSScriptRoot -Parent) 'Initialize-PiHoleTestData.ps1') -DnsServer $PiHoleServer.Host } } diff --git a/tests/Get-PiHoleStatsTopDomain.Integration.Tests.ps1 b/tests/Metrics/Get-PiHoleStatsTopDomain.Integration.Tests.ps1 similarity index 84% rename from tests/Get-PiHoleStatsTopDomain.Integration.Tests.ps1 rename to tests/Metrics/Get-PiHoleStatsTopDomain.Integration.Tests.ps1 index e09aa23..9b4e734 100644 --- a/tests/Get-PiHoleStatsTopDomain.Integration.Tests.ps1 +++ b/tests/Metrics/Get-PiHoleStatsTopDomain.Integration.Tests.ps1 @@ -4,13 +4,13 @@ # (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically # if that file is missing. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Get-PiHoleStatsTopDomain (Integration)' -Tag 'Integration' { BeforeAll { Import-Module .\PiHoleShell\PiHoleShell.psm1 -Force - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer @@ -18,7 +18,7 @@ Describe 'Get-PiHoleStatsTopDomain (Integration)' -Tag 'Integration' { $script:PiHoleIgnoreSsl = $PiHoleIgnoreSsl # Generates some real query traffic so live stats aren't all zero/empty. - & (Join-Path $PSScriptRoot 'Initialize-PiHoleTestData.ps1') -DnsServer $PiHoleServer.Host + & (Join-Path (Split-Path $PSScriptRoot -Parent) 'Initialize-PiHoleTestData.ps1') -DnsServer $PiHoleServer.Host } } diff --git a/tests/Get-PiHoleStatsUpstream.Integration.Tests.ps1 b/tests/Metrics/Get-PiHoleStatsUpstream.Integration.Tests.ps1 similarity index 85% rename from tests/Get-PiHoleStatsUpstream.Integration.Tests.ps1 rename to tests/Metrics/Get-PiHoleStatsUpstream.Integration.Tests.ps1 index 5b415be..498c3e5 100644 --- a/tests/Get-PiHoleStatsUpstream.Integration.Tests.ps1 +++ b/tests/Metrics/Get-PiHoleStatsUpstream.Integration.Tests.ps1 @@ -4,13 +4,13 @@ # (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically # if that file is missing. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Get-PiHoleStatsUpstream (Integration)' -Tag 'Integration' { BeforeAll { Import-Module .\PiHoleShell\PiHoleShell.psm1 -Force - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer @@ -18,7 +18,7 @@ Describe 'Get-PiHoleStatsUpstream (Integration)' -Tag 'Integration' { $script:PiHoleIgnoreSsl = $PiHoleIgnoreSsl # Generates some real query traffic so live stats aren't all zero/empty. - & (Join-Path $PSScriptRoot 'Initialize-PiHoleTestData.ps1') -DnsServer $PiHoleServer.Host + & (Join-Path (Split-Path $PSScriptRoot -Parent) 'Initialize-PiHoleTestData.ps1') -DnsServer $PiHoleServer.Host } } diff --git a/tests/Get-PiHolePadd.Integration.Tests.ps1 b/tests/Padd/Get-PiHolePadd.Integration.Tests.ps1 similarity index 84% rename from tests/Get-PiHolePadd.Integration.Tests.ps1 rename to tests/Padd/Get-PiHolePadd.Integration.Tests.ps1 index c03db0d..22c587a 100644 --- a/tests/Get-PiHolePadd.Integration.Tests.ps1 +++ b/tests/Padd/Get-PiHolePadd.Integration.Tests.ps1 @@ -4,13 +4,13 @@ # (copy it from IntegrationConfig.example.ps1) before running. Tests are skipped automatically # if that file is missing. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Get-PiHolePadd (Integration)' -Tag 'Integration' { BeforeAll { Import-Module .\PiHoleShell\PiHoleShell.psm1 -Force - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer @@ -18,7 +18,7 @@ Describe 'Get-PiHolePadd (Integration)' -Tag 'Integration' { $script:PiHoleIgnoreSsl = $PiHoleIgnoreSsl # Generates some real query traffic so live stats aren't all zero/empty. - & (Join-Path $PSScriptRoot 'Initialize-PiHoleTestData.ps1') -DnsServer $PiHoleServer.Host + & (Join-Path (Split-Path $PSScriptRoot -Parent) 'Initialize-PiHoleTestData.ps1') -DnsServer $PiHoleServer.Host } } From 2ff6e19d02e95136edee5f4d8526f54ac8ffb5dd Mon Sep 17 00:00:00 2001 From: Mike Madeja Date: Thu, 24 Sep 2026 19:00:06 -0500 Subject: [PATCH 3/4] fix: unshallow before diffing in CI, stop requiring non-empty history windows The changed-file scoping added in the previous commit failed on its first real run: the default Azure Pipelines checkout is shallow, so there's no common ancestor with the target branch to diff against ("no merge base"/ "unknown revision"). Fixed by unshallowing first when the repo is shallow, and fetching the target branch with an explicit refspec so origin/ gets created even under a checkout whose default fetch refspec is restricted to a single branch. Verified both fixes end-to-end against a real shallow, single-branch clone before trusting them in CI again. Because the scoping fallback ran the full suite on that failed attempt, it also surfaced a real, pre-existing bug (unrelated to this PR, already broken on main): Get-PiHoleHistoryDatabase/Get-PiHoleHistoryDatabaseClient asserted `Should -Not -BeNullOrEmpty` on their history array, but an empty array is a legitimate response when nothing was logged in the queried window - unlike the Stats(database) summary endpoints, which always return a populated object shape even with zero matching rows. Changed those assertions to verify the call succeeds (and, when data is present, that its shape is correct) instead of requiring non-empty results. Co-Authored-By: Claude Sonnet 5 --- azuredevops-pihole-pester-tests.yml | 11 +++++++- ...iHoleHistoryDatabase.Integration.Tests.ps1 | 23 +++++++++-------- ...istoryDatabaseClient.Integration.Tests.ps1 | 25 +++++++++++-------- 3 files changed, 37 insertions(+), 22 deletions(-) diff --git a/azuredevops-pihole-pester-tests.yml b/azuredevops-pihole-pester-tests.yml index 8c31543..82f7395 100644 --- a/azuredevops-pihole-pester-tests.yml +++ b/azuredevops-pihole-pester-tests.yml @@ -56,8 +56,17 @@ steps: if ($env:BUILD_REASON -eq 'PullRequest') { try { + # The default checkout is shallow, which leaves no common ancestor with the target + # branch to diff against ("no merge base") - unshallow first so the diff can work. + if ((git rev-parse --is-shallow-repository) -eq 'true') { + git fetch --unshallow --quiet + if ($LASTEXITCODE -ne 0) { throw "git fetch --unshallow failed" } + } + + # Fetch with an explicit refspec so origin/ is created even if the + # checkout's default fetch refspec is restricted to a single branch. $targetBranch = $env:SYSTEM_PULLREQUEST_TARGETBRANCH -replace '^refs/heads/', '' - git fetch origin $targetBranch --quiet + git fetch origin "${targetBranch}:refs/remotes/origin/${targetBranch}" --quiet if ($LASTEXITCODE -ne 0) { throw "git fetch failed for '$targetBranch'" } $changedFiles = git diff --name-only "origin/$targetBranch...HEAD" diff --git a/tests/History/Get-PiHoleHistoryDatabase.Integration.Tests.ps1 b/tests/History/Get-PiHoleHistoryDatabase.Integration.Tests.ps1 index 6cc19b8..26d3862 100644 --- a/tests/History/Get-PiHoleHistoryDatabase.Integration.Tests.ps1 +++ b/tests/History/Get-PiHoleHistoryDatabase.Integration.Tests.ps1 @@ -24,18 +24,23 @@ Describe 'Get-PiHoleHistoryDatabase (Integration)' -Tag 'Integration' { } It 'returns history as formatted objects' -Skip:(-not $script:ConfigAvailable) { - $result = Get-PiHoleHistoryDatabase -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -From $script:From -Until $script:Until -IgnoreSsl $script:PiHoleIgnoreSsl - $result | Select-Object -First 5 | Format-Table | Out-String | Write-Host - - $result | Should -Not -BeNullOrEmpty - $result[0].Total | Should -BeGreaterOrEqual 0 + # An empty array is a legitimate response here (no queries logged in the window), unlike + # the Stats(database) summary endpoints which always return a populated object shape even + # with zero matching rows - so this only asserts the call succeeds and, if there's data, + # that its shape is correct, rather than requiring non-empty results. + { $script:result = Get-PiHoleHistoryDatabase -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -From $script:From -Until $script:Until -IgnoreSsl $script:PiHoleIgnoreSsl } | Should -Not -Throw + $script:result | Select-Object -First 5 | Format-Table | Out-String | Write-Host + + if ($script:result) { + $script:result[0].Total | Should -BeGreaterOrEqual 0 + } } It 'returns the raw API response when RawOutput is set' -Skip:(-not $script:ConfigAvailable) { $result = Get-PiHoleHistoryDatabase -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -From $script:From -Until $script:Until -IgnoreSsl $script:PiHoleIgnoreSsl -RawOutput $true $result | Format-List | Out-String | Write-Host - $result.history | Should -Not -BeNullOrEmpty + $result.PSObject.Properties.Name | Should -Contain 'history' } It 'errors when given a bad password' -Skip:(-not $script:ConfigAvailable) { @@ -45,9 +50,7 @@ Describe 'Get-PiHoleHistoryDatabase (Integration)' -Tag 'Integration' { } It 'defaults to the last 8 hours when From/Until are omitted' -Skip:(-not $script:ConfigAvailable) { - $result = Get-PiHoleHistoryDatabase -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl - $result | Format-Table | Out-String | Write-Host - - $result | Should -Not -BeNullOrEmpty + { $script:result = Get-PiHoleHistoryDatabase -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl } | Should -Not -Throw + $script:result | Format-Table | Out-String | Write-Host } } diff --git a/tests/History/Get-PiHoleHistoryDatabaseClient.Integration.Tests.ps1 b/tests/History/Get-PiHoleHistoryDatabaseClient.Integration.Tests.ps1 index 173e188..4fe71fe 100644 --- a/tests/History/Get-PiHoleHistoryDatabaseClient.Integration.Tests.ps1 +++ b/tests/History/Get-PiHoleHistoryDatabaseClient.Integration.Tests.ps1 @@ -24,19 +24,24 @@ Describe 'Get-PiHoleHistoryDatabaseClient (Integration)' -Tag 'Integration' { } It 'returns per-client history as formatted objects' -Skip:(-not $script:ConfigAvailable) { - $result = Get-PiHoleHistoryDatabaseClient -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -From $script:From -Until $script:Until -IgnoreSsl $script:PiHoleIgnoreSsl - $result | Select-Object -First 3 | Format-List | Out-String | Write-Host - - $result | Should -Not -BeNullOrEmpty - $result[0].Clients | Should -Not -BeNullOrEmpty - $result[0].Clients[0].ClientId | Should -Not -BeNullOrEmpty + # An empty array is a legitimate response here (no queries logged in the window), unlike + # the Stats(database) summary endpoints which always return a populated object shape even + # with zero matching rows - so this only asserts the call succeeds and, if there's data, + # that its shape is correct, rather than requiring non-empty results. + { $script:result = Get-PiHoleHistoryDatabaseClient -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -From $script:From -Until $script:Until -IgnoreSsl $script:PiHoleIgnoreSsl } | Should -Not -Throw + $script:result | Select-Object -First 3 | Format-List | Out-String | Write-Host + + if ($script:result) { + $script:result[0].Clients | Should -Not -BeNullOrEmpty + $script:result[0].Clients[0].ClientId | Should -Not -BeNullOrEmpty + } } It 'returns the raw API response when RawOutput is set' -Skip:(-not $script:ConfigAvailable) { $result = Get-PiHoleHistoryDatabaseClient -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -From $script:From -Until $script:Until -IgnoreSsl $script:PiHoleIgnoreSsl -RawOutput $true $result | Format-List | Out-String | Write-Host - $result.history | Should -Not -BeNullOrEmpty + $result.PSObject.Properties.Name | Should -Contain 'history' } It 'errors when given a bad password' -Skip:(-not $script:ConfigAvailable) { @@ -46,9 +51,7 @@ Describe 'Get-PiHoleHistoryDatabaseClient (Integration)' -Tag 'Integration' { } It 'defaults to the last 8 hours when From/Until are omitted' -Skip:(-not $script:ConfigAvailable) { - $result = Get-PiHoleHistoryDatabaseClient -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl - $result | Format-List | Out-String | Write-Host - - $result | Should -Not -BeNullOrEmpty + { $script:result = Get-PiHoleHistoryDatabaseClient -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl } | Should -Not -Throw + $script:result | Format-List | Out-String | Write-Host } } From 705fdf20e067ffead7b77740fbb20ba6a8874c83 Mon Sep 17 00:00:00 2001 From: Mike Madeja Date: Thu, 24 Sep 2026 22:28:21 -0500 Subject: [PATCH 4/4] chore: move Invoke-PiHoleFlushLogs test into tests/Actions/ Merges the latest develop (which reorganized tests/ to mirror PiHoleShell/Public//) into this branch, then moves this PR's own new test file - added before that reorg landed - into tests/Actions/ to match, fixing its $PSScriptRoot-relative IntegrationConfig.local.ps1 lookup accordingly. Verified against the real Pi-hole server post-move. Co-Authored-By: Claude Sonnet 5 --- .../Invoke-PiHoleFlushLogs.Integration.Tests.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename tests/{ => Actions}/Invoke-PiHoleFlushLogs.Integration.Tests.ps1 (90%) diff --git a/tests/Invoke-PiHoleFlushLogs.Integration.Tests.ps1 b/tests/Actions/Invoke-PiHoleFlushLogs.Integration.Tests.ps1 similarity index 90% rename from tests/Invoke-PiHoleFlushLogs.Integration.Tests.ps1 rename to tests/Actions/Invoke-PiHoleFlushLogs.Integration.Tests.ps1 index 9a31e06..0771c2d 100644 --- a/tests/Invoke-PiHoleFlushLogs.Integration.Tests.ps1 +++ b/tests/Actions/Invoke-PiHoleFlushLogs.Integration.Tests.ps1 @@ -6,7 +6,7 @@ # Config availability must be known at discovery time so the -Skip parameter on each It block # (evaluated during discovery, before BeforeAll runs) sees the correct value. -$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') +$script:ConfigAvailable = Test-Path (Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1') Describe 'Invoke-PiHoleFlushLogs (Integration)' -Tag 'Integration' { BeforeAll { @@ -14,7 +14,7 @@ Describe 'Invoke-PiHoleFlushLogs (Integration)' -Tag 'Integration' { # Recomputed here (not read from the discovery-time $script:ConfigAvailable above) because # Pester runs discovery and run in separate scopes, so BeforeAll cannot see that value. - $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + $configPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'IntegrationConfig.local.ps1' if (Test-Path $configPath) { . $configPath $script:PiHoleServer = $PiHoleServer