vitest-cucumber-plugin 0.1.7 → 0.5.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 CHANGED
@@ -106,10 +106,3 @@ Then('I should be told {string}', function (state,[ answer ], dataTable) {
106
106
 
107
107
  Currently, all step definition files must be in ECMAScript module format. CommonJS files might
108
108
  work, but this configuration isn't tested.
109
-
110
-
111
- ### Not yet implemented
112
-
113
- This plugin is not yet feature complete. Here is the list of features from Cucumber which aren't yet implemented:
114
- * Rule keyword
115
- * Doc strings
package/RELEASE_NOTES.md CHANGED
@@ -1,3 +1,5 @@
1
+ * v0.5.0 : Implemented Doc Strings. Plugin is now feature complete.
2
+ * v0.1.8 : Implemented Rule keyword
1
3
  * v0.1.7 : Implemented Hooks API
2
4
  * v0.1.6 : Implemented tags boolean expression support
3
5
  * v0.1.5 : Implemented escape characters for Data Tables
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vitest-cucumber-plugin",
3
- "version": "0.1.7",
3
+ "version": "0.5.0",
4
4
  "description": "Plugin for Vitest which allows for tests to be written in Cucumber format.",
5
5
  "keywords": [
6
6
  "vite",
@@ -1,6 +1,6 @@
1
1
  import _ from 'lodash/fp.js';
2
2
  import { log } from '../logger.js';
3
- import { generateExample, generateScenarioOutline } from './index.js';
3
+ import { generateExample, generateScenarioOutline, generateRule } from './index.js';
4
4
  import { escape, shouldSkip } from './util.js';
5
5
 
6
6
  export const generateFeature = (config,feature) => {
@@ -18,6 +18,8 @@ export const generateFeature = (config,feature) => {
18
18
  return testStatements + generateExample(config,statement);
19
19
  } else if (statement.type.type === 'scenarioOutline') {
20
20
  return testStatements + generateScenarioOutline(config,statement);
21
+ } else if (statement.type.type === 'rule') {
22
+ return testStatements + generateRule(config,statement);
21
23
  }
22
24
  },'')(statements);
23
25
 
@@ -3,11 +3,13 @@ import { generateExample } from './example.js';
3
3
  import { generateExamples } from './examples.js';
4
4
  import { generateScenarioOutline } from './scenario-outline.js';
5
5
  import { generateFeature } from './feature.js';
6
+ import { generateRule } from './rule.js';
6
7
 
7
8
  export {
8
9
  generateTests,
9
10
  generateExample,
10
11
  generateExamples,
11
12
  generateScenarioOutline,
12
- generateFeature
13
+ generateFeature,
14
+ generateRule,
13
15
  };
@@ -0,0 +1,22 @@
1
+ import _ from 'lodash/fp.js';
2
+ import { generateExample } from './index.js';
3
+ import { escape, shouldSkip } from './util.js';
4
+ import { log } from '../logger.js';
5
+
6
+ export const generateRule = (config,rule) => {
7
+ log.debug('generateRule config: '+JSON.stringify(config)+' rule: '+JSON.stringify(rule));
8
+
9
+ const examplesCode = _.reduce((examplesCode,example) => {
10
+ return examplesCode + generateExample(config,example);
11
+ },'')(rule.examples);
12
+
13
+ const skip = shouldSkip(config,rule.tags) ? '.skip' : '';
14
+ const tagsStr = JSON.stringify(rule.tags);
15
+
16
+ const code = ` // tags : ${tagsStr}
17
+ describe${skip}('${escape(rule.type.name)}: ${escape(rule.name)}', () => {
18
+ ${examplesCode}});
19
+ `;
20
+
21
+ return code;
22
+ }
package/src/gherkin.js CHANGED
@@ -26,6 +26,7 @@ var gherkin_umd$1 = {exports: {}};
26
26
  escapedNewline : '\\n',
27
27
  escapedBackSlash : '\\\\',
28
28
  scenarioOutline : ['Scenario Outline','Scenario Template'],
29
+ docString : ['```','"""'],
29
30
  word : {
30
31
  match : /[^ \t\n\:\|\@\*]+/,
31
32
  type : moo.keywords({
@@ -34,9 +35,17 @@ var gherkin_umd$1 = {exports: {}};
34
35
  step : ['Given','When','Then','And','But'],
35
36
  example : ['Example','Scenario'],
36
37
  background : 'Background',
38
+ rule : 'Rule',
37
39
  }),
38
40
  },
39
41
  });
