@suffolklitlab/alkiln 5.13.3 → 5.13.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 +7 -7
- package/.github/workflows/playground.yml +1 -1
- package/CHANGELOG.md +24 -0
- package/action.yml +70 -28
- package/action_for_github_server/action.yml +61 -29
- package/docs/4_environments.md +243 -0
- package/docs/artifacts_folder_name.md +135 -0
- package/docs/constrained_random_tests.md +320 -0
- package/docs/decisions/006_which_log_level_to_pick_2024_09_5.md +70 -0
- package/docs/decisions/007_getting_and_storing_logs.md +179 -0
- package/docs/decisions/move_runtime_config_to_sources_folder.md +3 -1
- package/docs/decisions/reports_and_logs_2024_08_11.md +161 -0
- package/docs/kinds_of_errors.md +26 -0
- package/lib/docassemble/docassemble_api_interface.js +77 -51
- package/lib/docassemble/server_install.js +32 -9
- package/lib/docassemble/setup.js +40 -25
- package/lib/docassemble/takedown.js +33 -10
- package/lib/parse.js +36 -0
- package/lib/run_cucumber.js +115 -36
- package/lib/scope.js +60 -75
- package/lib/steps.js +70 -42
- package/lib/utils/Log.js +982 -0
- package/lib/utils/files.js +18 -11
- package/lib/utils/get_sources_paths.js +162 -0
- package/lib/utils/parse.js +1 -0
- package/lib/utils/proccess_command_line_args.js +267 -0
- package/lib/utils/reports.js +64 -17
- package/lib/utils/session_vars.js +34 -21
- package/lib/utils/time.js +44 -0
- package/package.json +1 -1
- package/tests/log_codes/check_codes.sh +2 -1
- package/tests/log_codes/log_code_expected_instances.txt +33 -9
- package/tests/unit_tests/getAllFields.test.js +5 -0
- package/tests/unit_tests/getMatchingRows.test.js +5 -0
- package/tests/unit_tests/log.test.js +581 -0
- package/tests/unit_tests/normalizeTable.test.js +5 -0
- package/lib/utils/log.js +0 -96
package/lib/steps.js
CHANGED
|
@@ -5,6 +5,7 @@ const {
|
|
|
5
5
|
Given,
|
|
6
6
|
After,
|
|
7
7
|
Before,
|
|
8
|
+
AfterStep,
|
|
8
9
|
BeforeAll,
|
|
9
10
|
AfterAll,
|
|
10
11
|
setDefaultTimeout //,
|
|
@@ -18,7 +19,7 @@ const { v4: uuidv4 } = require('uuid');
|
|
|
18
19
|
|
|
19
20
|
// Ours
|
|
20
21
|
const scope = require('./scope');
|
|
21
|
-
const
|
|
22
|
+
const Log = require(`./utils/Log`);
|
|
22
23
|
const session_vars = require('./utils/session_vars');
|
|
23
24
|
const files = require('./utils/files' );
|
|
24
25
|
const reports = require(`./utils/reports`);
|
|
@@ -82,7 +83,9 @@ let click_with = {
|
|
|
82
83
|
pc: 'click',
|
|
83
84
|
};
|
|
84
85
|
|
|
85
|
-
|
|
86
|
+
let log = null;
|
|
87
|
+
|
|
88
|
+
BeforeAll(async function() {
|
|
86
89
|
scope.showif_timeout = 600;
|
|
87
90
|
// TODO: Do these really need to be maps? As sets, they may make the output
|
|
88
91
|
// more predictable to the user, but they add complexity.
|
|
@@ -95,29 +98,30 @@ BeforeAll(async () => {
|
|
|
95
98
|
// Store path names for files and docs created for the tests
|
|
96
99
|
scope.paths = {};
|
|
97
100
|
|
|
98
|
-
//
|
|
99
|
-
//
|
|
101
|
+
// // Make the folder to store all the files for this run of the tests
|
|
102
|
+
// scope.paths.artifacts = files.make_artifacts_folder();
|
|
103
|
+
// // Save its name in a file. `session_vars` can get it back later.
|
|
104
|
+
// // The value we are saving is used by at least run_cucumber.js.
|
|
100
105
|
|
|
101
|
-
//
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
+
// A little indirect, but the artifacts path should always have already been
|
|
107
|
+
// created by now, either by `run_cucumber.js` or the relevant test
|
|
108
|
+
scope.paths.artifacts = session_vars.get_artifacts_path_name();
|
|
109
|
+
log = new Log({ path: scope.paths.artifacts, context: `steps` });
|
|
110
|
+
scope.set_log({ log_obj: log });
|
|
106
111
|
|
|
107
|
-
scope.paths.
|
|
108
|
-
scope.paths.
|
|
109
|
-
scope.paths.
|
|
110
|
-
|
|
112
|
+
scope.paths.debug_log = `${ scope.paths.artifacts }/${ log.debug_log_filename }`;
|
|
113
|
+
scope.paths.report_log = `${ scope.paths.artifacts }/${ log.report_log_filename }`;
|
|
114
|
+
scope.paths.report = `${ scope.paths.artifacts }/${ log.report_filename }`;
|
|
115
|
+
scope.paths.debug_of_unexpected = `${ scope.paths.artifacts }/${ log.temp_unexpected_debug_log_filename }`;
|
|
116
|
+
scope.paths.report_of_unexpected = `${ scope.paths.artifacts }/${ log.unexpected_filename }`;
|
|
111
117
|
|
|
112
118
|
reports.create( scope );
|
|
113
119
|
});
|
|
114
120
|
|
|
115
121
|
Before(async (scenario) => {
|
|
116
122
|
|
|
117
|
-
//
|
|
118
|
-
|
|
119
|
-
console.log('');
|
|
120
|
-
process.stdout.write(`Scenario: ${ scenario.pickle.name }: `);
|
|
123
|
+
// Start the running "progress bar" for the Scenario
|
|
124
|
+
log.stdout({}, `\nScenario: ${ scenario.pickle.name }: `);
|
|
121
125
|
|
|
122
126
|
// Create browser, which can't be created in BeforeAll() where .driver doesn't exist for some reason
|
|
123
127
|
if (!scope.browser) {
|
|
@@ -396,11 +400,9 @@ When(/^(?:the user gets)?(?:I get)? to ?(?:the)?(?: ?question)?(?: id)? "([^"]+)
|
|
|
396
400
|
from_story_table: true,
|
|
397
401
|
});
|
|
398
402
|
|
|
399
|
-
log.debug({
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
pre: `Rows, including special rows:, ${JSON.stringify( ensured_var_data )}`,
|
|
403
|
-
});
|
|
403
|
+
log.debug({ code: `ALK0061`, context: `table`, },
|
|
404
|
+
`Rows, including special rows:`, ensured_var_data
|
|
405
|
+
);
|
|
404
406
|
|
|
405
407
|
// THIS FUNCTION ACTUALLY MATTERS
|
|
406
408
|
// Some errors happen in there to be closer to the relevant code. We'd have to try/catch anyway.
|
|
@@ -972,7 +974,7 @@ When(/I answer randomly for at most ([0-9]+) (?:page(?:s)?|screen(?:s)?)/, { tim
|
|
|
972
974
|
} // ends if !has_content
|
|
973
975
|
|
|
974
976
|
if ( buttons_exist ) {
|
|
975
|
-
|
|
977
|
+
log.stdout({}, `\x1b[36m${ 'v' }\x1b[0m`); // pressed button
|
|
976
978
|
}
|
|
977
979
|
|
|
978
980
|
resolve();
|
|
@@ -1263,11 +1265,22 @@ Then(/I fail to delete (\d) detected interview(?:s)? and get no error __internal
|
|
|
1263
1265
|
//#####################################
|
|
1264
1266
|
//#####################################
|
|
1265
1267
|
|
|
1268
|
+
AfterStep(async function({ result }) {
|
|
1269
|
+
// TODO: Abstract this
|
|
1270
|
+
if ( result.status === `PASSED` ) { log.stdout({ records_only: true }, `.`); }
|
|
1271
|
+
else if ( result.status === `FAILED` ) { log.stdout({ records_only: true }, `F`); }
|
|
1272
|
+
else if ( result.status === `UNDEFINED` ) { log.stdout({ records_only: true }, `U`); }
|
|
1273
|
+
else if ( result.status === `SKIPPED` ) { log.stdout({ records_only: true }, `-`); }
|
|
1274
|
+
else if ( result.status === `PENDING` ) { log.stdout({ records_only: true }, `P`); }
|
|
1275
|
+
});
|
|
1276
|
+
|
|
1266
1277
|
After(async function(scenario) {
|
|
1267
1278
|
|
|
1268
1279
|
// Log errors
|
|
1269
1280
|
if ( scenario.result.message ) {
|
|
1270
|
-
log.debug({
|
|
1281
|
+
log.debug({ code: `ALK0091`, context: `scenario`, },
|
|
1282
|
+
scenario.result.message
|
|
1283
|
+
);
|
|
1271
1284
|
}
|
|
1272
1285
|
|
|
1273
1286
|
let changeable_test_status = scenario.result.status;
|
|
@@ -1297,11 +1310,9 @@ After(async function(scenario) {
|
|
|
1297
1310
|
reports.saveFinalScenarioData( scope, { status: changeable_test_status });
|
|
1298
1311
|
|
|
1299
1312
|
if (changeable_test_status !== `PASSED`) {
|
|
1300
|
-
log.debug({
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
pre: `Non-passed status occurred while running test: ${changeable_test_status}`,
|
|
1304
|
-
});
|
|
1313
|
+
log.debug({ code: `ALK0094`, level: `warn`, },
|
|
1314
|
+
`Non-passed status occurred while running test: ${ changeable_test_status }`
|
|
1315
|
+
);
|
|
1305
1316
|
|
|
1306
1317
|
if ( scope.page ) {
|
|
1307
1318
|
|
|
@@ -1397,8 +1408,9 @@ After(async function(scenario) {
|
|
|
1397
1408
|
+ `Expected status: ${scope.expected_status}. `
|
|
1398
1409
|
+ `See the report for details.`;
|
|
1399
1410
|
let code = `ALK0099`;
|
|
1400
|
-
log.debug({
|
|
1401
|
-
|
|
1411
|
+
expected_status_err_msg = log.debug({ code: code, level: `error`, },
|
|
1412
|
+
msg
|
|
1413
|
+
);
|
|
1402
1414
|
}
|
|
1403
1415
|
}
|
|
1404
1416
|
scope.expected_status = null; // reset for next Scenario
|
|
@@ -1418,17 +1430,25 @@ After(async function(scenario) {
|
|
|
1418
1430
|
// Make sure that tests which ALKiln has calculated as failed
|
|
1419
1431
|
// cause a cucumber error later. Just changing the status to `FAILED`
|
|
1420
1432
|
// causes unhelpful cucumber errors. TODO: Add to internal docs.
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
});
|
|
1433
|
+
// TODO: Should we move this to where the error is thrown?
|
|
1434
|
+
log.debug({ code: force_failure_code, level: `error`, },
|
|
1435
|
+
force_failure_msg
|
|
1436
|
+
);
|
|
1426
1437
|
// TODO: Look into setDefinitionFunctionWrapper to catch errors
|
|
1427
1438
|
// of failing tests that should indeed be failing:
|
|
1428
1439
|
// https://github.com/cucumber/cucumber-js/blob/main/docs/support_files/api_reference.md#setdefinitionfunctionwrapperwrapper
|
|
1429
1440
|
need_to_force_failed_status = true;
|
|
1430
1441
|
}
|
|
1431
1442
|
|
|
1443
|
+
// Not sure if this is necessary
|
|
1444
|
+
if ( changeable_test_status === 'PASSED' ) {
|
|
1445
|
+
log.stdout({ records_only: true }, `.` );
|
|
1446
|
+
} else if ( changeable_test_status === `SKIPPED` ) {
|
|
1447
|
+
log.stdout({ records_only: true }, `-` );
|
|
1448
|
+
} else {
|
|
1449
|
+
log.stdout({ records_only: true }, changeable_test_status[0].toUpperCase() );
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1432
1452
|
let signout_succeeded = true;
|
|
1433
1453
|
let signout_error_msg = ``;
|
|
1434
1454
|
// If there is a page open, then sign out and close it
|
|
@@ -1482,9 +1502,10 @@ After(async function(scenario) {
|
|
|
1482
1502
|
// going to the wrong file). If it becomes a problem we can track it down later.
|
|
1483
1503
|
if ( visible_keys.length > 0 ) {
|
|
1484
1504
|
// Can an API key ever see an interview that it can't delete?
|
|
1485
|
-
log.
|
|
1486
|
-
|
|
1487
|
-
|
|
1505
|
+
log.debug({ code: `ALK0197`, context: `internal`, level: `warn`, }
|
|
1506
|
+
`The API key can see ${ visible_keys.length } interviews that were not deleted:`,
|
|
1507
|
+
visible_keys
|
|
1508
|
+
);
|
|
1488
1509
|
}
|
|
1489
1510
|
} catch ( error ) {
|
|
1490
1511
|
// Deleting interviews is nice, but not non-critical. Don't bother the
|
|
@@ -1494,7 +1515,9 @@ After(async function(scenario) {
|
|
|
1494
1515
|
// interview. If it becomes a problem we can track it down later.
|
|
1495
1516
|
// Consider add "internal" to docs: "If you see this, make an
|
|
1496
1517
|
// issue in ALKiln with your debug/verbose log"
|
|
1497
|
-
log.
|
|
1518
|
+
log.debug({ code: `ALK0198`, context: `internal`, level: `warn`, error },
|
|
1519
|
+
`Cleaning up interviews incomplete, but unimportant.`
|
|
1520
|
+
);
|
|
1498
1521
|
}
|
|
1499
1522
|
}
|
|
1500
1523
|
|
|
@@ -1513,11 +1536,16 @@ After(async function(scenario) {
|
|
|
1513
1536
|
throw new Error( `🤕 ${ force_failure_code } unreachable ERROR: ${ force_failure_msg }` );
|
|
1514
1537
|
|
|
1515
1538
|
} else if ( internal_errors.length > 0 ) {
|
|
1516
|
-
log.
|
|
1539
|
+
log.debug({ code: `ALK0203`, context: `internal`, level: `warn`, },
|
|
1540
|
+
`There was no need to force failed status and yet there are error messages.`,
|
|
1541
|
+
internal_errors
|
|
1542
|
+
);
|
|
1517
1543
|
}
|
|
1518
1544
|
|
|
1519
1545
|
// Find the race condition.
|
|
1520
|
-
log.debug({
|
|
1546
|
+
log.debug({ code: `ALK0100`, context: `scenario`, },
|
|
1547
|
+
`Scenario After() message:`, scenario.result.message
|
|
1548
|
+
);
|
|
1521
1549
|
|
|
1522
1550
|
});
|
|
1523
1551
|
|