@suffolklitlab/alkiln 5.10.4 → 5.11.1
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 +45 -23
- package/.github/workflows/log_code_tests.yml +27 -0
- package/.github/workflows/playground.yml +38 -19
- package/.github/workflows/unit_tests.yml +2 -2
- package/CHANGELOG.md +30 -0
- package/action.yml +31 -54
- package/action_for_github_server/action.yml +61 -67
- package/lib/cucumber_8_shim.js +2 -1
- package/lib/docassemble/docassemble_api_REST.js +2 -2
- package/lib/docassemble/docassemble_api_interface.js +12 -8
- package/lib/docassemble/server_install.js +3 -2
- package/lib/docassemble/setup.js +5 -3
- package/lib/docassemble/takedown.js +4 -4
- package/lib/run_cucumber.js +21 -13
- package/lib/scope.js +123 -74
- package/lib/steps.js +82 -162
- package/lib/utils/log.js +56 -33
- package/lib/utils/reports.js +77 -20
- package/lib/utils/session_vars.js +12 -19
- package/package.json +4 -3
- package/tests/log_codes/check_codes.sh +138 -0
- package/tests/log_codes/deleted_codes.json +8 -0
package/lib/steps.js
CHANGED
|
@@ -186,7 +186,7 @@ Given(/I start the interview at "([^"]+)"/, {timeout: -1}, async (file_name) =>
|
|
|
186
186
|
// TODO: Move this to the `download` Step and only do it once per scenario
|
|
187
187
|
// Allow developer to save download files
|
|
188
188
|
let custom_download_behavior_timeout = new Promise(async ( resolve, reject ) => {
|
|
189
|
-
let page_timeout = setTimeout(function() {reject(
|
|
189
|
+
let page_timeout = setTimeout(function() {reject( `🤕 ALK0057 ERROR: Took too long to set download behavior.` ); }, scope.timeout);
|
|
190
190
|
// self-invoke an anonymous async function so we don't have to
|
|
191
191
|
// abstract the details of resolving and rejecting.
|
|
192
192
|
(async function() {
|
|
@@ -263,10 +263,11 @@ Given(/I go to "([^"]+)"/i, {timeout: -1}, async ( url ) => {
|
|
|
263
263
|
let result = await wrapPromiseWithTimeout(
|
|
264
264
|
scope.page.goto( url, { waitUntil: 'domcontentloaded', timeout: scope.timeout }),
|
|
265
265
|
scope.timeout,
|
|
266
|
-
|
|
266
|
+
// TODO: Turn this into a function
|
|
267
|
+
`🤕 ALK0058 ERROR: It took to long to get to "${ url }"`
|
|
267
268
|
);
|
|
268
269
|
|
|
269
|
-
reports.addToReport(scope, { type: `info`, value: `Successfully went to "${ url }"` });
|
|
270
|
+
reports.addToReport(scope, { type: `info`, code: `ALK0059`, value: `Successfully went to "${ url }"` });
|
|
270
271
|
return result;
|
|
271
272
|
});
|
|
272
273
|
|
|
@@ -355,7 +356,10 @@ When(/^(?:the user gets)?(?:I get)? to ?(?:the)?(?: ?question)?(?: id)? "([^"]+)
|
|
|
355
356
|
+ `too long to try to reach it (over ${ scope.timeout/1000/60 } min). The `
|
|
356
357
|
+ `test got stuck on "${ id }".`
|
|
357
358
|
let error = non_reload_report_msg;
|
|
358
|
-
await scope.handle_page_timeout_error( scope, {
|
|
359
|
+
await scope.handle_page_timeout_error( scope, { non_reload_report_data: {
|
|
360
|
+
code: `ALK0060`,
|
|
361
|
+
message: non_reload_report_msg,
|
|
362
|
+
}, error });
|
|
359
363
|
}; // Ends on_page_timeout()
|
|
360
364
|
let page_timeout_id = setTimeout(on_page_timeout, scope.timeout);
|
|
361
365
|
|
|
@@ -376,9 +380,11 @@ When(/^(?:the user gets)?(?:I get)? to ?(?:the)?(?: ?question)?(?: id)? "([^"]+)
|
|
|
376
380
|
from_story_table: true,
|
|
377
381
|
});
|
|
378
382
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
383
|
+
log.debug({
|
|
384
|
+
type: `info`,
|
|
385
|
+
code: `ALK0061`,
|
|
386
|
+
pre: `Rows, including special rows:, ${JSON.stringify( ensured_var_data )}`,
|
|
387
|
+
});
|
|
382
388
|
|
|
383
389
|
// THIS FUNCTION ACTUALLY MATTERS
|
|
384
390
|
// Some errors happen in there to be closer to the relevant code. We'd have to try/catch anyway.
|
|
@@ -388,7 +394,7 @@ When(/^(?:the user gets)?(?:I get)? to ?(?:the)?(?: ?question)?(?: id)? "([^"]+)
|
|
|
388
394
|
resolve();
|
|
389
395
|
} catch ( err ) {
|
|
390
396
|
let err_msg = `Error occurred when tried to answer fields on question "${ id }".`
|
|
391
|
-
reports.addToReport( scope, { type: `error`, value: err_msg });
|
|
397
|
+
reports.addToReport( scope, { type: `error`, code: `ALK0062`, value: err_msg });
|
|
392
398
|
// Throw error instead?
|
|
393
399
|
reject( err );
|
|
394
400
|
} finally {
|
|
@@ -418,13 +424,13 @@ When(/^(?:the user gets)?(?:I get)? to ?(?:the)?(?: ?question)?(?: id)? "([^"]+)
|
|
|
418
424
|
|
|
419
425
|
// Add full used table to report so it can be copied if needed.
|
|
420
426
|
// TODO: Should we/How do we get this in the final scenario report instead of here?
|
|
421
|
-
reports.addToReport( scope, { type: `note`, value: `\n${ ' '.repeat(2) }Rows that got set:` });
|
|
422
|
-
reports.addToReport( scope, { type: `step`, value: `${ ' '.repeat(4) }And I get to the question id "${ target_id }" with this data:` });
|
|
423
|
-
reports.addToReport(scope, { type: `row`, value: `${ ' '.repeat(6) }| var | value | trigger |`, });
|
|
427
|
+
reports.addToReport( scope, { type: `note info`, code: `ALK0063`, value: `\n${ ' '.repeat(2) }Rows that got set:` });
|
|
428
|
+
reports.addToReport( scope, { type: `step info`, code: `ALK0064`, value: `${ ' '.repeat(4) }And I get to the question id "${ target_id }" with this data:` });
|
|
429
|
+
reports.addToReport(scope, { type: `row info`, code: `ALK0065`, value: `${ ' '.repeat(6) }| var | value | trigger |`, });
|
|
424
430
|
let at_least_one_row_was_NOT_used = false;
|
|
425
431
|
for ( let row of sorted_rows ) {
|
|
426
432
|
if ( row.times_used > 0 ) {
|
|
427
|
-
reports.addToReport(scope, { type: `row`, value: row.report_str, });
|
|
433
|
+
reports.addToReport(scope, { type: `row info`, code: `ALK0066`, value: row.report_str, });
|
|
428
434
|
} else {
|
|
429
435
|
at_least_one_row_was_NOT_used = true;
|
|
430
436
|
}
|
|
@@ -432,135 +438,19 @@ When(/^(?:the user gets)?(?:I get)? to ?(?:the)?(?: ?question)?(?: id)? "([^"]+)
|
|
|
432
438
|
|
|
433
439
|
// Add unused rows if needed
|
|
434
440
|
if ( at_least_one_row_was_NOT_used ) {
|
|
435
|
-
reports.addToReport( scope, { type: `note`, value: `${ ' '.repeat(2) }Unused rows:` });
|
|
441
|
+
reports.addToReport( scope, { type: `note info`, code: `ALK0067`, value: `${ ' '.repeat(2) }Unused rows:` });
|
|
436
442
|
for ( let row of sorted_rows ) {
|
|
437
443
|
if ( row.times_used === 0 ) {
|
|
438
|
-
reports.addToReport(scope, { type: `row`, value: row.report_str, });
|
|
444
|
+
reports.addToReport(scope, { type: `row info`, code: `ALK0068`, value: row.report_str, });
|
|
439
445
|
}
|
|
440
446
|
}
|
|
441
447
|
} else {
|
|
442
|
-
reports.addToReport(scope, { type: `note`, value: `${ ' '.repeat(2) }All rows were used` });
|
|
448
|
+
reports.addToReport(scope, { type: `note info`, code: `ALK0069`, value: `${ ' '.repeat(2) }All rows were used` });
|
|
443
449
|
}
|
|
444
450
|
|
|
445
|
-
reports.addToReport(scope, { type: `
|
|
451
|
+
reports.addToReport(scope, { type: `plain`, value: `` });
|
|
446
452
|
});
|
|
447
453
|
|
|
448
|
-
// When(/^foo id "([^"]+)"/, {timeout: -1}, async (target_id, raw_var_data) => {
|
|
449
|
-
// /* NO CUCUMBER TIMEOUT. Must handle timeout ourselves:
|
|
450
|
-
// * https://github.com/cucumber/cucumber-js/blob/master/docs/support_files/timeouts.md#disable-timeouts
|
|
451
|
-
// * Iterate in here to keep timeout reasonable */
|
|
452
|
-
|
|
453
|
-
// // Note: Why do we not just stop when we've used all the vars in the table or
|
|
454
|
-
// // reach the last var? Vars are not required to be given in sequence and pages that
|
|
455
|
-
// // have non-button fields don't usually have a var assigned to the 'continue' button.
|
|
456
|
-
// // Alternative: require vars even for 'continue' pages. Then in loop require at least one var
|
|
457
|
-
// // to be found on a page before hitting 'continue'. That requires detecting navigation because
|
|
458
|
-
// // pages with fields will not have a var for the continue button, so there will
|
|
459
|
-
// // still have to be some automatic continuing.
|
|
460
|
-
// // It also seems harsh, but more reliable.
|
|
461
|
-
// // Ask developers what they'd like.
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
// let supported_table = await scope.normalizeTable( scope, { raw_var_data });
|
|
465
|
-
|
|
466
|
-
// let { question_has_id, id, id_matches } = await scope.examinePageID( scope, target_id );
|
|
467
|
-
// // Until we reach the target page, hit an error, or time out (take too long)
|
|
468
|
-
// while ( !id_matches ) {
|
|
469
|
-
// let custom_timeout = new Promise(function( resolve, reject ) {
|
|
470
|
-
|
|
471
|
-
// // Set up the timeout that avoids infinite loops
|
|
472
|
-
// let on_page_timeout = async function() {
|
|
473
|
-
|
|
474
|
-
// let non_reload_report_msg = `The target id was "${ target_id }", but it took `
|
|
475
|
-
// + `too long to try to reach it (over ${ scope.timeout/1000/60 } min). The `
|
|
476
|
-
// + `test got stuck on "${ id }".`
|
|
477
|
-
// let error = non_reload_report_msg;
|
|
478
|
-
// await scope.handle_page_timeout_error( scope, { non_reload_report_msg, error });
|
|
479
|
-
// }; // Ends on_page_timeout()
|
|
480
|
-
// let page_timeout_id = setTimeout(on_page_timeout, scope.timeout);
|
|
481
|
-
|
|
482
|
-
// // self-invoke an anonymous async function so we don't have to
|
|
483
|
-
// // abstract the details of resolving and rejecting.
|
|
484
|
-
// // If we need to call recursively, signature function might look like:
|
|
485
|
-
// // func( scope, { resolve, reject, supported_table, page_timeout_id })
|
|
486
|
-
// // Maybe list of timeout and/or interval ids in state that can all be cleared at once?
|
|
487
|
-
// (async function() {
|
|
488
|
-
// try {
|
|
489
|
-
// let { question_has_id, id, id_matches } = await scope.examinePageID( scope );
|
|
490
|
-
|
|
491
|
-
// // Add special rows. Basically, do weirder things.
|
|
492
|
-
// // TODO: Remove from_story_table - no longer needed if only called from in here
|
|
493
|
-
// let ensured_var_data = await scope.ensureSpecialRows( scope, {
|
|
494
|
-
// var_data: supported_table,
|
|
495
|
-
// from_story_table: true,
|
|
496
|
-
// });
|
|
497
|
-
|
|
498
|
-
// if ( session_vars.get_debug() ) {
|
|
499
|
-
// console.log( `Rows, including special rows:`, JSON.stringify( ensured_var_data ));
|
|
500
|
-
// }
|
|
501
|
-
|
|
502
|
-
// // Some errors happen in there to be closer to the relevant code. We'd have to try/catch anyway.
|
|
503
|
-
// let error = await scope.setFields(scope, { var_data: ensured_var_data, id, ensure_navigation: true });
|
|
504
|
-
// if ( error.was_found ) { await scope.throwPageError( scope, { id: id }); }
|
|
505
|
-
// resolve();
|
|
506
|
-
// } catch ( err ) {
|
|
507
|
-
// let err_msg = `Error occurred when tried to answer fields on question "${ id }".`
|
|
508
|
-
// reports.addToReport( scope, { type: `error`, value: err_msg });
|
|
509
|
-
// // Throw error instead?
|
|
510
|
-
// reject( err );
|
|
511
|
-
// } finally {
|
|
512
|
-
// clearTimeout( page_timeout_id ); // prevent temporary hang at end of tests
|
|
513
|
-
// }
|
|
514
|
-
// })();
|
|
515
|
-
// }); // ends custom_timeout for setFields
|
|
516
|
-
|
|
517
|
-
// await custom_timeout;
|
|
518
|
-
|
|
519
|
-
// // Prep for next loop
|
|
520
|
-
// ({ question_has_id, id, id_matches } = await scope.examinePageID( scope, target_id ));
|
|
521
|
-
|
|
522
|
-
// } // ends while !id_matches
|
|
523
|
-
// // Can anything unsatisfactory get through here?
|
|
524
|
-
|
|
525
|
-
// // Add report strings from supported table, not an altered one
|
|
526
|
-
// for ( let row of supported_table ) {
|
|
527
|
-
// row.report_str = `${ reports.convertToOriginalStoryTableRow(scope, { row_data: row }) }`;
|
|
528
|
-
// }
|
|
529
|
-
// // Sort into alphabetical order, as is recommended for writing story tables
|
|
530
|
-
// let sorted_rows = supported_table.sort( function ( row1, row2 ) {
|
|
531
|
-
// if( row1.report_str < row2.report_str ) { return -1; }
|
|
532
|
-
// if( row1.report_str > row2.report_str ) { return 1; }
|
|
533
|
-
// return 0;
|
|
534
|
-
// });
|
|
535
|
-
|
|
536
|
-
// // Add full used table to report so it can be copied if needed.
|
|
537
|
-
// // TODO: Should we/How do we get this in the final scenario report instead of here?
|
|
538
|
-
// reports.addToReport( scope, { type: `note`, value: `\n${ ' '.repeat(2) }Rows that got set:` });
|
|
539
|
-
// reports.addToReport( scope, { type: `step`, value: `${ ' '.repeat(4) }And I get to the question id "${ target_id }" with this data:` });
|
|
540
|
-
// reports.addToReport(scope, { type: `row`, value: `${ ' '.repeat(6) }| var | value | trigger |`, });
|
|
541
|
-
// let at_least_one_row_was_NOT_used = false;
|
|
542
|
-
// for ( let row of sorted_rows ) {
|
|
543
|
-
// if ( row.times_used > 0 ) {
|
|
544
|
-
// reports.addToReport(scope, { type: `row`, value: row.report_str, });
|
|
545
|
-
// } else {
|
|
546
|
-
// at_least_one_row_was_NOT_used = true;
|
|
547
|
-
// }
|
|
548
|
-
// }
|
|
549
|
-
|
|
550
|
-
// // Add unused rows if needed
|
|
551
|
-
// if ( at_least_one_row_was_NOT_used ) {
|
|
552
|
-
// reports.addToReport( scope, { type: `note`, value: `${ ' '.repeat(2) }Unused rows:` });
|
|
553
|
-
// for ( let row of sorted_rows ) {
|
|
554
|
-
// if ( row.times_used === 0 ) {
|
|
555
|
-
// reports.addToReport(scope, { type: `row`, value: row.report_str, });
|
|
556
|
-
// }
|
|
557
|
-
// }
|
|
558
|
-
// } else {
|
|
559
|
-
// reports.addToReport(scope, { type: `note`, value: `${ ' '.repeat(2) }All rows were used` });
|
|
560
|
-
// }
|
|
561
|
-
|
|
562
|
-
// reports.addToReport(scope, { type: `note`, value: `` });
|
|
563
|
-
// });
|
|
564
454
|
|
|
565
455
|
//#####################################
|
|
566
456
|
//#####################################
|
|
@@ -609,15 +499,15 @@ Then(/the (?:question|page|screen) id should be "([^"]+)"/i, { timeout: -1 }, as
|
|
|
609
499
|
// No question id exists
|
|
610
500
|
let no_id_msg = `Did not find any question id.`;
|
|
611
501
|
if ( !question_has_id ) {
|
|
612
|
-
reports.addToReport( scope, { type: `error`, value: no_id_msg });
|
|
502
|
+
reports.addToReport( scope, { type: `error`, code: `ALK0070`, value: no_id_msg });
|
|
613
503
|
}
|
|
614
504
|
expect( question_has_id , no_id_msg ).to.be.true;
|
|
615
505
|
|
|
616
506
|
// Wrong question id
|
|
617
507
|
let no_match_msg = `The question id was supposed to be "${ question_id }"`
|
|
618
|
-
+ `, but it
|
|
508
|
+
+ `, but it is actually "${ id }".`;
|
|
619
509
|
if ( !id_matches ) {
|
|
620
|
-
reports.addToReport( scope, { type: `error`, value: no_match_msg });
|
|
510
|
+
reports.addToReport( scope, { type: `error`, code: `ALK0071`, value: no_match_msg });
|
|
621
511
|
}
|
|
622
512
|
expect( id_matches, no_match_msg ).to.be.true;
|
|
623
513
|
|
|
@@ -630,7 +520,7 @@ Then(/I ?(?:should)? see the phrase "([^"]+)"/i, async ( phrase ) => { // √
|
|
|
630
520
|
const bodyText = await scope.page.$eval('body', elem => elem.innerText);
|
|
631
521
|
|
|
632
522
|
let msg = `The text "${ phrase }" SHOULD be on this page, but it's NOT.`;
|
|
633
|
-
if ( !bodyText.includes( phrase )) { reports.addToReport(scope, { type: `error`, value: msg }); }
|
|
523
|
+
if ( !bodyText.includes( phrase )) { reports.addToReport(scope, { type: `error`, code: `ALK0072`, value: msg }); }
|
|
634
524
|
expect( bodyText, msg ).to.contain( phrase );
|
|
635
525
|
|
|
636
526
|
await scope.afterStep(scope);
|
|
@@ -644,7 +534,7 @@ Then(/I should not see the phrase "([^"]+)"/i, async ( phrase ) => { // √
|
|
|
644
534
|
const bodyText = await scope.page.$eval('body', elem => elem.innerText);
|
|
645
535
|
|
|
646
536
|
let msg = `The text "${ phrase }" should NOT be on this page, but it IS here.`;
|
|
647
|
-
if ( bodyText.includes( phrase )) { reports.addToReport(scope, { type: `error`, value: msg }); }
|
|
537
|
+
if ( bodyText.includes( phrase )) { reports.addToReport(scope, { type: `error`, code: `ALK0073`, value: msg }); }
|
|
648
538
|
expect( bodyText, msg ).not.to.contain( phrase );
|
|
649
539
|
|
|
650
540
|
await scope.afterStep(scope);
|
|
@@ -654,7 +544,7 @@ Then('an element should have the id {string}', async ( id ) => { // √
|
|
|
654
544
|
const element = await scope.page.$('#' + id);
|
|
655
545
|
|
|
656
546
|
let msg = `No element on this page has the ID "${ id }".`;
|
|
657
|
-
if ( !element ) { reports.addToReport(scope, { type: `error`, value: msg }); }
|
|
547
|
+
if ( !element ) { reports.addToReport(scope, { type: `error`, code: `ALK0074`, value: msg }); }
|
|
658
548
|
expect( element, msg ).to.exist;
|
|
659
549
|
|
|
660
550
|
await scope.afterStep(scope);
|
|
@@ -709,7 +599,7 @@ Then(/I (don't|can't|don’t|can’t|cannot|do not) continue/, async (unused) =>
|
|
|
709
599
|
* Can other things trigger navigation? Re: other inputs things
|
|
710
600
|
* like 'Enter' acting like a click is a test for docassemble */
|
|
711
601
|
let msg = `The page should have stopped the user from continuing, but the user was able to continue.`;
|
|
712
|
-
if ( scope.navigated ) { reports.addToReport(scope, { type: `error`, value: msg }); }
|
|
602
|
+
if ( scope.navigated ) { reports.addToReport(scope, { type: `error`, code: `ALK0075`, value: msg }); }
|
|
713
603
|
expect( scope.navigated, msg ).to.be.false;
|
|
714
604
|
|
|
715
605
|
await scope.afterStep(scope);
|
|
@@ -720,12 +610,12 @@ Then('I will be told an answer is invalid', async () => { // √
|
|
|
720
610
|
let { was_found, error_handlers } = await scope.checkForError( scope );
|
|
721
611
|
|
|
722
612
|
let no_error_msg = `No error message was found on the page`;
|
|
723
|
-
if ( !was_found ) { reports.addToReport(scope, { type: `error`, value: no_error_msg }); }
|
|
613
|
+
if ( !was_found ) { reports.addToReport(scope, { type: `error`, code: `ALK0076`, value: no_error_msg }); }
|
|
724
614
|
expect( was_found, no_error_msg ).to.be.true;
|
|
725
615
|
|
|
726
616
|
let was_user_error = error_handlers.complex_user_error !== undefined || error_handlers.simple_user_error !== undefined;
|
|
727
|
-
let not_user_error_msg = `The error was a system error, not an invalid user answer. Check for the picture of the page's error if the
|
|
728
|
-
if ( !was_user_error ) { reports.addToReport(scope, { type: `error`, value: not_user_error_msg }); }
|
|
617
|
+
let not_user_error_msg = `The error was a system error, not an invalid user answer. Check for the picture of the page's error if the Step did not use any secret variables.`;
|
|
618
|
+
if ( !was_user_error ) { reports.addToReport(scope, { type: `error`, code: `ALK0077`, value: not_user_error_msg }); }
|
|
729
619
|
expect( was_user_error, not_user_error_msg ).to.be.true;
|
|
730
620
|
|
|
731
621
|
await scope.afterStep(scope);
|
|
@@ -736,7 +626,7 @@ Then('I arrive at the next page', async () => { // √
|
|
|
736
626
|
* Can other things trigger navigation? Re: other inputs things
|
|
737
627
|
* like 'Enter' acting like a click is a test for docassemble */
|
|
738
628
|
let msg = `User did not arrive at the next page.`
|
|
739
|
-
if ( !scope.navigated ) { reports.addToReport(scope, { type: `error`, value: msg }); }
|
|
629
|
+
if ( !scope.navigated ) { reports.addToReport(scope, { type: `error`, code: `ALK0078`, value: msg }); }
|
|
740
630
|
expect( scope.navigated, msg ).to.be.true;
|
|
741
631
|
await scope.afterStep(scope);
|
|
742
632
|
});
|
|
@@ -747,7 +637,7 @@ Then('I should see the link {string}', async ( linkText ) => { // √
|
|
|
747
637
|
let [link] = await scope.page.$x(`//a[contains(text(), "${linkText}")]`);
|
|
748
638
|
|
|
749
639
|
let msg = `Cannot find a link with the text "${ linkText }".`;
|
|
750
|
-
if ( !link ) { reports.addToReport(scope, { type: `error`, value: msg }); }
|
|
640
|
+
if ( !link ) { reports.addToReport(scope, { type: `error`, code: `ALK0079`, value: msg }); }
|
|
751
641
|
expect( link, msg ).to.exist;
|
|
752
642
|
|
|
753
643
|
await scope.afterStep(scope);
|
|
@@ -758,7 +648,7 @@ Then('I should see the link to {string}', async ( url ) => { // √
|
|
|
758
648
|
let link = await scope.page.$(`*[href="${ url }"]`);
|
|
759
649
|
|
|
760
650
|
let msg = `Cannot find a link to "${ url }".`;
|
|
761
|
-
if ( !link ) { reports.addToReport(scope, { type: `error`, value: msg }); }
|
|
651
|
+
if ( !link ) { reports.addToReport(scope, { type: `error`, code: `ALK0080`, value: msg }); }
|
|
762
652
|
expect(link, msg ).to.exist;
|
|
763
653
|
|
|
764
654
|
await scope.afterStep(scope);
|
|
@@ -774,7 +664,7 @@ Then(/the "([^"]+)" link leads to "([^"]+)"/, async (linkText, expected_url) =>
|
|
|
774
664
|
let actual_url = await prop_obj.jsonValue();
|
|
775
665
|
|
|
776
666
|
let msg = `Cannot find a link with the text "${ linkText }" leading to ${ expected_url }.`;
|
|
777
|
-
if ( actual_url !== expected_url ) { reports.addToReport(scope, { type: `error`, value: msg }); }
|
|
667
|
+
if ( actual_url !== expected_url ) { reports.addToReport(scope, { type: `error`, code: `ALK0081`, value: msg }); }
|
|
778
668
|
expect( actual_url ).to.equal( expected_url );
|
|
779
669
|
|
|
780
670
|
await scope.afterStep(scope);
|
|
@@ -793,7 +683,7 @@ Then(/the "([^"]+)" link opens in (a new window|the same window)/, async (linkTe
|
|
|
793
683
|
|| ( !should_open_a_new_window && !opens_a_new_window );
|
|
794
684
|
|
|
795
685
|
let msg = `The link "${ linkText }" does NOT open in ${ which_window }.`;
|
|
796
|
-
if ( !hasCorrectWindowTarget ) { reports.addToReport(scope, { type: `error`, value: msg }); }
|
|
686
|
+
if ( !hasCorrectWindowTarget ) { reports.addToReport(scope, { type: `error`, code: `ALK0082`, value: msg }); }
|
|
797
687
|
expect( hasCorrectWindowTarget, msg ).to.be.true;
|
|
798
688
|
|
|
799
689
|
await scope.afterStep(scope);
|
|
@@ -828,6 +718,7 @@ Then(/(?:the )?text(?: in)?(?: the)?(?: JSON)?(?: var)?(?:iable)?(?: )?"([^"]+)"
|
|
|
828
718
|
if ( actual_value !== expected_value ) {
|
|
829
719
|
reports.addToReport( scope, {
|
|
830
720
|
type: `error`,
|
|
721
|
+
code: `ALK0083`,
|
|
831
722
|
value: `The variable "${ var_name }" was not equal to the expected `
|
|
832
723
|
+ `value on the "${ scope.page_id }" screen. Check `
|
|
833
724
|
+ `${ json_path } to see the page's JSON variables.`
|
|
@@ -925,7 +816,11 @@ When(/I check the page for (?:accessibility|a11y) issues/i, {timeout: -1}, async
|
|
|
925
816
|
scope.checkForA11y(scope),
|
|
926
817
|
scope.timeout
|
|
927
818
|
)
|
|
928
|
-
|
|
819
|
+
|
|
820
|
+
let msg = `Found potential accessibility issues on the "${ scope.page_id }" screen. Details in ${ axe_filepath }.`;
|
|
821
|
+
if ( !passed ) {
|
|
822
|
+
reports.addToReport( scope, { type: `error`, code: `ALK0084`, value: msg });
|
|
823
|
+
}
|
|
929
824
|
expect( passed, msg ).to.be.true;
|
|
930
825
|
});
|
|
931
826
|
|
|
@@ -955,7 +850,8 @@ When(/I answer randomly for at most ([0-9]+) (?:page(?:s)?|screen(?:s)?)/, { tim
|
|
|
955
850
|
scope.paths.random_screenshots = random_input_path;
|
|
956
851
|
fs.mkdirSync( scope.paths.random_screenshots );
|
|
957
852
|
reports.addToReport( scope, {
|
|
958
|
-
type: 'row',
|
|
853
|
+
type: 'row info',
|
|
854
|
+
code: `ALK0085`,
|
|
959
855
|
value: `Testing interview with random input (in ${ random_input_path })`
|
|
960
856
|
});
|
|
961
857
|
|
|
@@ -996,6 +892,7 @@ When(/I answer randomly for at most ([0-9]+) (?:page(?:s)?|screen(?:s)?)/, { tim
|
|
|
996
892
|
if ( !has_content ) {
|
|
997
893
|
reports.addToReport( scope, {
|
|
998
894
|
type: `error`,
|
|
895
|
+
code: `ALK0086`,
|
|
999
896
|
value: no_content_err
|
|
1000
897
|
});
|
|
1001
898
|
reject( no_content_err );
|
|
@@ -1003,7 +900,7 @@ When(/I answer randomly for at most ([0-9]+) (?:page(?:s)?|screen(?:s)?)/, { tim
|
|
|
1003
900
|
} else {
|
|
1004
901
|
let timeout_message = `The page with an id of "${ id }" took too long`
|
|
1005
902
|
+ ` to fill with random answers (over ${ scope.timeout/1000/60 } min).`
|
|
1006
|
-
reports.addToReport( scope, { type: `error`, value: timeout_message });
|
|
903
|
+
reports.addToReport( scope, { type: `error`, code: `ALK0087`, value: timeout_message });
|
|
1007
904
|
reject( timeout_message );
|
|
1008
905
|
}
|
|
1009
906
|
|
|
@@ -1050,6 +947,7 @@ When(/I answer randomly for at most ([0-9]+) (?:page(?:s)?|screen(?:s)?)/, { tim
|
|
|
1050
947
|
has_thrown = true;
|
|
1051
948
|
reports.addToReport( scope, {
|
|
1052
949
|
type: `error`,
|
|
950
|
+
code: `ALK0088`,
|
|
1053
951
|
value: no_content_err
|
|
1054
952
|
});
|
|
1055
953
|
reject( no_content_err );
|
|
@@ -1079,6 +977,7 @@ When(/I answer randomly for at most ([0-9]+) (?:page(?:s)?|screen(?:s)?)/, { tim
|
|
|
1079
977
|
if ( !has_content ) {
|
|
1080
978
|
reports.addToReport( scope, {
|
|
1081
979
|
type: `error`,
|
|
980
|
+
code: `ALK0089`,
|
|
1082
981
|
value: no_content_err
|
|
1083
982
|
});
|
|
1084
983
|
reject( no_content_err );
|
|
@@ -1087,7 +986,7 @@ When(/I answer randomly for at most ([0-9]+) (?:page(?:s)?|screen(?:s)?)/, { tim
|
|
|
1087
986
|
} else {
|
|
1088
987
|
let err_msg = `The page with the question id "${ id }" errored when trying to fill`
|
|
1089
988
|
+ ` it with random answers: ${ error.name }`
|
|
1090
|
-
reports.addToReport( scope, { type: `error`, value: err_msg });
|
|
989
|
+
reports.addToReport( scope, { type: `error`, code: `ALK0090`, value: err_msg });
|
|
1091
990
|
reject( error );
|
|
1092
991
|
} // ends if !has_content
|
|
1093
992
|
|
|
@@ -1287,8 +1186,7 @@ After(async function(scenario) {
|
|
|
1287
1186
|
|
|
1288
1187
|
// Log errors
|
|
1289
1188
|
if ( scenario.result.message ) {
|
|
1290
|
-
log.debug({ type: `
|
|
1291
|
-
// log.debug({ type: `error`, pre: scenario.result.message, verbose: true });
|
|
1189
|
+
log.debug({ type: `info`, code: `ALK0091`, pre: `cucumber error: ${ scenario.result.message }` }); //, verbose: true });
|
|
1292
1190
|
}
|
|
1293
1191
|
|
|
1294
1192
|
let changeable_test_status = scenario.result.status;
|
|
@@ -1298,7 +1196,8 @@ After(async function(scenario) {
|
|
|
1298
1196
|
changeable_test_status = `FAILED`;
|
|
1299
1197
|
reports.addToReport(scope, {
|
|
1300
1198
|
type: `error`,
|
|
1301
|
-
|
|
1199
|
+
code: `ALK0092`,
|
|
1200
|
+
value: `Accessibility standards tests failed. See information above.`
|
|
1302
1201
|
});
|
|
1303
1202
|
}
|
|
1304
1203
|
|
|
@@ -1307,6 +1206,7 @@ After(async function(scenario) {
|
|
|
1307
1206
|
changeable_test_status = `FAILED`;
|
|
1308
1207
|
reports.addToReport(scope, {
|
|
1309
1208
|
type: `error`,
|
|
1209
|
+
code: `ALK0093`,
|
|
1310
1210
|
value: `PDF comparison failed ${ scope.failed_pdf_compares.length } time(s)\n---\n${ msg }\n---\n`
|
|
1311
1211
|
});
|
|
1312
1212
|
}
|
|
@@ -1315,15 +1215,18 @@ After(async function(scenario) {
|
|
|
1315
1215
|
reports.setReportScenarioStatus( scope, { status: changeable_test_status });
|
|
1316
1216
|
|
|
1317
1217
|
if (changeable_test_status !== `PASSED`) {
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1218
|
+
log.debug({
|
|
1219
|
+
type: `error`,
|
|
1220
|
+
code: `ALK0094`,
|
|
1221
|
+
pre: `Non-passed status occurred while running test: ${changeable_test_status}`,
|
|
1222
|
+
});
|
|
1321
1223
|
|
|
1322
1224
|
if ( scope.page ) {
|
|
1323
1225
|
|
|
1324
1226
|
if ( !!scope.disable_error_screenshot ) {
|
|
1325
1227
|
reports.addToReport(scope, {
|
|
1326
|
-
type: `row`,
|
|
1228
|
+
type: `row info`,
|
|
1229
|
+
code: `ALK0095`,
|
|
1327
1230
|
value: `For security, ALKiln will avoid creating a picture of the page for this error. It's possible a secret is being used on this screen.`
|
|
1328
1231
|
});
|
|
1329
1232
|
} else {
|
|
@@ -1347,7 +1250,7 @@ After(async function(scenario) {
|
|
|
1347
1250
|
|
|
1348
1251
|
// This has to come after the security message or security message doesn't print. Not sure why.
|
|
1349
1252
|
if (changeable_test_status === `FAILED`) {
|
|
1350
|
-
reports.addToReport(scope, { type: `outcome`, value: `**-- Scenario Failed --**` });
|
|
1253
|
+
reports.addToReport(scope, { type: `outcome failure info`, code: `ALK0096`, value: `**-- Scenario Failed --**` });
|
|
1351
1254
|
}
|
|
1352
1255
|
|
|
1353
1256
|
} // ends if not passed
|
|
@@ -1407,11 +1310,14 @@ After(async function(scenario) {
|
|
|
1407
1310
|
// TODO: Should a more specific message about signing out get into the report no matter what?
|
|
1408
1311
|
// If so, what should the message be in order to not get confused with these other messages?
|
|
1409
1312
|
let non_reload_report_msg = `It took too long to sign out in preparation for the next test.`;
|
|
1410
|
-
await scope.handle_page_timeout_error( scope, {
|
|
1313
|
+
await scope.handle_page_timeout_error( scope, { non_reload_report_data: {
|
|
1314
|
+
code: `ALK0097`,
|
|
1315
|
+
message: non_reload_report_msg,
|
|
1316
|
+
}, error });
|
|
1411
1317
|
} else {
|
|
1412
1318
|
// Throw any non-timeout error
|
|
1413
1319
|
let err_msg = `Error occurred when ALKiln tried to sign out in preparation for the next test.`
|
|
1414
|
-
reports.addToReport( scope, { type: `error`, value: err_msg });
|
|
1320
|
+
reports.addToReport( scope, { type: `error`, code: `ALK0098`, value: err_msg });
|
|
1415
1321
|
throw error;
|
|
1416
1322
|
} // ends if error is timeout error
|
|
1417
1323
|
|
|
@@ -1419,13 +1325,22 @@ After(async function(scenario) {
|
|
|
1419
1325
|
|
|
1420
1326
|
} // ends if scope.page
|
|
1421
1327
|
|
|
1328
|
+
// INTERNAL WARNING: TODO: A console.log here prevents the try/catch from
|
|
1329
|
+
// throwing an error. Why is that? Does it somehow make sure that scope.page
|
|
1330
|
+
// gets destroyed?
|
|
1331
|
+
|
|
1332
|
+
// console.log('This stops try/catch from throwing an error in some cases.');
|
|
1333
|
+
|
|
1334
|
+
// More internal testing stuff
|
|
1422
1335
|
if ( changeable_test_status === `FAILED` ) {
|
|
1423
1336
|
// If the result object status wasn't failure and we still want
|
|
1424
1337
|
// the tests to fail, as with a11y tests, we can't mess with the
|
|
1425
1338
|
// cucumber result.status object because it will cause unwanted
|
|
1426
1339
|
// errors. We have to throw an error here instead.
|
|
1427
1340
|
if ( scenario.result.status !== `FAILED` ) {
|
|
1428
|
-
|
|
1341
|
+
let msg = `The test unexpectedly didn't fail. Scenario status: ${scenario.result.status}.`
|
|
1342
|
+
reports.addToReport( scope, { type: `error`, code: `ALK0099`, value: msg });
|
|
1343
|
+
throw new Error(msg);
|
|
1429
1344
|
}
|
|
1430
1345
|
} else {
|
|
1431
1346
|
// Some internal test failures should be ok
|
|
@@ -1434,6 +1349,11 @@ After(async function(scenario) {
|
|
|
1434
1349
|
// https://github.com/cucumber/cucumber-js/blob/main/docs/support_files/api_reference.md#setdefinitionfunctionwrapperwrapper
|
|
1435
1350
|
scenario.result.status = changeable_test_status;
|
|
1436
1351
|
}
|
|
1352
|
+
// Ends more internal testing stuff
|
|
1353
|
+
|
|
1354
|
+
// WARNING: TODO: console.log can prevent a sign-out error. What race condition is going on?
|
|
1355
|
+
log.debug({ type: `cucumber`, code: `ALK0100`, verbose: true, pre: `Scenario AfterStep() message`, data: scenario.result.message });
|
|
1356
|
+
|
|
1437
1357
|
});
|
|
1438
1358
|
|
|
1439
1359
|
AfterAll(async function() {
|
package/lib/utils/log.js
CHANGED
|
@@ -1,64 +1,87 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const session_vars = require( './session_vars' );
|
|
3
3
|
|
|
4
|
+
// ? 🌈 💡 🔎 🤕 🐞
|
|
5
|
+
|
|
4
6
|
let log = {};
|
|
5
7
|
module.exports = log;
|
|
6
8
|
|
|
7
|
-
let create_msg_start = function ( types, pre='' ) {
|
|
8
|
-
|
|
9
|
-
let
|
|
10
|
-
|
|
9
|
+
let create_msg_start = function ( types, pre='', code=`? ALK0000` ) {
|
|
10
|
+
// ? - unknown (fallback)
|
|
11
|
+
let types_str = types.join(` `);
|
|
12
|
+
if ( types_str.includes(`plain`) ) {
|
|
13
|
+
return pre;
|
|
14
|
+
} else {
|
|
15
|
+
return `${ code } ${ types_str }: ${ pre }`;
|
|
16
|
+
}
|
|
11
17
|
};
|
|
12
18
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
19
|
+
// Where is this used?
|
|
20
|
+
log.success = function ({ type='', pre='', data='', post='', code=`ALK0000` }) {
|
|
21
|
+
/** Log success msg with the given information and strings, prepended with `ALKiln`.
|
|
22
|
+
* `type` is often something like 'setup', 'takedown', etc. */
|
|
23
|
+
// √ - info (fallback)
|
|
24
|
+
let start = create_msg_start([ type, `SUCCESS` ], pre, `🌈 ${code}` );
|
|
17
25
|
// Log them each on a separate line
|
|
18
26
|
console.info( `${ start }` );
|
|
19
27
|
if ( data ) { console.info( data ); }
|
|
20
28
|
if ( post ) { console.info( post ); }
|
|
21
29
|
};
|
|
22
30
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
31
|
+
// Where is this used?
|
|
32
|
+
log.info = function ({ type='', pre='', data='', post='', code=`ALK0000` }) {
|
|
33
|
+
/** Log info msg with the given information and strings, prepended with `ALKiln`.
|
|
34
|
+
* `type` is often something like 'setup', 'takedown', etc. */
|
|
35
|
+
// & - info (fallback)
|
|
36
|
+
let start = create_msg_start([ type, `INFO` ], pre, `💡 ${code}` );
|
|
37
|
+
// Log them each on a separate line
|
|
38
|
+
console.info( `${ start }` );
|
|
39
|
+
if ( data ) { console.info( data ); }
|
|
40
|
+
if ( post ) { console.info( post ); }
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// Where is this used?
|
|
44
|
+
log.warn = function ({ type='', pre='', data='', post='', code=`ALK0000` }) {
|
|
45
|
+
/** Log warning msg with the given information and strings, prepended with `ALKiln`.
|
|
46
|
+
* `type` is often something like 'setup', 'takedown', etc. */
|
|
47
|
+
// ! - warning (fallback)
|
|
48
|
+
let start = create_msg_start([ type, `WARNING` ], pre, `🔎 ${code}` );
|
|
27
49
|
// Log them each on a separate line
|
|
28
50
|
console.warn( `${ start }` );
|
|
29
51
|
if ( data ) { console.warn( data ); }
|
|
30
52
|
if ( post ) { console.warn( post ); }
|
|
31
53
|
};
|
|
32
54
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
55
|
+
// Where is this used?
|
|
56
|
+
log.error = function ({ type='', pre='', data='', post='', code=`ALK0000` }) {
|
|
57
|
+
/** Log error msg with the given information and strings, prepended with `ALKiln`.
|
|
58
|
+
* `type` is often something like 'setup', 'takedown', etc. */
|
|
59
|
+
// X - error (fallback)
|
|
60
|
+
let start = create_msg_start([ type, `ERROR` ], pre, `🤕 ${code}` );
|
|
37
61
|
// Log them each on a separate line with extra new lines around the whole thing
|
|
38
62
|
console.error( `\n${ start }` );
|
|
39
63
|
if ( data ) { console.error( data ); }
|
|
40
64
|
if ( post ) { console.error( post, `\n` ); }
|
|
41
65
|
};
|
|
42
66
|
|
|
43
|
-
log.debug = function ({ type='', pre='', data='', post='', verbose=false }) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
67
|
+
log.debug = function ({ type='', pre='', data='', post='', verbose=false, code=`ALK0000` }) {
|
|
68
|
+
/** If debugging is turned on, log a message that includes `ALKiln` and `debug` */
|
|
69
|
+
// @ - debug (fallback)
|
|
70
|
+
let start = create_msg_start([ type, `DEBUG` ], pre, `🐞 ${ code }` );
|
|
71
|
+
let full = `\n${ start }`;
|
|
72
|
+
if ( data ) { full += `\n${ data }`; }
|
|
73
|
+
if ( post ) { full += `\n${ post }`; }
|
|
74
|
+
|
|
75
|
+
// TODO: Make a verbose log instead of adding to the debug one and always add to it
|
|
76
|
+
if ( verbose ) {
|
|
77
|
+
log.add_to_debug_log( full );
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if ( session_vars.get_debug() ) {
|
|
48
81
|
// Log them each on a separate line
|
|
49
82
|
console.log( `\n${ start }` );
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
console.log( data );
|
|
53
|
-
}
|
|
54
|
-
if ( post ) {
|
|
55
|
-
full += `\n${ post }`;
|
|
56
|
-
console.log( post );
|
|
57
|
-
}
|
|
58
|
-
// TODO: Make a verbose log instead of adding to the debug one and always add to it
|
|
59
|
-
if ( verbose ) {
|
|
60
|
-
log.add_to_debug_log( full );
|
|
61
|
-
}
|
|
83
|
+
console.log( data );
|
|
84
|
+
console.log( post );
|
|
62
85
|
}
|
|
63
86
|
};
|
|
64
87
|
|