vitest-cucumber-plugin 0.1.4 → 0.1.6

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 (46) hide show
  1. package/CONTRIBUTING.md +12 -7
  2. package/README.md +0 -2
  3. package/RELEASE_NOTES.md +2 -0
  4. package/generate-parsers +6 -0
  5. package/package.json +5 -5
  6. package/rollup-tags-expression.js +10 -0
  7. package/run-tests +3 -2
  8. package/src/generate/example.js +2 -1
  9. package/src/generate/examples.js +3 -1
  10. package/src/generate/feature.js +4 -1
  11. package/src/generate/index.js +1 -1
  12. package/src/generate/{scenarioOutline.js → scenario-outline.js} +4 -1
  13. package/src/generate/util.js +3 -4
  14. package/src/gherkin.js +24 -50
  15. package/src/gherkin.ne +27 -10
  16. package/src/gherkin.umd.js +24 -10
  17. package/src/index.js +7 -3
  18. package/src/parse.js +1 -1
  19. package/src/tags-expression.js +58 -0
  20. package/src/tags-expression.ne +43 -0
  21. package/src/tags-expression.umd.js +46 -0
  22. package/src/tags.js +68 -0
  23. package/tests/background/package-lock.json +104 -867
  24. package/tests/background/package.json +5 -5
  25. package/tests/comments/package-lock.json +2 -36
  26. package/tests/comments/package.json +5 -5
  27. package/tests/data-tables/features/data-tables-escaping.feature +27 -0
  28. package/tests/data-tables/package-lock.json +2 -36
  29. package/tests/data-tables/package.json +5 -5
  30. package/tests/is-it-friday/package-lock.json +2 -36
  31. package/tests/is-it-friday/package.json +5 -5
  32. package/tests/is-it-friday-scenario-outline/package-lock.json +2 -36
  33. package/tests/is-it-friday-scenario-outline/package.json +5 -5
  34. package/tests/is-it-friday-two-scenarios/package-lock.json +2 -36
  35. package/tests/is-it-friday-two-scenarios/package.json +5 -5
  36. package/tests/is-it-friday-two-scenarios-multiple-feature-files/package-lock.json +2 -36
  37. package/tests/is-it-friday-two-scenarios-multiple-feature-files/package.json +5 -5
  38. package/tests/keyword-aliases/package-lock.json +2 -36
  39. package/tests/keyword-aliases/package.json +5 -5
  40. package/tests/tags/features/tags-scenario-outline.feature +10 -3
  41. package/tests/tags/features/tags.feature +2 -2
  42. package/tests/tags/package-lock.json +104 -867
  43. package/tests/tags/package.json +5 -5
  44. package/tests/tags/vite.config.js +1 -1
  45. package/tests/data-tables/vite.config.js.timestamp-1682359000824-3876ac2e9095b.mjs +0 -13
  46. /package/{rollup-nearley.js → rollup-gherkin.js} +0 -0
package/CONTRIBUTING.md CHANGED
@@ -37,10 +37,15 @@ branching model. The 'main' branch the release branch and is only pushed to dur
37
37
  ## Doing a release
38
38
 
39
39
  1. ```$ VERSION=<version>```
40
- 1. ```$ git flow release start $VERSION```
41
- 1. Update version number in package.json
42
- 1. Add the release notes to [RELEASE_NOTES.md](RELEASE_NOTES.md).
43
- 1. ```git add . ; git commit -m $VERSION```
44
- 1. ```git flow release finish $VERSION```
45
- 1. ```git push origin $VERSION```
46
- 1. npm publish
40
+ 1. ```$ git flow release start v$VERSION```
41
+ 1. ```$ npm pkg set version=$VERSION```
42
+ 1. ```$ sed -i "1s/^/* v$VERSION : \!\!\! ADD RELEASE NOTE HERE \!\!\!\n/" RELEASE_NOTES.md```
43
+ 1. ```$ emacs -nw RELEASE_NOTES.md```
44
+ 2. ```$ npm test```
45
+ 1. ```$ git add . ; git commit -m v$VERSION```
46
+ 3. ```$ git flow release finish v$VERSION```
47
+ 4. ```$ git push```
48
+ 5. ```$ git checkout main```
49
+ 6. ```$ git push```
50
+ 7. ```$ git push origin v$VERSION```
51
+ 8. ```$ npm publish```
package/README.md CHANGED
@@ -109,5 +109,3 @@ work, but this configuration isn't tested.
109
109
  This plugin is not yet feature complete. Here is the list of features from Cucumber which aren't yet implemented:
