@suffolklitlab/alkiln 5.13.3-feat-random-2 → 5.13.3-feat-random-4
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/.github/workflows/github_server.yml +1 -3
- package/.github/workflows/playground.yml +2 -4
- package/CHANGELOG.md +28 -1
- package/action.yml +4 -4
- package/docs/constrained_random_tests.md +24 -0
- package/lib/run_cucumber.js +0 -6
- package/lib/setup/TestGenerator.js +31 -29
- package/lib/steps.js +1 -17
- package/lib/utils/Log.js +0 -10
- package/lib/utils/session_vars.js +2 -3
- package/package.json +1 -1
- package/tests/unit_tests/constrained_random_answers/valid.fixtures.js +49 -12
- package/tests/unit_tests/constrained_random_answers/valid.test.js +23 -1
- package/_alkiln_meta/shift_logs.js +0 -75
|
@@ -159,9 +159,7 @@ jobs:
|
|
|
159
159
|
INSTALL_METHOD: "server"
|
|
160
160
|
#### Developer note: You can probably leave the rest out
|
|
161
161
|
#### To learn more, see https://assemblyline.suffolklitlab.org/docs/alkiln/writing/#optional-inputs
|
|
162
|
-
|
|
163
|
-
# Temp debugging GitHub multi-folder problem
|
|
164
|
-
ALKILN_TAG_EXPRESSION: "@rp1"
|
|
162
|
+
ALKILN_TAG_EXPRESSION: "${{ env.ALKILN_TAG_EXPRESSION }}"
|
|
165
163
|
ALKILN_VERSION: random
|
|
166
164
|
|
|
167
165
|
#### Developer note: Example of making an issue when tests fail
|
|
@@ -76,12 +76,10 @@ jobs:
|
|
|
76
76
|
DOCASSEMBLE_DEVELOPER_API_KEY: "${{ env.DOCASSEMBLE_DEVELOPER_API_KEY }}"
|
|
77
77
|
#### Developer note: See https://assemblyline.suffolklitlab.org/docs/alkiln/writing/#optional-inputs
|
|
78
78
|
#### You can probably leave this out
|
|
79
|
-
|
|
79
|
+
ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO: 10
|
|
80
80
|
# Internal: docassemble changes sometimes break @a11y tests. That is
|
|
81
81
|
# a da problem, not ours. We will trigger these tests manually when we
|
|
82
82
|
# want to check up on this.
|
|
83
|
-
|
|
84
|
-
# Temp debugging GitHub multi-folder problem
|
|
85
|
-
ALKILN_TAG_EXPRESSION: "@rp1"
|
|
83
|
+
ALKILN_TAG_EXPRESSION: "${{ env.ALKILN_TAG_EXPRESSION }}"
|
|
86
84
|
#### Developer note: You can probably leave this out
|
|
87
85
|
ALKILN_VERSION: random
|
package/CHANGELOG.md
CHANGED
|
@@ -43,7 +43,34 @@ Format:
|
|
|
43
43
|
-
|
|
44
44
|
-->
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
## [Unreleased]
|
|
47
|
+
|
|
48
|
+
### Added
|
|
49
|
+
|
|
50
|
+
- Add the `constrained random answers` Step. You must put the Step in a "constrained random test template" Scenario which goes in a "constrained random test template" file - a `.feature` file that starts with "alkiln_random". The file **MUST have ONLY 1 Scenario per template file** at the moment. The Step is pretty strict. If there are irregularities, it will probably fail, but it will fail quickly. It is flexible about number of tests, though, and will default to 1. Closes [#962](https://github.com/SuffolkLITLab/ALKiln/issues/962).
|
|
51
|
+
- Add `ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO` optional environment variable for the above `constrained random answers` Step. Default value is `40` until we hear otherwise.
|
|
52
|
+
- Regular tests that have incorrect syntax will fail more quickly now - very near the start. So will invalid "constrained random test template" files. This will be a little slower for GitHub Sandbox tests right now, but still faster than it has been in the past. Closes [#972](https://github.com/SuffolkLITLab/ALKiln/issues/972).
|
|
53
|
+
|
|
54
|
+
### Changed
|
|
55
|
+
|
|
56
|
+
- Improve report indentation and tweak styling.
|
|
57
|
+
- Clarify some logs, including addressing bite-sized issues like [#981](https://github.com/SuffolkLITLab/ALKiln/issues/981).
|
|
58
|
+
- The report now shows the name of every Step that gets run in a test.
|
|
59
|
+
|
|
60
|
+
### Internal
|
|
61
|
+
|
|
62
|
+
- Added: `lib/globals.js` file to hold some shared constant values across the framework. It should NOT manage state. We may want to change the name to `constants.js` or `global_contants.js`. Let's see how it serves us.
|
|
63
|
+
- Added: executable scripts for more setup steps - managing the artifacts path (at the start of a run) and validating and generating files.
|
|
64
|
+
- Changed: `Log` now prioritizes what folder it stores files in in this order:
|
|
65
|
+
1. Use the argument to use an existing folder and save that to runtime_config.json at root.
|
|
66
|
+
2. Use the argument to make a new folder with that name and save that to runtime_config.json at root.
|
|
67
|
+
3. Use the alread-existing folder name value in runtime_config.json at root
|
|
68
|
+
4. Create a new folder and save that to runtime_config.json at root
|
|
69
|
+
- Changed: Add `.error()` to `Log` for visual clarity when storing an error to throw later. We need to discuss this behavior and its return value. To make that work Logs can now get the `error` prop without throwing an error.
|
|
70
|
+
- Changed: the Story Table step now accepts multiple ids and stops at whatever id it reaches first. I highly recommend that only ALKiln generated tests use this feature. We may avoid documenting it unless authors ask for it.
|
|
71
|
+
- Changed: `.gitignore` and `.npmignore` more things
|
|
72
|
+
- Fixed: log codes checker obob.
|
|
73
|
+
- Fixed: updated `actions/upload-artifact@v3` to `actions/upload-artifact@v4`
|
|
47
74
|
|
|
48
75
|
## [5.13.4] - 2025-01-11
|
|
49
76
|
|
package/action.yml
CHANGED
|
@@ -33,7 +33,7 @@ inputs:
|
|
|
33
33
|
description: "The version of docassemblecli to install."
|
|
34
34
|
required: false
|
|
35
35
|
default: "0.0.17"
|
|
36
|
-
|
|
36
|
+
ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO:
|
|
37
37
|
description: "The maximum number of tests ALKiln will generate for every Scenario that can generate tests."
|
|
38
38
|
required: false
|
|
39
39
|
# Default will be internal to avoid duplication of data
|
|
@@ -72,7 +72,7 @@ runs:
|
|
|
72
72
|
MAX_SECONDS_FOR_SETUP: ${{ inputs.MAX_SECONDS_FOR_SETUP }}
|
|
73
73
|
SERVER_RELOAD_TIMEOUT_SECONDS: ${{ inputs.SERVER_RELOAD_TIMEOUT_SECONDS }}
|
|
74
74
|
DOCASSEMBLECLI_VERSION: ${{ inputs.DOCASSEMBLECLI_VERSION }}
|
|
75
|
-
|
|
75
|
+
ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO: ${{ inputs.ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO }}
|
|
76
76
|
shell: bash
|
|
77
77
|
run: |
|
|
78
78
|
log="💡 ALK0023 INFO: Set environment variables and create artifacts folder"
|
|
@@ -96,7 +96,7 @@ runs:
|
|
|
96
96
|
echo "DOCASSEMBLE_DEVELOPER_API_KEY=$DOCASSEMBLE_DEVELOPER_API_KEY" >> $GITHUB_ENV
|
|
97
97
|
echo "ALKILN_VERSION=$ALKILN_VERSION" >> $GITHUB_ENV
|
|
98
98
|
echo "MAX_SECONDS_FOR_SETUP=$MAX_SECONDS_FOR_SETUP" >> $GITHUB_ENV
|
|
99
|
-
echo "
|
|
99
|
+
echo "ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO=$ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO" >> $GITHUB_ENV
|
|
100
100
|
echo "SERVER_RELOAD_TIMEOUT_SECONDS=$SERVER_RELOAD_TIMEOUT_SECONDS" >> $GITHUB_ENV
|
|
101
101
|
echo "DOCASSEMBLECLI_VERSION=$DOCASSEMBLECLI_VERSION" >> $GITHUB_ENV
|
|
102
102
|
# Hard-coded internal ALKiln vars
|
|
@@ -106,7 +106,7 @@ runs:
|
|
|
106
106
|
run: |
|
|
107
107
|
log="💡 ALK0024 INFO: Confirm environment variables"
|
|
108
108
|
echo -e "\n$log" >> "${{ env.DEBUG_PATH }}"
|
|
109
|
-
vars_log='\nALKiln version is ${{ env.ALKILN_VERSION }}\nRepo is "${{ env.REPO_URL }}"\nBranch ref is "${{ env.BRANCH_PATH }}"\nCustom MAX_SECONDS_FOR_SETUP is "${{ env.MAX_SECONDS_FOR_SETUP }}"\nCustom SERVER_RELOAD_TIMEOUT_SECONDS is "${{ env.SERVER_RELOAD_TIMEOUT_SECONDS }}"\nCustom
|
|
109
|
+
vars_log='\nALKiln version is ${{ env.ALKILN_VERSION }}\nRepo is "${{ env.REPO_URL }}"\nBranch ref is "${{ env.BRANCH_PATH }}"\nCustom MAX_SECONDS_FOR_SETUP is "${{ env.MAX_SECONDS_FOR_SETUP }}"\nCustom SERVER_RELOAD_TIMEOUT_SECONDS is "${{ env.SERVER_RELOAD_TIMEOUT_SECONDS }}"\nCustom ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO is "${{ env.ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO }}"\n'
|
|
110
110
|
echo -e "$vars_log" >> "${{ env.DEBUG_PATH }}" && echo -e "$vars_log"
|
|
111
111
|
|
|
112
112
|
# Install ALKiln during GitHub workflow
|
|
@@ -252,3 +252,27 @@ Scenario: I visit the zoo
|
|
|
252
252
|
|
|
253
253
|
The AST doesn't have a list of lines. For examples, Scenarios and comments are in separate lists. The AST also stores line numbers, so we'd have to keep updating line numbers for every object, which adds complexity. We've currently decided that the more structured model isn't worth that complexity.
|
|
254
254
|
|
|
255
|
+
|
|
256
|
+
## Ranges may not be that useful
|
|
257
|
+
|
|
258
|
+
Focused tests with actual thought out options are so useful. Take these examples:
|
|
259
|
+
|
|
260
|
+
```gherkin
|
|
261
|
+
# ❌ Too broad: May miss important scenarios
|
|
262
|
+
Then ALKiln will stop at "end" with any combination of:
|
|
263
|
+
| var | possible values |
|
|
264
|
+
| income | 0..1000000 |
|
|
265
|
+
| assets | 0..1000000 |
|
|
266
|
+
|
|
267
|
+
# ✅ Better: Focused ranges with critical points
|
|
268
|
+
Then ALKiln will stop at "end" with any combination of:
|
|
269
|
+
| var | possible values |
|
|
270
|
+
| income | 0;; 30000;; 50000;; 75000;; 100000 |
|
|
271
|
+
| assets | 0;; 50000;; 100000;; 250000 |
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
The first one will make a lot of useless tests. Is there a way to have a cake and eat it too? I'm not sure. Example:
|
|
275
|
+
|
|
276
|
+
```
|
|
277
|
+
| income | 0..100;; 900..1000 |
|
|
278
|
+
```
|
package/lib/run_cucumber.js
CHANGED
|
@@ -79,12 +79,6 @@ async function main() {
|
|
|
79
79
|
log.info({ code: `ALK0049`, context: `pre_run environment` },
|
|
80
80
|
environment
|
|
81
81
|
);
|
|
82
|
-
|
|
83
|
-
// TODO: These are not used as far as I can tell. Delete them
|
|
84
|
-
// // We'll use the user info to construct the possible paths to /sources
|
|
85
|
-
// let id = session_vars.get_user_id();
|
|
86
|
-
// // `project` is the name in the server docassemble "Project" page
|
|
87
|
-
// let project = session_vars.get_user_project_name();
|
|
88
82
|
|
|
89
83
|
const { runConfiguration } = await cucumber_api.loadConfiguration({
|
|
90
84
|
provided: build_config( argv ),
|
|
@@ -7,19 +7,18 @@ const get_Gherkin_AST = require(`./get_Gherkin_AST`);
|
|
|
7
7
|
const get_error_stacks = require(`../utils/get_error_stacks`);
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* TODO:
|
|
11
|
-
*
|
|
12
|
-
* (like "missing number in constraints random test")
|
|
10
|
+
* TODO: Update ALKilnInThePlayground to let author download the generated
|
|
11
|
+
* tests. Also, store them in a unique location.
|
|
13
12
|
* TODO: Post-MVP, don't repeat tests that the author has already created
|
|
14
13
|
* TODO: Post-MVP, write Steps that warn about fore-Steps and constraints Steps
|
|
15
14
|
* when they appear in a regular test. It probably means someone named the
|
|
16
15
|
* file incorrectly.
|
|
17
|
-
* Discuss: Require author to use "
|
|
18
|
-
* "
|
|
19
|
-
* scan) for 2 reasons. 1. Gets the vocab of "
|
|
16
|
+
* Discuss: Require author to use "Template Scenario:" as they keyword (Also
|
|
17
|
+
* "Template Scenario Outline:") (or "Scenario Template", maybe harder to
|
|
18
|
+
* scan) for 2 reasons. 1. Gets the vocab of "template" in early (though
|
|
20
19
|
* that doesn't match "constraints" Step, which is a whole other language
|
|
21
|
-
* problem we haven't solved yet.) 2. Saying "
|
|
22
|
-
* is confusing when "Scenario" means different things - a
|
|
20
|
+
* problem we haven't solved yet.) 2. Saying "ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO"
|
|
21
|
+
* is confusing when "Scenario" means different things - a template
|
|
23
22
|
* Scenario and a regular Scenario.
|
|
24
23
|
* Discuss: Now that Log is less fragile and duplicated, shall we create a new
|
|
25
24
|
* Log instance in here?
|
|
@@ -30,6 +29,9 @@ const get_error_stacks = require(`../utils/get_error_stacks`);
|
|
|
30
29
|
* do that now, but without the icon.
|
|
31
30
|
* Discuss: If/when we allow multiple Scenarios, research how we find the end
|
|
32
31
|
* of a Scenario that ends in an `Example`.
|
|
32
|
+
* Discuss: We might give various levels of categories for warnings. For example,
|
|
33
|
+
* severe warnings (like "will skip the random test") vs. slight warnings
|
|
34
|
+
* (like "missing number in constraints random test")
|
|
33
35
|
* */
|
|
34
36
|
|
|
35
37
|
let log = null;
|
|
@@ -177,7 +179,7 @@ module.exports = class TestGenerator {
|
|
|
177
179
|
let scenario_objs = doc_AST.feature.children;
|
|
178
180
|
if ( !scenario_objs[0] ) {
|
|
179
181
|
let syntax_error = log.error({ code: `ALK0235`, context: `generating files`, before: `\n\n`, },
|
|
180
|
-
`
|
|
182
|
+
`It looks like the author's template .feature file at "${ generator_path }" has 0 Scenarios.`
|
|
181
183
|
);
|
|
182
184
|
return { new_contents: null, errors: [new Error( syntax_error )]};
|
|
183
185
|
}
|
|
@@ -185,7 +187,7 @@ module.exports = class TestGenerator {
|
|
|
185
187
|
|
|
186
188
|
if ( scenario_objs.length > 1 ) {
|
|
187
189
|
let too_many_scenarios = log.error({ code: `ALK0236`, context: `generating files`, },
|
|
188
|
-
`A
|
|
190
|
+
`A template file can only have 1 template Scenario. This one has ${ scenario_objs.length }.`
|
|
189
191
|
);
|
|
190
192
|
return { new_contents: ``, errors: [new Error( too_many_scenarios )] };
|
|
191
193
|
}
|
|
@@ -250,7 +252,7 @@ module.exports = class TestGenerator {
|
|
|
250
252
|
let errs_n_warns = new Misbehaviors();
|
|
251
253
|
|
|
252
254
|
let strs_for_all_new_Scenarios = [];
|
|
253
|
-
// Soon we want to be able to handle multiple
|
|
255
|
+
// Soon we want to be able to handle multiple template Scenarios per file
|
|
254
256
|
for ( let scenario_obj_i = 0; scenario_obj_i < scenario_objs.length; scenario_obj_i++ ) {
|
|
255
257
|
|
|
256
258
|
errs_n_warns.reset_warnings();
|
|
@@ -370,11 +372,11 @@ module.exports = class TestGenerator {
|
|
|
370
372
|
|
|
371
373
|
let got_fewer_tests_than_desired = new_test_bodies.length < num_to_make;
|
|
372
374
|
if ( got_fewer_tests_than_desired ) {
|
|
373
|
-
let warn_too_few = log.warn({ code: `ALK0260`, context: `generating files
|
|
374
|
-
`ALKiln could only make ${ new_test_bodies.length } *unique* tests out of the ${ num_to_make } the author wanted for this Scenario. Note that ALKiln compares all generated Scenarios with each other to make sure all are unique. This Scenario may be a duplicate of a Scenario generated
|
|
375
|
+
let warn_too_few = log.warn({ code: `ALK0260`, context: `generating files template-scenario-level`, },
|
|
376
|
+
`ALKiln could only make ${ new_test_bodies.length } *unique* tests out of the ${ num_to_make } the author wanted for this Scenario. Note that ALKiln compares all generated Scenarios with each other to make sure all are unique. This Scenario may be a duplicate of a Scenario generated from a previous template. The Scenario:\n ${ scenario_description_for_logs({ scenario }) }`,
|
|
375
377
|
)
|
|
376
378
|
// Discuss: Should we add more structure to Misbehaviors to give them
|
|
377
|
-
// context levels (Feature,
|
|
379
|
+
// context levels (Feature, template Scenario, generated Scenario)
|
|
378
380
|
misfits.add({ warnings: [ warn_too_few ] });
|
|
379
381
|
}
|
|
380
382
|
|
|
@@ -493,7 +495,7 @@ function get_generator_AST({ file_text, generator_path }) {
|
|
|
493
495
|
|
|
494
496
|
if ( generator_errors.length > 0 ) {
|
|
495
497
|
let syntax_error = log.error({ code: `ALK0232`, context: `generating files`, before: `\n\n`, },
|
|
496
|
-
`The author's
|
|
498
|
+
`The author's template .feature file at "${ generator_path }" has Gherkin syntax error(s). You might see more warnings above or below this one.\n`,
|
|
497
499
|
...get_error_stacks({ errors: generator_errors })
|
|
498
500
|
);
|
|
499
501
|
return { doc_AST: null, errors: [new Error( syntax_error )] };
|
|
@@ -503,14 +505,14 @@ function get_generator_AST({ file_text, generator_path }) {
|
|
|
503
505
|
|
|
504
506
|
if ( !doc_AST.feature ) {
|
|
505
507
|
let feature_error = log.error({ code: `ALK0233`, context: `generating files`, before: `\n\n`, },
|
|
506
|
-
`The author's
|
|
508
|
+
`The author's template .feature file at "${ generator_path }" needs to include the \`Feature\` keyword.`
|
|
507
509
|
);
|
|
508
510
|
return { doc_AST: null, errors: [new Error( feature_error )] };
|
|
509
511
|
}
|
|
510
512
|
|
|
511
513
|
// Should not get here
|
|
512
514
|
let unknown_error = log.error({ code: `ALK0234`, context: `generating files`, before: `\n\n`, },
|
|
513
|
-
`The author's
|
|
515
|
+
`The author's template .feature file at "${ generator_path }" ran into an unanticipated error when ALKiln tried to parse it. If you have a moment, we would love for you to send us your debug.txt.`
|
|
514
516
|
);
|
|
515
517
|
return { doc_AST, errors: [new Error( unknown_error )] };
|
|
516
518
|
}
|
|
@@ -657,7 +659,7 @@ function get_fore_Steps({ scenario }) {
|
|
|
657
659
|
if ( there_were_no_fore_Steps ) {
|
|
658
660
|
misfits.add({ errors: [
|
|
659
661
|
new Error( log.error({ code: `ALK0242`, context: `generating files`, },
|
|
660
|
-
`A
|
|
662
|
+
`A template Scenario's first Step must say how many constrained random answers tests to make. The template Scenario on line ${ scenario.location.line } is missing that Step. The Scenario's description is:\n${ description }`
|
|
661
663
|
) )
|
|
662
664
|
] });
|
|
663
665
|
} else {
|
|
@@ -724,7 +726,7 @@ function get_number_of_Scenarios_to_generate2({ step, prev_num_to_make }) {
|
|
|
724
726
|
// a way that is also maintainable?
|
|
725
727
|
warnings.push(
|
|
726
728
|
log.warn({ code: `ALK0238`, context: `generating files`, },
|
|
727
|
-
`A
|
|
729
|
+
`A template Scenario has too many Steps that set the number of tests to make. ALKiln will use the final number Step it finds or calculates. The current Step:\n ${ text }`
|
|
728
730
|
)
|
|
729
731
|
);
|
|
730
732
|
}
|
|
@@ -735,7 +737,7 @@ function get_number_of_Scenarios_to_generate2({ step, prev_num_to_make }) {
|
|
|
735
737
|
if ( number_matcher === null ) {
|
|
736
738
|
warnings.push(
|
|
737
739
|
log.warn({ code: `ALK0239`, context: `generating files`, },
|
|
738
|
-
`A
|
|
740
|
+
`A template Scenario is missing the number of tests to make. ALKiln will now make 1 constrained random answers test. The current Step:\n ${ text }`
|
|
739
741
|
)
|
|
740
742
|
);
|
|
741
743
|
return { num_to_make: 1, warnings, errors };
|
|
@@ -759,14 +761,14 @@ function get_number_of_Scenarios_to_generate2({ step, prev_num_to_make }) {
|
|
|
759
761
|
}
|
|
760
762
|
|
|
761
763
|
let num_to_make = Math.min(
|
|
762
|
-
session_vars.
|
|
764
|
+
session_vars.get_max_tests_per_template_scenario(),
|
|
763
765
|
user_num
|
|
764
766
|
);
|
|
765
767
|
|
|
766
768
|
if ( num_to_make !== user_num ) {
|
|
767
769
|
warnings.push(
|
|
768
770
|
log.warn({ code: `ALK0241`, context: `generating files`, },
|
|
769
|
-
`The author asked to make ${ user_num } tests, but maximum allowed is ${ num_to_make }. ALKiln will now make ${ num_to_make } tests. If you want to increase the maximum, use the
|
|
771
|
+
`The author asked to make ${ user_num } tests, but maximum allowed is ${ num_to_make }. ALKiln will now make ${ num_to_make } tests. If you want to increase the maximum, use the ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO input. Read more about inputs at https://assemblyline.suffolklitlab.org/docs/alkiln/writing/#workflow-inputs. The Step:\n ${ text }`
|
|
770
772
|
)
|
|
771
773
|
);
|
|
772
774
|
}
|
|
@@ -1099,7 +1101,7 @@ function get_final_ids({ step_text }) {
|
|
|
1099
1101
|
let ids = step_text.match( CAPTURE_QUESTION_IDS_REGEX );
|
|
1100
1102
|
|
|
1101
1103
|
if ( ids === null ) {
|
|
1102
|
-
let missing_ids_msg = `The constrained random answers Step is missing its question ids. ALKiln is unable to create random tests for this
|
|
1104
|
+
let missing_ids_msg = `The constrained random answers Step is missing its question ids. ALKiln is unable to create random tests for this template Scenario. The Step:\n${ step_text }`;
|
|
1103
1105
|
let error = log.error({ code: `ALK0250`, context: `generating files`, }, missing_ids_msg );
|
|
1104
1106
|
errors.push(new Error( error ));
|
|
1105
1107
|
}
|
|
@@ -1348,7 +1350,7 @@ function remove_warning_tag_placeholder({ new_text }) {
|
|
|
1348
1350
|
|
|
1349
1351
|
|
|
1350
1352
|
function add_total_tests({ scenario_group_str, num_tests }) {
|
|
1351
|
-
/** Paste in the total number of tests generated for this
|
|
1353
|
+
/** Paste in the total number of tests generated for this template Scenario.
|
|
1352
1354
|
*
|
|
1353
1355
|
* @param {object} obj - Named arguments
|
|
1354
1356
|
* @param {str} obj.scenario_group_str - The combined string of all the
|
|
@@ -1369,10 +1371,10 @@ function add_warnings_Scenario({ scenarios_str, warnings }) {
|
|
|
1369
1371
|
* Scenarios. Basically, a whole-generator-scope warning.
|
|
1370
1372
|
*
|
|
1371
1373
|
* Discuss: Add a pre-group Scenario for every group of generated Scenarios
|
|
1372
|
-
* identifying the
|
|
1374
|
+
* identifying the template Scenario of the subsequent new Scenarios.
|
|
1373
1375
|
* That is, even when there is no warning to give.
|
|
1374
1376
|
*
|
|
1375
|
-
* TODO: If/when we allow multiple
|
|
1377
|
+
* TODO: If/when we allow multiple template Scenarios, use the ID here too
|
|
1376
1378
|
*
|
|
1377
1379
|
* @param {object} obj - Named arguments
|
|
1378
1380
|
* @param {str} obj.scenarios_str - The str of the already existing Scenarios
|
|
@@ -1381,7 +1383,7 @@ function add_warnings_Scenario({ scenarios_str, warnings }) {
|
|
|
1381
1383
|
* @returns {str} - The text of the combined Scenarios.
|
|
1382
1384
|
* */
|
|
1383
1385
|
let tags = `@alkiln_extra_intro ${ ALKILN_WARNING_TAG }`;
|
|
1384
|
-
let keyword_line = `Scenario: ALKiln
|
|
1386
|
+
let keyword_line = `Scenario: ALKiln begs the author's forgiveness. The next tests might be flawed.`;
|
|
1385
1387
|
let step_text = get_goofy_warnings_Step_text();
|
|
1386
1388
|
|
|
1387
1389
|
let warnings_lines = warnings_as_list_of_lines({ warnings });
|
|
@@ -1435,7 +1437,7 @@ function get_warnings_docstring({ warnings_lines, indent }) {
|
|
|
1435
1437
|
* */
|
|
1436
1438
|
let doc_str_lines = [
|
|
1437
1439
|
`"""`,
|
|
1438
|
-
`―――――
|
|
1440
|
+
`――――― Template file warnings ―――――`,
|
|
1439
1441
|
...warnings_lines,
|
|
1440
1442
|
`―――――`,
|
|
1441
1443
|
`"""`,
|
|
@@ -1506,7 +1508,7 @@ function save_files({ tests_path, artifacts_path, file_strings }) {
|
|
|
1506
1508
|
|
|
1507
1509
|
let count = 1;
|
|
1508
1510
|
for ( let file_str of file_strings ) {
|
|
1509
|
-
let filename =
|
|
1511
|
+
let filename = `_alkiln_generated_${ count }_${ Date.now() }.feature`;
|
|
1510
1512
|
count++;
|
|
1511
1513
|
// Implementation note: If the files don't exist, this creates them
|
|
1512
1514
|
fs.appendFileSync( `${ tests_path }/${ filename }`, file_str );
|
package/lib/steps.js
CHANGED
|
@@ -99,28 +99,12 @@ BeforeAll(async function() {
|
|
|
99
99
|
// Store path names for files and docs created for the tests
|
|
100
100
|
scope.paths = {};
|
|
101
101
|
|
|
102
|
-
// // Make the folder to store all the files for this run of the tests
|
|
103
|
-
// scope.paths.artifacts = files.make_artifacts_folder();
|
|
104
|
-
// // Save its name in a file. `session_vars` can get it back later.
|
|
105
|
-
// // The value we are saving is used by at least run_cucumber.js.
|
|
106
|
-
|
|
107
102
|
// A little indirect, but the artifacts path should always have already been
|
|
108
103
|
// created by now, either by `run_cucumber.js` or the relevant test
|
|
109
|
-
|
|
110
|
-
// // TODO: Is this causing the GitHub tests artifacts trouble? Because
|
|
111
|
-
// // `.get_artifacts_path_name()` is messing up somehow? That shouldn't be a
|
|
112
|
-
// // problem. That's the same method `Log` uses. Why does runtime_config not
|
|
113
|
-
// // have a value here?
|
|
114
|
-
// scope.paths.artifacts = session_vars.get_artifacts_path_name();
|
|
115
|
-
// log = new Log({ path: scope.paths.artifacts, context: `steps` });
|
|
116
|
-
|
|
117
|
-
console.log(`\n\n`, `scope.paths.artifacts:`, scope.paths.artifacts, `\n\n`);
|
|
118
|
-
// New attempt avoids passing in a path. For the record, this shouldn't help.
|
|
119
104
|
log = new Log({ context: `steps` });
|
|
120
105
|
scope.set_log({ log_obj: log });
|
|
121
106
|
|
|
122
107
|
scope.paths.artifacts = session_vars.get_artifacts_path_name();
|
|
123
|
-
|
|
124
108
|
scope.paths.debug_log = `${ scope.paths.artifacts }/${ log.debug_log_filename }`;
|
|
125
109
|
scope.paths.report_log = `${ scope.paths.artifacts }/${ log.report_log_filename }`;
|
|
126
110
|
scope.paths.report = `${ scope.paths.artifacts }/${ log.report_filename }`;
|
|
@@ -196,7 +180,7 @@ BeforeStep(async function ( step ) {
|
|
|
196
180
|
// start of a Step after it's been completed, as cucumber already does. Add
|
|
197
181
|
// a 'step' type and additional success/failure information, though that
|
|
198
182
|
// may be challenging.
|
|
199
|
-
reports.addToReport(scope, { type: `row
|
|
183
|
+
reports.addToReport(scope, { type: `row`, value: step.pickleStep.text });
|
|
200
184
|
reports.indent();
|
|
201
185
|
});
|
|
202
186
|
|
package/lib/utils/Log.js
CHANGED
|
@@ -147,8 +147,6 @@ class Log {
|
|
|
147
147
|
* const log = new Log({ path: "_alkiln-123", context: "setup" });
|
|
148
148
|
* */
|
|
149
149
|
|
|
150
|
-
console.trace(`\n\nCreating from Log`);
|
|
151
|
-
|
|
152
150
|
// These records help internal tests check for correct behavior
|
|
153
151
|
this.internal_log_records = [];
|
|
154
152
|
|
|
@@ -164,7 +162,6 @@ class Log {
|
|
|
164
162
|
if ( context ) { context = context + ` log`; }
|
|
165
163
|
else { context = `log`; }
|
|
166
164
|
let files_msg = `ALKiln will save test results files at "${ this.path }"`;
|
|
167
|
-
console.log(`🐛🐛🐛🐛🐛 ALKTemp debugging Log path. Calculated path:`, this.path);
|
|
168
165
|
if ( is_new_folder ) {
|
|
169
166
|
this.info({ code: `ALK0214`, context, }, files_msg );
|
|
170
167
|
} else {
|
|
@@ -220,30 +217,23 @@ class Log {
|
|
|
220
217
|
* */
|
|
221
218
|
try {
|
|
222
219
|
|
|
223
|
-
console.log(`🐛🐛🐛🐛🐛 ALKTemp debugging Log path. Given dir:`, dir);
|
|
224
|
-
|
|
225
220
|
// GitHub actions pass in a dir, but other processes, like
|
|
226
221
|
// ALKilnInThePlayground, don't have a path
|
|
227
222
|
if ( !dir ) {
|
|
228
|
-
console.log(`🐛🐛🐛🐛🐛 ALKTemp debugging Log path. No dir given`);
|
|
229
223
|
if ( session_vars.get_artifacts_path_name() ) {
|
|
230
|
-
console.log(`🐛🐛🐛🐛🐛 ALKTemp debugging Log path. Artifacts path already has a name`);
|
|
231
224
|
dir = session_vars.get_artifacts_path_name();
|
|
232
225
|
} else {
|
|
233
|
-
console.log(`🐛🐛🐛🐛🐛 ALKTemp debugging Log path. Making brand new artifacts path`);
|
|
234
226
|
dir = files.make_artifacts_folder();
|
|
235
227
|
}
|
|
236
228
|
}
|
|
237
229
|
|
|
238
230
|
if ( !fs.existsSync( dir )) {
|
|
239
|
-
console.log(`🐛🐛🐛🐛🐛 ALKTemp debugging Log path. Artifacts path dir doesn't yet exist`);
|
|
240
231
|
files.make_artifacts_folder( dir );
|
|
241
232
|
}
|
|
242
233
|
|
|
243
234
|
return { dir, errors: [] };
|
|
244
235
|
|
|
245
236
|
} catch ( error_making_dir ) {
|
|
246
|
-
// Logs should fail silently. With no dir, though, we can't save the error
|
|
247
237
|
return { dir, errors: [ error_making_dir ]};
|
|
248
238
|
}
|
|
249
239
|
|
|
@@ -73,7 +73,7 @@ session_vars.get_setup_timeout_ms = function () {
|
|
|
73
73
|
return timeout;
|
|
74
74
|
};
|
|
75
75
|
|
|
76
|
-
session_vars.
|
|
76
|
+
session_vars.get_max_tests_per_template_scenario = function() {
|
|
77
77
|
/** Returns the maximum number of tests to generate for any one generator
|
|
78
78
|
* Scenario.
|
|
79
79
|
*
|
|
@@ -82,7 +82,7 @@ session_vars.get_max_tests_per_generator_scenario = function() {
|
|
|
82
82
|
*
|
|
83
83
|
* @returns {int} - Max number of tests for one generator Scenario
|
|
84
84
|
* */
|
|
85
|
-
return process.env.
|
|
85
|
+
return process.env.ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO || 40;
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
session_vars.get_da_server_url = function () {
|
|
@@ -280,7 +280,6 @@ session_vars.get_runtime_config_var = function ( key ) {
|
|
|
280
280
|
try {
|
|
281
281
|
let json = JSON.parse( fs.readFileSync( runtime_config_path ));
|
|
282
282
|
let value = json[ key ];
|
|
283
|
-
console.log(`🐛🐛🐛🐛🐛 ALK00temp config key/value pair:`, key, value);
|
|
284
283
|
if ( session_vars.get_debug() ) {
|
|
285
284
|
console.debug( `🐛 ALK0041 DEBUG: Runtime config var "${ key }" is "${ value }".` );
|
|
286
285
|
}
|
package/package.json
CHANGED
|
@@ -677,10 +677,10 @@ fixts.warnings.no_number.expected =
|
|
|
677
677
|
Feature: I generate constrained random tests (generated by ALKiln)
|
|
678
678
|
|
|
679
679
|
@alkiln_extra_intro @alkiln_generator_warning
|
|
680
|
-
Scenario: ALKiln
|
|
680
|
+
Scenario: ALKiln begs the author's forgiveness. The next tests might be flawed.
|
|
681
681
|
Then ALKiln warns the author about a generator ${ fixts.FLUB_PLACEHOLDER }:
|
|
682
682
|
"""
|
|
683
|
-
―――――
|
|
683
|
+
――――― Template file warnings ―――――
|
|
684
684
|
🔎 ALK0239 ${ fixts.WARNING_PLACEHOLDER }
|
|
685
685
|
―――――
|
|
686
686
|
"""
|
|
@@ -713,10 +713,10 @@ fixts.warnings.multiple_numbers.expected =
|
|
|
713
713
|
Feature: I generate constrained random tests (generated by ALKiln)
|
|
714
714
|
|
|
715
715
|
@alkiln_extra_intro @alkiln_generator_warning
|
|
716
|
-
Scenario: ALKiln
|
|
716
|
+
Scenario: ALKiln begs the author's forgiveness. The next tests might be flawed.
|
|
717
717
|
Then ALKiln warns the author about a generator ${ fixts.FLUB_PLACEHOLDER }:
|
|
718
718
|
"""
|
|
719
|
-
―――――
|
|
719
|
+
――――― Template file warnings ―――――
|
|
720
720
|
🔎 ALK0240 ${ fixts.WARNING_PLACEHOLDER }
|
|
721
721
|
―――――
|
|
722
722
|
"""
|
|
@@ -750,10 +750,10 @@ fixts.warnings.multiple_number_Steps.expected =
|
|
|
750
750
|
Feature: I generate constrained random tests (generated by ALKiln)
|
|
751
751
|
|
|
752
752
|
@alkiln_extra_intro @alkiln_generator_warning
|
|
753
|
-
Scenario: ALKiln
|
|
753
|
+
Scenario: ALKiln begs the author's forgiveness. The next tests might be flawed.
|
|
754
754
|
Then ALKiln warns the author about a generator ${ fixts.FLUB_PLACEHOLDER }:
|
|
755
755
|
"""
|
|
756
|
-
―――――
|
|
756
|
+
――――― Template file warnings ―――――
|
|
757
757
|
🔎 ALK0238 ${ fixts.WARNING_PLACEHOLDER }
|
|
758
758
|
―――――
|
|
759
759
|
"""
|
|
@@ -787,10 +787,10 @@ fixts.warnings.multiple_number_Steps_and_numbers.expected =
|
|
|
787
787
|
Feature: I generate constrained random tests (generated by ALKiln)
|
|
788
788
|
|
|
789
789
|
@alkiln_extra_intro @alkiln_generator_warning
|
|
790
|
-
Scenario: ALKiln
|
|
790
|
+
Scenario: ALKiln begs the author's forgiveness. The next tests might be flawed.
|
|
791
791
|
Then ALKiln warns the author about a generator ${ fixts.FLUB_PLACEHOLDER }:
|
|
792
792
|
"""
|
|
793
|
-
―――――
|
|
793
|
+
――――― Template file warnings ―――――
|
|
794
794
|
🔎 ALK0240 ${ fixts.WARNING_PLACEHOLDER }
|
|
795
795
|
🔎 ALK0238 ${ fixts.WARNING_PLACEHOLDER }
|
|
796
796
|
🔎 ALK0240 ${ fixts.WARNING_PLACEHOLDER }
|
|
@@ -840,10 +840,10 @@ Feature: I generate valid constrained random answers tests 1 (generated by ALKil
|
|
|
840
840
|
# The 1st of 2 related tests. This 1st one tests uniqueness within one Scenario.
|
|
841
841
|
|
|
842
842
|
@alkiln_extra_intro @alkiln_generator_warning
|
|
843
|
-
Scenario: ALKiln
|
|
843
|
+
Scenario: ALKiln begs the author's forgiveness. The next tests might be flawed.
|
|
844
844
|
Then ALKiln warns the author about a generator ${ fixts.FLUB_PLACEHOLDER }:
|
|
845
845
|
"""
|
|
846
|
-
―――――
|
|
846
|
+
――――― Template file warnings ―――――
|
|
847
847
|
🔎 ALK0260 ${ fixts.WARNING_PLACEHOLDER }
|
|
848
848
|
―――――
|
|
849
849
|
"""
|
|
@@ -868,10 +868,10 @@ Feature: I generate valid constrained random answers tests 2 (generated by ALKil
|
|
|
868
868
|
# 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.
|
|
869
869
|
|
|
870
870
|
@alkiln_extra_intro @alkiln_generator_warning
|
|
871
|
-
Scenario: ALKiln
|
|
871
|
+
Scenario: ALKiln begs the author's forgiveness. The next tests might be flawed.
|
|
872
872
|
Then ALKiln warns the author about a generator ${ fixts.FLUB_PLACEHOLDER }:
|
|
873
873
|
"""
|
|
874
|
-
―――――
|
|
874
|
+
――――― Template file warnings ―――――
|
|
875
875
|
🔎 ALK0260 ${ fixts.WARNING_PLACEHOLDER }
|
|
876
876
|
―――――
|
|
877
877
|
"""
|
|
@@ -888,6 +888,43 @@ fixts.warnings.fewer_unique_than_requested.included_log_codes = [
|
|
|
888
888
|
];
|
|
889
889
|
|
|
890
890
|
|
|
891
|
+
fixts.warnings.over_max = {};
|
|
892
|
+
fixts.warnings.over_max.max_num_allowed = 1;
|
|
893
|
+
fixts.warnings.over_max.arg =
|
|
894
|
+
`Feature: I generate constrained random tests
|
|
895
|
+
|
|
896
|
+
Scenario: I'm warned of asking for more than the max num tests
|
|
897
|
+
Given ALKiln makes 2 constrained random tests
|
|
898
|
+
Given I start the interview at "test_kickout"
|
|
899
|
+
And ALKiln gets to "end" when I pick from:
|
|
900
|
+
| var | possible_values |
|
|
901
|
+
| user_choice | correct;; wrong |`;
|
|
902
|
+
fixts.warnings.over_max.expected =
|
|
903
|
+
`@alkiln @generated @randomized @constraints
|
|
904
|
+
Feature: I generate constrained random tests (generated by ALKiln)
|
|
905
|
+
|
|
906
|
+
@alkiln_extra_intro @alkiln_generator_warning
|
|
907
|
+
Scenario: ALKiln begs the author's forgiveness. The next tests might be flawed.
|
|
908
|
+
Then ALKiln warns the author about a generator ${ fixts.FLUB_PLACEHOLDER }:
|
|
909
|
+
"""
|
|
910
|
+
――――― Template file warnings ―――――
|
|
911
|
+
🔎 ALK0241 ${ fixts.WARNING_PLACEHOLDER }
|
|
912
|
+
―――――
|
|
913
|
+
"""
|
|
914
|
+
|
|
915
|
+
@scenario1_of_1
|
|
916
|
+
Scenario: I'm warned of asking for more than the max num tests (1 of 1)
|
|
917
|
+
Given I start the interview at "test_kickout"
|
|
918
|
+
And I get to any of the question ids ["end"] with this data:
|
|
919
|
+
| var | value |
|
|
920
|
+
${ fixts.RANDOM_TABLE_PLACEHOLDER }`;
|
|
921
|
+
fixts.warnings.over_max.exact_log_codes = [
|
|
922
|
+
`ALK0237`, `ALK0241`, `ALK0243`, `ALK0244`,
|
|
923
|
+
`ALK0245`, `ALK0248`, `ALK0249`, `ALK0246`, `ALK0246`, `ALK0246`, `ALK0255`, `ALK0257`, `ALK0259`, `ALK0246`,
|
|
924
|
+
`ALK0261`, `ALK0262`, `ALK0264`,
|
|
925
|
+
];
|
|
926
|
+
|
|
927
|
+
|
|
891
928
|
/**
|
|
892
929
|
* ===========
|
|
893
930
|
* Silent warnings
|
|
@@ -20,7 +20,7 @@ const TABLE_ROW_REGEX = /^(?!(?:.*\| var \| value \|))(.*\| .* \|)/gm;
|
|
|
20
20
|
const TABLE_PLACEHOLDER_REGEX = new RegExp(`(${ RANDOM_TABLE_PLACEHOLDER }(\n)?)+`, `g`);
|
|
21
21
|
|
|
22
22
|
const WARNING_PLACEHOLDER = fixtures.WARNING_PLACEHOLDER;
|
|
23
|
-
const WARNING_MSG_REGEX = /(ALK\d{4} )(.*\d{4}-\d\d-\d\d \d\d:\d\d:\d\dUTC.*(?:\n
|
|
23
|
+
const WARNING_MSG_REGEX = /(ALK\d{4} )(.*\d{4}-\d\d-\d\d \d\d:\d\d:\d\dUTC.*(?!\n ―)(?:\n)?.+)/g;
|
|
24
24
|
|
|
25
25
|
const FLUB_PLACEHOLDER = fixtures.FLUB_PLACEHOLDER;
|
|
26
26
|
const FLUB_REGEX = fixtures.FLUB_OPTIONS_REGEX;
|
|
@@ -96,6 +96,11 @@ function mutate_globals_with({ testing_vals, do_compare=false }) {
|
|
|
96
96
|
// Reset log codes
|
|
97
97
|
logger.clear_internal_log_records();
|
|
98
98
|
|
|
99
|
+
process.env.ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO = 40;
|
|
100
|
+
if ( testing_vals.max_num_allowed ) {
|
|
101
|
+
process.env.ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO = testing_vals.max_num_allowed;
|
|
102
|
+
}
|
|
103
|
+
|
|
99
104
|
// Fresh namespace
|
|
100
105
|
let generator = new TestGenerator();
|
|
101
106
|
// Mutates `fixture`
|
|
@@ -505,6 +510,23 @@ describe(`Constrained random answers parser, when given a valid generator Scenar
|
|
|
505
510
|
});
|
|
506
511
|
});
|
|
507
512
|
|
|
513
|
+
describe(`that asks for over max # of tests allowed - 1 -`, function () {
|
|
514
|
+
|
|
515
|
+
before(function () { mutate_globals_with({ testing_vals: fixtures.warnings.over_max }); });
|
|
516
|
+
|
|
517
|
+
let outer = fixtures.warnings.over_max;
|
|
518
|
+
it(`has these exact log codes with warnings: ${ JSON.stringify( outer.exact_log_codes )}`, function () {
|
|
519
|
+
expect( get_log_codes({ logger }) ).to.have.all.members( fixture.exact_log_codes );
|
|
520
|
+
});
|
|
521
|
+
|
|
522
|
+
it(`returns no errors`, function () { expect( errors ).to.have.lengthOf( 0 ); });
|
|
523
|
+
|
|
524
|
+
it(`has max # of tests - 1`, function () {
|
|
525
|
+
expect( comparable_text( new_contents )).to.equal( fixture.expected );
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
});
|
|
529
|
+
|
|
508
530
|
describe(`that has a blank var value in a generator column`, function () {
|
|
509
531
|
|
|
510
532
|
before(function () { mutate_globals_with({ testing_vals: fixtures.empty_string_value }); });
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
|
|
4
|
-
function shift_logs(folderPath, startNum, endNum) {
|
|
5
|
-
// Validate inputs
|
|
6
|
-
if (!folderPath || typeof folderPath !== 'string') {
|
|
7
|
-
throw new Error('Invalid folder path provided');
|
|
8
|
-
}
|
|
9
|
-
if (!startNum || !endNum || isNaN(startNum) || isNaN(endNum)) {
|
|
10
|
-
throw new Error('Invalid number range provided');
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// Process directory recursively
|
|
14
|
-
function processDirectory(dirPath) {
|
|
15
|
-
// Read all files in the folder
|
|
16
|
-
const files = fs.readdirSync(dirPath);
|
|
17
|
-
|
|
18
|
-
files.forEach(file => {
|
|
19
|
-
const some_path = path.join(dirPath, file);
|
|
20
|
-
const stats = fs.statSync(some_path);
|
|
21
|
-
|
|
22
|
-
if (stats.isDirectory()) {
|
|
23
|
-
// Recursively process subdirectories
|
|
24
|
-
processDirectory(some_path);
|
|
25
|
-
} else if (stats.isFile()) {
|
|
26
|
-
// Only process supported file paths
|
|
27
|
-
if ( some_path.startsWith(`.`) || some_path.startsWith(`alkiln`) || some_path.startsWith(`_`)) {
|
|
28
|
-
console.log(`not editing`, some_path);
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
if (some_path.match(/(node_modules)|(_alkiln)|(package)|(shrinkwrap)|(runtime)|(alkiln\-)$/)) {
|
|
32
|
-
console.log(`not editing`, some_path);
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
let content = fs.readFileSync(some_path, 'utf8');
|
|
37
|
-
|
|
38
|
-
// Create regex pattern for ALK followed by digits
|
|
39
|
-
const pattern = /\bALK0(\d+)\b/g;
|
|
40
|
-
|
|
41
|
-
// Process matches and adjust numbers
|
|
42
|
-
content = content.replace(pattern, (match, numStr) => {
|
|
43
|
-
console.log(`match in ${ some_path }:`, JSON.stringify(match) );
|
|
44
|
-
|
|
45
|
-
const num = parseInt(numStr);
|
|
46
|
-
// Only modify numbers within our target range
|
|
47
|
-
if (num >= startNum && num <= endNum) {
|
|
48
|
-
console.log(`Changing match: previous content:`);
|
|
49
|
-
console.log( content );
|
|
50
|
-
return `ALK0${num + 1}`;
|
|
51
|
-
}
|
|
52
|
-
return match;
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
// Write back the modified content
|
|
56
|
-
fs.writeFileSync(some_path, content);
|
|
57
|
-
console.log(`Processed file: ${file}`);
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
processDirectory(folderPath)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Example usage
|
|
66
|
-
try {
|
|
67
|
-
shift_logs(`.`, 236, 276); //'./your_folder', 123, 456);
|
|
68
|
-
console.log('Sequence fixing completed');
|
|
69
|
-
} catch (error) {
|
|
70
|
-
console.error('Error:', error.message);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
function check_types({ folderPath, startNum, endNum }) {
|
|
75
|
-
}
|