42
+
43
+ const trimWhitespace = (cols,str) => {
44
+ const lines = str.split('\n').slice(0,-1);
45
+ return fp.reduce((s,line) => {
46
+ return s+line.slice(cols)+'\n'
47
+ },'')(lines);
48
+ };
40
49
  var grammar = {
41
50
  Lexer: lexer,
42
51
  ParserRules: [
@@ -61,6 +70,7 @@ var gherkin_umd$1 = {exports: {}};
61
70
  },
62
71
  {"name": "statement", "symbols": ["example"], "postprocess": data => data[0]},
63
72
  {"name": "statement", "symbols": ["scenarioOutline"], "postprocess": data => data[0]},
73
+ {"name": "statement", "symbols": ["rule"], "postprocess": data => data[0]},
64
74
  {"name": "statements", "symbols": [], "postprocess": data => []},
65
75
  {"name": "statements", "symbols": ["statements", "statement"], "postprocess": data => fp.concat(data[0],data[1])},
66
76
  {"name": "example", "symbols": ["tags", "exampleStatement", "steps"], "postprocess": (data) => fp.assign(data[1],{ tags : data[0], steps : data[2] })},
@@ -68,6 +78,8 @@ var gherkin_umd$1 = {exports: {}};
68
78
  (data) => { return { type : { type : 'example', name : data[1] }, name : data[4].trim() } }
69
79
  },
70
80
  {"name": "exampleKeyword", "symbols": [(lexer.has("example") ? {type: "example"} : example)], "postprocess": data => data[0].value},
81
+ {"name": "exampleList", "symbols": [], "postprocess": data => []},
82
+ {"name": "exampleList", "symbols": ["exampleList", "example"], "postprocess": data => fp.concat(data[0],data[1])},
71
83
  {"name": "scenarioOutline", "symbols": ["tags", "scenarioOutlineStatement", "steps", "examplesList"], "postprocess":
72
84
  data => fp.assign(data[1],{ tags : data[0], steps : data[2], examples : data[3] })
73
85
  },
@@ -75,6 +87,13 @@ var gherkin_umd$1 = {exports: {}};
75
87
  (data) => { return { type : { type : 'scenarioOutline', name : data[1] }, name : data[4].trim() } }
76
88
  },
77
89
  {"name": "scenarioOutlineKeyword", "symbols": [(lexer.has("scenarioOutline") ? {type: "scenarioOutline"} : scenarioOutline)], "postprocess": data => data[0].value},
90
+ {"name": "rule", "symbols": ["tags", "ruleStatement", "example", "exampleList"], "postprocess":
91
+ data => fp.assign(data[1],{ tags : data[0], examples : fp.concat(data[2],data[3]) })
92
+ },
93
+ {"name": "ruleStatement", "symbols": ["_", "ruleKeyword", "_", (lexer.has("colon") ? {type: "colon"} : colon), "text", (lexer.has("newline") ? {type: "newline"} : newline)], "postprocess":
94
+ (data) => { return { type : { type : 'rule', name : data[1] }, name : data[4].trim() } }
95
+ },
96
+ {"name": "ruleKeyword", "symbols": [(lexer.has("rule") ? {type: "rule"} : rule)], "postprocess": data => data[0].value},
78
97
  {"name": "examplesList", "symbols": [], "postprocess": data => []},
79
98
  {"name": "examplesList", "symbols": ["examplesList", "examples"], "postprocess": data => fp.concat(data[0],data[1])},