110
110
  * Rule keyword
111
111
  * Doc strings
112
- * Data Table escape characters
113
- * Boolean expression support for tags
package/RELEASE_NOTES.md CHANGED
@@ -1,3 +1,5 @@
1
+ * v0.1.6 : Implemented tags boolean expression support
2
+ * v0.1.5 : Implemented escape characters for Data Tables
1
3
  * v0.1.4 : Changed README to point to RPM registry
2
4
  * v0.1.3 : Import modules from generated code to make sure they are processed correctly
3
5
  * v0.1.2 : Set default log level to warn and make it configurable
@@ -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.4",
3
+ "version": "0.1.6",
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
@@ -13,7 +13,8 @@ export const generateExample = (config,example) => {
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;
@@ -41,7 +41,9 @@ export const generateExamples = (config,steps,examplesStatement) => {
41
41
  const skip = shouldSkip(config,examplesStatement.tags) ? '.skip' : '';
42
42
 
43
43
  const allTests = generateAllTests(steps,parameters,parameterValues);
44
- const code = ` describe${skip}('${escape(examplesStatement.type.name)}: ${escape(examplesStatement.name)}', () => {${allTests}
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') {
@@ -36,10 +39,10 @@ const importStepDefinitions = async (config) => {
36
39
 
37
40
  await importStepDefinitions(${configStr});
38
41
 
42
+ // tags : ${JSON.stringify(feature.tags)}
39
43
  describe${skip}('${escape(feature.type.name)}: ${escape(name)}', () => {
40
44
  ${testStatements}});
41
45
  `;
42
- log.debug(code);
43
46
 
44
47
  return code;
45
48
  }
@@ -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,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,52 +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
- var logger = /*#__PURE__*/Object.freeze({
44
- __proto__: null,
45
- log: log
46
- });
47
-
48
- var require$$2 = /*@__PURE__*/getAugmentedNamespace(logger);
49
-
50
10
  (function (module) {
51
11
  // Generated automatically by nearley, version 2.20.1
52
12
  // http://github.com/Hardmath123/nearley
@@ -54,7 +14,6 @@ var require$$2 = /*@__PURE__*/getAugmentedNamespace(logger);
54
14
 
55
15
  const fp = require$$0;
56
16
  const moo = require$$1;
57
- require$$2.log;
58
17
  const lexer = moo.compile({
59
18
  emptyLine : { match: /^[ \t]*(?:\#[^\n]+)?\n/, lineBreaks : true },
60
19
  newline : { match : '\n', lineBreaks : true },
@@ -63,10 +22,12 @@ var require$$2 = /*@__PURE__*/getAugmentedNamespace(logger);
63
22
  colon : ':',
64
23
  step : '*',
65
24
  pipe : '|',
66
- backSlash : '\\',
25
+ escapedPipe : '\\|',
26
+ escapedNewline : '\\n',
27
+ escapedBackSlash : '\\\\',
67
28
  scenarioOutline : ['Scenario Outline','Scenario Template'],
68
29
  word : {
69
- match : /[^ \t\n:|\\]+/,
30
+ match : /[^ \t\n\:\|\@\*]+/,
70
31
  type : moo.keywords({
71
32
  feature : 'Feature',
72
33
  examples : ['Examples','Scenarios'],
@@ -127,7 +88,15 @@ var require$$2 = /*@__PURE__*/getAugmentedNamespace(logger);
127
88
  {"name": "dataTable", "symbols": ["dataTable", "dataTableRow"], "postprocess": data => fp.concat(data[0],[data[1]])},
128
89
  {"name": "dataTableRow", "symbols": ["_", (lexer.has("pipe") ? {type: "pipe"} : pipe), "dataTableColumns", (lexer.has("newline") ? {type: "newline"} : newline)], "postprocess": data => data[2]},
129
90
  {"name": "dataTableColumns", "symbols": [], "postprocess": data => []},
130
- {"name": "dataTableColumns", "symbols": ["dataTableColumns", "text", (lexer.has("pipe") ? {type: "pipe"} : pipe)], "postprocess": data => fp.concat(data[0],data[1].trim())},
91
+ {"name": "dataTableColumns", "symbols": ["dataTableColumns", "dataTableColumnText", (lexer.has("pipe") ? {type: "pipe"} : pipe)], "postprocess": data => fp.concat(data[0],data[1].trim())},
92
+ {"name": "dataTableColumnText", "symbols": [], "postprocess": data => ''},
93
+ {"name": "dataTableColumnText", "symbols": ["dataTableColumnText", "escapedColumnCharaters"], "postprocess": data => data[0]+data[1]},
94
+ {"name": "dataTableColumnText", "symbols": ["dataTableColumnText", "keywords"], "postprocess": data => data[0]+data[1]},
95
+ {"name": "dataTableColumnText", "symbols": ["dataTableColumnText", (lexer.has("word") ? {type: "word"} : word)], "postprocess": data => data[0]+data[1].value},
96
+ {"name": "dataTableColumnText", "symbols": ["dataTableColumnText", (lexer.has("ws") ? {type: "ws"} : ws)], "postprocess": data => data[0]+data[1].value},
97
+ {"name": "escapedColumnCharaters", "symbols": [(lexer.has("escapedPipe") ? {type: "escapedPipe"} : escapedPipe)], "postprocess": data => '|'},
98
+ {"name": "escapedColumnCharaters", "symbols": [(lexer.has("escapedBackSlash") ? {type: "escapedBackSlash"} : escapedBackSlash)], "postprocess": data => '\\'},
99
+ {"name": "escapedColumnCharaters", "symbols": [(lexer.has("escapedNewline") ? {type: "escapedNewline"} : escapedNewline)], "postprocess": data => '\n'},
131
100
  {"name": "steps", "symbols": ["stepAndTable", "moreSteps"], "postprocess": data => fp.concat(data[0],data[1])},
132
101
  {"name": "moreSteps", "symbols": [], "postprocess": data => []},
133
102
  {"name": "moreSteps", "symbols": ["moreSteps", "stepAndTable"], "postprocess": data => fp.concat(data[0],data[1])},
@@ -138,12 +107,17 @@ var require$$2 = /*@__PURE__*/getAugmentedNamespace(logger);
138
107
  {"name": "text", "symbols": [], "postprocess": data => ''},
139
108
  {"name": "text", "symbols": ["text", (lexer.has("word") ? {type: "word"} : word)], "postprocess": data => data[0]+data[1].value},
140
109
  {"name": "text", "symbols": ["text", (lexer.has("ws") ? {type: "ws"} : ws)], "postprocess": data => data[0]+data[1].value},
141
- {"name": "text", "symbols": ["text", (lexer.has("step") ? {type: "step"} : step)], "postprocess": data => data[0]+data[1].value},
142
- {"name": "text", "symbols": ["text", (lexer.has("colon") ? {type: "colon"} : colon)], "postprocess": data => data[0]+data[1].value},
143
- {"name": "text", "symbols": ["text", (lexer.has("example") ? {type: "example"} : example)], "postprocess": data => data[0]+data[1].value},
144
- {"name": "text", "symbols": ["text", (lexer.has("examples") ? {type: "examples"} : examples)], "postprocess": data => data[0]+data[1].value},
145
- {"name": "text", "symbols": ["text", (lexer.has("scenarioOutline") ? {type: "scenarioOutline"} : scenarioOutline)], "postprocess": data => data[0]+data[1].value},
146
- {"name": "text", "symbols": ["text", (lexer.has("background") ? {type: "background"} : background)], "postprocess": data => data[0]+data[1].value},
110
+ {"name": "text", "symbols": ["text", "keywords"], "postprocess": data => data[0]+data[1]},
111
+ {"name": "text", "symbols": ["text", (lexer.has("pipe") ? {type: "pipe"} : pipe)], "postprocess": data => data[0]+data[1].value},
112
+ {"name": "text", "symbols": ["text", (lexer.has("escapedPipe") ? {type: "escapedPipe"} : escapedPipe)], "postprocess": data => data[0]+data[1].value},
113
+ {"name": "text", "symbols": ["text", (lexer.has("escapedNewline") ? {type: "escapedNewline"} : escapedNewline)], "postprocess": data => data[0]+data[1].value},
114
+ {"name": "text", "symbols": ["text", (lexer.has("escapedBackSlash") ? {type: "escapedBackSlash"} : escapedBackSlash)], "postprocess": data => data[0]+data[1].value},
115
+ {"name": "keywords", "symbols": [(lexer.has("step") ? {type: "step"} : step)], "postprocess": data => data[0].value},
116
+ {"name": "keywords", "symbols": [(lexer.has("colon") ? {type: "colon"} : colon)], "postprocess": data => data[0].value},
117
+ {"name": "keywords", "symbols": [(lexer.has("example") ? {type: "example"} : example)], "postprocess": data => data[0].value},
118
+ {"name": "keywords", "symbols": [(lexer.has("examples") ? {type: "examples"} : examples)], "postprocess": data => data[0].value},
119
+ {"name": "keywords", "symbols": [(lexer.has("scenarioOutline") ? {type: "scenarioOutline"} : scenarioOutline)], "postprocess": data => data[0].value},
120
+ {"name": "keywords", "symbols": [(lexer.has("background") ? {type: "background"} : background)], "postprocess": data => data[0].value},
147
121
  {"name": "bolText", "symbols": [(lexer.has("ws") ? {type: "ws"} : ws), (lexer.has("word") ? {type: "word"} : word)], "postprocess": data => data[1].value},
148
122
  {"name": "bolText", "symbols": [(lexer.has("word") ? {type: "word"} : word)], "postprocess": data => data[0].value},
149
123
  {"name": "freeform", "symbols": [], "postprocess": data => ''},
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 },
@@ -10,10 +9,12 @@ const lexer = moo.compile({
10
9
  colon : ':',
11
10
  step : '*',
12
11
  pipe : '|',
13
- backSlash : '\\',
12
+ escapedPipe : '\\|',
13
+ escapedNewline : '\\n',
14
+ escapedBackSlash : '\\\\',
14
15
  scenarioOutline : ['Scenario Outline','Scenario Template'],
15
16
  word : {
16
- match : /[^ \t\n:|\\]+/,
17
+ match : /[^ \t\n\:\|\@\*]+/,
17
18
  type : moo.keywords({
18
19
  feature : 'Feature',
19
20
  examples : ['Examples','Scenarios'],
@@ -90,7 +91,17 @@ dataTable -> null {% data => [] %}
90
91
  dataTableRow -> _ %pipe dataTableColumns %newline {% data => data[2] %}
91
92
 
92
93
  dataTableColumns -> null {% data => [] %}
93
- | dataTableColumns text %pipe {% data => fp.concat(data[0],data[1].trim()) %}
94
+ | dataTableColumns dataTableColumnText %pipe {% data => fp.concat(data[0],data[1].trim()) %}
95
+
96
+ dataTableColumnText -> null {% data => '' %}
97
+ | dataTableColumnText escapedColumnCharaters {% data => data[0]+data[1] %}
98
+ | dataTableColumnText keywords {% data => data[0]+data[1] %}
99
+ | dataTableColumnText %word {% data => data[0]+data[1].value %}
100
+ | dataTableColumnText %ws {% data => data[0]+data[1].value %}
101
+
102
+ escapedColumnCharaters -> %escapedPipe {% data => '|' %}
103
+ | %escapedBackSlash {% data => '\\' %}
104
+ | %escapedNewline {% data => '\n' %}
94
105
 
95
106
  steps -> stepAndTable moreSteps {% data => fp.concat(data[0],data[1]) %}
96
107
 
@@ -106,12 +117,18 @@ stepKeyword -> %step {% (data) => { return { type : 'step', name : data[0].value
106
117
  text -> null {% data => '' %}
107
118
  | text %word {% data => data[0]+data[1].value %}
108
119
  | text %ws {% data => data[0]+data[1].value %}
109
- | text %step {% data => data[0]+data[1].value %}
110
- | text %colon {% data => data[0]+data[1].value %}
111
- | text %example {% data => data[0]+data[1].value %}
112
- | text %examples {% data => data[0]+data[1].value %}
113
- | text %scenarioOutline {% data => data[0]+data[1].value %}
114
- | text %background {% data => data[0]+data[1].value %}
120
+ | text keywords {% data => data[0]+data[1] %}
121
+ | text %pipe {% data => data[0]+data[1].value %}
122
+ | text %escapedPipe {% data => data[0]+data[1].value %}
123
+ | text %escapedNewline {% data => data[0]+data[1].value %}
124
+ | text %escapedBackSlash {% data => data[0]+data[1].value %}
125
+
126
+ keywords -> %step {% data => data[0].value %}
127
+ | %colon {% data => data[0].value %}
128
+ | %example {% data => data[0].value %}
129
+ | %examples {% data => data[0].value %}
130
+ | %scenarioOutline {% data => data[0].value %}
131
+ | %background {% data => data[0].value %}
115
132
 
116
133
  bolText -> %ws %word {% data => data[1].value %}
117
134
  | %word {% data => data[0].value %}
@@ -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 },
@@ -14,10 +13,12 @@ const lexer = moo.compile({
14
13
  colon : ':',
15
14
  step : '*',
16
15
  pipe : '|',
17
- backSlash : '\\',
16
+ escapedPipe : '\\|',
17
+ escapedNewline : '\\n',
18
+ escapedBackSlash : '\\\\',
18
19
  scenarioOutline : ['Scenario Outline','Scenario Template'],
19
20
  word : {
20
- match : /[^ \t\n:|\\]+/,
21
+ match : /[^ \t\n\:\|\@\*]+/,
21
22
  type : moo.keywords({
22
23
  feature : 'Feature',
23
24
  examples : ['Examples','Scenarios'],
@@ -78,7 +79,15 @@ var grammar = {
78
79
  {"name": "dataTable", "symbols": ["dataTable", "dataTableRow"], "postprocess": data => fp.concat(data[0],[data[1]])},
79
80
  {"name": "dataTableRow", "symbols": ["_", (lexer.has("pipe") ? {type: "pipe"} : pipe), "dataTableColumns", (lexer.has("newline") ? {type: "newline"} : newline)], "postprocess": data => data[2]},
80
81
  {"name": "dataTableColumns", "symbols": [], "postprocess": data => []},
81
- {"name": "dataTableColumns", "symbols": ["dataTableColumns", "text", (lexer.has("pipe") ? {type: "pipe"} : pipe)], "postprocess": data => fp.concat(data[0],data[1].trim())},
82
+ {"name": "dataTableColumns", "symbols": ["dataTableColumns", "dataTableColumnText", (lexer.has("pipe") ? {type: "pipe"} : pipe)], "postprocess": data => fp.concat(data[0],data[1].trim())},
83
+ {"name": "dataTableColumnText", "symbols": [], "postprocess": data => ''},
84
+ {"name": "dataTableColumnText", "symbols": ["dataTableColumnText", "escapedColumnCharaters"], "postprocess": data => data[0]+data[1]},
85
+ {"name": "dataTableColumnText", "symbols": ["dataTableColumnText", "keywords"], "postprocess": data => data[0]+data[1]},
86
+ {"name": "dataTableColumnText", "symbols": ["dataTableColumnText", (lexer.has("word") ? {type: "word"} : word)], "postprocess": data => data[0]+data[1].value},
87
+ {"name": "dataTableColumnText", "symbols": ["dataTableColumnText", (lexer.has("ws") ? {type: "ws"} : ws)], "postprocess": data => data[0]+data[1].value},
88
+ {"name": "escapedColumnCharaters", "symbols": [(lexer.has("escapedPipe") ? {type: "escapedPipe"} : escapedPipe)], "postprocess": data => '|'},
89
+ {"name": "escapedColumnCharaters", "symbols": [(lexer.has("escapedBackSlash") ? {type: "escapedBackSlash"} : escapedBackSlash)], "postprocess": data => '\\'},
90
+ {"name": "escapedColumnCharaters", "symbols": [(lexer.has("escapedNewline") ? {type: "escapedNewline"} : escapedNewline)], "postprocess": data => '\n'},
82
91
  {"name": "steps", "symbols": ["stepAndTable", "moreSteps"], "postprocess": data => fp.concat(data[0],data[1])},
83
92
  {"name": "moreSteps", "symbols": [], "postprocess": data => []},
84
93
  {"name": "moreSteps", "symbols": ["moreSteps", "stepAndTable"], "postprocess": data => fp.concat(data[0],data[1])},
@@ -89,12 +98,17 @@ var grammar = {
89
98
  {"name": "text", "symbols": [], "postprocess": data => ''},
90
99
  {"name": "text", "symbols": ["text", (lexer.has("word") ? {type: "word"} : word)], "postprocess": data => data[0]+data[1].value},
91
100
  {"name": "text", "symbols": ["text", (lexer.has("ws") ? {type: "ws"} : ws)], "postprocess": data => data[0]+data[1].value},
92
- {"name": "text", "symbols": ["text", (lexer.has("step") ? {type: "step"} : step)], "postprocess": data => data[0]+data[1].value},
93
- {"name": "text", "symbols": ["text", (lexer.has("colon") ? {type: "colon"} : colon)], "postprocess": data => data[0]+data[1].value},
94
- {"name": "text", "symbols": ["text", (lexer.has("example") ? {type: "example"} : example)], "postprocess": data => data[0]+data[1].value},
95
- {"name": "text", "symbols": ["text", (lexer.has("examples") ? {type: "examples"} : examples)], "postprocess": data => data[0]+data[1].value},
96
- {"name": "text", "symbols": ["text", (lexer.has("scenarioOutline") ? {type: "scenarioOutline"} : scenarioOutline)], "postprocess": data => data[0]+data[1].value},
97
- {"name": "text", "symbols": ["text", (lexer.has("background") ? {type: "background"} : background)], "postprocess": data => data[0]+data[1].value},
101
+ {"name": "text", "symbols": ["text", "keywords"], "postprocess": data => data[0]+data[1]},
102
+ {"name": "text", "symbols": ["text", (lexer.has("pipe") ? {type: "pipe"} : pipe)], "postprocess": data => data[0]+data[1].value},
103
+ {"name": "text", "symbols": ["text", (lexer.has("escapedPipe") ? {type: "escapedPipe"} : escapedPipe)], "postprocess": data => data[0]+data[1].value},
104
+ {"name": "text", "symbols": ["text", (lexer.has("escapedNewline") ? {type: "escapedNewline"} : escapedNewline)], "postprocess": data => data[0]+data[1].value},
105
+ {"name": "text", "symbols": ["text", (lexer.has("escapedBackSlash") ? {type: "escapedBackSlash"} : escapedBackSlash)], "postprocess": data => data[0]+data[1].value},
106
+ {"name": "keywords", "symbols": [(lexer.has("step") ? {type: "step"} : step)], "postprocess": data => data[0].value},
107
+ {"name": "keywords", "symbols": [(lexer.has("colon") ? {type: "colon"} : colon)], "postprocess": data => data[0].value},
108
+ {"name": "keywords", "symbols": [(lexer.has("example") ? {type: "example"} : example)], "postprocess": data => data[0].value},
109
+ {"name": "keywords", "symbols": [(lexer.has("examples") ? {type: "examples"} : examples)], "postprocess": data => data[0].value},
110
+ {"name": "keywords", "symbols": [(lexer.has("scenarioOutline") ? {type: "scenarioOutline"} : scenarioOutline)], "postprocess": data => data[0].value},
111
+ {"name": "keywords", "symbols": [(lexer.has("background") ? {type: "background"} : background)], "postprocess": data => data[0].value},
98
112
  {"name": "bolText", "symbols": [(lexer.has("ws") ? {type: "ws"} : ws), (lexer.has("word") ? {type: "word"} : word)], "postprocess": data => data[1].value},
99
113
  {"name": "bolText", "symbols": [(lexer.has("word") ? {type: "word"} : word)], "postprocess": data => data[0].value},
100
114
  {"name": "freeform", "symbols": [], "postprocess": data => ''},
package/src/index.js CHANGED
@@ -4,6 +4,7 @@ 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';
7
8
 
8
9
  const featureRegex = /\.feature$/;
9
10
 
@@ -12,8 +13,6 @@ const compileFeatureToJS = (config,featureSrc) => {
12
13
 
13
14
  const code = generateFeature(config,feature);
14
15
 
15
- log.debug(code);
16
-
17
16
  return code;
18
17
  }
19
18
 
@@ -47,15 +46,20 @@ export default function vitestCucumberPlugin() {
47
46
  if (_.has('test.cucumber.logLevel',resolvedConfig)) {
48
47
  setLogLevel(resolvedConfig.test.cucumber.logLevel);
49
48
  }
50
- log.debug('config: resolvedConfig:'+JSON.stringify(resolvedConfig,null,2));
49
+
51
50
  config = _.get('test.cucumber',resolvedConfig);
52
51
  config = _.set('root',resolvedConfig.root,config);
52
+
53
+ config = _.set('tagsFunction',tagsFunction(_.get('tags',config)),config);
54
+
53
55
  log.debug('config: '+JSON.stringify(config));
54
56
  },
55
57
  transform : async (src,id) => {
56
58
  if (featureRegex.test(id)) {
57
59
  const code = compileFeatureToJS(config,src);
58
60
 
61
+ log.debug('transform '+id+' -> '+code);
62
+
59
63
  return {
60
64
  code
61
65
  }
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
+