vitest-cucumber-plugin 0.1.5 → 0.1.7
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 +9 -6
- package/RELEASE_NOTES.md +2 -0
- package/generate-parsers +6 -0
- package/package.json +5 -5
- package/rollup-tags-expression.js +10 -0
- package/run-tests +3 -2
- package/src/generate/example.js +3 -2
- package/src/generate/examples.js +6 -4
- package/src/generate/feature.js +46 -9
- package/src/generate/index.js +1 -1
- package/src/generate/{scenarioOutline.js → scenario-outline.js} +4 -1
- package/src/generate/tests.js +7 -2
- package/src/generate/util.js +3 -4
- package/src/gherkin.js +0 -44
- package/src/gherkin.ne +0 -1
- package/src/gherkin.umd.js +0 -1
- package/src/hooks.js +66 -0
- package/src/index.js +29 -8
- package/src/parse.js +1 -1
- package/src/tags-expression.js +58 -0
- package/src/tags-expression.ne +43 -0
- package/src/tags-expression.umd.js +46 -0
- package/src/tags.js +68 -0
- package/tests/background/features/support/hooks.js +3 -0
- package/tests/background/package-lock.json +104 -1427
- package/tests/background/package.json +5 -5
- package/tests/background/vite.config.js +1 -1
- package/tests/comments/package-lock.json +2 -596
- package/tests/comments/package.json +5 -5
- package/tests/data-tables/package-lock.json +2 -596
- package/tests/data-tables/package.json +5 -5
- package/tests/hooks/features/after-all.feature +5 -0
- package/tests/hooks/features/after.feature +5 -0
- package/tests/hooks/features/before-all.feature +14 -0
- package/tests/hooks/features/before-step.feature +6 -0
- package/tests/hooks/features/before.feature +14 -0
- package/tests/hooks/features/step_definitions/steps.js +28 -0
- package/tests/hooks/features/support/hooks.js +75 -0
- package/tests/hooks/features/support/tags-hooks.js +11 -0
- package/tests/hooks/features/tags.feature +14 -0
- package/tests/hooks/package-lock.json +1204 -0
- package/tests/hooks/package.json +11 -0
- package/tests/hooks/vite.config.js +9 -0
- package/tests/is-it-friday/package-lock.json +2 -596
- package/tests/is-it-friday/package.json +5 -5
- package/tests/is-it-friday-scenario-outline/package-lock.json +2 -596
- package/tests/is-it-friday-scenario-outline/package.json +5 -5
- package/tests/is-it-friday-two-scenarios/package-lock.json +2 -596
- package/tests/is-it-friday-two-scenarios/package.json +5 -5
- package/tests/is-it-friday-two-scenarios-multiple-feature-files/package-lock.json +2 -596
- package/tests/is-it-friday-two-scenarios-multiple-feature-files/package.json +5 -5
- package/tests/keyword-aliases/features/support/hooks.js +6 -0
- package/tests/keyword-aliases/package-lock.json +2 -596
- package/tests/keyword-aliases/package.json +5 -5
- package/tests/tags/features/support/hooks.js +6 -0
- package/tests/tags/features/tags-scenario-outline.feature +10 -3
- package/tests/tags/features/tags.feature +2 -2
- package/tests/tags/package-lock.json +104 -1427
- package/tests/tags/package.json +5 -5
- package/tests/tags/vite.config.js +1 -1
- /package/{rollup-nearley.js → rollup-gherkin.js} +0 -0
package/README.md
CHANGED
|
@@ -22,7 +22,10 @@ import vitestCucumberPlugin from 'vitest-cucumber-plugin';
|
|
|
22
22
|
export default defineConfig({
|
|
23
23
|
plugins: [vitestCucumberPlugin()],
|
|
24
24
|
test: {
|
|
25
|
-
include : [ '**/*.feature' ]
|
|
25
|
+
include : [ '**/*.feature' ],
|
|
26
|
+
cucumber : {
|
|
27
|
+
tags : "<tags boolean expression>"
|
|
28
|
+
}
|
|
26
29
|
},
|
|
27
30
|
})
|
|
28
31
|
```
|
|
@@ -46,8 +49,9 @@ there are a few differences in how step definitions are written.
|
|
|
46
49
|
|
|
47
50
|
The function signatures for Given, When and Then callbacks have been modified in order to make the step definitions
|
|
48
51
|
more friendly for functional programming. Specifically, the callback functions differ in that they
|
|
49
|
-
now have
|
|
50
|
-
|
|
52
|
+
now have three parameters. The first parameter is a state object which was returned by the previous step. The
|
|
53
|
+
second is an array of parameters values. The third is a data table or a doc string. The callback functions then
|
|
54
|
+
return a new state object which is passed to the next step definition in the chain.
|
|
51
55
|
|
|
52
56
|
For example, here is how you'd write step definitions in Cucumber:
|
|
53
57
|
```
|
|
@@ -70,7 +74,7 @@ When('I ask whether it\'s Friday yet', function () {
|
|
|
70
74
|
this.actualAnswer = isItFriday(this.today);
|
|
71
75
|
});
|
|
72
76
|
|
|
73
|
-
Then('I should be told {string}', function (expectedAnswer) {
|
|
77
|
+
Then('I should be told {string}', function (expectedAnswer, dataTable) {
|
|
74
78
|
assert.strictEqual(this.actualAnswer, expectedAnswer);
|
|
75
79
|
});
|
|
76
80
|
```
|
|
@@ -93,7 +97,7 @@ When('I ask whether it\'s Friday yet', function (state) {
|
|
|
93
97
|
return _.set('answer',(state.today === 'Friday') ? 'TGIF' : 'Nope',state);
|
|
94
98
|
});
|
|
95
99
|
|
|
96
|
-
Then('I should be told {string}', function (state,[ answer ]) {
|
|
100
|
+
Then('I should be told {string}', function (state,[ answer ], dataTable) {
|
|
97
101
|
expect(state.answer).toBe(answer);
|
|
98
102
|
});
|
|
99
103
|
```
|
|
@@ -109,4 +113,3 @@ work, but this configuration isn't tested.
|
|
|
109
113
|
This plugin is not yet feature complete. Here is the list of features from Cucumber which aren't yet implemented:
|
|
110
114
|
* Rule keyword
|
|
111
115
|
* Doc strings
|
|
112
|
-
* Boolean expression support for tags
|
package/RELEASE_NOTES.md
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
* v0.1.7 : Implemented Hooks API
|
|
2
|
+
* v0.1.6 : Implemented tags boolean expression support
|
|
1
3
|
* v0.1.5 : Implemented escape characters for Data Tables
|
|
2
4
|
* v0.1.4 : Changed README to point to RPM registry
|
|
3
5
|
* v0.1.3 : Import modules from generated code to make sure they are processed correctly
|
package/generate-parsers
ADDED
package/package.json
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vitest-cucumber-plugin",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "Plugin for Vitest which allows for tests to be written in Cucumber format.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"vite",
|
|
7
7
|
"vitest",
|
|
8
8
|
"cucumber"
|
|
9
9
|
],
|
|
10
|
-
"homepage": "https://github.com/
|
|
10
|
+
"homepage": "https://github.com/samuel-ziegler/vitest-cucumber-plugin#readme",
|
|
11
11
|
"bugs": {
|
|
12
|
-
"url": "https://github.com/
|
|
12
|
+
"url": "https://github.com/samuel-ziegler/vitest-cucumber-plugin/issues"
|
|
13
13
|
},
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"main": "src/index.js",
|
|
16
16
|
"type": "module",
|
|
17
17
|
"scripts": {
|
|
18
|
-
"nearley": "
|
|
18
|
+
"nearley": "./generate-parsers",
|
|
19
19
|
"test": "./run-tests"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
@@ -30,5 +30,5 @@
|
|
|
30
30
|
"@types/lodash": "^4.14.194",
|
|
31
31
|
"rollup": "^3.20.7"
|
|
32
32
|
},
|
|
33
|
-
"repository": "https://github.com/
|
|
33
|
+
"repository": "https://github.com/samuel-ziegler/vitest-cucumber-plugin.git"
|
|
34
34
|
}
|
package/run-tests
CHANGED
package/src/generate/example.js
CHANGED
|
@@ -9,11 +9,12 @@ export const generateExample = (config,example) => {
|
|
|
9
9
|
|
|
10
10
|
const steps = _.has('background.steps',example) ? _.concat(example.background.steps,example.steps) : example.steps;
|
|
11
11
|
|
|
12
|
-
tests += generateTests(steps);
|
|
12
|
+
tests += generateTests(steps,{},example.tags);
|
|
13
13
|
|
|
14
14
|
const skip = shouldSkip(config,example.tags) ? '.skip' : '';
|
|
15
15
|
|
|
16
|
-
const code = `
|
|
16
|
+
const code = ` // tags : ${JSON.stringify(example.tags)}
|
|
17
|
+
describe${skip}('${escape(example.type.name)}: ${escape(example.name)}', () => {${tests}
|
|
17
18
|
});
|
|
18
19
|
`;
|
|
19
20
|
return code;
|
package/src/generate/examples.js
CHANGED
|
@@ -14,12 +14,12 @@ const createParameterMap = (parameters,values) => {
|
|
|
14
14
|
return parameterMap.map;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
const generateAllTests = (steps,parameters,parameterValues) => {
|
|
17
|
+
const generateAllTests = (steps,parameters,parameterValues,tags) => {
|
|
18
18
|
const allTests = _.reduce((allTests,values) => {
|
|
19
19
|
const parameterMap = createParameterMap(parameters,values);
|
|
20
20
|
log.debug('parameterMap : '+JSON.stringify(parameterMap));
|
|
21
21
|
|
|
22
|
-
const tests = generateTests(steps,parameterMap,' ');
|
|
22
|
+
const tests = generateTests(steps,parameterMap,tags,' ');
|
|
23
23
|
|
|
24
24
|
return { tests : allTests.tests + `
|
|
25
25
|
describe('${allTests.index}',() => {${tests}
|
|
@@ -40,8 +40,10 @@ export const generateExamples = (config,steps,examplesStatement) => {
|
|
|
40
40
|
|
|
41
41
|
const skip = shouldSkip(config,examplesStatement.tags) ? '.skip' : '';
|
|
42
42
|
|
|
43
|
-
const allTests = generateAllTests(steps,parameters,parameterValues);
|
|
44
|
-
const code = `
|
|
43
|
+
const allTests = generateAllTests(steps,parameters,parameterValues,examplesStatement.tags);
|
|
44
|
+
const code = `
|
|
45
|
+
// tags : ${JSON.stringify(examplesStatement.tags)}
|
|
46
|
+
describe${skip}('${escape(examplesStatement.type.name)}: ${escape(examplesStatement.name)}', () => {${allTests}
|
|
45
47
|
});`;
|
|
46
48
|
return code;
|
|
47
49
|
}
|
package/src/generate/feature.js
CHANGED
|
@@ -11,6 +11,9 @@ export const generateFeature = (config,feature) => {
|
|
|
11
11
|
if (feature.background) {
|
|
12
12
|
statement = _.set('background',feature.background,statement);
|
|
13
13
|
}
|
|
14
|
+
|
|
15
|
+
statement = _.set('tags',_.concat(feature.tags,statement.tags),statement);
|
|
16
|
+
|
|
14
17
|
if (statement.type.type === 'example') {
|
|
15
18
|
return testStatements + generateExample(config,statement);
|
|
16
19
|
} else if (statement.type.type === 'scenarioOutline') {
|
|
@@ -20,26 +23,60 @@ export const generateFeature = (config,feature) => {
|
|
|
20
23
|
|
|
21
24
|
const skip = shouldSkip(config,feature.tags) ? '.skip' : '';
|
|
22
25
|
const configStr = JSON.stringify(config);
|
|
26
|
+
const tagsStr = JSON.stringify(feature.tags);
|
|
23
27
|
|
|
24
|
-
const code = `import { expect, test, describe } from 'vitest';
|
|
25
|
-
import {
|
|
28
|
+
const code = `import { expect, test, describe, beforeAll, afterAll, beforeEach, afterEach } from 'vitest';
|
|
29
|
+
import {
|
|
30
|
+
Test,
|
|
31
|
+
applyBeforeAllHooks,
|
|
32
|
+
applyBeforeHooks,
|
|
33
|
+
applyBeforeStepHooks,
|
|
34
|
+
applyAfterAllHooks,
|
|
35
|
+
applyAfterHooks,
|
|
36
|
+
applyAfterStepHooks,
|
|
37
|
+
} from 'vitest-cucumber-plugin';
|
|
26
38
|
import { readdir } from 'node:fs/promises';
|
|
39
|
+
import { log, setLogLevel } from 'vitest-cucumber-plugin';
|
|
40
|
+
|
|
41
|
+
setLogLevel('${config.logLevel}');
|
|
42
|
+
|
|
43
|
+
const importDirectory = async (directory) => {
|
|
44
|
+
log.debug('importDirectory directory: '+directory);
|
|
45
|
+
try {
|
|
46
|
+
const files = await readdir(directory);
|
|
27
47
|
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
48
|
+
for (const file of files) {
|
|
49
|
+
const filename = directory+'/'+file;
|
|
50
|
+
log.debug('importDirectory import: '+filename);
|
|
51
|
+
await import(filename);
|
|
52
|
+
}
|
|
53
|
+
} catch (e) {
|
|
54
|
+
log.debug('importDirectory error: '+e);
|
|
34
55
|
}
|
|
35
56
|
};
|
|
36
57
|
|
|
58
|
+
const importSupportFiles = async (config) => importDirectory(config.root+'/features/support');
|
|
59
|
+
|
|
60
|
+
await importSupportFiles(${configStr});
|
|
61
|
+
|
|
62
|
+
const importStepDefinitions = async (config) => importDirectory(config.root+'/features/step_definitions');
|
|
63
|
+
|
|
37
64
|
await importStepDefinitions(${configStr});
|
|
38
65
|
|
|
66
|
+
var state = {};
|
|
67
|
+
|
|
68
|
+
beforeAll(async () => {
|
|
69
|
+
state = await applyBeforeAllHooks(state,${tagsStr});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
afterAll(async () => {
|
|
73
|
+
state = await applyAfterAllHooks(state,${tagsStr});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// tags : ${tagsStr}
|
|
39
77
|
describe${skip}('${escape(feature.type.name)}: ${escape(name)}', () => {
|
|
40
78
|
${testStatements}});
|
|
41
79
|
`;
|
|
42
|
-
log.debug(code);
|
|
43
80
|
|
|
44
81
|
return code;
|
|
45
82
|
}
|
package/src/generate/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { generateTests } from './tests.js';
|
|
2
2
|
import { generateExample } from './example.js';
|
|
3
3
|
import { generateExamples } from './examples.js';
|
|
4
|
-
import { generateScenarioOutline } from './
|
|
4
|
+
import { generateScenarioOutline } from './scenario-outline.js';
|
|
5
5
|
import { generateFeature } from './feature.js';
|
|
6
6
|
|
|
7
7
|
export {
|
|
@@ -4,12 +4,15 @@ import { escape, shouldSkip } from './util.js';
|
|
|
4
4
|
|
|
5
5
|
export const generateScenarioOutline = (config,scenarioOutline) => {
|
|
6
6
|
const examplesStatements = _.reduce((examplesStatements,examplesStatement) => {
|
|
7
|
+
examplesStatement = _.set('tags',_.concat(scenarioOutline.tags,examplesStatement.tags),examplesStatement);
|
|
8
|
+
|
|
7
9
|
return examplesStatements + generateExamples(config,scenarioOutline.steps,examplesStatement);
|
|
8
10
|
},'')(scenarioOutline.examples);
|
|
9
11
|
|
|
10
12
|
const skip = shouldSkip(config,scenarioOutline.tags) ? '.skip' : '';
|
|
11
13
|
|
|
12
|
-
const code = `
|
|
14
|
+
const code = ` // tags : ${JSON.stringify(scenarioOutline.tags)}
|
|
15
|
+
describe${skip}('${escape(scenarioOutline.type.name)}: ${escape(scenarioOutline.name)}', () => {
|
|
13
16
|
${examplesStatements}
|
|
14
17
|
});
|
|
15
18
|
`;
|
package/src/generate/tests.js
CHANGED
|
@@ -3,11 +3,16 @@ import { escape } from './util.js';
|
|
|
3
3
|
import { parameterizeText } from '../parameterize.js';
|
|
4
4
|
import { log } from '../logger.js';
|
|
5
5
|
|
|
6
|
-
export const generateTests = (steps,parameterMap,extraIndent) => {
|
|
6
|
+
export const generateTests = (steps,parameterMap,tags,extraIndent) => {
|
|
7
7
|
log.debug('generateTests steps : '+JSON.stringify(steps));
|
|
8
|
+
const tagsStr = JSON.stringify(tags);
|
|
8
9
|
const indent = extraIndent ? extraIndent : '';
|
|
9
10
|
let tests = `
|
|
10
|
-
${indent}
|
|
11
|
+
${indent} beforeAll(async () => { state = await applyBeforeHooks(state,${tagsStr}); });
|
|
12
|
+
${indent} beforeEach(async () => { state = await applyBeforeStepHooks(state,${tagsStr}); });
|
|
13
|
+
${indent} afterAll(async () => { state = await applyAfterHooks(state,${tagsStr}); });
|
|
14
|
+
${indent} afterEach(async () => { state = await applyAfterStepHooks(state,${tagsStr}); });
|
|
15
|
+
`;
|
|
11
16
|
|
|
12
17
|
_.forEach((step) => {
|
|
13
18
|
const parameterizedText = ( parameterMap ? parameterizeText(step.text,parameterMap) : step.text);
|
package/src/generate/util.js
CHANGED
|
@@ -3,8 +3,7 @@ import { log } from '../logger.js';
|
|
|
3
3
|
|
|
4
4
|
export const escape = (str) => str.replace(/'/g,"\\'");
|
|
5
5
|
export const shouldSkip = (config,tags) => {
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
return intersection.length > 0;
|
|
6
|
+
const result = !config.tagsFunction(tags);
|
|
7
|
+
log.debug('shouldSkip? '+result+' tags: '+JSON.stringify(tags));
|
|
8
|
+
return result;
|
|
10
9
|
}
|
package/src/gherkin.js
CHANGED
|
@@ -1,55 +1,12 @@
|
|
|
1
1
|
import require$$0 from 'lodash/fp.js';
|
|
2
2
|
import require$$1 from 'moo';
|
|
3
|
-
import pino from 'pino';
|
|
4
3
|
|
|
5
4
|
function getDefaultExportFromCjs (x) {
|
|
6
5
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
|
7
6
|
}
|
|
8
7
|
|
|
9
|
-
function getAugmentedNamespace(n) {
|
|
10
|
-
if (n.__esModule) return n;
|
|
11
|
-
var f = n.default;
|
|
12
|
-
if (typeof f == "function") {
|
|
13
|
-
var a = function a () {
|
|
14
|
-
if (this instanceof a) {
|
|
15
|
-
var args = [null];
|
|
16
|
-
args.push.apply(args, arguments);
|
|
17
|
-
var Ctor = Function.bind.apply(f, args);
|
|
18
|
-
return new Ctor();
|
|
19
|
-
}
|
|
20
|
-
return f.apply(this, arguments);
|
|
21
|
-
};
|
|
22
|
-
a.prototype = f.prototype;
|
|
23
|
-
} else a = {};
|
|
24
|
-
Object.defineProperty(a, '__esModule', {value: true});
|
|
25
|
-
Object.keys(n).forEach(function (k) {
|
|
26
|
-
var d = Object.getOwnPropertyDescriptor(n, k);
|
|
27
|
-
Object.defineProperty(a, k, d.get ? d : {
|
|
28
|
-
enumerable: true,
|
|
29
|
-
get: function () {
|
|
30
|
-
return n[k];
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
});
|
|
34
|
-
return a;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
8
|
var gherkin_umd$1 = {exports: {}};
|
|
38
9
|
|
|
39
|
-
const log = pino();
|
|
40
|
-
|
|
41
|
-
log.level = 'warn';
|
|
42
|
-
|
|
43
|
-
const setLogLevel = (logLevel) => { log.level = logLevel; };
|
|
44
|
-
|
|
45
|
-
var logger = /*#__PURE__*/Object.freeze({
|
|
46
|
-
__proto__: null,
|
|
47
|
-
log: log,
|
|
48
|
-
setLogLevel: setLogLevel
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
var require$$2 = /*@__PURE__*/getAugmentedNamespace(logger);
|
|
52
|
-
|
|
53
10
|
(function (module) {
|
|
54
11
|
// Generated automatically by nearley, version 2.20.1
|
|
55
12
|
// http://github.com/Hardmath123/nearley
|
|
@@ -57,7 +14,6 @@ var require$$2 = /*@__PURE__*/getAugmentedNamespace(logger);
|
|
|
57
14
|
|
|
58
15
|
const fp = require$$0;
|
|
59
16
|
const moo = require$$1;
|
|
60
|
-
require$$2.log;
|
|
61
17
|
const lexer = moo.compile({
|
|
62
18
|
emptyLine : { match: /^[ \t]*(?:\#[^\n]+)?\n/, lineBreaks : true },
|
|
63
19
|
newline : { match : '\n', lineBreaks : true },
|
package/src/gherkin.ne
CHANGED
package/src/gherkin.umd.js
CHANGED
|
@@ -5,7 +5,6 @@ function id(x) { return x[0]; }
|
|
|
5
5
|
|
|
6
6
|
const fp = require('lodash/fp.js');
|
|
7
7
|
const moo = require('moo');
|
|
8
|
-
const log = require('./logger.js').log;
|
|
9
8
|
const lexer = moo.compile({
|
|
10
9
|
emptyLine : { match: /^[ \t]*(?:\#[^\n]+)?\n/, lineBreaks : true },
|
|
11
10
|
newline : { match : '\n', lineBreaks : true },
|
package/src/hooks.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { log } from './logger.js';
|
|
2
|
+
import _ from 'lodash/fp.js';
|
|
3
|
+
import { tagsFunction } from './tags.js';
|
|
4
|
+
|
|
5
|
+
const allHooks = {
|
|
6
|
+
beforeAll : [],
|
|
7
|
+
before : [],
|
|
8
|
+
beforeStep : [],
|
|
9
|
+
afterAll : [],
|
|
10
|
+
after : [],
|
|
11
|
+
afterStep : [],
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const applyHooks = async (hooksName,state,tags) => {
|
|
15
|
+
const hooks = allHooks[hooksName];
|
|
16
|
+
log.debug('applyHooks: '+hooksName+' state: '+JSON.stringify(state));
|
|
17
|
+
for (let i = 0; i < hooks.length; i++) {
|
|
18
|
+
let hook = hooks[i];
|
|
19
|
+
|
|
20
|
+
log.debug('applyHooks name: '+hook.name+' state: '+JSON.stringify(state));
|
|
21
|
+
|
|
22
|
+
const result = hook.tagsFunction(tags);
|
|
23
|
+
|
|
24
|
+
log.debug('applyHooks match? '+result+' tags: '+JSON.stringify(tags));
|
|
25
|
+
if (result) {
|
|
26
|
+
state = await hook.f(state);
|
|
27
|
+
log.debug('applyHooks name: '+hook.name+' new state: '+JSON.stringify(state));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return state;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const addHook = (hooksName,opts,f) => {
|
|
34
|
+
if (_.isFunction(opts)) {
|
|
35
|
+
opts = { name : '', f : opts };
|
|
36
|
+
} else if (_.isString(opts)) {
|
|
37
|
+
opts = { name : opts, f };
|
|
38
|
+
} else if (_.isObject(opts)) {
|
|
39
|
+
opts.f = f;
|
|
40
|
+
} else {
|
|
41
|
+
throw new Error('Unknown options argument: '+JSON.stringify(opts));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
opts = _.set('tagsFunction',tagsFunction(opts.tags),opts);
|
|
45
|
+
|
|
46
|
+
log.debug('addHook hooksName: '+hooksName+' name: '+opts.name);
|
|
47
|
+
allHooks[hooksName] = _.concat(allHooks[hooksName],opts);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const BeforeAll = (opts,f) => { addHook('beforeAll',opts,f) };
|
|
51
|
+
export const applyBeforeAllHooks = (state,tags) => applyHooks('beforeAll',state,tags);
|
|
52
|
+
|
|
53
|
+
export const Before = (opts,f) => { addHook('before',opts,f) };
|
|
54
|
+
export const applyBeforeHooks = (state,tags) => applyHooks('before',state,tags);
|
|
55
|
+
|
|
56
|
+
export const BeforeStep = (opts,f) => { addHook('beforeStep',opts,f) };
|
|
57
|
+
export const applyBeforeStepHooks = (state,tags) => applyHooks('beforeStep',state,tags);
|
|
58
|
+
|
|
59
|
+
export const AfterAll = (opts,f) => { addHook('afterAll',opts,f) };
|
|
60
|
+
export const applyAfterAllHooks = (state,tags) => applyHooks('afterAll',state,tags);
|
|
61
|
+
|
|
62
|
+
export const After = (opts,f) => { addHook('after',opts,f) };
|
|
63
|
+
export const applyAfterHooks = (state,tags) => applyHooks('after',state,tags);
|
|
64
|
+
|
|
65
|
+
export const AfterStep = (opts,f) => { addHook('afterStep',opts,f) };
|
|
66
|
+
export const applyAfterStepHooks = (state,tags) => applyHooks('afterStep',state,tags);
|
package/src/index.js
CHANGED
|
@@ -4,6 +4,15 @@ import { parameterizeText } from './parameterize.js';
|
|
|
4
4
|
import { generateFeature } from './generate/index.js';
|
|
5
5
|
import { log, setLogLevel } from './logger.js';
|
|
6
6
|
import { parse } from './parse.js';
|
|
7
|
+
import { tagsFunction } from './tags.js';
|
|
8
|
+
import {
|
|
9
|
+
BeforeAll, applyBeforeAllHooks,
|
|
10
|
+
Before, applyBeforeHooks,
|
|
11
|
+
AfterAll, applyAfterAllHooks,
|
|
12
|
+
After, applyAfterHooks,
|
|
13
|
+
BeforeStep, applyBeforeStepHooks,
|
|
14
|
+
AfterStep, applyAfterStepHooks,
|
|
15
|
+
} from './hooks.js';
|
|
7
16
|
|
|
8
17
|
const featureRegex = /\.feature$/;
|
|
9
18
|
|
|
@@ -12,11 +21,22 @@ const compileFeatureToJS = (config,featureSrc) => {
|
|
|
12
21
|
|
|
13
22
|
const code = generateFeature(config,feature);
|
|
14
23
|
|
|
15
|
-
log.debug(code);
|
|
16
|
-
|
|
17
24
|
return code;
|
|
18
25
|
}
|
|
19
26
|
|
|
27
|
+
export { BeforeAll, Before, AfterAll, After, BeforeStep, AfterStep };
|
|
28
|
+
|
|
29
|
+
export {
|
|
30
|
+
applyBeforeAllHooks,
|
|
31
|
+
applyBeforeHooks,
|
|
32
|
+
applyAfterAllHooks,
|
|
33
|
+
applyAfterHooks,
|
|
34
|
+
applyBeforeStepHooks,
|
|
35
|
+
applyAfterStepHooks,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export { setLogLevel, log };
|
|
39
|
+
|
|
20
40
|
export const Given = addStepDefinition;
|
|
21
41
|
export const When = addStepDefinition;
|
|
22
42
|
export const Then = addStepDefinition;
|
|
@@ -44,18 +64,19 @@ export default function vitestCucumberPlugin() {
|
|
|
44
64
|
return {
|
|
45
65
|
name : 'vitest-cucumber-transform',
|
|
46
66
|
configResolved : (resolvedConfig) => {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
config = _.set('root',resolvedConfig.root,config);
|
|
67
|
+
config = _.defaults({ root : resolvedConfig.root, logLevel : 'warn' },_.get('test.cucumber',resolvedConfig))
|
|
68
|
+
setLogLevel(config.logLevel);
|
|
69
|
+
|
|
70
|
+
config = _.set('tagsFunction',tagsFunction(_.get('tags',config)),config);
|
|
71
|
+
|
|
53
72
|
log.debug('config: '+JSON.stringify(config));
|
|
54
73
|
},
|
|
55
74
|
transform : async (src,id) => {
|
|
56
75
|
if (featureRegex.test(id)) {
|
|
57
76
|
const code = compileFeatureToJS(config,src);
|
|
58
77
|
|
|
78
|
+
log.debug('transform '+id+' -> '+code);
|
|
79
|
+
|
|
59
80
|
return {
|
|
60
81
|
code
|
|
61
82
|
}
|
package/src/parse.js
CHANGED
|
@@ -11,7 +11,7 @@ export const parse = (src) => {
|
|
|
11
11
|
if (parser.results.length == 0) {
|
|
12
12
|
throw new Error('Unexpected end of file');
|
|
13
13
|
}
|
|
14
|
-
log.debug('parsing result: '+JSON.stringify(parser.results
|
|
14
|
+
log.debug('parsing result: '+JSON.stringify(parser.results));
|
|
15
15
|
if (parser.results.length > 1) {
|
|
16
16
|
throw new Error('Ambiguous parsing: '+parser.results.length);
|
|
17
17
|
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import 'lodash/fp.js';
|
|
2
|
+
import require$$1 from 'moo';
|
|
3
|
+
|
|
4
|
+
function getDefaultExportFromCjs (x) {
|
|
5
|
+
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
var tagsExpression_umd$1 = {exports: {}};
|
|
9
|
+
|
|
10
|
+
(function (module) {
|
|
11
|
+
// Generated automatically by nearley, version 2.20.1
|
|
12
|
+
// http://github.com/Hardmath123/nearley
|
|
13
|
+
(function () {
|
|
14
|
+
function id(x) { return x[0]; }
|
|
15
|
+
const moo = require$$1;
|
|
16
|
+
const lexer = moo.compile({
|
|
17
|
+
and : 'and',
|
|
18
|
+
or : 'or',
|
|
19
|
+
not : 'not',
|
|
20
|
+
openParen : '(',
|
|
21
|
+
closeParen : ')',
|
|
22
|
+
newline : { match : '\n', lineBreaks : true },
|
|
23
|
+
ws : /[ \t]+/,
|
|
24
|
+
tag : /\@[\w\.]+/,
|
|
25
|
+
});
|
|
26
|
+
var grammar = {
|
|
27
|
+
Lexer: lexer,
|
|
28
|
+
ParserRules: [
|
|
29
|
+
{"name": "main", "symbols": ["expression", (lexer.has("newline") ? {type: "newline"} : newline)], "postprocess": data => data[0]},
|
|
30
|
+
{"name": "expression", "symbols": ["tag"], "postprocess": data => data[0]},
|
|
31
|
+
{"name": "expression", "symbols": ["unaryOperation"], "postprocess": data => data[0]},
|
|
32
|
+
{"name": "expression", "symbols": ["binaryOperation"], "postprocess": data => data[0]},
|
|
33
|
+
{"name": "expression", "symbols": ["parenOperation"], "postprocess": data => data[0]},
|
|
34
|
+
{"name": "parenOperation", "symbols": [(lexer.has("openParen") ? {type: "openParen"} : openParen), "_", "expression", "_", (lexer.has("closeParen") ? {type: "closeParen"} : closeParen)], "postprocess": data => data[2]},
|
|
35
|
+
{"name": "unaryOperation", "symbols": [(lexer.has("not") ? {type: "not"} : not), (lexer.has("ws") ? {type: "ws"} : ws), "unaryExpression"], "postprocess": data => { return { operator : 'not', expression : data[2] } }},
|
|
36
|
+
{"name": "unaryExpression", "symbols": ["tag"], "postprocess": id},
|
|
37
|
+
{"name": "unaryExpression", "symbols": ["parenOperation"], "postprocess": id},
|
|
38
|
+
{"name": "binaryOperation", "symbols": ["expression", "_", "binaryOperator", "_", "expression"], "postprocess":
|
|
39
|
+
data => { return { operator : data[2], left : data[0], right : data[4] } }
|
|
40
|
+
},
|
|
41
|
+
{"name": "binaryOperator", "symbols": [(lexer.has("and") ? {type: "and"} : and)], "postprocess": data => data[0].value},
|
|
42
|
+
{"name": "binaryOperator", "symbols": [(lexer.has("or") ? {type: "or"} : or)], "postprocess": data => data[0].value},
|
|
43
|
+
{"name": "tag", "symbols": [(lexer.has("tag") ? {type: "tag"} : tag)], "postprocess": data => data[0].value.slice(1)},
|
|
44
|
+
{"name": "_", "symbols": []},
|
|
45
|
+
{"name": "_", "symbols": [(lexer.has("ws") ? {type: "ws"} : ws)]}
|
|
46
|
+
]
|
|
47
|
+
, ParserStart: "main"
|
|
48
|
+
};
|
|
49
|
+
{
|
|
50
|
+
module.exports = grammar;
|
|
51
|
+
}
|
|
52
|
+
})();
|
|
53
|
+
} (tagsExpression_umd$1));
|
|
54
|
+
|
|
55
|
+
var tagsExpression_umdExports = tagsExpression_umd$1.exports;
|
|
56
|
+
var tagsExpression_umd = /*@__PURE__*/getDefaultExportFromCjs(tagsExpression_umdExports);
|
|
57
|
+
|
|
58
|
+
export { tagsExpression_umd as default };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
@{%
|
|
2
|
+
const fp = require('lodash/fp.js');
|
|
3
|
+
const moo = require('moo');
|
|
4
|
+
const lexer = moo.compile({
|
|
5
|
+
and : 'and',
|
|
6
|
+
or : 'or',
|
|
7
|
+
not : 'not',
|
|
8
|
+
openParen : '(',
|
|
9
|
+
closeParen : ')',
|
|
10
|
+
newline : { match : '\n', lineBreaks : true },
|
|
11
|
+
ws : /[ \t]+/,
|
|
12
|
+
tag : /\@[\w\.]+/,
|
|
13
|
+
});
|
|
14
|
+
%}
|
|
15
|
+
|
|
16
|
+
@lexer lexer
|
|
17
|
+
|
|
18
|
+
main -> expression %newline {% data => data[0] %}
|
|
19
|
+
|
|
20
|
+
expression -> tag {% data => data[0] %}
|
|
21
|
+
| unaryOperation {% data => data[0] %}
|
|
22
|
+
| binaryOperation {% data => data[0] %}
|
|
23
|
+
| parenOperation {% data => data[0] %}
|
|
24
|
+
|
|
25
|
+
parenOperation -> %openParen _ expression _ %closeParen {% data => data[2] %}
|
|
26
|
+
|
|
27
|
+
unaryOperation -> %not %ws unaryExpression {% data => { return { operator : 'not', expression : data[2] } } %}
|
|
28
|
+
|
|
29
|
+
unaryExpression -> tag {% id %}
|
|
30
|
+
| parenOperation {% id %}
|
|
31
|
+
|
|
32
|
+
binaryOperation -> expression _ binaryOperator _ expression {%
|
|
33
|
+
data => { return { operator : data[2], left : data[0], right : data[4] } }
|
|
34
|
+
%}
|
|
35
|
+
|
|
36
|
+
binaryOperator -> %and {% data => data[0].value %}
|
|
37
|
+
| %or {% data => data[0].value %}
|
|
38
|
+
|
|
39
|
+
tag -> %tag {% data => data[0].value.slice(1) %}
|
|
40
|
+
|
|
41
|
+
_ -> null
|
|
42
|
+
| %ws
|
|
43
|
+
|