80
99
  {"name": "examples", "symbols": ["tags", "examplesStatement", "dataTable", "emptyLines"], "postprocess":
@@ -84,7 +103,7 @@ var gherkin_umd$1 = {exports: {}};
84
103
  (data) => { return { type : { type : 'examples', name : data[1] }, name : data[4] } }
85
104
  },
86
105
  {"name": "examplesKeyword", "symbols": [(lexer.has("examples") ? {type: "examples"} : examples)], "postprocess": data => data[0].value},
87
- {"name": "dataTable", "symbols": [], "postprocess": data => []},
106
+ {"name": "dataTable", "symbols": ["dataTableRow"], "postprocess": data => [data[0]]},
88
107
  {"name": "dataTable", "symbols": ["dataTable", "dataTableRow"], "postprocess": data => fp.concat(data[0],[data[1]])},
89
108
  {"name": "dataTableRow", "symbols": ["_", (lexer.has("pipe") ? {type: "pipe"} : pipe), "dataTableColumns", (lexer.has("newline") ? {type: "newline"} : newline)], "postprocess": data => data[2]},
90
109
  {"name": "dataTableColumns", "symbols": [], "postprocess": data => []},
@@ -97,12 +116,14 @@ var gherkin_umd$1 = {exports: {}};
97
116
  {"name": "escapedColumnCharaters", "symbols": [(lexer.has("escapedPipe") ? {type: "escapedPipe"} : escapedPipe)], "postprocess": data => '|'},
98
117
  {"name": "escapedColumnCharaters", "symbols": [(lexer.has("escapedBackSlash") ? {type: "escapedBackSlash"} : escapedBackSlash)], "postprocess": data => '\\'},
99
118
  {"name": "escapedColumnCharaters", "symbols": [(lexer.has("escapedNewline") ? {type: "escapedNewline"} : escapedNewline)], "postprocess": data => '\n'},
100
- {"name": "steps", "symbols": ["stepAndTable", "moreSteps"], "postprocess": data => fp.concat(data[0],data[1])},
119
+ {"name": "steps", "symbols": ["step", "moreSteps"], "postprocess": data => fp.concat(data[0],data[1])},
101
120
  {"name": "moreSteps", "symbols": [], "postprocess": data => []},
102
- {"name": "moreSteps", "symbols": ["moreSteps", "stepAndTable"], "postprocess": data => fp.concat(data[0],data[1])},
121
+ {"name": "moreSteps", "symbols": ["moreSteps", "step"], "postprocess": data => fp.concat(data[0],data[1])},
103
122
  {"name": "moreSteps", "symbols": ["moreSteps", (lexer.has("emptyLine") ? {type: "emptyLine"} : emptyLine)], "postprocess": data => data[0]},
104
- {"name": "step", "symbols": ["_", "stepKeyword", "text", (lexer.has("newline") ? {type: "newline"} : newline)], "postprocess": data => { return { type : data[1], text : data[2].trim() } }},
105
- {"name": "stepAndTable", "symbols": ["step", "dataTable"], "postprocess": data => fp.set('dataTable',data[1],data[0])},
123
+ {"name": "step", "symbols": ["stepStatement"]},
124
+ {"name": "step", "symbols": ["stepStatement", "dataTable"], "postprocess": data => fp.set('dataTable',data[1],data[0])},
125
+ {"name": "step", "symbols": ["stepStatement", "docString"], "postprocess": data => fp.set('docString',data[1],data[0])},
126
+ {"name": "stepStatement", "symbols": ["_", "stepKeyword", "text", (lexer.has("newline") ? {type: "newline"} : newline)], "postprocess": data => { return { type : data[1], text : data[2].trim() } }},
106
127
  {"name": "stepKeyword", "symbols": [(lexer.has("step") ? {type: "step"} : step)], "postprocess": (data) => { return { type : 'step', name : data[0].value } }},
107
128
  {"name": "text", "symbols": [], "postprocess": data => ''},
108
129
  {"name": "text", "symbols": ["text", (lexer.has("word") ? {type: "word"} : word)], "postprocess": data => data[0]+data[1].value},
@@ -126,6 +147,18 @@ var gherkin_umd$1 = {exports: {}};
126
147
  }
