Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/microsoft/playwright into d…
Browse files Browse the repository at this point in the history
…ialog-ui
  • Loading branch information
agg23 committed Dec 19, 2024
2 parents c51a74c + a239ab3 commit cf2da8d
Show file tree
Hide file tree
Showing 41 changed files with 738 additions and 65 deletions.
106 changes: 106 additions & 0 deletions docs/src/test-api/class-test.md
Original file line number Diff line number Diff line change
Expand Up @@ -1773,6 +1773,112 @@ Specifies a custom location for the step to be shown in test reports and trace v

Maximum time in milliseconds for the step to finish. Defaults to `0` (no timeout).

## async method: Test.step.fail
* since: v1.50
- returns: <[void]>

Marks a test step as "should fail". Playwright runs this test step and ensures that it actually fails. This is useful for documentation purposes to acknowledge that some functionality is broken until it is fixed.

:::note
If the step exceeds the timeout, a [TimeoutError] is thrown. This indicates the step did not fail as expected.
:::

**Usage**

You can declare a test step as failing, so that Playwright ensures it actually fails.

```js
import { test, expect } from '@playwright/test';

test('my test', async ({ page }) => {
// ...
await test.step.fail('currently failing', async () => {
// ...
});
});
```

### param: Test.step.fail.title
* since: v1.50
- `title` <[string]>

Step name.

### param: Test.step.fail.body
* since: v1.50
- `body` <[function]\(\):[Promise]<[any]>>

Step body.

### option: Test.step.fail.box
* since: v1.50
- `box` <boolean>

Whether to box the step in the report. Defaults to `false`. When the step is boxed, errors thrown from the step internals point to the step call site. See below for more details.

### option: Test.step.fail.location
* since: v1.50
- `location` <[Location]>

Specifies a custom location for the step to be shown in test reports and trace viewer. By default, location of the [`method: Test.step`] call is shown.

### option: Test.step.fail.timeout
* since: v1.50
- `timeout` <[float]>

Maximum time in milliseconds for the step to finish. Defaults to `0` (no timeout).

## async method: Test.step.fixme
* since: v1.50
- returns: <[void]>

Mark a test step as "fixme", with the intention to fix it. Playwright will not run the step.

**Usage**

You can declare a test step as failing, so that Playwright ensures it actually fails.

```js
import { test, expect } from '@playwright/test';

test('my test', async ({ page }) => {
// ...
await test.step.fixme('not yet ready', async () => {
// ...
});
});
```

### param: Test.step.fixme.title
* since: v1.50
- `title` <[string]>

Step name.

### param: Test.step.fixme.body
* since: v1.50
- `body` <[function]\(\):[Promise]<[any]>>

Step body.

### option: Test.step.fixme.box
* since: v1.50
- `box` <boolean>

Whether to box the step in the report. Defaults to `false`. When the step is boxed, errors thrown from the step internals point to the step call site. See below for more details.

### option: Test.step.fixme.location
* since: v1.50
- `location` <[Location]>

Specifies a custom location for the step to be shown in test reports and trace viewer. By default, location of the [`method: Test.step`] call is shown.

### option: Test.step.fixme.timeout
* since: v1.50
- `timeout` <[float]>

Maximum time in milliseconds for the step to finish. Defaults to `0` (no timeout).

## method: Test.use
* since: v1.10

