Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add @fail decorator #18

Merged
merged 1 commit into from
Jul 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class MyTestSuite {
#### Options
- `name` (optional) - name of the test suite. By default, name of the class.


### Creating a test: `@test(options?)`
Mark class method as test.
Under the hood, decorator creates a `test` block and runs the method inside it.
Expand All @@ -59,6 +60,7 @@ class MyTestSuite {
#### Options
- `name` (optional) - name of the test. By default, name of the method.


### Run method before all test in the suite: `@beforeAll()`
Mark method as `beforeAll` book.

Expand All @@ -74,6 +76,7 @@ class MyTestSuite {
}
```


### Run method before each test in the suite: `@beforeEach()`
Mark method as `beforeEach` book.

Expand All @@ -89,6 +92,7 @@ class MyTestSuite {
}
```


### Run method after all test in the suite: `@afterAll()`
Mark method as `afterAll` book.

Expand All @@ -104,6 +108,7 @@ class MyTestSuite {
}
```


### Run method after each test in the suite: `@afterEach()`
Mark method as `afterEach` book.

Expand All @@ -119,6 +124,7 @@ class MyTestSuite {
}
```


### Skip test or suite: `@skip(reason?: string)`
Skip single `@test` or `@suite`.

Expand All @@ -145,6 +151,29 @@ class MyTestSuite {
#### Options
- `reason` (optional) - reason of skipping. Will be displayed in the test report.


### Mark test as "should fail": `@fail(reason?: string)`
Mark single `@test` 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.

```ts
import { suite, test, fail } from 'playwright-decorators';

@suite()
class MyTestSuite {
@fail() // <-- Decorate test with @fail()
@test()
async failingTest({ page }) {
// ...
}
}
```

#### Options
- `reason` (optional) - reason of marking as "should fail". Will be displayed in the test report.


### Mark test or suite as "slow": `@slow(reason?: string)`
Mark single `@test` or `@suite` as "slow".
Slow test will be given triple the default timeout.
Expand Down Expand Up @@ -172,6 +201,7 @@ class MyTestSuite {
#### Options
- `reason` (optional) - reason of marking as "slow". Will be displayed in the test report.


### Run only selected test(s) or suite(s): `@only()`
Declares a focused `@test` or `@suite`.
If there are some focused tests or suites, all of them will be run but nothing else.
Expand All @@ -196,6 +226,7 @@ class TestSuite {
}
```


### Run test(s) or suite(s) with certain tag(s): `@tag(tags: string[])`
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.
Expand Down
13 changes: 13 additions & 0 deletions lib/fail.decorator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import {TestDecoratedMethod} from "./test.decorator";

/**
* Marks a @test 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.
*/
export const fail = (reason?: string) => function(originalMethod: any, context?: any) {
if ((originalMethod as TestDecoratedMethod)?.testDecorator) {
originalMethod.testDecorator.fail = reason || true;
return;
}
}
1 change: 1 addition & 0 deletions lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export { afterEach } from './afterEach.decorator';
// annotations
export { skip } from './skip.decorator';
export { slow } from './slow.decorator';
export { fail } from './fail.decorator';
export { only } from './only.decorator';
// helpers
export { tag } from './tag.decorator';
20 changes: 20 additions & 0 deletions lib/test.decorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ interface TestDecoratorOptions {
* Slow test will be given triple the default timeout.
*/
slow?: string | boolean;
/**
* Marks a test 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 fixe
*/
fail?: string | boolean
/**
* Declares a focused test.
* If there are some focused @test(s) or @suite(s), all of them will be run but nothing else.
Expand All @@ -26,6 +32,7 @@ class TestDecorator implements TestDecoratorOptions {
name: string;
skip: string | boolean = false;
slow: string | boolean = false;
fail: string | boolean = false;
only = false;

constructor(private testMethod: any, options: TestDecoratorOptions) {
Expand Down Expand Up @@ -58,13 +65,26 @@ class TestDecorator implements TestDecoratorOptions {
return playwright.slow();
}

private handleFail() {
if (this.fail === false) {
return;
}

if (typeof this.fail === 'string') {
return playwright.fail(true, this.fail);
}

return playwright.fail();
}

/**
* Run playwright.test function using all collected data.
*/
run(executionContext: any) {
const decoratedTest: TestDecoratorFunction = (testFunction) => (...args) => {
this.handleSkip();
this.handleSlow();
this.handleFail();

// set correct executionContext (test class)
return testFunction.call(executionContext, ...args);
Expand Down
23 changes: 23 additions & 0 deletions tests/fail.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import playwright, {expect} from "@playwright/test";
import {suite, test, fail} from "../lib";

playwright.describe('@fail decorator', () => {
playwright.describe('with @test', () => {
const called: string[] = [];

@suite()
class FocusedSuite {
@fail()
@test()
failingTest() {
called.push('failingTest');
expect(true).toBe(false);
}
}

playwright('@fail decorator should not throw error when test fails', () => {
// is called and not throw error
expect(called).toEqual(['failingTest']);
});
});
});
Loading