playwright-decorators
Version:
Decorators for writing Playwright based tests.
368 lines (363 loc) • 14.2 kB
JavaScript
;
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const __cjsInterop1__ = require("@playwright/test");
const { default: playwright$c = __cjsInterop1__ } = ((_a = __cjsInterop1__ == null ? void 0 : __cjsInterop1__.default) == null ? void 0 : _a.__esModule) ? __cjsInterop1__.default : __cjsInterop1__;
class SuiteDecorator {
constructor(suiteClass, options) {
this.suiteClass = suiteClass;
this.only = false;
this.initializedHooks = [];
this.name = suiteClass.name;
Object.assign(this, options);
}
handleInitializedHooks() {
return Promise.all(this.initializedHooks.map((hookFn) => hookFn()));
}
async runSuite(userSuiteCode) {
this.handleInitializedHooks();
return userSuiteCode();
}
/**
* Run playwright.describe function using all collected data.
*/
run() {
const suiteRunner = this.only ? playwright$c.describe.only : playwright$c.describe;
suiteRunner(this.name, () => this.runSuite(() => new this.suiteClass()));
}
/**
* Declares an `initialized` hook that is executed in `playwright.describe` context, when suite is executed.
* It is equivalent to code: playwright.describe(..., () => { initialized(); ... })
*/
initialized(hookFn) {
this.initializedHooks.push(hookFn);
}
}
function isSuiteDecoratedMethod(method) {
return method.suiteDecorator !== void 0;
}
const suite = (options = {}) => function(constructor, context) {
const suiteDecorator = new SuiteDecorator(constructor, options);
Object.assign(constructor, { suiteDecorator });
context.addInitializer(() => {
suiteDecorator.run();
});
};
const decoratePlaywrightTest = (testFunction, decorationFunction) => {
const decoratedTestFunction = decorationFunction(testFunction);
decoratedTestFunction.toString = () => testFunction.toString();
return decoratedTestFunction;
};
const { default: playwright$b = __cjsInterop1__ } = ((_b = __cjsInterop1__ == null ? void 0 : __cjsInterop1__.default) == null ? void 0 : _b.__esModule) ? __cjsInterop1__.default : __cjsInterop1__;
class TestDecorator {
constructor(testMethod, options) {
this.testMethod = testMethod;
this.only = false;
this.playwright = playwright$b;
this.beforeTestHooks = [];
this.afterTestHooks = [];
this.name = testMethod.name;
Object.assign(this, options);
}
handleBeforeTestHooks() {
return Promise.all(this.beforeTestHooks.map((initializer) => initializer()));
}
handleAfterTestHooks() {
return Promise.all(this.afterTestHooks.map((initializer) => initializer()));
}
/**
* Run playwright.test function using all collected data.
*/
run(executionContext) {
const extendedTestMethod = (testFunction) => async (...args) => {
await this.handleBeforeTestHooks();
await testFunction.call(executionContext, ...args);
await this.handleAfterTestHooks();
};
const testRunner = this.only ? this.playwright.only : this.playwright;
testRunner(this.name, decoratePlaywrightTest(this.testMethod, extendedTestMethod));
}
/**
* Declares an `before` hook that is executed in `playwright()` context just before execution of test code.
* It is equivalent to code: playwright(..., () => { beforeTest(); ... })
*/
beforeTest(initializer) {
this.beforeTestHooks.push(initializer);
}
/**
* Declares an `after` hook that is executed in `playwright()` context just after execution of test code.
* It is equivalent to code: playwright(..., () => { ...; afterTest() })
*/
afterTest(initializer) {
this.afterTestHooks.push(initializer);
}
}
function isTestDecoratedMethod(method) {
return method.testDecorator !== void 0;
}
const test = (options = {}) => function(originalMethod, context) {
const testDecorator = new TestDecorator(originalMethod, options);
Object.assign(originalMethod, { testDecorator });
context.addInitializer(function() {
testDecorator.run(this);
});
};
const { default: playwright$a = __cjsInterop1__ } = ((_c = __cjsInterop1__ == null ? void 0 : __cjsInterop1__.default) == null ? void 0 : _c.__esModule) ? __cjsInterop1__.default : __cjsInterop1__;
const beforeAll = (options) => function(originalMethod, context) {
context.addInitializer(function() {
const decoratedBeforeAll = decoratePlaywrightTest(
originalMethod,
(originalMethod2) => (...args) => originalMethod2.call(this, ...args)
);
const { beforeAll: beforeAll2 } = (options == null ? void 0 : options.playwright) || playwright$a;
beforeAll2(decoratedBeforeAll);
});
};
const { default: playwright$9 = __cjsInterop1__ } = ((_d = __cjsInterop1__ == null ? void 0 : __cjsInterop1__.default) == null ? void 0 : _d.__esModule) ? __cjsInterop1__.default : __cjsInterop1__;
const beforeEach = (options) => function(originalMethod, context) {
context.addInitializer(function() {
const decoratedBeforeEach = decoratePlaywrightTest(
originalMethod,
(originalMethod2) => (...args) => originalMethod2.call(this, ...args)
);
const { beforeEach: beforeEach2 } = (options == null ? void 0 : options.playwright) || playwright$9;
beforeEach2(decoratedBeforeEach);
});
};
const { default: playwright$8 = __cjsInterop1__ } = ((_e = __cjsInterop1__ == null ? void 0 : __cjsInterop1__.default) == null ? void 0 : _e.__esModule) ? __cjsInterop1__.default : __cjsInterop1__;
const afterAll = (options) => function(originalMethod, context) {
context.addInitializer(function() {
const decoratedBeforeAll = decoratePlaywrightTest(
originalMethod,
(originalMethod2) => (...args) => originalMethod2.call(this, ...args)
);
const { afterAll: afterAll2 } = (options == null ? void 0 : options.playwright) || playwright$8;
afterAll2(decoratedBeforeAll);
});
};
const { default: playwright$7 = __cjsInterop1__ } = ((_f = __cjsInterop1__ == null ? void 0 : __cjsInterop1__.default) == null ? void 0 : _f.__esModule) ? __cjsInterop1__.default : __cjsInterop1__;
const afterEach = (options) => function(originalMethod, context) {
context.addInitializer(function() {
const decoratedBeforeEach = decoratePlaywrightTest(
originalMethod,
(originalMethod2) => (...args) => originalMethod2.call(this, ...args)
);
const { afterEach: afterEach2 } = (options == null ? void 0 : options.playwright) || playwright$7;
afterEach2(decoratedBeforeEach);
});
};
class NotSuiteDecoratedMethodError extends Error {
constructor(decoratorName, method) {
super(`
The @${decoratorName} decorator can only be used on class that also have the @suite decorator.
Make sure ${method == null ? void 0 : method.name} is marked with @suite, and that @${decoratorName} comes before @suite, like this:
@${decoratorName}
@suite()
class ${method == null ? void 0 : method.name} {}`);
}
}
class NotTestDecoratedMethodError extends Error {
constructor(decoratorName, method) {
super(`
The @${decoratorName} decorator can only be used on methods that also have the @test decorator.
Make sure ${method == null ? void 0 : method.name} is marked with @test, and that @${decoratorName} comes before @test, like this:
@${decoratorName}
@test()
${method == null ? void 0 : method.name}() {}`);
}
}
class NotSuiteOrTestDecoratedMethodError extends Error {
constructor(decoratorName, method) {
super(`
The @${decoratorName} decorator can only be used on classes with the @suite decorator or methods with the @test decorator.
Make sure ${method == null ? void 0 : method.name} is marked with @suite or @test, and that @${decoratorName} comes before @suite or @test, like this:
for suite:
@${decoratorName}
@suite()
class ${method == null ? void 0 : method.name} {}
for test:
@${decoratorName}
@test()
${method == null ? void 0 : method.name}() {}
`);
}
}
const createSuiteDecorator = (name, suiteDecorator) => {
return function(suiteClass, context) {
if (!isSuiteDecoratedMethod(suiteClass)) {
throw new NotSuiteDecoratedMethodError(name, suiteClass);
}
suiteDecorator({
suite: suiteClass.suiteDecorator,
suiteClass,
context
});
};
};
const createTestDecorator = (name, testDecorator) => {
return function(testMethod, context) {
if (!isTestDecoratedMethod(testMethod)) {
throw new NotTestDecoratedMethodError(name, testMethod);
}
testDecorator({
test: testMethod.testDecorator,
testMethod,
context
});
};
};
const createSuiteAndTestDecorator = (name, suiteDecorator, testDecorator) => {
return function(originalMethod, context) {
if (isSuiteDecoratedMethod(originalMethod)) {
suiteDecorator({
suite: originalMethod.suiteDecorator,
suiteClass: originalMethod,
context
});
return;
}
if (isTestDecoratedMethod(originalMethod)) {
testDecorator({
test: originalMethod.testDecorator,
testMethod: originalMethod,
context
});
return;
}
throw new NotSuiteOrTestDecoratedMethodError(name, originalMethod);
};
};
const { default: playwright$6 = __cjsInterop1__ } = ((_g = __cjsInterop1__ == null ? void 0 : __cjsInterop1__.default) == null ? void 0 : _g.__esModule) ? __cjsInterop1__.default : __cjsInterop1__;
const skip = (reason) => createSuiteAndTestDecorator(
"skip",
({ suite: suite2 }) => {
suite2.initialized(() => playwright$6.skip(true, reason));
},
({ test: test2 }) => {
test2.beforeTest(() => playwright$6.skip(true, reason));
}
);
const { default: playwright$5 = __cjsInterop1__ } = ((_h = __cjsInterop1__ == null ? void 0 : __cjsInterop1__.default) == null ? void 0 : _h.__esModule) ? __cjsInterop1__.default : __cjsInterop1__;
const slow = (reason) => createSuiteAndTestDecorator(
"slow",
({ suite: suite2 }) => {
suite2.initialized(() => playwright$5.slow(true, reason));
},
({ test: test2 }) => {
test2.beforeTest(() => playwright$5.slow(true, reason));
}
);
const { default: playwright$4 = __cjsInterop1__ } = ((_i = __cjsInterop1__ == null ? void 0 : __cjsInterop1__.default) == null ? void 0 : _i.__esModule) ? __cjsInterop1__.default : __cjsInterop1__;
const fail = (reason) => createSuiteAndTestDecorator(
"fail",
({ suite: suite2 }) => {
suite2.initialized(() => playwright$4.fail(true, reason));
},
({ test: test2 }) => {
test2.beforeTest(() => playwright$4.fail(true, reason));
}
);
const { default: playwright$3 = __cjsInterop1__ } = ((_j = __cjsInterop1__ == null ? void 0 : __cjsInterop1__.default) == null ? void 0 : _j.__esModule) ? __cjsInterop1__.default : __cjsInterop1__;
const fixme = (reason) => createSuiteAndTestDecorator(
"fixme",
({ suite: suite2 }) => {
suite2.initialized(() => playwright$3.fixme(true, reason));
},
({ test: test2 }) => {
test2.beforeTest(() => playwright$3.fixme(true, reason));
}
);
const only = () => createSuiteAndTestDecorator(
"only",
({ suite: suite2 }) => {
suite2.only = true;
},
({ test: test2 }) => {
test2.only = true;
}
);
const { default: playwright$2 = __cjsInterop1__ } = ((_k = __cjsInterop1__ == null ? void 0 : __cjsInterop1__.default) == null ? void 0 : _k.__esModule) ? __cjsInterop1__.default : __cjsInterop1__;
const annotation = (options) => createTestDecorator("annotation", ({ test: test2 }) => {
test2.beforeTest(() => {
playwright$2.info().annotations.push(options);
});
});
const tagsAsPlaywrightAnnotations = (tags) => tags.map((tag2) => `@${tag2}`).join(" ");
const tag = (tags) => createSuiteAndTestDecorator(
"tag",
({ suite: suite2 }) => {
suite2.name = `${suite2.name} ${tagsAsPlaywrightAnnotations(tags)}`;
},
({ test: test2 }) => {
test2.name = `${test2.name} ${tagsAsPlaywrightAnnotations(tags)}`;
}
);
const { default: playwright$1 = __cjsInterop1__ } = ((_l = __cjsInterop1__ == null ? void 0 : __cjsInterop1__.default) == null ? void 0 : _l.__esModule) ? __cjsInterop1__.default : __cjsInterop1__;
const retries = (retries2) => createSuiteDecorator("retry", ({ suite: suite2 }) => {
suite2.initialized(() => {
playwright$1.describe.configure({ retries: retries2 });
});
});
const debug = () => createSuiteAndTestDecorator(
"debug",
({ suite: suite2 }) => {
process.env.PWDEBUG = "1";
suite2.only = true;
},
({ test: test2 }) => {
process.env.PWDEBUG = "1";
test2.only = true;
}
);
const { default: playwright = __cjsInterop1__ } = ((_m = __cjsInterop1__ == null ? void 0 : __cjsInterop1__.default) == null ? void 0 : _m.__esModule) ? __cjsInterop1__.default : __cjsInterop1__;
const playwrightPreviewPreset = () => {
playwright.describe.configure({ timeout: 0 });
playwright.use({
// enable headed mode
headless: false,
launchOptions: {
// slow down every operation by 1000ms
slowMo: 1e3
}
});
};
const preview = () => createSuiteAndTestDecorator(
"preview",
({ suite: suite2 }) => {
playwrightPreviewPreset();
suite2.only = true;
},
({ test: test2 }) => {
playwrightPreviewPreset();
test2.only = true;
}
);
const extend = (customPlaywright) => {
return {
afterAll: (...options) => afterAll({ ...options, playwright: customPlaywright }),
afterEach: (...options) => afterEach({ ...options, playwright: customPlaywright }),
test: (...options) => test({ ...options, playwright: customPlaywright }),
beforeAll: (...options) => beforeAll({ ...options, playwright: customPlaywright }),
beforeEach: (...options) => beforeEach({ ...options, playwright: customPlaywright })
};
};
exports.afterAll = afterAll;
exports.afterEach = afterEach;
exports.annotation = annotation;
exports.beforeAll = beforeAll;
exports.beforeEach = beforeEach;
exports.createSuiteAndTestDecorator = createSuiteAndTestDecorator;
exports.createSuiteDecorator = createSuiteDecorator;
exports.createTestDecorator = createTestDecorator;
exports.debug = debug;
exports.extend = extend;
exports.fail = fail;
exports.fixme = fixme;
exports.only = only;
exports.preview = preview;
exports.retries = retries;
exports.skip = skip;
exports.slow = slow;
exports.suite = suite;
exports.tag = tag;
exports.test = test;