New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@playwright/test

Package Overview
Dependencies
Maintainers
6
Versions
2472
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@playwright/test - npm Package Compare versions

Comparing version 0.1101.0 to 0.1102.0-alpha1

216

out/index.d.ts

@@ -16,53 +16,181 @@ /**

*/
import { Browser, BrowserContext, BrowserContextOptions, Page, LaunchOptions } from 'playwright';
import * as folio from 'folio';
export * from 'folio';
export { BrowserContextOptions, LaunchOptions } from 'playwright';
export declare type BrowserName = 'chromium' | 'firefox' | 'webkit';
export declare type PlaywrightTestArgs = {
import type { Browser, BrowserContext, BrowserContextOptions, BrowserType, LaunchOptions, Page } from 'playwright';
export { expect, config } from 'folio';
declare type PlaywrightParameters = {
browserName: 'chromium' | 'firefox' | 'webkit';
headful: boolean;
platform: 'win32' | 'linux' | 'darwin';
screenshotOnFailure: boolean;
slowMo: number;
video: boolean;
};
declare type PlaywrightWorkerFixtures = {
playwright: typeof import('playwright');
browserName: BrowserName;
browserType: BrowserType<Browser>;
browserOptions: LaunchOptions;
browser: Browser;
isChromium: boolean;
isFirefox: boolean;
isWebKit: boolean;
isWindows: boolean;
isMac: boolean;
isLinux: boolean;
};
declare type PlaywrightTestFixtures = {
contextOptions: BrowserContextOptions;
contextFactory: (options?: BrowserContextOptions) => Promise<BrowserContext>;
context: BrowserContext;
page: Page;
};
export declare type PlaywrightOptions = LaunchOptions & BrowserContextOptions & {
screenshot?: 'off' | 'on' | 'only-on-failure';
video?: 'off' | 'on' | 'retain-on-failure' | 'retry-with-video';
snapshotPathSegment?: string;
export declare const folio: import("folio").Folio<{
testInfo: import("folio").TestInfo;
testParametersPathSegment: string;
} & PlaywrightTestFixtures, {
testWorkerIndex: number;
} & PlaywrightWorkerFixtures, PlaywrightParameters>;
export declare const it: {
(name: string, inner: (fixtures: PlaywrightParameters & {
testWorkerIndex: number;
} & PlaywrightWorkerFixtures & {
testInfo: import("folio").TestInfo;
testParametersPathSegment: string;
} & PlaywrightTestFixtures) => void | Promise<void>): void;
(name: string, modifierFn: (modifier: import("folio/out/testModifier").TestModifier, parameters: PlaywrightParameters) => any, inner: (fixtures: PlaywrightParameters & {
testWorkerIndex: number;
} & PlaywrightWorkerFixtures & {
testInfo: import("folio").TestInfo;
testParametersPathSegment: string;
} & PlaywrightTestFixtures) => void | Promise<void>): void;
} & {
only: {
(name: string, inner: (fixtures: PlaywrightParameters & {
testWorkerIndex: number;
} & PlaywrightWorkerFixtures & {
testInfo: import("folio").TestInfo;
testParametersPathSegment: string;
} & PlaywrightTestFixtures) => void | Promise<void>): void;
(name: string, modifierFn: (modifier: import("folio/out/testModifier").TestModifier, parameters: PlaywrightParameters) => any, inner: (fixtures: PlaywrightParameters & {
testWorkerIndex: number;
} & PlaywrightWorkerFixtures & {
testInfo: import("folio").TestInfo;
testParametersPathSegment: string;
} & PlaywrightTestFixtures) => void | Promise<void>): void;
};
skip: {
(name: string, inner: (fixtures: PlaywrightParameters & {
testWorkerIndex: number;
} & PlaywrightWorkerFixtures & {
testInfo: import("folio").TestInfo;
testParametersPathSegment: string;
} & PlaywrightTestFixtures) => void | Promise<void>): void;
(name: string, modifierFn: (modifier: import("folio/out/testModifier").TestModifier, parameters: PlaywrightParameters) => any, inner: (fixtures: PlaywrightParameters & {
testWorkerIndex: number;
} & PlaywrightWorkerFixtures & {
testInfo: import("folio").TestInfo;
testParametersPathSegment: string;
} & PlaywrightTestFixtures) => void | Promise<void>): void;
};
};
export declare class PlaywrightEnv implements folio.Env<PlaywrightTestArgs> {
private _playwright;
private _browserName;
private _options;
private _browser;
private _context;
private _page;
private _allPages;
constructor(browserName: BrowserName, options?: PlaywrightOptions);
beforeAll(): Promise<void>;
beforeEach(testInfo: folio.TestInfo): Promise<{
playwright: typeof import("playwright");
browserName: "chromium" | "firefox" | "webkit";
browser: Browser;
context: BrowserContext;
page: Page;
}>;
afterEach(testInfo: folio.TestInfo): Promise<void>;
afterAll(): Promise<void>;
}
export declare class ChromiumEnv extends PlaywrightEnv {
constructor(options?: PlaywrightOptions);
}
export declare class FirefoxEnv extends PlaywrightEnv {
constructor(options?: PlaywrightOptions);
}
export declare class WebKitEnv extends PlaywrightEnv {
constructor(options?: PlaywrightOptions);
}
declare type PlaywrightTestOptions = {
contextOptions?: BrowserContextOptions;
export declare const fit: {
(name: string, inner: (fixtures: PlaywrightParameters & {
testWorkerIndex: number;
} & PlaywrightWorkerFixtures & {
testInfo: import("folio").TestInfo;
testParametersPathSegment: string;
} & PlaywrightTestFixtures) => void | Promise<void>): void;
(name: string, modifierFn: (modifier: import("folio/out/testModifier").TestModifier, parameters: PlaywrightParameters) => any, inner: (fixtures: PlaywrightParameters & {
testWorkerIndex: number;
} & PlaywrightWorkerFixtures & {
testInfo: import("folio").TestInfo;
testParametersPathSegment: string;
} & PlaywrightTestFixtures) => void | Promise<void>): void;
};
export declare function newTestType<TestArgs = {}, TestOptions = {}>(): folio.TestType<TestArgs & PlaywrightTestArgs, TestOptions & PlaywrightTestOptions>;
export declare const test: folio.TestType<PlaywrightTestArgs, PlaywrightTestOptions>;
export declare const xit: {
(name: string, inner: (fixtures: PlaywrightParameters & {
testWorkerIndex: number;
} & PlaywrightWorkerFixtures & {
testInfo: import("folio").TestInfo;
testParametersPathSegment: string;
} & PlaywrightTestFixtures) => void | Promise<void>): void;
(name: string, modifierFn: (modifier: import("folio/out/testModifier").TestModifier, parameters: PlaywrightParameters) => any, inner: (fixtures: PlaywrightParameters & {
testWorkerIndex: number;
} & PlaywrightWorkerFixtures & {
testInfo: import("folio").TestInfo;
testParametersPathSegment: string;
} & PlaywrightTestFixtures) => void | Promise<void>): void;
};
export declare const test: {
(name: string, inner: (fixtures: PlaywrightParameters & {
testWorkerIndex: number;
} & PlaywrightWorkerFixtures & {
testInfo: import("folio").TestInfo;
testParametersPathSegment: string;
} & PlaywrightTestFixtures) => void | Promise<void>): void;
(name: string, modifierFn: (modifier: import("folio/out/testModifier").TestModifier, parameters: PlaywrightParameters) => any, inner: (fixtures: PlaywrightParameters & {
testWorkerIndex: number;
} & PlaywrightWorkerFixtures & {
testInfo: import("folio").TestInfo;
testParametersPathSegment: string;
} & PlaywrightTestFixtures) => void | Promise<void>): void;
} & {
only: {
(name: string, inner: (fixtures: PlaywrightParameters & {
testWorkerIndex: number;
} & PlaywrightWorkerFixtures & {
testInfo: import("folio").TestInfo;
testParametersPathSegment: string;
} & PlaywrightTestFixtures) => void | Promise<void>): void;
(name: string, modifierFn: (modifier: import("folio/out/testModifier").TestModifier, parameters: PlaywrightParameters) => any, inner: (fixtures: PlaywrightParameters & {
testWorkerIndex: number;
} & PlaywrightWorkerFixtures & {
testInfo: import("folio").TestInfo;
testParametersPathSegment: string;
} & PlaywrightTestFixtures) => void | Promise<void>): void;
};
skip: {
(name: string, inner: (fixtures: PlaywrightParameters & {
testWorkerIndex: number;
} & PlaywrightWorkerFixtures & {
testInfo: import("folio").TestInfo;
testParametersPathSegment: string;
} & PlaywrightTestFixtures) => void | Promise<void>): void;
(name: string, modifierFn: (modifier: import("folio/out/testModifier").TestModifier, parameters: PlaywrightParameters) => any, inner: (fixtures: PlaywrightParameters & {
testWorkerIndex: number;
} & PlaywrightWorkerFixtures & {
testInfo: import("folio").TestInfo;
testParametersPathSegment: string;
} & PlaywrightTestFixtures) => void | Promise<void>): void;
};
};
export declare const describe: {
(name: string, inner: () => void): void;
(name: string, modifierFn: (modifier: import("folio/out/testModifier").TestModifier, parameters: PlaywrightParameters) => any, inner: () => void): void;
} & {
only: {
(name: string, inner: () => void): void;
(name: string, modifierFn: (modifier: import("folio/out/testModifier").TestModifier, parameters: PlaywrightParameters) => any, inner: () => void): void;
};
skip: {
(name: string, inner: () => void): void;
(name: string, modifierFn: (modifier: import("folio/out/testModifier").TestModifier, parameters: PlaywrightParameters) => any, inner: () => void): void;
};
};
export declare const beforeEach: (inner: (fixtures: PlaywrightParameters & {
testWorkerIndex: number;
} & PlaywrightWorkerFixtures & {
testInfo: import("folio").TestInfo;
testParametersPathSegment: string;
} & PlaywrightTestFixtures) => Promise<void>) => void;
export declare const afterEach: (inner: (fixtures: PlaywrightParameters & {
testWorkerIndex: number;
} & PlaywrightWorkerFixtures & {
testInfo: import("folio").TestInfo;
testParametersPathSegment: string;
} & PlaywrightTestFixtures) => Promise<void>) => void;
export declare const beforeAll: (inner: (fixtures: {
testWorkerIndex: number;
} & PlaywrightWorkerFixtures) => Promise<void>) => void;
export declare const afterAll: (inner: (fixtures: {
testWorkerIndex: number;
} & PlaywrightWorkerFixtures) => Promise<void>) => void;
//# sourceMappingURL=index.d.ts.map

@@ -17,122 +17,109 @@ "use strict";

*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.test = exports.newTestType = exports.WebKitEnv = exports.FirefoxEnv = exports.ChromiumEnv = exports.PlaywrightEnv = void 0;
const folio = __importStar(require("folio"));
const fs = __importStar(require("fs"));
const util = __importStar(require("util"));
__exportStar(require("folio"), exports);
class PlaywrightEnv {
constructor(browserName, options = {}) {
this._allPages = [];
this._browserName = browserName;
this._options = options;
}
async beforeAll() {
this._playwright = require('playwright');
this._browser = await this._playwright[this._browserName].launch({
...this._options,
handleSIGINT: false,
exports.afterAll = exports.beforeAll = exports.afterEach = exports.beforeEach = exports.describe = exports.test = exports.xit = exports.fit = exports.it = exports.folio = exports.config = exports.expect = void 0;
const folio_1 = require("folio");
var folio_2 = require("folio");
Object.defineProperty(exports, "expect", { enumerable: true, get: function () { return folio_2.expect; } });
Object.defineProperty(exports, "config", { enumerable: true, get: function () { return folio_2.config; } });
// Test timeout for e2e tests is 30 seconds.
folio_1.config.timeout = 30000;
const fixtures = folio_1.folio.extend();
fixtures.browserName.initParameter('Browser type name', (process.env.BROWSER || 'chromium'));
fixtures.headful.initParameter('Whether to run tests headless or headful', process.env.HEADFUL ? true : false);
fixtures.platform.initParameter('Operating system', process.platform);
fixtures.screenshotOnFailure.initParameter('Generate screenshot on failure', false);
fixtures.slowMo.initParameter('Slows down Playwright operations by the specified amount of milliseconds', 0);
fixtures.video.initParameter('Record videos while running tests', false);
fixtures.browserOptions.init(async ({ headful, slowMo }, run) => {
await run({
handleSIGINT: false,
slowMo,
headless: !headful,
});
}, { scope: 'worker' });
fixtures.playwright.init(async ({}, run) => {
const playwright = require('playwright');
await run(playwright);
}, { scope: 'worker' });
fixtures.browserType.init(async ({ playwright, browserName }, run) => {
const browserType = playwright[browserName];
await run(browserType);
}, { scope: 'worker' });
fixtures.browser.init(async ({ browserType, browserOptions }, run) => {
const browser = await browserType.launch(browserOptions);
await run(browser);
await browser.close();
}, { scope: 'worker' });
fixtures.isChromium.init(async ({ browserName }, run) => {
await run(browserName === 'chromium');
}, { scope: 'worker' });
fixtures.isFirefox.init(async ({ browserName }, run) => {
await run(browserName === 'firefox');
}, { scope: 'worker' });
fixtures.isWebKit.init(async ({ browserName }, run) => {
await run(browserName === 'webkit');
}, { scope: 'worker' });
fixtures.isWindows.init(async ({ platform }, run) => {
await run(platform === 'win32');
}, { scope: 'worker' });
fixtures.isMac.init(async ({ platform }, run) => {
await run(platform === 'darwin');
}, { scope: 'worker' });
fixtures.isLinux.init(async ({ platform }, run) => {
await run(platform === 'linux');
}, { scope: 'worker' });
fixtures.contextOptions.init(async ({ video, testInfo }, run) => {
if (video) {
await run({
videosPath: testInfo.outputPath(''),
});
}
async beforeEach(testInfo) {
const options = testInfo.testOptions;
const recordVideo = this._options.video === 'on' || this._options.video === 'retain-on-failure' ||
(this._options.video === 'retry-with-video' && !!testInfo.retry);
this._context = await this._browser.newContext({
recordVideo: recordVideo ? { dir: testInfo.outputPath('') } : undefined,
...this._options,
...options.contextOptions
});
this._allPages = [];
this._context.on('page', page => this._allPages.push(page));
this._page = await this._context.newPage();
testInfo.snapshotPathSegment = this._options.snapshotPathSegment || (this._browserName + '-' + process.platform);
return {
playwright: this._playwright,
browserName: this._browserName,
browser: this._browser,
context: this._context,
page: this._page,
};
else {
await run({});
}
async afterEach(testInfo) {
const testFailed = testInfo.status !== testInfo.expectedStatus;
if (this._context) {
if (this._options.screenshot === 'on' || (this._options.screenshot === 'only-on-failure' && testFailed)) {
await Promise.all(this._context.pages().map((page, index) => {
const screenshotPath = testInfo.outputPath(`test-${testFailed ? 'failed' : 'finished'}-${++index}.png`);
return page.screenshot({ timeout: 5000, path: screenshotPath }).catch(e => { });
}));
}
await this._context.close();
});
fixtures.contextFactory.init(async ({ browser, contextOptions, testInfo, screenshotOnFailure }, run) => {
const contexts = [];
async function contextFactory(options = {}) {
const context = await browser.newContext({ ...contextOptions, ...options });
contexts.push(context);
return context;
}
await run(contextFactory);
if (screenshotOnFailure && (testInfo.status !== testInfo.expectedStatus)) {
let ordinal = 0;
for (const context of contexts) {
for (const page of context.pages())
await page.screenshot({ timeout: 5000, path: testInfo.outputPath(`test-failed-${++ordinal}.png`) });
}
const deleteVideos = this._options.video === 'retain-on-failure' && !testFailed;
if (deleteVideos) {
await Promise.all(this._allPages.map(async (page) => {
const video = page.video();
if (!video)
return;
const videoPath = await video.path();
await util.promisify(fs.unlink)(videoPath).catch(e => { });
}));
}
this._allPages = [];
this._context = undefined;
this._page = undefined;
}
async afterAll() {
if (this._browser)
await this._browser.close();
this._browser = undefined;
}
}
exports.PlaywrightEnv = PlaywrightEnv;
// Environment that runs tests in Chromium.
class ChromiumEnv extends PlaywrightEnv {
constructor(options = {}) {
super('chromium', options);
}
}
exports.ChromiumEnv = ChromiumEnv;
// Environment that runs tests in Firefox.
class FirefoxEnv extends PlaywrightEnv {
constructor(options = {}) {
super('firefox', options);
}
}
exports.FirefoxEnv = FirefoxEnv;
// Environment that runs tests in WebKit.
class WebKitEnv extends PlaywrightEnv {
constructor(options = {}) {
super('webkit', options);
}
}
exports.WebKitEnv = WebKitEnv;
function newTestType() {
return folio.newTestType();
}
exports.newTestType = newTestType;
exports.test = newTestType();
for (const context of contexts)
await context.close();
});
fixtures.context.init(async ({ contextFactory }, run) => {
const context = await contextFactory();
await run(context);
// Context factory is taking care of closing the context,
// so that it could capture a screenshot on failure.
});
fixtures.page.init(async ({ context }, run) => {
// Always create page off context so that they matched.
await run(await context.newPage());
// Context fixture is taking care of closing the page.
});
fixtures.testParametersPathSegment.override(async ({ browserName, platform }, run) => {
await run(browserName + '-' + platform);
});
exports.folio = fixtures.build();
exports.it = exports.folio.it;
exports.fit = exports.folio.fit;
exports.xit = exports.folio.xit;
exports.test = exports.folio.test;
exports.describe = exports.folio.describe;
exports.beforeEach = exports.folio.beforeEach;
exports.afterEach = exports.folio.afterEach;
exports.beforeAll = exports.folio.beforeAll;
exports.afterAll = exports.folio.afterAll;
// If browser is not specified, we are running tests against all three browsers.
exports.folio.generateParametrizedTests('browserName', process.env.BROWSER ? [process.env.BROWSER] : ['chromium', 'webkit', 'firefox']);
//# sourceMappingURL=index.js.map
{
"name": "@playwright/test",
"version": "0.1101.0",
"version": "0.1102.0-alpha1",
"license": "Apache-2.0",

@@ -17,3 +17,3 @@ "author": {

"prepublishOnly": "rm tsconfig.tsbuildinfo && rm -rf out && npm run build",
"test": "folio --config=test/simple/config.ts && folio --config=test/complex/config.ts"
"test": "folio test/"
},

@@ -24,3 +24,3 @@ "repository": "github:Microsoft/playwright-test",

"dependencies": {
"folio": "=0.3.23-alpha",
"folio": "=0.3.18",
"playwright": "=1.10.0",

@@ -27,0 +27,0 @@ "rimraf": "^3.0.2"

@@ -0,4 +1,6 @@

# ⚠️ This project is not ready for production. Stay tuned! ⚠️
# 🎭 Playwright test runner [![npm version](https://img.shields.io/npm/v/@playwright/test.svg?style=flat)](https://www.npmjs.com/package/@playwright/test)
Cross-browser end-to-end testing for web apps. Browser automation with [Playwright](https://playwright.dev), Jest-like assertions and built-in support for TypeScript.
Zero config cross-browser end-to-end testing for web apps. Browser automation with [Playwright](https://playwright.dev), Jest-like assertions and built-in support for TypeScript.

@@ -10,3 +12,2 @@ Playwright test runner is **available in preview** and minor breaking changes could happen. We welcome your feedback to shape this towards 1.0.

- [Write a test](#write-a-test)
- [Write a configuration file](#write-a-configuration-file)
- [Run the test](#run-the-test)

@@ -19,5 +20,5 @@ - [Examples](#examples)

- [Configuration](#configuration)
- [Modify options](#modify-options)
- [Modify context options](#modify-context-options)
- [Modify launch options](#modify-launch-options)
- [Skip tests with annotations](#skip-tests-with-annotations)
- [Modify context options for a single test](#modify-context-options-for-a-single-test)
- [Export JUnit report](#export-junit-report)

@@ -37,6 +38,6 @@

```ts
import { test, expect } from "@playwright/test";
```js
import { it, expect } from "@playwright/test";
test("is a basic test with the page", async ({ page }) => {
it("is a basic test with the page", async ({ page }) => {
await page.goto("https://playwright.dev/");

@@ -48,30 +49,25 @@ const name = await page.innerText(".navbar__title");

#### Default arguments
The test runner provides browser primitives as arguments to your test functions. Test functions can use one or more of these arguments.
- `page`: Instance of [Page][page]. Each test gets a new isolated page to run the test.
- `context`: Instance of [BrowserContext][browser-context]. Each test gets a new isolated context to run the test. The `page` object belongs to this context. Learn [how to configure](#modify-options) context creation.
- `browser`: Instance of [Browser][browser]. Browsers are shared across tests to optimize resources. Learn [how to configure](#modify-options) browser launch.
- `browserName`: The name of the browser currently running the test. Either `chromium`, `firefox` or `webkit`.
- `context`: Instance of [BrowserContext][browser-context]. Each test gets a new isolated context to run the test. The `page` object belongs to this context.
- `contextOptions`: Default options passed to context creation. Learn [how to modify them](#modify-context-options).
- `browser`: Instance of [Browser][browser]. Browsers are shared across tests to optimize resources. Each worker process gets a browser instance.
- `browserOptions`: Default options passed to browser/launch creation.
### Write a configuration file
#### Specs and assertions
Create `config.ts` to configure your tests. Here is an example configuration that runs every test in Chromium, Firefox and WebKit.
- Use `it` and `describe` to write test functions. Run a single test with `it.only` and skip a test with `it.skip`.
- For assertions, use the [`expect` API](https://jestjs.io/docs/en/expect).
```ts
import { ChromiumEnv, FirefoxEnv, WebKitEnv, test, setConfig } from "@playwright/test";
```js
const { it, describe } = require("@playwright/test");
setConfig({
testDir: __dirname, // Search for tests in this directory.
timeout: 30000, // Each test is given 30 seconds.
describe("feature foo", () => {
it("is working correctly", async ({ page }) => {
// Test function
});
});
const options = {
headless: true, // Run tests in headless browsers.
viewport: { width: 1280, height: 720 },
};
// Run tests in three browsers.
test.runWith(new ChromiumEnv(options), { tag: 'chromium' });
test.runWith(new FirefoxEnv(options), { tag: 'firefox' });
test.runWith(new WebKitEnv(options), { tag: 'webkit' });
```

@@ -81,25 +77,31 @@

Tests can be run in single or multiple browsers, in parallel or sequentially.
Tests can be run on single or multiple browsers and with flags to generate screenshot on test failures.
```sh
# Run all tests across Chromium, Firefox and WebKit
$ npx folio --config=config.ts
npx folio
# Run tests on a single browser
$ npx folio --config=config.ts --tag=chromium
npx folio --param browserName=chromium
# Run tests in parallel
$ npx folio --config=config.ts --workers=5
# Run all tests in headful mode
npx folio --param headful
# Run tests sequentially
$ npx folio --config=config.ts --workers=1
# Run tests with slowMo (slows down Playwright operations by n milliseconds)
npx folio --param slowMo=100
# Retry failing tests
$ npx folio --config=config.ts --retries=2
# Save screenshots on failure in test-results directory
npx folio --param screenshotOnFailure
# Record videos
npx folio --param video
# Retry test failures
npx folio --retries 3
# See all options
$ npx folio --help
npx folio --help
```
Refer to the [command line documentation][folio-cli] for all options.
Test runner CLI can be customized with [Folio parameters][folio-parameters].

@@ -113,3 +115,3 @@ #### Configure NPM scripts

"scripts": {
"test": "npx folio --config=config.ts"
"test": "npx folio --param screenshotOnFailure"
}

@@ -119,26 +121,2 @@ }

### Tests and assertions syntax
- Use `test` to write test functions. Run a single test with `test.only` and skip a test with `test.skip`.
- Use `test.describe` to group related tests together.
- Use `test.beforeAll` and `test.afterAll` hooks to set up and tear down resources shared between tests.
- Use `test.beforeEach` and `test.afterEach` hooks to set up and tear down resources for each test individually.
- For assertions, use the [`expect` API](https://jestjs.io/docs/expect).
```js
const { test, expect } = require("@playwright/test");
test.describe("feature foo", () => {
test.beforeEach(async ({ page }) => {
// Go to the starting url before each test.
await page.goto("https://my.start.url/feature-foo");
});
test("is working correctly", async ({ page }) => {
// Assertions use the expect API.
expect(page.url()).toBe("https://my.start.url/feature-foo");
});
});
```
-----------

@@ -153,5 +131,5 @@

```js
import { test } from "@playwright/test";
import { it } from "@playwright/test";
test("tests on multiple web pages", async ({ context }) => {
it("tests on multiple web pages", async ({ context }) => {
const pageFoo = await context.newPage();

@@ -165,24 +143,20 @@ const pageBar = await context.newPage();

`options` in the configuration file can be used to configure mobile emulation in the default `context`.
The `contextOptions` fixture defines default options used for context creation. This fixture can be overriden to configure mobile emulation in the default `context`.
```diff
// config.ts
import { ChromiumEnv, FirefoxEnv, WebKitEnv, test, setConfig } from "@playwright/test";
+ import { devices } from "playwright";
```js
import { folio } from "@playwright/test";
import { devices } from "playwright";
setConfig({
testDir: __dirname, // Search for tests in this directory.
timeout: 30000, // Each test is given 30 seconds.
const fixtures = folio.extend();
fixtures.contextOptions.override(async ({ contextOptions }, runTest) => {
await runTest({
...contextOptions,
...devices["iPhone 11"]
});
});
const { it, describe, extend } = fixtures.build();
const options = {
headless: true, // Run tests in headless browsers.
- viewport: { width: 1280, height: 720 },
+ ...devices["iPhone 11"],
};
// Run tests in three browsers.
test.runWith(new ChromiumEnv(options), { tag: 'chromium' });
test.runWith(new FirefoxEnv(options), { tag: 'firefox' });
test.runWith(new WebKitEnv(options), { tag: 'webkit' });
it("uses mobile emulation", async ({ context }) => {
// Test function
});
```

@@ -192,19 +166,31 @@

Define a custom route that mocks network calls for a browser context.
Define a custom argument that mocks networks call for a browser context.
```js
// In foo.spec.ts
import { test, expect } from "@playwright/test";
// In fixtures.ts
import { folio as base } from "@playwright/test";
import { BrowserContext } from "playwright";
test.beforeEach(async ({ context }) => {
// Block any css requests for each test in this file.
await context.route(/.css/, route => route.abort());
// Extend base fixtures with a new test-level fixture
const fixtures = base.extend<{ mockedContext: BrowserContext }>();
fixtures.mockedContext.init(async ({ context }, runTest) => {
// Modify existing `context` fixture to add a route
context.route(/.css/, route => route.abort());
// Pass fixture to test functions
runTest(context);
});
test("loads page without css", async ({ page }) => {
// Alternatively, block any png requests just for this test.
await page.route(/.png/, route => route.abort());
export folio = fixtures.build();
```
// Test function code.
```js
// In foo.spec.ts
import { folio } from "./fixtures";
const { it, expect } = folio;
it("loads pages without css requests", async ({ mockedContext }) => {
const page = await mockedContext.newPage();
await page.goto("https://stackoverflow.com");
// Test function code
});

@@ -218,8 +204,8 @@ ```

```js
import { test, expect } from "@playwright/test";
import { it, expect } from "@playwright/test";
test("compares page screenshot", async ({ page }) => {
it("compares page screenshot", async ({ page, browserName }) => {
await page.goto("https://stackoverflow.com");
const screenshot = await page.screenshot();
expect(screenshot).toMatchSnapshot(`test.png`, { threshold: 0.2 });
expect(screenshot).toMatchSnapshot(`test-${browserName}.png`, { threshold: 0.2 });
});

@@ -239,108 +225,152 @@ ```

### Modify options
### Modify context options
You can modify browser launch options, context creation options and testing options in the configuration file.
You can modify the built-in fixtures. This example modifies the default `contextOptions` with a custom viewport size.
**Step 1**: Create a new file (say `test/fixtures.ts`) which contains our modifications.
```ts
// test/fixtures.ts
import { folio as baseFolio } from "@playwright/test";
const builder = baseFolio.extend();
// Fixture modifications go here
const folio = builder.build();
```
**Step 2**: Override the existing `contextOptions` fixture to configure viewport size and HTTPS error handling.
```diff
// config.ts
import { ChromiumEnv, FirefoxEnv, WebKitEnv, test, setConfig } from "@playwright/test";
// test/fixtures.ts
import { folio as baseFolio } from "@playwright/test";
+ import { BrowserContextOptions } from "playwright";
setConfig({
testDir: __dirname, // Search for tests in this directory.
- timeout: 30000, // Each test is given 30 seconds.
+ timeout: 90000, // Each test is given 90 seconds.
+ retries: 2, // Failing tests will be retried at most two times.
const builder = baseFolio.extend();
+ builder.contextOptions.override(async ({ contextOptions }, runTest) => {
+ const modifiedOptions: BrowserContextOptions = {
+ ...contextOptions, // default options
+ viewport: { width: 1440, height: 900 },
+ ignoreHTTPSErrors: true
+ }
+ await runTest(modifiedOptions);
+ });
const folio = builder.build();
```
**Step 3**: Export `it` and other helpers from the modified fixtures. In your test files, import the modified fixture.
```diff
// test/fixtures.ts
import { folio as baseFolio } from "@playwright/test";
import { BrowserContextOptions } from "playwright";
const builder = baseFolio.extend();
builder.contextOptions.override(async ({ contextOptions }, runTest) => {
const modifiedOptions: BrowserContextOptions = {
...contextOptions, // default options
viewport: { width: 1440, height: 900 }
ignoreHTTPSErrors: true
}
await runTest(modifiedOptions);
});
const options = {
- headless: true, // Run tests in headless browsers.
- viewport: { width: 1280, height: 720 },
+ // Launch options:
+ headless: false,
+ slowMo: 50,
+ // Context options:
+ viewport: { width: 800, height: 600 },
+ ignoreHTTPSErrors: true,
+ // Testing options:
+ video: 'retain-on-failure',
};
const folio = builder.build();
// Run tests in three browsers.
test.runWith(new ChromiumEnv(options), { tag: 'chromium' });
test.runWith(new FirefoxEnv(options), { tag: 'firefox' });
test.runWith(new WebKitEnv(options), { tag: 'webkit' });
+ export const it = folio.it;
+ export const expect = folio.expect;
```
See the full list of launch options in [`browserType.launch()`](https://playwright.dev/docs/api/class-browsertype#browsertypelaunchoptions) documentation.
```ts
// test/index.spec.ts
import { it, expect } from "./fixtures";
See the full list of context options in [`browser.newContext()`](https://playwright.dev/docs/api/class-browser#browsernewcontextoptions) documentation.
// Test functions go here
it("should have modified viewport", async ({ context }) => {
// ...
});
```
Available testing options:
- `screenshot: 'off' | 'on' | 'only-on-failure'` - Whether to capture a screenshot after each test, off by default.
- `off` - Do not capture screenshots.
- `on` - Capture screenshot after each test.
- `only-on-failure` - Capture screenshot after each test failure.
- `video: 'off' | 'on' | 'retain-on-failure' | 'retry-with-video'` - Whether to record video for each test, off by default.
- `off` - Do not record video.
- `on` - Record video for each test.
- `retain-on-failure` - Record video for each test, but remove all videos from successful test runs.
- `retry-with-video` - Record video only when retrying a test.
### Modify launch options
Most notable `setConfig` options, see the full list in [Folio documentation](https://github.com/microsoft/folio):
- `retries: number` - Each failing test will be retried up to the certain number of times.
- `testDir: string` - Directory where test runner should search for test files.
- `timeout: number` - Timeout in milliseconds for each test.
- `workers: number` - The maximum number of worker processes to run in parallel.
You can modify the built-in fixtures. This example modifies the default `browserOptions` with a slowMo.
#### Browser-specific options
**Step 1**: Create a new file (say `test/fixtures.ts`) which contains our modifications.
You can specify different options for each browser when creating a corresponding environment.
```ts
// test/fixtures.ts
import { folio as baseFolio } from "@playwright/test";
const builder = baseFolio.extend();
// Fixture modifications go here
const folio = builder.build();
```
**Step 2**: Override the existing `browserOptions` fixture to configure the slowMo.
```diff
// config.ts
import { ChromiumEnv, FirefoxEnv, WebKitEnv, test, setConfig } from "@playwright/test";
// test/fixtures.ts
import { folio as baseFolio } from "@playwright/test";
+ import { LaunchOptions } from "playwright";
setConfig({
testDir: __dirname, // Search for tests in this directory.
timeout: 30000, // Each test is given 30 seconds.
});
const builder = baseFolio.extend();
const options = {
headless: true, // Run tests in headless browsers.
viewport: { width: 1280, height: 720 },
};
+ builder.browserOptions.override(async ({ browserOptions }, runTest) => {
+ const modifiedOptions: LaunchOptions = {
+ ...browserOptions, // Default options
+ slowMo: 50,
+ }
+ await runTest(modifiedOptions);
+ });
// Run tests in three browsers.
test.runWith(new ChromiumEnv(options), { tag: 'chromium' });
test.runWith(new FirefoxEnv(options), { tag: 'firefox' });
- test.runWith(new WebKitEnv(options), { tag: 'webkit' });
+ test.runWith(new WebKitEnv({
+ ...options,
+ viewport: { width: 800, height: 600 }, // Use different viewport for WebKit.
+ }), { tag: 'webkit' });
const folio = builder.build();
```
### Skip tests with annotations
**Step 3**: Export `it` and other helpers from the modified fixtures. In your test files, import the modified fixture.
The Playwright test runner can annotate tests to skip under certain parameters. This is enabled by [Folio annotations][folio-annotations].
```diff
// test/fixtures.ts
import { folio as baseFolio } from "@playwright/test";
import { LaunchOptions } from "playwright";
```js
test("should be skipped on firefox", async ({ page, browserName }) => {
test.skip(browserName === "firefox", "optional description for the skip");
// Test function
const builder = baseFolio.extend();
builder.browserOptions.override(async ({ browserOptions }, runTest) => {
const modifiedOptions: LaunchOptions = {
...browserOptions, // default
slowMo: 50,
}
await runTest(modifiedOptions);
});
const folio = builder.build();
+ export const it = folio.it;
+ export const expect = folio.expect;
```
### Modify context options for a single test
```ts
// test/index.spec.ts
import { it, expect } from "./fixtures";
Pass a second parameter that has `contextOptions` property to the `test` function:
// Test functions go here
it("should have the slow mo", async ({ context }) => {
// ...
});
```
### Skip tests with annotations
The Playwright test runner can annotate tests to skip under certain parameters. This is enabled by [Folio annotations][folio-annotations].
```js
const options = {
contextOptions: {
ignoreHTTPSErrors: true,
}
};
test("no https errors in this test", options, async ({ page }) => {
it("should be skipped on firefox", (test, { browserName }) => {
test.skip(browserName === "firefox", "optional description for the skip")
}, async ({ page, browserName }) => {
// Test function

@@ -354,30 +384,18 @@ });

```diff
// config.ts
import { ChromiumEnv, FirefoxEnv, WebKitEnv, test, setConfig } from "@playwright/test";
+ import { reporters, setReporters } from "@playwright/test";
```sh
# Specify output file as an environment variable
# Linux/macOS
export FOLIO_JUNIT_OUTPUT_NAME=junit.xml
# Windows
set FOLIO_JUNIT_OUTPUT_NAME=junit.xml
setConfig({
testDir: __dirname, // Search for tests in this directory.
timeout: 30000, // Each test is given 30 seconds.
});
# Use junit and CLI reporters
npx folio --reporter=junit,line
+ setReporters([
+ // Report to the terminal with "line" reporter.
+ new reporters.line(),
+ // Additionally, output a JUnit XML file.
+ new reporters.junit({ outputFile: 'junit.xml' }),
+ ]);
const options = {
headless: true, // Run tests in headless browsers.
viewport: { width: 1280, height: 720 },
};
// Run tests in three browsers.
test.runWith(new ChromiumEnv(options), { tag: 'chromium' });
test.runWith(new FirefoxEnv(options), { tag: 'firefox' });
test.runWith(new WebKitEnv(options), { tag: 'webkit' });
# See all supported reporters
npx folio --help
```
[browser-opts]: https://playwright.dev/docs/api/class-browsertype#browsertypelaunchoptions
[context-opts]: https://playwright.dev/docs/api/class-browser#browsernewcontextoptions
[multi-page]: https://playwright.dev/docs/multi-pages

@@ -388,2 +406,2 @@ [browser]: https://playwright.dev/docs/api/class-browser

[folio-annotations]: https://github.com/microsoft/folio#annotations
[folio-cli]: https://github.com/microsoft/folio#command-line
[folio-parameters]: https://github.com/microsoft/folio#parameters
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc