@suffolklitlab/alkiln 5.13.4 → 5.15.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.
Files changed (44) hide show
  1. package/.github/workflows/github_server.yml +1 -1
  2. package/.github/workflows/playground.yml +2 -1
  3. package/.github/workflows/unit_tests.yml +1 -1
  4. package/CHANGELOG.md +40 -0
  5. package/action.yml +26 -10
  6. package/action_for_github_server/action.yml +31 -27
  7. package/docs/4_environments.md +2 -2
  8. package/docs/artifacts_folder_name.md +121 -71
  9. package/docs/constrained_random_tests.md +220 -289
  10. package/docs/decisions/move_runtime_config_to_sources_folder.md +3 -1
  11. package/docs/prioritize_constrained_random_tests.md +35 -76
  12. package/lib/docassemble/server_install.js +0 -2
  13. package/lib/docassemble/setup.js +1 -3
  14. package/lib/docassemble/takedown.js +2 -2
  15. package/lib/globals.js +10 -0
  16. package/lib/run_cucumber.js +40 -53
  17. package/lib/scope.js +44 -1
  18. package/lib/setup/TestGenerator.js +1757 -0
  19. package/lib/setup/artifacts.js +20 -0
  20. package/lib/setup/generate.js +42 -0
  21. package/lib/setup/get_Gherkin_AST.js +26 -0
  22. package/lib/setup/validate.js +89 -0
  23. package/lib/steps.js +101 -42
  24. package/lib/utils/Log.js +317 -165
  25. package/lib/utils/_alkiln-constrained_random_tests_old.js +1776 -0
  26. package/lib/utils/get_error_stacks.js +16 -0
  27. package/lib/utils/reports.js +44 -22
  28. package/lib/utils/session_vars.js +77 -57
  29. package/lib/utils/set_sources_paths.js +98 -0
  30. package/package.json +18 -7
  31. package/tests/log_codes/check_codes.sh +17 -13
  32. package/tests/log_codes/log_code_expected_instances.txt +58 -0
  33. package/tests/unit_tests/constrained_random_answers/invalid.fixtures.js +178 -0
  34. package/tests/unit_tests/constrained_random_answers/invalid.test.js +251 -0
  35. package/tests/unit_tests/constrained_random_answers/valid.fixtures.js +957 -0
  36. package/tests/unit_tests/constrained_random_answers/valid.test.js +563 -0
  37. package/tests/unit_tests/example_of_chai_test_lifecycle.js +78 -0
  38. package/tests/unit_tests/log.test.js +17 -41
  39. package/docs/seprate_file_generation_GitHub_action.md +0 -11
  40. package/lib/parse.js +0 -36
  41. package/lib/utils/get_sources_paths.js +0 -162
  42. package/lib/utils/parse.js +0 -1
  43. package/lib/utils/proccess_command_line_args.js +0 -267
  44. /package/docs/{expected_inernal_results.md → expected_internal_results.md} +0 -0
@@ -169,6 +169,10 @@ describe(`An instance of log`, function () {
169
169
  })
170
170
 
