@qavajs/cypress-runner-adapter 1.10.0 → 1.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -0
- package/adapter/index.js +20 -1
- package/adapter/make_mocha_tests_describe.js +8 -3
- package/adapter/make_mocha_tests_it.js +7 -3
- package/index.d.ts +1 -44
- package/package.json +11 -5
- package/supportCodeLibrary/index.d.ts +112 -0
package/README.md
CHANGED
|
@@ -30,6 +30,47 @@ module.exports = defineConfig({
|
|
|
30
30
|
});
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
+
### TypeScript
|
|
34
|
+
|
|
35
|
+
TypeScript support is built-in. Point `supportFile` at a `.ts` file and the adapter will compile it automatically:
|
|
36
|
+
|
|
37
|
+
```javascript
|
|
38
|
+
const { defineConfig } = require('cypress');
|
|
39
|
+
const cucumber = require('@qavajs/cypress-runner-adapter/adapter');
|
|
40
|
+
|
|
41
|
+
module.exports = defineConfig({
|
|
42
|
+
e2e: {
|
|
43
|
+
specPattern: 'cypress/feature/**/*.feature',
|
|
44
|
+
supportFile: 'cypress/support/e2e.ts',
|
|
45
|
+
setupNodeEvents(on, config) {
|
|
46
|
+
on('file:preprocessor', cucumber);
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
// cypress/support/e2e.ts
|
|
54
|
+
import { Given, When, Then, setWorldConstructor, World, WorldOptions } from '@qavajs/cypress-runner-adapter';
|
|
55
|
+
|
|
56
|
+
class CustomWorld extends World {
|
|
57
|
+
myValue: string | null;
|
|
58
|
+
|
|
59
|
+
constructor(options: WorldOptions) {
|
|
60
|
+
super(options);
|
|
61
|
+
this.myValue = null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
setWorldConstructor(CustomWorld);
|
|
66
|
+
|
|
67
|
+
Given('I navigate to {string}', function (this: CustomWorld, url: string) {
|
|
68
|
+
cy.visit(url);
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
A `tsconfig.json` is not required but recommended. The adapter uses `transpileOnly: true` so type errors will not block the test run.
|
|
73
|
+
|
|
33
74
|
## Step Definitions
|
|
34
75
|
|
|
35
76
|
Define steps in your support file (e.g. `cypress/support/e2e.js`):
|
package/adapter/index.js
CHANGED
|
@@ -2,7 +2,26 @@ const { mkdirSync, writeFileSync, readFileSync } = require('node:fs');
|
|
|
2
2
|
const { dirname } = require('node:path');
|
|
3
3
|
const { randomUUID } = require('node:crypto');
|
|
4
4
|
const { AstBuilder, compile, GherkinClassicTokenMatcher, Parser } = require('@cucumber/gherkin');
|
|
5
|
-
const webpackPreprocessor = require('@cypress/webpack-preprocessor')(
|
|
5
|
+
const webpackPreprocessor = require('@cypress/webpack-preprocessor')({
|
|
6
|
+
webpackOptions: {
|
|
7
|
+
mode: 'development',
|
|
8
|
+
resolve: { extensions: ['.ts', '.js'] },
|
|
9
|
+
module: {
|
|
10
|
+
rules: [
|
|
11
|
+
{
|
|
12
|
+
test: /\.tsx?$/,
|
|
13
|
+
exclude: [/node_modules/],
|
|
14
|
+
use: [{ loader: 'ts-loader', options: { transpileOnly: true } }]
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
test: /\.jsx?$/,
|
|
18
|
+
exclude: [/node_modules/],
|
|
19
|
+
use: [{ loader: 'babel-loader', options: { presets: ['@babel/preset-env'] } }]
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
});
|
|
6
25
|
const tagExpressionParser = require('@cucumber/tag-expressions').default;
|
|
7
26
|
const makeMochaTestDescribe = require('./make_mocha_tests_describe');
|
|
8
27
|
const makeMochaTestIt = require('./make_mocha_tests_it');
|
|
@@ -50,7 +50,7 @@ module.exports = function makeMochaTest(tests) {
|
|
|
50
50
|
step: { text, argument },
|
|
51
51
|
world: this
|
|
52
52
|
});
|
|
53
|
-
step.code.apply(this, parameters);
|
|
53
|
+
return step.code.apply(this, parameters);
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
function executeStep(pickle, world) {
|
|
@@ -60,7 +60,7 @@ module.exports = function makeMochaTest(tests) {
|
|
|
60
60
|
if (pickle.argument && pickle.argument.docString) {
|
|
61
61
|
Cypress.log({ displayName: 'Multiline', message: pickle.argument.docString.content });
|
|
62
62
|
}
|
|
63
|
-
executeStepByText.call(world, pickle.text, pickle.argument);
|
|
63
|
+
return executeStepByText.call(world, pickle.text, pickle.argument);
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
if (supportCodeLibrary.beforeTestRunHookDefinitions.length > 0) {
|
|
@@ -150,7 +150,12 @@ module.exports = function makeMochaTest(tests) {
|
|
|
150
150
|
}]);
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
|
-
executeStep(step, world);
|
|
153
|
+
const stepResult = executeStep(step, world);
|
|
154
|
+
if (stepResult === 'pending' || stepResult === 'skipped') {
|
|
155
|
+
skip = true;
|
|
156
|
+
status = stepResult;
|
|
157
|
+
return this.skip();
|
|
158
|
+
}
|
|
154
159
|
});
|
|
155
160
|
}
|
|
156
161
|
for (const afterTest of supportCodeLibrary.afterTestCaseHookDefinitions) {
|
|
@@ -58,7 +58,7 @@ module.exports = function makeMochaTest(tests) {
|
|
|
58
58
|
step: { text, argument },
|
|
59
59
|
world: this
|
|
60
60
|
});
|
|
61
|
-
step.code.apply(this, parameters);
|
|
61
|
+
return step.code.apply(this, parameters);
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
function executeStep(pickle, world) {
|
|
@@ -70,7 +70,7 @@ module.exports = function makeMochaTest(tests) {
|
|
|
70
70
|
Cypress.log({ displayName: 'Multiline', message: pickle.argument.docString.content });
|
|
71
71
|
}
|
|
72
72
|
});
|
|
73
|
-
executeStepByText.call(world, pickle.text, pickle.argument);
|
|
73
|
+
return executeStepByText.call(world, pickle.text, pickle.argument);
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
supportCodeLibrary.World.prototype.executeStep = executeStepByText;
|
|
@@ -186,7 +186,11 @@ module.exports = function makeMochaTest(tests) {
|
|
|
186
186
|
}]);
|
|
187
187
|
}
|
|
188
188
|
}
|
|
189
|
-
executeStep(step, world);
|
|
189
|
+
const stepResult = executeStep(step, world);
|
|
190
|
+
if (stepResult === 'pending' || stepResult === 'skipped') {
|
|
191
|
+
result.status = stepResult;
|
|
192
|
+
return this.skip();
|
|
193
|
+
}
|
|
190
194
|
for (const afterStep of supportCodeLibrary.afterTestStepHookDefinitions) {
|
|
191
195
|
if (afterStep.appliesToTestCase(this.step)) {
|
|
192
196
|
afterStep.code.apply(world, [{
|
package/index.d.ts
CHANGED
|
@@ -1,44 +1 @@
|
|
|
1
|
-
|
|
2
|
-
declare type TestHookOptions = {
|
|
3
|
-
tags?: string,
|
|
4
|
-
name?: string
|
|
5
|
-
};
|
|
6
|
-
declare type StepHookOptions = {
|
|
7
|
-
tags?: string
|
|
8
|
-
};
|
|
9
|
-
declare type ParameterTypeOption = {
|
|
10
|
-
name: string,
|
|
11
|
-
preferForRegexpMatch?: boolean,
|
|
12
|
-
regexp: RegExp,
|
|
13
|
-
transformer?: Function,
|
|
14
|
-
useForSnippets?: boolean
|
|
15
|
-
}
|
|
16
|
-
export function defineStep(keyword: string, expression: Expression, fn: Function): void;
|
|
17
|
-
export function Given(expression: Expression, fn: Function): void;
|
|
18
|
-
export function When(expression: Expression, fn: Function): void;
|
|
19
|
-
export function Then(expression: Expression, fn: Function): void;
|
|
20
|
-
export function Before(fn: Function): void;
|
|
21
|
-
export function Before(options: TestHookOptions, fn: Function): void;
|
|
22
|
-
export function After(fn: Function): void;
|
|
23
|
-
export function After(options: TestHookOptions, fn: Function): void;
|
|
24
|
-
export function BeforeStep(fn: Function): void;
|
|
25
|
-
export function BeforeStep(options: StepHookOptions, fn: Function): void;
|
|
26
|
-
export function AfterStep(fn: Function): void;
|
|
27
|
-
export function AfterStep(options: StepHookOptions, fn: Function): void;
|
|
28
|
-
export function BeforeAll(fn: Function): void;
|
|
29
|
-
export function AfterAll(fn: Function): void;
|
|
30
|
-
export function setWorldConstructor(world: IWorld): void;
|
|
31
|
-
export function defineParameterType(option: ParameterTypeOption): void;
|
|
32
|
-
export function setDefaultTimeout(milliseconds: number): void;
|
|
33
|
-
export function Template(template: (...args: any[]) => string): () => void;
|
|
34
|
-
export class World {
|
|
35
|
-
log: (...args: any) => void;
|
|
36
|
-
attach: (...args: any) => void;
|
|
37
|
-
link: (...args: any) => void;
|
|
38
|
-
executeStep(text: string, argument?: any): void;
|
|
39
|
-
constructor(options: {
|
|
40
|
-
log: (...args: any) => void;
|
|
41
|
-
attach: (...args: any) => void;
|
|
42
|
-
link: (...args: any) => void;
|
|
43
|
-
});
|
|
44
|
-
}
|
|
1
|
+
export * from './supportCodeLibrary/index';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qavajs/cypress-runner-adapter",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.0",
|
|
4
4
|
"main": "supportCodeLibrary/index.js",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./supportCodeLibrary/index.js",
|
|
@@ -16,7 +16,11 @@
|
|
|
16
16
|
"debug": "cypress open --config-file test/cypress.config.js",
|
|
17
17
|
"test": "cypress run --config-file test/cypress.config.js",
|
|
18
18
|
"debug:it": "MODE=it cypress open --config-file test/cypress.config.js",
|
|
19
|
-
"test:it": "MODE=it cypress run --config-file test/cypress.config.js"
|
|
19
|
+
"test:it": "MODE=it cypress run --config-file test/cypress.config.js",
|
|
20
|
+
"debug:ts": "cypress open --config-file test/cypress-ts.config.js",
|
|
21
|
+
"test:ts": "cypress run --config-file test/cypress-ts.config.js",
|
|
22
|
+
"debug:ts:it": "MODE=it cypress open --config-file test/cypress-ts.config.js",
|
|
23
|
+
"test:ts:it": "MODE=it cypress run --config-file test/cypress-ts.config.js"
|
|
20
24
|
},
|
|
21
25
|
"license": "MIT",
|
|
22
26
|
"description": "feature file preprocessor",
|
|
@@ -35,10 +39,12 @@
|
|
|
35
39
|
"@cucumber/cucumber-expressions": "^19.0.0",
|
|
36
40
|
"@cucumber/gherkin": "^39.1.0",
|
|
37
41
|
"@cucumber/tag-expressions": "^9.1.0",
|
|
38
|
-
"@cypress/webpack-preprocessor": "^7.1.0"
|
|
42
|
+
"@cypress/webpack-preprocessor": "^7.1.0",
|
|
43
|
+
"ts-loader": "^9.5.7"
|
|
39
44
|
},
|
|
40
45
|
"devDependencies": {
|
|
41
|
-
"cypress": "^15.14.2"
|
|
46
|
+
"cypress": "^15.14.2",
|
|
47
|
+
"typescript": "^6.0.3"
|
|
42
48
|
},
|
|
43
49
|
"keywords": [
|
|
44
50
|
"cypress",
|
|
@@ -50,4 +56,4 @@
|
|
|
50
56
|
"test",
|
|
51
57
|
"test-automation"
|
|
52
58
|
]
|
|
53
|
-
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
export type Expression = string | RegExp;
|
|
2
|
+
|
|
3
|
+
export class DataTable {
|
|
4
|
+
constructor(sourceTable: string[][] | { rows: { cells: { value: string }[] }[] });
|
|
5
|
+
raw(): string[][];
|
|
6
|
+
rows(): string[][];
|
|
7
|
+
hashes(): Record<string, string>[];
|
|
8
|
+
rowsHash(): Record<string, string>;
|
|
9
|
+
transpose(): DataTable;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface GherkinDocument {
|
|
13
|
+
uri?: string;
|
|
14
|
+
feature?: {
|
|
15
|
+
name: string;
|
|
16
|
+
description: string;
|
|
17
|
+
tags: { name: string }[];
|
|
18
|
+
children: object[];
|
|
19
|
+
};
|
|
20
|
+
comments: object[];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface Pickle {
|
|
24
|
+
id: string;
|
|
25
|
+
uri: string;
|
|
26
|
+
name: string;
|
|
27
|
+
language: string;
|
|
28
|
+
steps: { id: string; text: string; argument?: object }[];
|
|
29
|
+
tags: { name: string; astNodeId: string }[];
|
|
30
|
+
astNodeIds: string[];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface TestStepResult {
|
|
34
|
+
status: string;
|
|
35
|
+
duration?: { seconds: number; nanos: number };
|
|
36
|
+
message?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface TestCaseHookParams {
|
|
40
|
+
gherkinDocument: GherkinDocument;
|
|
41
|
+
pickle: Pickle;
|
|
42
|
+
testCaseStartedId: string;
|
|
43
|
+
willBeRetried: boolean;
|
|
44
|
+
result?: TestStepResult;
|
|
45
|
+
error?: Error;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface TestStepHookParams {
|
|
49
|
+
gherkinDocument: GherkinDocument;
|
|
50
|
+
pickle: Pickle;
|
|
51
|
+
testCaseStartedId: string;
|
|
52
|
+
result?: TestStepResult;
|
|
53
|
+
error?: Error;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface WorldOptions {
|
|
57
|
+
log: (...args: any[]) => void;
|
|
58
|
+
attach: (data: string, mediaType?: string) => void;
|
|
59
|
+
link: (url: string, text?: string) => void;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export class World {
|
|
63
|
+
log(...args: any[]): void;
|
|
64
|
+
attach(data: string, mediaType?: string): void;
|
|
65
|
+
link(url: string, text?: string): void;
|
|
66
|
+
executeStep(text: string, argument?: DataTable | string): void;
|
|
67
|
+
constructor(options: WorldOptions);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
type StepFn<W extends World = World> = (this: W, ...args: any[]) => any;
|
|
71
|
+
|
|
72
|
+
export function defineStep<W extends World = World>(keyword: string, expression: Expression, fn: StepFn<W>): void;
|
|
73
|
+
export function Given<W extends World = World>(expression: Expression, fn: StepFn<W>): void;
|
|
74
|
+
export function When<W extends World = World>(expression: Expression, fn: StepFn<W>): void;
|
|
75
|
+
export function Then<W extends World = World>(expression: Expression, fn: StepFn<W>): void;
|
|
76
|
+
|
|
77
|
+
type TestCaseHookFn = (this: World, params: TestCaseHookParams) => any;
|
|
78
|
+
type TestStepHookFn = (this: World, params: TestStepHookParams) => any;
|
|
79
|
+
type TestRunHookFn = (this: World) => any;
|
|
80
|
+
|
|
81
|
+
export interface TestCaseHookOptions {
|
|
82
|
+
tags?: string;
|
|
83
|
+
name?: string;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface TestStepHookOptions {
|
|
87
|
+
tags?: string;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function Before(fn: TestCaseHookFn): void;
|
|
91
|
+
export function Before(options: TestCaseHookOptions, fn: TestCaseHookFn): void;
|
|
92
|
+
export function After(fn: TestCaseHookFn): void;
|
|
93
|
+
export function After(options: TestCaseHookOptions, fn: TestCaseHookFn): void;
|
|
94
|
+
export function BeforeStep(fn: TestStepHookFn): void;
|
|
95
|
+
export function BeforeStep(options: TestStepHookOptions, fn: TestStepHookFn): void;
|
|
96
|
+
export function AfterStep(fn: TestStepHookFn): void;
|
|
97
|
+
export function AfterStep(options: TestStepHookOptions, fn: TestStepHookFn): void;
|
|
98
|
+
export function BeforeAll(fn: TestRunHookFn): void;
|
|
99
|
+
export function AfterAll(fn: TestRunHookFn): void;
|
|
100
|
+
|
|
101
|
+
export interface ParameterTypeOption {
|
|
102
|
+
name: string;
|
|
103
|
+
regexp: RegExp;
|
|
104
|
+
transformer?: (...args: string[]) => any;
|
|
105
|
+
useForSnippets?: boolean;
|
|
106
|
+
preferForRegexpMatch?: boolean;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function defineParameterType(option: ParameterTypeOption): void;
|
|
110
|
+
export function setWorldConstructor(world: new (...args: any[]) => World): void;
|
|
111
|
+
export function setDefaultTimeout(milliseconds: number): void;
|
|
112
|
+
export function Template(template: (...args: any[]) => string): (...args: any[]) => void;
|