Now that the patch has been cherry-picked to the release branch
reverting it on main.
This reverts commit 6deba5dc21
.
This commit is contained in:
Родитель
7c65b5d1f5
Коммит
05fb3e6de8
|
@ -0,0 +1,36 @@
|
|||
# class: Storage
|
||||
* since: v1.28
|
||||
* langs: js
|
||||
|
||||
Playwright Test provides a [`method: TestInfo.storage`] object for passing values between project setup and tests.
|
||||
TODO: examples
|
||||
|
||||
## async method: Storage.get
|
||||
* since: v1.28
|
||||
- returns: <[any]>
|
||||
|
||||
Get named item from the storage. Returns undefined if there is no value with given name.
|
||||
|
||||
### param: Storage.get.name
|
||||
* since: v1.28
|
||||
- `name` <[string]>
|
||||
|
||||
Item name.
|
||||
|
||||
## async method: Storage.set
|
||||
* since: v1.28
|
||||
|
||||
Set value to the storage.
|
||||
|
||||
### param: Storage.set.name
|
||||
* since: v1.28
|
||||
- `name` <[string]>
|
||||
|
||||
Item name.
|
||||
|
||||
### param: Storage.set.value
|
||||
* since: v1.28
|
||||
- `value` <[any]>
|
||||
|
||||
Item value. The value must be serializable to JSON. Passing `undefined` deletes the entry with given name.
|
||||
|
|
@ -505,6 +505,12 @@ Output written to `process.stderr` or `console.error` during the test execution.
|
|||
|
||||
Output written to `process.stdout` or `console.log` during the test execution.
|
||||
|
||||
## method: TestInfo.storage
|
||||
* since: v1.28
|
||||
- returns: <[Storage]>
|
||||
|
||||
Returns a [Storage] instance for the currently running project.
|
||||
|
||||
## property: TestInfo.timeout
|
||||
* since: v1.10
|
||||
- type: <[int]>
|
||||
|
|
|
@ -202,6 +202,14 @@ Learn more about [automatic screenshots](../test-configuration.md#automatic-scre
|
|||
## property: TestOptions.storageState = %%-js-python-context-option-storage-state-%%
|
||||
* since: v1.10
|
||||
|
||||
## property: TestOptions.storageStateName
|
||||
* since: v1.28
|
||||
- type: <[string]>
|
||||
|
||||
Name of the [Storage] entry that should be used to initialize [`property: TestOptions.storageState`]. The value must be
|
||||
written to the storage before creatiion of a browser context that uses it (usually in [`property: TestProject.setup`]). If both
|
||||
this property and [`property: TestOptions.storageState`] are specified, this property will always take precedence.
|
||||
|
||||
## property: TestOptions.testIdAttribute
|
||||
* since: v1.27
|
||||
|
||||
|
|
|
@ -162,6 +162,12 @@ Metadata that will be put directly to the test report serialized as JSON.
|
|||
|
||||
Project name is visible in the report and during test execution.
|
||||
|
||||
## property: TestProject.setup
|
||||
* since: v1.28
|
||||
- type: ?<[string]|[RegExp]|[Array]<[string]|[RegExp]>>
|
||||
|
||||
Project setup files that would be executed before all tests in the project. If project setup fails the tests in this project will be skipped. All project setup files will run in every shard if the project is sharded.
|
||||
|
||||
## property: TestProject.snapshotDir
|
||||
* since: v1.10
|
||||
- type: ?<[string]>
|
||||
|
|
|
@ -49,7 +49,6 @@ type TestFixtures = PlaywrightTestArgs & PlaywrightTestOptions & {
|
|||
};
|
||||
type WorkerFixtures = PlaywrightWorkerArgs & PlaywrightWorkerOptions & {
|
||||
_browserOptions: LaunchOptions;
|
||||
_storageStateName: string | undefined;
|
||||
_artifactsDir: () => string;
|
||||
_snapshotSuffix: string;
|
||||
};
|
||||
|
@ -152,7 +151,7 @@ export const test = _baseTest.extend<TestFixtures, WorkerFixtures>({
|
|||
permissions: [({ contextOptions }, use) => use(contextOptions.permissions), { option: true }],
|
||||
proxy: [({ contextOptions }, use) => use(contextOptions.proxy), { option: true }],
|
||||
storageState: [({ contextOptions }, use) => use(contextOptions.storageState), { option: true }],
|
||||
_storageStateName: [undefined, { option: true, scope: 'worker' }],
|
||||
storageStateName: [undefined, { option: true }],
|
||||
timezoneId: [({ contextOptions }, use) => use(contextOptions.timezoneId), { option: true }],
|
||||
userAgent: [({ contextOptions }, use) => use(contextOptions.userAgent), { option: true }],
|
||||
viewport: [({ contextOptions }, use) => use(contextOptions.viewport === undefined ? { width: 1280, height: 720 } : contextOptions.viewport), { option: true }],
|
||||
|
@ -182,7 +181,7 @@ export const test = _baseTest.extend<TestFixtures, WorkerFixtures>({
|
|||
permissions,
|
||||
proxy,
|
||||
storageState,
|
||||
_storageStateName,
|
||||
storageStateName,
|
||||
viewport,
|
||||
timezoneId,
|
||||
userAgent,
|
||||
|
@ -221,10 +220,10 @@ export const test = _baseTest.extend<TestFixtures, WorkerFixtures>({
|
|||
options.permissions = permissions;
|
||||
if (proxy !== undefined)
|
||||
options.proxy = proxy;
|
||||
if (_storageStateName !== undefined) {
|
||||
const value = await (test.info() as TestInfoImpl)._storage().get(_storageStateName);
|
||||
if (storageStateName !== undefined) {
|
||||
const value = await test.info().storage().get(storageStateName);
|
||||
if (!value)
|
||||
throw new Error(`Cannot find value in the storage for storageStateName: "${_storageStateName}"`);
|
||||
throw new Error(`Cannot find value in the storage for storageStateName: "${storageStateName}"`);
|
||||
options.storageState = value as any;
|
||||
} else if (storageState !== undefined) {
|
||||
options.storageState = storageState;
|
||||
|
|
|
@ -274,7 +274,7 @@ export class Loader {
|
|||
const outputDir = takeFirst(projectConfig.outputDir, config.outputDir, path.join(throwawayArtifactsPath, 'test-results'));
|
||||
const snapshotDir = takeFirst(projectConfig.snapshotDir, config.snapshotDir, testDir);
|
||||
const name = takeFirst(projectConfig.name, config.name, '');
|
||||
const _setup = takeFirst((projectConfig as any)._setup, []);
|
||||
const _setup = takeFirst(projectConfig.setup, []);
|
||||
|
||||
const defaultSnapshotPathTemplate = '{snapshotDir}/{testFileDir}/{testFileName}-snapshots/{arg}{-projectName}{-snapshotSuffix}{ext}';
|
||||
const snapshotPathTemplate = takeFirst(projectConfig.snapshotPathTemplate, config.snapshotPathTemplate, defaultSnapshotPathTemplate);
|
||||
|
@ -614,7 +614,7 @@ function validateProject(file: string, project: Project, title: string) {
|
|||
throw errorWithFile(file, `${title}.testDir must be a string`);
|
||||
}
|
||||
|
||||
for (const prop of ['testIgnore', 'testMatch'] as const) {
|
||||
for (const prop of ['testIgnore', 'testMatch', 'setup'] as const) {
|
||||
if (prop in project && project[prop] !== undefined) {
|
||||
const value = project[prop];
|
||||
if (Array.isArray(value)) {
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { monotonicTime } from 'playwright-core/lib/utils';
|
||||
import type { TestError, TestInfo, TestStatus } from '../types/test';
|
||||
import type { Storage, TestError, TestInfo, TestStatus } from '../types/test';
|
||||
import type { WorkerInitParams } from './ipc';
|
||||
import type { Loader } from './loader';
|
||||
import type { TestCase } from './test';
|
||||
|
@ -60,7 +60,7 @@ export class TestInfoImpl implements TestInfo {
|
|||
readonly snapshotDir: string;
|
||||
errors: TestError[] = [];
|
||||
currentStep: TestStepInternal | undefined;
|
||||
private readonly _testStorage: JsonStorage;
|
||||
private readonly _storage: JsonStorage;
|
||||
|
||||
get error(): TestError | undefined {
|
||||
return this.errors[0];
|
||||
|
@ -108,7 +108,7 @@ export class TestInfoImpl implements TestInfo {
|
|||
this.expectedStatus = test.expectedStatus;
|
||||
|
||||
this._timeoutManager = new TimeoutManager(this.project.timeout);
|
||||
this._testStorage = new JsonStorage(this);
|
||||
this._storage = new JsonStorage(this);
|
||||
|
||||
this.outputDir = (() => {
|
||||
const relativeTestFilePath = path.relative(this.project.testDir, test._requireFile.replace(/\.(spec|test)\.(js|ts|mjs)$/, ''));
|
||||
|
@ -281,12 +281,12 @@ export class TestInfoImpl implements TestInfo {
|
|||
this._timeoutManager.setTimeout(timeout);
|
||||
}
|
||||
|
||||
_storage() {
|
||||
return this._testStorage;
|
||||
storage() {
|
||||
return this._storage;
|
||||
}
|
||||
}
|
||||
|
||||
class JsonStorage {
|
||||
class JsonStorage implements Storage {
|
||||
constructor(private _testInfo: TestInfoImpl) {
|
||||
}
|
||||
|
||||
|
|
|
@ -1849,6 +1849,11 @@ export interface TestInfo {
|
|||
*/
|
||||
stdout: Array<string|Buffer>;
|
||||
|
||||
/**
|
||||
* Returns a [Storage] instance for the currently running project.
|
||||
*/
|
||||
storage(): Storage;
|
||||
|
||||
/**
|
||||
* Timeout in milliseconds for the currently running test. Zero means no timeout. Learn more about
|
||||
* [various timeouts](https://playwright.dev/docs/test-timeouts).
|
||||
|
@ -2777,6 +2782,24 @@ type ConnectOptions = {
|
|||
timeout?: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* Playwright Test provides a [testInfo.storage()](https://playwright.dev/docs/api/class-testinfo#test-info-storage) object
|
||||
* for passing values between project setup and tests. TODO: examples
|
||||
*/
|
||||
export interface Storage {
|
||||
/**
|
||||
* Get named item from the storage. Returns undefined if there is no value with given name.
|
||||
* @param name Item name.
|
||||
*/
|
||||
get<T>(name: string): Promise<T | undefined>;
|
||||
/**
|
||||
* Set value to the storage.
|
||||
* @param name Item name.
|
||||
* @param value Item value. The value must be serializable to JSON. Passing `undefined` deletes the entry with given name.
|
||||
*/
|
||||
set<T>(name: string, value: T | undefined): Promise<void>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Playwright Test provides many options to configure test environment, [Browser], [BrowserContext] and more.
|
||||
*
|
||||
|
@ -3011,6 +3034,15 @@ export interface PlaywrightTestOptions {
|
|||
* Either a path to the file with saved storage, or an object with the following fields:
|
||||
*/
|
||||
storageState: StorageState | undefined;
|
||||
/**
|
||||
* Name of the [Storage] entry that should be used to initialize
|
||||
* [testOptions.storageState](https://playwright.dev/docs/api/class-testoptions#test-options-storage-state). The value must
|
||||
* be written to the storage before creatiion of a browser context that uses it (usually in
|
||||
* [testProject.setup](https://playwright.dev/docs/api/class-testproject#test-project-setup)). If both this property and
|
||||
* [testOptions.storageState](https://playwright.dev/docs/api/class-testoptions#test-options-storage-state) are specified,
|
||||
* this property will always take precedence.
|
||||
*/
|
||||
storageStateName: string | undefined;
|
||||
/**
|
||||
* Changes the timezone of the context. See
|
||||
* [ICU's metaZones.txt](https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt?rcl=faee8bc70570192d82d2978a71e2a615788597d1)
|
||||
|
@ -4523,6 +4555,12 @@ interface TestProject {
|
|||
*/
|
||||
name?: string;
|
||||
|
||||
/**
|
||||
* Project setup files that would be executed before all tests in the project. If project setup fails the tests in this
|
||||
* project will be skipped. All project setup files will run in every shard if the project is sharded.
|
||||
*/
|
||||
setup?: string|RegExp|Array<string|RegExp>;
|
||||
|
||||
/**
|
||||
* The base directory, relative to the config file, for snapshot files created with `toMatchSnapshot`. Defaults to
|
||||
* [testProject.testDir](https://playwright.dev/docs/api/class-testproject#test-project-test-dir).
|
||||
|
|
|
@ -480,3 +480,41 @@ test('should have correct types for the config', async ({ runTSC }) => {
|
|||
});
|
||||
expect(result.exitCode).toBe(0);
|
||||
});
|
||||
|
||||
test('should throw when project.setup has wrong type', async ({ runInlineTest }) => {
|
||||
const result = await runInlineTest({
|
||||
'playwright.config.ts': `
|
||||
module.exports = {
|
||||
projects: [
|
||||
{ name: 'a', setup: 100 },
|
||||
],
|
||||
};
|
||||
`,
|
||||
'a.test.ts': `
|
||||
const { test } = pwt;
|
||||
test('pass', async () => {});
|
||||
`
|
||||
});
|
||||
|
||||
expect(result.exitCode).toBe(1);
|
||||
expect(result.output).toContain(`Error: playwright.config.ts: config.projects[0].setup must be a string or a RegExp`);
|
||||
});
|
||||
|
||||
test('should throw when project.setup has wrong array type', async ({ runInlineTest }) => {
|
||||
const result = await runInlineTest({
|
||||
'playwright.config.ts': `
|
||||
module.exports = {
|
||||
projects: [
|
||||
{ name: 'a', setup: [/100/, 100] },
|
||||
],
|
||||
};
|
||||
`,
|
||||
'a.test.ts': `
|
||||
const { test } = pwt;
|
||||
test('pass', async () => {});
|
||||
`
|
||||
});
|
||||
|
||||
expect(result.exitCode).toBe(1);
|
||||
expect(result.output).toContain(`Error: playwright.config.ts: config.projects[0].setup[1] must be a string or a RegExp`);
|
||||
});
|
||||
|
|
|
@ -98,7 +98,7 @@ function expectFilesRunBefore(timeline: Timeline, before: string[], after: strin
|
|||
test('should work for one project', async ({ runGroups }, testInfo) => {
|
||||
const projectTemplates = {
|
||||
'a': {
|
||||
_setup: ['**/*.setup.ts']
|
||||
setup: ['**/*.setup.ts']
|
||||
},
|
||||
};
|
||||
const configWithFiles = createConfigWithProjects(['a'], testInfo, projectTemplates);
|
||||
|
@ -114,13 +114,13 @@ a > a${path.sep}a.spec.ts > a test [end]`);
|
|||
test('should work for several projects', async ({ runGroups }, testInfo) => {
|
||||
const projectTemplates = {
|
||||
'a': {
|
||||
_setup: ['**/*.setup.ts']
|
||||
setup: ['**/*.setup.ts']
|
||||
},
|
||||
'b': {
|
||||
_setup: /.*b.setup.ts/
|
||||
setup: /.*b.setup.ts/
|
||||
},
|
||||
'c': {
|
||||
_setup: '**/c.setup.ts'
|
||||
setup: '**/c.setup.ts'
|
||||
},
|
||||
};
|
||||
const configWithFiles = createConfigWithProjects(['a', 'b', 'c'], testInfo, projectTemplates);
|
||||
|
@ -134,10 +134,10 @@ test('should work for several projects', async ({ runGroups }, testInfo) => {
|
|||
test('should stop project if setup fails', async ({ runGroups }, testInfo) => {
|
||||
const projectTemplates = {
|
||||
'a': {
|
||||
_setup: ['**/*.setup.ts']
|
||||
setup: ['**/*.setup.ts']
|
||||
},
|
||||
'b': {
|
||||
_setup: /.*b.setup.ts/
|
||||
setup: /.*b.setup.ts/
|
||||
},
|
||||
};
|
||||
const configWithFiles = createConfigWithProjects(['a', 'b', 'c'], testInfo, projectTemplates);
|
||||
|
@ -162,7 +162,7 @@ test('should run setup in each project shard', async ({ runGroups }, testInfo) =
|
|||
projects: [
|
||||
{
|
||||
name: 'p1',
|
||||
_setup: /.*.setup.ts/,
|
||||
setup: /.*.setup.ts/,
|
||||
},
|
||||
]
|
||||
};`,
|
||||
|
@ -210,12 +210,12 @@ test('should run setup only for projects that have tests in the shard', async ({
|
|||
projects: [
|
||||
{
|
||||
name: 'p1',
|
||||
_setup: /.*p1.setup.ts$/,
|
||||
setup: /.*p1.setup.ts$/,
|
||||
testMatch: /.*a.test.ts/,
|
||||
},
|
||||
{
|
||||
name: 'p2',
|
||||
_setup: /.*p2.setup.ts$/,
|
||||
setup: /.*p2.setup.ts$/,
|
||||
testMatch: /.*b.test.ts/,
|
||||
},
|
||||
]
|
||||
|
@ -265,10 +265,10 @@ test('should run setup only for projects that have tests in the shard', async ({
|
|||
test('--project only runs setup from that project;', async ({ runGroups }, testInfo) => {
|
||||
const projectTemplates = {
|
||||
'a': {
|
||||
_setup: /.*a.setup.ts/
|
||||
setup: /.*a.setup.ts/
|
||||
},
|
||||
'b': {
|
||||
_setup: /.*b.setup.ts/
|
||||
setup: /.*b.setup.ts/
|
||||
},
|
||||
};
|
||||
const configWithFiles = createConfigWithProjects(['a', 'b', 'c'], testInfo, projectTemplates);
|
||||
|
@ -285,7 +285,7 @@ test('same file cannot be a setup and a test in the same project', async ({ runG
|
|||
projects: [
|
||||
{
|
||||
name: 'p1',
|
||||
_setup: /.*a.test.ts$/,
|
||||
setup: /.*a.test.ts$/,
|
||||
testMatch: /.*a.test.ts$/,
|
||||
},
|
||||
]
|
||||
|
@ -308,12 +308,12 @@ test('same file cannot be a setup and a test in different projects', async ({ ru
|
|||
projects: [
|
||||
{
|
||||
name: 'p1',
|
||||
_setup: /.*a.test.ts$/,
|
||||
setup: /.*a.test.ts$/,
|
||||
testMatch: /.*noMatch.test.ts$/,
|
||||
},
|
||||
{
|
||||
name: 'p2',
|
||||
_setup: /.*noMatch.test.ts$/,
|
||||
setup: /.*noMatch.test.ts$/,
|
||||
testMatch: /.*a.test.ts$/
|
||||
},
|
||||
]
|
||||
|
|
|
@ -24,14 +24,14 @@ test('should provide storage fixture', async ({ runInlineTest }) => {
|
|||
'a.test.ts': `
|
||||
const { test } = pwt;
|
||||
test('should store number', async ({ }) => {
|
||||
const storage = test.info()._storage();
|
||||
const storage = test.info().storage();
|
||||
expect(storage).toBeTruthy();
|
||||
expect(await storage.get('number')).toBe(undefined);
|
||||
await storage.set('number', 2022)
|
||||
expect(await storage.get('number')).toBe(2022);
|
||||
});
|
||||
test('should store object', async ({ }) => {
|
||||
const storage = test.info()._storage();
|
||||
const storage = test.info().storage();
|
||||
expect(storage).toBeTruthy();
|
||||
expect(await storage.get('object')).toBe(undefined);
|
||||
await storage.set('object', { 'a': 2022 })
|
||||
|
@ -50,7 +50,7 @@ test('should share storage state between project setup and tests', async ({ runI
|
|||
projects: [
|
||||
{
|
||||
name: 'p1',
|
||||
_setup: /.*storage.setup.ts/
|
||||
setup: /.*storage.setup.ts/
|
||||
}
|
||||
]
|
||||
};
|
||||
|
@ -58,7 +58,7 @@ test('should share storage state between project setup and tests', async ({ runI
|
|||
'storage.setup.ts': `
|
||||
const { test, expect } = pwt;
|
||||
test('should initialize storage', async ({ }) => {
|
||||
const storage = test.info()._storage();
|
||||
const storage = test.info().storage();
|
||||
expect(await storage.get('number')).toBe(undefined);
|
||||
await storage.set('number', 2022)
|
||||
expect(await storage.get('number')).toBe(2022);
|
||||
|
@ -71,7 +71,7 @@ test('should share storage state between project setup and tests', async ({ runI
|
|||
'a.test.ts': `
|
||||
const { test } = pwt;
|
||||
test('should get data from setup', async ({ }) => {
|
||||
const storage = test.info()._storage();
|
||||
const storage = test.info().storage();
|
||||
expect(await storage.get('number')).toBe(2022);
|
||||
expect(await storage.get('object')).toEqual({ 'a': 2022 });
|
||||
});
|
||||
|
@ -79,7 +79,7 @@ test('should share storage state between project setup and tests', async ({ runI
|
|||
'b.test.ts': `
|
||||
const { test } = pwt;
|
||||
test('should get data from setup', async ({ }) => {
|
||||
const storage = test.info()._storage();
|
||||
const storage = test.info().storage();
|
||||
expect(await storage.get('number')).toBe(2022);
|
||||
expect(await storage.get('object')).toEqual({ 'a': 2022 });
|
||||
});
|
||||
|
@ -97,7 +97,7 @@ test('should persist storage state between project runs', async ({ runInlineTest
|
|||
'a.test.ts': `
|
||||
const { test } = pwt;
|
||||
test('should have no data on first run', async ({ }) => {
|
||||
const storage = test.info()._storage();
|
||||
const storage = test.info().storage();
|
||||
expect(await storage.get('number')).toBe(undefined);
|
||||
await storage.set('number', 2022)
|
||||
expect(await storage.get('object')).toBe(undefined);
|
||||
|
@ -107,7 +107,7 @@ test('should persist storage state between project runs', async ({ runInlineTest
|
|||
'b.test.ts': `
|
||||
const { test } = pwt;
|
||||
test('should get data from previous run', async ({ }) => {
|
||||
const storage = test.info()._storage();
|
||||
const storage = test.info().storage();
|
||||
expect(await storage.get('number')).toBe(2022);
|
||||
expect(await storage.get('object')).toEqual({ 'a': 2022 });
|
||||
});
|
||||
|
@ -132,11 +132,11 @@ test('should isolate storage state between projects', async ({ runInlineTest })
|
|||
projects: [
|
||||
{
|
||||
name: 'p1',
|
||||
_setup: /.*storage.setup.ts/
|
||||
setup: /.*storage.setup.ts/
|
||||
},
|
||||
{
|
||||
name: 'p2',
|
||||
_setup: /.*storage.setup.ts/
|
||||
setup: /.*storage.setup.ts/
|
||||
}
|
||||
]
|
||||
};
|
||||
|
@ -144,7 +144,7 @@ test('should isolate storage state between projects', async ({ runInlineTest })
|
|||
'storage.setup.ts': `
|
||||
const { test, expect } = pwt;
|
||||
test('should initialize storage', async ({ }) => {
|
||||
const storage = test.info()._storage();
|
||||
const storage = test.info().storage();
|
||||
expect(await storage.get('number')).toBe(undefined);
|
||||
await storage.set('number', 2022)
|
||||
expect(await storage.get('number')).toBe(2022);
|
||||
|
@ -157,7 +157,7 @@ test('should isolate storage state between projects', async ({ runInlineTest })
|
|||
'a.test.ts': `
|
||||
const { test } = pwt;
|
||||
test('should get data from setup', async ({ }) => {
|
||||
const storage = test.info()._storage();
|
||||
const storage = test.info().storage();
|
||||
expect(await storage.get('number')).toBe(2022);
|
||||
expect(await storage.get('name')).toBe('str-' + test.info().project.name);
|
||||
});
|
||||
|
@ -165,7 +165,7 @@ test('should isolate storage state between projects', async ({ runInlineTest })
|
|||
'b.test.ts': `
|
||||
const { test } = pwt;
|
||||
test('should get data from setup', async ({ }) => {
|
||||
const storage = test.info()._storage();
|
||||
const storage = test.info().storage();
|
||||
expect(await storage.get('number')).toBe(2022);
|
||||
expect(await storage.get('name')).toBe('str-' + test.info().project.name);
|
||||
});
|
||||
|
@ -186,7 +186,7 @@ test('should load context storageState from storage', async ({ runInlineTest, se
|
|||
projects: [
|
||||
{
|
||||
name: 'p1',
|
||||
_setup: /.*storage.setup.ts/
|
||||
setup: /.*storage.setup.ts/
|
||||
}
|
||||
]
|
||||
};
|
||||
|
@ -194,7 +194,7 @@ test('should load context storageState from storage', async ({ runInlineTest, se
|
|||
'storage.setup.ts': `
|
||||
const { test, expect } = pwt;
|
||||
test('should save storageState', async ({ page, context }) => {
|
||||
const storage = test.info()._storage();
|
||||
const storage = test.info().storage();
|
||||
expect(await storage.get('user')).toBe(undefined);
|
||||
await page.goto('${server.PREFIX}/setcookie.html');
|
||||
const state = await page.context().storageState();
|
||||
|
@ -204,7 +204,7 @@ test('should load context storageState from storage', async ({ runInlineTest, se
|
|||
'a.test.ts': `
|
||||
const { test } = pwt;
|
||||
test.use({
|
||||
_storageStateName: 'user'
|
||||
storageStateName: 'user'
|
||||
})
|
||||
test('should get data from setup', async ({ page }) => {
|
||||
await page.goto('${server.EMPTY_PAGE}');
|
||||
|
@ -225,7 +225,7 @@ test('should load context storageState from storage', async ({ runInlineTest, se
|
|||
expect(result.passed).toBe(3);
|
||||
});
|
||||
|
||||
test('should load _storageStateName specified in the project config from storage', async ({ runInlineTest, server }) => {
|
||||
test('should load storageStateName specified in the project config from storage', async ({ runInlineTest, server }) => {
|
||||
server.setRoute('/setcookie.html', (req, res) => {
|
||||
res.setHeader('Set-Cookie', ['a=v1']);
|
||||
res.end();
|
||||
|
@ -236,9 +236,9 @@ test('should load _storageStateName specified in the project config from storage
|
|||
projects: [
|
||||
{
|
||||
name: 'p1',
|
||||
_setup: /.*storage.setup.ts/,
|
||||
setup: /.*storage.setup.ts/,
|
||||
use: {
|
||||
_storageStateName: 'stateInStorage',
|
||||
storageStateName: 'stateInStorage',
|
||||
},
|
||||
}
|
||||
]
|
||||
|
@ -247,10 +247,10 @@ test('should load _storageStateName specified in the project config from storage
|
|||
'storage.setup.ts': `
|
||||
const { test, expect } = pwt;
|
||||
test.use({
|
||||
_storageStateName: ({}, use) => use(undefined),
|
||||
storageStateName: ({}, use) => use(undefined),
|
||||
})
|
||||
test('should save storageState', async ({ page, context }) => {
|
||||
const storage = test.info()._storage();
|
||||
const storage = test.info().storage();
|
||||
expect(await storage.get('stateInStorage')).toBe(undefined);
|
||||
await page.goto('${server.PREFIX}/setcookie.html');
|
||||
const state = await page.context().storageState();
|
||||
|
@ -270,7 +270,7 @@ test('should load _storageStateName specified in the project config from storage
|
|||
expect(result.passed).toBe(2);
|
||||
});
|
||||
|
||||
test('should load _storageStateName specified in the global config from storage', async ({ runInlineTest, server }) => {
|
||||
test('should load storageStateName specified in the global config from storage', async ({ runInlineTest, server }) => {
|
||||
server.setRoute('/setcookie.html', (req, res) => {
|
||||
res.setHeader('Set-Cookie', ['a=v1']);
|
||||
res.end();
|
||||
|
@ -279,12 +279,12 @@ test('should load _storageStateName specified in the global config from storage'
|
|||
'playwright.config.js': `
|
||||
module.exports = {
|
||||
use: {
|
||||
_storageStateName: 'stateInStorage',
|
||||
storageStateName: 'stateInStorage',
|
||||
},
|
||||
projects: [
|
||||
{
|
||||
name: 'p1',
|
||||
_setup: /.*storage.setup.ts/,
|
||||
setup: /.*storage.setup.ts/,
|
||||
}
|
||||
]
|
||||
};
|
||||
|
@ -292,10 +292,10 @@ test('should load _storageStateName specified in the global config from storage'
|
|||
'storage.setup.ts': `
|
||||
const { test, expect } = pwt;
|
||||
test.use({
|
||||
_storageStateName: ({}, use) => use(undefined),
|
||||
storageStateName: ({}, use) => use(undefined),
|
||||
})
|
||||
test('should save _storageStateName', async ({ page, context }) => {
|
||||
const storage = test.info()._storage();
|
||||
test('should save storageStateName', async ({ page, context }) => {
|
||||
const storage = test.info().storage();
|
||||
expect(await storage.get('stateInStorage')).toBe(undefined);
|
||||
await page.goto('${server.PREFIX}/setcookie.html');
|
||||
const state = await page.context().storageState();
|
||||
|
@ -315,7 +315,7 @@ test('should load _storageStateName specified in the global config from storage'
|
|||
expect(result.passed).toBe(2);
|
||||
});
|
||||
|
||||
test('should throw on unknown _storageStateName value', async ({ runInlineTest, server }) => {
|
||||
test('should throw on unknown storageStateName value', async ({ runInlineTest, server }) => {
|
||||
const result = await runInlineTest({
|
||||
'playwright.config.js': `
|
||||
module.exports = {
|
||||
|
@ -323,7 +323,7 @@ test('should throw on unknown _storageStateName value', async ({ runInlineTest,
|
|||
{
|
||||
name: 'p1',
|
||||
use: {
|
||||
_storageStateName: 'stateInStorage',
|
||||
storageStateName: 'stateInStorage',
|
||||
},
|
||||
}
|
||||
]
|
||||
|
|
|
@ -188,3 +188,18 @@ test('config should allow void/empty options', async ({ runTSC }) => {
|
|||
});
|
||||
expect(result.exitCode).toBe(0);
|
||||
});
|
||||
|
||||
test('should provide storage interface', async ({ runTSC }) => {
|
||||
const result = await runTSC({
|
||||
'a.spec.ts': `
|
||||
const { test } = pwt;
|
||||
test('my test', async () => {
|
||||
await test.info().storage().set('foo', 'bar');
|
||||
const val = await test.info().storage().get('foo');
|
||||
// @ts-expect-error
|
||||
await test.info().storage().unknown();
|
||||
});
|
||||
`
|
||||
});
|
||||
expect(result.exitCode).toBe(0);
|
||||
});
|
||||
|
|
|
@ -196,6 +196,11 @@ type ConnectOptions = {
|
|||
timeout?: number;
|
||||
};
|
||||
|
||||
export interface Storage {
|
||||
get<T>(name: string): Promise<T | undefined>;
|
||||
set<T>(name: string, value: T | undefined): Promise<void>;
|
||||
}
|
||||
|
||||
export interface PlaywrightWorkerOptions {
|
||||
browserName: BrowserName;
|
||||
defaultBrowserType: BrowserName;
|
||||
|
@ -228,6 +233,7 @@ export interface PlaywrightTestOptions {
|
|||
permissions: string[] | undefined;
|
||||
proxy: Proxy | undefined;
|
||||
storageState: StorageState | undefined;
|
||||
storageStateName: string | undefined;
|
||||
timezoneId: string | undefined;
|
||||
userAgent: string | undefined;
|
||||
viewport: ViewportSize | null | undefined;
|
||||
|
|
Загрузка…
Ссылка в новой задаче