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
1 change: 1 addition & 0 deletions .claude/skills/playwright-dev/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ description: Explains how to develop Playwright - add APIs, MCP tools, CLI comma
- [Adding and Modifying APIs](api.md) — define API docs, implement client/server, add tests
- [MCP Tools and CLI Commands](mcp-dev.md) — add MCP tools, CLI commands, config options
- [Vendoring Dependencies](vendor.md) — bundle third-party npm packages into playwright-core or playwright
- [Uploading Fixes to GitHub](github.md) — branch naming, commit format, pushing fixes for issues

## Build
- Assume watch is running and everything is up to date.
Expand Down
56 changes: 56 additions & 0 deletions .claude/skills/playwright-dev/github.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Uploading a Fix for a GitHub Issue

## Branch naming

Create a branch named after the issue number:

```
git checkout -b fix-39562
```

## Committing changes

Use conventional commit format with a scope:

- `fix(proxy): description` — bug fixes
- `feat(locator): description` — new features
- `chore(cli): description` — maintenance, refactoring, tests

The commit body must be a single line: `Fixes: https://github.com/microsoft/playwright/issues/39562`

Stage only the files related to the fix. Do not use `git add -A` or `git add .`.

```
git add src/server/proxy.ts tests/proxy.spec.ts
git commit -m "$(cat <<'EOF'
fix(proxy): handle SOCKS proxy authentication

Fixes: https://github.com/microsoft/playwright/issues/39562
EOF
)"
```

## Pushing

Push the branch to origin:

```
git push origin fix-39562
```

## Full example

For issue https://github.com/microsoft/playwright/issues/39562:

