@suffolklitlab/alkiln 5.14.0 → 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 (35) hide show
  1. package/.github/workflows/github_server.yml +1 -1
  2. package/.github/workflows/playground.yml +2 -1
  3. package/CHANGELOG.md +29 -0
  4. package/action.yml +26 -10
  5. package/action_for_github_server/action.yml +31 -27
  6. package/docs/4_environments.md +2 -2
  7. package/docs/artifacts_folder_name.md +121 -71
  8. package/lib/docassemble/server_install.js +0 -2
  9. package/lib/docassemble/setup.js +1 -3
  10. package/lib/docassemble/takedown.js +2 -2
  11. package/lib/globals.js +10 -0
  12. package/lib/run_cucumber.js +40 -53
  13. package/lib/scope.js +32 -0
  14. package/lib/setup/TestGenerator.js +1757 -0
  15. package/lib/setup/artifacts.js +20 -0
  16. package/lib/setup/generate.js +42 -0
  17. package/lib/setup/get_Gherkin_AST.js +26 -0
  18. package/lib/setup/validate.js +89 -0
  19. package/lib/steps.js +53 -19
  20. package/lib/utils/Log.js +302 -149
  21. package/lib/utils/get_error_stacks.js +16 -0
  22. package/lib/utils/reports.js +43 -23
  23. package/lib/utils/session_vars.js +77 -57
  24. package/lib/utils/set_sources_paths.js +98 -0
  25. package/package.json +18 -7
  26. package/tests/log_codes/check_codes.sh +17 -13
  27. package/tests/log_codes/log_code_expected_instances.txt +58 -0
  28. package/tests/unit_tests/constrained_random_answers/invalid.fixtures.js +178 -0
  29. package/tests/unit_tests/constrained_random_answers/invalid.test.js +251 -0
  30. package/tests/unit_tests/constrained_random_answers/valid.fixtures.js +957 -0
  31. package/tests/unit_tests/constrained_random_answers/valid.test.js +563 -0
  32. package/tests/unit_tests/log.test.js +17 -41
  33. package/_alkiln_meta/gherkin_parsed_example.json +0 -1546
  34. package/_alkiln_meta/shift_logs.js +0 -75
  35. /package/docs/{expected_inernal_results.md → expected_internal_results.md} +0 -0
