diff --git a/PiHoleShell/Public/Actions/Update-PiHoleActionsGravity.ps1 b/PiHoleShell/Public/Actions/Update-PiHoleActionsGravity.ps1 index 8d392db..3e23c04 100644 --- a/PiHoleShell/Public/Actions/Update-PiHoleActionsGravity.ps1 +++ b/PiHoleShell/Public/Actions/Update-PiHoleActionsGravity.ps1 @@ -1,10 +1,29 @@ function Update-PiHoleActionsGravity { <# .SYNOPSIS -Update Pi-hole's adlists by running pihole -g. The output of the process is streamed with chunked encoding. Use the optional color query parameter to include ANSI color escape codes in the output. +Update Pi-hole's adlists by running pihole -g +.DESCRIPTION +Triggers a Pi-hole gravity update (equivalent to running `pihole -g` on the server), which +re-downloads and rebuilds the adlists used for blocking. This can take anywhere from several +seconds to a few minutes depending on adlist size. The API streams back the raw `pihole -g` +console log as plain text rather than JSON, so -RawOutput returns that log verbatim. + +.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 raw pihole -g console log instead of the formatted object + +.EXAMPLE +Update-PiHoleActionsGravity -PiHoleServer "http://pihole.domain.com:8080" -Password "your-app-password" #> - #Work In Progress [CmdletBinding(SupportsShouldProcess = $true, HelpUri = 'https://ftl.pi-hole.net/master/docs/#post-/action/gravity')] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] param ( @@ -26,27 +45,23 @@ Update Pi-hole's adlists by running pihole -g. The output of the process is stre ContentType = "application/json" } - if ($PSCmdlet.ShouldProcess("Pi-Hole server at $PiHoleServer", "Update gravity actions")) { + if ($PSCmdlet.ShouldProcess("Pi-Hole server at $PiHoleServer", "Update gravity")) { $Response = Invoke-RestMethod @Params - } - - if ($RawOutput) { - Write-Output $Response - } - else { - $ObjectFinal = @() - $Object = $null - if ($Object) { - $ObjectFinal += $Object + if ($RawOutput) { + Write-Output $Response + } + else { + $Object = [PSCustomObject]@{ + Status = "Completed" + } + Write-Output $Object } - Write-Output $ObjectFinal } } catch { Write-Error -Message $_.Exception.Message - break } finally { diff --git a/PiHoleShell/Public/Authentication/Request-PiHoleAuth.ps1 b/PiHoleShell/Public/Authentication/Request-PiHoleAuth.ps1 index aaec1a4..6428a97 100644 --- a/PiHoleShell/Public/Authentication/Request-PiHoleAuth.ps1 +++ b/PiHoleShell/Public/Authentication/Request-PiHoleAuth.ps1 @@ -1,8 +1,8 @@ function Request-PiHoleAuth { #INTERNAL FUNCTION + [CmdletBinding()] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] param ( - [CmdletBinding()] [System.URI]$PiHoleServer, [string]$Password, [bool]$IgnoreSsl = $false @@ -25,6 +25,5 @@ function Request-PiHoleAuth { catch { Write-Error -Message $_.Exception.Message - break } } \ No newline at end of file diff --git a/PiHoleShell/Public/DnsControl/Get-PiHoleDnsBlockingStatus.ps1 b/PiHoleShell/Public/DnsControl/Get-PiHoleDnsBlockingStatus.ps1 index 804b3e7..f6fd6a6 100644 --- a/PiHoleShell/Public/DnsControl/Get-PiHoleDnsBlockingStatus.ps1 +++ b/PiHoleShell/Public/DnsControl/Get-PiHoleDnsBlockingStatus.ps1 @@ -1,7 +1,12 @@ function Get-PiHoleDnsBlockingStatus { <# .SYNOPSIS -https://ftl.pi-hole.net/master/docs/#get-/config +Get Pi-hole's current DNS blocking status + +.DESCRIPTION +Returns whether Pi-hole is currently blocking DNS queries. If blocking has been temporarily +toggled with a timer (see Set-PiHoleDnsBlocking), this also returns how many seconds remain +until the opposite setting reverts. .PARAMETER PiHoleServer The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" diff --git a/PiHoleShell/Public/DnsControl/Set-PiHoleDnsBlocking.ps1 b/PiHoleShell/Public/DnsControl/Set-PiHoleDnsBlocking.ps1 index de140d2..8a7692b 100644 --- a/PiHoleShell/Public/DnsControl/Set-PiHoleDnsBlocking.ps1 +++ b/PiHoleShell/Public/DnsControl/Set-PiHoleDnsBlocking.ps1 @@ -1,7 +1,13 @@ function Set-PiHoleDnsBlocking { <# .SYNOPSIS -https://ftl.pi-hole.net/master/docs/#get-/dns/blocking +Enable or disable Pi-hole's DNS blocking + +.DESCRIPTION +Turns Pi-hole's DNS blocking on or off. Optionally pass -TimeInSeconds to have Pi-hole +automatically revert to the opposite setting after that many seconds - for example, +disabling blocking for 60 seconds to temporarily let all DNS queries through, after which +blocking resumes on its own. .PARAMETER PiHoleServer The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" diff --git a/PiHoleShell/Public/GroupManagement/Get-PiHoleGroup.ps1 b/PiHoleShell/Public/GroupManagement/Get-PiHoleGroup.ps1 index 5bd952c..c93bc09 100644 --- a/PiHoleShell/Public/GroupManagement/Get-PiHoleGroup.ps1 +++ b/PiHoleShell/Public/GroupManagement/Get-PiHoleGroup.ps1 @@ -73,7 +73,6 @@ Get groups catch { Write-Error -Message $_.Exception.Message - break } finally { diff --git a/PiHoleShell/Public/ListManagement/Add-PiHoleList.ps1 b/PiHoleShell/Public/ListManagement/Add-PiHoleList.ps1 index af8acc5..d1b4ad3 100644 --- a/PiHoleShell/Public/ListManagement/Add-PiHoleList.ps1 +++ b/PiHoleShell/Public/ListManagement/Add-PiHoleList.ps1 @@ -1,7 +1,11 @@ function Add-PiHoleList { <# .SYNOPSIS -Add new list +Add a new list + +.DESCRIPTION +Subscribes Pi-hole to a new allow or block list. The list is fetched and applied the next +time gravity runs (see Update-PiHoleActionsGravity). .PARAMETER PiHoleServer The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" @@ -12,11 +16,27 @@ The API Password you generated from your PiHole server .PARAMETER IgnoreSsl Set to $true to skip SSL certificate validation +.PARAMETER Address +The URL of the list to subscribe to + +.PARAMETER Type +Whether this is an Allow list or a Block list + +.PARAMETER Comment +An optional comment to store alongside the list + +.PARAMETER Group +The group(s) this list applies to. Defaults to "Default" + +.PARAMETER Enabled +Whether the list is enabled immediately. Defaults to $true + .PARAMETER RawOutput This will dump the response instead of the formatted object +.EXAMPLE +Add-PiHoleList -PiHoleServer "http://pihole.domain.com:8080" -Password "your-app-password" -Address "https://hosts-file.net/ad_servers.txt" -Type Block #> - #Work In Progress [CmdletBinding(HelpUri = 'https://ftl.pi-hole.net/master/docs/#post-/lists')] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] param ( @@ -25,6 +45,7 @@ This will dump the response instead of the formatted object [Parameter(Mandatory = $true)] [string]$Password, [bool]$IgnoreSsl = $false, + [Parameter(Mandatory = $true)] [System.Uri]$Address, [Parameter(Mandatory = $true)] [ValidateSet("Allow", "Block")] @@ -61,7 +82,6 @@ This will dump the response instead of the formatted object $Body = @{ address = $Address - type = $Type groups = [Object[]]($AllGroupsIds) comment = $Comment enabled = $Enabled @@ -69,7 +89,7 @@ This will dump the response instead of the formatted object $Params = @{ Headers = @{sid = $($Sid) } - Uri = "$($PiHoleServer.OriginalString)/api/lists" + Uri = "$($PiHoleServer.OriginalString)/api/lists?type=$($Type.ToLower())" Method = "Post" SkipCertificateCheck = $IgnoreSsl Body = $Body | ConvertTo-Json -Depth 10 @@ -78,21 +98,19 @@ This will dump the response instead of the formatted object $Response = Invoke-RestMethod @Params - if ($Item.date_updated -eq 0) { - $DateUpdated = $null - } - else { - $DateUpdated = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.date_modified).LocalTime - } - if ($RawOutput) { Write-Output $Response } else { $ObjectFinal = @() - $Object = $null foreach ($Item in $Response.lists) { + if ($Item.date_updated -eq 0) { + $DateUpdated = $null + } + else { + $DateUpdated = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.date_modified).LocalTime + } $Object = [PSCustomObject]@{ Address = $Item.address @@ -120,7 +138,6 @@ This will dump the response instead of the formatted object catch { Write-Error -Message $_.Exception.Message - break } finally { diff --git a/PiHoleShell/Public/ListManagement/Get-PiHoleList.ps1 b/PiHoleShell/Public/ListManagement/Get-PiHoleList.ps1 index 5539fda..50d09ba 100644 --- a/PiHoleShell/Public/ListManagement/Get-PiHoleList.ps1 +++ b/PiHoleShell/Public/ListManagement/Get-PiHoleList.ps1 @@ -88,7 +88,6 @@ This will dump the response instead of the formatted object catch { Write-Error -Message $_.Exception.Message - break } finally { diff --git a/PiHoleShell/Public/ListManagement/Remove-PiHoleList.ps1 b/PiHoleShell/Public/ListManagement/Remove-PiHoleList.ps1 index 93e3d21..0fdc319 100644 --- a/PiHoleShell/Public/ListManagement/Remove-PiHoleList.ps1 +++ b/PiHoleShell/Public/ListManagement/Remove-PiHoleList.ps1 @@ -1,7 +1,11 @@ function Remove-PiHoleList { <# .SYNOPSIS -Deletes multiple lists in the lists object. +Remove a list + +.DESCRIPTION +Unsubscribes Pi-hole from an allow or block list. The Pi-hole API deletes lists in a batch, +so this sends a single-item batch containing just the list you specify. .PARAMETER PiHoleServer The URL to the PiHole Server, for example "http://pihole.domain.com:8080", or "http://192.168.1.100" @@ -12,11 +16,18 @@ The API Password you generated from your PiHole server .PARAMETER IgnoreSsl Set to $true to skip SSL certificate validation +.PARAMETER Address +The URL of the list to remove + +.PARAMETER Type +Whether this is an Allow list or a Block list + .PARAMETER RawOutput -This will dump the response instead of the formatted objec +This will dump the response instead of the formatted object +.EXAMPLE +Remove-PiHoleList -PiHoleServer "http://pihole.domain.com:8080" -Password "your-app-password" -Address "https://hosts-file.net/ad_servers.txt" -Type Block #> - #Work In Progress (NEED TO FINISH) [CmdletBinding(SupportsShouldProcess = $true, HelpUri = 'https://ftl.pi-hole.net/master/docs/#post-/lists-batchDelete')] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Password")] param ( @@ -25,19 +36,16 @@ This will dump the response instead of the formatted objec [Parameter(Mandatory = $true)] [string]$Password, [bool]$IgnoreSsl = $false, + [Parameter(Mandatory = $true)] [System.Uri]$Address, + [Parameter(Mandatory = $true)] + [ValidateSet("Allow", "Block")] [string]$Type, [bool]$RawOutput = $false ) try { $Target = "Pi-Hole list $Address of type $Type" if ($PSCmdlet.ShouldProcess($Target, "Remove list")) { - $FindMatchingList = Get-PiHoleList -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl | Where-Object { $_.Address -eq $Address } - - if ($FindMatchingList) { - - } - $Sid = Request-PiHoleAuth -PiHoleServer $PiHoleServer -Password $Password -IgnoreSsl $IgnoreSsl $Body = @( @@ -65,38 +73,20 @@ This will dump the response instead of the formatted objec } else { - $ObjectFinal = @() - $Object = $null - - foreach ($Item in $Response.lists) { - $Object = [PSCustomObject]@{ - Address = $Item.address - Comment = $Item.comment - Groups = $AllGroupsNames - Enabled = $Item.enabled - Id = $Item.id - DateAdded = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.date_added).LocalTime - DateModified = (Convert-PiHoleUnixTimeToLocalTime -UnixTime $Item.date_modified).LocalTime - Type = $Item.type.SubString(0, 1).ToUpper() + $Item.type.SubString(1).ToLower() - DateUpdated = $DateUpdated - Number = $Item.number - InvalidDomains = $Item.invalid_domains - AbpEntries = $Item.abp_entries - Status = $Item.status - } - if ($Object) { - $ObjectFinal += $Object - } + # A successful delete returns 204 No Content, so there's no response body to + # build a rich object from. + $Object = [PSCustomObject]@{ + Address = $Address + Type = $Type + Status = "Removed" } - - Write-Output $ObjectFinal + Write-Output $Object } } } catch { Write-Error -Message $_.Exception.Message - break } finally { diff --git a/README.md b/README.md index 31ddd4f..456bdfe 100644 --- a/README.md +++ b/README.md @@ -89,14 +89,14 @@ Functions marked 🚧 are still under active development — signatures and outp |---|---| | `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. The output of the process is streamed with chunked encoding. Use the optional color query parameter to include ANSI color escape codes in the output. | +| `Update-PiHoleActionsGravity` | Update Pi-hole's adlists by running pihole -g | ### DNS Control | Function | Description | |---|---| -| `Get-PiHoleDnsBlockingStatus` | _No description yet_ | -| `Set-PiHoleDnsBlocking` | _No description yet_ | +| `Get-PiHoleDnsBlockingStatus` | Get Pi-hole's current DNS blocking status | +| `Set-PiHoleDnsBlocking` | Enable or disable Pi-hole's DNS blocking | ### Group Management @@ -111,9 +111,9 @@ Functions marked 🚧 are still under active development — signatures and outp | Function | Description | |---|---| -| `Add-PiHoleList` 🚧 | Add new list | +| `Add-PiHoleList` | Add a new list | | `Get-PiHoleList` 🚧 | Get lists | -| `Remove-PiHoleList` 🚧 | Deletes multiple lists in the lists object. | +| `Remove-PiHoleList` | Remove a list | | `Search-PiHoleListDomain` | _No description yet_ | ### Metrics diff --git a/tests/Add-PiHoleList.Integration.Tests.ps1 b/tests/Add-PiHoleList.Integration.Tests.ps1 new file mode 100644 index 0000000..ce60d01 --- /dev/null +++ b/tests/Add-PiHoleList.Integration.Tests.ps1 @@ -0,0 +1,74 @@ +# 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. + +$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') + +Describe 'Add-PiHoleList (Integration)' -Tag 'Integration' { + BeforeAll { + Import-Module .\PiHoleShell\PiHoleShell.psm1 -Force + + $script:TestListAddress = 'https://blocklistproject.github.io/Lists/alt-version/ransomware-nl.txt' + + $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + if (Test-Path $configPath) { + . $configPath + $script:PiHoleServer = $PiHoleServer + $script:PiHoleToken = $PiHoleToken + $script:PiHoleIgnoreSsl = $PiHoleIgnoreSsl + + # Defensive cleanup in case a previous failed run left the test list behind + Remove-PiHoleList -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl -Address $script:TestListAddress -Type Block -Confirm:$false -ErrorAction SilentlyContinue | Out-Null + } + } + + AfterAll { + if ($script:PiHoleServer) { + # Ensures the test list is never left behind for other test files to trip over + Remove-PiHoleList -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl -Address $script:TestListAddress -Type Block -Confirm:$false -ErrorAction SilentlyContinue | Out-Null + } + } + + It 'adds a new list and returns a formatted object' -Skip:(-not $script:ConfigAvailable) { + $result = Add-PiHoleList -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl -Address $script:TestListAddress -Type Block -Comment 'Pester integration test list' + $result | Format-List | Out-String | Write-Host + + $result | Should -Not -BeNullOrEmpty + $result.Address | Should -Be $script:TestListAddress + $result.Type | Should -Be 'Block' + $result.Enabled | Should -BeTrue + + # Clean up immediately so the next test starts from a known (list-absent) state + Remove-PiHoleList -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl -Address $script:TestListAddress -Type Block -Confirm:$false | Out-Null + } + + It 'returns the raw API response when RawOutput is set' -Skip:(-not $script:ConfigAvailable) { + $result = Add-PiHoleList -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl -Address $script:TestListAddress -Type Block -RawOutput $true + $result | Format-List | Out-String | Write-Host + + $result | Should -Not -BeNullOrEmpty + $result.lists[0].address | Should -Be $script:TestListAddress + + Remove-PiHoleList -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl -Address $script:TestListAddress -Type Block -Confirm:$false | Out-Null + } + + It 'errors when the list already exists' -Skip:(-not $script:ConfigAvailable) { + Add-PiHoleList -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl -Address $script:TestListAddress -Type Block | Out-Null + + $result = Add-PiHoleList -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl -Address $script:TestListAddress -Type Block -ErrorVariable errOut -ErrorAction SilentlyContinue + Write-Host "Error: [$errOut]" + + $errOut | Should -Not -BeNullOrEmpty + + Remove-PiHoleList -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl -Address $script:TestListAddress -Type Block -Confirm:$false | Out-Null + } + + It 'errors when given a bad password' -Skip:(-not $script:ConfigAvailable) { + $result = Add-PiHoleList -PiHoleServer $script:PiHoleServer -Password 'definitely-not-the-real-token' -IgnoreSsl $script:PiHoleIgnoreSsl -Address $script:TestListAddress -Type Block -ErrorVariable errOut -ErrorAction SilentlyContinue + Write-Host "Error: [$errOut]" + + $errOut | Should -Not -BeNullOrEmpty + } +} diff --git a/tests/Remove-PiHoleList.Integration.Tests.ps1 b/tests/Remove-PiHoleList.Integration.Tests.ps1 new file mode 100644 index 0000000..ff9df8e --- /dev/null +++ b/tests/Remove-PiHoleList.Integration.Tests.ps1 @@ -0,0 +1,67 @@ +# 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. + +$script:ConfigAvailable = Test-Path (Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1') + +Describe 'Remove-PiHoleList (Integration)' -Tag 'Integration' { + BeforeAll { + Import-Module .\PiHoleShell\PiHoleShell.psm1 -Force + + $script:TestListAddress = 'https://blocklistproject.github.io/Lists/alt-version/ransomware-nl.txt' + + $configPath = Join-Path $PSScriptRoot 'IntegrationConfig.local.ps1' + if (Test-Path $configPath) { + . $configPath + $script:PiHoleServer = $PiHoleServer + $script:PiHoleToken = $PiHoleToken + $script:PiHoleIgnoreSsl = $PiHoleIgnoreSsl + + # Defensive cleanup in case a previous failed run left the test list behind + Remove-PiHoleList -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl -Address $script:TestListAddress -Type Block -Confirm:$false -ErrorAction SilentlyContinue | Out-Null + } + } + + AfterAll { + if ($script:PiHoleServer) { + # Defensive cleanup in case a test left the list behind + Remove-PiHoleList -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl -Address $script:TestListAddress -Type Block -Confirm:$false -ErrorAction SilentlyContinue | Out-Null + } + } + + It 'removes an existing list and returns a formatted object' -Skip:(-not $script:ConfigAvailable) { + Add-PiHoleList -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl -Address $script:TestListAddress -Type Block -Comment 'Pester integration test list' | Out-Null + + $result = Remove-PiHoleList -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl -Address $script:TestListAddress -Type Block -Confirm:$false + $result | Format-List | Out-String | Write-Host + + $result | Should -Not -BeNullOrEmpty + $result.Address | Should -Be $script:TestListAddress + $result.Status | Should -Be 'Removed' + + $remaining = Get-PiHoleList -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl | Where-Object { $_.Address -eq $script:TestListAddress } + $remaining | Should -BeNullOrEmpty + } + + It 'removes the list when RawOutput is set, even though the API returns no body' -Skip:(-not $script:ConfigAvailable) { + Add-PiHoleList -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl -Address $script:TestListAddress -Type Block | Out-Null + + # A successful delete is HTTP 204 No Content, so RawOutput is expected to be empty here - + # the list actually being gone afterward is the real signal of success. + Remove-PiHoleList -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl -Address $script:TestListAddress -Type Block -RawOutput $true -Confirm:$false + + $remaining = Get-PiHoleList -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl | Where-Object { $_.Address -eq $script:TestListAddress } + $remaining | Should -BeNullOrEmpty + } + + It 'errors when given a bad password' -Skip:(-not $script:ConfigAvailable) { + Add-PiHoleList -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl -Address $script:TestListAddress -Type Block | Out-Null + + $result = Remove-PiHoleList -PiHoleServer $script:PiHoleServer -Password 'definitely-not-the-real-token' -IgnoreSsl $script:PiHoleIgnoreSsl -Address $script:TestListAddress -Type Block -Confirm:$false -ErrorVariable errOut -ErrorAction SilentlyContinue + Write-Host "Error: [$errOut]" + + $errOut | Should -Not -BeNullOrEmpty + } +} diff --git a/tests/Update-PiHoleActionsGravity.Integration.Tests.ps1 b/tests/Update-PiHoleActionsGravity.Integration.Tests.ps1 index a9a64bc..9257a43 100644 --- a/tests/Update-PiHoleActionsGravity.Integration.Tests.ps1 +++ b/tests/Update-PiHoleActionsGravity.Integration.Tests.ps1 @@ -26,6 +26,14 @@ Describe 'Update-PiHoleActionsGravity (Integration)' -Tag 'Integration' { } } + It 'runs a gravity update and returns a formatted object' -Skip:(-not $script:ConfigAvailable) { + $result = Update-PiHoleActionsGravity -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl -Confirm:$false + $result | Format-List | Out-String | Write-Host + + $result | Should -Not -BeNullOrEmpty + $result.Status | Should -Be "Completed" + } + It 'runs a gravity update and returns the raw API response' -Skip:(-not $script:ConfigAvailable) { $result = Update-PiHoleActionsGravity -PiHoleServer $script:PiHoleServer -Password $script:PiHoleToken -IgnoreSsl $script:PiHoleIgnoreSsl -RawOutput $true -Confirm:$false Write-Host "RawOutput: [$result]" @@ -35,6 +43,7 @@ Describe 'Update-PiHoleActionsGravity (Integration)' -Tag 'Integration' { It 'errors when given a bad password' -Skip:(-not $script:ConfigAvailable) { $result = Update-PiHoleActionsGravity -PiHoleServer $script:PiHoleServer -Password 'definitely-not-the-real-token' -IgnoreSsl $script:PiHoleIgnoreSsl -Confirm:$false -ErrorVariable errOut -ErrorAction SilentlyContinue + Write-Host "Error: [$errOut]" $errOut | Should -Not -BeNullOrEmpty }