Merge branch 'microsoft:main' into main
This commit is contained in:
commit
2f91918256
|
|
@ -601,6 +601,23 @@ steps:
|
|||
- 'CI=true'
|
||||
```
|
||||
|
||||
### Drone
|
||||
* langs: js
|
||||
|
||||
To run Playwright tests on Drone, use our public Docker image ([see Dockerfile](./docker.md)).
|
||||
|
||||
```yml
|
||||
kind: pipeline
|
||||
name: default
|
||||
type: docker
|
||||
|
||||
steps:
|
||||
- name: test
|
||||
image: mcr.microsoft.com/playwright:v%%VERSION%%-jammy
|
||||
commands:
|
||||
- npx playwright test
|
||||
```
|
||||
|
||||
## Caching browsers
|
||||
|
||||
Caching browser binaries is not recommended, since the amount of time it takes to restore the cache is comparable to the time it takes to download the binaries. Especially under Linux, [operating system dependencies](./browsers.md#install-system-dependencies) need to be installed, which are not cacheable.
|
||||
|
|
@ -633,7 +650,7 @@ By default, Playwright launches browsers in headless mode. See in our [Running t
|
|||
On Linux agents, headed execution requires [Xvfb](https://en.wikipedia.org/wiki/Xvfb) to be installed. Our [Docker image](./docker.md) and GitHub Action have Xvfb pre-installed. To run browsers in headed mode with Xvfb, add `xvfb-run` before the actual command.
|
||||
|
||||
```bash js
|
||||
xvfb-run npx playwrght test
|
||||
xvfb-run npx playwright test
|
||||
```
|
||||
```bash python
|
||||
xvfb-run pytest
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@ Utilizing the new [Clock] API allows to manipulate and control time within tests
|
|||
```csharp
|
||||
// Initialize clock with some time before the test time and let the page load naturally.
|
||||
// `Date.now` will progress as the timers fire.
|
||||
await Page.Clock.InstallAsync(new
|
||||
await Page.Clock.InstallAsync(new()
|
||||
{
|
||||
Time = new DateTime(2024, 2, 2, 8, 0, 0)
|
||||
TimeDate = new DateTime(2024, 2, 2, 8, 0, 0)
|
||||
});
|
||||
await Page.GotoAsync("http://localhost:3333");
|
||||
|
||||
|
|
@ -28,11 +28,11 @@ await Page.GotoAsync("http://localhost:3333");
|
|||
await Page.Clock.PauseAtAsync(new DateTime(2024, 2, 2, 10, 0, 0));
|
||||
|
||||
// Assert the page state.
|
||||
await Expect(Page.GetByTestId("current-time")).ToHaveText("2/2/2024, 10:00:00 AM");
|
||||
await Expect(Page.GetByTestId("current-time")).ToHaveTextAsync("2/2/2024, 10:00:00 AM");
|
||||
|
||||
// Close the laptop lid again and open it at 10:30am.
|
||||
await Page.Clock.FastForwardAsync("30:00");
|
||||
await Expect(Page.GetByTestId("current-time")).ToHaveText("2/2/2024, 10:30:00 AM");
|
||||
await Expect(Page.GetByTestId("current-time")).ToHaveTextAsync("2/2/2024, 10:30:00 AM");
|
||||
```
|
||||
|
||||
See [the clock guide](./clock.md) for more details.
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
},
|
||||
{
|
||||
"name": "webkit",
|
||||
"revision": "2039",
|
||||
"revision": "2041",
|
||||
"installByDefault": true,
|
||||
"revisionOverrides": {
|
||||
"mac10.14": "1446",
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ import type { Page } from './page';
|
|||
import { ConsoleMessage } from './consoleMessage';
|
||||
import type { Env, WaitForEventOptions, Headers, BrowserContextOptions } from './types';
|
||||
import { Waiter } from './waiter';
|
||||
import { TargetClosedError } from './errors';
|
||||
import { TargetClosedError, isTargetClosedError } from './errors';
|
||||
|
||||
type ElectronOptions = Omit<channels.ElectronLaunchOptions, 'env'|'extraHTTPHeaders'|'recordHar'|'colorScheme'|'acceptDownloads'> & {
|
||||
env?: Env,
|
||||
|
|
@ -116,7 +116,13 @@ export class ElectronApplication extends ChannelOwner<channels.ElectronApplicati
|
|||
}
|
||||
|
||||
async close() {
|
||||
await this._context.close().catch(() => {});
|
||||
try {
|
||||
await this._context.close();
|
||||
} catch (e) {
|
||||
if (isTargetClosedError(e))
|
||||
return;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
async waitForEvent(event: string, optionsOrPredicate: WaitForEventOptions = {}): Promise<any> {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,8 @@
|
|||
"./hooks": {
|
||||
"types": "./hooks.d.ts",
|
||||
"default": "./hooks.mjs"
|
||||
}
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@playwright/experimental-ct-core": "1.46.0-next",
|
||||
|
|
|
|||
|
|
@ -26,7 +26,8 @@
|
|||
"./hooks": {
|
||||
"types": "./hooks.d.ts",
|
||||
"default": "./hooks.mjs"
|
||||
}
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@playwright/experimental-ct-core": "1.46.0-next",
|
||||
|
|
|
|||
|
|
@ -26,7 +26,8 @@
|
|||
"./hooks": {
|
||||
"types": "./hooks.d.ts",
|
||||
"default": "./hooks.mjs"
|
||||
}
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@playwright/experimental-ct-core": "1.46.0-next",
|
||||
|
|
|
|||
|
|
@ -26,7 +26,8 @@
|
|||
"./hooks": {
|
||||
"types": "./hooks.d.ts",
|
||||
"default": "./hooks.mjs"
|
||||
}
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@playwright/experimental-ct-core": "1.46.0-next",
|
||||
|
|
|
|||
|
|
@ -26,7 +26,8 @@
|
|||
"./hooks": {
|
||||
"types": "./hooks.d.ts",
|
||||
"default": "./hooks.mjs"
|
||||
}
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@playwright/experimental-ct-core": "1.46.0-next",
|
||||
|
|
|
|||
|
|
@ -26,7 +26,8 @@
|
|||
"./hooks": {
|
||||
"types": "./hooks.d.ts",
|
||||
"default": "./hooks.mjs"
|
||||
}
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@playwright/experimental-ct-core": "1.46.0-next",
|
||||
|
|
|
|||
|
|
@ -609,7 +609,7 @@ class ArtifactsRecorder {
|
|||
if ((tracing as any)[this._startedCollectingArtifacts])
|
||||
return;
|
||||
(tracing as any)[this._startedCollectingArtifacts] = true;
|
||||
if (this._testInfo._tracing.traceOptions())
|
||||
if (this._testInfo._tracing.traceOptions() && (tracing as any)[kTracingStarted])
|
||||
await tracing.stopChunk({ path: this._testInfo._tracing.generateNextTraceRecordingPath() });
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
import { test } from './npmTest';
|
||||
import fs from 'fs';
|
||||
import { expect } from 'packages/playwright-test';
|
||||
import path from 'path';
|
||||
|
||||
test('electron should work', async ({ exec, tsc, writeFiles }) => {
|
||||
|
|
@ -39,3 +40,46 @@ test('electron should work with special characters in path', async ({ exec, tmpW
|
|||
cwd: path.join(folderName)
|
||||
});
|
||||
});
|
||||
|
||||
test('should work when wrapped inside @playwright/test and trace is enabled', async ({ exec, tmpWorkspace, writeFiles }) => {
|
||||
await exec('npm i -D @playwright/test electron@31');
|
||||
await writeFiles({
|
||||
'electron-with-tracing.spec.ts': `
|
||||
import { test, expect, _electron } from '@playwright/test';
|
||||
|
||||
test('should work', async ({ trace }) => {
|
||||
const electronApp = await _electron.launch({ args: [${JSON.stringify(path.join(__dirname, '../electron/electron-window-app.js'))}] });
|
||||
|
||||
const window = await electronApp.firstWindow();
|
||||
if (trace)
|
||||
await window.context().tracing.start({ screenshots: true, snapshots: true });
|
||||
|
||||
await window.goto('data:text/html,<title>Playwright</title><h1>Playwright</h1>');
|
||||
await expect(window).toHaveTitle(/Playwright/);
|
||||
await expect(window.getByRole('heading')).toHaveText('Playwright');
|
||||
|
||||
const path = test.info().outputPath('electron-trace.zip');
|
||||
if (trace) {
|
||||
await window.context().tracing.stop({ path });
|
||||
test.info().attachments.push({ name: 'trace', path, contentType: 'application/zip' });
|
||||
}
|
||||
await electronApp.close();
|
||||
});
|
||||
`,
|
||||
});
|
||||
const jsonOutputName = test.info().outputPath('report.json');
|
||||
await exec('npx playwright test --trace=on --reporter=json electron-with-tracing.spec.ts', {
|
||||
env: { PLAYWRIGHT_JSON_OUTPUT_NAME: jsonOutputName }
|
||||
});
|
||||
const traces = [
|
||||
// our actual trace.
|
||||
path.join(tmpWorkspace, 'test-results', 'electron-with-tracing-should-work', 'electron-trace.zip'),
|
||||
// contains the expect() calls
|
||||
path.join(tmpWorkspace, 'test-results', 'electron-with-tracing-should-work', 'trace.zip'),
|
||||
];
|
||||
for (const trace of traces)
|
||||
expect(fs.existsSync(trace)).toBe(true);
|
||||
const report = JSON.parse(fs.readFileSync(jsonOutputName, 'utf-8'));
|
||||
expect(new Set(['trace'])).toEqual(new Set(report.suites[0].specs[0].tests[0].results[0].attachments.map(a => a.name)));
|
||||
expect(new Set(traces.map(p => fs.realpathSync(p)))).toEqual(new Set(report.suites[0].specs[0].tests[0].results[0].attachments.map(a => a.path)));
|
||||
});
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
*/
|
||||
|
||||
import { test as it, expect } from './pageTest';
|
||||
import { attachFrame, chromiumVersionLessThan } from '../config/utils';
|
||||
import { attachFrame } from '../config/utils';
|
||||
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
|
|
@ -37,7 +37,7 @@ it('should upload the file', async ({ page, server, asset }) => {
|
|||
}, input)).toBe('contents of the file');
|
||||
});
|
||||
|
||||
it('should upload a folder', async ({ page, server, browserName, headless, browserVersion, isAndroid }) => {
|
||||
it('should upload a folder', async ({ page, server, browserName, headless, browserMajorVersion, isAndroid }) => {
|
||||
it.skip(isAndroid);
|
||||
it.skip(os.platform() === 'darwin' && parseInt(os.release().split('.')[0], 10) <= 21, 'WebKit on macOS-12 is frozen');
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ it('should upload a folder', async ({ page, server, browserName, headless, brows
|
|||
await input.setInputFiles(dir);
|
||||
expect(new Set(await page.evaluate(e => [...e.files].map(f => f.webkitRelativePath), input))).toEqual(new Set([
|
||||
// https://issues.chromium.org/issues/345393164
|
||||
...((browserName === 'chromium' && headless && !process.env.PLAYWRIGHT_CHROMIUM_USE_HEADLESS_NEW && chromiumVersionLessThan(browserVersion, '127.0.6533.0')) ? [] : ['file-upload-test/sub-dir/really.txt']),
|
||||
...((browserName === 'chromium' && headless && !process.env.PLAYWRIGHT_CHROMIUM_USE_HEADLESS_NEW && browserMajorVersion < 127) ? [] : ['file-upload-test/sub-dir/really.txt']),
|
||||
'file-upload-test/file1.txt',
|
||||
'file-upload-test/file2',
|
||||
]));
|
||||
|
|
|
|||
Loading…
Reference in a new issue