171
171
  describe(`given totally custom metadata`, function () {
172
+ let error;
173
+ before(function() {
174
+ error = new Error(`custom_SUCCESS_error`);
175
+ });
172
176
  it(`.success overwrites the right values`, async function() {
173
177
  let options = {
174
178
  before: `custom_SUCCESS_before~`,
@@ -176,17 +180,22 @@ describe(`An instance of log`, function () {
176
180
  icon: `custom_SUCCESS_icon`,
177
181
  code: `custom_SUCCESS_code`,
178
182
  context: `custom_SUCCESS_context`,
183
+ // Discuss: too complex to test right now? Test separately? Test
184
+ // unexpected file contents?
185
+ error,
179
186
  do_throw: true,
180
187
  };
181
188
  let returned = log.success( options, `custom_SUCCESS_log` );
182
189
  // Note the intentional lack of space with `before`
183
190
  expect( returned ).to.include(`custom_SUCCESS_before~🌈 custom_SUCCESS_code custom_SUCCESS_context SUCCESS`);
184
191
  expect( returned ).to.include(`custom_SUCCESS_log`);
192
+ expect( returned ).to.include( error.stack );
185
193
  expect( returned ).to.not.include(`Skip`);
186
194
  });
187
195
  it(`.success stores the right text in the debug file`, async function() {
188
196
  expect_debug_file_to_include(`custom_SUCCESS_before~🌈 custom_SUCCESS_code custom_SUCCESS_context SUCCESS`);
189
197
  expect_debug_file_to_include(`custom_SUCCESS_log`);
198
+ expect_debug_file_to_include( error.stack );
190
199
  expect_debug_file_to_not_include(`Skip`);
191
200
  });
192
201
  })
@@ -313,10 +322,10 @@ describe(`An instance of log`, function () {
313
322
  } catch ( error ) {
314
323
  error_to_test = error;
315
324
  }
316
- // Note: No metadata is included in the error so that we don't have
317
- // to re-throw every error that comes in and they can keep their nice
318
- // stack traces.
319
- // Note: Also excludes logs from error message
325
+ // Note: No metadata is included in the error so that we don't have to
326
+ // re-throw every error that comes in (in order to add the metadata) and
327
+ // they can keep their nice stack traces. Note: Also excludes logs from
328
+ // error message
320
329
  expect( error_to_test.message ).to.include(`CUSTOM_THROW_ERROR_STRING`);
321
330
  expect( error_to_test.stack ).to.include(`at Log.throw`);
322
331
  expect( error_to_test.stack ).to.not.include(`Skip`);
@@ -435,47 +444,14 @@ describe(`An instance of log`, function () {
435
444
  })
436
445
 
437
446
  describe(`with a value for \`error\` and no throw with .debug()`, function () {
438
- it(`returns a value that excludes the error and the error stack`, async function() {
447
+ it(`returns a value that includes the error and the error stack, but does not throw`, async function() {
439
448
  let options = { error: `custom_DEBUG_non_thrown_error`, };
440
449
  let returned = log.debug( options );
441
- expect( returned ).to.not.include(`custom_DEBUG_non_thrown_error`);
450
+ expect( returned ).to.include(`custom_DEBUG_non_thrown_error`);
442
451
  expect( returned ).to.not.include(`at Log.throw`);
443
452
  });
444
- it(`excludes the error in the debug file`, async function() {
445
- expect_debug_file_to_not_include(`custom_DEBUG_non_thrown_error`);
446
- });
447
- it(`stores the warning code in the debug file`, async function() {
448
- expect_debug_file_to_include(`ALK0223`);
449
- });
450
- it(`stores the text 'Skip' in the debug file`, async function() {
451
- expect_debug_file_to_include(`Skip`);
452
- });
453
- it(`excludes the error in the unexpected output file`, async function() {
454
- expect_unexpected_output_file_to_not_include(`custom_DEBUG_non_thrown_error`);
455
- });
456
- it(`stores the warning code in the unexpected output file`, async function() {
457
- expect_unexpected_output_file_to_include(`ALK0223`);
458
- });
459
- it(`stores the text 'Skip' in the unexpected output file`, async function() {
460
- expect_unexpected_output_file_to_include(`Skip`);
461
- });
462
- })
463
-
464
- describe(`given an error without a do_throw`, function () {
465
- it(`.debug saves a warning and ignores the error`, async function() {
466
- let options = {
467
- error: `Illegal error`,
468
- do_throw: false,
469
- };
470
- let returned = log.debug( options, `DEBUG log with illegal error` );
471
- expect( returned ).to.include(`DEBUG log with illegal error`);
472
- expect( returned ).to.not.include(`Illegal error`);
473
- // To not include `Illegal error`
474
- });
475
- it(`.debug stores and excludes the right text in the debug file`, async function() {
476
- expect_debug_file_to_include(`ALK0223`);
477
- expect_debug_file_to_include(`DEBUG log with illegal error`);
478
- expect_debug_file_to_not_include(`Illegal error`);
453
+ it(`includes the error in the debug file`, async function() {
454
+ expect_debug_file_to_include(`custom_DEBUG_non_thrown_error`);
479
455
  });
480
456
  })
481
457
 
@@ -1,11 +0,0 @@
1
- Pros for separate action:
2
-
3
- - Reflects nature of process - generating files is inherently separate.
4
- - Potentially cleaner separation conceptually for us.
5
-
6
- Cons:
7
-
8
- - Main beef: Developing and maintaining GitHub actions is hard
9
- - Authors have more in their workflow file
10
- - Need to update existing workflows
11
- - Need to update ALKilnSetup interview
package/lib/parse.js DELETED
@@ -1,36 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- let log = `log`;
4
- let args = get_command_line_args();
5
- let sources_paths = get_sources_paths( args );
6
- let feature_files_paths = get_feature_files( sources_paths );
7
-
8
- let all_errors = [];
9
- // Just see if any error when Gherkin parses them
10
- for ( let file_path of feature_files_paths ) {
11
- try {
12
- Gherkin.parse( file_path );
13
- } catch ( error ) {
14
- all_errors.push( error );
15
- }
16
- }
17
- // let generated_files_paths = constrained_random_answer_tests.generate();
18
- // // Just see if any error when Gherkin parses them
19
- // for ( let generated_path of generated_files_paths ) {
20
- // try {
21
- // Gherkin.parse( generated_path );
22
- // } catch ( error ) {
23
- // all_errors.push( error );
24
- // }
25
- // }
26
-
27
- let generator_errors = constrained_random_answer_tests.generate();
28
- all_errors = [ ...all_errors, ...generator_errors ];
29
-
30
- if ( all_errors.length > 0 ) {
31
- // Use the Log class in here
32
- for ( let one_error of all_errors ) {
33
- console.log( `An error:`, one_error );
34
- }
35
- throw new Error( `ALKiln ran into an error when parsing the test files. See above for more details` );
36
- }
@@ -1,162 +0,0 @@
1
- /**
2
- fast_glob (fast glob)
3
-
4
- files
5
- session_vars
6
- */
7
-
8
-
9
- // let log = null;
10
-
11
- // function set_log ( artifacts_path ) {
12
- // log = Log( artifacts_path );
13
- // }
14
-
15
- // TODO: Remove after merging Log class PR
16
- let artifacts_path = files.make_artifacts_folder();
17
- session_vars.save_artifacts_path_name( artifacts_path );
18
-
19
-
20
- function proccess_command_line_args({ log }) {
21
-
22
- // Discuss: Wouldn't have to use log if we moved this up.
23
- const environment = { cwd: process.cwd() };
24
- log.info({ type: `run`, code: `ALK0049`, pre: `environment`, data: environment });
25
-
26
- // We'll use the user info to construct the possible paths to /sources
27
- let id = session_vars.get_user_id();
28
- // `project` is the name in the server docassemble "Project" page
29
- let project = session_vars.get_user_project_name();
30
-
31
- // process.argv is a list of strings of commands and args.
32
- // Internal note: If using `npm run cucumber`, use `--` before
33
- // `--sources=./foo`
34
- let command_line_args = require(`minimist`)( process.argv.slice(2), {
35
- default: {
36
- sources: [
37
- `./docassemble/*/data/sources`, // In GitHub folder
38
- `/usr/share/docassemble/files/playgroundsources/${id}/${project}/*.feature`, // From playground without S3
39
- `/tmp/playgroundsources/${id}/${project}/*.feature` // From playground with S3
40
- ],
41
- }
42
- });
43
-
44
- let processed = {};
45
- processed.sources = get_sources_paths({ command_line_args });
46
- let tags = get_tags({ command_line_args });
47
-
48
- return command_line_args;
49
- }
50
-
51
-
52
- function get_sources_paths({ command_line_args }) {
53
-
54
- // Make sure `sources` is always a list
55
- let sources_list = command_line_args.sources;
56
- if ( typeof command_line_args.sources === `string` ) {
57
- sources_list = [ command_line_args.sources ];
58
- }
59
-
60
- // Check every path, tracking which exist and which are missing
61
- let existing_paths = [];
62
- let missing_paths = [];
63
- for ( let path of paths ) {
64
- let dirs = fast_glob.sync(
65
- [ path ],
66
- { onlyFiles: false, suppressErrors: true }
67
- );
68
-
69
- if ( dirs.length > 0 ) {
70
- existing_paths.push( ...dirs );
71
- } else {
72
- missing_paths.push( path );
73
- }
74
- }
75
-
76
- // If no paths were valid
77
- if ( existing_paths.length <= 0 ) {
78
- // session_vars.set_sources_paths( null );
79
-
80
- // Discuss: Wouldn't have to use log if we moved this up.
81
- // If we don't throw, it'll be more confusing when no tests run
82
- let msg = `ALKiln can't find your "sources" folder(s). See above for details.`;
83
- let code = `ALK0050`
84
- log.error({ type: `run`, code: code, pre: msg });
85
- // pass error up instead?
86
- throw new ReferenceError(`🤕 ${ code } run ERROR: ${ msg }`);
87
- }
88
-
89
- // TODO: move this out a level
90
- console.info(
91
- `lightbulb ALK0042 INFO: Did find "sources" file(s) at "${ existing_paths.join('", "') }".`
92
- )
93
-
94
- // session_vars.set_sources_paths( existing_paths );
95
- return existing_paths;
96
- }
97
-
98
-
99
- function get_tags({ command_line_args }) {
100
- // Normalize tag expressions, if there are any Joining and splitting handles
101
- // both tags surrounded with `""` or those without `""`
102
- let tags = command_line_args[`_`].join(` `).split(` `);
103
- // If there was no tag expression, `tags` is ['']. Remove that item.
104
- tags = tags.filter(function(entry) { return entry !== ""; })
105
- if ( tags.length > 0 ) {
106
- let joined_tags = '';
107
- // Cucumber expects tags in boolean expressions, like (@a0 or @a1) and
108
- // @random. If we get a list of only tags, then "or" them all together
109
- if (tags.every((val) => val.startsWith(`@`))) {
110
- joined_tags = tags.join(` or `);
111
- }
112
- // If we get a list of seemingly no tags, assume they meant to use tags
113
- else if (tags.every((val) => !val.startsWith(`@`))) {
114
- joined_tags = tags.map((val) => `@` + val).join(` or `);
115
- }
116
- // If it's a mix of tags and no tags, it's probably a boolean expression!
117
- else {
118
- joined_tags = tags.join(` `);
119
- }
120
-
121
- // config.tags = joined_tags;
122
- return joined_tags;
123
- }
124
-
125
- return null;
126
- }
127
-
128
-
129
- /**
130
- * get sources paths
131
- * generate feature files
132
- * try to parse everything
133
- * pass on the feature files?
134
- *
135
- * When running run_cucumber, pass whether files have yet been parsed
136
- * Alternatively, have 2 setup steps? The second one parses before run_cucumber
137
- * That seems maybe better...? Have to pass on the feature files somehow, though
138
- *
139
- * setup_server_stuff
140
- * get_feature_files
141
- * run_cucumber(with files list somehow... runtime_config?)
142
- * */
143
-
144
- function get_feature_paths() {
145
- // Turn all the paths to the sources folders into paths to the feature files
146
- let sources_paths = session_vars.get_sources_paths();
147
- let feature_paths = [];
148
-
149
- // Get all the paths for the right feature files (for cucumber to use)
150
- for ( let sources_path of sources_paths ) {
151
- const generators_prefix = `alkiln_random`;
152
- constrained_random_tests.create({ generators_prefix, sources_path });
153
- // Ignore feature files that we parsed ourselves
154
- let glob = fast_glob.sync(
155
- `${ sources_path }/**/*.feature`,
156
- { ignore: [`${ sources_path }/${ generators_prefix }*.feature`] }
157
- );
158
- feature_paths.push( ...glob );
159
- }
160
- }
161
-
162
-
@@ -1 +0,0 @@
1
- parse.js
@@ -1,267 +0,0 @@
1
- /**
2
- * before everything else
3
- * error if there are generator errors
4
- *
5
- * problem:
6
- *
7
- * because of the 3 (4) env of ALKiln, have to be able to generate and error in
8
- * 2 places: run_cucumber, at the start of the GitHub action
9
- *
10
- * If there's an error, no problem (nothing will run twice)
11
- *
12
- * Otherwise (success, warnings, etc.), generation/parsing will be run 2x. Do we
13
- * care?
14
- *
15
- * Note that generation cleans out its folder before generating.
16
- *
17
- * Warnings are the problem if we log them at the top (not if we log them along
18
- * with the other test errors/warnings).
19
- *
20
- * Error:
21
- * Action: Errors, nothing else is run
22
- * Local/Playground: Errors, nothing else is run
23
- * TODO: Need to generate error files?
24
- *
25
- * Success:
26
- * Action: Generate twice
27
- * Local/Playground: Generate once
28
- *
29
- * Warnings (same warnings):
30
- * Action: Generate, warn?, generate, warn?, warn at end of test run
31
- * Do we need a "dry run" env var?
32
- * Local/Playground: Generate, warn, warn at end of test run
33
- *
34
- * Maybe run_cucumber needs an idea of whether it's running as the first
35
- * operation or as a follow-up
36
- * `is_followup` (general state of affairs)
37
- * `don't_generate` (a command of a specific action to take)
38
- * previous_steps = [`pre_parse`, `server_setup`/`github_playground_setup`]
39
- *
40
- * Maybe do this completely separately and call it in different places in
41
- * different processes.
42
- *
43
- *
44
- * action needs:
45
- * pre-setup needs:
46
- * `generate` which needs:
47
- * (really??) trigger_any_parsing_errors which needs:
48
- * feature files list/glob which needs:
49
- * sources paths which needs
50
- * command line args
51
- * and
52
- * prints environment PROBLEM TO REPEAT
53
- * potentially errors
54
- * and
55
- * potentially errors
56
- *
57
- * run_cucumber needs
58
- * pre-setup
59
- * (maybe) generate which needs:
60
- * (maybe) trigger_any_parsing_errors etc.
61
- * (maybe) trigger_any_parsing_errors which needs:
62
- * feature files, etc.
63
- *
64
- * feature files list/glob which needs:
65
- * sources paths which needs
66
- * command line args
67
- * and
68
- * prints environment PROBLEM TO REPEAT
69
- * potentially errors (not a problem. won't run if the other errors)
70
- * tags needs
71
- * command line args
72
- *
73
- * ## Problem 1 - printing environment in 2 places
74
- * Fix: Move print environment into run_cucumber
75
- *
76
- * ====
77
- *
78
- * ## Problem 2 - parsing in both places.
79
- * Parsing errors will prevent duplicate parsing.
80
- * What about when there are no errors?
81
- * Fix: I guess we can check for parsing errors again without harm, though it'll
82
- * take an extra second. Errors will only be parsed once because they'll
83
- * prevent execution.
84
- *
85
- * ## Problem 3 - generating in both places
86
- * Fix: flag? Or maybe re-generating isn't a problem if it doesn't take too long
87
- *
88
- * ## Problem 4
89
- * Parse before generating or after generating?
90
- * - Can generating create files that have parsing errors without already
91
- * having parsing errors? If so, parse before.
92
- * - Generating can create its own errors, though. So generate before?
93
- * - Also, errors for generated tests may be confusing because author may think,
94
- * "I didn't write those tests."
95
- * Maybe:
96
- * 1. test all files before generating
97
- * 2. generate (and pass back errors or just throw?)
98
- * 3. test generated files and throw just generator process errors and parsing
99
- * errors
100
- *
101
- * All:
102
- * 0. Get command line args
103
- * 1. Get sources
104
- * 2. Get feature files
105
- * 3. Parse all current (can throw) (accumulated errors?)
106
- * 4. Generate (with possible errors) (can throw accumulated errors)
107
- * 5. Parse generated (can throw)
108
- * Should those throw all together? Probably not. They can affect each other.
109
- *
110
- * run_cucumber also independently needs:
111
- * 1. sources
112
- * 2. feature files
113
- * */
114
-
115
- /**
116
- * get sources paths
117
- * generate feature files
118
- * try to parse everything
119
- * pass on the feature files?
120
- *
121
- * When running run_cucumber, pass whether files have yet been parsed
122
- * Alternatively, have 2 setup steps? The second one parses before run_cucumber
123
- * That seems maybe better...? Have to pass on the feature files somehow, though
124
- *
125
- * setup_server_stuff
126
- * get_feature_files
127
- * run_cucumber(with files list somehow... runtime_config?)
128
- * */
129
-
130
- /**
131
- fast_glob (fast glob)
132
-
133
- files
134
- session_vars
135
- */
136
-
137
- // let log = null;
138
-
139
- // function set_log ( artifacts_path ) {
140
- // log = Log( artifacts_path );
141
- // }
142
-
143
- // TODO: Remove after merging Log class PR
144
- let artifacts_path = files.make_artifacts_folder();
145
- session_vars.save_artifacts_path_name( artifacts_path );
146
-
147
- function get_command_line_args({ log }) {
148
-
149
- // We'll use the user info to construct the possible paths to /sources
150
- let id = session_vars.get_user_id();
151
- // `project` is the name in the author's server's docassemble "Project" page
152
- let project = session_vars.get_user_project_name();
153
-
154
- // process.argv is a list of strings of commands and args.
155
- // Internal note: If using `npm run cucumber`, use `--` before
156
- // `--sources=./foo`
157
- let command_line_args = require(`minimist`)( process.argv.slice(2), {
158
- default: {
159
- sources: [
160
- `./docassemble/*/data/sources`, // In GitHub folder
161
- `/usr/share/docassemble/files/playgroundsources/${id}/${project}/*.feature`, // From playground without S3
162
- `/tmp/playgroundsources/${id}/${project}/*.feature` // From playground with S3
163
- ],
164
- }
165
- });
166
-
167
- // let processed = {};
168
- // processed.sources = get_sources_paths({ command_line_args });
169
- // let tags = get_tags({ command_line_args });
170
-
171
- return command_line_args;
172
- }
173
-
174
-
175
- function get_sources_paths({ command_line_args }) {
176
-
177
- // Make sure `sources` is always a list
178
- let sources_list = command_line_args.sources;
179
- if ( typeof command_line_args.sources === `string` ) {
180
- sources_list = [ command_line_args.sources ];
181
- }
182
-
183
- // Check every path, tracking which exist and which are missing
184
- let existing_paths = [];
185
- let missing_paths = [];
186
- for ( let path of paths ) {
187
- let dirs = fast_glob.sync(
188
- [ path ],
189
- { onlyFiles: false, suppressErrors: true }
190
- );
191
-
192
- if ( dirs.length > 0 ) {
193
- existing_paths.push( ...dirs );
194
- } else {
195
- missing_paths.push( path );
196
- }
197
- }
198
-
199
- // If no paths were valid
200
- if ( existing_paths.length <= 0 ) {
201
- // session_vars.set_sources_paths( null );
202
-
203
- // Discuss: Wouldn't have to use log if we moved this up.
204
- // If we don't throw, it'll be more confusing when no tests run
205
- let msg = `ALKiln can't find your "sources" folder(s). See above for details.`;
206
- let code = `ALK0050`
207
- log.error({ type: `run`, code: code, pre: msg });
208
- // pass error up instead?
209
- throw new ReferenceError(`🤕 ${ code } run ERROR: ${ msg }`);
210
- }
211
-
212
- // TODO: move this out a level
213
- console.info(
214
- `lightbulb ALK0042 INFO: Did find "sources" file(s) at "${ existing_paths.join('", "') }".`
215
- )
216
-
217
- // session_vars.set_sources_paths( existing_paths );
218
- return existing_paths;
219
- }
220
-
221
-
222
- function get_tags({ command_line_args }) {
223
- // Normalize tag expressions, if there are any Joining and splitting handles
224
- // both tags surrounded with `""` or those without `""`
225
- let tags = command_line_args[`_`].join(` `).split(` `);
226
- // If there was no tag expression, `tags` is ['']. Remove that item.
227
- tags = tags.filter(function(entry) { return entry !== ""; })
228
- if ( tags.length > 0 ) {
229
- let joined_tags = '';
230
- // Cucumber expects tags in boolean expressions, like (@a0 or @a1) and
231
- // @random. If we get a list of only tags, then "or" them all together
232
- if (tags.every((val) => val.startsWith(`@`))) {
233
- joined_tags = tags.join(` or `);
234
- }
235
- // If we get a list of seemingly no tags, assume they meant to use tags
236
- else if (tags.every((val) => !val.startsWith(`@`))) {
237
- joined_tags = tags.map((val) => `@` + val).join(` or `);
238
- }
239
- // If it's a mix of tags and no tags, it's probably a boolean expression!
240
- else {
241
- joined_tags = tags.join(` `);
242
- }
243
-
244
- // config.tags = joined_tags;
245
- return joined_tags;
246
- }
247
-
248
- return null;
249
- }
250
-
251
- function get_feature_paths() {
252
- // Turn all the paths to the sources folders into paths to the feature files
253
- let sources_paths = session_vars.get_sources_paths();
254
- let feature_paths = [];
255
-
256
- // Get all the paths for the right feature files (for cucumber to use)
257
- for ( let sources_path of sources_paths ) {
258
- const generators_prefix = `alkiln_random`;
259
- constrained_random_tests.create({ generators_prefix, sources_path });
260
- // Ignore feature files that we parsed ourselves
261
- let glob = fast_glob.sync(
262
- `${ sources_path }/**/*.feature`,
263
- { ignore: [`${ sources_path }/${ generators_prefix }*.feature`] }
264
- );
265
- feature_paths.push( ...glob );
266
- }
267
- }