127
148
  },
128
149
  {"name": "freeform", "symbols": ["freeform", (lexer.has("emptyLine") ? {type: "emptyLine"} : emptyLine)], "postprocess": data => data[0]+'\n'},
150
+ {"name": "docString", "symbols": ["docStringStatement", "docText", "docStringStatement"], "postprocess":
151
+ data => fp.set('text',trimWhitespace(data[0].ws.length,data[1]),data[0])
152
+ },
153
+ {"name": "docStringStatement", "symbols": ["_", (lexer.has("docString") ? {type: "docString"} : docString), "contentType", (lexer.has("newline") ? {type: "newline"} : newline)], "postprocess":
154
+ (data) => { return { type : { type : 'docString', name : data[1].value }, ws : data[0], contentType : data[2] } }
155
+ },
156
+ {"name": "contentType", "symbols": [], "postprocess": data => null},
157
+ {"name": "contentType", "symbols": [(lexer.has("ws") ? {type: "ws"} : ws)], "postprocess": data => null},
158
+ {"name": "contentType", "symbols": [(lexer.has("word") ? {type: "word"} : word)], "postprocess": data => data[0].value},
159
+ {"name": "docText", "symbols": [], "postprocess": data => ''},
160
+ {"name": "docText", "symbols": ["docText", "text", (lexer.has("newline") ? {type: "newline"} : newline)], "postprocess": data => data[0]+data[1]+data[2].value},
161
+ {"name": "docText", "symbols": ["docText", (lexer.has("emptyLine") ? {type: "emptyLine"} : emptyLine)], "postprocess": data => data[0]+data[1].value},
129
162
  {"name": "_", "symbols": [], "postprocess": data => ''},
130
163
  {"name": "_", "symbols": [(lexer.has("ws") ? {type: "ws"} : ws)], "postprocess": data => data[0].value},
131
164
  {"name": "emptyLines", "symbols": [], "postprocess": data => ''},