@@ -0,0 +1,957 @@
1
+ /** Actual and expected values for valid constrained random answer tests. */
2
+
3
+ /**
4
+ * TODO:
5
+ * - When we allow multiple Scenarios in one file, test when a Scenario ends in
6
+ * a docstring before another Scenario, especially with comments and blank
7
+ * lines after the docstring and with comment-like text in the docstring
8
+ * itself.
9
+ * */
10
+
11
+
12
+ module.exports = fixts = {};
13
+
14
+ fixts.RANDOM_TABLE_PLACEHOLDER = `@@@ ALK_RANDOM_TABLE_BODY_PLACEHOLDER @@@`;
15
+ fixts.WARNING_PLACEHOLDER = `@@@ ALK_WARNING_PLACEHOLDER @@@`;
16
+ fixts.FLUB_PLACEHOLDER = `@@@ ALK_FLUB_PLACEHOLDER @@@`;
17
+ fixts.FLUB_OPTIONS_REGEX = /(hiccup|snafu|bumble|stumble|fumble|slip|goof|flub)/g;
18
+
19
+ /**
20
+ * ===========
21
+ * Simplest test
22
+ * =========== */
23
+ fixts.simple = simple = {};
24
+ simple.arg =
25
+ `Feature: I generate constrained random tests
26
+
27
+ Scenario: simplest random answers
28
+ Given ALKiln makes 1 constrained random answers test
29
+ Given I start the interview at "test_kickout"
30
+ And ALKiln can get to one of "kickout screen", "success screen" with:
31
+ | var | possible_values |
32
+ | user_choice | correct;; wrong |
33
+ | row_2 | answer1;; answer2;; answer3 |`;
34
+ // ======= ENDS ARG ======= //
35
+ simple.expected =
36
+ `@alkiln @generated @randomized @constraints
37
+ Feature: I generate constrained random tests (generated by ALKiln)
38
+
39
+ @scenario1_of_1
40
+ Scenario: simplest random answers (1 of 1)
41
+ Given I start the interview at "test_kickout"
42
+ And I get to any of the question ids ["kickout screen", "success screen"] with this data:
43
+ | var | value |
44
+ ${ fixts.RANDOM_TABLE_PLACEHOLDER }`;
45
+ // ======= ENDS EXPECTED ======= //
46
+ simple.exact_log_codes = [
47
+ `ALK0237`, `ALK0243`, `ALK0244`,
48
+ `ALK0245`, `ALK0248`, `ALK0249`, `ALK0246`, `ALK0246`, `ALK0246`, `ALK0246`, `ALK0255`, `ALK0257`, `ALK0259`, `ALK0246`,
49
+ `ALK0261`, `ALK0262`, `ALK0264`,
50
+ ];
51
+ simple.num_Scenarios = 1;
52
+
53
+
54
+ /**
55
+ * ===========
56
+ * Minimal required Step text:
57
+ * - Required: "constrain", "ALKiln"
58
+ * - Required: "generat" or "rand" or "mak" or "mad"
59
+ * =========== */
60
+ fixts.generat = {};
61
+ fixts.generat.arg =
62
+ `Feature: I generate constrained random tests
63
+
64
+ Scenario: I use minimal text (constrain and generat)
65
+ Given ALKiln constrain generat 1
66
+ Given I start the interview at "test_kickout"
67
+ And ALKiln can/will get to/reach "end" with:
68
+ | var | possible_values |
69
+ | user_choice | correct;; wrong |`;
70
+ fixts.generat.expected =
71
+ `@alkiln @generated @randomized @constraints
72
+ Feature: I generate constrained random tests (generated by ALKiln)
73
+
74
+ @scenario1_of_1
75
+ Scenario: I use minimal text (constrain and generat) (1 of 1)
76
+ Given I start the interview at "test_kickout"
77
+ And I get to any of the question ids ["end"] with this data:
78
+ | var | value |
79
+ ${ fixts.RANDOM_TABLE_PLACEHOLDER }`;
80
+ fixts.generat.exact_log_codes = [
81
+ `ALK0237`, `ALK0243`, `ALK0244`,
82
+ `ALK0245`, `ALK0248`, `ALK0249`, `ALK0246`, `ALK0246`, `ALK0246`, `ALK0255`, `ALK0257`, `ALK0259`, `ALK0246`,
83
+ `ALK0261`, `ALK0262`, `ALK0264`,
84
+ ];
85
+
86
+
87
+ // ===============
88
+ fixts.rand = {};
89
+ fixts.rand.arg =
90
+ `Feature: I generate constrained random tests
91
+
92
+ Scenario: I use minimal text (constrain and rand)
93
+ Given 1 rand constrain ALKiln
94
+ Given I start the interview at "test_kickout"
95
+ And ALKiln can/will get to/reach "end" with:
96
+ | var | possible_values |
97
+ | user_choice | correct;; wrong |`;
98
+ fixts.rand.expected =
99
+ `@alkiln @generated @randomized @constraints
100
+ Feature: I generate constrained random tests (generated by ALKiln)
101
+
102
+ @scenario1_of_1
103
+ Scenario: I use minimal text (constrain and rand) (1 of 1)
104
+ Given I start the interview at "test_kickout"
105
+ And I get to any of the question ids ["end"] with this data:
106
+ | var | value |
107
+ ${ fixts.RANDOM_TABLE_PLACEHOLDER }`;
108
+ fixts.rand.exact_log_codes = [
109
+ `ALK0237`, `ALK0243`, `ALK0244`,
110
+ `ALK0245`, `ALK0248`, `ALK0249`, `ALK0246`, `ALK0246`, `ALK0246`, `ALK0255`, `ALK0257`, `ALK0259`, `ALK0246`,
111
+ `ALK0261`, `ALK0262`, `ALK0264`,
112
+ ];
113
+
114
+
115
+ // ===============
116
+ fixts.make = {};
117
+ fixts.make.arg =
118
+ `Feature: I generate constrained random tests
119
+
120
+ Scenario: I use minimal text (constrain and make)
121
+ Given 1 constrain make ALKiln
122
+ Given I start the interview at "test_kickout"
123
+ And ALKiln can/will get to/reach "end" with:
124
+ | var | possible_values |
125
+ | user_choice | correct;; wrong |`;
126
+ fixts.make.expected =
127
+ `@alkiln @generated @randomized @constraints
128
+ Feature: I generate constrained random tests (generated by ALKiln)
129
+
130
+ @scenario1_of_1
131
+ Scenario: I use minimal text (constrain and make) (1 of 1)
132
+ Given I start the interview at "test_kickout"
133
+ And I get to any of the question ids ["end"] with this data:
134
+ | var | value |
135
+ ${ fixts.RANDOM_TABLE_PLACEHOLDER }`;
136
+ fixts.make.exact_log_codes = [
137
+ `ALK0237`, `ALK0243`, `ALK0244`,
138
+ `ALK0245`, `ALK0248`, `ALK0249`, `ALK0246`, `ALK0246`, `ALK0246`, `ALK0255`, `ALK0257`, `ALK0259`, `ALK0246`,
139
+ `ALK0261`, `ALK0262`, `ALK0264`,
140
+ ];
141
+
142
+
143
+ // ===============
144
+ fixts.made = {};
145
+ fixts.made.arg =
146
+ `Feature: I generate constrained random tests
147
+
148
+ Scenario: I use minimal text (constrain and made)
149
+ Given 1 made ALKiln constrain
150
+ Given I start the interview at "test_kickout"
151
+ And ALKiln will get to "end" with:
152
+ | var | possible_values |
153
+ | user_choice | correct;; wrong |`;
154
+ fixts.made.expected =
155
+ `@alkiln @generated @randomized @constraints
156
+ Feature: I generate constrained random tests (generated by ALKiln)
157
+
158
+ @scenario1_of_1
159
+ Scenario: I use minimal text (constrain and made) (1 of 1)
160
+ Given I start the interview at "test_kickout"
161
+ And I get to any of the question ids ["end"] with this data:
162
+ | var | value |
163
+ ${ fixts.RANDOM_TABLE_PLACEHOLDER }`;
164
+ fixts.made.exact_log_codes = [
165
+ `ALK0237`, `ALK0243`, `ALK0244`,
166
+ `ALK0245`, `ALK0248`, `ALK0249`, `ALK0246`, `ALK0246`, `ALK0246`, `ALK0255`, `ALK0257`, `ALK0259`, `ALK0246`,
167
+ `ALK0261`, `ALK0262`, `ALK0264`,
168
+ ];
169
+
170
+
171
+ /**
172
+ * ===========
173
+ * Complex:
174
+ * - 3 Scenarios with extra "Scenario:" keyword not counted (from 2 generator Scenarios)
175
+ * - Able to generate just one Scenario
176
+ * - Text under Feature
177
+ * - Inconsistent tag spacing
178
+ * - Inconsistent table indentation
179
+ * - A Step after the table
180
+ * - Comments in between Scenarios repeat for each generated Scenario
181
+ * - Comments in the Scenario repeats
182
+ * - Comments in the table
183
+ * - Comment has generator Step text and it doesn't get changed
184
+ * =========== */
185
+ fixts.complex = complex = {};
186
+ complex.arg =
187
+ `Feature: I generate constrained random tests
188
+
189
+ Line 1 after Feature that includes Scenario: keyword. Keep. No comments allowed above this line.
190
+ # Comment 0 keep
191
+
192
+ Scenario: generate a complex Scenario
193
+ # Comment 1 keep and repeat
194
+ Given ALKiln makes 2 constrained answers tests
195
+ Given I start the interview at "test_kickout"
196
+ # Comment 2 keep and repeat
197
+ And ALKiln can get to any of "kickout screen", "success screen" with:
198
+ # Comment 3 keep and repeat
199
+ | var | possible_values |
200
+ # Comment 4 keep and repeat and same with blank line below
201
+
202
+
203
+ | user_choice | correct;; wrong |
204
+ # Comment 5 keep and repeat
205
+ And I wait 0.1 second
206
+ # Comment 6 keep and repeat
207
+ And a docstring containing keywords
208
+ """
209
+ @not_really_a_tag
210
+ Scenario: not really a Scenario
211
+ # Not really a comment. Should test table, but would have to improve test infrastructure for that.
212
+ """
213
+ # Comment 7 keep and repeat. Would belong to different Scenario in future.
214
+ `;
215
+ // // Restore if/when we allow multiple Scenarios
216
+ // Scenario: generate 1st complex Scenario
217
+ // Scenario: generate 2nd complex Scenario
218
+ // # Comment 7 keep
219
+ // Given I start the interview at "interview_2"
220
+ // # And ALKiln will get to "end" with:
221
+ // And ALKiln will get to "end" with:
222
+ // | var | possible_values |
223
+ // | question_1 | opt1;; opt2;; opt3 |
224
+ // | question_2 | optA;; optB;; optC |
225
+ // // ======= ENDS ARG ======= //
226
+ complex.expected =
227
+ `@alkiln @generated @randomized @constraints
228
+ Feature: I generate constrained random tests (generated by ALKiln)
229
+
230
+ Line 1 after Feature that includes Scenario: keyword. Keep. No comments allowed above this line.
231
+ # Comment 0 keep
232
+
233
+ @scenario1_of_2
234
+ Scenario: generate a complex Scenario (1 of 2)
235
+ # Comment 1 keep and repeat
236
+ Given I start the interview at "test_kickout"
237
+ # Comment 2 keep and repeat
238
+ And I get to any of the question ids ["kickout screen", "success screen"] with this data:
239
+ # Comment 3 keep and repeat
240
+ | var | value |
241
+ # Comment 4 keep and repeat and same with blank line below
242
+
243
+
244
+ ${ fixts.RANDOM_TABLE_PLACEHOLDER }
245
+ # Comment 5 keep and repeat
246
+ And I wait 0.1 second
247
+ # Comment 6 keep and repeat
248
+ And a docstring containing keywords
249
+ """
250
+ @not_really_a_tag
251
+ Scenario: not really a Scenario
252
+ # Not really a comment. Should test table, but would have to improve test infrastructure for that.
253
+ """
254
+ # Comment 7 keep and repeat. Would belong to different Scenario in future.
255
+
256
+
257
+ @scenario2_of_2
258
+ Scenario: generate a complex Scenario (2 of 2)
259
+ # Comment 1 keep and repeat
260
+ Given I start the interview at "test_kickout"
261
+ # Comment 2 keep and repeat
262
+ And I get to any of the question ids ["kickout screen", "success screen"] with this data:
263
+ # Comment 3 keep and repeat
264
+ | var | value |
265
+ # Comment 4 keep and repeat and same with blank line below
266
+
267
+
268
+ ${ fixts.RANDOM_TABLE_PLACEHOLDER }
269
+ # Comment 5 keep and repeat
270
+ And I wait 0.1 second
271
+ # Comment 6 keep and repeat
272
+ And a docstring containing keywords
273
+ """
274
+ @not_really_a_tag
275
+ Scenario: not really a Scenario
276
+ # Not really a comment. Should test table, but would have to improve test infrastructure for that.
277
+ """
278
+ # Comment 7 keep and repeat. Would belong to different Scenario in future.
279
+ `;
280
+ // // Restore if/when we allow multiple Scenarios
281
+ // `@scenario1_of_2
282
+ // @scenario2_of_2`
283
+ // `@scenario1_of_1
284
+ // Scenario: generate complex 2 (1 of 1)
285
+ // # Comment 7 keep
286
+ // Given I start the interview at "interview_2"
287
+ // # And ALKiln will get to "end" with:
288
+ // And I get to any of the question ids ["end"] with this data:
289
+ // | var | value |
290
+ // ${ fixts.RANDOM_TABLE_PLACEHOLDER }
291
+ // `;
292
+ // ======= ENDS EXPECTED ======= //
293
+ complex.num_Scenarios = 2;
294
+ complex.included_log_codes = [
295
+ `ALK0237`, `ALK0243`, `ALK0244`,
296
+ `ALK0245`, `ALK0248`, `ALK0249`, `ALK0246`, `ALK0255`, `ALK0257`, `ALK0259`,
297
+ `ALK0261`, `ALK0262`, `ALK0264`,
298
+ ];
299
+
300
+
301
+ /** Existing Feature and Scenario tags are preserved */
302
+ fixts.tags = tags = {};
303
+ tags.arg =
304
+ `@feature_tag1 @feature_tag2
305
+ Feature: I generate constrained random tests
306
+
307
+ @scenario_tag1 @scenario_tag2
308
+ Scenario: simplest random answers
309
+ Given ALKiln makes 1 constrained answers test
310
+ Given I start the interview at "test_kickout"
311
+ And ALKiln will get to any of ["kickout screen", "success screen"] when I pick from these constraints:
312
+ | var | possible_values |
313
+ | user_choice | correct;; wrong |`;
314
+ // ======= ENDS ARG ======= //
315
+ tags.expected =
316
+ `@feature_tag1 @feature_tag2 @alkiln @generated @randomized @constraints
317
+ Feature: I generate constrained random tests (generated by ALKiln)
318
+
319
+ @scenario_tag1 @scenario_tag2 @scenario1_of_1
320
+ Scenario: simplest random answers (1 of 1)
321
+ Given I start the interview at "test_kickout"
322
+ And I get to any of the question ids ["kickout screen", "success screen"] with this data:
323
+ | var | value |
324
+ ${ fixts.RANDOM_TABLE_PLACEHOLDER }`;
325
+ tags.exact_log_codes = [
326
+ `ALK0237`, `ALK0243`, `ALK0244`,
327
+ `ALK0246`, `ALK0245`, `ALK0248`, `ALK0249`, `ALK0246`, `ALK0246`, `ALK0246`, `ALK0255`, `ALK0257`, `ALK0259`, `ALK0246`,
328
+ `ALK0261`, `ALK0262`, `ALK0264`,
329
+ ];
330
+
331
+
332
+ /**
333
+ * WEIRD SPACING
334
+ * - [x] Feature tags have extra spaces and are indented
335
+ * - [x] Scenario tags have extra spaces and are indented
336
+ * - [x] Weird indention, including table
337
+ * - [x] No space between choices (no expected value)
338
+ * */
339
+
340
+ fixts.weird_spacing = {};
341
+
342
+ /** Weird spacing is preserved in all tag types */
343
+ fixts.weird_spacing.tags = {};
344
+ fixts.weird_spacing.tags.arg =
345
+ ` @feature_tag @spacing
346
+ Feature: I generate constrained random tests
347
+
348
+ @scenario_tag @spacing
349
+ Scenario: a scenario
350
+ Given ALKiln makes 1 constrained answers test
351
+ Given I start the interview at "test_kickout"
352
+ And ALKiln will get to any of ["kickout screen", "success screen"] when I pick from these constraints:
353
+ | var | possible_values |
354
+ | user_choice | correct;; wrong |
355
+ `;
356
+ // ======= ENDS ARG ======= //
357
+ fixts.weird_spacing.tags.expected =
358
+ ` @feature_tag @spacing @alkiln @generated @randomized @constraints
359
+ Feature: I generate constrained random tests (generated by ALKiln)
360
+
361
+ @scenario_tag @spacing @scenario1_of_1
362
+ Scenario: a scenario (1 of 1)
363
+ Given I start the interview at "test_kickout"
364
+ And I get to any of the question ids ["kickout screen", "success screen"] with this data:
365
+ | var | value |
366
+ ${ fixts.RANDOM_TABLE_PLACEHOLDER }
367
+ `;
368
+ // ======= ENDS EXPECTED ======= //
369
+ fixts.weird_spacing.tags.exact_log_codes = [
370
+ `ALK0237`, `ALK0243`, `ALK0244`,
371
+ `ALK0246`, `ALK0245`, `ALK0248`, `ALK0249`, `ALK0246`, `ALK0246`, `ALK0246`, `ALK0255`, `ALK0257`, `ALK0259`, `ALK0246`,
372
+ `ALK0261`, `ALK0262`, `ALK0264`,
373
+ ];
374
+
375
+
376
+ /** Weird spacing is preserved in all tag types */
377
+ fixts.weird_spacing.tags_line_2 = {};
378
+ fixts.weird_spacing.tags_line_2.arg =
379
+ `
380
+ @line_2_tag
381
+ Feature: I generate constrained random tests
382
+
383
+ Scenario: a scenario
384
+ Given ALKiln makes 1 constrained answers test
385
+ Given I start the interview at "test_kickout"
386
+ And ALKiln will get to any of ["kickout screen", "success screen"] when I pick from these constraints:
387
+ | var | possible_values |
388
+ | user_choice | correct;; wrong |
389
+ `;
390
+ // ======= ENDS ARG ======= //
391
+ fixts.weird_spacing.tags_line_2.expected =
392
+ `
393
+ @line_2_tag @alkiln @generated @randomized @constraints
394
+ Feature: I generate constrained random tests (generated by ALKiln)
395
+
396
+ @scenario1_of_1
397
+ Scenario: a scenario (1 of 1)
398
+ Given I start the interview at "test_kickout"
399
+ And I get to any of the question ids ["kickout screen", "success screen"] with this data:
400
+ | var | value |
401
+ ${ fixts.RANDOM_TABLE_PLACEHOLDER }
402
+ `;
403
+ // ======= ENDS EXPECTED ======= //
404
+ fixts.weird_spacing.tags_line_2.exact_log_codes = [
405
+ `ALK0237`, `ALK0243`, `ALK0244`,
406
+ `ALK0245`, `ALK0248`, `ALK0249`, `ALK0246`, `ALK0246`, `ALK0246`, `ALK0255`, `ALK0257`, `ALK0259`, `ALK0246`,
407
+ `ALK0261`, `ALK0262`, `ALK0264`,
408
+ ];
409
+
410
+
411
+ /** Various lines are not indented the usual way */
412
+ fixts.weird_spacing.indents = {};
413
+ fixts.weird_spacing.indents.arg =
414
+ ` Feature: I generate constrained random tests
415
+
416
+ Scenario: a scenario
417
+ # Comment line
418
+ Given ALKiln makes 1 constrained answers tests
419
+ Given I start the interview at "interview_2"
420
+ And ALKiln will get to "end" with:
421
+ | var | possible_values |
422
+ | question_1 | opt1;; opt2;; opt3 |
423
+ | question_2 | optA;; optB;; optC |
424
+ `;
425
+ // ======= ENDS ARG ======= //
426
+ fixts.weird_spacing.indents.expected =
427
+ `@alkiln @generated @randomized @constraints
428
+ Feature: I generate constrained random tests (generated by ALKiln)
429
+
430
+ @scenario1_of_1
431
+ Scenario: a scenario (1 of 1)
432
+ # Comment line
433
+ Given I start the interview at "interview_2"
434
+ And I get to any of the question ids ["end"] with this data:
435
+ | var | value |
436
+ ${ fixts.RANDOM_TABLE_PLACEHOLDER }
437
+ `;
438
+ // ======= ENDS EXPECTED ======= //
439
+ fixts.weird_spacing.indents.exact_log_codes = [
440
+ `ALK0237`, `ALK0243`, `ALK0244`,
441
+ `ALK0246`, `ALK0245`, `ALK0248`, `ALK0249`, `ALK0246`, `ALK0246`, `ALK0246`, `ALK0255`, `ALK0257`, `ALK0259`, `ALK0246`,
442
+ `ALK0261`, `ALK0262`, `ALK0264`,
443
+ ];
444
+
445
+
446
+ /** No spacing between choices (No `.expected` val. Different kind of test) */
447
+ fixts.weird_spacing.choices = {};
448
+ fixts.weird_spacing.choices.arg =
449
+ `Feature: I generate constrained random tests
450
+
451
+ Scenario: a scenario
452
+ Given ALKiln makes 1 constrained answers test
453
+ Given I start the interview at "test_kickout"
454
+ And ALKiln will get to "end" with:
455
+ | var | possible_values |
456
+ | user_choice | correct;;wrong |
457
+ `;
458
+ // ======= ENDS ARG ======= //
459
+ fixts.weird_spacing.choices.expected = `Not appropriate to use use expected value for this test.`;
460
+ // ======= ENDS EXPECTED ======= //
461
+ fixts.weird_spacing.choices.find_1 = /(?:correct)|(?:wrong)/;
462
+ // ======= ENDS OPTIONS TO FIND ONE OF ======= //
463
+ fixts.weird_spacing.choices.exact_log_codes = [
464
+ `ALK0237`, `ALK0243`, `ALK0244`,
465
+ `ALK0245`, `ALK0248`, `ALK0249`, `ALK0246`, `ALK0246`, `ALK0246`, `ALK0255`, `ALK0257`, `ALK0259`, `ALK0246`,
466
+ `ALK0261`, `ALK0262`, `ALK0264`,
467
+ ];
468
+
469
+
470
+ /**
471
+ * ===========
472
+ * Column shenanigans
473
+ * =========== */
474
+ fixts.columns_3 = {};
475
+ fixts.columns_3.arg =
476
+ `Feature: I generate constrained random tests
477
+
478
+ Scenario: 3 columns
479
+ Given ALKiln makes 1 constrained answers test
480
+ Given I start the interview at "file.yml"
481
+ And ALKiln will get to "end" with:
482
+ | var | possible_values | column 3 becomes "trigger" |
483
+ | users[0].has_bear | True | users[0].name.first |`;
484
+ // ======= ENDS ARG ======= //
485
+ fixts.columns_3.expected =
486
+ `@alkiln @generated @randomized @constraints
487
+ Feature: I generate constrained random tests (generated by ALKiln)
488
+
489
+ @scenario1_of_1
490
+ Scenario: 3 columns (1 of 1)
491
+ Given I start the interview at "file.yml"
492
+ And I get to any of the question ids ["end"] with this data:
493
+ | var | value | trigger |
494
+ | users[0].has_bear | True | users[0].name.first |`;
495
+ // ======= ENDS EXPECTED ======= //
496
+ fixts.columns_3.exact_log_codes = [
497
+ `ALK0237`, `ALK0243`, `ALK0244`,
498
+ `ALK0245`, `ALK0248`, `ALK0249`, `ALK0246`, `ALK0246`, `ALK0246`, `ALK0255`, `ALK0257`, `ALK0259`, `ALK0246`,
499
+ `ALK0261`, `ALK0262`, `ALK0264`,
500
+ ];
501
+
502
+
503
+ fixts.columns_4 = {};
504
+ fixts.columns_4.arg =
505
+ `Feature: I generate constrained random tests
506
+
507
+ Scenario: 4 columns
508
+ Given ALKiln makes 1 constrained answers test
509
+ Given I start the interview at "file.yml"
510
+ And ALKiln will get to "end" with:
511
+ | var | possible_values | column 3 becomes "target" | column 4 is ignored |
512
+ | users[0].has_bear | True | users[0].name.first | is_ignored |`;
513
+ // ======= ENDS ARG ======= //
514
+ fixts.columns_4.expected =
515
+ `@alkiln @generated @randomized @constraints
516
+ Feature: I generate constrained random tests (generated by ALKiln)
517
+
518
+ @scenario1_of_1
519
+ Scenario: 4 columns (1 of 1)
520
+ Given I start the interview at "file.yml"
521
+ And I get to any of the question ids ["end"] with this data:
522
+ | var | value | trigger |
523
+ | users[0].has_bear | True | users[0].name.first |`;
524
+ // ======= ENDS EXPECTED ======= //
525
+ fixts.columns_4.exact_log_codes = [
526
+ `ALK0237`, `ALK0243`, `ALK0244`,
527
+ `ALK0245`, `ALK0248`, `ALK0249`, `ALK0246`, `ALK0246`, `ALK0246`, `ALK0255`, `ALK0257`, `ALK0259`, `ALK0246`,
528
+ `ALK0261`, `ALK0262`, `ALK0264`,
529
+ ];
530
+
531
+
532
+ /**
533
+ * ===========
534
+ * Row shenanigans
535
+ * =========== */
536
+ fixts.rows_comments = {};
537
+ fixts.rows_comments.arg =
538
+ `Feature: I generate constrained random tests
539
+
540
+ Scenario: Keeps comments before and in table
541
+ Given ALKiln makes 1 constrained answers test
542
+ Given I start the interview at "file.yml"
543
+ And ALKiln will get to "end" with:
544
+ # Comment 1 keep and repeat
545
+ | var | possible_values |
546
+ # Comment 2 keep and repeat
547
+ | user_choice | correct;; wrong |`;
548
+ fixts.rows_comments.expected =
549
+ `@alkiln @generated @randomized @constraints
550
+ Feature: I generate constrained random tests (generated by ALKiln)
551
+
552
+ @scenario1_of_1
553
+ Scenario: Keeps comments before and in table (1 of 1)
554
+ Given I start the interview at "file.yml"
555
+ And I get to any of the question ids ["end"] with this data:
556
+ # Comment 1 keep and repeat
557
+ | var | value |
558
+ # Comment 2 keep and repeat
559
+ ${ fixts.RANDOM_TABLE_PLACEHOLDER }`;
560
+ fixts.rows_comments.exact_log_codes = [
561
+ `ALK0237`, `ALK0243`, `ALK0244`,
562
+ `ALK0245`, `ALK0248`, `ALK0249`, `ALK0246`, `ALK0246`, `ALK0246`, `ALK0255`, `ALK0257`, `ALK0259`, `ALK0246`,
563
+ `ALK0261`, `ALK0262`, `ALK0264`,
564
+ ];
565
+
566
+
567
+ fixts.comment_after_last_row = {};
568
+ fixts.comment_after_last_row.arg =
569
+ `Feature: I generate constrained random tests
570
+
571
+ Scenario: Keeps comment after table
572
+ Given ALKiln makes 2 constrained answers tests
573
+ Given I start the interview at "file.yml"
574
+ And ALKiln will get to "end" with:
575
+ | var | possible_values |
576
+ | user_choice | correct;; wrong |
577
+ # Comment 1 keep and repeat
578
+
579
+ # Comment 2 keep and repeat`;
580
+ fixts.comment_after_last_row.expected =
581
+ `@alkiln @generated @randomized @constraints
582
+ Feature: I generate constrained random tests (generated by ALKiln)
583
+
584
+ @scenario1_of_2
585
+ Scenario: Keeps comment after table (1 of 2)
586
+ Given I start the interview at "file.yml"
587
+ And I get to any of the question ids ["end"] with this data:
588
+ | var | value |
589
+ ${ fixts.RANDOM_TABLE_PLACEHOLDER }
590
+ # Comment 1 keep and repeat
591
+
592
+ # Comment 2 keep and repeat
593
+
594
+ @scenario2_of_2
595
+ Scenario: Keeps comment after table (2 of 2)
596
+ Given I start the interview at "file.yml"
597
+ And I get to any of the question ids ["end"] with this data:
598
+ | var | value |
599
+ ${ fixts.RANDOM_TABLE_PLACEHOLDER }
600
+ # Comment 1 keep and repeat
601
+
602
+ # Comment 2 keep and repeat`;
603
+ fixts.comment_after_last_row.included_log_codes = [
604
+ `ALK0237`, `ALK0243`, `ALK0244`,
605
+ `ALK0245`, `ALK0248`, `ALK0249`, `ALK0246`, `ALK0255`, `ALK0257`, `ALK0259`,
606
+ `ALK0261`, `ALK0262`, `ALK0264`,
607
+ ];
608
+
609
+
610
+ fixts.rows_empty = {};
611
+ fixts.rows_empty.arg =
612
+ `Feature: I generate constrained random tests
613
+
614
+ Scenario: Keeps empty rows before and in table
615
+ Given ALKiln makes 1 constrained answers test
616
+ Given I start the interview at "file.yml"
617
+ And ALKiln will get to "end" with:
618
+
619
+ | var | possible_values |
620
+
621
+ | user_choice | correct;; wrong |`;
622
+ fixts.rows_empty.expected =
623
+ `@alkiln @generated @randomized @constraints
624
+ Feature: I generate constrained random tests (generated by ALKiln)
625
+
626
+ @scenario1_of_1
627
+ Scenario: Keeps empty rows before and in table (1 of 1)
628
+ Given I start the interview at "file.yml"
629
+ And I get to any of the question ids ["end"] with this data:
630
+
631
+ | var | value |
632
+
633
+ ${ fixts.RANDOM_TABLE_PLACEHOLDER }`;
634
+ fixts.rows_empty.exact_log_codes = [
635
+ `ALK0237`, `ALK0243`, `ALK0244`,
636
+ `ALK0245`, `ALK0248`, `ALK0249`, `ALK0246`, `ALK0246`, `ALK0246`, `ALK0255`, `ALK0257`, `ALK0259`, `ALK0246`,
637
+ `ALK0261`, `ALK0262`, `ALK0264`,
638
+ ];
639
+
640
+
641
+ /**
642
+ * ===========
643
+ * Warnings
644
+ * Discuss: add a "strict mode" to fail on warnings?
645
+ * =========== */
646
+ fixts.warnings = {};
647
+
648
+
649
+ fixts.warnings.no_number = {};
650
+ fixts.warnings.no_number.arg =
651
+ `Feature: I generate constrained random tests
652
+
653
+ Scenario: I'm warned with missing number in random answers generator
654
+ Given ALKiln makes not a number constrained random tests
655
+ Given I start the interview at "test_kickout"
656
+ And ALKiln gets to "end" when I pick from:
657
+ | var | possible_values |
658
+ | user_choice | correct;; wrong |`;
659
+ fixts.warnings.no_number.expected =
660
+ `@alkiln @generated @randomized @constraints
661
+ Feature: I generate constrained random tests (generated by ALKiln)
662
+
663
+ @alkiln_extra_intro @alkiln_generator_warning
664
+ Scenario: ALKiln begs the author's forgiveness. The next tests might be flawed.
665
+ Then ALKiln warns the author about a generator ${ fixts.FLUB_PLACEHOLDER }:
666
+ """
667
+ ――――― Template file warnings ―――――
668
+ 🔎 ALK0239 ${ fixts.WARNING_PLACEHOLDER }
669
+ ―――――
670
+ """
671
+
672
+ @scenario1_of_1
673
+ Scenario: I'm warned with missing number in random answers generator (1 of 1)
674
+ Given I start the interview at "test_kickout"
675
+ And I get to any of the question ids ["end"] with this data:
676
+ | var | value |
677
+ ${ fixts.RANDOM_TABLE_PLACEHOLDER }`;
678
+ fixts.warnings.no_number.exact_log_codes = [
679
+ `ALK0237`, `ALK0239`, `ALK0243`, `ALK0244`,
680
+ `ALK0245`, `ALK0248`, `ALK0249`, `ALK0246`, `ALK0246`, `ALK0246`, `ALK0255`, `ALK0257`, `ALK0259`, `ALK0246`,
681
+ `ALK0261`, `ALK0262`, `ALK0264`,
682
+ ];
683
+
684
+
685
+ fixts.warnings.multiple_numbers = {};
686
+ fixts.warnings.multiple_numbers.arg =
687
+ `Feature: I generate constrained random tests
688
+
689
+ Scenario: I'm warned with too many numbers in random answers tests
690
+ Given ALKiln makes 4 1 constrained random tests
691
+ Given I start the interview at "test_kickout"
692
+ And ALKiln gets to "end" when I pick from:
693
+ | var | possible_values |
694
+ | user_choice | correct;; wrong |`;
695
+ fixts.warnings.multiple_numbers.expected =
696
+ `@alkiln @generated @randomized @constraints
697
+ Feature: I generate constrained random tests (generated by ALKiln)
698
+
699
+ @alkiln_extra_intro @alkiln_generator_warning
700
+ Scenario: ALKiln begs the author's forgiveness. The next tests might be flawed.
701
+ Then ALKiln warns the author about a generator ${ fixts.FLUB_PLACEHOLDER }:
702
+ """
703
+ ――――― Template file warnings ―――――
704
+ 🔎 ALK0240 ${ fixts.WARNING_PLACEHOLDER }
705
+ ―――――
706
+ """
707
+
708
+ @scenario1_of_1
709
+ Scenario: I'm warned with too many numbers in random answers tests (1 of 1)
710
+ Given I start the interview at "test_kickout"
711
+ And I get to any of the question ids ["end"] with this data:
712
+ | var | value |
713
+ ${ fixts.RANDOM_TABLE_PLACEHOLDER }`;
714
+ fixts.warnings.multiple_numbers.exact_log_codes = [
715
+ `ALK0237`, `ALK0240`, `ALK0243`, `ALK0244`,
716
+ `ALK0245`, `ALK0248`, `ALK0249`, `ALK0246`, `ALK0246`, `ALK0246`, `ALK0255`, `ALK0257`, `ALK0259`, `ALK0246`,
717
+ `ALK0261`, `ALK0262`, `ALK0264`,
718
+ ];
719
+
720
+
721
+ fixts.warnings.multiple_number_Steps = {};
722
+ fixts.warnings.multiple_number_Steps.arg =
723
+ `Feature: I generate constrained random tests
724
+
725
+ Scenario: I'm warned with too many number Steps in random answers tests
726
+ Given ALKiln makes 7 constrained random tests
727
+ Given ALKiln makes 1 constrained random tests
728
+ Given I start the interview at "test_kickout"
729
+ And ALKiln gets to "end" when I pick from:
730
+ | var | possible_values |
731
+ | user_choice | correct;; wrong |`;
732
+ fixts.warnings.multiple_number_Steps.expected =
733
+ `@alkiln @generated @randomized @constraints
734
+ Feature: I generate constrained random tests (generated by ALKiln)
735
+
736
+ @alkiln_extra_intro @alkiln_generator_warning
737
+ Scenario: ALKiln begs the author's forgiveness. The next tests might be flawed.
738
+ Then ALKiln warns the author about a generator ${ fixts.FLUB_PLACEHOLDER }:
739
+ """
740
+ ――――― Template file warnings ―――――
741
+ 🔎 ALK0238 ${ fixts.WARNING_PLACEHOLDER }
742
+ ―――――
743
+ """
744
+
745
+ @scenario1_of_1
746
+ Scenario: I'm warned with too many number Steps in random answers tests (1 of 1)
747
+ Given I start the interview at "test_kickout"
748
+ And I get to any of the question ids ["end"] with this data:
749
+ | var | value |
750
+ ${ fixts.RANDOM_TABLE_PLACEHOLDER }`;
751
+ fixts.warnings.multiple_number_Steps.exact_log_codes = [
752
+ `ALK0237`, `ALK0238`, `ALK0243`, `ALK0244`,
753
+ `ALK0245`, `ALK0248`, `ALK0249`, `ALK0246`, `ALK0246`, `ALK0246`, `ALK0255`, `ALK0257`, `ALK0259`, `ALK0246`,
754
+ `ALK0261`, `ALK0262`, `ALK0264`,
755
+ ];
756
+
757
+
758
+ fixts.warnings.multiple_number_Steps_and_numbers = {};
759
+ fixts.warnings.multiple_number_Steps_and_numbers.arg =
760
+ `Feature: I generate constrained random tests
761
+
762
+ Scenario: I'm warned with too many numbers in too many numbers Steps in random answers tests
763
+ Given ALKiln makes 3 2 constrained random tests
764
+ Given ALKiln makes 4 1 constrained random tests
765
+ Given I start the interview at "test_kickout"
766
+ And ALKiln gets to "end" when I pick from:
767
+ | var | possible_values |
768
+ | user_choice | correct;; wrong |`;
769
+ fixts.warnings.multiple_number_Steps_and_numbers.expected =
770
+ `@alkiln @generated @randomized @constraints
771
+ Feature: I generate constrained random tests (generated by ALKiln)
772
+
773
+ @alkiln_extra_intro @alkiln_generator_warning
774
+ Scenario: ALKiln begs the author's forgiveness. The next tests might be flawed.
775
+ Then ALKiln warns the author about a generator ${ fixts.FLUB_PLACEHOLDER }:
776
+ """
777
+ ――――― Template file warnings ―――――
778
+ 🔎 ALK0240 ${ fixts.WARNING_PLACEHOLDER }
779
+ 🔎 ALK0238 ${ fixts.WARNING_PLACEHOLDER }
780
+ 🔎 ALK0240 ${ fixts.WARNING_PLACEHOLDER }
781
+ ―――――
782
+ """
783
+
784
+ @scenario1_of_1
785
+ Scenario: I'm warned with too many numbers in too many numbers Steps in random answers tests (1 of 1)
786
+ Given I start the interview at "test_kickout"
787
+ And I get to any of the question ids ["end"] with this data:
788
+ | var | value |
789
+ ${ fixts.RANDOM_TABLE_PLACEHOLDER }`;
790
+ fixts.warnings.multiple_number_Steps_and_numbers.exact_log_codes = [
791
+ `ALK0237`, `ALK0240`, `ALK0238`, `ALK0240`, `ALK0243`, `ALK0244`,
792
+ `ALK0245`, `ALK0248`, `ALK0249`, `ALK0246`, `ALK0246`, `ALK0246`, `ALK0255`, `ALK0257`, `ALK0259`, `ALK0246`,
793
+ `ALK0261`, `ALK0262`, `ALK0264`,
794
+ ];
795
+
796
+
797
+ fixts.warnings.fewer_unique_than_requested = {};
798
+ fixts.warnings.fewer_unique_than_requested.arg = [
799
+ `Feature: I generate valid constrained random answers tests 1
800
+
801
+ # The 1st of 2 related tests. This 1st one tests uniqueness within one Scenario.
802
+
803
+ Scenario: 1st I'm warned when I ask for too many unique tests in one generator
804
+ Given ALKiln will make 3 random constrained tests
805
+ Given I start the interview at "test_kickout"
806
+ And ALKiln will get to ["kickout screen", "success screen"] with any combination of:
807
+ | var | possible_values |
808
+ | user_choice | correct;; wrong |`,
809
+ `Feature: I generate valid constrained random answers tests 2
810
+
811
+ # The 2nd of 2 related tests. Because ALKiln will try to only generate unique tests between all the generators, this 2nd one tests uniqueness of tests between generators. Only the body of the Scenario should matter for uniqueness.
812
+
813
+ Scenario: 2nd I'm warned when I ask for too many unique tests between 2 generators
814
+ Given ALKiln will make 1 random constrained test
815
+ Given I start the interview at "test_kickout"
816
+ And ALKiln will get to ["kickout screen", "success screen"] with any combination of:
817
+ | var | possible_values |
818
+ | user_choice | correct;; wrong |`
819
+ ];
820
+ fixts.warnings.fewer_unique_than_requested.expected =
821
+ `@alkiln @generated @randomized @constraints
822
+ Feature: I generate valid constrained random answers tests 1 (generated by ALKiln)
823
+
824
+ # The 1st of 2 related tests. This 1st one tests uniqueness within one Scenario.
825
+
826
+ @alkiln_extra_intro @alkiln_generator_warning
827
+ Scenario: ALKiln begs the author's forgiveness. The next tests might be flawed.
828
+ Then ALKiln warns the author about a generator ${ fixts.FLUB_PLACEHOLDER }:
829
+ """
830
+ ――――― Template file warnings ―――――
831
+ 🔎 ALK0260 ${ fixts.WARNING_PLACEHOLDER }
832
+ ―――――
833
+ """
834
+
835
+ @scenario1_of_2
836
+ Scenario: 1st I'm warned when I ask for too many unique tests in one generator (1 of 2)
837
+ Given I start the interview at "test_kickout"
838
+ And I get to any of the question ids ["kickout screen", "success screen"] with this data:
839
+ | var | value |
840
+ ${ fixts.RANDOM_TABLE_PLACEHOLDER }
841
+
842
+ @scenario2_of_2
843
+ Scenario: 1st I'm warned when I ask for too many unique tests in one generator (2 of 2)
844
+ Given I start the interview at "test_kickout"
845
+ And I get to any of the question ids ["kickout screen", "success screen"] with this data:
846
+ | var | value |
847
+ ${ fixts.RANDOM_TABLE_PLACEHOLDER }
848
+
849
+ @alkiln @generated @randomized @constraints
850
+ Feature: I generate valid constrained random answers tests 2 (generated by ALKiln)
851
+
852
+ # The 2nd of 2 related tests. Because ALKiln will try to only generate unique tests between all the generators, this 2nd one tests uniqueness of tests between generators. Only the body of the Scenario should matter for uniqueness.
853
+
854
+ @alkiln_extra_intro @alkiln_generator_warning
855
+ Scenario: ALKiln begs the author's forgiveness. The next tests might be flawed.
856
+ Then ALKiln warns the author about a generator ${ fixts.FLUB_PLACEHOLDER }:
857
+ """
858
+ ――――― Template file warnings ―――――
859
+ 🔎 ALK0260 ${ fixts.WARNING_PLACEHOLDER }
860
+ ―――――
861
+ """
862
+
863
+ `;
864
+ fixts.warnings.fewer_unique_than_requested.find_1_of = [/\| correct \|/, /\| wrong \|/];
865
+ // The 3rd and 4th are the warning Scenarios
866
+ fixts.warnings.fewer_unique_than_requested.num_Scenarios = 4;
867
+ fixts.warnings.fewer_unique_than_requested.repeat = { code: `ALK0257`, count: 10 };
868
+ fixts.warnings.fewer_unique_than_requested.included_log_codes = [
869
+ `ALK0237`, `ALK0243`, `ALK0244`,
870
+ `ALK0245`, `ALK0248`, `ALK0249`, `ALK0246`, `ALK0255`, `ALK0257`, `ALK0259`,
871
+ `ALK0260`, `ALK0261`, `ALK0262`, `ALK0264`,
872
+ ];
873
+
874
+
875
+ fixts.warnings.over_max = {};
876
+ fixts.warnings.over_max.max_num_allowed = 1;
877
+ fixts.warnings.over_max.arg =
878
+ `Feature: I generate constrained random tests
879
+
880
+ Scenario: I'm warned of asking for more than the max num tests
881
+ Given ALKiln makes 2 constrained random tests
882
+ Given I start the interview at "test_kickout"
883
+ And ALKiln gets to "end" when I pick from:
884
+ | var | possible_values |
885
+ | user_choice | correct;; wrong |`;
886
+ fixts.warnings.over_max.expected =
887
+ `@alkiln @generated @randomized @constraints
888
+ Feature: I generate constrained random tests (generated by ALKiln)
889
+
890
+ @alkiln_extra_intro @alkiln_generator_warning
891
+ Scenario: ALKiln begs the author's forgiveness. The next tests might be flawed.
892
+ Then ALKiln warns the author about a generator ${ fixts.FLUB_PLACEHOLDER }:
893
+ """
894
+ ――――― Template file warnings ―――――
895
+ 🔎 ALK0241 ${ fixts.WARNING_PLACEHOLDER }
896
+ ―――――
897
+ """
898
+
899
+ @scenario1_of_1
900
+ Scenario: I'm warned of asking for more than the max num tests (1 of 1)
901
+ Given I start the interview at "test_kickout"
902
+ And I get to any of the question ids ["end"] with this data:
903
+ | var | value |
904
+ ${ fixts.RANDOM_TABLE_PLACEHOLDER }`;
905
+ fixts.warnings.over_max.exact_log_codes = [
906
+ `ALK0237`, `ALK0241`, `ALK0243`, `ALK0244`,
907
+ `ALK0245`, `ALK0248`, `ALK0249`, `ALK0246`, `ALK0246`, `ALK0246`, `ALK0255`, `ALK0257`, `ALK0259`, `ALK0246`,
908
+ `ALK0261`, `ALK0262`, `ALK0264`,
909
+ ];
910
+
911
+
912
+ /**
913
+ * ===========
914
+ * Silent warnings
915
+ *
916
+ * Discuss: Should we have author warnings that are only in the debug logs?
917
+ * These would be warnings for tests that aren't invalid, but may (or may
918
+ * not) have unexpected behavior. Should they have a different icon and
919
+ * keyword?
920
+ *
921
+ * Discuss: Would a "strict mode" to fail on this warning?
922
+ * =========== */
923
+
924
+ fixts.empty_string_value = {};
925
+ fixts.empty_string_value.arg =
926
+ `Feature: I generate constrained random tests
927
+
928
+ Scenario: An empty string as a value causes silent log warnings
929
+ Given ALKiln makes 2 constrained answers tests
930
+ Given I start the interview at "test_kickout"
931
+ And ALKiln will get to "end" with:
932
+ | var | possible_values |
933
+ | user_choice | correct;; |`;
934
+ fixts.empty_string_value.expected =
935
+ `@alkiln @generated @randomized @constraints
936
+ Feature: I generate constrained random tests (generated by ALKiln)
937
+
938
+ @scenario1_of_2
939
+ Scenario: An empty string as a value causes silent log warnings (1 of 2)
940
+ Given I start the interview at "test_kickout"
941
+ And I get to any of the question ids ["end"] with this data:
942
+ | var | value |
943
+ ${ fixts.RANDOM_TABLE_PLACEHOLDER }
944
+
945
+ @scenario2_of_2
946
+ Scenario: An empty string as a value causes silent log warnings (2 of 2)
947
+ Given I start the interview at "test_kickout"
948
+ And I get to any of the question ids ["end"] with this data:
949
+ | var | value |
950
+ ${ fixts.RANDOM_TABLE_PLACEHOLDER }`;
951
+ fixts.empty_string_value.find_1_of = [/\| correct \|/, /\| \|/];
952
+ fixts.empty_string_value.num_Scenarios = 2;
953
+ fixts.empty_string_value.included_log_codes = [
954
+ `ALK0237`, `ALK0243`, `ALK0244`,
955
+ `ALK0245`, `ALK0248`, `ALK0249`, `ALK0246`, `ALK0254`, `ALK0255`, `ALK0257`, `ALK0259`,
956
+ `ALK0261`, `ALK0262`, `ALK0264`,
957
+ ];