-
-
Notifications
You must be signed in to change notification settings - Fork 457
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Cooperative request intercepts (#2403)
* some progress * cr * cr * requestId is string * unflake test * prettier
- Loading branch information
Showing
23 changed files
with
1,587 additions
and
144 deletions.
There are no files selected for viewing
787 changes: 787 additions & 0 deletions
787
...peteerSharp.Tests/RequestInterceptionExperimentalTests/PageSetRequestInterceptionTests.cs
Large diffs are not rendered by default.
Oops, something went wrong.
127 changes: 127 additions & 0 deletions
127
lib/PuppeteerSharp.Tests/RequestInterceptionExperimentalTests/RequestContinueTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Net.Http; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using PuppeteerSharp.Tests.Attributes; | ||
using PuppeteerSharp.Nunit; | ||
using NUnit.Framework; | ||
|
||
namespace PuppeteerSharp.Tests.RequestInterceptionExperimentalTests; | ||
|
||
public class RequestContinueTests : PuppeteerPageBaseTest | ||
{ | ||
[PuppeteerTest("requestinterception-experimental.spec.ts", "Request.continue", "should work")] | ||
[Skip(SkipAttribute.Targets.Firefox)] | ||
public async Task ShouldWork() | ||
{ | ||
await Page.SetRequestInterceptionAsync(true); | ||
Page.AddRequestInterceptor(async request => await request.ContinueAsync(new Payload(), 0)); | ||
await Page.GoToAsync(TestConstants.EmptyPage); | ||
} | ||
|
||
[PuppeteerTest("requestinterception-experimental.spec.ts", "Request.continue", "should amend HTTP headers")] | ||
[Skip(SkipAttribute.Targets.Firefox)] | ||
public async Task ShouldAmendHTTPHeaders() | ||
{ | ||
await Page.SetRequestInterceptionAsync(true); | ||
Page.AddRequestInterceptor(request => | ||
{ | ||
var headers = new Dictionary<string, string>(request.Headers) { ["FOO"] = "bar" }; | ||
return request.ContinueAsync(new Payload { Headers = headers }, 0); | ||
}); | ||
await Page.GoToAsync(TestConstants.EmptyPage); | ||
var requestTask = Server.WaitForRequest("/sleep.zzz", request => request.Headers["foo"].ToString()); | ||
await Task.WhenAll( | ||
requestTask, | ||
Page.EvaluateExpressionAsync("fetch('/sleep.zzz')") | ||
); | ||
Assert.AreEqual("bar", requestTask.Result); | ||
} | ||
|
||
[PuppeteerTest("requestinterception-experimental.spec.ts", "Request.continue", | ||
"should redirect in a way non-observable to page")] | ||
[Skip(SkipAttribute.Targets.Firefox)] | ||
public async Task ShouldRedirectInAWayNonObservableToPage() | ||
{ | ||
await Page.SetRequestInterceptionAsync(true); | ||
Page.AddRequestInterceptor(request => | ||
{ | ||
var redirectURL = request.Url.Contains("/empty.html") | ||
? TestConstants.ServerUrl + "/consolelog.html" | ||
: null; | ||
return request.ContinueAsync(new Payload { Url = redirectURL }, 0); | ||
}); | ||
string consoleMessage = null; | ||
Page.Console += (_, e) => consoleMessage = e.Message.Text; | ||
await Page.GoToAsync(TestConstants.EmptyPage); | ||
Assert.AreEqual(TestConstants.EmptyPage, Page.Url); | ||
Assert.AreEqual("yellow", consoleMessage); | ||
} | ||
|
||
[PuppeteerTest("requestinterception-experimental.spec.ts", "Request.continue", "should amend method")] | ||
[Skip(SkipAttribute.Targets.Firefox)] | ||
public async Task ShouldAmendMethodData() | ||
{ | ||
await Page.GoToAsync(TestConstants.EmptyPage); | ||
await Page.SetRequestInterceptionAsync(true); | ||
Page.AddRequestInterceptor(request => request.ContinueAsync(new Payload { Method = HttpMethod.Post }, 0)); | ||
|
||
var requestTask = Server.WaitForRequest<string>("/sleep.zzz", request => request.Method); | ||
|
||
await Task.WhenAll( | ||
requestTask, | ||
Page.EvaluateExpressionAsync("fetch('/sleep.zzz')") | ||
); | ||
|
||
Assert.AreEqual("POST", requestTask.Result); | ||
} | ||
|
||
[PuppeteerTest("requestinterception-experimental.spec.ts", "Request.continue", "should amend post data")] | ||
[Skip(SkipAttribute.Targets.Firefox)] | ||
public async Task ShouldAmendPostData() | ||
{ | ||
await Page.SetRequestInterceptionAsync(true); | ||
Page.AddRequestInterceptor(request => request.ContinueAsync(new Payload { Method = HttpMethod.Post, PostData = "doggo" }, 0)); | ||
var requestTask = Server.WaitForRequest("/sleep.zzz", async request => | ||
{ | ||
using var reader = new StreamReader(request.Body, Encoding.UTF8); | ||
return await reader.ReadToEndAsync(); | ||
}); | ||
|
||
await Task.WhenAll( | ||
requestTask, | ||
Page.GoToAsync(TestConstants.ServerUrl + "/sleep.zzz") | ||
); | ||
|
||
Assert.AreEqual("doggo", await requestTask.Result); | ||
} | ||
|
||
[PuppeteerTest("requestinterception-experimental.spec.ts", "Request.continue", | ||
"should amend both post data and method on navigation")] | ||
[Skip(SkipAttribute.Targets.Firefox)] | ||
public async Task ShouldAmendBothPostDataAndMethodOnNavigation() | ||
{ | ||
await Page.SetRequestInterceptionAsync(true); | ||
Page.AddRequestInterceptor(request => request.ContinueAsync( | ||
new Payload | ||
{ | ||
Method = HttpMethod.Post, PostData = "doggo" | ||
}, | ||
0)); | ||
|
||
var serverRequestTask = Server.WaitForRequest("/empty.html", async req => | ||
{ | ||
var body = await new StreamReader(req.Body).ReadToEndAsync(); | ||
return new { req.Method, Body = body }; | ||
}); | ||
|
||
await Task.WhenAll( | ||
serverRequestTask, | ||
Page.GoToAsync(TestConstants.EmptyPage) | ||
); | ||
var serverRequest = await serverRequestTask; | ||
Assert.AreEqual(HttpMethod.Post.Method, serverRequest.Result.Method); | ||
Assert.AreEqual("doggo", serverRequest.Result.Body); | ||
} | ||
} |
149 changes: 149 additions & 0 deletions
149
lib/PuppeteerSharp.Tests/RequestInterceptionExperimentalTests/RequestRespondTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Net; | ||
using System.Threading.Tasks; | ||
using PuppeteerSharp.Tests.Attributes; | ||
using PuppeteerSharp.Nunit; | ||
using NUnit.Framework; | ||
|
||
namespace PuppeteerSharp.Tests.RequestInterceptionExperimentalTests; | ||
|
||
public class RequestRespondTests : PuppeteerPageBaseTest | ||
{ | ||
[PuppeteerTest("requestinterception-experimental.spec.ts", "Request.respond", "should work")] | ||
[Skip(SkipAttribute.Targets.Firefox)] | ||
public async Task ShouldWork() | ||
{ | ||
await Page.SetRequestInterceptionAsync(true); | ||
Page.AddRequestInterceptor(request => request.RespondAsync(new ResponseData | ||
{ | ||
Status = HttpStatusCode.Created, | ||
Headers = new Dictionary<string, object> { ["foo"] = "bar" }, | ||
Body = "Yo, page!" | ||
}, 0)); | ||
|
||
var response = await Page.GoToAsync(TestConstants.EmptyPage); | ||
Assert.AreEqual(HttpStatusCode.Created, response.Status); | ||
Assert.AreEqual("bar", response.Headers["foo"]); | ||
Assert.AreEqual("Yo, page!", await Page.EvaluateExpressionAsync<string>("document.body.textContent")); | ||
} | ||
|
||
/// <summary> | ||
/// In puppeteer this method is called ShouldWorkWithStatusCode422. | ||
/// I found that status 422 is not available in all .NET runtimes (see https://github.com/dotnet/core/blob/4c4642d548074b3fbfd425541a968aadd75fea99/release-notes/2.1/Preview/api-diff/preview2/2.1-preview2_System.Net.md) | ||
/// As the goal here is testing HTTP codes that are not in Chromium (see https://cs.chromium.org/chromium/src/net/http/http_status_code_list.h?sq=package:chromium&g=0) we will use code 426: Upgrade Required | ||
/// </summary> | ||
[PuppeteerTest("requestinterception-experimental.spec.ts", "Request.respond", "should work with status code 422")] | ||
[Skip(SkipAttribute.Targets.Firefox)] | ||
public async Task ShouldWorkReturnStatusPhrases() | ||
{ | ||
await Page.SetRequestInterceptionAsync(true); | ||
Page.AddRequestInterceptor(request => request.RespondAsync(new ResponseData | ||
{ | ||
Status = HttpStatusCode.UpgradeRequired, Body = "Yo, page!" | ||
}, 0)); | ||
|
||
var response = await Page.GoToAsync(TestConstants.EmptyPage); | ||
Assert.AreEqual(HttpStatusCode.UpgradeRequired, response.Status); | ||
Assert.AreEqual("Upgrade Required", response.StatusText); | ||
Assert.AreEqual("Yo, page!", await Page.EvaluateExpressionAsync<string>("document.body.textContent")); | ||
} | ||
|
||
[PuppeteerTest("requestinterception-experimental.spec.ts", "Request.respond", "should redirect")] | ||
[Skip(SkipAttribute.Targets.Firefox)] | ||
public async Task ShouldRedirect() | ||
{ | ||
await Page.SetRequestInterceptionAsync(true); | ||
|
||
Page.AddRequestInterceptor(request => | ||
{ | ||
if (!request.Url.Contains("rrredirect")) | ||
{ | ||
return request.ContinueAsync(new Payload(), 0); | ||
} | ||
|
||
return request.RespondAsync(new ResponseData | ||
{ | ||
Status = HttpStatusCode.Redirect, | ||
Headers = new Dictionary<string, object> { ["location"] = TestConstants.EmptyPage } | ||
}, 0); | ||
}); | ||
|
||
var response = await Page.GoToAsync(TestConstants.ServerUrl + "/rrredirect"); | ||
|
||
Assert.That(response.Request.RedirectChain, Has.Exactly(1).Items); | ||
Assert.AreEqual(TestConstants.ServerUrl + "/rrredirect", response.Request.RedirectChain[0].Url); | ||
Assert.AreEqual(TestConstants.EmptyPage, response.Url); | ||
} | ||
|
||
[PuppeteerTest("requestinterception-experimental.spec.ts", "Request.respond", "should allow mocking binary responses")] | ||
[Skip(SkipAttribute.Targets.Firefox)] | ||
public async Task ShouldAllowMockingBinaryResponses() | ||
{ | ||
await Page.SetRequestInterceptionAsync(true); | ||
Page.AddRequestInterceptor(request => | ||
{ | ||
var imageData = File.ReadAllBytes("./Assets/pptr.png"); | ||
return request.RespondAsync(new ResponseData { ContentType = "image/png", BodyData = imageData }, 0); | ||
}); | ||
|
||
await Page.EvaluateFunctionAsync(@"PREFIX => | ||
{ | ||
const img = document.createElement('img'); | ||
img.src = PREFIX + '/does-not-exist.png'; | ||
document.body.appendChild(img); | ||
return new Promise(fulfill => img.onload = fulfill); | ||
}", TestConstants.ServerUrl); | ||
var img = await Page.QuerySelectorAsync("img"); | ||
Assert.True(ScreenshotHelper.PixelMatch("mock-binary-response.png", await img.ScreenshotDataAsync())); | ||
} | ||
|
||
[PuppeteerTest("requestinterception-experimental.spec.ts", "Request.respond", | ||
"should stringify intercepted request response headers")] | ||
[Skip(SkipAttribute.Targets.Firefox)] | ||
public async Task ShouldStringifyInterceptedRequestResponseHeaders() | ||
{ | ||
await Page.SetRequestInterceptionAsync(true); | ||
Page.AddRequestInterceptor(request => request.RespondAsync(new ResponseData | ||
{ | ||
Status = HttpStatusCode.OK, | ||
Headers = new Dictionary<string, object> { ["foo"] = true }, | ||
Body = "Yo, page!" | ||
}, 0)); | ||
|
||
var response = await Page.GoToAsync(TestConstants.EmptyPage); | ||
Assert.AreEqual(HttpStatusCode.OK, response.Status); | ||
Assert.AreEqual("True", response.Headers["foo"]); | ||
Assert.AreEqual("Yo, page!", await Page.EvaluateExpressionAsync<string>("document.body.textContent")); | ||
} | ||
|
||
[Skip(SkipAttribute.Targets.Firefox)] | ||
public async Task ShouldAllowMultipleInterceptedRequestResponseHeaders() | ||
{ | ||
await Page.SetRequestInterceptionAsync(true); | ||
Page.AddRequestInterceptor(request => | ||
{ | ||
return request.RespondAsync(new ResponseData | ||
{ | ||
Status = HttpStatusCode.OK, | ||
Headers = new Dictionary<string, object> | ||
{ | ||
["foo"] = new [] { true, false }, | ||
["Set-Cookie"] = new [] { "sessionId=abcdef", "specialId=123456" } | ||
}, | ||
Body = "Yo, page!" | ||
}, 0); | ||
}); | ||
|
||
var response = await Page.GoToAsync(TestConstants.EmptyPage); | ||
var cookies = await Page.GetCookiesAsync(TestConstants.EmptyPage); | ||
|
||
Assert.AreEqual(HttpStatusCode.OK, response.Status); | ||
Assert.AreEqual("True\nFalse", response.Headers["foo"]); | ||
Assert.AreEqual("Yo, page!", await Page.EvaluateExpressionAsync<string>("document.body.textContent")); | ||
Assert.AreEqual("specialId", cookies[0].Name); | ||
Assert.AreEqual("123456", cookies[0].Value); | ||
Assert.AreEqual("sessionId", cookies[1].Name); | ||
Assert.AreEqual("abcdef", cookies[1].Value); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file modified
BIN
-27.2 KB
(17%)
lib/PuppeteerSharp.Tests/Screenshots/golden-chromium/test.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.