package/src/gherkin.ne CHANGED
@@ -13,6 +13,7 @@ const lexer = moo.compile({
13
13
  escapedNewline : '\\n',
14
14
  escapedBackSlash : '\\\\',
15
15
  scenarioOutline : ['Scenario Outline','Scenario Template'],
16
+ docString : ['```','"""'],
16
17
  word : {
17
18
  match : /[^ \t\n\:\|\@\*]+/,
18
19
  type : moo.keywords({
@@ -21,9 +22,17 @@ const lexer = moo.compile({
21
22
  step : ['Given','When','Then','And','But'],
22
23
  example : ['Example','Scenario'],
23
24
  background : 'Background',
25
+ rule : 'Rule',
24
26
  }),
25
27
  },
26
28
  });
29
+
30
+ const trimWhitespace = (cols,str) => {
31
+ const lines = str.split('\n').slice(0,-1);
32
+ return fp.reduce((s,line) => {
33
+ return s+line.slice(cols)+'\n'
34
+ },'')(lines);
35
+ };
27
36
  %}
28
37
 
29
38
  @lexer lexer
@@ -56,6 +65,7 @@ backgroundStatement -> _ %background _ %colon text %newline {%
56
65
 
57
66
  statement -> example {% data => data[0] %}
58
67
  | scenarioOutline {% data => data[0] %}
68
+ | rule {% data => data[0] %}
59
69
 
60
70
  statements -> null {% data => [] %}
61
71
  | statements statement {% data => fp.concat(data[0],data[1]) %}
@@ -66,6 +76,9 @@ exampleStatement -> _ exampleKeyword _ %colon text %newline {%
66
76
  %}
67
77
  exampleKeyword -> %example {% data => data[0].value %}
68
78
 
79
+ exampleList -> null {% data => [] %}
80
+ | exampleList example {% data => fp.concat(data[0],data[1]) %}
81
+
69
82
  scenarioOutline -> tags scenarioOutlineStatement steps examplesList {%
70
83
  data => fp.assign(data[1],{ tags : data[0], steps : data[2], examples : data[3] })
71
84
  %}
@@ -74,6 +87,14 @@ scenarioOutlineStatement -> _ scenarioOutlineKeyword _ %colon text %newline {%
74
87
  %}
75
88
  scenarioOutlineKeyword -> %scenarioOutline {% data => data[0].value %}
76
89
 
90
+ rule -> tags ruleStatement example exampleList {%
91
+ data => fp.assign(data[1],{ tags : data[0], examples : fp.concat(data[2],data[3]) })
92
+ %}
93
+ ruleStatement -> _ ruleKeyword _ %colon text %newline {%
94
+ (data) => { return { type : { type : 'rule', name : data[1] }, name : data[4].trim() } }
95
+ %}
96
+ ruleKeyword -> %rule {% data => data[0].value %}
97
+
77
98
  examplesList -> null {% data => [] %}
78
99
  | examplesList examples {% data => fp.concat(data[0],data[1]) %}
79
100
 
@@ -85,7 +106,7 @@ examplesStatement -> _ examplesKeyword _ %colon text %newline {%
85
106
  %}
86
107
  examplesKeyword -> %examples {% data => data[0].value %}
87
108
 
88
- dataTable -> null {% data => [] %}
109
+ dataTable -> dataTableRow {% data => [data[0]] %}
89
110
  | dataTable dataTableRow {% data => fp.concat(data[0],[data[1]]) %}
90
111
 
91
112
  dataTableRow -> _ %pipe dataTableColumns %newline {% data => data[2] %}
@@ -103,14 +124,17 @@ escapedColumnCharaters -> %escapedPipe {% data => '|' %}
103
124
  | %escapedBackSlash {% data => '\\' %}
104
125
  | %escapedNewline {% data => '\n' %}
105
126
 
106
- steps -> stepAndTable moreSteps {% data => fp.concat(data[0],data[1]) %}
127
+ steps -> step moreSteps {% data => fp.concat(data[0],data[1]) %}
107
128
 
108
129
  moreSteps -> null {% data => [] %}
109
- | moreSteps stepAndTable {% data => fp.concat(data[0],data[1]) %}
130
+ | moreSteps step {% data => fp.concat(data[0],data[1]) %}
110
131
  | moreSteps %emptyLine {% data => data[0] %}
111
132
 
112
- step -> _ stepKeyword text %newline {% data => { return { type : data[1], text : data[2].trim() } } %}
113
- stepAndTable -> step dataTable {% data => fp.set('dataTable',data[1],data[0]) %}
133
+ step -> stepStatement
134
+ | stepStatement dataTable {% data => fp.set('dataTable',data[1],data[0]) %}
135
+ | stepStatement docString {% data => fp.set('docString',data[1],data[0]) %}
136
+
137
+ stepStatement -> _ stepKeyword text %newline {% data => { return { type : data[1], text : data[2].trim() } } %}
114
138
 
115
139
  stepKeyword -> %step {% (data) => { return { type : 'step', name : data[0].value } } %}
116
140
 
@@ -140,6 +164,21 @@ freeform -> null {% data => '' %}
140
164
  %}
141
165
  | freeform %emptyLine {% data => data[0]+'\n' %}
142
166
 
167
+ docString -> docStringStatement docText docStringStatement {%
168
+ data => fp.set('text',trimWhitespace(data[0].ws.length,data[1]),data[0])
169
+ %}
170
+ docStringStatement -> _ %docString contentType %newline {%
171
+ (data) => { return { type : { type : 'docString', name : data[1].value }, ws : data[0], contentType : data[2] } }
172
+ %}
173
+
174
+ contentType -> null {% data => null %}
175
+ | %ws {% data => null %}
176
+ | %word {% data => data[0].value %}
177
+
178
+ docText -> null {% data => '' %}
179
+ | docText text %newline {% data => data[0]+data[1]+data[2].value %}
180
+ | docText %emptyLine {% data => data[0]+data[1].value %}
181
+
143
182
  _ -> null {% data => '' %}
144
183
  | %ws {% data => data[0].value %}
145
184
 
@@ -17,6 +17,7 @@ const lexer = moo.compile({
17
17
  escapedNewline : '\\n',
18
18
  escapedBackSlash : '\\\\',
19
19
  scenarioOutline : ['Scenario Outline','Scenario Template'],
20
+ docString : ['```','"""'],
20
21
  word : {
21
22
  match : /[^ \t\n\:\|\@\*]+/,
22
23
  type : moo.keywords({
@@ -25,9 +26,17 @@ const lexer = moo.compile({
25
26
  step : ['Given','When','Then','And','But'],
26
27
  example : ['Example','Scenario'],
27
28
  background : 'Background',
29
+ rule : 'Rule',
28
30
  }),
29
31
  },
30
32
  });
33
+
34
+ const trimWhitespace = (cols,str) => {
35
+ const lines = str.split('\n').slice(0,-1);
36
+ return fp.reduce((s,line) => {
37
+ return s+line.slice(cols)+'\n'
38
+ },'')(lines);
39
+ };
31
40
  var grammar = {
32
41
  Lexer: lexer,
33
42
  ParserRules: [
@@ -52,6 +61,7 @@ var grammar = {
52
61
  },
53
62
  {"name": "statement", "symbols": ["example"], "postprocess": data => data[0]},
54
63
  {"name": "statement", "symbols": ["scenarioOutline"], "postprocess": data => data[0]},
64
+ {"name": "statement", "symbols": ["rule"], "postprocess": data => data[0]},
55
65
  {"name": "statements", "symbols": [], "postprocess": data => []},
56
66
  {"name": "statements", "symbols": ["statements", "statement"], "postprocess": data => fp.concat(data[0],data[1])},
57
67
  {"name": "example", "symbols": ["tags", "exampleStatement", "steps"], "postprocess": (data) => fp.assign(data[1],{ tags : data[0], steps : data[2] })},
@@ -59,6 +69,8 @@ var grammar = {
59
69
  (data) => { return { type : { type : 'example', name : data[1] }, name : data[4].trim() } }
60
70
  },
61
71
  {"name": "exampleKeyword", "symbols": [(lexer.has("example") ? {type: "example"} : example)], "postprocess": data => data[0].value},
72
+ {"name": "exampleList", "symbols": [], "postprocess": data => []},
73
+ {"name": "exampleList", "symbols": ["exampleList", "example"], "postprocess": data => fp.concat(data[0],data[1])},
62
74
  {"name": "scenarioOutline", "symbols": ["tags", "scenarioOutlineStatement", "steps", "examplesList"], "postprocess":
63
75
  data => fp.assign(data[1],{ tags : data[0], steps : data[2], examples : data[3] })
64
76
  },
@@ -66,6 +78,13 @@ var grammar = {
66
78
  (data) => { return { type : { type : 'scenarioOutline', name : data[1] }, name : data[4].trim() } }
67
79
  },
68
80
  {"name": "scenarioOutlineKeyword", "symbols": [(lexer.has("scenarioOutline") ? {type: "scenarioOutline"} : scenarioOutline)], "postprocess": data => data[0].value},
81
+ {"name": "rule", "symbols": ["tags", "ruleStatement", "example", "exampleList"], "postprocess":
82
+ data => fp.assign(data[1],{ tags : data[0], examples : fp.concat(data[2],data[3]) })
83
+ },
84
+ {"name": "ruleStatement", "symbols": ["_", "ruleKeyword", "_", (lexer.has("colon") ? {type: "colon"} : colon), "text", (lexer.has("newline") ? {type: "newline"} : newline)], "postprocess":
85
+ (data) => { return { type : { type : 'rule', name : data[1] }, name : data[4].trim() } }
86
+ },
87
+ {"name": "ruleKeyword", "symbols": [(lexer.has("rule") ? {type: "rule"} : rule)], "postprocess": data => data[0].value},
69
88
  {"name": "examplesList", "symbols": [], "postprocess": data => []},
70
89
  {"name": "examplesList", "symbols": ["examplesList", "examples"], "postprocess": data => fp.concat(data[0],data[1])},
71
90
  {"name": "examples", "symbols": ["tags", "examplesStatement", "dataTable", "emptyLines"], "postprocess":
@@ -75,7 +94,7 @@ var grammar = {
75
94
  (data) => { return { type : { type : 'examples', name : data[1] }, name : data[4] } }
76
95
  },
77
96
  {"name": "examplesKeyword", "symbols": [(lexer.has("examples") ? {type: "examples"} : examples)], "postprocess": data => data[0].value},
78
- {"name": "dataTable", "symbols": [], "postprocess": data => []},
97
+ {"name": "dataTable", "symbols": ["dataTableRow"], "postprocess": data => [data[0]]},
79
98
  {"name": "dataTable", "symbols": ["dataTable", "dataTableRow"], "postprocess": data => fp.concat(data[0],[data[1]])},
80
99
  {"name": "dataTableRow", "symbols": ["_", (lexer.has("pipe") ? {type: "pipe"} : pipe), "dataTableColumns", (lexer.has("newline") ? {type: "newline"} : newline)], "postprocess": data => data[2]},
81
100
  {"name": "dataTableColumns", "symbols": [], "postprocess": data => []},
@@ -88,12 +107,14 @@ var grammar = {
88
107
  {"name": "escapedColumnCharaters", "symbols": [(lexer.has("escapedPipe") ? {type: "escapedPipe"} : escapedPipe)], "postprocess": data => '|'},
89
108
  {"name": "escapedColumnCharaters", "symbols": [(lexer.has("escapedBackSlash") ? {type: "escapedBackSlash"} : escapedBackSlash)], "postprocess": data => '\\'},
90
109
  {"name": "escapedColumnCharaters", "symbols": [(lexer.has("escapedNewline") ? {type: "escapedNewline"} : escapedNewline)], "postprocess": data => '\n'},
91
- {"name": "steps", "symbols": ["stepAndTable", "moreSteps"], "postprocess": data => fp.concat(data[0],data[1])},
110
+ {"name": "steps", "symbols": ["step", "moreSteps"], "postprocess": data => fp.concat(data[0],data[1])},
92
111
  {"name": "moreSteps", "symbols": [], "postprocess": data => []},
93
- {"name": "moreSteps", "symbols": ["moreSteps", "stepAndTable"], "postprocess": data => fp.concat(data[0],data[1])},
112
+ {"name": "moreSteps", "symbols": ["moreSteps", "step"], "postprocess": data => fp.concat(data[0],data[1])},
94
113
  {"name": "moreSteps", "symbols": ["moreSteps", (lexer.has("emptyLine") ? {type: "emptyLine"} : emptyLine)], "postprocess": data => data[0]},
95
- {"name": "step", "symbols": ["_", "stepKeyword", "text", (lexer.has("newline") ? {type: "newline"} : newline)], "postprocess": data => { return { type : data[1], text : data[2].trim() } }},
96
- {"name": "stepAndTable", "symbols": ["step", "dataTable"], "postprocess": data => fp.set('dataTable',data[1],data[0])},
114
+ {"name": "step", "symbols": ["stepStatement"]},
115
+ {"name": "step", "symbols": ["stepStatement", "dataTable"], "postprocess": data => fp.set('dataTable',data[1],data[0])},
116
+ {"name": "step", "symbols": ["stepStatement", "docString"], "postprocess": data => fp.set('docString',data[1],data[0])},
117
+ {"name": "stepStatement", "symbols": ["_", "stepKeyword", "text", (lexer.has("newline") ? {type: "newline"} : newline)], "postprocess": data => { return { type : data[1], text : data[2].trim() } }},
97
118
  {"name": "stepKeyword", "symbols": [(lexer.has("step") ? {type: "step"} : step)], "postprocess": (data) => { return { type : 'step', name : data[0].value } }},
98
119
  {"name": "text", "symbols": [], "postprocess": data => ''},
99
120
  {"name": "text", "symbols": ["text", (lexer.has("word") ? {type: "word"} : word)], "postprocess": data => data[0]+data[1].value},
@@ -117,6 +138,18 @@ var grammar = {
117
138
  }
118
139
  },
119
140
  {"name": "freeform", "symbols": ["freeform", (lexer.has("emptyLine") ? {type: "emptyLine"} : emptyLine)], "postprocess": data => data[0]+'\n'},
141
+ {"name": "docString", "symbols": ["docStringStatement", "docText", "docStringStatement"], "postprocess":
142
+ data => fp.set('text',trimWhitespace(data[0].ws.length,data[1]),data[0])
143
+ },
144
+ {"name": "docStringStatement", "symbols": ["_", (lexer.has("docString") ? {type: "docString"} : docString), "contentType", (lexer.has("newline") ? {type: "newline"} : newline)], "postprocess":
145
+ (data) => { return { type : { type : 'docString', name : data[1].value }, ws : data[0], contentType : data[2] } }
146
+ },
147
+ {"name": "contentType", "symbols": [], "postprocess": data => null},
148
+ {"name": "contentType", "symbols": [(lexer.has("ws") ? {type: "ws"} : ws)], "postprocess": data => null},
149
+ {"name": "contentType", "symbols": [(lexer.has("word") ? {type: "word"} : word)], "postprocess": data => data[0].value},
150
+ {"name": "docText", "symbols": [], "postprocess": data => ''},
151
+ {"name": "docText", "symbols": ["docText", "text", (lexer.has("newline") ? {type: "newline"} : newline)], "postprocess": data => data[0]+data[1]+data[2].value},
152
+ {"name": "docText", "symbols": ["docText", (lexer.has("emptyLine") ? {type: "emptyLine"} : emptyLine)], "postprocess": data => data[0]+data[1].value},
120
153
  {"name": "_", "symbols": [], "postprocess": data => ''},
121
154
  {"name": "_", "symbols": [(lexer.has("ws") ? {type: "ws"} : ws)], "postprocess": data => data[0].value},
122
155
  {"name": "emptyLines", "symbols": [], "postprocess": data => ''},
package/src/index.js CHANGED
@@ -45,7 +45,9 @@ export const Test = (state,step) => {
45
45
  log.debug('Test step: '+JSON.stringify(step)+' state:'+JSON.stringify(state));
46
46
  const stepDefinitionMatch = findStepDefinitionMatch(step);
47
47
 
48
- const newState = stepDefinitionMatch.stepDefinition.f(state,stepDefinitionMatch.parameters,step.dataTable);
48
+ const extraData = step.dataTable ? step.dataTable : (step.docString ? step.docString.text : null );
49
+
50
+ const newState = stepDefinitionMatch.stepDefinition.f(state,stepDefinitionMatch.parameters,extraData);
49
51
  log.debug('Test newState: '+JSON.stringify(newState));
50
52
 
51
53
  return newState;
@@ -0,0 +1,21 @@
1
+ Feature: Doc Strings
2
+ Scenario: You should be able to use Doc Strings with Given, When and Then statements
3
+ Given the following doc string:
4
+ """markdown
5
+ This is some cool text.
6
+
7
+ It is fun.
8
+ """
9
+
10
+ When the following doc string is appended:
11
+ ```
12
+ This is more fun.
13
+ ```
14
+
15
+ Then final doc string will look like this:
16
+ """
17
+ This is some cool text.
18
+
19
+ It is fun.
20
+ This is more fun.
21
+ """
@@ -0,0 +1,15 @@
1
+ import { Given, When, Then, DataTable } from 'vitest-cucumber-plugin';
2
+ import { expect } from 'vitest'
3
+ import _ from 'lodash/fp';
4
+
5
+ Given('the following doc string:',(state,params,docString) => {
6
+ return _.set('docString',docString,state);
7
+ });
8
+
9
+ When('the following doc string is appended:',(state,params,docString) => {
10
+ return _.set('docString',_.getOr('','docString',state)+docString,state);
11
+ });
12
+
13
+ Then('final doc string will look like this:',(state,params,docString) => {
14
+ expect(docString).toEqual(_.get('docString',state));
15
+ });