diff --git a/docs/src/release-notes-csharp.md b/docs/src/release-notes-csharp.md index 1b582d2c0f..409050bd81 100644 --- a/docs/src/release-notes-csharp.md +++ b/docs/src/release-notes-csharp.md @@ -5,6 +5,124 @@ title: "Release notes" +## Version 1.23 + +### API Testing + +Playwright for .NET 1.23 introduces new [API Testing](./api/class-apirequestcontext) that lets you send requests to the server directly from .NET! +Now you can: + +- test your server API +- prepare server side state before visiting the web application in a test +- validate server side post-conditions after running some actions in the browser + +To do a request on behalf of Playwright's Page, use **new [`property: Page.request`] API**: + +```csharp +// Do a GET request on behalf of page +var response = await Page.APIRequest.GetAsync("http://example.com/foo.json"); +Console.WriteLine(response.Status); +Console.WriteLine(response.StatusText); +Console.WriteLine(response.Ok); +Console.WriteLine(response.Headers["Content-Type"]); +Console.WriteLine(await response.TextAsync()); +Console.WriteLine((await response.JsonAsync())?.GetProperty("foo").GetString()); +``` + +Read more about it in our [API testing guide](./api-testing). + +### Network Replay + +Now you can record network traffic into a HAR file and re-use this traffic in your tests. + +To record network into HAR file: + +```bash +pwsh bin\Debug\netX\playwright.ps1 open --save-har=example.har --save-har-glob="**/api/**" https://example.com +``` + +Alternatively, you can record HAR programmatically: + +```csharp +var context = await browser.NewContextAsync(new () +{ + RecordHarPath = harPath, + RecordHarUrlFilterString = "**/api/**", +}); + +// ... Perform actions ... + +// Close context to ensure HAR is saved to disk. +context.CloseAsync(); +``` + +Use the new methods [`method: Page.routeFromHAR`] or [`method: BrowserContext.routeFromHAR`] to serve matching responses from the [HAR](http://www.softwareishard.com/blog/har-12-spec/) file: + + +```csharp +await context.RouteFromHARAsync("example.har"); +``` + +Read more in [our documentation](./network#record-and-replay-requests). + + +### Advanced Routing + +You can now use [`method: Route.fallback`] to defer routing to other handlers. + +Consider the following example: + +```csharp +// Remove a header from all requests. +await page.RouteAsync("**/*", async route => +{ + var headers = route.Request.Headers; + headers.Remove("X-Secret"); + await route.ContinueAsync(new () { Headers = headers }); +}); + +// Abort all images. +await page.RouteAsync("**/*", async route => +{ + if (route.Request.ResourceType == "image") + { + await route.AbortAsync(); + } + else + { + await route.FallbackAsync(); + } +}); +``` + +Note that the new methods [`method: Page.routeFromHAR`] and [`method: BrowserContext.routeFromHAR`] also participate in routing and could be deferred to. + +### Web-First Assertions Update + +* New method [`method: LocatorAssertions.toHaveValues`] that asserts all selected values of `