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(skip): add skip decorator #13

Merged
merged 1 commit into from
Jul 15, 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
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,29 @@ class MyTestSuite {
}
}
```

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

```ts
import { suite, test, skip } 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 }) {
// ...
}
}
```

#### Options
- `reason` (optional) - reason of skipping. Will be displayed in the test report.
4 changes: 4 additions & 0 deletions lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
// base
export { suite } from './suite.decorator';
export { test } from './test.decorator';
// hooks
export { beforeAll } from './beforeAll.decorator';
export { beforeEach } from './beforeEach.decorator';
export { afterAll } from './afterAll.decorator';
export { afterEach } from './afterEach.decorator';
// annotations
export { skip } from './skip.decorator';
17 changes: 17 additions & 0 deletions lib/skip.decorator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {SuiteDecoratedMethod} from "./suite.decorator";
import {TestDecoratedMethod} from "./test.decorator";

/**
* Skip @test or @suite (with optional reason).
*/
export const skip = (reason?: string) => function(originalMethod: any, context?: any) {
if ((originalMethod as SuiteDecoratedMethod)?.suiteDecorator) {
originalMethod.suiteDecorator.skip = reason || true;
return;
}

if ((originalMethod as TestDecoratedMethod)?.testDecorator) {
originalMethod.testDecorator.skip = reason || true;
return;
}
}
19 changes: 19 additions & 0 deletions lib/suite.decorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,37 @@ interface SuiteDecoratorOptions {
* Name of the suite. Default: name of the suite class
*/
name?: string;
/**
* Skip suite (with optional reason)
*/
skip?: string | boolean;
}

class SuiteDecorator implements SuiteDecoratorOptions {
name: string;
skip: string | boolean = false;

constructor(private suiteClass: Constructor, options: SuiteDecoratorOptions) {
this.name = suiteClass.name;

Object.assign(this, options);
}

private handleSkip() {
if (this.skip === false) {
return;
}

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

playwright.skip();
}

private runSuite(userSuiteCode: () => Promise<any>) {
this.handleSkip();

return userSuiteCode();
}

Expand Down
19 changes: 19 additions & 0 deletions lib/test.decorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,41 @@ interface TestDecoratorOptions {
* Name of the test. Default: name of the method
*/
name?: string;
/**
* Skip suite (with optional reason)
*/
skip?: string | boolean;
}

class TestDecorator implements TestDecoratorOptions {
name: string;
skip: string | boolean = false;

constructor(private testMethod: any, options: TestDecoratorOptions) {
this.name = testMethod.name;

Object.assign(this, options);
}

private handleSkip() {
if (this.skip === false) {
return;
}

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

playwright.skip();
}

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

// set correct executionContext (test class)
return testFunction.call(executionContext, ...args);
};
Expand Down
52 changes: 34 additions & 18 deletions tests/suite.spec.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,44 @@
import { suite } from '../lib';
import {skip, suite, test} from '../lib';
import playwright, {expect} from '@playwright/test';

playwright.describe('@suite decorator', () => {
let withSuiteDecoratorRun = false;
let withoutSuiteDecoratorRun = false;

@suite()
class WithSuiteDecorator {
constructor() {
withSuiteDecoratorRun = true;
playwright.describe('Class with @suite should be initialized', () => {
const called: string[] = [];

@suite()
class WithSuiteDecorator {
constructor() {
called.push('constructor');
}
}
}

class WithoutSuiteDecorator {
constructor() {
withoutSuiteDecoratorRun = true;
}
}

playwright('Class with @suite should be initialized', () => {
expect(withSuiteDecoratorRun).toBeTruthy();
expect(called).toContain('constructor');
});

playwright('Class without @suite should not be initialized', () => {
expect(withoutSuiteDecoratorRun).toBeFalsy();
const called: string[] = [];

class WithoutSuiteDecorator {
constructor() {
called.push('constructor');
}
}

expect(called).not.toContain('constructor');
});

playwright.describe('Class with @suite & @skip should not run any tests', () => {
const called: string[] = [];

@skip()
@suite()
class WithSuiteDecorator {
@test()
testMethod() {
called.push('testMethod');
}
}

expect(called).not.toContain(['testMethod']);
});
})
25 changes: 24 additions & 1 deletion tests/test.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import playwright, {expect} from "@playwright/test";
import {suite, test} from "../lib";
import {skip, suite, test} from "../lib";

playwright.describe('@test decorator', () => {
const called: string[] = [];
Expand Down Expand Up @@ -44,4 +44,27 @@ playwright.describe('@test decorator', () => {
playwright.afterAll(() => {
expect(called.length).toEqual(4);
})

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

@suite()
class withSkipSuite {
@test()
test() {
called.push('test')
}

@skip()
@test()
skippedTest() {
called.push('skippedTest')
}
}

playwright('should not run skipped tests', () => {
expect(called).toContain('test');
expect(called).not.toContain('skippedTest');
})
})
})