Expand Down
8 changes: 7 additions & 1 deletion docs/src/test-global-setup-teardown-js.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,13 @@ You can use the `globalSetup` option in the [configuration file](./test-configur
Similarly, use `globalTeardown` to run something once after all the tests. Alternatively, let `globalSetup` return a function that will be used as a global teardown. You can pass data such as port number, authentication tokens, etc. from your global setup to your tests using environment variables.

:::note
Using `globalSetup` and `globalTeardown` will not produce traces or artifacts, and options like `headless` or `testIdAttribute` specified in the config file are not applied. If you want to produce traces and artifacts and respect config options, use [project dependencies](#option-1-project-dependencies).
Beware of `globalSetup` and `globalTeardown` caveats:

- These methods will not produce traces or artifacts unless explictly enabled, as described in [Capturing trace of failures during global setup](#capturing-trace-of-failures-during-global-setup).
- Options sush as `headless` or `testIdAttribute` specified in the config file are not applied,
- An uncaught exception thrown in `globalSetup` will prevent Playwright from running tests, and no test results will appear in reporters.

Consider using [project dependencies](#option-1-project-dependencies) to produce traces, artifacts, respect config options and get test results in reporters even in case of a setup failure.
:::

```js title="playwright.config.ts"
Expand Down
2 changes: 1 addition & 1 deletion packages/html-reporter/src/links.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ export function useIsAnchored(id: AnchorID) {
export function Anchor({ id, children }: React.PropsWithChildren<{ id: AnchorID }>) {
const ref = React.useRef<HTMLDivElement>(null);
const onAnchorReveal = React.useCallback(() => {
requestAnimationFrame(() => ref.current?.scrollIntoView({ block: 'start', inline: 'start' }));
ref.current?.scrollIntoView({ block: 'start', inline: 'start' });
}, []);
useAnchor(id, onAnchorReveal);

Expand Down
File renamed without changes.
8 changes: 4 additions & 4 deletions packages/playwright-core/browsers.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
},
{
"name": "chromium-tip-of-tree",
"revision": "1286",
"revision": "1287",
"installByDefault": false,
"browserVersion": "133.0.6891.0"
"browserVersion": "133.0.6901.0"
},
{
"name": "firefox",
Expand All @@ -27,7 +27,7 @@
},
{
"name": "webkit",
"revision": "2119",
"revision": "2120",
"installByDefault": true,
"revisionOverrides": {
"debian11-x64": "2105",
Expand All @@ -45,7 +45,7 @@
},
{
"name": "ffmpeg",
"revision": "1010",
"revision": "1011",
"installByDefault": true,
"revisionOverrides": {
"mac12": "1010",
Expand Down
8 changes: 5 additions & 3 deletions packages/playwright-core/src/remote/playwrightConnection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { debugLogger } from '../utils/debugLogger';
export type ClientType = 'controller' | 'launch-browser' | 'reuse-browser' | 'pre-launched-browser-or-android';

type Options = {
allowFSPaths: boolean,
socksProxyPattern: string | undefined,
browserName: string | null,
launchOptions: LaunchOptions,
Expand Down Expand Up @@ -60,7 +61,7 @@ export class PlaywrightConnection {
this._ws = ws;
this._preLaunched = preLaunched;
this._options = options;
options.launchOptions = filterLaunchOptions(options.launchOptions);
options.launchOptions = filterLaunchOptions(options.launchOptions, options.allowFSPaths);
if (clientType === 'reuse-browser' || clientType === 'pre-launched-browser-or-android')
assert(preLaunched.playwright);
if (clientType === 'pre-launched-browser-or-android')
Expand Down Expand Up @@ -284,7 +285,7 @@ function launchOptionsHash(options: LaunchOptions) {
return JSON.stringify(copy);
}

function filterLaunchOptions(options: LaunchOptions): LaunchOptions {
function filterLaunchOptions(options: LaunchOptions, allowFSPaths: boolean): LaunchOptions {
return {
channel: options.channel,
args: options.args,
Expand All @@ -296,7 +297,8 @@ function filterLaunchOptions(options: LaunchOptions): LaunchOptions {
chromiumSandbox: options.chromiumSandbox,
firefoxUserPrefs: options.firefoxUserPrefs,
slowMo: options.slowMo,
executablePath: isUnderTest() ? options.executablePath : undefined,
executablePath: (isUnderTest() || allowFSPaths) ? options.executablePath : undefined,
downloadsPath: allowFSPaths ? options.downloadsPath : undefined,
};
}

Expand Down
2 changes: 1 addition & 1 deletion packages/playwright-core/src/remote/playwrightServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export class PlaywrightServer {
return new PlaywrightConnection(
semaphore.acquire(),
clientType, ws,
{ socksProxyPattern: proxyValue, browserName, launchOptions },
{ socksProxyPattern: proxyValue, browserName, launchOptions, allowFSPaths: this._options.mode === 'extension' },
{
playwright: this._preLaunchedPlaywright,
browser: this._options.preLaunchedBrowser,
Expand Down
12 changes: 8 additions & 4 deletions packages/playwright-core/src/server/codegen/csharp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,10 @@ export class CSharpLanguageGenerator implements LanguageGenerator {
using var playwright = await Playwright.CreateAsync();
await using var browser = await playwright.${toPascal(options.browserName)}.LaunchAsync(${formatObject(options.launchOptions, ' ', 'BrowserTypeLaunchOptions')});
var context = await browser.NewContextAsync(${formatContextOptions(options.contextOptions, options.deviceName)});`);
if (options.contextOptions.recordHar)
formatter.add(` await context.RouteFromHARAsync(${quote(options.contextOptions.recordHar.path)});`);
if (options.contextOptions.recordHar) {
const url = options.contextOptions.recordHar.urlFilter;
formatter.add(` await context.RouteFromHARAsync(${quote(options.contextOptions.recordHar.path)}${url ? `, ${formatObject({ url }, ' ', 'BrowserContextRouteFromHAROptions')}` : ''});`);
}
formatter.newLine();
return formatter.format();
}
Expand All @@ -198,8 +200,10 @@ export class CSharpLanguageGenerator implements LanguageGenerator {
formatter.add(` [${this._mode === 'nunit' ? 'Test' : 'TestMethod'}]
public async Task MyTest()
{`);
if (options.contextOptions.recordHar)
formatter.add(` await context.RouteFromHARAsync(${quote(options.contextOptions.recordHar.path)});`);
if (options.contextOptions.recordHar) {
const url = options.contextOptions.recordHar.urlFilter;
formatter.add(` await Context.RouteFromHARAsync(${quote(options.contextOptions.recordHar.path)}${url ? `, ${formatObject({ url }, ' ', 'BrowserContextRouteFromHAROptions')}` : ''});`);
}
return formatter.format();
}

Expand Down
18 changes: 14 additions & 4 deletions packages/playwright-core/src/server/codegen/java.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,28 +150,38 @@ export class JavaLanguageGenerator implements LanguageGenerator {
import com.microsoft.playwright.Page;
import com.microsoft.playwright.options.*;
import org.junit.jupiter.api.*;
${options.contextOptions.recordHar ? `import java.nio.file.Paths;\n` : ''}import org.junit.jupiter.api.*;
import static com.microsoft.playwright.assertions.PlaywrightAssertions.*;
@UsePlaywright
public class TestExample {
@Test
void test(Page page) {`);
if (options.contextOptions.recordHar) {
const url = options.contextOptions.recordHar.urlFilter;
const recordHarOptions = typeof url === 'string' ? `, new Page.RouteFromHAROptions()
.setUrl(${quote(url)})` : '';
formatter.add(` page.routeFromHAR(Paths.get(${quote(options.contextOptions.recordHar.path)})${recordHarOptions});`);
}
return formatter.format();
}
formatter.add(`
import com.microsoft.playwright.*;
import com.microsoft.playwright.options.*;
import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
import java.util.*;
${options.contextOptions.recordHar ? `import java.nio.file.Paths;\n` : ''}import java.util.*;
public class Example {
public static void main(String[] args) {
try (Playwright playwright = Playwright.create()) {
Browser browser = playwright.${options.browserName}().launch(${formatLaunchOptions(options.launchOptions)});
BrowserContext context = browser.newContext(${formatContextOptions(options.contextOptions, options.deviceName)});`);
if (options.contextOptions.recordHar)
formatter.add(` context.routeFromHAR(${quote(options.contextOptions.recordHar.path)});`);
if (options.contextOptions.recordHar) {
const url = options.contextOptions.recordHar.urlFilter;
const recordHarOptions = typeof url === 'string' ? `, new BrowserContext.RouteFromHAROptions()
.setUrl(${quote(url)})` : '';
formatter.add(` context.routeFromHAR(Paths.get(${quote(options.contextOptions.recordHar.path)})${recordHarOptions});`);
}
return formatter.format();
}

Expand Down
6 changes: 4 additions & 2 deletions packages/playwright-core/src/server/codegen/javascript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,10 @@ export class JavaScriptLanguageGenerator implements LanguageGenerator {
import { test, expect${options.deviceName ? ', devices' : ''} } from '@playwright/test';
${useText ? '\ntest.use(' + useText + ');\n' : ''}
test('test', async ({ page }) => {`);
if (options.contextOptions.recordHar)
formatter.add(` await page.routeFromHAR(${quote(options.contextOptions.recordHar.path)});`);
if (options.contextOptions.recordHar) {
const url = options.contextOptions.recordHar.urlFilter;
formatter.add(` await page.routeFromHAR(${quote(options.contextOptions.recordHar.path)}${url ? `, ${formatOptions({ url }, false)}` : ''});`);
}
return formatter.format();
}

Expand Down
15 changes: 8 additions & 7 deletions packages/playwright-core/src/server/codegen/python.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ export class PythonLanguageGenerator implements LanguageGenerator {

generateHeader(options: LanguageGeneratorOptions): string {
const formatter = new PythonFormatter();
const recordHar = options.contextOptions.recordHar;
if (this._isPyTest) {
const contextOptions = formatContextOptions(options.contextOptions, options.deviceName, true /* asDict */);
const fixture = contextOptions ? `
Expand All @@ -146,13 +147,13 @@ def browser_context_args(browser_context_args, playwright) {
return {${contextOptions}}
}
` : '';
formatter.add(`${options.deviceName ? 'import pytest\n' : ''}import re
formatter.add(`${options.deviceName || contextOptions ? 'import pytest\n' : ''}import re
from playwright.sync_api import Page, expect
${fixture}
def test_example(page: Page) -> None {`);
if (options.contextOptions.recordHar)
formatter.add(` page.route_from_har(${quote(options.contextOptions.recordHar.path)})`);
if (recordHar)
formatter.add(` page.route_from_har(${quote(recordHar.path)}${typeof recordHar.urlFilter === 'string' ? `, url=${quote(recordHar.urlFilter)}` : ''})`);
} else if (this._isAsync) {
formatter.add(`
import asyncio
Expand All @@ -163,8 +164,8 @@ from playwright.async_api import Playwright, async_playwright, expect
async def run(playwright: Playwright) -> None {
browser = await playwright.${options.browserName}.launch(${formatOptions(options.launchOptions, false)})
context = await browser.new_context(${formatContextOptions(options.contextOptions, options.deviceName)})`);
if (options.contextOptions.recordHar)
formatter.add(` await page.route_from_har(${quote(options.contextOptions.recordHar.path)})`);
if (recordHar)
formatter.add(` await context.route_from_har(${quote(recordHar.path)}${typeof recordHar.urlFilter === 'string' ? `, url=${quote(recordHar.urlFilter)}` : ''})`);
} else {
formatter.add(`
import re
Expand All @@ -174,8 +175,8 @@ from playwright.sync_api import Playwright, sync_playwright, expect
def run(playwright: Playwright) -> None {
browser = playwright.${options.browserName}.launch(${formatOptions(options.launchOptions, false)})
context = browser.new_context(${formatContextOptions(options.contextOptions, options.deviceName)})`);
if (options.contextOptions.recordHar)
formatter.add(` context.route_from_har(${quote(options.contextOptions.recordHar.path)})`);
if (recordHar)
formatter.add(` context.route_from_har(${quote(recordHar.path)}${typeof recordHar.urlFilter === 'string' ? `, url=${quote(recordHar.urlFilter)}` : ''})`);
}
return formatter.format();
}
Expand Down
8 changes: 2 additions & 6 deletions packages/playwright-core/src/server/registry/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,9 @@ const PACKAGE_PATH = path.join(__dirname, '..', '..', '..');
const BIN_PATH = path.join(__dirname, '..', '..', '..', 'bin');

const PLAYWRIGHT_CDN_MIRRORS = [
'https://playwright.azureedge.net/dbazure/download/playwright', // ESRP CDN
'https://cdn.playwright.dev/dbazure/download/playwright', // ESRP CDN
'https://playwright.download.prss.microsoft.com/dbazure/download/playwright', // Directly hit ESRP CDN

// Old endpoints which hit the Storage Bucket directly:
'https://playwright.azureedge.net',
'https://playwright-akamai.azureedge.net', // Actually Edgio which will be retired Q4 2025.
'https://playwright-verizon.azureedge.net', // Actually Edgio which will be retired Q4 2025.
'https://cdn.playwright.dev', // Hit the Storage Bucket directly
];

if (process.env.PW_TEST_CDN_THAT_SHOULD_WORK) {
Expand Down
Loading

0 comments on commit cf2da8d

Please sign in to comment.