Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions dotnet/docs/api/class-browsertype.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ Connecting over the Chrome DevTools Protocol is only supported for Chromium-base
This connection is significantly lower fidelity than the Playwright protocol connection via [BrowserType.ConnectAsync()](/api/class-browsertype.mdx#browser-type-connect). If you are experiencing issues or attempting to use advanced functionality, you probably want to use [BrowserType.ConnectAsync()](/api/class-browsertype.mdx#browser-type-connect).
:::

:::warning
Playwright maintains a curated list of arguments for launching the browser. If you launch the browser without Playwright and do not pass the exact same arguments, some of Playwright functionality may be broken upon connecting to the browser.
:::

**Usage**

```csharp
Expand Down
71 changes: 61 additions & 10 deletions dotnet/docs/api/class-credentials.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,59 @@ There are two common ways to use it:

**Usage: seed a known credential**

```csharp
var context = await browser.NewContextAsync();

// A passkey your backend already provisioned for a test user.
await context.Credentials.CreateAsync("example.com", new()
{
Id = knownCredentialId, // base64url
UserHandle = knownUserHandle, // base64url
PrivateKey = knownPrivateKey, // base64url PKCS#8 (DER)
PublicKey = knownPublicKey, // base64url SPKI (DER)
});
await context.Credentials.InstallAsync();

var page = await context.NewPageAsync();
await page.GotoAsync("https://example.com/login");
// The page's navigator.credentials.get() is answered with the seeded passkey.
```

**Usage: capture a passkey, then reuse it**

```csharp
// setup test: let the app register a passkey, then save it.
var context = await browser.NewContextAsync();
await context.Credentials.InstallAsync();

var page = await context.NewPageAsync();
await page.GotoAsync("https://example.com/register");
await page.GetByRole(AriaRole.Button, new() { Name = "Create a passkey" }).ClickAsync();

// Read back the passkey the page registered — it includes the private key.
var credentials = await context.Credentials.GetAsync(new() { RpId = "example.com" });
File.WriteAllText("playwright/.auth/passkey.json", JsonSerializer.Serialize(credentials[0]));
```

```csharp
// later test: seed the captured passkey so the app starts already enrolled.
var credential = JsonSerializer.Deserialize<VirtualCredential>(
File.ReadAllText("playwright/.auth/passkey.json"));
var context = await browser.NewContextAsync();
await context.Credentials.CreateAsync(credential.RpId, new()
{
Id = credential.Id,
UserHandle = credential.UserHandle,
PrivateKey = credential.PrivateKey,
PublicKey = credential.PublicKey,
});
await context.Credentials.InstallAsync();

var page = await context.NewPageAsync();
await page.GotoAsync("https://example.com/login");
// navigator.credentials.get() resolves the captured passkey — already signed in.
```

**Defaults**


Expand All @@ -28,20 +79,23 @@ There are two common ways to use it:

Seeds a virtual WebAuthn credential and returns it.

With only `rpId`, generates a fresh **ECDSA P-256** keypair, credential id and user handle. The seeded credential is discoverable (resident), so the page can resolve it from both username-then-passkey and usernameless passkey flows. The returned object carries the `privateKey` and `publicKey`, so it can be persisted to disk and re-seeded in a later test.
With only [rpId](/api/class-credentials.mdx#credentials-create-option-rp-id), generates a fresh **ECDSA P-256** keypair, credential id and user handle. The seeded credential is discoverable (resident), so the page can resolve it from both username-then-passkey and usernameless passkey flows. The returned object carries the private and public keys, so it can be persisted to disk and re-seeded in a later test.

To **import a known credential**, supply all four of `id`, `userHandle`, `privateKey` and `publicKey` together.
To **import a known credential**, supply all four of [Id](/api/class-credentials.mdx#credentials-create-option-id), [UserHandle](/api/class-credentials.mdx#credentials-create-option-user-handle), [PrivateKey](/api/class-credentials.mdx#credentials-create-option-private-key) and [PublicKey](/api/class-credentials.mdx#credentials-create-option-public-key) together.

Call [Credentials.InstallAsync()](/api/class-credentials.mdx#credentials-install) before navigating to a page that uses WebAuthn.

**Usage**

```csharp
await Credentials.CreateAsync(options);
await Credentials.CreateAsync(rpId, options);
```

**Arguments**
- `options` `CredentialsCreateOptions?`
- `rpId` [string]<a aria-hidden="true" tabIndex="-1" class="list-anchor-link" id="credentials-create-option-rp-id"/><a href="#credentials-create-option-rp-id" class="list-anchor">#</a>

Relying party id (typically the site's effective domain).
- `options` `CredentialsCreateOptions?` *(optional)*
- `Id` [string]? *(optional)*<a aria-hidden="true" tabIndex="-1" class="list-anchor-link" id="credentials-create-option-id"/><a href="#credentials-create-option-id" class="list-anchor">#</a>

Base64url-encoded credential id. Auto-generated if omitted.
Expand All @@ -51,9 +105,6 @@ await Credentials.CreateAsync(options);
- `PublicKey` [string]? *(optional)*<a aria-hidden="true" tabIndex="-1" class="list-anchor-link" id="credentials-create-option-public-key"/><a href="#credentials-create-option-public-key" class="list-anchor">#</a>

Base64url-encoded SPKI (DER) public key. Auto-generated if omitted.
- `RpId` [string]<a aria-hidden="true" tabIndex="-1" class="list-anchor-link" id="credentials-create-option-rp-id"/><a href="#credentials-create-option-rp-id" class="list-anchor">#</a>

Relying party id (typically the site's effective domain).
- `UserHandle` [string]? *(optional)*<a aria-hidden="true" tabIndex="-1" class="list-anchor-link" id="credentials-create-option-user-handle"/><a href="#credentials-create-option-user-handle" class="list-anchor">#</a>

Base64url-encoded user handle. Auto-generated if omitted.
Expand Down Expand Up @@ -104,9 +155,9 @@ await Credentials.DeleteAsync(id);

<font size="2" style={{position: "relative", top: "-20px"}}>Added in: v1.61</font><x-search>credentials.GetAsync</x-search>

Returns every credential currently held by the authenticator, optionally filtered by `rpId` or `id`. This includes both credentials seeded with [Credentials.CreateAsync()](/api/class-credentials.mdx#credentials-create) and credentials the page registered itself by calling `navigator.credentials.create()`.
Returns every credential currently held by the authenticator, optionally filtered by [RpId](/api/class-credentials.mdx#credentials-get-option-rp-id) or [Id](/api/class-credentials.mdx#credentials-get-option-id). This includes both credentials seeded with [Credentials.CreateAsync()](/api/class-credentials.mdx#credentials-create) and credentials the page registered itself by calling `navigator.credentials.create()`.

Each returned credential includes its `privateKey` and `publicKey`, so a passkey the app just registered can be saved and re-seeded into a later test with [Credentials.CreateAsync()](/api/class-credentials.mdx#credentials-create) — see the second example in the class overview.
Each returned credential includes its private and public keys, so a passkey the app just registered can be saved and re-seeded into a later test with [Credentials.CreateAsync()](/api/class-credentials.mdx#credentials-create) — see the second example in the class overview.

**Usage**

Expand Down Expand Up @@ -148,7 +199,7 @@ await Credentials.GetAsync(options);

Installs the virtual WebAuthn authenticator into the context, overriding `navigator.credentials.create()` and `navigator.credentials.get()` in all current and future pages. Call this before the page first touches `navigator.credentials`.

Required: until `install()` is called, no interception is in place and the page sees the platform's native (or absent) WebAuthn behaviour. Seeding credentials with [Credentials.CreateAsync()](/api/class-credentials.mdx#credentials-create) without `install()` populates the authenticator, but the page will never see those credentials.
Required: until [Credentials.InstallAsync()](/api/class-credentials.mdx#credentials-install) is called, no interception is in place and the page sees the platform's native (or absent) WebAuthn behaviour. Seeding credentials with [Credentials.CreateAsync()](/api/class-credentials.mdx#credentials-create) without installing populates the authenticator, but the page will never see those credentials.

**Usage**

Expand Down
8 changes: 4 additions & 4 deletions dotnet/docs/api/class-webstorage.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ await WebStorage.ClearAsync();

<font size="2" style={{position: "relative", top: "-20px"}}>Added in: v1.61</font><x-search>webStorage.GetItemAsync</x-search>

Returns the value for the given `name`, or `null` if the key is not present.
Returns the value for the given [name](/api/class-webstorage.mdx#web-storage-get-item-option-name) if present.

**Usage**

Expand All @@ -68,7 +68,7 @@ await WebStorage.GetItemAsync(name);

<font size="2" style={{position: "relative", top: "-20px"}}>Added in: v1.61</font><x-search>webStorage.ItemsAsync</x-search>

Returns all items in the storage as `name`/`value` pairs.
Returns all items in the storage as name/value pairs.

**Usage**

Expand All @@ -90,7 +90,7 @@ await WebStorage.ItemsAsync();

<font size="2" style={{position: "relative", top: "-20px"}}>Added in: v1.61</font><x-search>webStorage.RemoveItemAsync</x-search>

Removes the item with the given `name`. No-op if the item is absent.
Removes the item with the given [name](/api/class-webstorage.mdx#web-storage-remove-item-option-name). No-op if the item is absent.

**Usage**

Expand All @@ -112,7 +112,7 @@ await WebStorage.RemoveItemAsync(name);

<font size="2" style={{position: "relative", top: "-20px"}}>Added in: v1.61</font><x-search>webStorage.SetItemAsync</x-search>

Sets the value for the given `name`. Overwrites any existing value for that name.
Sets the value for the given [name](/api/class-webstorage.mdx#web-storage-set-item-option-name). Overwrites any existing value for that name.

**Usage**

Expand Down
2 changes: 2 additions & 0 deletions dotnet/docs/docker.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ We currently publish images with the following tags:
- `:v1.60.0` - Playwright v1.60.0 release docker image based on Ubuntu 24.04 LTS (Noble Numbat).
- `:v1.60.0-noble` - Playwright v1.60.0 release docker image based on Ubuntu 24.04 LTS (Noble Numbat).
- `:v1.60.0-jammy` - Playwright v1.60.0 release docker image based on Ubuntu 22.04 LTS (Jammy Jellyfish).
- `:v1.60.0-resolute` - Playwright v1.60.0 release docker image based on Ubuntu 26.04 LTS (Resolute Raccoon).

:::note

Expand All @@ -144,6 +145,7 @@ It is recommended to always pin your Docker image to a specific version if possi
### Base images

We currently publish images based on the following [Ubuntu](https://hub.docker.com/_/ubuntu) versions:
- **Ubuntu 26.04 LTS** (Resolute Raccoon), image tags include `resolute`
- **Ubuntu 24.04 LTS** (Noble Numbat), image tags include `noble`
- **Ubuntu 22.04 LTS** (Jammy Jellyfish), image tags include `jammy`

Expand Down
1 change: 1 addition & 0 deletions dotnet/docs/getting-started-cli.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ playwright-cli --help
Alternatively, install `@playwright/cli` as a local dependency and use `npx`:

```bash
npm install -D @playwright/cli@latest
npx playwright-cli --help
```

Expand Down
4 changes: 2 additions & 2 deletions dotnet/docs/intro.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -275,8 +275,8 @@ See our doc on [Running and Debugging Tests](./running-tests.mdx) to learn more
## System requirements
- Playwright is distributed as a .NET Standard 2.0 library. We recommend .NET 8.
- Windows 11+, Windows Server 2019+ or Windows Subsystem for Linux (WSL).
- macOS 14 Sonoma, or later.
- Debian 12, Debian 13, Ubuntu 22.04, Ubuntu 24.04, on x86-64 and arm64 architecture.
- macOS 14 (Sonoma) or later.
- Debian 12 / 13, Ubuntu 22.04 / 24.04 / 26.04 (x86-64 or arm64).

## What's next
- [Write tests using web first assertions, page fixtures and locators](./writing-tests.mdx)
Expand Down
55 changes: 55 additions & 0 deletions dotnet/docs/release-notes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,61 @@ import HTMLCard from '@site/src/components/HTMLCard';

import LiteYouTube from '@site/src/components/LiteYouTube';

## Version 1.61

### 🔑 WebAuthn passkeys

New [Credentials] virtual authenticator, available via [BrowserContext.Credentials](/api/class-browsercontext.mdx#browser-context-credentials), lets tests register passkeys and answer `navigator.credentials.create()` / `navigator.credentials.get()` ceremonies in the page — no real hardware key required, works in all browsers:

```csharp
var context = await browser.NewContextAsync();

// Seed a passkey your backend provisioned for a test user.
await context.Credentials.CreateAsync("example.com", new()
{
Id = credentialId,
UserHandle = userHandle,
PrivateKey = privateKey,
PublicKey = publicKey,
});
await context.Credentials.InstallAsync();

var page = await context.NewPageAsync();
await page.GotoAsync("https://example.com/login");
// The page's navigator.credentials.get() is answered with the seeded passkey.
```

You can also let the app register a passkey once in a setup test, read it back with [Credentials.GetAsync()](/api/class-credentials.mdx#credentials-get), and seed it into later tests — see [Credentials] for details.

### 🗃️ Web Storage

New [WebStorage] API, available via [Page.LocalStorage](/api/class-page.mdx#page-local-storage) and [Page.SessionStorage](/api/class-page.mdx#page-session-storage), reads and writes the page's storage for the current origin:

```csharp
await page.LocalStorage.SetItemAsync("token", "abc");
var token = await page.LocalStorage.GetItemAsync("token");
var items = await page.SessionStorage.ItemsAsync();
```

### New APIs
- [ApiResponse.SecurityDetailsAsync()](/api/class-apiresponse.mdx#api-response-security-details) and [ApiResponse.ServerAddrAsync()](/api/class-apiresponse.mdx#api-response-server-addr) mirror the browser-side [Response.SecurityDetailsAsync()](/api/class-response.mdx#response-security-details) and [Response.ServerAddrAsync()](/api/class-response.mdx#response-server-addr).
- New option `ArtifactsDir` in [BrowserType.ConnectOverCDPAsync()](/api/class-browsertype.mdx#browser-type-connect-over-cdp) controls where artifacts such as traces and downloads are stored when attached to an existing browser.
- New option `Cursor` in [Screencast.ShowActionsAsync()](/api/class-screencast.mdx#screencast-show-actions) controls the cursor decoration rendered for pointer actions.
- The `OnFrame` callback in [Screencast.StartAsync()](/api/class-screencast.mdx#screencast-start) now receives a `Timestamp` of when the frame was presented by the browser.

### 🛠️ Other improvements
- Playwright now supports Ubuntu 26.04.
- HAR and trace recordings now include WebSocket requests.

### Browser Versions
- Chromium 149.0.7827.55
- Mozilla Firefox 151.0
- WebKit 26.5

This version was also tested against the following stable channels:
- Google Chrome 149
- Microsoft Edge 149

## Version 1.60

### 🌐 HAR recording on Tracing
Expand Down
4 changes: 4 additions & 0 deletions java/docs/api/class-browsertype.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ Connecting over the Chrome DevTools Protocol is only supported for Chromium-base
This connection is significantly lower fidelity than the Playwright protocol connection via [BrowserType.connect()](/api/class-browsertype.mdx#browser-type-connect). If you are experiencing issues or attempting to use advanced functionality, you probably want to use [BrowserType.connect()](/api/class-browsertype.mdx#browser-type-connect).
:::

:::warning
Playwright maintains a curated list of arguments for launching the browser. If you launch the browser without Playwright and do not pass the exact same arguments, some of Playwright functionality may be broken upon connecting to the browser.
:::

**Usage**

```java
Expand Down
Loading
Loading