Repository: PowerShell/PowerShell
File: test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1 (PowerShell)

Code before:
        # Core throws if a header has null value.
        # We ignore such headers so no exception is expected.
        { Invoke-WebRequest -Uri $uri -Headers @{ "Location" = $null } } | Should -Not -Throw
        { Invoke-WebRequest -Uri $uri -ContentType $null } | Should -Not -Throw
        { Invoke-RestMethod -Uri $uri -Headers @{ "Location" = $null } } | Should -Not -Throw
        { Invoke-RestMethod -Uri $uri -ContentType $null } | Should -Not -Throw
    }
}

Describe 'Invoke-WebRequest and Invoke-RestMethod support Cancellation through CTRL-C' -Tags "CI", "RequireAdminOnWindows" {
    BeforeAll {
        $oldProgress = $ProgressPreference
        $ProgressPreference = 'SilentlyContinue'
        $WebListener = Start-WebListener
    }

    AfterAll {
        $ProgressPreference = $oldProgress
    }

    function RunWithCancellation {
        param(
            [string]$Command = 'Invoke-WebRequest',
            [string]$Arguments = '',
            [uri]$Uri,
            [int]$DelayMs = 1000,
            [switch]$WillComplete
        )

        $pwsh = [PowerShell]::Create()
        $invoke = "`$result = $Command -Uri `"$Uri`" $Arguments"
        $task = $pwsh.AddScript($invoke).InvokeAsync()
        $delay = [System.Threading.Tasks.Task]::Delay($DelayMs)

        # Stop sleeping as soon as the main task ends or vice versa
        $null = [System.Threading.Tasks.Task]::WhenAny($task, $delay).GetAwaiter().GetResult()
        $task.IsCompleted | Should -Be $WillComplete.ToBool()
        $pwsh.Stop()
        Wait-UntilTrue { [bool]($Task.IsCompleted) } | Should -BeTrue
        $result = $pwsh.Runspace.SessionStateProxy.GetVariable('result')
        $pwsh.Dispose()
        return $result
    }

    It 'Invoke-WebRequest: CTRL-C Cancels request before request headers received' {
        $uri = Get-WebListenerUrl -test Delay -TestValue 30
        RunWithCancellation -Uri $uri -DelayMs 0
    }

    It 'Invoke-WebRequest: CTRL-C Cancels request after request headers received' {
        $uri = Get-WebListenerUrl -test Stall -TestValue '30/application%2fjson'

Review comment (refactor):
The default timeout used in our utility function `Wait-UntilTrue` is 10 seconds, so maybe you should use the same timeout value here.
https://github.com/PowerShell/PowerShell/blob/5e96ed38225c702e96cb584367cf1df925e36cc3/test/tools/Modules/HelpersCommon/HelpersCommon.psm1#L8

Also, since you are not delaying anymore (calling start-sleep), I think you should change this parameter name to be `TimoutMs`

Code after:
        # Core throws if a header has null value.
        # We ignore such headers so no exception is expected.
        { Invoke-WebRequest -Uri $uri -Headers @{ "Location" = $null } } | Should -Not -Throw
        { Invoke-WebRequest -Uri $uri -ContentType $null } | Should -Not -Throw
        { Invoke-RestMethod -Uri $uri -Headers @{ "Location" = $null } } | Should -Not -Throw
        { Invoke-RestMethod -Uri $uri -ContentType $null } | Should -Not -Throw
    }
}

Describe 'Invoke-WebRequest and Invoke-RestMethod support Cancellation through CTRL-C' -Tags "CI", "RequireAdminOnWindows" {
    BeforeAll {
        $oldProgress = $ProgressPreference
        $ProgressPreference = 'SilentlyContinue'
        $WebListener = Start-WebListener
    }

    AfterAll {
        $ProgressPreference = $oldProgress
    }

    function RunWithCancellation {
        param(
            [string]$Command = 'Invoke-WebRequest',
            [string]$Arguments = '',
            [uri]$Uri,
            [int]$DelayBeforeStopSimulationMs = 5000,
            [switch]$WillComplete
        )

        $pwsh = [PowerShell]::Create()
        $invoke = "`$result = $Command -Uri `"$Uri`" $Arguments"
        $task = $pwsh.AddScript($invoke).InvokeAsync()
        $delay = [System.Threading.Tasks.Task]::Delay($DelayBeforeStopSimulationMs)

        # Simulate CTRL-C as soon as the timeout expires or the main task ends
        $null = [System.Threading.Tasks.Task]::WaitAny($task, $delay)
        $task.IsCompleted | Should -Be $WillComplete.ToBool()
        $pwsh.Stop()

        # The download stall is normally 30 seconds from the web listener based
        # on the first slash separated parameter in the -TestValue provided to
        # Get-WebListenerUrl -test Stall -TestValue duration/content-type.
        Wait-UntilTrue { [bool]($Task.IsCompleted) } | Should -BeTrue
        $result = $pwsh.Runspace.SessionStateProxy.GetVariable('result')
        $pwsh.Dispose()
        return $result
    }

    It 'Invoke-WebRequest: CTRL-C Cancels request before request headers received' {
        $uri = Get-WebListenerUrl -test Delay -TestValue 30
        RunWithCancellation -Uri $uri -DelayBeforeStopSimulationMs 1000