@suffolklitlab/alkiln 3.0.9 → 4.0.0-pre-api.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/test_tests.yml +11 -2
- package/CHANGELOG.md +22 -20
- package/action.yml +42 -32
- package/lib/cucumber_8_shim.js +25 -0
- package/lib/docassemble/docassemble_api_REST.js +130 -0
- package/lib/docassemble/docassemble_api_interface.js +404 -0
- package/lib/docassemble/setup.js +38 -0
- package/lib/docassemble/takedown.js +18 -0
- package/lib/scope.js +337 -60
- package/lib/steps.js +209 -138
- package/lib/utils/env_vars.js +73 -69
- package/lib/utils/log.js +51 -0
- package/lib/utils/session_vars.js +188 -0
- package/lib/utils/time.js +26 -0
- package/lib/world.js +2 -2
- package/package.json +13 -12
- package/tests/features/establishing_steps.feature +15 -0
- package/tests/features/observation_steps.feature +31 -0
- package/tests/features/reports.feature +70 -12
- package/lib/github_integration/install-branch.js +0 -84
- package/lib/github_integration/puppeteer-utils.js +0 -224
- package/lib/github_integration/setup.js +0 -4
- package/lib/github_integration/takedown.js +0 -4
package/lib/steps.js
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
|
-
const {
|
|
1
|
+
const {
|
|
2
|
+
When,
|
|
3
|
+
Then,
|
|
4
|
+
And,
|
|
5
|
+
Given,
|
|
6
|
+
After,
|
|
7
|
+
Before,
|
|
8
|
+
BeforeAll,
|
|
9
|
+
AfterAll,
|
|
10
|
+
setDefaultTimeout //,
|
|
11
|
+
// wrapPromiseWithTimeout // cucumber v8
|
|
12
|
+
} = require('@cucumber/cucumber');
|
|
13
|
+
const wrapPromiseWithTimeout = require('./cucumber_8_shim');
|
|
2
14
|
const fs = require('fs');
|
|
3
15
|
const path = require('path');
|
|
4
16
|
const { expect } = require('chai');
|
|
5
17
|
const puppeteer = require('puppeteer');
|
|
6
18
|
const { v4: uuidv4 } = require('uuid');
|
|
7
19
|
|
|
20
|
+
// Ours
|
|
8
21
|
const scope = require('./scope');
|
|
9
22
|
const env_vars = require('./utils/env_vars');
|
|
10
23
|
|
|
@@ -57,6 +70,7 @@ BeforeAll(async () => {
|
|
|
57
70
|
scope.timeout = 30 * 1000;
|
|
58
71
|
scope.showif_timeout = 600;
|
|
59
72
|
scope.report = new Map();
|
|
73
|
+
fs.writeFileSync('log.txt', "");
|
|
60
74
|
});
|
|
61
75
|
|
|
62
76
|
Before(async (scenario) => {
|
|
@@ -76,7 +90,6 @@ Before(async (scenario) => {
|
|
|
76
90
|
|
|
77
91
|
// Reset default timeout
|
|
78
92
|
scope.timeout = 30 * 1000;
|
|
79
|
-
setDefaultTimeout( 30 * 1000 );
|
|
80
93
|
});
|
|
81
94
|
|
|
82
95
|
// Add a check for an error page before each step? After each step?
|
|
@@ -167,8 +180,9 @@ Given(/I start the interview at "([^"]+)"(?: in lang "([^"]+)")?/, {timeout: -1}
|
|
|
167
180
|
|
|
168
181
|
// If response has a file in it that matches the file we are downloading
|
|
169
182
|
if ( response._headers['content-disposition'] && (response._headers['content-disposition']).includes(`attachment;filename=${scope.toDownload}`) ) {
|
|
170
|
-
//
|
|
171
|
-
|
|
183
|
+
// We're chosing avoid removing the event listener in case removal
|
|
184
|
+
// would prevent downloading other files. The listener should get
|
|
185
|
+
// destroyed when the page closes anyway.
|
|
172
186
|
|
|
173
187
|
// Watch event on download folder or file
|
|
174
188
|
await fs.watchFile( docs_dir, function (curr, prev) {
|
|
@@ -220,6 +234,24 @@ Given(/I start the interview at "([^"]+)"(?: in lang "([^"]+)")?/, {timeout: -1}
|
|
|
220
234
|
await custom_aferStep_timeout;
|
|
221
235
|
});
|
|
222
236
|
|
|
237
|
+
Given(/I (?:sign|log) ?(?:in)?(?:on)?(?:to the server)? with(?: the email)? "([^"]+)" and(?: the password)? "([^"]+)"(?: SECRETs)?/i, {timeout: -1}, async ( email, password ) => {
|
|
238
|
+
/** Uses the names of environment variables (most often GitHub SECRETs) to
|
|
239
|
+
* log into an account on the user's server. Must be SECRETs to stay secure.
|
|
240
|
+
*
|
|
241
|
+
* Variations:
|
|
242
|
+
* I sign into the server with the email "USER1_EMAIL" and the password "USER1_PASSWORD" SECRETs
|
|
243
|
+
* I sign on with the email "USER1_EMAIL" and the password "USER1_PASSWORD" SECRETs
|
|
244
|
+
* I log in with "USER1_EMAIL" and "USER1_PASSWORD"
|
|
245
|
+
*/
|
|
246
|
+
return wrapPromiseWithTimeout(
|
|
247
|
+
scope.steps.sign_in( scope, {
|
|
248
|
+
email_secret_name: email,
|
|
249
|
+
password_secret_name: password
|
|
250
|
+
}),
|
|
251
|
+
scope.timeout
|
|
252
|
+
);
|
|
253
|
+
});
|
|
254
|
+
|
|
223
255
|
// I am using a moble/pc
|
|
224
256
|
When(/I am using an? (.*)/, async ( device ) => {
|
|
225
257
|
// Let developer pick mobile device if they want to
|
|
@@ -240,7 +272,9 @@ When(/I am using an? (.*)/, async ( device ) => {
|
|
|
240
272
|
Given(/the max(?:imum)? sec(?:ond)?s for each step (?:in this scenario )?is (\d+)/i, async ( seconds ) => {
|
|
241
273
|
/* At any time, set a custom timeout for the scenario. */
|
|
242
274
|
scope.timeout = parseInt( seconds ) * 1000;
|
|
243
|
-
|
|
275
|
+
|
|
276
|
+
// Cucumber timeouts are made custom for each step that needs it
|
|
277
|
+
|
|
244
278
|
// If there is no page yet, we've ensured custom timeout will still be set
|
|
245
279
|
// appropriately in the interview loading step
|
|
246
280
|
if ( scope.page ) { await scope.page.setDefaultTimeout( scope.timeout ); }
|
|
@@ -326,7 +360,7 @@ When(/^(?:the user gets)?(?:I get)? to ?(?:the)?(?: ?question)?(?: id)? "([^"]+)
|
|
|
326
360
|
// Add full used table to report so it can be copied if needed.
|
|
327
361
|
// TODO: Should we/How do we get this in the final scenario report instead of here?
|
|
328
362
|
await scope.addToReport( scope, { type: `note`, value: `\n${ ' '.repeat(2) }Rows that got set:` });
|
|
329
|
-
await scope.addToReport( scope, { type: `step`, value: `${ ' '.repeat(4) }And I get the question id "${ target_id }" with this data:` });
|
|
363
|
+
await scope.addToReport( scope, { type: `step`, value: `${ ' '.repeat(4) }And I get to the question id "${ target_id }" with this data:` });
|
|
330
364
|
await scope.addToReport(scope, { type: `row`, value: `${ ' '.repeat(6) }| var | value | trigger |`, });
|
|
331
365
|
let at_least_one_row_was_NOT_used = false;
|
|
332
366
|
for ( let row of sorted_rows ) {
|
|
@@ -358,41 +392,57 @@ When(/^(?:the user gets)?(?:I get)? to ?(?:the)?(?: ?question)?(?: id)? "([^"]+)
|
|
|
358
392
|
//#####################################
|
|
359
393
|
//#####################################
|
|
360
394
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
395
|
+
When(/I wait (\d*\.?\d+) seconds?/, { timeout: -1 }, async ( seconds ) => {
|
|
396
|
+
/** Wait for a specified amount of time. Can help with some race conditions.
|
|
397
|
+
* We're working on reducing race conditions, but it'll never be perfect.
|
|
398
|
+
*
|
|
399
|
+
* Variations:
|
|
400
|
+
* - I wait 1 second
|
|
401
|
+
* - I wait .5 seconds
|
|
402
|
+
*
|
|
403
|
+
* Questions:
|
|
404
|
+
* - Should this really reset the 'navigated' flag? Should the below
|
|
405
|
+
* return succeed or fail? e.g:
|
|
406
|
+
* I tap to continue; I wait 10 seconds; I arrive at the next page;
|
|
407
|
+
* Maybe the 'navitaged' flag should only be reset just before trying to
|
|
408
|
+
* navigate (after pressing a button)
|
|
409
|
+
*/
|
|
410
|
+
return wrapPromiseWithTimeout(
|
|
411
|
+
scope.afterStep(scope, {waitForTimeout: (parseFloat( seconds ) * 1000)}),
|
|
412
|
+
scope.timeout
|
|
413
|
+
);
|
|
370
414
|
});
|
|
371
415
|
|
|
372
|
-
Then(/I take a screenshot ?(?:named "([^"]+)")?/, async ( name ) => {
|
|
373
|
-
/*
|
|
374
|
-
* the filename will be made unique. */
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
416
|
+
Then(/I take a screenshot ?(?:named "([^"]+)")?/, { timeout: -1 }, async ( name ) => {
|
|
417
|
+
/* Download and save a screenshot. `name` does not have to be
|
|
418
|
+
* unique as the filename will be made unique. */
|
|
419
|
+
return wrapPromiseWithTimeout(
|
|
420
|
+
scope.steps.screenshot( scope, name ),
|
|
421
|
+
scope.timeout
|
|
422
|
+
);
|
|
379
423
|
});
|
|
380
424
|
|
|
381
425
|
/* Here to make writing tests more comfortable. */
|
|
382
426
|
When("I do nothing", async () => { await scope.afterStep(scope); }); // √
|
|
383
427
|
|
|
384
|
-
Then('the question id should be {string}', async (question_id) => {
|
|
428
|
+
Then('the question id should be {string}', { timeout: -1 }, async ( question_id ) => {
|
|
385
429
|
/* Looks for a santized version of the question id as it's written
|
|
386
430
|
* in the .yml. docassemble's way */
|
|
387
431
|
let { question_has_id, id, id_matches } = await scope.examinePageID( scope, question_id );
|
|
388
432
|
|
|
389
|
-
//
|
|
433
|
+
// No question id exists
|
|
390
434
|
let no_id_msg = `Did not find any question id.`;
|
|
391
|
-
if ( !question_has_id ) {
|
|
435
|
+
if ( !question_has_id ) {
|
|
436
|
+
await scope.addToReport( scope, { type: `error`, value: no_id_msg });
|
|
437
|
+
}
|
|
392
438
|
expect( question_has_id , no_id_msg ).to.be.true;
|
|
393
439
|
|
|
394
|
-
|
|
395
|
-
|
|
440
|
+
// Wrong question id
|
|
441
|
+
let no_match_msg = `The question id was supposed to be "${ question_id }"`
|
|
442
|
+
+ `, but it's actually "${ id }".`;
|
|
443
|
+
if ( !id_matches ) {
|
|
444
|
+
await scope.addToReport( scope, { type: `error`, value: no_match_msg });
|
|
445
|
+
}
|
|
396
446
|
expect( id_matches, no_match_msg ).to.be.true;
|
|
397
447
|
|
|
398
448
|
await scope.afterStep(scope);
|
|
@@ -477,7 +527,7 @@ Then('an element should have the id {string}', async ( id ) => { // √
|
|
|
477
527
|
// await scope.afterStep(scope);
|
|
478
528
|
// });
|
|
479
529
|
|
|
480
|
-
// This
|
|
530
|
+
// This phrase is confusing. It sounds like it's going to at least try to continue.
|
|
481
531
|
Then(/I (don't|can't|don’t|can’t|cannot|do not) continue/, async (unused) => { // √
|
|
482
532
|
/* Tests for detection of url change from button or link tap.
|
|
483
533
|
* Can other things trigger navigation? Re: other inputs things
|
|
@@ -573,6 +623,63 @@ Then(/the "([^"]+)" link opens in (a new window|the same window)/, async (linkTe
|
|
|
573
623
|
await scope.afterStep(scope);
|
|
574
624
|
});
|
|
575
625
|
|
|
626
|
+
Then(/(?:the )?text(?: in)?(?: the)?(?: JSON)?(?: var)?(?:iable)?(?: )?"([^"]+)" should be/i, async (var_name, expected_value) => {
|
|
627
|
+
/* Check that the text string of the page's JSON var value matches
|
|
628
|
+
* the given text string. Does not currently accept nested values
|
|
629
|
+
* like "foo.bar". The word "text" is required.
|
|
630
|
+
*
|
|
631
|
+
* The format for this step is something like this:
|
|
632
|
+
* ```
|
|
633
|
+
* Then the text in the JSON variable "var_name" should be
|
|
634
|
+
* """
|
|
635
|
+
* A single or
|
|
636
|
+
* multiline string
|
|
637
|
+
* """
|
|
638
|
+
* ```
|
|
639
|
+
*
|
|
640
|
+
* Sentence combinations that will work:
|
|
641
|
+
* `the text in the JSON variable "variable_with_text_value" should be`
|
|
642
|
+
* `the text in the JSON var "variable_with_text_value" should be`
|
|
643
|
+
* `the text in "variable_with_text_value" should be`
|
|
644
|
+
* `text var "variable_with_text_value" should be`
|
|
645
|
+
*/
|
|
646
|
+
|
|
647
|
+
// Get JSON variable value
|
|
648
|
+
let { filename, json } = await scope.savePageJSONData( scope );
|
|
649
|
+
let actual_value = json.variables[ var_name ];
|
|
650
|
+
|
|
651
|
+
// Add warning to report if value is not as expected
|
|
652
|
+
if ( actual_value !== expected_value ) {
|
|
653
|
+
await scope.addToReport( scope, {
|
|
654
|
+
type: `error`,
|
|
655
|
+
value: `The variable "${ var_name }" was not equal to the expected `
|
|
656
|
+
+ `value on the "${ scope.page_id }" screen. Check the downloads `
|
|
657
|
+
+ `file ${ filename } to see the page's JSON variables.`
|
|
658
|
+
});
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
expect( actual_value ).to.equal( expected_value );
|
|
662
|
+
|
|
663
|
+
});
|
|
664
|
+
|
|
665
|
+
|
|
666
|
+
Then(/I get the(?: page's)?(?: JSON)? var(?:iable)?s and val(?:ue)?s/i, { timeout: -1 }, async () => {
|
|
667
|
+
/** Uses https://docassemble.org/docs/functions.html#js_get_interview_variables
|
|
668
|
+
* to get the variable values on the page of the interview and add
|
|
669
|
+
* them to the report.
|
|
670
|
+
*
|
|
671
|
+
* Varations:
|
|
672
|
+
* I get the page's JSON variables and values
|
|
673
|
+
* I get the json vars and vals
|
|
674
|
+
* I get the page's vars and vals
|
|
675
|
+
* I get the vars and vals
|
|
676
|
+
*/
|
|
677
|
+
return await wrapPromiseWithTimeout(
|
|
678
|
+
scope.steps.add_json_vars_to_report( scope ),
|
|
679
|
+
scope.timeout
|
|
680
|
+
);
|
|
681
|
+
});
|
|
682
|
+
|
|
576
683
|
//#####################################
|
|
577
684
|
//#####################################
|
|
578
685
|
// Actions
|
|
@@ -585,27 +692,20 @@ Then(/the "([^"]+)" link opens in (a new window|the same window)/, async (linkTe
|
|
|
585
692
|
|
|
586
693
|
// Consider people wanting to use this for an in-interview page
|
|
587
694
|
// Also consider 'the link url "..." should open...'?
|
|
588
|
-
Then(/the "([^"]+)" link opens a working page/, async (linkText) => {
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
let linkPage = await scope.browser.newPage();
|
|
594
|
-
let response = await linkPage.goto(actual_url, {waitUntil: 'domcontentloaded'});
|
|
595
|
-
|
|
596
|
-
let msg = `The "${ linkText }" link is broken.`;
|
|
597
|
-
if ( !response.ok() ) { await scope.addToReport(scope, { type: `error`, value: msg }); }
|
|
598
|
-
expect( response.ok(), msg ).to.be.true;
|
|
599
|
-
|
|
600
|
-
linkPage.close()
|
|
601
|
-
|
|
602
|
-
await scope.afterStep(scope);
|
|
695
|
+
Then(/the "([^"]+)" link opens a working page/, { timeout: -1 }, async ( linkText ) => {
|
|
696
|
+
return wrapPromiseWithTimeout(
|
|
697
|
+
scope.steps.link_works( scope, linkText ),
|
|
698
|
+
scope.timeout
|
|
699
|
+
);
|
|
603
700
|
});
|
|
604
701
|
|
|
605
|
-
When('I tap to continue', async () => {
|
|
702
|
+
When('I tap to continue', { timeout: -1 }, async () => {
|
|
606
703
|
// Any selectors for this seem somewhat precarious
|
|
607
704
|
// No data will cause an automatic continue when `ensure_navigation` is true
|
|
608
|
-
|
|
705
|
+
return wrapPromiseWithTimeout(
|
|
706
|
+
scope.setFields( scope, { var_data: [], ensure_navigation: true }),
|
|
707
|
+
scope.timeout
|
|
708
|
+
);
|
|
609
709
|
});
|
|
610
710
|
|
|
611
711
|
|
|
@@ -616,7 +716,7 @@ When('I tap to continue', async () => {
|
|
|
616
716
|
// -------------------------------------
|
|
617
717
|
// --- VARIABLES-BASED STEPS ---
|
|
618
718
|
|
|
619
|
-
When(/I set the var(?:iable)? "([^"]+)" to "([^"]+)"/, async ( var_name, set_to ) => {
|
|
719
|
+
When(/I set the var(?:iable)? "([^"]+)" to "([^"]+)"/, { timeout: -1 }, async ( var_name, set_to ) => {
|
|
620
720
|
/* Set any variable (with or without a choice associated with it) to a value. Set:
|
|
621
721
|
* - Buttons associated with variables
|
|
622
722
|
* - Dropdowns
|
|
@@ -629,60 +729,51 @@ When(/I set the var(?:iable)? "([^"]+)" to "([^"]+)"/, async ( var_name, set_to
|
|
|
629
729
|
* 1. I set the var "benefits['SSI']" to "false"
|
|
630
730
|
* 1. I set the var "rent_interval" to "weekly"
|
|
631
731
|
*/
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
// on this page, trigger an error
|
|
637
|
-
await scope.setFields( scope, { var_data, ensure_navigation: false, ensure_all_vars_used: true });
|
|
732
|
+
return wrapPromiseWithTimeout(
|
|
733
|
+
scope.steps.set_regular_var( scope, var_name, set_to ),
|
|
734
|
+
scope.timeout
|
|
735
|
+
);
|
|
638
736
|
});
|
|
639
737
|
|
|
640
|
-
Then(/I upload "([^"]+)" to "([^"]+)"/, async ( filenames, var_name ) => {
|
|
738
|
+
Then(/I upload "([^"]+)" to "([^"]+)"/, { timeout: -1 }, async ( filenames, var_name ) => {
|
|
641
739
|
/* Uploads sibling file (docx, jpg, etc) to input var. Can actually use
|
|
642
740
|
* 'I set the var "" to ""', but this is more explicit if it's desired. */
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
// on this page, trigger an error
|
|
648
|
-
await scope.setFields( scope, { var_data, ensure_navigation: false, ensure_all_vars_used: true });
|
|
741
|
+
return wrapPromiseWithTimeout(
|
|
742
|
+
scope.steps.set_regular_var( scope, var_name, filenames ),
|
|
743
|
+
scope.timeout
|
|
744
|
+
);
|
|
649
745
|
});
|
|
650
746
|
|
|
651
747
|
|
|
652
748
|
// -------------------------------------
|
|
653
749
|
// --- OTHER UI STEPS ---
|
|
654
750
|
|
|
655
|
-
When('I tap the defined text link {string}', async (phrase) => {
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
expect( link, msg ).to.exist;
|
|
662
|
-
|
|
663
|
-
await link.evaluate( elem => { return elem.click(); });
|
|
664
|
-
|
|
665
|
-
await scope.afterStep(scope, {waitForShowIf: true});
|
|
751
|
+
When('I tap the defined text link {string}', { timeout: -1 }, async ( phrase ) => {
|
|
752
|
+
/** Tap a link that doesn't navigate. Depends on the language of the text. */
|
|
753
|
+
return wrapPromiseWithTimeout(
|
|
754
|
+
scope.steps.tap_term( scope, phrase ),
|
|
755
|
+
scope.timeout
|
|
756
|
+
);
|
|
666
757
|
});
|
|
667
758
|
|
|
668
|
-
Then('I sign', async () => {
|
|
669
|
-
|
|
670
|
-
|
|
759
|
+
Then('I sign', { timeout: -1 }, async () => {
|
|
760
|
+
return wrapPromiseWithTimeout(
|
|
761
|
+
scope.steps.sign( scope ),
|
|
762
|
+
scope.timeout
|
|
763
|
+
);
|
|
671
764
|
});
|
|
672
765
|
|
|
673
|
-
When(/I download "([^"]+)"$/, async (filename) => {
|
|
766
|
+
When(/I download "([^"]+)"$/, { timeout: -1 }, async ( filename ) => {
|
|
674
767
|
/* Taps the link that leads to the given filename to trigger downloading.
|
|
675
|
-
*
|
|
676
|
-
WARNING: Cannot download the same file twice in a single scenario.
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
await elem.evaluate( elem => { return elem.click(); });
|
|
685
|
-
await scope.detectDownloadComplete( scope );
|
|
768
|
+
* and waits till the file has been downloaded before allowing the tests to continue.
|
|
769
|
+
* WARNING: Cannot download the same file twice in a single scenario.
|
|
770
|
+
* WARNING: Must not contain any characters that are totally unique to that
|
|
771
|
+
* page load. Just stick to the name of the file.
|
|
772
|
+
*/
|
|
773
|
+
return wrapPromiseWithTimeout(
|
|
774
|
+
scope.steps.download( scope, filename ),
|
|
775
|
+
scope.timeout
|
|
776
|
+
);
|
|
686
777
|
});
|
|
687
778
|
|
|
688
779
|
//#####################################
|
|
@@ -691,7 +782,7 @@ When(/I download "([^"]+)"$/, async (filename) => {
|
|
|
691
782
|
//#####################################
|
|
692
783
|
//#####################################
|
|
693
784
|
|
|
694
|
-
When(/I set the name of ?(?:the var(?:iable)?)? "([^"]+)" to "([^"]+)"/, async (var_base, name_str) => {
|
|
785
|
+
When(/I set the name of ?(?:the var(?:iable)?)? "([^"]+)" to "([^"]+)"/, { timeout: -1 }, async (var_base, name_str) => {
|
|
695
786
|
/* Given a variable name and a space-separated string, fills the
|
|
696
787
|
* appropriate fields on an Assembly Line name question.
|
|
697
788
|
* It handles any of:
|
|
@@ -708,28 +799,14 @@ When(/I set the name of ?(?:the var(?:iable)?)? "([^"]+)" to "([^"]+)"/, async (
|
|
|
708
799
|
* 1. I set the name of the var "defendant" to "Dalia Day Defo Jr"
|
|
709
800
|
* 1. I set the name of the variable "defendant" to "Dalia Day Defo Jr"
|
|
710
801
|
*/
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
[ `first`, `middle`, `last`, `suffix` ],
|
|
716
|
-
];
|
|
717
|
-
|
|
718
|
-
let name_parts = name_str.split(' ');
|
|
719
|
-
let desired_pattern = name_patterns[( name_parts.length - 1 )];
|
|
720
|
-
|
|
721
|
-
for ( let parti = 0; parti < name_parts.length; parti++ ) {
|
|
722
|
-
let var_name = `${ var_base }.name.${ desired_pattern[ parti ] }`
|
|
723
|
-
let value = name_parts[ parti ];
|
|
724
|
-
await scope.setVar( scope, var_name, value );
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
// Continue to next page...?
|
|
728
|
-
await scope.afterStep(scope, {waitForShowIf: true});
|
|
802
|
+
return wrapPromiseWithTimeout(
|
|
803
|
+
scope.steps.set_al_name( scope, var_base, name_str ),
|
|
804
|
+
scope.timeout
|
|
805
|
+
);
|
|
729
806
|
});
|
|
730
807
|
|
|
731
808
|
|
|
732
|
-
When(/I set the address of ?(?:the var(?:iable)?)? "([^"]+)" to "([^"]+)"/, async (var_base, address_str) => {
|
|
809
|
+
When(/I set the address of ?(?:the var(?:iable)?)? "([^"]+)" to "([^"]+)"/, { timeout: -1 }, async (var_base, address_str) => {
|
|
733
810
|
/* Given a variable name and a four-part address formatted as below,
|
|
734
811
|
* sets the appropriate Assembly Line address fields.
|
|
735
812
|
*
|
|
@@ -740,24 +817,10 @@ When(/I set the address of ?(?:the var(?:iable)?)? "([^"]+)" to "([^"]+)"/, asyn
|
|
|
740
817
|
* 1. When I set the address of the variable "users[0]" to "112 Southampton St., Unit 1, Boston, MA 02118"
|
|
741
818
|
* 1. When I set the address of the var "users[0]" to "112 Southampton St., Unit 1, Boston, MA 02118"
|
|
742
819
|
*/
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
let last_parts = (split.pop()).split(/\s+/);
|
|
748
|
-
// ...and add them back in, to end up with [address line 1, address line 2, city, state, zip].
|
|
749
|
-
let address_parts = split.concat( last_parts );
|
|
750
|
-
let start = `${ var_base }.address.`;
|
|
751
|
-
|
|
752
|
-
let index = 0;
|
|
753
|
-
await scope.setVar( scope, `${start}address`, address_parts[0] );
|
|
754
|
-
// Ensure it's without 'Unit '/'unit '
|
|
755
|
-
await scope.setVar( scope, `${start}unit`, (address_parts[1].toLowerCase()).replace(/unit\s*/, '') );
|
|
756
|
-
await scope.setVar( scope, `${start}city`, address_parts[2] );
|
|
757
|
-
await scope.setVar( scope, `${start}state`, address_parts[3] );
|
|
758
|
-
await scope.setVar( scope, `${start}zip`, address_parts[4] );
|
|
759
|
-
|
|
760
|
-
await scope.afterStep(scope, {waitForShowIf: true});
|
|
820
|
+
return wrapPromiseWithTimeout(
|
|
821
|
+
scope.steps.set_al_address( scope, var_base, address_str ),
|
|
822
|
+
scope.timeout
|
|
823
|
+
);
|
|
761
824
|
});
|
|
762
825
|
|
|
763
826
|
// Next macro - download sequence?
|
|
@@ -788,7 +851,7 @@ Given(/the final Scenario status should be "(passed|failed)"/i, async ( expected
|
|
|
788
851
|
/* WARNING: If a Step will fail, this Step must come first.
|
|
789
852
|
*
|
|
790
853
|
* Prepare to test that the Scenario completes with the correct status. */
|
|
791
|
-
scope.expected_status = expected_status;
|
|
854
|
+
scope.expected_status = expected_status.toUpperCase();
|
|
792
855
|
});
|
|
793
856
|
|
|
794
857
|
|
|
@@ -803,18 +866,23 @@ After(async function(scenario) {
|
|
|
803
866
|
// Record status before internal report tests can interfere with values
|
|
804
867
|
await scope.setReportScenarioStatus( scope, { status: scenario.result.status });
|
|
805
868
|
|
|
806
|
-
if (scenario.result.status !== `
|
|
869
|
+
if (scenario.result.status !== `PASSED`) {
|
|
807
870
|
if ( env_vars.DEBUG ) {
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
await scope.page.
|
|
871
|
+
console.log( `Non-passed status occurred while running test:`, scenario.result.status );
|
|
872
|
+
// If there's a page visible, give us time to examine it
|
|
873
|
+
if ( scope.page ) { await scope.page.waitForTimeout( 60 * 1000 ); }
|
|
811
874
|
}
|
|
812
875
|
|
|
813
876
|
await scope.addToReport(scope, { type: `outcome`, value: `**-- Scenario Failed --**` });
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
877
|
+
if ( scope.page ) {
|
|
878
|
+
// Save/download a picture of the screen that's showing during the unexpected status
|
|
879
|
+
let safe_filename = await scope.getSafeScenarioFilename( scope, { prefix: `error` });
|
|
880
|
+
await scope.page.screenshot({ path: `${ safe_filename }.jpg`, type: `jpeg`, fullPage: true });
|
|
881
|
+
}
|
|
882
|
+
} // Ends if not passed
|
|
817
883
|
|
|
884
|
+
if (scenario.result.status === `FAILED`) {
|
|
885
|
+
await scope.addToReport(scope, { type: `outcome`, value: `**-- Scenario Failed --**` });
|
|
818
886
|
}
|
|
819
887
|
|
|
820
888
|
let original_scenario_status = scenario.result.status;
|
|
@@ -831,7 +899,7 @@ After(async function(scenario) {
|
|
|
831
899
|
// Maybe this should be in `Before`, but it would be so out of context there...
|
|
832
900
|
scope.expected_in_report = [];
|
|
833
901
|
let all_were_included = await scope.reportIncludesAllExpected( scope, { expected });
|
|
834
|
-
if ( all_were_included ) { scenario.result.status = `
|
|
902
|
+
if ( all_were_included ) { scenario.result.status = `PASSED`; }
|
|
835
903
|
}
|
|
836
904
|
|
|
837
905
|
// If there is a page open, then sign out and close it
|
|
@@ -843,23 +911,26 @@ After(async function(scenario) {
|
|
|
843
911
|
try {
|
|
844
912
|
await scope.page.goto(`${ env_vars.BASE_URL }/user/sign-out`, {waitUntil: `domcontentloaded`});
|
|
845
913
|
} catch ( err ) {
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
914
|
+
if ( env_vars.DEBUG ) {
|
|
915
|
+
console.log( `Trying to reset for the next test a second time because the first time failed.` );
|
|
916
|
+
}
|
|
917
|
+
|
|
850
918
|
try {
|
|
851
919
|
await scope.page.goto(`${ env_vars.BASE_URL }/user/sign-out`, {waitUntil: `domcontentloaded`});
|
|
920
|
+
|
|
852
921
|
} catch ( err ) {
|
|
853
922
|
await scope.addToReport(scope, {
|
|
854
923
|
type: `warning`,
|
|
855
|
-
value: `This test ${ original_scenario_status }, but also there
|
|
924
|
+
value: `This test ${ original_scenario_status }, but also there `
|
|
925
|
+
+ `was an error while trying to reset for the next test. You can try `
|
|
926
|
+
+ `re-running the test or checking your server.`
|
|
856
927
|
});
|
|
857
928
|
}
|
|
858
929
|
}
|
|
859
930
|
|
|
860
931
|
await scope.page.close();
|
|
861
932
|
scope.page = null;
|
|
862
|
-
}
|
|
933
|
+
} // ends if scope.page
|
|
863
934
|
});
|
|
864
935
|
|
|
865
936
|
AfterAll(async function() {
|