docs: align Node.js code snippets with ESLint (#23916)
This commit is contained in:
parent
71650f9bd1
commit
9980f054bc
|
@ -82,8 +82,8 @@ test('navigation menu flyout should not have automatically detectable accessibil
|
||||||
await page.locator('#navigation-menu-flyout').waitFor();
|
await page.locator('#navigation-menu-flyout').waitFor();
|
||||||
|
|
||||||
const accessibilityScanResults = await new AxeBuilder({ page })
|
const accessibilityScanResults = await new AxeBuilder({ page })
|
||||||
.include('#navigation-menu-flyout')
|
.include('#navigation-menu-flyout')
|
||||||
.analyze();
|
.analyze();
|
||||||
|
|
||||||
expect(accessibilityScanResults.violations).toEqual([]);
|
expect(accessibilityScanResults.violations).toEqual([]);
|
||||||
});
|
});
|
||||||
|
@ -102,8 +102,8 @@ test('should not have any automatically detectable WCAG A or AA violations', asy
|
||||||
await page.goto('https://your-site.com/');
|
await page.goto('https://your-site.com/');
|
||||||
|
|
||||||
const accessibilityScanResults = await new AxeBuilder({ page })
|
const accessibilityScanResults = await new AxeBuilder({ page })
|
||||||
.withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'])
|
.withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'])
|
||||||
.analyze();
|
.analyze();
|
||||||
|
|
||||||
expect(accessibilityScanResults.violations).toEqual([]);
|
expect(accessibilityScanResults.violations).toEqual([]);
|
||||||
});
|
});
|
||||||
|
@ -130,8 +130,8 @@ test('should not have any accessibility violations outside of elements with know
|
||||||
await page.goto('https://your-site.com/page-with-known-issues');
|
await page.goto('https://your-site.com/page-with-known-issues');
|
||||||
|
|
||||||
const accessibilityScanResults = await new AxeBuilder({ page })
|
const accessibilityScanResults = await new AxeBuilder({ page })
|
||||||
.exclude('#element-with-known-issue')
|
.exclude('#element-with-known-issue')
|
||||||
.analyze();
|
.analyze();
|
||||||
|
|
||||||
expect(accessibilityScanResults.violations).toEqual([]);
|
expect(accessibilityScanResults.violations).toEqual([]);
|
||||||
});
|
});
|
||||||
|
@ -150,8 +150,8 @@ test('should not have any accessibility violations outside of rules with known i
|
||||||
await page.goto('https://your-site.com/page-with-known-issues');
|
await page.goto('https://your-site.com/page-with-known-issues');
|
||||||
|
|
||||||
const accessibilityScanResults = await new AxeBuilder({ page })
|
const accessibilityScanResults = await new AxeBuilder({ page })
|
||||||
.disableRules(['duplicate-id'])
|
.disableRules(['duplicate-id'])
|
||||||
.analyze();
|
.analyze();
|
||||||
|
|
||||||
expect(accessibilityScanResults.violations).toEqual([]);
|
expect(accessibilityScanResults.violations).toEqual([]);
|
||||||
});
|
});
|
||||||
|
@ -176,14 +176,14 @@ expect(violationFingerprints(accessibilityScanResults)).toMatchSnapshot();
|
||||||
|
|
||||||
// my-test-utils.js
|
// my-test-utils.js
|
||||||
function violationFingerprints(accessibilityScanResults) {
|
function violationFingerprints(accessibilityScanResults) {
|
||||||
const violationFingerprints = accessibilityScanResults.violations.map(violation => ({
|
const violationFingerprints = accessibilityScanResults.violations.map(violation => ({
|
||||||
rule: violation.id,
|
rule: violation.id,
|
||||||
// These are CSS selectors which uniquely identify each element with
|
// These are CSS selectors which uniquely identify each element with
|
||||||
// a violation of the rule in question.
|
// a violation of the rule in question.
|
||||||
targets: violation.nodes.map(node => node.target),
|
targets: violation.nodes.map(node => node.target),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return JSON.stringify(violationFingerprints, null, 2);
|
return JSON.stringify(violationFingerprints, null, 2);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -238,8 +238,8 @@ type AxeFixture = {
|
||||||
export const test = base.extend<AxeFixture>({
|
export const test = base.extend<AxeFixture>({
|
||||||
makeAxeBuilder: async ({ page }, use, testInfo) => {
|
makeAxeBuilder: async ({ page }, use, testInfo) => {
|
||||||
const makeAxeBuilder = () => new AxeBuilder({ page })
|
const makeAxeBuilder = () => new AxeBuilder({ page })
|
||||||
.withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'])
|
.withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'])
|
||||||
.exclude('#commonly-reused-element-with-known-issue');
|
.exclude('#commonly-reused-element-with-known-issue');
|
||||||
|
|
||||||
await use(makeAxeBuilder);
|
await use(makeAxeBuilder);
|
||||||
}
|
}
|
||||||
|
@ -259,8 +259,8 @@ const AxeBuilder = require('@axe-core/playwright').default;
|
||||||
exports.test = base.test.extend({
|
exports.test = base.test.extend({
|
||||||
makeAxeBuilder: async ({ page }, use, testInfo) => {
|
makeAxeBuilder: async ({ page }, use, testInfo) => {
|
||||||
const makeAxeBuilder = () => new AxeBuilder({ page })
|
const makeAxeBuilder = () => new AxeBuilder({ page })
|
||||||
.withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'])
|
.withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'])
|
||||||
.exclude('#commonly-reused-element-with-known-issue');
|
.exclude('#commonly-reused-element-with-known-issue');
|
||||||
|
|
||||||
await use(makeAxeBuilder);
|
await use(makeAxeBuilder);
|
||||||
}
|
}
|
||||||
|
@ -279,10 +279,10 @@ test('example using custom fixture', async ({ page, makeAxeBuilder }) => {
|
||||||
await page.goto('https://your-site.com/');
|
await page.goto('https://your-site.com/');
|
||||||
|
|
||||||
const accessibilityScanResults = await makeAxeBuilder()
|
const accessibilityScanResults = await makeAxeBuilder()
|
||||||
// Automatically uses the shared AxeBuilder configuration,
|
// Automatically uses the shared AxeBuilder configuration,
|
||||||
// but supports additional test-specific configuration too
|
// but supports additional test-specific configuration too
|
||||||
.include('#specific-element-under-test')
|
.include('#specific-element-under-test')
|
||||||
.analyze();
|
.analyze();
|
||||||
|
|
||||||
expect(accessibilityScanResults.violations).toEqual([]);
|
expect(accessibilityScanResults.violations).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
|
@ -147,7 +147,7 @@ const USER = 'github-username';
|
||||||
'Authorization': `token ${process.env.API_TOKEN}`,
|
'Authorization': `token ${process.env.API_TOKEN}`,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})()
|
})();
|
||||||
```
|
```
|
||||||
|
|
||||||
## Sending API requests from UI tests
|
## Sending API requests from UI tests
|
||||||
|
@ -180,7 +180,7 @@ test.beforeAll(async ({ playwright }) => {
|
||||||
'Authorization': `token ${process.env.API_TOKEN}`,
|
'Authorization': `token ${process.env.API_TOKEN}`,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
test.afterAll(async ({ }) => {
|
test.afterAll(async ({ }) => {
|
||||||
// Dispose all responses.
|
// Dispose all responses.
|
||||||
|
@ -227,7 +227,7 @@ test.beforeAll(async ({ playwright }) => {
|
||||||
'Authorization': `token ${process.env.API_TOKEN}`,
|
'Authorization': `token ${process.env.API_TOKEN}`,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
test.afterAll(async ({ }) => {
|
test.afterAll(async ({ }) => {
|
||||||
// Dispose all responses.
|
// Dispose all responses.
|
||||||
|
@ -289,7 +289,7 @@ automatically update browser cookies if [APIResponse] has `Set-Cookie` header:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
test('context request will share cookie storage with its browser context', async ({ page, context }) => {
|
test('context request will share cookie storage with its browser context', async ({ page, context }) => {
|
||||||
await context.route('https://www.github.com/', async (route) => {
|
await context.route('https://www.github.com/', async route => {
|
||||||
// Send an API request that shares cookie storage with the browser context.
|
// Send an API request that shares cookie storage with the browser context.
|
||||||
const response = await context.request.fetch(route.request());
|
const response = await context.request.fetch(route.request());
|
||||||
const responseHeaders = response.headers();
|
const responseHeaders = response.headers();
|
||||||
|
@ -300,11 +300,11 @@ test('context request will share cookie storage with its browser context', async
|
||||||
expect(responseCookies.size).toBe(3);
|
expect(responseCookies.size).toBe(3);
|
||||||
const contextCookies = await context.cookies();
|
const contextCookies = await context.cookies();
|
||||||
// The browser context will already contain all the cookies from the API response.
|
// The browser context will already contain all the cookies from the API response.
|
||||||
expect(new Map(contextCookies.map(({name, value}) => [name, value]))).toEqual(responseCookies);
|
expect(new Map(contextCookies.map(({ name, value }) => [name, value]))).toEqual(responseCookies);
|
||||||
|
|
||||||
route.fulfill({
|
route.fulfill({
|
||||||
response,
|
response,
|
||||||
headers: {...responseHeaders, foo: 'bar'},
|
headers: { ...responseHeaders, foo: 'bar' },
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
await page.goto('https://www.github.com/');
|
await page.goto('https://www.github.com/');
|
||||||
|
@ -318,7 +318,7 @@ create a new instance of [APIRequestContext] which will have its own isolated co
|
||||||
test('global context request has isolated cookie storage', async ({ page, context, browser, playwright }) => {
|
test('global context request has isolated cookie storage', async ({ page, context, browser, playwright }) => {
|
||||||
// Create a new instance of APIRequestContext with isolated cookie storage.
|
// Create a new instance of APIRequestContext with isolated cookie storage.
|
||||||
const request = await playwright.request.newContext();
|
const request = await playwright.request.newContext();
|
||||||
await context.route('https://www.github.com/', async (route) => {
|
await context.route('https://www.github.com/', async route => {
|
||||||
const response = await request.fetch(route.request());
|
const response = await request.fetch(route.request());
|
||||||
const responseHeaders = response.headers();
|
const responseHeaders = response.headers();
|
||||||
|
|
||||||
|
@ -335,11 +335,11 @@ test('global context request has isolated cookie storage', async ({ page, contex
|
||||||
const browserContext2 = await browser.newContext({ storageState });
|
const browserContext2 = await browser.newContext({ storageState });
|
||||||
const contextCookies2 = await browserContext2.cookies();
|
const contextCookies2 = await browserContext2.cookies();
|
||||||
// The new browser context will already contain all the cookies from the API response.
|
// The new browser context will already contain all the cookies from the API response.
|
||||||
expect(new Map(contextCookies2.map(({name, value}) => [name, value]))).toEqual(responseCookies);
|
expect(new Map(contextCookies2.map(({ name, value }) => [name, value]))).toEqual(responseCookies);
|
||||||
|
|
||||||
route.fulfill({
|
route.fulfill({
|
||||||
response,
|
response,
|
||||||
headers: {...responseHeaders, foo: 'bar'},
|
headers: { ...responseHeaders, foo: 'bar' },
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
await page.goto('https://www.github.com/');
|
await page.goto('https://www.github.com/');
|
||||||
|
|
|
@ -299,7 +299,7 @@ be opened in Chrome DevTools performance panel.
|
||||||
**Usage**
|
**Usage**
|
||||||
|
|
||||||
```js
|
```js
|
||||||
await browser.startTracing(page, {path: 'trace.json'});
|
await browser.startTracing(page, { path: 'trace.json' });
|
||||||
await page.goto('https://www.google.com');
|
await page.goto('https://www.google.com');
|
||||||
await browser.stopTracing();
|
await browser.stopTracing();
|
||||||
```
|
```
|
||||||
|
|
|
@ -1307,7 +1307,7 @@ Sets the context's geolocation. Passing `null` or `undefined` emulates position
|
||||||
**Usage**
|
**Usage**
|
||||||
|
|
||||||
```js
|
```js
|
||||||
await browserContext.setGeolocation({latitude: 59.95, longitude: 30.31667});
|
await browserContext.setGeolocation({ latitude: 59.95, longitude: 30.31667 });
|
||||||
```
|
```
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|
|
@ -7,7 +7,7 @@ context.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// Listen for all console logs
|
// Listen for all console logs
|
||||||
page.on('console', msg => console.log(msg.text()))
|
page.on('console', msg => console.log(msg.text()));
|
||||||
|
|
||||||
// Listen for all console events and handle errors
|
// Listen for all console events and handle errors
|
||||||
page.on('console', msg => {
|
page.on('console', msg => {
|
||||||
|
@ -23,8 +23,8 @@ await page.evaluate(() => {
|
||||||
const msg = await msgPromise;
|
const msg = await msgPromise;
|
||||||
|
|
||||||
// Deconstruct console log arguments
|
// Deconstruct console log arguments
|
||||||
await msg.args()[0].jsonValue() // hello
|
await msg.args()[0].jsonValue(); // hello
|
||||||
await msg.args()[1].jsonValue() // 42
|
await msg.args()[1].jsonValue(); // 42
|
||||||
```
|
```
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|
|
@ -14,7 +14,7 @@ Coverage APIs are only supported on Chromium-based browsers.
|
||||||
const { chromium } = require('playwright');
|
const { chromium } = require('playwright');
|
||||||
const v8toIstanbul = require('v8-to-istanbul');
|
const v8toIstanbul = require('v8-to-istanbul');
|
||||||
|
|
||||||
(async() => {
|
(async () => {
|
||||||
const browser = await chromium.launch();
|
const browser = await chromium.launch();
|
||||||
const page = await browser.newPage();
|
const page = await browser.newPage();
|
||||||
await page.coverage.startJSCoverage();
|
await page.coverage.startJSCoverage();
|
||||||
|
|
|
@ -128,11 +128,11 @@ Convenience method that waits for the first application window to be opened.
|
||||||
**Usage**
|
**Usage**
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const electronApp = await electron.launch({
|
const electronApp = await electron.launch({
|
||||||
args: ['main.js']
|
args: ['main.js']
|
||||||
});
|
});
|
||||||
const window = await electronApp.firstWindow();
|
const window = await electronApp.firstWindow();
|
||||||
// ...
|
// ...
|
||||||
```
|
```
|
||||||
|
|
||||||
### option: ElectronApplication.firstWindow.timeout
|
### option: ElectronApplication.firstWindow.timeout
|
||||||
|
|
|
@ -984,7 +984,7 @@ To press a special key, like `Control` or `ArrowDown`, use [`method: ElementHand
|
||||||
|
|
||||||
```js
|
```js
|
||||||
await elementHandle.type('Hello'); // Types instantly
|
await elementHandle.type('Hello'); // Types instantly
|
||||||
await elementHandle.type('World', {delay: 100}); // Types slower, like a user
|
await elementHandle.type('World', { delay: 100 }); // Types slower, like a user
|
||||||
```
|
```
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|
|
@ -25,9 +25,8 @@ const { firefox } = require('playwright'); // Or 'chromium' or 'webkit'.
|
||||||
|
|
||||||
function dumpFrameTree(frame, indent) {
|
function dumpFrameTree(frame, indent) {
|
||||||
console.log(indent + frame.url());
|
console.log(indent + frame.url());
|
||||||
for (const child of frame.childFrames()) {
|
for (const child of frame.childFrames())
|
||||||
dumpFrameTree(child, indent + ' ');
|
dumpFrameTree(child, indent + ' ');
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
```
|
```
|
||||||
|
@ -733,8 +732,8 @@ If the function, passed to the [`method: Frame.evaluateHandle`], returns a [Prom
|
||||||
**Usage**
|
**Usage**
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
// Handle for the window object
|
||||||
const aWindowHandle = await frame.evaluateHandle(() => Promise.resolve(window));
|
const aWindowHandle = await frame.evaluateHandle(() => Promise.resolve(window));
|
||||||
aWindowHandle; // Handle for the window object.
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
@ -1739,7 +1738,7 @@ To press a special key, like `Control` or `ArrowDown`, use [`method: Keyboard.pr
|
||||||
|
|
||||||
```js
|
```js
|
||||||
await frame.type('#mytextarea', 'Hello'); // Types instantly
|
await frame.type('#mytextarea', 'Hello'); // Types instantly
|
||||||
await frame.type('#mytextarea', 'World', {delay: 100}); // Types slower, like a user
|
await frame.type('#mytextarea', 'World', { delay: 100 }); // Types slower, like a user
|
||||||
```
|
```
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
@ -1857,7 +1856,7 @@ const { firefox } = require('playwright'); // Or 'chromium' or 'webkit'.
|
||||||
const browser = await firefox.launch();
|
const browser = await firefox.launch();
|
||||||
const page = await browser.newPage();
|
const page = await browser.newPage();
|
||||||
const watchDog = page.mainFrame().waitForFunction('window.innerWidth < 100');
|
const watchDog = page.mainFrame().waitForFunction('window.innerWidth < 100');
|
||||||
await page.setViewportSize({width: 50, height: 50});
|
await page.setViewportSize({ width: 50, height: 50 });
|
||||||
await watchDog;
|
await watchDog;
|
||||||
await browser.close();
|
await browser.close();
|
||||||
})();
|
})();
|
||||||
|
@ -2137,7 +2136,7 @@ const { chromium } = require('playwright'); // Or 'firefox' or 'webkit'.
|
||||||
(async () => {
|
(async () => {
|
||||||
const browser = await chromium.launch();
|
const browser = await chromium.launch();
|
||||||
const page = await browser.newPage();
|
const page = await browser.newPage();
|
||||||
for (let currentURL of ['https://google.com', 'https://bbc.com']) {
|
for (const currentURL of ['https://google.com', 'https://bbc.com']) {
|
||||||
await page.goto(currentURL);
|
await page.goto(currentURL);
|
||||||
const element = await page.mainFrame().waitForSelector('img');
|
const element = await page.mainFrame().waitForSelector('img');
|
||||||
console.log('Loaded image: ' + await element.getAttribute('src'));
|
console.log('Loaded image: ' + await element.getAttribute('src'));
|
||||||
|
|
|
@ -132,7 +132,7 @@ The method returns a map with **own property names** as keys and JSHandle instan
|
||||||
**Usage**
|
**Usage**
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const handle = await page.evaluateHandle(() => ({window, document}));
|
const handle = await page.evaluateHandle(() => ({ window, document }));
|
||||||
const properties = await handle.getProperties();
|
const properties = await handle.getProperties();
|
||||||
const windowHandle = properties.get('window');
|
const windowHandle = properties.get('window');
|
||||||
const documentHandle = properties.get('document');
|
const documentHandle = properties.get('document');
|
||||||
|
@ -140,7 +140,7 @@ await handle.dispose();
|
||||||
```
|
```
|
||||||
|
|
||||||
```java
|
```java
|
||||||
JSHandle handle = page.evaluateHandle("() => ({window, document})");
|
JSHandle handle = page.evaluateHandle("() => ({ window, document })");
|
||||||
Map<String, JSHandle> properties = handle.getProperties();
|
Map<String, JSHandle> properties = handle.getProperties();
|
||||||
JSHandle windowHandle = properties.get("window");
|
JSHandle windowHandle = properties.get("window");
|
||||||
JSHandle documentHandle = properties.get("document");
|
JSHandle documentHandle = properties.get("document");
|
||||||
|
@ -148,7 +148,7 @@ handle.dispose();
|
||||||
```
|
```
|
||||||
|
|
||||||
```python async
|
```python async
|
||||||
handle = await page.evaluate_handle("({window, document})")
|
handle = await page.evaluate_handle("({ window, document })")
|
||||||
properties = await handle.get_properties()
|
properties = await handle.get_properties()
|
||||||
window_handle = properties.get("window")
|
window_handle = properties.get("window")
|
||||||
document_handle = properties.get("document")
|
document_handle = properties.get("document")
|
||||||
|
@ -156,7 +156,7 @@ await handle.dispose()
|
||||||
```
|
```
|
||||||
|
|
||||||
```python sync
|
```python sync
|
||||||
handle = page.evaluate_handle("({window, document})")
|
handle = page.evaluate_handle("({ window, document })")
|
||||||
properties = handle.get_properties()
|
properties = handle.get_properties()
|
||||||
window_handle = properties.get("window")
|
window_handle = properties.get("window")
|
||||||
document_handle = properties.get("document")
|
document_handle = properties.get("document")
|
||||||
|
@ -164,7 +164,7 @@ handle.dispose()
|
||||||
```
|
```
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
var handle = await page.EvaluateHandleAsync("() => ({window, document}");
|
var handle = await page.EvaluateHandleAsync("() => ({ window, document }");
|
||||||
var properties = await handle.GetPropertiesAsync();
|
var properties = await handle.GetPropertiesAsync();
|
||||||
var windowHandle = properties["window"];
|
var windowHandle = properties["window"];
|
||||||
var documentHandle = properties["document"];
|
var documentHandle = properties["document"];
|
||||||
|
|
|
@ -319,7 +319,7 @@ To press a special key, like `Control` or `ArrowDown`, use [`method: Keyboard.pr
|
||||||
|
|
||||||
```js
|
```js
|
||||||
await page.keyboard.type('Hello'); // Types instantly
|
await page.keyboard.type('Hello'); // Types instantly
|
||||||
await page.keyboard.type('World', {delay: 100}); // Types slower, like a user
|
await page.keyboard.type('World', { delay: 100 }); // Types slower, like a user
|
||||||
```
|
```
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|
|
@ -2145,7 +2145,7 @@ To press a special key, like `Control` or `ArrowDown`, use [`method: Locator.pre
|
||||||
|
|
||||||
```js
|
```js
|
||||||
await element.type('Hello'); // Types instantly
|
await element.type('Hello'); // Types instantly
|
||||||
await element.type('World', {delay: 100}); // Types slower, like a user
|
await element.type('World', { delay: 100 }); // Types slower, like a user
|
||||||
```
|
```
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|
|
@ -1750,8 +1750,8 @@ For example, given the following element:
|
||||||
```
|
```
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const locator = page.locator("id=favorite-colors");
|
const locator = page.locator('id=favorite-colors');
|
||||||
await locator.selectOption(["R", "G"]);
|
await locator.selectOption(['R', 'G']);
|
||||||
await expect(locator).toHaveValues([/R/, /G/]);
|
await expect(locator).toHaveValues([/R/, /G/]);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ const { chromium } = require('playwright'); // Or 'firefox' or 'webkit'.
|
||||||
log: (name, severity, message, args) => console.log(`${name} ${message}`)
|
log: (name, severity, message, args) => console.log(`${name} ${message}`)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
...
|
// ...
|
||||||
})();
|
})();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ const { webkit } = require('playwright'); // Or 'chromium' or 'firefox'.
|
||||||
const context = await browser.newContext();
|
const context = await browser.newContext();
|
||||||
const page = await context.newPage();
|
const page = await context.newPage();
|
||||||
await page.goto('https://example.com');
|
await page.goto('https://example.com');
|
||||||
await page.screenshot({path: 'screenshot.png'});
|
await page.screenshot({ path: 'screenshot.png' });
|
||||||
await browser.close();
|
await browser.close();
|
||||||
})();
|
})();
|
||||||
```
|
```
|
||||||
|
@ -338,7 +338,7 @@ Emitted when a file chooser is supposed to appear, such as after clicking the `
|
||||||
respond to it via setting the input files using [`method: FileChooser.setFiles`] that can be uploaded after that.
|
respond to it via setting the input files using [`method: FileChooser.setFiles`] that can be uploaded after that.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
page.on('filechooser', async (fileChooser) => {
|
page.on('filechooser', async fileChooser => {
|
||||||
await fileChooser.setFiles('/tmp/myfile.pdf');
|
await fileChooser.setFiles('/tmp/myfile.pdf');
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
@ -1508,7 +1508,7 @@ Console.WriteLine(await page.EvaluateAsync<int>("1 + 2")); // prints "3"
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const bodyHandle = await page.evaluate('document.body');
|
const bodyHandle = await page.evaluate('document.body');
|
||||||
const html = await page.evaluate(([body, suffix]) => body.innerHTML + suffix, [bodyHandle, 'hello']);
|
const html = await page.evaluate<string, HTMLElement>(([body, suffix]) => body.innerHTML + suffix, [bodyHandle, 'hello']);
|
||||||
await bodyHandle.dispose();
|
await bodyHandle.dispose();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1562,8 +1562,8 @@ promise to resolve and return its value.
|
||||||
**Usage**
|
**Usage**
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
// Handle for the window object.
|
||||||
const aWindowHandle = await page.evaluateHandle(() => Promise.resolve(window));
|
const aWindowHandle = await page.evaluateHandle(() => Promise.resolve(window));
|
||||||
aWindowHandle; // Handle for the window object.
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
@ -2796,8 +2796,8 @@ force rendering of exact colors.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// Generates a PDF with 'screen' media type.
|
// Generates a PDF with 'screen' media type.
|
||||||
await page.emulateMedia({media: 'screen'});
|
await page.emulateMedia({ media: 'screen' });
|
||||||
await page.pdf({path: 'page.pdf'});
|
await page.pdf({ path: 'page.pdf' });
|
||||||
```
|
```
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
@ -3777,7 +3777,7 @@ To press a special key, like `Control` or `ArrowDown`, use [`method: Keyboard.pr
|
||||||
|
|
||||||
```js
|
```js
|
||||||
await page.type('#mytextarea', 'Hello'); // Types instantly
|
await page.type('#mytextarea', 'Hello'); // Types instantly
|
||||||
await page.type('#mytextarea', 'World', {delay: 100}); // Types slower, like a user
|
await page.type('#mytextarea', 'World', { delay: 100 }); // Types slower, like a user
|
||||||
```
|
```
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
@ -4090,7 +4090,7 @@ const { webkit } = require('playwright'); // Or 'chromium' or 'firefox'.
|
||||||
const browser = await webkit.launch();
|
const browser = await webkit.launch();
|
||||||
const page = await browser.newPage();
|
const page = await browser.newPage();
|
||||||
const watchDog = page.waitForFunction(() => window.innerWidth < 100);
|
const watchDog = page.waitForFunction(() => window.innerWidth < 100);
|
||||||
await page.setViewportSize({width: 50, height: 50});
|
await page.setViewportSize({ width: 50, height: 50 });
|
||||||
await watchDog;
|
await watchDog;
|
||||||
await browser.close();
|
await browser.close();
|
||||||
})();
|
})();
|
||||||
|
@ -4698,7 +4698,7 @@ const { chromium } = require('playwright'); // Or 'firefox' or 'webkit'.
|
||||||
(async () => {
|
(async () => {
|
||||||
const browser = await chromium.launch();
|
const browser = await chromium.launch();
|
||||||
const page = await browser.newPage();
|
const page = await browser.newPage();
|
||||||
for (let currentURL of ['https://google.com', 'https://bbc.com']) {
|
for (const currentURL of ['https://google.com', 'https://bbc.com']) {
|
||||||
await page.goto(currentURL);
|
await page.goto(currentURL);
|
||||||
const element = await page.waitForSelector('img');
|
const element = await page.waitForSelector('img');
|
||||||
console.log('Loaded image: ' + await element.getAttribute('src'));
|
console.log('Loaded image: ' + await element.getAttribute('src'));
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { test, expect } from '@playwright/test';
|
||||||
|
|
||||||
test('status becomes submitted', async ({ page }) => {
|
test('status becomes submitted', async ({ page }) => {
|
||||||
// ...
|
// ...
|
||||||
await page.locator('#submit-button').click()
|
await page.locator('#submit-button').click();
|
||||||
await expect(page.locator('.status')).toHaveText('Submitted');
|
await expect(page.locator('.status')).toHaveText('Submitted');
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
|
@ -51,7 +51,7 @@ await page.route('**/*', (route, request) => {
|
||||||
foo: 'foo-value', // set "foo" header
|
foo: 'foo-value', // set "foo" header
|
||||||
bar: undefined, // remove "bar" header
|
bar: undefined, // remove "bar" header
|
||||||
};
|
};
|
||||||
route.continue({headers});
|
route.continue({ headers });
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -337,7 +337,7 @@ await page.route('**/*', (route, request) => {
|
||||||
foo: 'foo-value', // set "foo" header
|
foo: 'foo-value', // set "foo" header
|
||||||
bar: undefined, // remove "bar" header
|
bar: undefined, // remove "bar" header
|
||||||
};
|
};
|
||||||
route.fallback({headers});
|
route.fallback({ headers });
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -12,12 +12,12 @@ const playwright = require('playwright');
|
||||||
const context = await browser.newContext();
|
const context = await browser.newContext();
|
||||||
const page = await context.newPage();
|
const page = await context.newPage();
|
||||||
try {
|
try {
|
||||||
await page.locator("text=Foo").click({
|
await page.locator('text=Foo').click({
|
||||||
timeout: 100,
|
timeout: 100,
|
||||||
})
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof playwright.errors.TimeoutError)
|
if (error instanceof playwright.errors.TimeoutError)
|
||||||
console.log("Timeout!")
|
console.log('Timeout!');
|
||||||
}
|
}
|
||||||
await browser.close();
|
await browser.close();
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -1302,9 +1302,13 @@ By default, the `data-testid` attribute is used as a test id. Use [`method: Sele
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// Set custom test id attribute from @playwright/test config:
|
// Set custom test id attribute from @playwright/test config:
|
||||||
use: {
|
import { defineConfig } from '@playwright/test';
|
||||||
testIdAttribute: 'data-pw'
|
|
||||||
}
|
export default defineConfig({
|
||||||
|
use: {
|
||||||
|
testIdAttribute: 'data-pw'
|
||||||
|
},
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
## template-locator-get-by-text
|
## template-locator-get-by-text
|
||||||
|
@ -1327,19 +1331,19 @@ You can locate by text substring, exact string, or a regular expression:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// Matches <span>
|
// Matches <span>
|
||||||
page.getByText('world')
|
page.getByText('world');
|
||||||
|
|
||||||
// Matches first <div>
|
// Matches first <div>
|
||||||
page.getByText('Hello world')
|
page.getByText('Hello world');
|
||||||
|
|
||||||
// Matches second <div>
|
// Matches second <div>
|
||||||
page.getByText('Hello', { exact: true })
|
page.getByText('Hello', { exact: true });
|
||||||
|
|
||||||
// Matches both <div>s
|
// Matches both <div>s
|
||||||
page.getByText(/Hello/)
|
page.getByText(/Hello/);
|
||||||
|
|
||||||
// Matches second <div>
|
// Matches second <div>
|
||||||
page.getByText(/^hello$/i)
|
page.getByText(/^hello$/i);
|
||||||
```
|
```
|
||||||
|
|
||||||
```python async
|
```python async
|
||||||
|
@ -1503,8 +1507,8 @@ You can fill the input after locating it by the placeholder text:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
await page
|
await page
|
||||||
.getByPlaceholder("name@example.com")
|
.getByPlaceholder('name@example.com')
|
||||||
.fill("playwright@microsoft.com");
|
.fill('playwright@microsoft.com');
|
||||||
```
|
```
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|
|
@ -497,7 +497,7 @@ You can introduce fixtures that will provide a page authenticated as each role.
|
||||||
Below is an example that [creates fixtures](./test-fixtures.md#creating-a-fixture) for two [Page Object Models](./pom.md) - admin POM and user POM. It assumes `adminStorageState.json` and `userStorageState.json` files were created in the global setup.
|
Below is an example that [creates fixtures](./test-fixtures.md#creating-a-fixture) for two [Page Object Models](./pom.md) - admin POM and user POM. It assumes `adminStorageState.json` and `userStorageState.json` files were created in the global setup.
|
||||||
|
|
||||||
```js title="playwright/fixtures.ts"
|
```js title="playwright/fixtures.ts"
|
||||||
import { test as base, Page, Locator } from '@playwright/test';
|
import { test as base, type Page, type Locator } from '@playwright/test';
|
||||||
|
|
||||||
// Page Object Model for the "admin" page.
|
// Page Object Model for the "admin" page.
|
||||||
// Here you can add locators and helper methods specific to the admin page.
|
// Here you can add locators and helper methods specific to the admin page.
|
||||||
|
@ -579,9 +579,8 @@ fs.writeFileSync('playwright/.auth/session.json', JSON.stringify(sessionStorage)
|
||||||
const sessionStorage = JSON.parse(fs.readFileSync('playwright/.auth/session.json', 'utf-8'));
|
const sessionStorage = JSON.parse(fs.readFileSync('playwright/.auth/session.json', 'utf-8'));
|
||||||
await context.addInitScript(storage => {
|
await context.addInitScript(storage => {
|
||||||
if (window.location.hostname === 'example.com') {
|
if (window.location.hostname === 'example.com') {
|
||||||
for (const [key, value] of Object.entries(storage)) {
|
for (const [key, value] of Object.entries(storage))
|
||||||
window.sessionStorage.setItem(key, value);
|
window.sessionStorage.setItem(key, value);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, sessionStorage);
|
}, sessionStorage);
|
||||||
```
|
```
|
||||||
|
|
|
@ -65,7 +65,8 @@ If working with a database then make sure you control the data. Test against a s
|
||||||
In order to write end to end tests we need to first find elements on the webpage. We can do this by using Playwright's built in [locators](./locators.md). Locators come with auto waiting and retry-ability. Auto waiting means that Playwright performs a range of actionability checks on the elements, such as ensuring the element is visible and enabled before it performs the click. To make tests resilient, we recommend prioritizing user-facing attributes and explicit contracts.
|
In order to write end to end tests we need to first find elements on the webpage. We can do this by using Playwright's built in [locators](./locators.md). Locators come with auto waiting and retry-ability. Auto waiting means that Playwright performs a range of actionability checks on the elements, such as ensuring the element is visible and enabled before it performs the click. To make tests resilient, we recommend prioritizing user-facing attributes and explicit contracts.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
👍 page.getByRole('button', { name: 'submit' })
|
// 👍
|
||||||
|
page.getByRole('button', { name: 'submit' });
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Use chaining and filtering
|
#### Use chaining and filtering
|
||||||
|
@ -92,13 +93,15 @@ Your DOM can easily change so having your tests depend on your DOM structure can
|
||||||
|
|
||||||
|
|
||||||
```js
|
```js
|
||||||
👎 page.locator('button.buttonIcon.episode-actions-later')
|
// 👎
|
||||||
|
page.locator('button.buttonIcon.episode-actions-later');
|
||||||
```
|
```
|
||||||
|
|
||||||
Use locators that are resilient to changes in the DOM.
|
Use locators that are resilient to changes in the DOM.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
👍 page.getByRole('button', { name: 'submit' })
|
// 👍
|
||||||
|
page.getByRole('button', { name: 'submit' });
|
||||||
```
|
```
|
||||||
### Generate locators
|
### Generate locators
|
||||||
|
|
||||||
|
@ -129,9 +132,11 @@ You can also use the [VS Code Extension](./getting-started-vscode.md) to generat
|
||||||
Assertions are a way to verify that the expected result and the actual result matched or not. By using [web first assertions](./test-assertions.md) Playwright will wait until the expected condition is met. For example, when testing an alert message, a test would click a button that makes a message appear and check that the alert message is there. If the alert message takes half a second to appear, assertions such as `toBeVisible()` will wait and retry if needed.
|
Assertions are a way to verify that the expected result and the actual result matched or not. By using [web first assertions](./test-assertions.md) Playwright will wait until the expected condition is met. For example, when testing an alert message, a test would click a button that makes a message appear and check that the alert message is there. If the alert message takes half a second to appear, assertions such as `toBeVisible()` will wait and retry if needed.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
👍 await expect(page.getByText('welcome')).toBeVisible();
|
// 👍
|
||||||
|
await expect(page.getByText('welcome')).toBeVisible();
|
||||||
|
|
||||||
👎 expect(await page.getByText('welcome').isVisible()).toBe(true);
|
// 👎
|
||||||
|
expect(await page.getByText('welcome').isVisible()).toBe(true);
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Don't use manual assertions
|
#### Don't use manual assertions
|
||||||
|
@ -139,13 +144,15 @@ Assertions are a way to verify that the expected result and the actual result ma
|
||||||
Don't use manual assertions that are not awaiting the expect. In the code below the await is inside the expect rather than before it. When using assertions such as `isVisible()` the test won't wait a single second, it will just check the locator is there and return immediately.
|
Don't use manual assertions that are not awaiting the expect. In the code below the await is inside the expect rather than before it. When using assertions such as `isVisible()` the test won't wait a single second, it will just check the locator is there and return immediately.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
👎 expect(await page.getByText('welcome').isVisible()).toBe(true);
|
// 👎
|
||||||
|
expect(await page.getByText('welcome').isVisible()).toBe(true);
|
||||||
```
|
```
|
||||||
|
|
||||||
Use web first assertions such as `toBeVisible()` instead.
|
Use web first assertions such as `toBeVisible()` instead.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
👍 await expect(page.getByText('welcome')).toBeVisible();
|
// 👍
|
||||||
|
await expect(page.getByText('welcome')).toBeVisible();
|
||||||
```
|
```
|
||||||
|
|
||||||
### Configure debugging
|
### Configure debugging
|
||||||
|
@ -162,7 +169,7 @@ You can live debug your test by clicking or editing the locators in your test in
|
||||||
|
|
||||||
You can also debug your tests with the Playwright inspector by running your tests with the `--debug` flag.
|
You can also debug your tests with the Playwright inspector by running your tests with the `--debug` flag.
|
||||||
|
|
||||||
```js
|
```bash
|
||||||
npx playwright test --debug
|
npx playwright test --debug
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -174,7 +181,7 @@ You can then step through your test, view actionability logs and edit the locato
|
||||||
|
|
||||||
To debug a specific test add the name of the test file and the line number of the test followed by the `--debug` flag.
|
To debug a specific test add the name of the test file and the line number of the test followed by the `--debug` flag.
|
||||||
|
|
||||||
```js
|
```bash
|
||||||
npx playwright test example.spec.ts:9 --debug
|
npx playwright test example.spec.ts:9 --debug
|
||||||
```
|
```
|
||||||
#### Debugging on CI
|
#### Debugging on CI
|
||||||
|
@ -185,12 +192,12 @@ For CI failures, use the Playwright [trace viewer](./trace-viewer.md) instead of
|
||||||
|
|
||||||
Traces are configured in the Playwright config file and are set to run on CI on the first retry of a failed test. We don't recommend setting this to `on` so that traces are run on every test as it's very performance heavy. However you can run a trace locally when developing with the `--trace` flag.
|
Traces are configured in the Playwright config file and are set to run on CI on the first retry of a failed test. We don't recommend setting this to `on` so that traces are run on every test as it's very performance heavy. However you can run a trace locally when developing with the `--trace` flag.
|
||||||
|
|
||||||
```js
|
```bash
|
||||||
npx playwright test --trace on
|
npx playwright test --trace on
|
||||||
```
|
```
|
||||||
Once you run this command your traces will be recorded for each test and can be viewed directly from the HTML report.
|
Once you run this command your traces will be recorded for each test and can be viewed directly from the HTML report.
|
||||||
|
|
||||||
```js
|
```bash
|
||||||
npx playwright show-report
|
npx playwright show-report
|
||||||
````
|
````
|
||||||
|
|
||||||
|
@ -237,14 +244,14 @@ export default defineConfig({
|
||||||
|
|
||||||
By keeping your Playwright version up to date you will be able to test your app on the latest browser versions and catch failures before the latest browser version is released to the public.
|
By keeping your Playwright version up to date you will be able to test your app on the latest browser versions and catch failures before the latest browser version is released to the public.
|
||||||
|
|
||||||
```js
|
```bash
|
||||||
npm install -D @playwright/test@latest
|
npm install -D @playwright/test@latest
|
||||||
```
|
```
|
||||||
Check the [release notes](./release-notes.md) to see what the latest version is and what changes have been released.
|
Check the [release notes](./release-notes.md) to see what the latest version is and what changes have been released.
|
||||||
|
|
||||||
You can see what version of Playwright you have by running the following command.
|
You can see what version of Playwright you have by running the following command.
|
||||||
|
|
||||||
```js
|
```bash
|
||||||
npx playwright --version
|
npx playwright --version
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -273,7 +280,7 @@ test('runs in parallel 2', async ({ page }) => { /* ... */ });
|
||||||
|
|
||||||
Playwright can [shard](./test-parallel.md#shard-tests-between-multiple-machines) a test suite, so that it can be executed on multiple machines.
|
Playwright can [shard](./test-parallel.md#shard-tests-between-multiple-machines) a test suite, so that it can be executed on multiple machines.
|
||||||
|
|
||||||
```js
|
```bash
|
||||||
npx playwright test --shard=1/3
|
npx playwright test --shard=1/3
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -611,7 +611,11 @@ steps:
|
||||||
```
|
```
|
||||||
Note: The JUnit reporter needs to be configured accordingly via
|
Note: The JUnit reporter needs to be configured accordingly via
|
||||||
```js
|
```js
|
||||||
["junit", { outputFile: "test-results/e2e-junit-results.xml" }]
|
import { defineConfig } from '@playwright/test';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
reporter: ['junit', { outputFile: 'test-results/e2e-junit-results.xml' }],
|
||||||
|
});
|
||||||
```
|
```
|
||||||
in `playwright.config.ts`.
|
in `playwright.config.ts`.
|
||||||
|
|
||||||
|
|
|
@ -501,7 +501,7 @@ Change the location later:
|
||||||
import { test, expect } from '@playwright/test';
|
import { test, expect } from '@playwright/test';
|
||||||
|
|
||||||
test.use({
|
test.use({
|
||||||
geolocation: { longitude: 41.890221, latitude: 12.492348},
|
geolocation: { longitude: 41.890221, latitude: 12.492348 },
|
||||||
permissions: ['geolocation'],
|
permissions: ['geolocation'],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -662,7 +662,7 @@ The User Agent is included in the device and therefore you will rarely need to
|
||||||
```js tab=js-test title="tests/example.spec.ts"
|
```js tab=js-test title="tests/example.spec.ts"
|
||||||
import { test, expect } from '@playwright/test';
|
import { test, expect } from '@playwright/test';
|
||||||
|
|
||||||
test.use({ userAgent: 'My user agent'});
|
test.use({ userAgent: 'My user agent' });
|
||||||
|
|
||||||
test('my user agent test', async ({ page }) => {
|
test('my user agent test', async ({ page }) => {
|
||||||
// ...
|
// ...
|
||||||
|
|
|
@ -163,7 +163,7 @@ await page.GotoAsync("https://www.openstreetmap.org/");
|
||||||
If a certain event needs to be handled once, there is a convenience API for that:
|
If a certain event needs to be handled once, there is a convenience API for that:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
page.once('dialog', dialog => dialog.accept("2021"));
|
page.once('dialog', dialog => dialog.accept('2021'));
|
||||||
await page.evaluate("prompt('Enter a number:')");
|
await page.evaluate("prompt('Enter a number:')");
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -88,7 +88,7 @@ Using [`method: Locator.setChecked`] is the easiest way to check and uncheck a c
|
||||||
await page.getByLabel('I agree to the terms above').check();
|
await page.getByLabel('I agree to the terms above').check();
|
||||||
|
|
||||||
// Assert the checked state
|
// Assert the checked state
|
||||||
expect(await page.getByLabel('Subscribe to newsletter').isChecked()).toBeTruthy()
|
expect(await page.getByLabel('Subscribe to newsletter').isChecked()).toBeTruthy();
|
||||||
|
|
||||||
// Select the radio button
|
// Select the radio button
|
||||||
await page.getByLabel('XL').check();
|
await page.getByLabel('XL').check();
|
||||||
|
@ -219,7 +219,7 @@ await page.getByText('Item').click({ modifiers: ['Shift'] });
|
||||||
await page.getByText('Item').hover();
|
await page.getByText('Item').hover();
|
||||||
|
|
||||||
// Click the top left corner
|
// Click the top left corner
|
||||||
await page.getByText('Item').click({ position: { x: 0, y: 0} });
|
await page.getByText('Item').click({ position: { x: 0, y: 0 } });
|
||||||
```
|
```
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|
|
@ -33,7 +33,7 @@ import assert from 'node:assert';
|
||||||
// Teardown
|
// Teardown
|
||||||
await context.close();
|
await context.close();
|
||||||
await browser.close();
|
await browser.close();
|
||||||
})()
|
})();
|
||||||
```
|
```
|
||||||
|
|
||||||
```js tab=js-js
|
```js tab=js-js
|
||||||
|
@ -55,7 +55,7 @@ const { chromium, devices } = require('playwright');
|
||||||
// Teardown
|
// Teardown
|
||||||
await context.close();
|
await context.close();
|
||||||
await browser.close();
|
await browser.close();
|
||||||
})()
|
})();
|
||||||
```
|
```
|
||||||
|
|
||||||
Run it with `node my-script.js`.
|
Run it with `node my-script.js`.
|
||||||
|
@ -185,7 +185,7 @@ Playwright includes built-in support for TypeScript. Type definitions will be im
|
||||||
Add the following to the top of your JavaScript file to get type-checking in VS Code or WebStorm.
|
Add the following to the top of your JavaScript file to get type-checking in VS Code or WebStorm.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
//@ts-check
|
// @ts-check
|
||||||
// ...
|
// ...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -112,7 +112,7 @@ DOM changes in between the calls due to re-render, the new element corresponding
|
||||||
locator will be used.
|
locator will be used.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const locator = page.getByRole('button', { name: 'Sign in' })
|
const locator = page.getByRole('button', { name: 'Sign in' });
|
||||||
|
|
||||||
await locator.hover();
|
await locator.hover();
|
||||||
await locator.click();
|
await locator.click();
|
||||||
|
@ -316,8 +316,8 @@ You can fill the input after locating it by the placeholder text:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
await page
|
await page
|
||||||
.getByPlaceholder("name@example.com")
|
.getByPlaceholder('name@example.com')
|
||||||
.fill("playwright@microsoft.com");
|
.fill('playwright@microsoft.com');
|
||||||
```
|
```
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
@ -932,9 +932,9 @@ Locators support an option to only select elements that have or have not a desce
|
||||||
```js
|
```js
|
||||||
await page
|
await page
|
||||||
.getByRole('listitem')
|
.getByRole('listitem')
|
||||||
.filter({ has: page.getByRole('heading', { name: 'Product 2' })})
|
.filter({ has: page.getByRole('heading', { name: 'Product 2' }) })
|
||||||
.getByRole('button', { name: 'Add to cart' })
|
.getByRole('button', { name: 'Add to cart' })
|
||||||
.click()
|
.click();
|
||||||
```
|
```
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
@ -1531,9 +1531,9 @@ To take a screenshot of the row with "Mary" and "Say goodbye":
|
||||||
const rowLocator = page.getByRole('listitem');
|
const rowLocator = page.getByRole('listitem');
|
||||||
|
|
||||||
await rowLocator
|
await rowLocator
|
||||||
.filter({ hasText: 'Mary' })
|
.filter({ hasText: 'Mary' })
|
||||||
.filter({ has: page.getByRole('button', { name: 'Say goodbye' }) })
|
.filter({ has: page.getByRole('button', { name: 'Say goodbye' }) })
|
||||||
.screenshot({ path: 'screenshot.png' });
|
.screenshot({ path: 'screenshot.png' });
|
||||||
```
|
```
|
||||||
|
|
||||||
```python async
|
```python async
|
||||||
|
|
|
@ -130,7 +130,7 @@ test('update battery status (no golden)', async ({ page }) => {
|
||||||
this.charging = value;
|
this.charging = value;
|
||||||
this._chargingListeners.forEach(cb => cb());
|
this._chargingListeners.forEach(cb => cb());
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
const mockBattery = new BatteryMock();
|
const mockBattery = new BatteryMock();
|
||||||
// Override the method to always return mock battery info.
|
// Override the method to always return mock battery info.
|
||||||
window.navigator.getBattery = async () => mockBattery;
|
window.navigator.getBattery = async () => mockBattery;
|
||||||
|
|
|
@ -194,7 +194,7 @@ const browser = await chromium.launch({
|
||||||
});
|
});
|
||||||
const context = await browser.newContext({
|
const context = await browser.newContext({
|
||||||
proxy: { server: 'http://myproxy.com:3128' }
|
proxy: { server: 'http://myproxy.com:3128' }
|
||||||
})
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
@ -555,8 +555,7 @@ await page.route('**/*.{png,jpg,jpeg}', route => route.abort());
|
||||||
|
|
||||||
// Abort based on the request type
|
// Abort based on the request type
|
||||||
await page.route('**/*', route => {
|
await page.route('**/*', route => {
|
||||||
return route.request().resourceType() === 'image' ?
|
return route.request().resourceType() === 'image' ? route.abort() : route.continue();
|
||||||
route.abort() : route.continue();
|
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -901,9 +901,9 @@ is equivalent to
|
||||||
|
|
||||||
```js browser
|
```js browser
|
||||||
document
|
document
|
||||||
.querySelector('article')
|
.querySelector('article')
|
||||||
.querySelector('.bar > .baz')
|
.querySelector('.bar > .baz')
|
||||||
.querySelector('span[attr=value]')
|
.querySelector('span[attr=value]');
|
||||||
```
|
```
|
||||||
|
|
||||||
If a selector needs to include `>>` in the body, it should be escaped inside a string to not be confused with chaining separator, e.g. `text="some >> text"`.
|
If a selector needs to include `>>` in the body, it should be escaped inside a string to not be confused with chaining separator, e.g. `text="some >> text"`.
|
||||||
|
|
|
@ -195,7 +195,7 @@ If the action that triggers the new page is unknown, the following pattern can b
|
||||||
context.on('page', async page => {
|
context.on('page', async page => {
|
||||||
await page.waitForLoadState();
|
await page.waitForLoadState();
|
||||||
console.log(await page.title());
|
console.log(await page.title());
|
||||||
})
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
@ -295,7 +295,7 @@ If the action that triggers the popup is unknown, the following pattern can be u
|
||||||
page.on('popup', async popup => {
|
page.on('popup', async popup => {
|
||||||
await popup.waitForLoadState();
|
await popup.waitForLoadState();
|
||||||
console.log(await popup.title());
|
console.log(await popup.title());
|
||||||
})
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|
|
@ -42,11 +42,11 @@ exports.PlaywrightDevPage = class PlaywrightDevPage {
|
||||||
await this.getStarted();
|
await this.getStarted();
|
||||||
await this.pomLink.click();
|
await this.pomLink.click();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
```js tab=js-ts title="playwright-dev-page.ts"
|
```js tab=js-ts title="playwright-dev-page.ts"
|
||||||
import { expect, Locator, Page } from '@playwright/test';
|
import { expect, type Locator, type Page } from '@playwright/test';
|
||||||
|
|
||||||
export class PlaywrightDevPage {
|
export class PlaywrightDevPage {
|
||||||
readonly page: Page;
|
readonly page: Page;
|
||||||
|
|
|
@ -39,13 +39,13 @@ describe('angularjs homepage todo list', function() {
|
||||||
element(by.model('todoList.todoText')).sendKeys('first test');
|
element(by.model('todoList.todoText')).sendKeys('first test');
|
||||||
element(by.css('[value="add"]')).click();
|
element(by.css('[value="add"]')).click();
|
||||||
|
|
||||||
var todoList = element.all(by.repeater('todo in todoList.todos'));
|
const todoList = element.all(by.repeater('todo in todoList.todos'));
|
||||||
expect(todoList.count()).toEqual(3);
|
expect(todoList.count()).toEqual(3);
|
||||||
expect(todoList.get(2).getText()).toEqual('first test');
|
expect(todoList.get(2).getText()).toEqual('first test');
|
||||||
|
|
||||||
// You wrote your first test, cross it off the list
|
// You wrote your first test, cross it off the list
|
||||||
todoList.get(2).element(by.css('input')).click();
|
todoList.get(2).element(by.css('input')).click();
|
||||||
var completedAmount = element.all(by.css('.done-true'));
|
const completedAmount = element.all(by.css('.done-true'));
|
||||||
expect(completedAmount.count()).toEqual(2);
|
expect(completedAmount.count()).toEqual(2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -57,14 +57,14 @@ Line-by-line migration to Playwright Test:
|
||||||
```js
|
```js
|
||||||
const { test, expect } = require('@playwright/test'); // 1
|
const { test, expect } = require('@playwright/test'); // 1
|
||||||
|
|
||||||
test.describe('angularjs homepage todo list', function() {
|
test.describe('angularjs homepage todo list', () => {
|
||||||
test('should add a todo', async function({page}) { // 2, 3
|
test('should add a todo', async ({ page }) => { // 2, 3
|
||||||
await page.goto('https://angularjs.org'); // 4
|
await page.goto('https://angularjs.org'); // 4
|
||||||
|
|
||||||
await page.locator('[ng-model="todoList.todoText"]').fill('first test');
|
await page.locator('[ng-model="todoList.todoText"]').fill('first test');
|
||||||
await page.locator('[value="add"]').click();
|
await page.locator('[value="add"]').click();
|
||||||
|
|
||||||
var todoList = page.locator('[ng-repeat="todo in todoList.todos"]'); // 5
|
const todoList = page.locator('[ng-repeat="todo in todoList.todos"]'); // 5
|
||||||
await expect(todoList).toHaveCount(3);
|
await expect(todoList).toHaveCount(3);
|
||||||
await expect(todoList.nth(2)).toHaveText('first test', {
|
await expect(todoList.nth(2)).toHaveText('first test', {
|
||||||
useInnerText: true,
|
useInnerText: true,
|
||||||
|
@ -72,10 +72,10 @@ test.describe('angularjs homepage todo list', function() {
|
||||||
|
|
||||||
// You wrote your first test, cross it off the list
|
// You wrote your first test, cross it off the list
|
||||||
await todoList.nth(2).getByRole('textbox').click();
|
await todoList.nth(2).getByRole('textbox').click();
|
||||||
var completedAmount = page.locator('.done-true');
|
const completedAmount = page.locator('.done-true');
|
||||||
await expect(completedAmount).toHaveCount(2);
|
await expect(completedAmount).toHaveCount(2);
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
Migration highlights (see inline comments in the Playwright Test code snippet):
|
Migration highlights (see inline comments in the Playwright Test code snippet):
|
||||||
|
@ -98,23 +98,23 @@ Here's how to polyfill `waitForAngular` function in Playwright Test:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
async function waitForAngular(page) {
|
async function waitForAngular(page) {
|
||||||
const clientSideScripts = require('protractor/built/clientsidescripts.js');
|
const clientSideScripts = require('protractor/built/clientsidescripts.js');
|
||||||
|
|
||||||
async function executeScriptAsync(page, script, ...scriptArgs) {
|
async function executeScriptAsync(page, script, ...scriptArgs) {
|
||||||
await page.evaluate(`
|
await page.evaluate(`
|
||||||
new Promise((resolve, reject) => {
|
new Promise((resolve, reject) => {
|
||||||
const callback = (errMessage) => {
|
const callback = (errMessage) => {
|
||||||
if (errMessage)
|
if (errMessage)
|
||||||
reject(new Error(errMessage));
|
reject(new Error(errMessage));
|
||||||
else
|
else
|
||||||
resolve();
|
resolve();
|
||||||
};
|
};
|
||||||
(function() {${script}}).apply(null, [...${JSON.stringify(scriptArgs)}, callback]);
|
(function() {${script}}).apply(null, [...${JSON.stringify(scriptArgs)}, callback]);
|
||||||
})
|
})
|
||||||
`);
|
`);
|
||||||
}
|
}
|
||||||
|
|
||||||
await executeScriptAsync(page, clientSideScripts.waitForAngular, '');
|
await executeScriptAsync(page, clientSideScripts.waitForAngular, '');
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
If you don't want to keep a version protractor around, you can also use this simpler approach using this function (only works for Angular 2+):
|
If you don't want to keep a version protractor around, you can also use this simpler approach using this function (only works for Angular 2+):
|
||||||
|
@ -127,7 +127,7 @@ Here's how to polyfill `waitForAngular` function in Playwright Test:
|
||||||
await Promise.all(window.getAllAngularTestabilities().map(whenStable));
|
await Promise.all(window.getAllAngularTestabilities().map(whenStable));
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
async function whenStable(testability) {
|
async function whenStable(testability) {
|
||||||
return new Promise((res) => testability.whenStable(res) );
|
return new Promise(res => testability.whenStable(res));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -111,7 +111,7 @@ describe('Playwright homepage', () => {
|
||||||
it('contains hero title', async () => {
|
it('contains hero title', async () => {
|
||||||
await page.goto('https://playwright.dev/');
|
await page.goto('https://playwright.dev/');
|
||||||
await page.waitForSelector('.hero__title');
|
await page.waitForSelector('.hero__title');
|
||||||
const text = await page.$eval('.hero__title', (e) => e.textContent);
|
const text = await page.$eval('.hero__title', e => e.textContent);
|
||||||
expect(text).toContain('Playwright enables reliable end-to-end testing'); // 5
|
expect(text).toContain('Playwright enables reliable end-to-end testing'); // 5
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ test.describe('Playwright homepage', () => {
|
||||||
await page.goto('https://playwright.dev/');
|
await page.goto('https://playwright.dev/');
|
||||||
const titleLocator = page.locator('.hero__title'); // 4
|
const titleLocator = page.locator('.hero__title'); // 4
|
||||||
await expect(titleLocator).toContainText( // 5
|
await expect(titleLocator).toContainText( // 5
|
||||||
'Playwright enables reliable end-to-end testing'
|
'Playwright enables reliable end-to-end testing'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -589,7 +589,11 @@ All the same methods are also available on [Locator], [FrameLocator] and [Frame]
|
||||||
|
|
||||||
- New options `host` and `port` for the html reporter.
|
- New options `host` and `port` for the html reporter.
|
||||||
```js
|
```js
|
||||||
reporters: [['html', { host: 'localhost', port: '9223' }]]
|
import { defineConfig } from '@playwright/test';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
reporter: [['html', { host: 'localhost', port: '9223' }]],
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
- New field `FullConfig.configFile` is available to test reporters, specifying the path to the config file if any.
|
- New field `FullConfig.configFile` is available to test reporters, specifying the path to the config file if any.
|
||||||
|
@ -1001,7 +1005,7 @@ WebServer is now considered "ready" if request to the specified url has any of t
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// Click a button with accessible name "log in"
|
// Click a button with accessible name "log in"
|
||||||
await page.locator('role=button[name="log in"]').click()
|
await page.locator('role=button[name="log in"]').click();
|
||||||
```
|
```
|
||||||
|
|
||||||
Read more in [our documentation](./locators.md#locate-by-role).
|
Read more in [our documentation](./locators.md#locate-by-role).
|
||||||
|
@ -1044,7 +1048,7 @@ WebServer is now considered "ready" if request to the specified url has any of t
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// Click a button with accessible name "log in"
|
// Click a button with accessible name "log in"
|
||||||
await page.locator('role=button[name="log in"]').click()
|
await page.locator('role=button[name="log in"]').click();
|
||||||
```
|
```
|
||||||
|
|
||||||
Read more in [our documentation](./locators.md#locate-by-role).
|
Read more in [our documentation](./locators.md#locate-by-role).
|
||||||
|
|
|
@ -128,14 +128,14 @@ Additionally, any network request made by the **Page** (including its sub-[Frame
|
||||||
Many Service Worker implementations simply execute the request from the page (possibly with some custom caching/offline logic omitted for simplicity):
|
Many Service Worker implementations simply execute the request from the page (possibly with some custom caching/offline logic omitted for simplicity):
|
||||||
|
|
||||||
```js title="transparent-service-worker.js"
|
```js title="transparent-service-worker.js"
|
||||||
self.addEventListener("fetch", (event) => {
|
self.addEventListener('fetch', event => {
|
||||||
// actually make the request
|
// actually make the request
|
||||||
const responsePromise = fetch(event.request);
|
const responsePromise = fetch(event.request);
|
||||||
// send it back to the page
|
// send it back to the page
|
||||||
event.respondWith(responsePromise);
|
event.respondWith(responsePromise);
|
||||||
});
|
});
|
||||||
|
|
||||||
self.addEventListener("activate", (event) => {
|
self.addEventListener('activate', (event) => {
|
||||||
event.waitUntil(clients.claim());
|
event.waitUntil(clients.claim());
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
@ -180,17 +180,17 @@ Consider the code snippets below to understand Playwright's view into the Reques
|
||||||
|
|
||||||
|
|
||||||
```js title="complex-service-worker.js"
|
```js title="complex-service-worker.js"
|
||||||
self.addEventListener("install", function (event) {
|
self.addEventListener('install', function (event) {
|
||||||
event.waitUntil(
|
event.waitUntil(
|
||||||
caches.open("v1").then(function (cache) {
|
caches.open('v1').then(function (cache) {
|
||||||
// 1. Pre-fetches and caches /addressbook.json
|
// 1. Pre-fetches and caches /addressbook.json
|
||||||
return cache.add("/addressbook.json");
|
return cache.add('/addressbook.json');
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Opt to handle FetchEvent's from the page
|
// Opt to handle FetchEvent's from the page
|
||||||
self.addEventListener("fetch", (event) => {
|
self.addEventListener('fetch', (event) => {
|
||||||
event.respondWith(
|
event.respondWith(
|
||||||
(async () => {
|
(async () => {
|
||||||
// 1. Try to first serve directly from caches
|
// 1. Try to first serve directly from caches
|
||||||
|
@ -198,13 +198,13 @@ self.addEventListener("fetch", (event) => {
|
||||||
if (response) return response;
|
if (response) return response;
|
||||||
|
|
||||||
// 2. Re-write request for /foo to /bar
|
// 2. Re-write request for /foo to /bar
|
||||||
if (event.request.url.endsWith("foo")) return fetch("./bar");
|
if (event.request.url.endsWith('foo')) return fetch('./bar');
|
||||||
|
|
||||||
// 3. Prevent tracker.js from being retrieved, and returns a placeholder response
|
// 3. Prevent tracker.js from being retrieved, and returns a placeholder response
|
||||||
if (event.request.url.endsWith("tracker.js"))
|
if (event.request.url.endsWith('tracker.js'))
|
||||||
return new Response('console.log("no trackers!")', {
|
return new Response('console.log('no trackers!')', {
|
||||||
status: 200,
|
status: 200,
|
||||||
headers: { "Content-Type": "text/javascript" },
|
headers: { 'Content-Type': 'text/javascript' },
|
||||||
});
|
});
|
||||||
|
|
||||||
// 4. Otherwise, fallthrough, perform the fetch and respond
|
// 4. Otherwise, fallthrough, perform the fetch and respond
|
||||||
|
@ -213,7 +213,7 @@ self.addEventListener("fetch", (event) => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
self.addEventListener("activate", (event) => {
|
self.addEventListener('activate', (event) => {
|
||||||
event.waitUntil(clients.claim());
|
event.waitUntil(clients.claim());
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
|
@ -644,7 +644,7 @@ module.exports = defineConfig({
|
||||||
|
|
||||||
```js tab=js-ts title="playwright.config.ts"
|
```js tab=js-ts title="playwright.config.ts"
|
||||||
import { defineConfig } from '@playwright/test';
|
import { defineConfig } from '@playwright/test';
|
||||||
import { Options } from './my-test';
|
import type { Options } from './my-test';
|
||||||
|
|
||||||
export default defineConfig<Options>({
|
export default defineConfig<Options>({
|
||||||
projects: [
|
projects: [
|
||||||
|
|
|
@ -57,7 +57,7 @@ of the matchers:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
expect(value).not.toEqual(0);
|
expect(value).not.toEqual(0);
|
||||||
await expect(locator).not.toContainText("some text");
|
await expect(locator).not.toContainText('some text');
|
||||||
```
|
```
|
||||||
|
|
||||||
## Soft Assertions
|
## Soft Assertions
|
||||||
|
|
|
@ -378,7 +378,9 @@ import { defineConfig } from '@playwright/experimental-ct-react';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
use: {
|
use: {
|
||||||
ctViteConfig: { ... },
|
ctViteConfig: {
|
||||||
|
// ...
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
@ -386,7 +388,7 @@ export default defineConfig({
|
||||||
### Q) What's the difference between `@playwright/test` and `@playwright/experimental-ct-{react,svelte,vue,solid}`?
|
### Q) What's the difference between `@playwright/test` and `@playwright/experimental-ct-{react,svelte,vue,solid}`?
|
||||||
|
|
||||||
```js
|
```js
|
||||||
test('…', async { mount, page, context } => {
|
test('…', async ({ mount, page, context }) => {
|
||||||
// …
|
// …
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
@ -560,44 +562,44 @@ export default defineConfig({
|
||||||
Pinia needs to be initialized in `playwright/index.{js,ts,jsx,tsx}`. If you do this inside a `beforeMount` hook, the `initialState` can be overwritten on a per-test basis:
|
Pinia needs to be initialized in `playwright/index.{js,ts,jsx,tsx}`. If you do this inside a `beforeMount` hook, the `initialState` can be overwritten on a per-test basis:
|
||||||
|
|
||||||
```js title="playwright/index.ts"
|
```js title="playwright/index.ts"
|
||||||
import { beforeMount, afterMount } from '@playwright/experimental-ct-vue/hooks';
|
import { beforeMount, afterMount } from '@playwright/experimental-ct-vue/hooks';
|
||||||
import { createTestingPinia } from '@pinia/testing';
|
import { createTestingPinia } from '@pinia/testing';
|
||||||
import type { StoreState } from 'pinia';
|
import type { StoreState } from 'pinia';
|
||||||
import type { useStore } from '../src/store';
|
import type { useStore } from '../src/store';
|
||||||
|
|
||||||
export type HooksConfig = {
|
export type HooksConfig = {
|
||||||
store?: StoreState<ReturnType<typeof useStore>>;
|
store?: StoreState<ReturnType<typeof useStore>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeMount<HooksConfig>(async ({ hooksConfig }) => {
|
beforeMount<HooksConfig>(async ({ hooksConfig }) => {
|
||||||
createTestingPinia({
|
createTestingPinia({
|
||||||
initialState: hooksConfig?.store,
|
initialState: hooksConfig?.store,
|
||||||
/**
|
/**
|
||||||
* Use http intercepting to mock api calls instead:
|
* Use http intercepting to mock api calls instead:
|
||||||
* https://playwright.dev/docs/mock#mock-api-requests
|
* https://playwright.dev/docs/mock#mock-api-requests
|
||||||
*/
|
*/
|
||||||
stubActions: false,
|
stubActions: false,
|
||||||
createSpy(args) {
|
createSpy(args) {
|
||||||
console.log('spy', args)
|
console.log('spy', args)
|
||||||
return () => console.log('spy-returns')
|
return () => console.log('spy-returns')
|
||||||
},
|
},
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
#### In your test file:
|
#### In your test file:
|
||||||
|
|
||||||
```js title="src/pinia.spec.ts"
|
```js title="src/pinia.spec.ts"
|
||||||
import { test, expect } from '@playwright/experimental-ct-vue';
|
import { test, expect } from '@playwright/experimental-ct-vue';
|
||||||
import type { HooksConfig } from '@playwright/test';
|
import type { HooksConfig } from '@playwright/test';
|
||||||
import Store from './Store.vue';
|
import Store from './Store.vue';
|
||||||
|
|
||||||
test('override initialState ', async ({ mount }) => {
|
test('override initialState ', async ({ mount }) => {
|
||||||
const component = await mount<HooksConfig>(Store, {
|
const component = await mount<HooksConfig>(Store, {
|
||||||
hooksConfig: {
|
hooksConfig: {
|
||||||
store: { name: 'override initialState' }
|
store: { name: 'override initialState' }
|
||||||
}
|
}
|
||||||
});
|
|
||||||
await expect(component).toContainText('override initialState');
|
|
||||||
});
|
});
|
||||||
|
await expect(component).toContainText('override initialState');
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
|
|
@ -132,7 +132,7 @@ export default defineConfig({
|
||||||
maxDiffPixels: 10,
|
maxDiffPixels: 10,
|
||||||
},
|
},
|
||||||
|
|
||||||
toMatchSnapshot: {
|
toMatchSnapshot: {
|
||||||
// An acceptable ratio of pixels that are different to the total amount of pixels, between 0 and 1.
|
// An acceptable ratio of pixels that are different to the total amount of pixels, between 0 and 1.
|
||||||
maxDiffPixelRatio: 0.1,
|
maxDiffPixelRatio: 0.1,
|
||||||
},
|
},
|
||||||
|
|
|
@ -83,7 +83,7 @@ export class TodoPage {
|
||||||
```
|
```
|
||||||
|
|
||||||
```js tab=js-ts title="todo-page.ts"
|
```js tab=js-ts title="todo-page.ts"
|
||||||
import { Page, Locator } from '@playwright/test';
|
import type { Page, Locator } from '@playwright/test';
|
||||||
|
|
||||||
export class TodoPage {
|
export class TodoPage {
|
||||||
private readonly inputBox: Locator;
|
private readonly inputBox: Locator;
|
||||||
|
@ -207,7 +207,7 @@ export class TodoPage {
|
||||||
```
|
```
|
||||||
|
|
||||||
```js tab=js-ts title="todo-page.ts"
|
```js tab=js-ts title="todo-page.ts"
|
||||||
import { Page, Locator } from '@playwright/test';
|
import type { Page, Locator } from '@playwright/test';
|
||||||
|
|
||||||
export class TodoPage {
|
export class TodoPage {
|
||||||
private readonly inputBox: Locator;
|
private readonly inputBox: Locator;
|
||||||
|
@ -349,7 +349,7 @@ export class TodoPage {
|
||||||
```
|
```
|
||||||
|
|
||||||
```js tab=js-ts title="todo-page.ts"
|
```js tab=js-ts title="todo-page.ts"
|
||||||
import { Page, Locator } from '@playwright/test';
|
import type { Page, Locator } from '@playwright/test';
|
||||||
|
|
||||||
export class TodoPage {
|
export class TodoPage {
|
||||||
private readonly inputBox: Locator;
|
private readonly inputBox: Locator;
|
||||||
|
@ -402,7 +402,7 @@ export class SettingsPage {
|
||||||
```
|
```
|
||||||
|
|
||||||
```js tab=js-ts title="settings-page.ts"
|
```js tab=js-ts title="settings-page.ts"
|
||||||
import { Page } from '@playwright/test';
|
import type { Page } from '@playwright/test';
|
||||||
|
|
||||||
export class SettingsPage {
|
export class SettingsPage {
|
||||||
constructor(public readonly page: Page) {
|
constructor(public readonly page: Page) {
|
||||||
|
@ -792,7 +792,7 @@ export class TodoPage {
|
||||||
```
|
```
|
||||||
|
|
||||||
```js tab=js-ts title="todo-page.ts"
|
```js tab=js-ts title="todo-page.ts"
|
||||||
import { Page, Locator } from '@playwright/test';
|
import type { Page, Locator } from '@playwright/test';
|
||||||
|
|
||||||
export class TodoPage {
|
export class TodoPage {
|
||||||
private readonly inputBox: Locator;
|
private readonly inputBox: Locator;
|
||||||
|
@ -903,7 +903,7 @@ module.exports = defineConfig({
|
||||||
|
|
||||||
```js tab=js-ts title="playwright.config.ts"
|
```js tab=js-ts title="playwright.config.ts"
|
||||||
import { defineConfig } from '@playwright/test';
|
import { defineConfig } from '@playwright/test';
|
||||||
import { MyOptions } from './my-test';
|
import type { MyOptions } from './my-test';
|
||||||
|
|
||||||
export default defineConfig<MyOptions>({
|
export default defineConfig<MyOptions>({
|
||||||
projects: [
|
projects: [
|
||||||
|
|
|
@ -71,10 +71,10 @@ export default defineConfig({
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'logged in chromium',
|
name: 'logged in chromium',
|
||||||
use: { ...devices['Desktop Chrome'] },
|
|
||||||
testMatch: '**/*.loggedin.spec.ts',
|
testMatch: '**/*.loggedin.spec.ts',
|
||||||
dependencies: ['setup'],
|
dependencies: ['setup'],
|
||||||
use: {
|
use: {
|
||||||
|
...devices['Desktop Chrome'],
|
||||||
storageState: STORAGE_STATE,
|
storageState: STORAGE_STATE,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -115,7 +115,7 @@ test.beforeEach(async ({ page }) => {
|
||||||
|
|
||||||
test('menu', async ({ page }) => {
|
test('menu', async ({ page }) => {
|
||||||
// You are signed in!
|
// You are signed in!
|
||||||
})
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
For a more detailed example check out our blog post: [A better global setup in Playwright reusing login with project dependencies](https://dev.to/playwright/a-better-global-setup-in-playwright-reusing-login-with-project-dependencies-14) or check the [v1.31 release video](https://youtu.be/PI50YAPTAs4) to see the demo.
|
For a more detailed example check out our blog post: [A better global setup in Playwright reusing login with project dependencies](https://dev.to/playwright/a-better-global-setup-in-playwright-reusing-login-with-project-dependencies-14) or check the [v1.31 release video](https://youtu.be/PI50YAPTAs4) to see the demo.
|
||||||
|
@ -234,7 +234,7 @@ export default defineConfig({
|
||||||
Here is a global setup example that authenticates once and reuses authentication state in tests. It uses the `baseURL` and `storageState` options from the configuration file.
|
Here is a global setup example that authenticates once and reuses authentication state in tests. It uses the `baseURL` and `storageState` options from the configuration file.
|
||||||
|
|
||||||
```js title="global-setup.ts"
|
```js title="global-setup.ts"
|
||||||
import { chromium, FullConfig } from '@playwright/test';
|
import { chromium, type FullConfig } from '@playwright/test';
|
||||||
|
|
||||||
async function globalSetup(config: FullConfig) {
|
async function globalSetup(config: FullConfig) {
|
||||||
const { baseURL, storageState } = config.projects[0].use;
|
const { baseURL, storageState } = config.projects[0].use;
|
||||||
|
@ -278,7 +278,7 @@ test('test', async ({ page }) => {
|
||||||
You can make arbitrary data available in your tests from your global setup file by setting them as environment variables via `process.env`.
|
You can make arbitrary data available in your tests from your global setup file by setting them as environment variables via `process.env`.
|
||||||
|
|
||||||
```js title="global-setup.ts"
|
```js title="global-setup.ts"
|
||||||
import { FullConfig } from '@playwright/test';
|
import type { FullConfig } from '@playwright/test';
|
||||||
|
|
||||||
async function globalSetup(config: FullConfig) {
|
async function globalSetup(config: FullConfig) {
|
||||||
process.env.FOO = 'some data';
|
process.env.FOO = 'some data';
|
||||||
|
@ -311,7 +311,7 @@ test('test', async ({ page }) => {
|
||||||
In some instances, it may be useful to capture a trace of failures encountered during the global setup. In order to do this, you must [start tracing](./api/class-tracing.md#tracing-start) in your setup, and you must ensure that you [stop tracing](./api/class-tracing.md#tracing-stop) if an error occurs before that error is thrown. This can be achieved by wrapping your setup in a `try...catch` block. Here is an example that expands the global setup example to capture a trace.
|
In some instances, it may be useful to capture a trace of failures encountered during the global setup. In order to do this, you must [start tracing](./api/class-tracing.md#tracing-start) in your setup, and you must ensure that you [stop tracing](./api/class-tracing.md#tracing-stop) if an error occurs before that error is thrown. This can be achieved by wrapping your setup in a `try...catch` block. Here is an example that expands the global setup example to capture a trace.
|
||||||
|
|
||||||
```js title="global-setup.ts"
|
```js title="global-setup.ts"
|
||||||
import { chromium, FullConfig } from '@playwright/test';
|
import { chromium, type FullConfig } from '@playwright/test';
|
||||||
|
|
||||||
async function globalSetup(config: FullConfig) {
|
async function globalSetup(config: FullConfig) {
|
||||||
const { baseURL, storageState } = config.projects[0].use;
|
const { baseURL, storageState } = config.projects[0].use;
|
||||||
|
|
|
@ -99,7 +99,7 @@ Using serial is not recommended. It is usually better to make your tests isolate
|
||||||
:::
|
:::
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import { test, Page } from '@playwright/test';
|
import { test, type Page } from '@playwright/test';
|
||||||
|
|
||||||
// Annotate entire file as serial.
|
// Annotate entire file as serial.
|
||||||
test.describe.configure({ mode: 'serial' });
|
test.describe.configure({ mode: 'serial' });
|
||||||
|
|
|
@ -36,7 +36,7 @@ module.exports = MyReporter;
|
||||||
```
|
```
|
||||||
|
|
||||||
```js tab=js-ts title="my-awesome-reporter.ts"
|
```js tab=js-ts title="my-awesome-reporter.ts"
|
||||||
import { Reporter, FullConfig, Suite, TestCase, TestResult, FullResult } from '@playwright/test/reporter';
|
import type { Reporter, FullConfig, Suite, TestCase, TestResult, FullResult } from '@playwright/test/reporter';
|
||||||
|
|
||||||
class MyReporter implements Reporter {
|
class MyReporter implements Reporter {
|
||||||
constructor(options: { customOption?: string } = {}) {
|
constructor(options: { customOption?: string } = {}) {
|
||||||
|
|
|
@ -289,7 +289,7 @@ export default defineConfig({
|
||||||
You can create a custom reporter by implementing a class with some of the reporter methods. Learn more about the [Reporter] API.
|
You can create a custom reporter by implementing a class with some of the reporter methods. Learn more about the [Reporter] API.
|
||||||
|
|
||||||
```js title="my-awesome-reporter.ts"
|
```js title="my-awesome-reporter.ts"
|
||||||
import { FullConfig, FullResult, Reporter, Suite, TestCase, TestResult } from '@playwright/test/reporter';
|
import type { FullConfig, FullResult, Reporter, Suite, TestCase, TestResult } from '@playwright/test/reporter';
|
||||||
|
|
||||||
class MyReporter implements Reporter {
|
class MyReporter implements Reporter {
|
||||||
onBegin(config: FullConfig, suite: Suite) {
|
onBegin(config: FullConfig, suite: Suite) {
|
||||||
|
|
|
@ -191,7 +191,7 @@ test('runs second', async () => {
|
||||||
```
|
```
|
||||||
|
|
||||||
```js tab=js-ts title="example.spec.ts"
|
```js tab=js-ts title="example.spec.ts"
|
||||||
import { test, Page } from '@playwright/test';
|
import { test, type Page } from '@playwright/test';
|
||||||
|
|
||||||
test.describe.configure({ mode: 'serial' });
|
test.describe.configure({ mode: 'serial' });
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ import { defineConfig } from '@playwright/test';
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
use: {
|
use: {
|
||||||
// Base URL to use in actions like `await page.goto('/')`.
|
// Base URL to use in actions like `await page.goto('/')`.
|
||||||
baseURL: 'http://127.0.0.1:3000'
|
baseURL: 'http://127.0.0.1:3000',
|
||||||
|
|
||||||
// Populates context with given storage state.
|
// Populates context with given storage state.
|
||||||
storageState: 'state.json',
|
storageState: 'state.json',
|
||||||
|
@ -133,7 +133,7 @@ import { defineConfig } from '@playwright/test';
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
use: {
|
use: {
|
||||||
// Capture screenshot after each test failure.
|
// Capture screenshot after each test failure.
|
||||||
screenshot: 'only-on-failure'
|
screenshot: 'only-on-failure',
|
||||||
|
|
||||||
// Record trace only when retrying a test for the first time.
|
// Record trace only when retrying a test for the first time.
|
||||||
trace: 'on-first-retry',
|
trace: 'on-first-retry',
|
||||||
|
@ -224,11 +224,9 @@ export default defineConfig({
|
||||||
An example test illustrating the initial context options are set:
|
An example test illustrating the initial context options are set:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import { test, expect } from "@playwright/test";
|
import { test, expect } from '@playwright/test';
|
||||||
|
|
||||||
test('should inherit use options on context when using built-in browser fixture', async ({
|
test('should inherit use options on context when using built-in browser fixture', async ({ browser }) => {
|
||||||
browser,
|
|
||||||
}) => {
|
|
||||||
const context = await browser.newContext();
|
const context = await browser.newContext();
|
||||||
const page = await context.newPage();
|
const page = await context.newPage();
|
||||||
expect(await page.evaluate(() => navigator.userAgent)).toBe('some custom ua');
|
expect(await page.evaluate(() => navigator.userAgent)).toBe('some custom ua');
|
||||||
|
@ -263,7 +261,7 @@ export default defineConfig({
|
||||||
name: 'chromium',
|
name: 'chromium',
|
||||||
use: {
|
use: {
|
||||||
...devices['Desktop Chrome'],
|
...devices['Desktop Chrome'],
|
||||||
locale: 'de-DE'
|
locale: 'de-DE',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -289,7 +287,7 @@ import { test, expect } from '@playwright/test';
|
||||||
|
|
||||||
test.describe('french language block', () => {
|
test.describe('french language block', () => {
|
||||||
|
|
||||||
test.use({ { locale: 'fr-FR' }});
|
test.use({ locale: 'fr-FR' });
|
||||||
|
|
||||||
test('example', async ({ page }) => {
|
test('example', async ({ page }) => {
|
||||||
// ...
|
// ...
|
||||||
|
|
|
@ -92,13 +92,13 @@ Playwright includes [assertions](./test-assertions) that automatically wait for
|
||||||
```js
|
```js
|
||||||
// Testing Library
|
// Testing Library
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(getByText('the lion king')).toBeInTheDocument()
|
expect(getByText('the lion king')).toBeInTheDocument();
|
||||||
})
|
});
|
||||||
await waitForElementToBeRemoved(() => queryByText('the mummy'))
|
await waitForElementToBeRemoved(() => queryByText('the mummy'));
|
||||||
|
|
||||||
// Playwright
|
// Playwright
|
||||||
await expect(page.getByText('the lion king')).toBeVisible()
|
await expect(page.getByText('the lion king')).toBeVisible();
|
||||||
await expect(page.getByText('the mummy')).toBeHidden()
|
await expect(page.getByText('the mummy')).toBeHidden();
|
||||||
```
|
```
|
||||||
|
|
||||||
When you cannot find a suitable assertion, use [`expect.poll`](./test-assertions#polling) instead.
|
When you cannot find a suitable assertion, use [`expect.poll`](./test-assertions#polling) instead.
|
||||||
|
@ -116,12 +116,12 @@ You can create a locator inside another locator with [`method: Locator.locator`]
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// Testing Library
|
// Testing Library
|
||||||
const messages = document.getElementById('messages')
|
const messages = document.getElementById('messages');
|
||||||
const helloMessage = within(messages).getByText('hello')
|
const helloMessage = within(messages).getByText('hello');
|
||||||
|
|
||||||
// Playwright
|
// Playwright
|
||||||
const messages = component.locator('id=messages')
|
const messages = component.locator('id=messages');
|
||||||
const helloMessage = messages.getByText('hello')
|
const helloMessage = messages.getByText('hello');
|
||||||
```
|
```
|
||||||
|
|
||||||
## Playwright Test Super Powers
|
## Playwright Test Super Powers
|
||||||
|
|
|
@ -25,7 +25,7 @@ By default the [playwright.config](/test-configuration.md#record-test-trace) fil
|
||||||
import { defineConfig } from '@playwright/test';
|
import { defineConfig } from '@playwright/test';
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
retries: process.env.CI ? 2 : 0, // set to 2 when running on CI
|
retries: process.env.CI ? 2 : 0, // set to 2 when running on CI
|
||||||
...
|
// ...
|
||||||
use: {
|
use: {
|
||||||
trace: 'on-first-retry', // record traces on first retry of each test
|
trace: 'on-first-retry', // record traces on first retry of each test
|
||||||
},
|
},
|
||||||
|
|
|
@ -96,7 +96,7 @@ export const test = base.extend({
|
||||||
}));
|
}));
|
||||||
const browser = await playwright.chromium.connectOverCDP(`http://127.0.0.1:${cdpPort}`);
|
const browser = await playwright.chromium.connectOverCDP(`http://127.0.0.1:${cdpPort}`);
|
||||||
await use(browser);
|
await use(browser);
|
||||||
await browser.close()
|
await browser.close();
|
||||||
childProcess.execSync(`taskkill /pid ${webView2Process.pid} /T /F`);
|
childProcess.execSync(`taskkill /pid ${webView2Process.pid} /T /F`);
|
||||||
fs.rmdirSync(userDataDir, { recursive: true });
|
fs.rmdirSync(userDataDir, { recursive: true });
|
||||||
},
|
},
|
||||||
|
|
|
@ -154,7 +154,8 @@ Playwright Test is based on the concept of [test fixtures](./test-fixtures.md) s
|
||||||
|
|
||||||
```js title="tests/example.spec.ts"
|
```js title="tests/example.spec.ts"
|
||||||
test('basic test', async ({ page }) => {
|
test('basic test', async ({ page }) => {
|
||||||
...
|
// ...
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
### Using Test Hooks
|
### Using Test Hooks
|
||||||
|
@ -162,17 +163,17 @@ test('basic test', async ({ page }) => {
|
||||||
You can use various [test hooks](./api/class-test.md) such as `test.describe` to declare a group of tests and `test.beforeEach` and `test.afterEach` which are executed before/after each test. Other hooks include the `test.beforeAll` and `test.afterAll` which are executed once per worker before/after all tests.
|
You can use various [test hooks](./api/class-test.md) such as `test.describe` to declare a group of tests and `test.beforeEach` and `test.afterEach` which are executed before/after each test. Other hooks include the `test.beforeAll` and `test.afterAll` which are executed once per worker before/after all tests.
|
||||||
|
|
||||||
```js title="tests/example.spec.ts"
|
```js title="tests/example.spec.ts"
|
||||||
import { test, expect } from "@playwright/test";
|
import { test, expect } from '@playwright/test';
|
||||||
|
|
||||||
test.describe("navigation", () => {
|
test.describe('navigation', () => {
|
||||||
test.beforeEach(async ({ page }) => {
|
test.beforeEach(async ({ page }) => {
|
||||||
// Go to the starting url before each test.
|
// Go to the starting url before each test.
|
||||||
await page.goto("https://playwright.dev/");
|
await page.goto('https://playwright.dev/');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("main navigation", async ({ page }) => {
|
test('main navigation', async ({ page }) => {
|
||||||
// Assertions use the expect API.
|
// Assertions use the expect API.
|
||||||
await expect(page).toHaveURL("https://playwright.dev/");
|
await expect(page).toHaveURL('https://playwright.dev/');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
|
@ -45,7 +45,7 @@ type ElementHandleWaitForSelectorOptionsNotHidden = ElementHandleWaitForSelector
|
||||||
* const context = await browser.newContext();
|
* const context = await browser.newContext();
|
||||||
* const page = await context.newPage();
|
* const page = await context.newPage();
|
||||||
* await page.goto('https://example.com');
|
* await page.goto('https://example.com');
|
||||||
* await page.screenshot({path: 'screenshot.png'});
|
* await page.screenshot({ path: 'screenshot.png' });
|
||||||
* await browser.close();
|
* await browser.close();
|
||||||
* })();
|
* })();
|
||||||
* ```
|
* ```
|
||||||
|
@ -112,7 +112,7 @@ export interface Page {
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* const bodyHandle = await page.evaluate('document.body');
|
* const bodyHandle = await page.evaluate('document.body');
|
||||||
* const html = await page.evaluate(([body, suffix]) => body.innerHTML + suffix, [bodyHandle, 'hello']);
|
* const html = await page.evaluate<string, HTMLElement>(([body, suffix]) => body.innerHTML + suffix, [bodyHandle, 'hello']);
|
||||||
* await bodyHandle.dispose();
|
* await bodyHandle.dispose();
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
|
@ -159,7 +159,7 @@ export interface Page {
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* const bodyHandle = await page.evaluate('document.body');
|
* const bodyHandle = await page.evaluate('document.body');
|
||||||
* const html = await page.evaluate(([body, suffix]) => body.innerHTML + suffix, [bodyHandle, 'hello']);
|
* const html = await page.evaluate<string, HTMLElement>(([body, suffix]) => body.innerHTML + suffix, [bodyHandle, 'hello']);
|
||||||
* await bodyHandle.dispose();
|
* await bodyHandle.dispose();
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
|
@ -186,8 +186,8 @@ export interface Page {
|
||||||
* **Usage**
|
* **Usage**
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
|
* // Handle for the window object.
|
||||||
* const aWindowHandle = await page.evaluateHandle(() => Promise.resolve(window));
|
* const aWindowHandle = await page.evaluateHandle(() => Promise.resolve(window));
|
||||||
* aWindowHandle; // Handle for the window object.
|
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* A string can also be passed in instead of a function:
|
* A string can also be passed in instead of a function:
|
||||||
|
@ -228,8 +228,8 @@ export interface Page {
|
||||||
* **Usage**
|
* **Usage**
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
|
* // Handle for the window object.
|
||||||
* const aWindowHandle = await page.evaluateHandle(() => Promise.resolve(window));
|
* const aWindowHandle = await page.evaluateHandle(() => Promise.resolve(window));
|
||||||
* aWindowHandle; // Handle for the window object.
|
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* A string can also be passed in instead of a function:
|
* A string can also be passed in instead of a function:
|
||||||
|
@ -559,7 +559,7 @@ export interface Page {
|
||||||
* const browser = await webkit.launch();
|
* const browser = await webkit.launch();
|
||||||
* const page = await browser.newPage();
|
* const page = await browser.newPage();
|
||||||
* const watchDog = page.waitForFunction(() => window.innerWidth < 100);
|
* const watchDog = page.waitForFunction(() => window.innerWidth < 100);
|
||||||
* await page.setViewportSize({width: 50, height: 50});
|
* await page.setViewportSize({ width: 50, height: 50 });
|
||||||
* await watchDog;
|
* await watchDog;
|
||||||
* await browser.close();
|
* await browser.close();
|
||||||
* })();
|
* })();
|
||||||
|
@ -595,7 +595,7 @@ export interface Page {
|
||||||
* const browser = await webkit.launch();
|
* const browser = await webkit.launch();
|
||||||
* const page = await browser.newPage();
|
* const page = await browser.newPage();
|
||||||
* const watchDog = page.waitForFunction(() => window.innerWidth < 100);
|
* const watchDog = page.waitForFunction(() => window.innerWidth < 100);
|
||||||
* await page.setViewportSize({width: 50, height: 50});
|
* await page.setViewportSize({ width: 50, height: 50 });
|
||||||
* await watchDog;
|
* await watchDog;
|
||||||
* await browser.close();
|
* await browser.close();
|
||||||
* })();
|
* })();
|
||||||
|
@ -641,7 +641,7 @@ export interface Page {
|
||||||
* (async () => {
|
* (async () => {
|
||||||
* const browser = await chromium.launch();
|
* const browser = await chromium.launch();
|
||||||
* const page = await browser.newPage();
|
* const page = await browser.newPage();
|
||||||
* for (let currentURL of ['https://google.com', 'https://bbc.com']) {
|
* for (const currentURL of ['https://google.com', 'https://bbc.com']) {
|
||||||
* await page.goto(currentURL);
|
* await page.goto(currentURL);
|
||||||
* const element = await page.waitForSelector('img');
|
* const element = await page.waitForSelector('img');
|
||||||
* console.log('Loaded image: ' + await element.getAttribute('src'));
|
* console.log('Loaded image: ' + await element.getAttribute('src'));
|
||||||
|
@ -679,7 +679,7 @@ export interface Page {
|
||||||
* (async () => {
|
* (async () => {
|
||||||
* const browser = await chromium.launch();
|
* const browser = await chromium.launch();
|
||||||
* const page = await browser.newPage();
|
* const page = await browser.newPage();
|
||||||
* for (let currentURL of ['https://google.com', 'https://bbc.com']) {
|
* for (const currentURL of ['https://google.com', 'https://bbc.com']) {
|
||||||
* await page.goto(currentURL);
|
* await page.goto(currentURL);
|
||||||
* const element = await page.waitForSelector('img');
|
* const element = await page.waitForSelector('img');
|
||||||
* console.log('Loaded image: ' + await element.getAttribute('src'));
|
* console.log('Loaded image: ' + await element.getAttribute('src'));
|
||||||
|
@ -717,7 +717,7 @@ export interface Page {
|
||||||
* (async () => {
|
* (async () => {
|
||||||
* const browser = await chromium.launch();
|
* const browser = await chromium.launch();
|
||||||
* const page = await browser.newPage();
|
* const page = await browser.newPage();
|
||||||
* for (let currentURL of ['https://google.com', 'https://bbc.com']) {
|
* for (const currentURL of ['https://google.com', 'https://bbc.com']) {
|
||||||
* await page.goto(currentURL);
|
* await page.goto(currentURL);
|
||||||
* const element = await page.waitForSelector('img');
|
* const element = await page.waitForSelector('img');
|
||||||
* console.log('Loaded image: ' + await element.getAttribute('src'));
|
* console.log('Loaded image: ' + await element.getAttribute('src'));
|
||||||
|
@ -755,7 +755,7 @@ export interface Page {
|
||||||
* (async () => {
|
* (async () => {
|
||||||
* const browser = await chromium.launch();
|
* const browser = await chromium.launch();
|
||||||
* const page = await browser.newPage();
|
* const page = await browser.newPage();
|
||||||
* for (let currentURL of ['https://google.com', 'https://bbc.com']) {
|
* for (const currentURL of ['https://google.com', 'https://bbc.com']) {
|
||||||
* await page.goto(currentURL);
|
* await page.goto(currentURL);
|
||||||
* const element = await page.waitForSelector('img');
|
* const element = await page.waitForSelector('img');
|
||||||
* console.log('Loaded image: ' + await element.getAttribute('src'));
|
* console.log('Loaded image: ' + await element.getAttribute('src'));
|
||||||
|
@ -977,7 +977,7 @@ export interface Page {
|
||||||
* that can be uploaded after that.
|
* that can be uploaded after that.
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* page.on('filechooser', async (fileChooser) => {
|
* page.on('filechooser', async fileChooser => {
|
||||||
* await fileChooser.setFiles('/tmp/myfile.pdf');
|
* await fileChooser.setFiles('/tmp/myfile.pdf');
|
||||||
* });
|
* });
|
||||||
* ```
|
* ```
|
||||||
|
@ -1273,7 +1273,7 @@ export interface Page {
|
||||||
* that can be uploaded after that.
|
* that can be uploaded after that.
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* page.on('filechooser', async (fileChooser) => {
|
* page.on('filechooser', async fileChooser => {
|
||||||
* await fileChooser.setFiles('/tmp/myfile.pdf');
|
* await fileChooser.setFiles('/tmp/myfile.pdf');
|
||||||
* });
|
* });
|
||||||
* ```
|
* ```
|
||||||
|
@ -1664,7 +1664,7 @@ export interface Page {
|
||||||
* that can be uploaded after that.
|
* that can be uploaded after that.
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* page.on('filechooser', async (fileChooser) => {
|
* page.on('filechooser', async fileChooser => {
|
||||||
* await fileChooser.setFiles('/tmp/myfile.pdf');
|
* await fileChooser.setFiles('/tmp/myfile.pdf');
|
||||||
* });
|
* });
|
||||||
* ```
|
* ```
|
||||||
|
@ -2557,8 +2557,8 @@ export interface Page {
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* await page
|
* await page
|
||||||
* .getByPlaceholder("name@example.com")
|
* .getByPlaceholder('name@example.com')
|
||||||
* .fill("playwright@microsoft.com");
|
* .fill('playwright@microsoft.com');
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @param text Text to locate the element for.
|
* @param text Text to locate the element for.
|
||||||
|
@ -2705,9 +2705,13 @@ export interface Page {
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* // Set custom test id attribute from @playwright/test config:
|
* // Set custom test id attribute from @playwright/test config:
|
||||||
* use: {
|
* import { defineConfig } from '@playwright/test';
|
||||||
* testIdAttribute: 'data-pw'
|
*
|
||||||
* }
|
* export default defineConfig({
|
||||||
|
* use: {
|
||||||
|
* testIdAttribute: 'data-pw'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @param testId Id to locate the element by.
|
* @param testId Id to locate the element by.
|
||||||
|
@ -2733,19 +2737,19 @@ export interface Page {
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* // Matches <span>
|
* // Matches <span>
|
||||||
* page.getByText('world')
|
* page.getByText('world');
|
||||||
*
|
*
|
||||||
* // Matches first <div>
|
* // Matches first <div>
|
||||||
* page.getByText('Hello world')
|
* page.getByText('Hello world');
|
||||||
*
|
*
|
||||||
* // Matches second <div>
|
* // Matches second <div>
|
||||||
* page.getByText('Hello', { exact: true })
|
* page.getByText('Hello', { exact: true });
|
||||||
*
|
*
|
||||||
* // Matches both <div>s
|
* // Matches both <div>s
|
||||||
* page.getByText(/Hello/)
|
* page.getByText(/Hello/);
|
||||||
*
|
*
|
||||||
* // Matches second <div>
|
* // Matches second <div>
|
||||||
* page.getByText(/^hello$/i)
|
* page.getByText(/^hello$/i);
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* **Details**
|
* **Details**
|
||||||
|
@ -3295,8 +3299,8 @@ export interface Page {
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* // Generates a PDF with 'screen' media type.
|
* // Generates a PDF with 'screen' media type.
|
||||||
* await page.emulateMedia({media: 'screen'});
|
* await page.emulateMedia({ media: 'screen' });
|
||||||
* await page.pdf({path: 'page.pdf'});
|
* await page.pdf({ path: 'page.pdf' });
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* The `width`, `height`, and `margin` options accept values labeled with units. Unlabeled values are treated as
|
* The `width`, `height`, and `margin` options accept values labeled with units. Unlabeled values are treated as
|
||||||
|
@ -4105,7 +4109,7 @@ export interface Page {
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* await page.type('#mytextarea', 'Hello'); // Types instantly
|
* await page.type('#mytextarea', 'Hello'); // Types instantly
|
||||||
* await page.type('#mytextarea', 'World', {delay: 100}); // Types slower, like a user
|
* await page.type('#mytextarea', 'World', { delay: 100 }); // Types slower, like a user
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @param selector A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
|
* @param selector A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
|
||||||
|
@ -4321,7 +4325,7 @@ export interface Page {
|
||||||
* that can be uploaded after that.
|
* that can be uploaded after that.
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* page.on('filechooser', async (fileChooser) => {
|
* page.on('filechooser', async fileChooser => {
|
||||||
* await fileChooser.setFiles('/tmp/myfile.pdf');
|
* await fileChooser.setFiles('/tmp/myfile.pdf');
|
||||||
* });
|
* });
|
||||||
* ```
|
* ```
|
||||||
|
@ -4719,9 +4723,8 @@ export interface Page {
|
||||||
*
|
*
|
||||||
* function dumpFrameTree(frame, indent) {
|
* function dumpFrameTree(frame, indent) {
|
||||||
* console.log(indent + frame.url());
|
* console.log(indent + frame.url());
|
||||||
* for (const child of frame.childFrames()) {
|
* for (const child of frame.childFrames())
|
||||||
* dumpFrameTree(child, indent + ' ');
|
* dumpFrameTree(child, indent + ' ');
|
||||||
* }
|
|
||||||
* }
|
* }
|
||||||
* })();
|
* })();
|
||||||
* ```
|
* ```
|
||||||
|
@ -4833,8 +4836,8 @@ export interface Frame {
|
||||||
* **Usage**
|
* **Usage**
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
|
* // Handle for the window object
|
||||||
* const aWindowHandle = await frame.evaluateHandle(() => Promise.resolve(window));
|
* const aWindowHandle = await frame.evaluateHandle(() => Promise.resolve(window));
|
||||||
* aWindowHandle; // Handle for the window object.
|
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* A string can also be passed in instead of a function.
|
* A string can also be passed in instead of a function.
|
||||||
|
@ -4875,8 +4878,8 @@ export interface Frame {
|
||||||
* **Usage**
|
* **Usage**
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
|
* // Handle for the window object
|
||||||
* const aWindowHandle = await frame.evaluateHandle(() => Promise.resolve(window));
|
* const aWindowHandle = await frame.evaluateHandle(() => Promise.resolve(window));
|
||||||
* aWindowHandle; // Handle for the window object.
|
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* A string can also be passed in instead of a function.
|
* A string can also be passed in instead of a function.
|
||||||
|
@ -5192,7 +5195,7 @@ export interface Frame {
|
||||||
* const browser = await firefox.launch();
|
* const browser = await firefox.launch();
|
||||||
* const page = await browser.newPage();
|
* const page = await browser.newPage();
|
||||||
* const watchDog = page.mainFrame().waitForFunction('window.innerWidth < 100');
|
* const watchDog = page.mainFrame().waitForFunction('window.innerWidth < 100');
|
||||||
* await page.setViewportSize({width: 50, height: 50});
|
* await page.setViewportSize({ width: 50, height: 50 });
|
||||||
* await watchDog;
|
* await watchDog;
|
||||||
* await browser.close();
|
* await browser.close();
|
||||||
* })();
|
* })();
|
||||||
|
@ -5226,7 +5229,7 @@ export interface Frame {
|
||||||
* const browser = await firefox.launch();
|
* const browser = await firefox.launch();
|
||||||
* const page = await browser.newPage();
|
* const page = await browser.newPage();
|
||||||
* const watchDog = page.mainFrame().waitForFunction('window.innerWidth < 100');
|
* const watchDog = page.mainFrame().waitForFunction('window.innerWidth < 100');
|
||||||
* await page.setViewportSize({width: 50, height: 50});
|
* await page.setViewportSize({ width: 50, height: 50 });
|
||||||
* await watchDog;
|
* await watchDog;
|
||||||
* await browser.close();
|
* await browser.close();
|
||||||
* })();
|
* })();
|
||||||
|
@ -5270,7 +5273,7 @@ export interface Frame {
|
||||||
* (async () => {
|
* (async () => {
|
||||||
* const browser = await chromium.launch();
|
* const browser = await chromium.launch();
|
||||||
* const page = await browser.newPage();
|
* const page = await browser.newPage();
|
||||||
* for (let currentURL of ['https://google.com', 'https://bbc.com']) {
|
* for (const currentURL of ['https://google.com', 'https://bbc.com']) {
|
||||||
* await page.goto(currentURL);
|
* await page.goto(currentURL);
|
||||||
* const element = await page.mainFrame().waitForSelector('img');
|
* const element = await page.mainFrame().waitForSelector('img');
|
||||||
* console.log('Loaded image: ' + await element.getAttribute('src'));
|
* console.log('Loaded image: ' + await element.getAttribute('src'));
|
||||||
|
@ -5308,7 +5311,7 @@ export interface Frame {
|
||||||
* (async () => {
|
* (async () => {
|
||||||
* const browser = await chromium.launch();
|
* const browser = await chromium.launch();
|
||||||
* const page = await browser.newPage();
|
* const page = await browser.newPage();
|
||||||
* for (let currentURL of ['https://google.com', 'https://bbc.com']) {
|
* for (const currentURL of ['https://google.com', 'https://bbc.com']) {
|
||||||
* await page.goto(currentURL);
|
* await page.goto(currentURL);
|
||||||
* const element = await page.mainFrame().waitForSelector('img');
|
* const element = await page.mainFrame().waitForSelector('img');
|
||||||
* console.log('Loaded image: ' + await element.getAttribute('src'));
|
* console.log('Loaded image: ' + await element.getAttribute('src'));
|
||||||
|
@ -5346,7 +5349,7 @@ export interface Frame {
|
||||||
* (async () => {
|
* (async () => {
|
||||||
* const browser = await chromium.launch();
|
* const browser = await chromium.launch();
|
||||||
* const page = await browser.newPage();
|
* const page = await browser.newPage();
|
||||||
* for (let currentURL of ['https://google.com', 'https://bbc.com']) {
|
* for (const currentURL of ['https://google.com', 'https://bbc.com']) {
|
||||||
* await page.goto(currentURL);
|
* await page.goto(currentURL);
|
||||||
* const element = await page.mainFrame().waitForSelector('img');
|
* const element = await page.mainFrame().waitForSelector('img');
|
||||||
* console.log('Loaded image: ' + await element.getAttribute('src'));
|
* console.log('Loaded image: ' + await element.getAttribute('src'));
|
||||||
|
@ -5384,7 +5387,7 @@ export interface Frame {
|
||||||
* (async () => {
|
* (async () => {
|
||||||
* const browser = await chromium.launch();
|
* const browser = await chromium.launch();
|
||||||
* const page = await browser.newPage();
|
* const page = await browser.newPage();
|
||||||
* for (let currentURL of ['https://google.com', 'https://bbc.com']) {
|
* for (const currentURL of ['https://google.com', 'https://bbc.com']) {
|
||||||
* await page.goto(currentURL);
|
* await page.goto(currentURL);
|
||||||
* const element = await page.mainFrame().waitForSelector('img');
|
* const element = await page.mainFrame().waitForSelector('img');
|
||||||
* console.log('Loaded image: ' + await element.getAttribute('src'));
|
* console.log('Loaded image: ' + await element.getAttribute('src'));
|
||||||
|
@ -6019,8 +6022,8 @@ export interface Frame {
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* await page
|
* await page
|
||||||
* .getByPlaceholder("name@example.com")
|
* .getByPlaceholder('name@example.com')
|
||||||
* .fill("playwright@microsoft.com");
|
* .fill('playwright@microsoft.com');
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @param text Text to locate the element for.
|
* @param text Text to locate the element for.
|
||||||
|
@ -6167,9 +6170,13 @@ export interface Frame {
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* // Set custom test id attribute from @playwright/test config:
|
* // Set custom test id attribute from @playwright/test config:
|
||||||
* use: {
|
* import { defineConfig } from '@playwright/test';
|
||||||
* testIdAttribute: 'data-pw'
|
*
|
||||||
* }
|
* export default defineConfig({
|
||||||
|
* use: {
|
||||||
|
* testIdAttribute: 'data-pw'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @param testId Id to locate the element by.
|
* @param testId Id to locate the element by.
|
||||||
|
@ -6195,19 +6202,19 @@ export interface Frame {
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* // Matches <span>
|
* // Matches <span>
|
||||||
* page.getByText('world')
|
* page.getByText('world');
|
||||||
*
|
*
|
||||||
* // Matches first <div>
|
* // Matches first <div>
|
||||||
* page.getByText('Hello world')
|
* page.getByText('Hello world');
|
||||||
*
|
*
|
||||||
* // Matches second <div>
|
* // Matches second <div>
|
||||||
* page.getByText('Hello', { exact: true })
|
* page.getByText('Hello', { exact: true });
|
||||||
*
|
*
|
||||||
* // Matches both <div>s
|
* // Matches both <div>s
|
||||||
* page.getByText(/Hello/)
|
* page.getByText(/Hello/);
|
||||||
*
|
*
|
||||||
* // Matches second <div>
|
* // Matches second <div>
|
||||||
* page.getByText(/^hello$/i)
|
* page.getByText(/^hello$/i);
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* **Details**
|
* **Details**
|
||||||
|
@ -7106,7 +7113,7 @@ export interface Frame {
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* await frame.type('#mytextarea', 'Hello'); // Types instantly
|
* await frame.type('#mytextarea', 'Hello'); // Types instantly
|
||||||
* await frame.type('#mytextarea', 'World', {delay: 100}); // Types slower, like a user
|
* await frame.type('#mytextarea', 'World', { delay: 100 }); // Types slower, like a user
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @param selector A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
|
* @param selector A selector to search for an element. If there are multiple elements satisfying the selector, the first will be
|
||||||
|
@ -8423,7 +8430,7 @@ export interface BrowserContext {
|
||||||
* **Usage**
|
* **Usage**
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* await browserContext.setGeolocation({latitude: 59.95, longitude: 30.31667});
|
* await browserContext.setGeolocation({ latitude: 59.95, longitude: 30.31667 });
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* **NOTE** Consider using
|
* **NOTE** Consider using
|
||||||
|
@ -8904,7 +8911,7 @@ export interface JSHandle<T = any> {
|
||||||
* **Usage**
|
* **Usage**
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* const handle = await page.evaluateHandle(() => ({window, document}));
|
* const handle = await page.evaluateHandle(() => ({ window, document }));
|
||||||
* const properties = await handle.getProperties();
|
* const properties = await handle.getProperties();
|
||||||
* const windowHandle = properties.get('window');
|
* const windowHandle = properties.get('window');
|
||||||
* const documentHandle = properties.get('document');
|
* const documentHandle = properties.get('document');
|
||||||
|
@ -10200,7 +10207,7 @@ export interface ElementHandle<T=Node> extends JSHandle<T> {
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* await elementHandle.type('Hello'); // Types instantly
|
* await elementHandle.type('Hello'); // Types instantly
|
||||||
* await elementHandle.type('World', {delay: 100}); // Types slower, like a user
|
* await elementHandle.type('World', { delay: 100 }); // Types slower, like a user
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* An example of typing into a text field and then submitting the form:
|
* An example of typing into a text field and then submitting the form:
|
||||||
|
@ -11241,8 +11248,8 @@ export interface Locator {
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* await page
|
* await page
|
||||||
* .getByPlaceholder("name@example.com")
|
* .getByPlaceholder('name@example.com')
|
||||||
* .fill("playwright@microsoft.com");
|
* .fill('playwright@microsoft.com');
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @param text Text to locate the element for.
|
* @param text Text to locate the element for.
|
||||||
|
@ -11389,9 +11396,13 @@ export interface Locator {
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* // Set custom test id attribute from @playwright/test config:
|
* // Set custom test id attribute from @playwright/test config:
|
||||||
* use: {
|
* import { defineConfig } from '@playwright/test';
|
||||||
* testIdAttribute: 'data-pw'
|
*
|
||||||
* }
|
* export default defineConfig({
|
||||||
|
* use: {
|
||||||
|
* testIdAttribute: 'data-pw'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @param testId Id to locate the element by.
|
* @param testId Id to locate the element by.
|
||||||
|
@ -11417,19 +11428,19 @@ export interface Locator {
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* // Matches <span>
|
* // Matches <span>
|
||||||
* page.getByText('world')
|
* page.getByText('world');
|
||||||
*
|
*
|
||||||
* // Matches first <div>
|
* // Matches first <div>
|
||||||
* page.getByText('Hello world')
|
* page.getByText('Hello world');
|
||||||
*
|
*
|
||||||
* // Matches second <div>
|
* // Matches second <div>
|
||||||
* page.getByText('Hello', { exact: true })
|
* page.getByText('Hello', { exact: true });
|
||||||
*
|
*
|
||||||
* // Matches both <div>s
|
* // Matches both <div>s
|
||||||
* page.getByText(/Hello/)
|
* page.getByText(/Hello/);
|
||||||
*
|
*
|
||||||
* // Matches second <div>
|
* // Matches second <div>
|
||||||
* page.getByText(/^hello$/i)
|
* page.getByText(/^hello$/i);
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* **Details**
|
* **Details**
|
||||||
|
@ -12282,7 +12293,7 @@ export interface Locator {
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* await element.type('Hello'); // Types instantly
|
* await element.type('Hello'); // Types instantly
|
||||||
* await element.type('World', {delay: 100}); // Types slower, like a user
|
* await element.type('World', { delay: 100 }); // Types slower, like a user
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* An example of typing into a text field and then submitting the form:
|
* An example of typing into a text field and then submitting the form:
|
||||||
|
@ -13204,12 +13215,12 @@ export namespace errors {
|
||||||
* const context = await browser.newContext();
|
* const context = await browser.newContext();
|
||||||
* const page = await context.newPage();
|
* const page = await context.newPage();
|
||||||
* try {
|
* try {
|
||||||
* await page.locator("text=Foo").click({
|
* await page.locator('text=Foo').click({
|
||||||
* timeout: 100,
|
* timeout: 100,
|
||||||
* })
|
* });
|
||||||
* } catch (error) {
|
* } catch (error) {
|
||||||
* if (error instanceof playwright.errors.TimeoutError)
|
* if (error instanceof playwright.errors.TimeoutError)
|
||||||
* console.log("Timeout!")
|
* console.log('Timeout!');
|
||||||
* }
|
* }
|
||||||
* await browser.close();
|
* await browser.close();
|
||||||
* })();
|
* })();
|
||||||
|
@ -13517,11 +13528,11 @@ export interface ElectronApplication {
|
||||||
* **Usage**
|
* **Usage**
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* const electronApp = await electron.launch({
|
* const electronApp = await electron.launch({
|
||||||
* args: ['main.js']
|
* args: ['main.js']
|
||||||
* });
|
* });
|
||||||
* const window = await electronApp.firstWindow();
|
* const window = await electronApp.firstWindow();
|
||||||
* // ...
|
* // ...
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @param options
|
* @param options
|
||||||
|
@ -16305,7 +16316,7 @@ export interface Browser extends EventEmitter {
|
||||||
* **Usage**
|
* **Usage**
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* await browser.startTracing(page, {path: 'trace.json'});
|
* await browser.startTracing(page, { path: 'trace.json' });
|
||||||
* await page.goto('https://www.google.com');
|
* await page.goto('https://www.google.com');
|
||||||
* await browser.stopTracing();
|
* await browser.stopTracing();
|
||||||
* ```
|
* ```
|
||||||
|
@ -16409,7 +16420,7 @@ export interface BrowserServer {
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* // Listen for all console logs
|
* // Listen for all console logs
|
||||||
* page.on('console', msg => console.log(msg.text()))
|
* page.on('console', msg => console.log(msg.text()));
|
||||||
*
|
*
|
||||||
* // Listen for all console events and handle errors
|
* // Listen for all console events and handle errors
|
||||||
* page.on('console', msg => {
|
* page.on('console', msg => {
|
||||||
|
@ -16425,8 +16436,8 @@ export interface BrowserServer {
|
||||||
* const msg = await msgPromise;
|
* const msg = await msgPromise;
|
||||||
*
|
*
|
||||||
* // Deconstruct console log arguments
|
* // Deconstruct console log arguments
|
||||||
* await msg.args()[0].jsonValue() // hello
|
* await msg.args()[0].jsonValue(); // hello
|
||||||
* await msg.args()[1].jsonValue() // 42
|
* await msg.args()[1].jsonValue(); // 42
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -16483,7 +16494,7 @@ export interface ConsoleMessage {
|
||||||
* const { chromium } = require('playwright');
|
* const { chromium } = require('playwright');
|
||||||
* const v8toIstanbul = require('v8-to-istanbul');
|
* const v8toIstanbul = require('v8-to-istanbul');
|
||||||
*
|
*
|
||||||
* (async() => {
|
* (async () => {
|
||||||
* const browser = await chromium.launch();
|
* const browser = await chromium.launch();
|
||||||
* const page = await browser.newPage();
|
* const page = await browser.newPage();
|
||||||
* await page.coverage.startJSCoverage();
|
* await page.coverage.startJSCoverage();
|
||||||
|
@ -17188,8 +17199,8 @@ export interface FrameLocator {
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* await page
|
* await page
|
||||||
* .getByPlaceholder("name@example.com")
|
* .getByPlaceholder('name@example.com')
|
||||||
* .fill("playwright@microsoft.com");
|
* .fill('playwright@microsoft.com');
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @param text Text to locate the element for.
|
* @param text Text to locate the element for.
|
||||||
|
@ -17336,9 +17347,13 @@ export interface FrameLocator {
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* // Set custom test id attribute from @playwright/test config:
|
* // Set custom test id attribute from @playwright/test config:
|
||||||
* use: {
|
* import { defineConfig } from '@playwright/test';
|
||||||
* testIdAttribute: 'data-pw'
|
*
|
||||||
* }
|
* export default defineConfig({
|
||||||
|
* use: {
|
||||||
|
* testIdAttribute: 'data-pw'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @param testId Id to locate the element by.
|
* @param testId Id to locate the element by.
|
||||||
|
@ -17364,19 +17379,19 @@ export interface FrameLocator {
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* // Matches <span>
|
* // Matches <span>
|
||||||
* page.getByText('world')
|
* page.getByText('world');
|
||||||
*
|
*
|
||||||
* // Matches first <div>
|
* // Matches first <div>
|
||||||
* page.getByText('Hello world')
|
* page.getByText('Hello world');
|
||||||
*
|
*
|
||||||
* // Matches second <div>
|
* // Matches second <div>
|
||||||
* page.getByText('Hello', { exact: true })
|
* page.getByText('Hello', { exact: true });
|
||||||
*
|
*
|
||||||
* // Matches both <div>s
|
* // Matches both <div>s
|
||||||
* page.getByText(/Hello/)
|
* page.getByText(/Hello/);
|
||||||
*
|
*
|
||||||
* // Matches second <div>
|
* // Matches second <div>
|
||||||
* page.getByText(/^hello$/i)
|
* page.getByText(/^hello$/i);
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* **Details**
|
* **Details**
|
||||||
|
@ -17627,7 +17642,7 @@ export interface Keyboard {
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* await page.keyboard.type('Hello'); // Types instantly
|
* await page.keyboard.type('Hello'); // Types instantly
|
||||||
* await page.keyboard.type('World', {delay: 100}); // Types slower, like a user
|
* await page.keyboard.type('World', { delay: 100 }); // Types slower, like a user
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* **NOTE** Modifier keys DO NOT effect `keyboard.type`. Holding down `Shift` will not type the text in upper case.
|
* **NOTE** Modifier keys DO NOT effect `keyboard.type`. Holding down `Shift` will not type the text in upper case.
|
||||||
|
@ -17663,7 +17678,7 @@ export interface Keyboard {
|
||||||
* log: (name, severity, message, args) => console.log(`${name} ${message}`)
|
* log: (name, severity, message, args) => console.log(`${name} ${message}`)
|
||||||
* }
|
* }
|
||||||
* });
|
* });
|
||||||
* ...
|
* // ...
|
||||||
* })();
|
* })();
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
|
@ -18309,7 +18324,7 @@ export interface Route {
|
||||||
* foo: 'foo-value', // set "foo" header
|
* foo: 'foo-value', // set "foo" header
|
||||||
* bar: undefined, // remove "bar" header
|
* bar: undefined, // remove "bar" header
|
||||||
* };
|
* };
|
||||||
* route.continue({headers});
|
* route.continue({ headers });
|
||||||
* });
|
* });
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
|
@ -18403,7 +18418,7 @@ export interface Route {
|
||||||
* foo: 'foo-value', // set "foo" header
|
* foo: 'foo-value', // set "foo" header
|
||||||
* bar: undefined, // remove "bar" header
|
* bar: undefined, // remove "bar" header
|
||||||
* };
|
* };
|
||||||
* route.fallback({headers});
|
* route.fallback({ headers });
|
||||||
* });
|
* });
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
|
|
|
@ -3322,7 +3322,7 @@ export interface TestType<TestArgs extends KeyValue, WorkerArgs extends KeyValue
|
||||||
* ```js
|
* ```js
|
||||||
* // playwright.config.ts
|
* // playwright.config.ts
|
||||||
* import { defineConfig } from '@playwright/test';
|
* import { defineConfig } from '@playwright/test';
|
||||||
* import { Options } from './my-test';
|
* import type { Options } from './my-test';
|
||||||
*
|
*
|
||||||
* export default defineConfig<Options>({
|
* export default defineConfig<Options>({
|
||||||
* projects: [
|
* projects: [
|
||||||
|
@ -5573,8 +5573,8 @@ interface LocatorAssertions {
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* const locator = page.locator("id=favorite-colors");
|
* const locator = page.locator('id=favorite-colors');
|
||||||
* await locator.selectOption(["R", "G"]);
|
* await locator.selectOption(['R', 'G']);
|
||||||
* await expect(locator).toHaveValues([/R/, /G/]);
|
* await expect(locator).toHaveValues([/R/, /G/]);
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
|
|
|
@ -316,7 +316,7 @@ export interface FullResult {
|
||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* // my-awesome-reporter.ts
|
* // my-awesome-reporter.ts
|
||||||
* import { Reporter, FullConfig, Suite, TestCase, TestResult, FullResult } from '@playwright/test/reporter';
|
* import type { Reporter, FullConfig, Suite, TestCase, TestResult, FullResult } from '@playwright/test/reporter';
|
||||||
*
|
*
|
||||||
* class MyReporter implements Reporter {
|
* class MyReporter implements Reporter {
|
||||||
* constructor(options: { customOption?: string } = {}) {
|
* constructor(options: { customOption?: string } = {}) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//@ts-check
|
// @ts-check
|
||||||
import '../src/assets/index.css';
|
import '../src/assets/index.css';
|
||||||
import { beforeMount, afterMount } from '@playwright/experimental-ct-svelte/hooks';
|
import { beforeMount, afterMount } from '@playwright/experimental-ct-svelte/hooks';
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue