@suffolklitlab/alkiln 3.0.9

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 (40) hide show
  1. package/.github/workflows/test_tests.yml +77 -0
  2. package/CHANGELOG.md +381 -0
  3. package/README.md +18 -0
  4. package/action.yml +158 -0
  5. package/lib/DOM.md.html +63 -0
  6. package/lib/github_integration/install-branch.js +84 -0
  7. package/lib/github_integration/puppeteer-utils.js +224 -0
  8. package/lib/github_integration/setup.js +4 -0
  9. package/lib/github_integration/takedown.js +4 -0
  10. package/lib/index.js +2 -0
  11. package/lib/scope.js +1632 -0
  12. package/lib/steps.js +878 -0
  13. package/lib/utils/env_vars.js +173 -0
  14. package/lib/utils/langs.js +51 -0
  15. package/lib/world.js +10 -0
  16. package/package.json +53 -0
  17. package/tests/features/assembly_line.feature +43 -0
  18. package/tests/features/establishing_steps.feature +22 -0
  19. package/tests/features/example_test.feature +11 -0
  20. package/tests/features/interactive_steps.feature +85 -0
  21. package/tests/features/observation_steps.feature +97 -0
  22. package/tests/features/reports.feature +482 -0
  23. package/tests/features/some_png_1.png +0 -0
  24. package/tests/features/some_png_2.png +0 -0
  25. package/tests/features/story_table_formats.feature +77 -0
  26. package/tests/features/story_tables.feature +88 -0
  27. package/tests/unit_tests/ensureSpecialRows.test.js +34 -0
  28. package/tests/unit_tests/env_vars.test.js +53 -0
  29. package/tests/unit_tests/fields.fixtures.js +904 -0
  30. package/tests/unit_tests/getAllFields.test.js +142 -0
  31. package/tests/unit_tests/getMatchingRows.test.js +261 -0
  32. package/tests/unit_tests/getSafeScenarioBaseFilename.fixtures.js +12 -0
  33. package/tests/unit_tests/getSafeScenarioBaseFilename.test.js +62 -0
  34. package/tests/unit_tests/getSafeScenarioFilename.test.js +83 -0
  35. package/tests/unit_tests/html.fixtures.js +861 -0
  36. package/tests/unit_tests/matches.fixtures.js +168 -0
  37. package/tests/unit_tests/names.fixtures.js +35 -0
  38. package/tests/unit_tests/normalizeTable.test.js +22 -0
  39. package/tests/unit_tests/special_rows.fixtures.js +101 -0
  40. package/tests/unit_tests/tables.fixtures.js +428 -0
@@ -0,0 +1,142 @@
1
+ const chai = require('chai');
2
+ const expect = chai.expect;
3
+ // We need jest or something, right? To do fancy stuff.
4
+
5
+ const html = require('./html.fixtures.js');
6
+ const fields = require('./fields.fixtures.js');
7
+ const scope = require('../../lib/scope.js');
8
+ const getAllFields = scope.getAllFields;
9
+ // TODO: Rearrange fixtures so related fixtures are next to each other? e.g.
10
+ // buttons_yesno.html, buttons_yesno.fields, buttons_yesno.table, buttons_yesno.matches
11
+ // May make more files both to make and to import, but may be more useful
12
+ // for editing, maintaining, and clarity.
13
+
14
+
15
+ /* Test `scope.getAllFields()`. Discuss: If we do a good job outlining
16
+ * what behvior the main tests cover, then we might not need to test
17
+ * each individual function separately.
18
+ *
19
+ * NOTE: scope.getField should only be concerned with the stuff in `#daquestion`
20
+ */
21
+
22
+ // ============================
23
+ // Standard fields - no proxies
24
+ // ============================
25
+ // TODO: Add more complex fields. E.g `object_checkboxes` and dropdown with `object`.
26
+
27
+ // TODO: Add notes detailing what behavior each test covers, including the
28
+ // behavior in sub-functions if they are not tested independently
29
+ it(`creates the right data for standard fields`, async function() {
30
+ // 18 fields (03/15/21)
31
+ let result = await getAllFields( scope, { html: html.standard });
32
+ expect( result ).to.deep.equal( fields.standard );
33
+ });
34
+
35
+
36
+ // ============================
37
+ // Simple show if fields - no proxies
38
+ // ============================
39
+ it(`creates the right data for 'show if' fields`, async function() {
40
+ let result = await getAllFields( scope, { html: html.show_if });
41
+ expect( result ).to.deep.equal( fields.show_if );
42
+ });
43
+
44
+
45
+ // ============================
46
+ // Buttons
47
+ // ============================
48
+ it(`creates the right data for one continue button`, async function() {
49
+ // `continue button field:`
50
+ let result = await getAllFields( scope, { html: html.button_continue });
51
+ expect( result ).to.deep.equal( fields.button_continue );
52
+ });
53
+
54
+ it(`creates the right data for yesnomaybe buttons`, async function() {
55
+ // `yesnomaybe:`
56
+ let result = await getAllFields( scope, { html: html.buttons_yesnomaybe });
57
+ expect( result ).to.deep.equal( fields.buttons_yesnomaybe );
58
+ });
59
+
60
+ it(`creates the right data for other mutiple choice continue buttons`, async function() {
61
+ // `field:` and `buttons:`
62
+ let result = await getAllFields( scope, { html: html.buttons_other });
63
+ expect( result ).to.deep.equal( fields.buttons_other );
64
+ });
65
+
66
+ it(`creates the right data for an event action button`, async function() {
67
+ // `field:` and `action buttons:`
68
+ let result = await getAllFields( scope, { html: html.buttons_event_action });
69
+ expect( result ).to.deep.equal( fields.buttons_event_action );
70
+ });
71
+
72
+
73
+ // ============================
74
+ // Proxy vars (x, i, j, ...)
75
+ // ============================
76
+ // x[i].name.first
77
+ it(`creates the right data for a multi-proxy name (x[i])`, async function() {
78
+ let result = await getAllFields( scope, { html: html.proxies_xi });
79
+ expect( result ).to.deep.equal( fields.proxies_xi );
80
+ });
81
+
82
+ // Multiple proxies by the same name are on the list (because of a loop)
83
+ // x[i].name.first
84
+ it(`creates the right data for a multi-proxy name (x[i]) again for consistency`, async function() {
85
+ // same data as `proxies_xi`, but have this here for consistency
86
+ let result = await getAllFields( scope, { html: html.proxies_multi });
87
+ expect( result ).to.deep.equal( fields.proxies_multi );
88
+ });
89
+
90
+
91
+ // ============================
92
+ // Signature
93
+ // ============================
94
+ it(`creates the right data for a signature field`, async function() {
95
+ // `field:` and `action buttons:`
96
+ let result = await getAllFields( scope, { html: html.signature });
97
+ expect( result ).to.deep.equal( fields.signature );
98
+ });
99
+
100
+
101
+ // ============================
102
+ // `choices:`
103
+ // ============================
104
+ // ```
105
+ // field: favorite_fruit
106
+ // choices:
107
+ // - Apple
108
+ // - Orange
109
+ // ```
110
+ it(`creates the right data for a 'choices:' field`, async function() {
111
+ let result = await getAllFields( scope, { html: html.choices });
112
+ expect( result ).to.deep.equal( fields.choices );
113
+ });
114
+
115
+
116
+ // ============================
117
+ // dropdowns created with objects
118
+ // ============================
119
+ // ```
120
+ // - Something: some_var
121
+ // datatype: object
122
+ // choices:
123
+ // - obj1
124
+ // - obj2
125
+ // ```
126
+ it(`creates the right data for a dropdown created with an object`, async function() {
127
+ let result = await getAllFields( scope, { html: html.object_dropdown });
128
+ expect( result ).to.deep.equal( fields.object_dropdown );
129
+ });
130
+
131
+
132
+ // ============================
133
+ // DOM for mixed quotes test in getMatchingRows.test.js
134
+ // ============================
135
+ // Why is this test useful? Or so someone might ask when looking at this closely.
136
+ // This file runs tests for `.getAllFields()`, but also helps us generate the
137
+ // objects in fields.fixtures.js for the `.getMatchingRows()` unit tests. The
138
+ // following test is mostly useful for that second purpose.
139
+ it(`creates the right data for a question whose table will have mixed quotes`, async function() {
140
+ let result = await getAllFields( scope, { html: html.mixed_quotes });
141
+ expect( result ).to.deep.equal( fields.mixed_quotes );
142
+ });
@@ -0,0 +1,261 @@
1
+ const chai = require('chai');
2
+ const expect = chai.expect;
3
+
4
+
5
+ const tables = require('./tables.fixtures.js');
6
+ const fields = require('./fields.fixtures.js');
7
+ const matches = require('./matches.fixtures.js');
8
+ const scope = require('../../lib/scope.js');
9
+ const getMatchingRows = scope.getMatchingRows;
10
+
11
+ // TODO: Add tests for reports
12
+
13
+ // ============================
14
+ // Helpers
15
+
16
+ let getSafeName = function ( field ) {
17
+ let name = 'a field with no name';
18
+ let guess_1 = field.guesses[0];
19
+ if ( guess_1 ) { name = field.guesses[0].var }
20
+ return name;
21
+ };
22
+
23
+ // TODO: Add `testForMatches()` to reduce duplication (will run for loops)
24
+
25
+ // ============================
26
+
27
+
28
+ // ============================
29
+ // Standard fields - no proxies, no showifs.
30
+ // ============================
31
+ describe("Matches: For standard fields", async function() {
32
+ // TODO: One of these should have a report for having two fields that match. Test the report?
33
+ for ( let test_i = 0; test_i < fields.standard.length; test_i++ ) {
34
+ let field = fields.standard[ test_i ];
35
+ let curr_matches = matches.standard[ test_i ];
36
+ let name = getSafeName( field );
37
+ let result = await getMatchingRows( scope, { field, var_data: tables.standard });
38
+ it( `finds the right matches for ${ name }`, async function() {
39
+ expect( result ).to.deep.equal( curr_matches );
40
+ });
41
+ }
42
+ });
43
+
44
+
45
+ // ============================
46
+ // Simple show if fields - no proxies
47
+ // ============================
48
+ describe("For simple show if fields", async function() {
49
+ for ( let test_i = 0; test_i < fields.show_if.length; test_i++ ) {
50
+ let field = fields.show_if[ test_i ];
51
+ let curr_matches = matches.show_if[ test_i ];
52
+ let name = getSafeName( field );
53
+ let result = await getMatchingRows( scope, { field, var_data: tables.show_if });
54
+ it( `finds the right matches for ${ name }`, async function() {
55
+ expect( result ).to.deep.equal( curr_matches );
56
+ });
57
+ }
58
+ });
59
+
60
+
61
+ // ============================
62
+ // Buttons
63
+ // ============================
64
+ // `continue button field:`
65
+ describe("For one continue button", async function() {
66
+ for ( let test_i = 0; test_i < fields.button_continue.length; test_i++ ) {
67
+ let field = fields.button_continue[ test_i ];
68
+ let curr_matches = matches.button_continue[ test_i ];
69
+ let name = getSafeName( field );
70
+ it( `finds the right matches for ${ name }`, async function() {
71
+ let result = await getMatchingRows( scope, { field, var_data: tables.button_continue });
72
+ expect( result ).to.deep.equal( curr_matches );
73
+ });
74
+ }
75
+ });
76
+
77
+ // `yesnomaybe:`
78
+ describe("For the 'yes' choice of yesnomaybe buttons", async function() {
79
+ for ( let test_i = 0; test_i < fields.buttons_yesnomaybe.length; test_i++ ) {
80
+ let field = fields.buttons_yesnomaybe[ test_i ];
81
+ let curr_matches = matches.buttons_yesnomaybe_yes[ test_i ];
82
+ let name = getSafeName( field );
83
+ it( `finds the right matches for ${ name }`, async function() {
84
+ let result = await getMatchingRows( scope, { field, var_data: tables.buttons_yesnomaybe_yes });
85
+ expect( result ).to.deep.equal( curr_matches );
86
+ });
87
+ }
88
+ });
89
+ describe("For the 'no' choice of yesnomaybe buttons", async function() {
90
+ for ( let test_i = 0; test_i < fields.buttons_yesnomaybe.length; test_i++ ) {
91
+ let field = fields.buttons_yesnomaybe[ test_i ];
92
+ let curr_matches = matches.buttons_yesnomaybe_no[ test_i ];
93
+ let name = getSafeName( field );
94
+ it( `finds the right matches for ${ name }`, async function() {
95
+ let result = await getMatchingRows( scope, { field, var_data: tables.buttons_yesnomaybe_no });
96
+ expect( result ).to.deep.equal( curr_matches );
97
+ });
98
+ }
99
+ });
100
+ describe("For the 'maybe' choice of yesnomaybe buttons", async function() {
101
+ for ( let test_i = 0; test_i < fields.buttons_yesnomaybe.length; test_i++ ) {
102
+ let field = fields.buttons_yesnomaybe[ test_i ];
103
+ let curr_matches = matches.buttons_yesnomaybe_none[ test_i ];
104
+ let name = getSafeName( field );
105
+ it( `finds the right matches for ${ name }`, async function() {
106
+ let result = await getMatchingRows( scope, { field, var_data: tables.buttons_yesnomaybe_none });
107
+ expect( result ).to.deep.equal( curr_matches );
108
+ });
109
+ }
110
+ });
111
+
112
+ // `field:` and `buttons:`
113
+ describe("For choice 1 of other mutiple choice continue buttons", async function() {
114
+ for ( let test_i = 0; test_i < fields.buttons_other.length; test_i++ ) {
115
+ let field = fields.buttons_other[ test_i ];
116
+ let curr_matches = matches.buttons_other_1[ test_i ];
117
+ let name = getSafeName( field );
118
+ it( `finds the right matches for ${ name }`, async function() {
119
+ let result = await getMatchingRows( scope, { field, var_data: tables.buttons_other_1 });
120
+ expect( result ).to.deep.equal( curr_matches );
121
+ });
122
+ }
123
+ });
124
+ describe("For choice 2 of other mutiple choice continue buttons", async function() {
125
+ for ( let test_i = 0; test_i < fields.buttons_other.length; test_i++ ) {
126
+ let field = fields.buttons_other[ test_i ];
127
+ let curr_matches = matches.buttons_other_2[ test_i ];
128
+ let name = getSafeName( field );
129
+ it( `finds the right matches for ${ name }`, async function() {
130
+ let result = await getMatchingRows( scope, { field, var_data: tables.buttons_other_2 });
131
+ expect( result ).to.deep.equal( curr_matches );
132
+ });
133
+ }
134
+ });
135
+ describe("For choice 3 of other mutiple choice continue buttons", async function() {
136
+ for ( let test_i = 0; test_i < fields.buttons_other.length; test_i++ ) {
137
+ let field = fields.buttons_other[ test_i ];
138
+ let curr_matches = matches.buttons_other_3[ test_i ];
139
+ let name = getSafeName( field );
140
+ it( `finds the right matches for ${ name }`, async function() {
141
+ let result = await getMatchingRows( scope, { field, var_data: tables.buttons_other_3 });
142
+ expect( result ).to.deep.equal( curr_matches );
143
+ });
144
+ }
145
+ });
146
+
147
+ // `field:` and `action buttons:`
148
+ describe(`For an action button`, async function() {
149
+ for ( let test_i = 0; test_i < fields.buttons_event_action.length; test_i++ ) {
150
+ let field = fields.buttons_event_action[ test_i ];
151
+ let curr_matches = matches.buttons_event_action[ test_i ];
152
+ let name = getSafeName( field );
153
+ it( `finds the right matches for ${ name }`, async function() {
154
+ let result = await getMatchingRows( scope, { field, var_data: tables.buttons_event_action });
155
+ expect( result ).to.deep.equal( curr_matches );
156
+ });
157
+ }
158
+ });
159
+
160
+
161
+ // ============================
162
+ // Proxy vars (x, i, j, ...)
163
+ // ============================
164
+ // x[i].name.first
165
+ describe(`For a multi-proxy name (x[i])`, async function() {
166
+ for ( let test_i = 0; test_i < fields.proxies_xi.length; test_i++ ) {
167
+ let field = fields.proxies_xi[ test_i ];
168
+ let curr_matches = matches.proxies_xi[ test_i ];
169
+ let name = getSafeName( field );
170
+ it( `finds the right matches for ${ name }`, async function() {
171
+ let result = await getMatchingRows( scope, { field, var_data: tables.proxies_xi });
172
+ expect( result ).to.deep.equal( curr_matches );
173
+ });
174
+ }
175
+ });
176
+
177
+ // Multiple proxies by the same name are on the list (because of a loop)
178
+ // x[i].name.first
179
+ describe(`For mulitple rows with the same proxies`, async function() {
180
+ for ( let test_i = 0; test_i < fields.proxies_multi.length; test_i++ ) {
181
+ let field = fields.proxies_multi[ test_i ];
182
+ let curr_matches = matches.proxies_multi[ test_i ];
183
+ let name = getSafeName( field );
184
+ it( `finds the right matches for ${ name }`, async function() {
185
+ let result = await getMatchingRows( scope, { field, var_data: tables.proxies_multi });
186
+ expect( result ).to.deep.equal( curr_matches );
187
+ });
188
+ }
189
+ });
190
+
191
+
192
+ // ============================
193
+ // Signature
194
+ // ============================
195
+ describe(`For a signature field`, async function() {
196
+ for ( let test_i = 0; test_i < fields.signature.length; test_i++ ) {
197
+ let field = fields.signature[ test_i ];
198
+ let curr_matches = matches.signature[ test_i ];
199
+ let name = getSafeName( field );
200
+ it( `finds the right matches for ${ name }`, async function() {
201
+ let result = await getMatchingRows( scope, { field, var_data: tables.signature });
202
+ expect( result ).to.deep.equal( curr_matches );
203
+ });
204
+ }
205
+ });
206
+
207
+
208
+ // ============================
209
+ // `choices:`
210
+ // ============================
211
+ // `field:` and `choices:`
212
+ describe(`For a 'choices:' specifier`, async function() {
213
+ for ( let test_i = 0; test_i < fields.choices.length; test_i++ ) {
214
+ let field = fields.choices[ test_i ];
215
+ let curr_matches = matches.choices[ test_i ];
216
+ let name = getSafeName( field );
217
+ it( `finds the right matches for ${ name }`, async function() {
218
+ let result = await getMatchingRows( scope, { field, var_data: tables.choices });
219
+ expect( result ).to.deep.equal( curr_matches );
220
+ });
221
+ }
222
+ });
223
+
224
+
225
+ // ============================
226
+ // dropdowns created with objects
227
+ // ============================
228
+ // ```
229
+ // - Something: some_var
230
+ // datatype: object
231
+ // object labeler: |
232
+ // lambda y: y.short_label()```
233
+ // choices: some_obj
234
+ // ```
235
+ describe(`For a dropdown created with objects`, async function() {
236
+ for ( let test_i = 0; test_i < fields.object_dropdown.length; test_i++ ) {
237
+ let field = fields.object_dropdown[ test_i ];
238
+ let curr_matches = matches.object_dropdown[ test_i ];
239
+ let name = getSafeName( field );
240
+ it( `finds the right matches for ${ name }`, async function() {
241
+ let result = await getMatchingRows( scope, { field, var_data: tables.object_dropdown });
242
+ expect( result ).to.deep.equal( curr_matches );
243
+ });
244
+ }
245
+ });
246
+
247
+
248
+ // ============================
249
+ // mixed quotes
250
+ // ============================
251
+ describe(`For quotes that are mismatched`, async function() {
252
+ for ( let test_i = 0; test_i < fields.mixed_quotes.length; test_i++ ) {
253
+ let field = fields.mixed_quotes[ test_i ];
254
+ let curr_matches = matches.mixed_quotes[ test_i ];
255
+ let name = getSafeName( field );
256
+ it( `finds the right matches for ${ name }`, async function() {
257
+ let result = await getMatchingRows( scope, { field, var_data: tables.mixed_quotes });
258
+ expect( result ).to.deep.equal( curr_matches );
259
+ });
260
+ }
261
+ });
@@ -0,0 +1,12 @@
1
+ let names = {};
2
+
3
+ names.with_spaces = `a tests description`;
4
+ names.tag1 = `tag1`;
5
+ names.tag2 = `tag2`;
6
+
7
+ names.non_english_chars = `是汉字`;
8
+
9
+ names.colon_input = `invalid:colon`;
10
+ names.colon_output = `invalid_colon`;
11
+
12
+ module.exports = names;
@@ -0,0 +1,62 @@
1
+ const chai = require(`chai`);
2
+ const expect = chai.expect;
3
+
4
+ const names = require(`./getSafeScenarioBaseFilename.fixtures.js`);
5
+ const scope = require(`../../lib/scope.js`);
6
+ const getSafeScenarioBaseFilename = scope.getSafeScenarioBaseFilename;
7
+
8
+
9
+ let mock_scenario = function ( description, tag_names=[] ) {
10
+ /** Mock the complex structure of a Scenario object */
11
+ let scenario = {
12
+ pickle: { name: description, tags: [], }
13
+ };
14
+ for ( let tag of tag_names ) {
15
+ scenario.pickle.tags.push({ name: tag });
16
+ }
17
+ return scenario;
18
+ }; // Ends mock_scenario();
19
+
20
+ describe(`When I use scope.getSafeScenarioBaseFilename()`, function() {
21
+
22
+ beforeEach(function() {
23
+ scope.language = undefined;
24
+ });
25
+
26
+ // No language, no tags
27
+ it(`preserves spaces`, async function() {
28
+ let scenario = mock_scenario( names.with_spaces, [] );
29
+ let result = await getSafeScenarioBaseFilename( scope, { scenario });
30
+ expect( result ).to.equal( names.with_spaces );
31
+ });
32
+
33
+ it(`preserves non-english characters`, async function() {
34
+ let scenario = mock_scenario( names.non_english_chars, [] );
35
+ let result = await getSafeScenarioBaseFilename( scope, { scenario });
36
+ expect( result ).to.equal( names.non_english_chars );
37
+ });
38
+
39
+ it(`replaces invalid characters with "_"`, async function() {
40
+ let scenario = mock_scenario( names.colon_input, [] );
41
+ let result = await getSafeScenarioBaseFilename( scope, { scenario });
42
+ expect( result ).to.equal( names.colon_output );
43
+ });
44
+
45
+ // language, 1 tag
46
+ it(`adds a language and 1 tag correctly, preserving numbers`, async function() {
47
+ scope.language = names.non_english_chars;
48
+ let scenario = mock_scenario( names.with_spaces, [ names.tag1 ] );
49
+ let result = await getSafeScenarioBaseFilename( scope, { scenario });
50
+ let expected = `${ names.non_english_chars }-${ names.with_spaces }-${ names.tag1 }`;
51
+ expect( result ).to.equal( expected );
52
+ });
53
+
54
+ // 2 tags
55
+ it(`adds 2 tags correctly, preserving numbers`, async function() {
56
+ let scenario = mock_scenario( names.with_spaces, [ names.tag1, names.tag2 ] );
57
+ let result = await getSafeScenarioBaseFilename( scope, { scenario });
58
+ let expected = `${ names.with_spaces }-${ names.tag1 }-${ names.tag2 }`;
59
+ expect( result ).to.equal( expected );
60
+ });
61
+
62
+ });
@@ -0,0 +1,83 @@
1
+
2
+ const chai = require('chai');
3
+ const expect = chai.expect;
4
+
5
+ const names = require('./names.fixtures.js');
6
+ const scope = require('../../lib/scope.js');
7
+ const getSafeScenarioFilename = scope.getSafeScenarioFilename;
8
+
9
+
10
+ let test_filename = function ( expected_prefix, result ) {
11
+ /* Test a name to see if it's valid output with a language defined. */
12
+ let expected_name_regex_str = `^${ expected_prefix }\\d{13}-${ names.base_filename }$`;
13
+ let regex = new RegExp( expected_name_regex_str );
14
+
15
+ // Log more info if it failed
16
+ let found_match = regex.test( result );
17
+ if ( !found_match ) {
18
+ console.log( 'regex:', regex.source );
19
+ console.log( 'result:', result );
20
+ }
21
+
22
+ expect( found_match ).to.be.true;
23
+ };
24
+
25
+
26
+ describe(`When I use scope.getSafeScenarioFilename()`, function() {
27
+
28
+ beforeEach(function() {
29
+ scope.base_filename = names.base_filename;
30
+ });
31
+
32
+ it(`preserves chinese characters`, async function() {
33
+ let result = await getSafeScenarioFilename( scope, { prefix: names.chinese_input });
34
+ test_filename( names.chinese_output, result );
35
+ });
36
+
37
+ it(`adds an underscore when there is none`, async function() {
38
+ let result = await getSafeScenarioFilename( scope, { prefix: names.no_underscore_input });
39
+ test_filename( names.no_underscore_output, result );
40
+ });
41
+
42
+ it(`preserves one underscore`, async function() {
43
+ let result = await getSafeScenarioFilename( scope, { prefix: names.one_underscore_input });
44
+ test_filename( names.one_underscore_output, result );
45
+ });
46
+
47
+ it(`preserves two underscores`, async function() {
48
+ let result = await getSafeScenarioFilename( scope, { prefix: names.two_underscores_input });
49
+ test_filename( names.two_underscores_output, result );
50
+ });
51
+
52
+ it(`does not add underscores to an empty string`, async function() {
53
+ let result = await getSafeScenarioFilename( scope, { prefix: names.empty_string_input });
54
+ test_filename( names.empty_string_output, result );
55
+ });
56
+
57
+ it(`converts undefined to an empty string`, async function() {
58
+ let result = await getSafeScenarioFilename( scope, { prefix: names.undefined_input });
59
+ test_filename( names.undefined_output, result );
60
+ });
61
+
62
+ it(`replaces invalid ':' with '_'`, async function() {
63
+ let result = await getSafeScenarioFilename( scope, { prefix: names.colon_input });
64
+ test_filename( names.colon_output, result );
65
+ });
66
+
67
+ it(`replaces invalid '/' with '_'`, async function() {
68
+ let result = await getSafeScenarioFilename( scope, { prefix: names.slash_input });
69
+ test_filename( names.slash_output, result );
70
+ });
71
+
72
+ it(`replaces two consecutive invalid chars with one '_' each`, async function() {
73
+ let result = await getSafeScenarioFilename( scope, { prefix: names.two_consecutive_invalid_input });
74
+ test_filename( names.two_consecutive_invalid_output, result );
75
+ });
76
+
77
+ it(`does not replace numbers`, async function() {
78
+ let result = await getSafeScenarioFilename( scope, { prefix: names.numerical_input });
79
+ test_filename( names.numerical_output, result );
80
+ });
81
+
82
+ });
83
+