TypeScript's decorators for writing Playwright based tests.
npm i playwright-decoratorsDeclare tests using @suite and @test decorators
import { suite, test, slow, tag, TestArgs, TestInfo } from 'playwright-decorators';
@suite() // <-- Decorate class with @suite
class MyTestSuite {
@test() // <-- Decorate test method with @test
async myTest({ page }: TestArgs, testInfo: TestInfo) {
// ...
}
@tag(['team-x'])
@slow('Response from reset password service needs more time')
@test()
async userShouldBeAbleToResetPassword({ page }: TestArgs) {
// ...
}
@withUser({ features: ['payment'] }) // <- Use your own custom decorators
@test()
async userShouldBeAbleToCancelSubscription({ page }: TestArgs) {
// ...
}
}- To view all the available decorators, check the docs section.
- For guidance on creating custom decorators, refer to the custom decorators section.
- Explore additional examples in the examples directory.
- Creating a test suite:
@suite - Creating a test:
@test - Run method before all tests in the suite:
@beforeAll - Run method before each test in the suite:
@beforeEach - Run method after all tests in the suite:
@afterAll - Run method after each test in the suite:
@afterEach - Skip test or suite:
@skip - Mark test or suite as "should fail":
@fail - Mark test or suite as "fixme", with the intention to fix it:
@fixme - Mark test or suite as "slow":
@slow - Run only selected test(s) or suite(s):
@only - Run test(s) or suite(s) with certain tag(s):
@tag - Add custom annotation to test(s):
@annotate - Change or set retries for test(s):
@retries - Run test(s) or suite(s) in debug mode:
@debug - Run test(s) or suite(s) in preview mode:
@preview - Create custom decorator:
createSuiteDecorator,createTestDecorator,createSuiteAndTestDecorator - Using custom fixtures:
extend
Mark class as test suite.
Under the hood, decorator creates a describe block and runs all methods decorated by @test inside it.
import { suite } from 'playwright-decorators';
@suite() // <-- Decorate class with @suite() or @suite(options)
class MyTestSuite {
// ...
}name(optional) - name of the test suite. By default, name of the class.only(optional) - declares focused test suite. If there are some focused @test(s) or @suite(s), all of them will be run but nothing else.
Mark class method as test.
Under the hood, decorator creates a test block and runs the method inside it.
import { suite, test, TestArgs } from 'playwright-decorators';
@suite()
class MyTestSuite {
@test() // <-- Decorate test method with @test() or @test(options)
async myTest({ page }: TestArgs) {
// ...
}
}name(optional) - name of the test. By default, name of the method.only(optional) - declares focused test. If there are some focused @test(s) or @suite(s), all of them will be run but nothing else.playwright(optional) - Custom playwright instance to use instead of standard one. For example, provide result ofplaywright.extend<T>(customFixture)to ensure availability of custom fixture in thetestmethod.
Mark the method as beforeAll book.
import { suite, test, beforeAll, TestArgs } from 'playwright-decorators';
@suite()
class MyTestSuite {
@beforeAll() // <-- Decorate method with @beforeAll()
async beforeAll({ page }: TestArgs) {
// ...
}
}playwright(optional) - Custom playwright instance to use instead of standard one. For example, provide result ofplaywright.extend<T>(customFixture)to ensure availability of custom fixture in thebeforeAllhook.
Mark the method as beforeEach book.
import { suite, test, beforeEach, TestArgs } from 'playwright-decorators';
@suite()
class MyTestSuite {
@beforeEach() // <-- Decorate method with @beforeEach()
async beforeEach({ page }: TestArgs) {
// ...
}
}playwright(optional) - Custom playwright instance to use instead of standard one. For example, provide result ofplaywright.extend<T>(customFixture)to ensure availability of custom fixture in thebeforeEachhook.
Mark the method as afterAll book.
import { suite, test, afterAll, TestArgs } from 'playwright-decorators';
@suite()
class MyTestSuite {
@afterAll() // <-- Decorate method with @afterAll()
async afterAll({ page }: TestArgs) {
// ...
}
}playwright(optional) - Custom playwright instance to use instead of standard one. For example, provide result ofplaywright.extend<T>(customFixture)to ensure availability of custom fixture in theafterAllhook.
Mark the method as afterEach book.
import { suite, test, afterEach, TestArgs } from 'playwright-decorators';
@suite()
class MyTestSuite {
@afterEach() // <-- Decorate method with @afterEach()
async afterEach({ page }: TestArgs) {
// ...
}
}playwright(optional) - Custom playwright instance to use instead of standard one. For example, provide result ofplaywright.extend<T>(customFixture)to ensure availability of custom fixture in theafterEachhook.
Skip single @test or @suite.
import { suite, test, skip, TestArgs } from 'playwright-decorators';
// Skip test suite
@skip() // <-- Decorate suite with @skip()
@suite()
class SkippedTestSuite {
}
// Or skip selected test
@suite()
class MyTestSuite {
@skip() // <-- Decorate test with @skip()
@test()
async skippedTest({ page }: TestArgs) {
// ...
}
}reason(optional) - the reason for skipping. Will be displayed in the test report.
Mark single @test or @suite as "should fail".
Playwright Test runs this test and ensures that it is actually failing.
This is useful for documentation purposes to acknowledge that some functionality is broken until it is fixed.
import { suite, test, fail, TestArgs } from 'playwright-decorators';
// Mark suite as "fail", and ensure that all tests from suite fail
@fail() // <-- Decorate suite with @fail()
@suite()
class FailTestSuite {
}
// Or mark selected test as "fail"
@suite()
class MyTestSuite {
@fail() // <-- Decorate test with @fail()
@test()
async failingTest({ page }: TestArgs) {
// ...
}
}reason(optional) - the reason for marking as "should fail". Will be displayed in the test report.
Marks a @test or @suite as "fixme", with the intention to fix (with optional reason).
Decorated tests or suites will not be run.
import { suite, test, fixme, TestArgs } from 'playwright-decorators';
// Mark test suite as "fixme"
@fixme() // <-- Decorate suite with @fixme()
@suite()
class FixmeTestSuite {
}
// Or mark selected test as "fixme"
@suite()
class MyTestSuite {
@fixme() // <-- Decorate test with @fixme()
@test()
async fixmeTest({ page }: TestArgs) {
// ...
}
}reason(optional) - the reason for marking as "fixme". Will be displayed in the test report.
Mark single @test or @suite as "slow".
Slow test will be given triple the default timeout.
import { suite, test, skip, TestArgs } from 'playwright-decorators';
// Mark test suite as "slow"
@slow() // <-- Decorate suite with @slow()
@suite()
class SlowTestSuite {
}
// Or mark selected test as "slow"
@suite()
class MyTestSuite {
@slow() // <-- Decorate test with @slow()
@test()
async slowTest({ page }: TestArgs) {
// ...
}
}reason(optional) - the reason for marking as "slow". Will be displayed in the test report.
Declares a focused @test or @suite.
If there are some focused tests or suites, all of them will be run but nothing else.
import { suite, test, only, TestArgs } from 'playwright-decorators';
// Run only selected test suite(s)
@only() // <-- Decorate suite with @only()
@suite()
class FocusedTestSuite {
}
// Or run only selected test(s)
@suite()
class TestSuite {
@only() // <-- Decorate test with @only()
@test()
async focusedTest({ page }: TestArgs) {
// ...
}
}Adds tags to @test or @suite.
You can later run test(s) or suite(s) with specific tag, using npx playwright test --grep "@nameOfTag" command.
For example: to run tests/suites with x tag, please run npx playwright test --grep "@x"
import { suite, test, tag, TestArgs } from 'playwright-decorators';
// Run only selected test suite(s)
@tag(['x-api-consumer']) // <-- Decorate suite with @tag()
@suite()
class ApiConsumerTestSuite {
}
// Or run only selected test(s)
@suite()
class TestSuite {
@tag(['x-api-consumer']) // <-- Decorate test with @tag()
@test()
async apiConsumerTest({ page }: TestArgs) {
// ...
}
}To run test(s) or suite(s) for x-api-consumer tag (example above), please type and run the below command:
npx playwright test --grep "@x-api-consumer"tags(required) - array of tags. (Tags should not be prefixed with@sign, as sign will be automatically added to every tag by@tagdecorator).
Add custom annotation to a test.
Annotations are accessible via test.info().annotations. Many reporters show annotations, for example 'html'.
import { suite, test, annotation, TestArgs } from 'playwright-decorators';
@suite()
class MyTestSuite {
@annotation({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/<some-issue>' }) // <-- Decorate test with @annotate()
@test()
async testWithCustomAnnotation({ page }: TestArgs) {
// ...
}
}type(required) - type of annotation, for example 'skip' or 'fail'.description(optional) - description of annotation.
Set the maximum number of retry attempts given to failed @tests in the @suite
import { suite, test, retries } from 'playwright-decorators';
@retries(3) // <-- Decorate suite with @retries()
@suite()
class MyTestSuite {
@test()
async test() { // <- This test may be retried up to 3 times if it fails
// ...
}
}retries(required) - the max number of retries for each test.
Runs a @test(s) or @suite(s) in debug mode.
Tests or suites without the @debug decorator will not be excluded.
Learn more about debug mode: https://playwright.dev/docs/debug
import { suite, test, debug, TestArgs } from 'playwright-decorators';
// Debug selected test suite(s)
@debug() // <-- Decorate suite with @debug()
@suite()
class DebugTestSuite {
}
// Or debug selected test(s)
@suite()
class TestSuite {
@debug() // <-- Decorate test with @debug()
@test()
async test({ page }: TestArgs) {
// ...
}
}Then run playwright tests as usual, i.e. npx playwright test.
For debugging purposes, running tests only on local machine for one project/browser is recommended.
Runs a @test(s) or @suite(s) in preview (headed browser) mode, simulating user interaction (slowing down each operation by 1000ms).
Tests or suites without the @preview decorator will not be excluded.
import { suite, test, preview, TestArgs } from 'playwright-decorators';
// Preview selected test suite(s)
@preview() // <-- Decorate suite with @preview()
@suite()
class PreviewTestSuite {
}
// Or preview selected test(s)
@suite()
class TestSuite {
@preview() // <-- Decorate test with @preview()
@test()
async test({ page }: TestArgs) {
// ...
}
}Then run playwright tests as usual, i.e. npx playwright test.
For preview purposes, running tests only for one project/browser is recommended.
Custom decorators can be created using createTestDecorator and createSuiteDecorator functions.
Simple usage examples are provided below. For more advanced examples, please take a look at example decorators directory.
The createTestDecorator function enables the generation of custom test decorators.
Attempting to utilize a custom test decorator on a method that lacks the @test decoration will result in an error.
import { suite, createTestDecorator } from 'playwright-decorators';
import playwright from '@playwright/test';
const customTestDecorator = createTestDecorator('customTestDecorator', ({ test }) => {
// create code using hooks provided by test decorator...
test.beforeTest(() => { /* ... */ })
test.afterTest(() => { /* ... */ })
// ...or Playwright hooks
playwright.beforeEach(() => {
// ...
})
});Then use it on @test decorator:
@suite()
class MyTestSuite {
@customTestDecorator() // <-- Decorate test with custom decorator
@test()
async myTest({ page }: TestArgs) {
// ...
}
}The createSuiteDecorator function allows the creation of custom suite decorators.
Attempting to apply a custom suite decorator to a class that lacks the @suite decoration will result in an error.
import { suite, createSuiteDecorator } from 'playwright-decorators';
const customSuiteDecorator = createSuiteDecorator('customSuiteDecorator', ({ suite }) => {
// run your custom code immediately
suite.name = 'Custom name';
// or attach to specific hooks...
suite.initialized(() => { /* ... */ })
});Then use it on @suite decorator:
@customSuiteDecorator() // <-- Decorate suite with custom decorator
@suite()
class MyTestSuite {
// ...
}The createSuiteAndTestDecorator function allows the creation of custom decorators that can be applied to both suites and tests.
import {createSuiteAndTestDecorator} from 'playwright-decorators';
const customSuiteAndTestDecorator = createSuiteAndTestDecorator(
'customSuiteAndTestDecorator',
({ suite }) => {
// custom suite decorator code
},
({ test }) => {
// custom test decorator code
}
)If you are not familiar with concept of fixtures in Playwright, please read this article first.
The extend<T>(customFixture) method generates decorators with access to custom fixture.
The following example illustrates how to create decorators with access to user fixture:
import { test as base } from 'playwright';
import { suite, test, extend } from 'playwright-decorators';
// #1 Create fixture type
type UserFixture = {
user: {
firstName: string;
lastName: string;
}
}
// #2 Create user fixture
const withUser = base.extend<UserFixture>({
user: async ({}, use) => {
await use({
firstName: 'John',
lastName: 'Doe'
})
}
})
// #3 Generate afterAll, afterEach, test, beforeAll, beforeEach decorators with access to the user fixture
const {
afterAll,
afterEach,
test,
beforeAll,
beforeEach,
} = extend<UserFixture>(withUser);
// #4 Use decorators
@suite()
class MyTestSuite {
@beforeAll()
async beforeAll({ user }: TestArgs<UserFixture>) { // have access to user fixture
// ...
}
@test()
async test({ user }: TestArgs<UserFixture>) { // have access to user fixture
// ...
}
}