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.
Files changed (61) hide show
  1. package/README.md +9 -6
  2. package/RELEASE_NOTES.md +2 -0
  3. package/generate-parsers +6 -0
  4. package/package.json +5 -5
  5. package/rollup-tags-expression.js +10 -0
  6. package/run-tests +3 -2
  7. package/src/generate/example.js +3 -2
  8. package/src/generate/examples.js +6 -4
  9. package/src/generate/feature.js +46 -9
  10. package/src/generate/index.js +1 -1
  11. package/src/generate/{scenarioOutline.js → scenario-outline.js} +4 -1
  12. package/src/generate/tests.js +7 -2
  13. package/src/generate/util.js +3 -4
  14. package/src/gherkin.js +0 -44
  15. package/src/gherkin.ne +0 -1
  16. package/src/gherkin.umd.js +0 -1
  17. package/src/hooks.js +66 -0
  18. package/src/index.js +29 -8
  19. package/src/parse.js +1 -1
  20. package/src/tags-expression.js +58 -0
  21. package/src/tags-expression.ne +43 -0
  22. package/src/tags-expression.umd.js +46 -0
  23. package/src/tags.js +68 -0
  24. package/tests/background/features/support/hooks.js +3 -0
  25. package/tests/background/package-lock.json +104 -1427
  26. package/tests/background/package.json +5 -5
  27. package/tests/background/vite.config.js +1 -1
  28. package/tests/comments/package-lock.json +2 -596
  29. package/tests/comments/package.json +5 -5
  30. package/tests/data-tables/package-lock.json +2 -596
  31. package/tests/data-tables/package.json +5 -5
  32. package/tests/hooks/features/after-all.feature +5 -0
  33. package/tests/hooks/features/after.feature +5 -0
  34. package/tests/hooks/features/before-all.feature +14 -0
  35. package/tests/hooks/features/before-step.feature +6 -0
  36. package/tests/hooks/features/before.feature +14 -0
  37. package/tests/hooks/features/step_definitions/steps.js +28 -0
  38. package/tests/hooks/features/support/hooks.js +75 -0
  39. package/tests/hooks/features/support/tags-hooks.js +11 -0
  40. package/tests/hooks/features/tags.feature +14 -0
  41. package/tests/hooks/package-lock.json +1204 -0
  42. package/tests/hooks/package.json +11 -0
  43. package/tests/hooks/vite.config.js +9 -0
  44. package/tests/is-it-friday/package-lock.json +2 -596
  45. package/tests/is-it-friday/package.json +5 -5
  46. package/tests/is-it-friday-scenario-outline/package-lock.json +2 -596
  47. package/tests/is-it-friday-scenario-outline/package.json +5 -5
  48. package/tests/is-it-friday-two-scenarios/package-lock.json +2 -596
  49. package/tests/is-it-friday-two-scenarios/package.json +5 -5
  50. package/tests/is-it-friday-two-scenarios-multiple-feature-files/package-lock.json +2 -596
  51. package/tests/is-it-friday-two-scenarios-multiple-feature-files/package.json +5 -5
  52. package/tests/keyword-aliases/features/support/hooks.js +6 -0
  53. package/tests/keyword-aliases/package-lock.json +2 -596
  54. package/tests/keyword-aliases/package.json +5 -5
  55. package/tests/tags/features/support/hooks.js +6 -0
  56. package/tests/tags/features/tags-scenario-outline.feature +10 -3
  57. package/tests/tags/features/tags.feature +2 -2
  58. package/tests/tags/package-lock.json +104 -1427
  59. package/tests/tags/package.json +5 -5
  60. package/tests/tags/vite.config.js +1 -1
  61. /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 two parameters, a state object and array of parameters. The callback functions then return a new state
50
- object which is passed to the next step definition in the chain.
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
@@ -0,0 +1,6 @@
1
+ #!/bin/bash
2
+
3
+ nearleyc src/gherkin.ne -o src/gherkin.umd.js || exit 1
4
+ nearleyc src/tags-expression.ne -o src/tags-expression.umd.js || exit 1
5
+ rollup -c rollup-gherkin.js || exit 1
6
+ rollup -c rollup-tags-expression.js || exit 1
package/package.json CHANGED
@@ -1,21 +1,21 @@
1
1
  {
2
2
  "name": "vitest-cucumber-plugin",
3
- "version": "0.1.5",
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/SamZiegler/vitest-cucumber-plugin#readme",
10
+ "homepage": "https://github.com/samuel-ziegler/vitest-cucumber-plugin#readme",
11
11
  "bugs": {
12
- "url": "https://github.com/SamZiegler/vitest-cucumber-plugin/issues"
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": "nearleyc src/gherkin.ne -o src/gherkin.umd.js && rollup -c rollup-nearley.js",
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/SamZiegler/vitest-cucumber-plugin.git"
33
+ "repository": "https://github.com/samuel-ziegler/vitest-cucumber-plugin.git"
34
34
  }
@@ -0,0 +1,10 @@
1
+ import commonjs from "@rollup/plugin-commonjs";
2
+
3
+ export default {
4
+ input: "src/tags-expression.umd.js",
5
+ output: {
6
+ file: "src/tags-expression.js",
7
+ format: "es",
8
+ },
9
+ plugins: [commonjs()],
10
+ };
package/run-tests CHANGED
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/bash
2
2
 
3
3
  for i in `ls tests`; do
4
+ echo $i
4
5
  pushd tests/$i
5
- npm install || exit
6
- npm test || exit
6
+ npm install || exit 1
7
+ npm test || exit 1
7
8
  popd
8
9
  done
@@ -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 = ` describe${skip}('${escape(example.type.name)}: ${escape(example.name)}', () => {${tests}
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;
@@ -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 = ` describe${skip}('${escape(examplesStatement.type.name)}: ${escape(examplesStatement.name)}', () => {${allTests}
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
  }
@@ -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 { Test } from 'vitest-cucumber-plugin';
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 importStepDefinitions = async (config) => {
29
- const stepDefinitionDirectory = config.root+'/features/step_definitions';
30
- const files = await readdir(stepDefinitionDirectory);
31
- for (const file of files) {
32
- const stepDefinition = stepDefinitionDirectory+'/'+file;
33
- await import(stepDefinition);
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
  }
@@ -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 './scenarioOutline.js';
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 = ` describe${skip}('${escape(scenarioOutline.type.name)}: ${escape(scenarioOutline.name)}', () => {
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
  `;
@@ -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} var state = {};`;
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);
@@ -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 exclude = _.getOr([],'tags.exclude',config);
7
- const intersection = _.intersection(exclude,tags);
8
- log.debug('shouldSkip config: '+JSON.stringify(config)+' tags: '+JSON.stringify(tags)+' intersection: '+JSON.stringify(intersection));
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
@@ -1,7 +1,6 @@
1
1
  @{%
2
2
  const fp = require('lodash/fp.js');
3
3
  const moo = require('moo');
4
- const log = require('./logger.js').log;
5
4
  const lexer = moo.compile({
6
5
  emptyLine : { match: /^[ \t]*(?:\#[^\n]+)?\n/, lineBreaks : true },
7
6
  newline : { match : '\n', lineBreaks : true },
@@ -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
- if (_.has('test.cucumber.logLevel',resolvedConfig)) {
48
- setLogLevel(resolvedConfig.test.cucumber.logLevel);
49
- }
50
- log.debug('config: resolvedConfig:'+JSON.stringify(resolvedConfig,null,2));
51
- config = _.get('test.cucumber',resolvedConfig);
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,null,2));
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
+