```bash
git checkout -b fix-39562
# ... make changes ...
git add <changed-files>
git commit -m "$(cat <<'EOF'
fix(proxy): handle SOCKS proxy authentication

Fixes: https://github.com/microsoft/playwright/issues/39562
EOF
)"
git push origin fix-39562
```
2 changes: 1 addition & 1 deletion docs/src/api/class-cdpsession.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ Emitted when the session is closed, either because the target was closed or `ses
* since: v1.59
* langs: js
- argument: <[Object]>
- `name` <[string]> CDP event name.
- `method` <[string]> CDP event name.
- `params` ?<[Object]> CDP event parameters.

Emitted for every CDP event received from the session. Allows subscribing to all CDP events at once without knowing
Expand Down
2 changes: 1 addition & 1 deletion docs/src/test-agents-js.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ When the test fails, the healer agent:

**Output**

* A passing test, or a skipped test if the healer believes the that functionality is broken.
* A passing test, or a skipped test if the healer believes that functionality is broken.

## Artifacts and Conventions

Expand Down
4 changes: 3 additions & 1 deletion docs/src/trace-viewer.md
Original file line number Diff line number Diff line change
Expand Up @@ -686,7 +686,9 @@ public class WithTestNameAttribute : BeforeAfterTestAttribute
## Trace Viewer features
### Actions

In the Actions tab you can see what locator was used for every action and how long each one took to run. Hover over each action of your test and visually see the change in the DOM snapshot. Go back and forward in time and click an action to inspect and debug. Use the Before and After tabs to visually see what happened before and after the action.
In the Actions tab you can see what locator was used for every action and how long each one took to run. Use the **Filter actions** search field at the top of the list to filter the action hierarchy by text; only actions whose title matches the search (and their parent actions) are shown. Clear the filter to show all actions again; expanded nodes are preserved when the filter is removed.

Hover over each action of your test and visually see the change in the DOM snapshot. Go back and forward in time and click an action to inspect and debug. Use the Before and After tabs to visually see what happened before and after the action.

<img src="https://github.com/microsoft/playwright/assets/13063165/948b65cd-f0fd-4c7f-8e53-2c632b5a07f1" alt="actions tab in trace viewer" width="3598" height="2218" />

Expand Down
11 changes: 6 additions & 5 deletions packages/devtools/src/devtools.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const BUTTONS = ['left', 'middle', 'right'] as const;

export const DevTools: React.FC<{ wsUrl?: string }> = ({ wsUrl }) => {
const [interactive, setInteractive] = React.useState(false);
const [tabs, setTabs] = React.useState<Tab[]>([]);
const [tabs, setTabs] = React.useState<Tab[] | null>(null);
const [url, setUrl] = React.useState('');
const [frame, setFrame] = React.useState<DevToolsChannelEvents['frame']>();
const [showInspector, setShowInspector] = React.useState(false);
Expand Down Expand Up @@ -215,13 +215,14 @@ export const DevTools: React.FC<{ wsUrl?: string }> = ({ wsUrl }) => {
}
}

const selectedTab = tabs.find(t => t.selected);
const hasPages = !!selectedTab;
const selectedTab = tabs?.find(t => t.selected);

let overlayText: string | undefined;
if (!channel)
overlayText = 'Disconnected';
if (channel && !hasPages)
else if (tabs === null)
overlayText = 'Loading...';
else if (tabs.length === 0)
overlayText = 'No tabs open';

return (<div className={'devtools-view' + (interactive ? ' interactive' : '')}
Expand All @@ -233,7 +234,7 @@ export const DevTools: React.FC<{ wsUrl?: string }> = ({ wsUrl }) => {
Sessions
</a>
<div id='tabstrip' className='tabstrip' role='tablist'>
{tabs.map(tab => (
{tabs?.map(tab => (
<div
key={tab.pageId}
className={'tab' + (tab.selected ? ' active' : '')}
Expand Down
12 changes: 6 additions & 6 deletions packages/playwright-client/types/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16058,7 +16058,7 @@ export interface CDPSession {
/**
* CDP event name.
*/
name: string;
method: string;

/**
* CDP event parameters.
Expand All @@ -16078,7 +16078,7 @@ export interface CDPSession {
/**
* CDP event name.
*/
name: string;
method: string;

/**
* CDP event parameters.
Expand Down Expand Up @@ -16108,7 +16108,7 @@ export interface CDPSession {
/**
* CDP event name.
*/
name: string;
method: string;

/**
* CDP event parameters.
Expand All @@ -16128,7 +16128,7 @@ export interface CDPSession {
/**
* CDP event name.
*/
name: string;
method: string;

/**
* CDP event parameters.
Expand All @@ -16148,7 +16148,7 @@ export interface CDPSession {
/**
* CDP event name.
*/
name: string;
method: string;

/**
* CDP event parameters.
Expand Down Expand Up @@ -16178,7 +16178,7 @@ export interface CDPSession {
/**
* CDP event name.
*/
name: string;
method: string;

/**
* CDP event parameters.
Expand Down
6 changes: 3 additions & 3 deletions packages/playwright-core/src/client/cdpSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ export class CDPSession extends ChannelOwner<channels.CDPSessionChannel> impleme
constructor(parent: ChannelOwner, type: string, guid: string, initializer: channels.CDPSessionInitializer) {
super(parent, type, guid, initializer);

this._channel.on('event', ({ method, params }) => {
this.emit(method, params);
this.emit('event', { name: method, params });
this._channel.on('event', event => {
this.emit(event.method, event.params);
this.emit('event', event);
});

this._channel.on('close', () => {
Expand Down
3 changes: 2 additions & 1 deletion packages/playwright-core/src/server/chromium/chromium.ts
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,8 @@ export class Chromium extends BrowserType {
proxyBypassRules.push('<-loopback>');
if (proxy.bypass)
proxyBypassRules.push(...proxy.bypass.split(',').map(t => t.trim()).map(t => t.startsWith('.') ? '*' + t : t));
if (!process.env.PLAYWRIGHT_DISABLE_FORCED_CHROMIUM_PROXIED_LOOPBACK && !proxyBypassRules.includes('<-loopback>'))
const bypassesLoopback = proxyBypassRules.some(rule => rule === '<-loopback>' || rule === 'localhost' || rule === '127.0.0.1' || rule === '::1');
if (!process.env.PLAYWRIGHT_DISABLE_FORCED_CHROMIUM_PROXIED_LOOPBACK && !bypassesLoopback)
proxyBypassRules.push('<-loopback>');
if (proxyBypassRules.length > 0)
chromeArguments.push(`--proxy-bypass-list=${proxyBypassRules.join(';')}`);
Expand Down
4 changes: 4 additions & 0 deletions packages/playwright-core/src/utils/isomorphic/mimeType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ export function isJsonMimeType(mimeType: string) {
return !!mimeType.match(/^(application\/json|application\/.*?\+json|text\/(x-)?json)(;\s*charset=.*)?$/);
}

export function isXmlMimeType(mimeType: string) {
return !!mimeType.match(/^(application\/xml|application\/.*?\+xml|text\/xml)(;\s*charset=.*)?$/);
}

export function isTextualMimeType(mimeType: string) {
return !!mimeType.match(/^(text\/.*?|application\/(json|(x-)?javascript|xml.*?|ecmascript|graphql|x-www-form-urlencoded)|image\/svg(\+xml)?|application\/.*?(\+json|\+xml))(;\s*charset=.*)?$/);
}
Expand Down
12 changes: 6 additions & 6 deletions packages/playwright-core/types/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16058,7 +16058,7 @@ export interface CDPSession {
/**
* CDP event name.
*/
name: string;
method: string;

/**
* CDP event parameters.
Expand All @@ -16078,7 +16078,7 @@ export interface CDPSession {
/**
* CDP event name.
*/
name: string;
method: string;

/**
* CDP event parameters.
Expand Down Expand Up @@ -16108,7 +16108,7 @@ export interface CDPSession {
/**
* CDP event name.
*/
name: string;
method: string;

/**
* CDP event parameters.
Expand All @@ -16128,7 +16128,7 @@ export interface CDPSession {
/**
* CDP event name.
*/
name: string;
method: string;

/**
* CDP event parameters.
Expand All @@ -16148,7 +16148,7 @@ export interface CDPSession {
/**
* CDP event name.
*/
name: string;
method: string;

/**
* CDP event parameters.
Expand Down Expand Up @@ -16178,7 +16178,7 @@ export interface CDPSession {
/**
* CDP event name.
*/
name: string;
method: string;

/**
* CDP event parameters.
Expand Down
1 change: 1 addition & 0 deletions packages/playwright/src/isomorphic/testServerInterface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ export interface TestServerInterface {
locations?: string[];
grep?: string;
grepInvert?: string;
onlyChanged?: string;
}): Promise<{
report: ReportEntry[],
status: reporterTypes.FullResult['status']
Expand Down
2 changes: 2 additions & 0 deletions packages/playwright/src/runner/testRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export type ListTestsParams = {
locations?: string[];
grep?: string;
grepInvert?: string;
onlyChanged?: string;
};

export type RunTestsParams = {
Expand Down Expand Up @@ -271,6 +272,7 @@ export class TestRunner extends EventEmitter<TestRunnerEventMap> {
config.cliGrep = params.grep;
config.cliGrepInvert = params.grepInvert;
config.cliProjectFilter = params.projects?.length ? params.projects : undefined;
config.cliOnlyChanged = params.onlyChanged;
config.cliListOnly = true;

const status = await runTasks(new TestRun(config, reporter), [
Expand Down
Loading
Loading