@suffolklitlab/alkiln 4.9.3 → 4.10.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/test_tests.yml +8 -6
- package/CHANGELOG.md +21 -0
- package/MANIFEST.in +1 -0
- package/_alkiln-misc_artifacts/unit_tests_logs-2022-12-29 at 02h22m01s457ms UTC.txt +20 -0
- package/action.yml +2 -2
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Base64 encoded corner cases are decoded correctly-2022-12-29 at 02h12m20s302ms UTC/report.txt +23 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Fail to find var while keeping value secret-2022-12-29 at 02h14m21s556ms UTC/report.txt +13 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Fail with 2 wrong signin secret names-2022-12-29 at 02h14m19s733ms UTC/report.txt +12 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Fail with a missing phrase-2022-12-29 at 02h13m42s632ms UTC/report.txt +10 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Fail with cannot find missing document-2022-12-29 at 02h14m13s528ms UTC/report.txt +10 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Fail with could not find files-2022-12-29 at 02h14m20s192ms UTC/report.txt +13 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Fail with error page from random input-2022-12-29 at 02h13m27s716ms UTC/random_answers_screenshots-2022-12-29 at 02h13m28s915ms UTC/random-1672280009244.jpg +0 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Fail with error page from random input-2022-12-29 at 02h13m27s716ms UTC/report.txt +12 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Fail with incorrectly present phrase-2022-12-29 at 02h13m43s918ms UTC/report.txt +10 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Fail with link text not visible-2022-12-29 at 02h13m52s649ms UTC/report.txt +10 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Fail with link unexpectedly opens in a new window-2022-12-29 at 02h14m06s008ms UTC/report.txt +56 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Fail with link unexpectedly opens in same window-2022-12-29 at 02h14m01s128ms UTC/report.txt +56 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Fail with link with given text does not lead to correct url-2022-12-29 at 02h13m55s993ms UTC/report.txt +56 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Fail with missing element id-2022-12-29 at 02h13m45s207ms UTC/report.txt +10 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Fail with missing error message-2022-12-29 at 02h13m48s710ms UTC/report.txt +10 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Fail with missing link with url-2022-12-29 at 02h13m54s329ms UTC/report.txt +10 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Fail with missing term with the given text-2022-12-29 at 02h14m12s071ms UTC/report.txt +10 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Fail with no interview at arbitrary url-2022-12-29 at 02h11m01s999ms UTC/report.txt +10 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Fail with system error after Step using wrong file name as trigger-2022-12-29 at 02h14m15s021ms UTC/report.txt +10 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Fail with unexpectedly able to continue-2022-12-29 at 02h13m46s819ms UTC/report.txt +11 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Fail with var not on page-2022-12-29 at 02h14m10s627ms UTC/report.txt +12 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Fail with was unexpectedly not able to continue for invalid field input message-2022-12-29 at 02h13m50s143ms UTC/report.txt +13 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Fail with wrong email secret name-2022-12-29 at 02h14m18s763ms UTC/report.txt +10 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Fail with wrong password secret name-2022-12-29 at 02h14m19s291ms UTC/report.txt +10 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Fails as it doesn't try to 'continue' with a restart button-2022-12-29 at 02h12m22s559ms UTC/report.txt +19 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Fails when table has no header row and rows have only one column-2022-12-29 at 02h14m50s261ms UTC/report.txt +10 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Fields are listed out of order-2022-12-29 at 02h14m55s580ms UTC/report.txt +103 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I am able to set a custom wait time before an interview has been loaded-2022-12-29 at 02h10m12s300ms UTC/report.txt +6 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I am able to set a custom wait time that allows steps to run longer than the half minute default-2022-12-29 at 02h09m35s267ms UTC/report.txt +6 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I answer randomly till the end twice-2022-12-29 at 02h13m19s494ms UTC/random_answers_screenshots-2022-12-29 at 02h13m20s448ms UTC/random-1672280001009.jpg +0 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I answer randomly till the end twice-2022-12-29 at 02h13m19s494ms UTC/random_answers_screenshots-2022-12-29 at 02h13m20s448ms UTC/random-1672280001551.jpg +0 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I answer randomly till the end twice-2022-12-29 at 02h13m19s494ms UTC/random_answers_screenshots-2022-12-29 at 02h13m20s448ms UTC/random-1672280002244.jpg +0 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I answer randomly till the end twice-2022-12-29 at 02h13m19s494ms UTC/random_answers_screenshots-2022-12-29 at 02h13m20s448ms UTC/random-1672280003073.jpg +0 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I answer randomly till the end twice-2022-12-29 at 02h13m19s494ms UTC/random_answers_screenshots-2022-12-29 at 02h13m20s448ms UTC/random-1672280003428.jpg +0 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I answer randomly till the end twice-2022-12-29 at 02h13m19s494ms UTC/random_answers_screenshots-2022-12-29 at 02h13m24s217ms UTC/random-1672280004868.jpg +0 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I answer randomly till the end twice-2022-12-29 at 02h13m19s494ms UTC/random_answers_screenshots-2022-12-29 at 02h13m24s217ms UTC/random-1672280005425.jpg +0 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I answer randomly till the end twice-2022-12-29 at 02h13m19s494ms UTC/random_answers_screenshots-2022-12-29 at 02h13m24s217ms UTC/random-1672280006159.jpg +0 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I answer randomly till the end twice-2022-12-29 at 02h13m19s494ms UTC/random_answers_screenshots-2022-12-29 at 02h13m24s217ms UTC/random-1672280007028.jpg +0 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I answer randomly till the end twice-2022-12-29 at 02h13m19s494ms UTC/random_answers_screenshots-2022-12-29 at 02h13m24s217ms UTC/random-1672280007371.jpg +0 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I answer randomly till the end twice-2022-12-29 at 02h13m19s494ms UTC/report.txt +21 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I can include .yml in the filename-2022-12-29 at 02h12m39s613ms UTC/report.txt +6 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I can match JSON page var to str-2022-12-29 at 02h12m57s106ms UTC/json_for-showifs-2022-12-29 at 02h12m59s731ms UTC.json +154 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I can match JSON page var to str-2022-12-29 at 02h12m57s106ms UTC/report.txt +33 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I can wait as a first step in a test-2022-12-29 at 02h10m50s651ms UTC/report.txt +5 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I can't match JSON page var to str-2022-12-29 at 02h14m16s014ms UTC/json_for-showifs-2022-12-29 at 02h14m18s373ms UTC.json +154 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I can't match JSON page var to str-2022-12-29 at 02h14m16s014ms UTC/report.txt +37 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I check navigation-2022-12-29 at 02h12m41s028ms UTC/report.txt +54 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I check the pages for accessibility-2022-12-29 at 02h13m02s923ms UTC/report.txt +58 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I fill in random input for 1 page-2022-12-29 at 02h13m17s219ms UTC/random_answers_screenshots-2022-12-29 at 02h13m18s174ms UTC/random-1672279998764.jpg +0 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I fill in random input for 1 page-2022-12-29 at 02h13m17s219ms UTC/report.txt +7 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I fill in random input till the end-2022-12-29 at 02h13m12s258ms UTC/random_answers_screenshots-2022-12-29 at 02h13m13s676ms UTC/random-1672279994312.jpg +0 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I fill in random input till the end-2022-12-29 at 02h13m12s258ms UTC/random_answers_screenshots-2022-12-29 at 02h13m13s676ms UTC/random-1672279994892.jpg +0 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I fill in random input till the end-2022-12-29 at 02h13m12s258ms UTC/random_answers_screenshots-2022-12-29 at 02h13m13s676ms UTC/random-1672279995594.jpg +0 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I fill in random input till the end-2022-12-29 at 02h13m12s258ms UTC/random_answers_screenshots-2022-12-29 at 02h13m13s676ms UTC/random-1672279996542.jpg +0 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I fill in random input till the end-2022-12-29 at 02h13m12s258ms UTC/random_answers_screenshots-2022-12-29 at 02h13m13s676ms UTC/random-1672279996887.jpg +0 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I fill in random input till the end-2022-12-29 at 02h13m12s258ms UTC/report.txt +13 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I get the page's JSON-2022-12-29 at 02h13m00s023ms UTC/report.txt +71 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I have four name parts-2022-12-29 at 02h09m31s566ms UTC/report.txt +10 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I have three name parts-2022-12-29 at 02h09m27s653ms UTC/report.txt +10 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I have two name parts-2022-12-29 at 02h09m21s065ms UTC/report.txt +10 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I observe things on a single page when I arrive-2022-12-29 at 02h12m35s237ms UTC/report.txt +7 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I see user errors_-2022-12-29 at 02h12m37s167ms UTC/report.txt +9 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I set various values-2022-12-29 at 02h11m10s659ms UTC/report.txt +58 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I set various values-2022-12-29 at 02h11m10s659ms UTC/simple-doc.pdf +0 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I sign in-2022-12-29 at 02h10m54s349ms UTC/report.txt +7 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I take a screenshot-2022-12-29 at 02h13m01s434ms UTC/report.txt +6 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I take a screenshot-2022-12-29 at 02h13m01s434ms UTC/screenshot-some-screenshot-on-upload-files-2022-12-29 at 02h13m02s597ms UTC.jpg +0 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I upload files with a table-2022-12-29 at 02h15m13s490ms UTC/report.txt +19 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/I want to go to a full arbitrary url-2022-12-29 at 02h10m58s362ms UTC/report.txt +6 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Interview name includes url args with a wait-2022-12-29 at 02h10m52s195ms UTC/report.txt +6 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Interview name includes url args-2022-12-29 at 02h10m48s849ms UTC/report.txt +6 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Latin-Fail with missing language link-2022-12-29 at 02h13m40s278ms UTC/report.txt +10 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Latin-Fail with wrong page id-2022-12-29 at 02h13m41s379ms UTC/report.txt +10 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Proxy and regular vars are mixed-2022-12-29 at 02h14m51s648ms UTC/report.txt +35 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Report doesn't complain about `there_is_another _ False` in a table_-2022-12-29 at 02h14m36s652ms UTC/report.txt +16 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Report lists unused table rows-2022-12-29 at 02h14m29s563ms UTC/report.txt +65 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Report still shows page id when I tap to continue without setting any fields-2022-12-29 at 02h14m25s620ms UTC/report.txt +22 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Server finishes reloading-2022-12-29 at 02h11m08s477ms UTC/report.txt +6 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Sign in to server successfully-2022-12-29 at 02h14m34s127ms UTC/report.txt +6 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Story table accidentally uses the opposite double or single quotes-2022-12-29 at 02h15m11s462ms UTC/report.txt +18 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Table MISSING trigger column-2022-12-29 at 02h14m41s898ms UTC/report.txt +33 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Table has no header row, MISSING trigger column-2022-12-29 at 02h14m47s483ms UTC/report.txt +33 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Table has no header row, has trigger column-2022-12-29 at 02h14m44s776ms UTC/report.txt +37 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Table has trigger column-2022-12-29 at 02h14m39s081ms UTC/report.txt +37 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Test _Then I cannot continue_-2022-12-29 at 02h12m48s119ms UTC/report.txt +9 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Test _Then I can/342/200/231t continue_ with an apostrophe-2022-12-29 at 02h12m52s553ms UTC/report.txt" +9 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Test _Then I do not continue_-2022-12-29 at 02h12m50s316ms UTC/report.txt +9 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Test _Then I don't continue_ with a single quote-2022-12-29 at 02h12m45s907ms UTC/report.txt +9 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Test _Then I don/342/200/231t continue_ with an apostrophe-2022-12-29 at 02h12m54s800ms UTC/report.txt" +9 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/Warn when there are too many names-2022-12-29 at 02h14m22s722ms UTC/report.txt +8 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/debug_log.txt +2373 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/handles settings from Github secrets-2022-12-29 at 02h12m13s413ms UTC/report.txt +19 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/report.txt +1439 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/tap element with an error-2022-12-29 at 02h12m18s853ms UTC/report.txt +10 -0
- package/alkiln-2022-12-29 at 02h09m19s552ms UTC/tap elements-2022-12-29 at 02h12m16s677ms UTC/report.txt +6 -0
- package/docassemble/__init__.py +5 -0
- package/lib/scope.js +183 -119
- package/lib/steps.js +28 -0
- package/lib/utils/files.js +3 -3
- package/lib/utils/session_vars.js +5 -3
- package/package.json +5 -4
- package/setup.py +60 -0
- package/tests/unit_tests/fields.fixtures.js +79 -103
- package/tests/unit_tests/getAllFields.test.js +18 -13
- package/tests/unit_tests/getSafeScenarioFilename.test.js +2 -2
- package/tests/unit_tests/html.fixtures.js +0 -1
- package/tests/features/assembly_line.feature +0 -43
- package/tests/features/establishing_steps.feature +0 -62
- package/tests/features/example_test.feature +0 -11
- package/tests/features/interactive_steps.feature +0 -134
- package/tests/features/observation_steps.feature +0 -153
- package/tests/features/random_input.feature +0 -31
- package/tests/features/reload.feature +0 -155
- package/tests/features/reports.feature +0 -546
- package/tests/features/some_png_1.png +0 -0
- package/tests/features/some_png_2.png +0 -0
- package/tests/features/story_table_formats.feature +0 -125
- package/tests/features/story_tables.feature +0 -91
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
|
|
2
|
+
---------------
|
|
3
|
+
Scenario: tap element with an error
|
|
4
|
+
Tags: @interactive @i4 @tap-elements @tabs @error
|
|
5
|
+
---------------
|
|
6
|
+
Trying to load the interview
|
|
7
|
+
|
|
8
|
+
ERROR: Couldn't find the tab with id "#Tests-not_there-tab" on the page, is there a typo?
|
|
9
|
+
|
|
10
|
+
**-- Scenario Failed --**
|
package/lib/scope.js
CHANGED
|
@@ -54,8 +54,34 @@ let is_secret_var = function(row) {
|
|
|
54
54
|
return original.flags !== undefined && original.flags.secret_name !== undefined;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
let fromBase64 = function(base64_str) {
|
|
58
|
+
/* Takes a base64 encoded string and returns it decoded.
|
|
59
|
+
* Note that this can take strings with invalid base 64 characters,
|
|
60
|
+
* but will change those characters to `/`s instead.
|
|
61
|
+
*/
|
|
62
|
+
let buffer = Buffer.from( base64_str, 'base64' );
|
|
63
|
+
return buffer.toString( `utf-8` );
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
let toBase64 = function ( utf8_str, exclude_padding=true) {
|
|
67
|
+
/* Encoded a given string (@param utf8_str) in base64.
|
|
68
|
+
* @param exclude_padding {boolean} - if true, strips off `=` characters
|
|
69
|
+
* that are added as padding while base64 encoding (docassemble doesn't
|
|
70
|
+
* include those characters, and uses the UTF-7 base64 encoding
|
|
71
|
+
* (RFC-2152)). For more details, see
|
|
72
|
+
* https://github.com/nodejs/node/issues/6107#issuecomment-207177131
|
|
73
|
+
*/
|
|
74
|
+
if ( typeof( utf8_str ) !== `string` ) { // Prevent an error
|
|
75
|
+
return `Will+Never+Match+Existing+DOM+Node==`;
|
|
76
|
+
}
|
|
77
|
+
let buffer = Buffer.from( utf8_str, 'utf-8' );
|
|
78
|
+
let base64str = buffer.toString( `base64` )
|
|
79
|
+
return exclude_padding ? base64str.replace(/=/g, '') : base64str;
|
|
80
|
+
}
|
|
81
|
+
|
|
57
82
|
let proxies_regex = /(\bx\.)|(\bx\[)|(\[[ijklmn]\])/g;
|
|
58
|
-
let
|
|
83
|
+
let da_base64_regex = /^[A-Za-z0-9+/]+$/;
|
|
84
|
+
let misc_artifacts_dir = `_alkiln-misc_artifacts`;
|
|
59
85
|
|
|
60
86
|
module.exports = {
|
|
61
87
|
trigger_not_needed_flag: `ALKiln: no trigger variable needed`,
|
|
@@ -620,7 +646,7 @@ module.exports = {
|
|
|
620
646
|
* - Birthdate fields that will be showing up relatively soon
|
|
621
647
|
* - Time fields?
|
|
622
648
|
*/
|
|
623
|
-
let base64_var_name =
|
|
649
|
+
let base64_var_name = toBase64( var_name );
|
|
624
650
|
|
|
625
651
|
// Will catch some radio and checkbox inputs too, which will then be rejected
|
|
626
652
|
// Note: I think `showif`s with `code` don't use `data-saveas`
|
|
@@ -659,12 +685,14 @@ module.exports = {
|
|
|
659
685
|
return to_manipulate;
|
|
660
686
|
}, // Ends scope.setVar()
|
|
661
687
|
|
|
688
|
+
continue_button_selector: `fieldset.da-field-buttons button[type="submit"].btn-primary`,
|
|
689
|
+
signature_selector: `fieldset .dasigsave`,
|
|
662
690
|
continue: async function ( scope ) {
|
|
663
691
|
/* Presses whatever button it finds that might lead to the next page. */
|
|
664
692
|
// Any selectors I find seem somewhat precarious.
|
|
665
693
|
let elem = await Promise.race([
|
|
666
|
-
scope.page.waitForSelector(
|
|
667
|
-
scope.page.waitForSelector(
|
|
694
|
+
scope.page.waitForSelector(scope.continue_button_selector), // other pages (this is the most consistent way)
|
|
695
|
+
scope.page.waitForSelector(scope.signature_selector), // signature page
|
|
668
696
|
]);
|
|
669
697
|
await elem.evaluate( el => { return el.className });
|
|
670
698
|
// Waits for navigation or user error
|
|
@@ -675,15 +703,16 @@ module.exports = {
|
|
|
675
703
|
/** Return true if a button that will allow continuing appears
|
|
676
704
|
* on this page. Otherwise return false. */
|
|
677
705
|
|
|
678
|
-
//
|
|
706
|
+
// Will only find this with "Continue buttons":
|
|
707
|
+
// * An actual continue button that doesn't set a variable
|
|
708
|
+
// <button class="btn btn-da btn-primary" type="submit">Continue</button>
|
|
709
|
+
// * One that sets a variable:
|
|
710
|
+
// <button type="submit" class="btn btn-da btn-primary" name="Zm9v" value="True">Continue</button>
|
|
711
|
+
// It will not find event screen `buttons:`, like an exit button or a restart button
|
|
679
712
|
// <button type="submit" class="btn btn-da btn-danger" name="X211bHRpcGxlX2Nob2ljZQ" value="0">exit</button>
|
|
680
|
-
// An actual continue button that doesn't set a variable
|
|
681
|
-
// <button class="btn btn-da btn-primary" type="submit">Continue</button>
|
|
682
|
-
// One that sets a variable:
|
|
683
|
-
// <button type="submit" class="btn btn-da btn-primary" name="Zm9v" value="True">Continue</button>
|
|
684
713
|
// `buttons:` can be used in question blocks as choices
|
|
685
|
-
let regular = await scope.page.$(
|
|
686
|
-
let signature = await scope.page.$(
|
|
714
|
+
let regular = await scope.page.$(scope.continue_button_selector);
|
|
715
|
+
let signature = await scope.page.$(scope.signature_selector);
|
|
687
716
|
|
|
688
717
|
return regular !== null || signature !== null;
|
|
689
718
|
|
|
@@ -972,9 +1001,9 @@ module.exports = {
|
|
|
972
1001
|
if ( !encoded_trigger_var ) {
|
|
973
1002
|
// TODO: Add documentation and then link to it in this message.
|
|
974
1003
|
await scope.addToReport(scope, { type: `warning`, value: `You are missing an element containing the data for the page's trigger variable. Some fields, like loops with index variables, may not work correctly in these tests. See https://suffolklitlab.org/docassemble-AssemblyLine-documentation/docs/automated_integrated_testing/#a-missing-trigger-variable.` });
|
|
975
|
-
encoded_trigger_var =
|
|
1004
|
+
encoded_trigger_var = toBase64( `None` );
|
|
976
1005
|
}
|
|
977
|
-
let trigger =
|
|
1006
|
+
let trigger = fromBase64( encoded_trigger_var );
|
|
978
1007
|
|
|
979
1008
|
|
|
980
1009
|
// Some `show if` fields have `names` like '_field_n' instead of their var name. Ex: _field_1
|
|
@@ -1120,7 +1149,18 @@ module.exports = {
|
|
|
1120
1149
|
// Inputs like textareas don't have values
|
|
1121
1150
|
if ( values.length > 0 ) {
|
|
1122
1151
|
for ( let value of values ){
|
|
1123
|
-
possible_table_rows.push({ var: var_name, value, });
|
|
1152
|
+
possible_table_rows.push({ var: var_name, value: value, });
|
|
1153
|
+
// Ignore blanks, and values that certainly aren't base64 encoded like True and False
|
|
1154
|
+
// Modified from https://stackoverflow.com/a/8571649/11416267
|
|
1155
|
+
// DA doesn't use `==` to pad base 64
|
|
1156
|
+
if (value !== 'None' && value !== 'True' && value !== 'False'
|
|
1157
|
+
&& value.match(da_base64_regex)) {
|
|
1158
|
+
let value_decoded = fromBase64(value);
|
|
1159
|
+
let values_decoded = scope.decodeFully( scope, {expr_str: value_decoded });
|
|
1160
|
+
for (let possible_val of values_decoded) {
|
|
1161
|
+
possible_table_rows.push({var: var_name, value: possible_val, });
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1124
1164
|
}
|
|
1125
1165
|
} else {
|
|
1126
1166
|
possible_table_rows.push({ var: var_name, value: '', });
|
|
@@ -1145,11 +1185,11 @@ module.exports = {
|
|
|
1145
1185
|
|
|
1146
1186
|
let field_like_names = {};
|
|
1147
1187
|
let field_like_names_encoded = $('input[name="_varnames"]')[0].attribs.value;
|
|
1148
|
-
let field_like_names_str =
|
|
1188
|
+
let field_like_names_str = fromBase64( field_like_names_encoded );
|
|
1149
1189
|
let field_like_names_json = JSON.parse( field_like_names_str );
|
|
1150
1190
|
for ( let field_like_key in field_like_names_json ) {
|
|
1151
|
-
let field_like_DOM_name =
|
|
1152
|
-
let field_like_var_name =
|
|
1191
|
+
let field_like_DOM_name = fromBase64( field_like_key );
|
|
1192
|
+
let field_like_var_name = fromBase64( field_like_names_json[ field_like_key ] );
|
|
1153
1193
|
field_like_names[ field_like_DOM_name ] = field_like_var_name;
|
|
1154
1194
|
}
|
|
1155
1195
|
|
|
@@ -1178,14 +1218,11 @@ module.exports = {
|
|
|
1178
1218
|
* @param encoded {str} - base64 encoded string of the node
|
|
1179
1219
|
* @param field_like_names {obj} - e.g. `{ _field_0: 'some_checkbox_var_name' }`
|
|
1180
1220
|
* @param nota {bool} - is the field a 'none of the above' field? */
|
|
1181
|
-
let var_names = [];
|
|
1182
|
-
let var_name = '';
|
|
1183
|
-
|
|
1184
1221
|
// E.g. continue buttons that don't set a variable
|
|
1185
|
-
if ( encoded === undefined ) { return
|
|
1222
|
+
if ( encoded === undefined ) { return []; }
|
|
1186
1223
|
|
|
1187
1224
|
// Names can be encoded multiple times, so start peeling the layers
|
|
1188
|
-
let layer_1_decoded =
|
|
1225
|
+
let layer_1_decoded = fromBase64( encoded );
|
|
1189
1226
|
// If this is of the format `_field_n`, we need to get the actual matching var name.
|
|
1190
1227
|
if ( field_like_names[ layer_1_decoded ] ) {
|
|
1191
1228
|
layer_1_decoded = field_like_names[ layer_1_decoded ];
|
|
@@ -1200,60 +1237,66 @@ module.exports = {
|
|
|
1200
1237
|
// TODO: Should we move this back into `getAllFields()`?
|
|
1201
1238
|
}
|
|
1202
1239
|
|
|
1203
|
-
|
|
1204
|
-
|
|
1240
|
+
return scope.decodeFully(scope, { expr_str: layer_1_decoded, field_like_names, nota });
|
|
1241
|
+
}, // Ends scope.getPossibleVarNames()
|
|
1242
|
+
|
|
1243
|
+
decodeFully: function ( scope, { expr_str, field_like_names = {}, nota} ) {
|
|
1244
|
+
/*
|
|
1245
|
+
* Given a DA variable or value name, make sure it's fully decoded from base64.
|
|
1246
|
+
* @param variable_str {str} - a python variable string, potentially partially base64 encoded
|
|
1247
|
+
* Some examples:
|
|
1248
|
+
* - my_variable
|
|
1249
|
+
* - checkboxes_choices[B'Y2hlY2tib3hfb3RoZXJfb3B0XzI']
|
|
1250
|
+
* - foo[bar][B'Y2hlY2tib3hfb3RoZXJfb3B0XzI']
|
|
1251
|
+
* @param field_like_names {obj} - e.g. `{ _field_0: 'some_checkbox_var_name' }`
|
|
1252
|
+
* @param nota {bool} - is the field a 'none of the above' field?
|
|
1253
|
+
*/
|
|
1254
|
+
// Some fields have a key hidden inside them.
|
|
1255
|
+
// This gets the variable name before the final brackets, and the likely
|
|
1256
|
+
// still base64 encoded string inside the brackets
|
|
1257
|
+
let before_and_in_brackets = expr_str.match( /^(.*)\[[BR]'(.*)'\]/ );
|
|
1205
1258
|
|
|
1206
1259
|
// Of the format `foo[B'encoded']` or `foo[R'encoded']`
|
|
1260
|
+
// The B means internal to docassemble, the encoded portion is a string,
|
|
1261
|
+
// and the R means that the python `repr` function was called with a
|
|
1262
|
+
// non-string object
|
|
1207
1263
|
// See https://github.com/jhpyle/docassemble/blob/595ad0a08572c0188f9ab49b1a6af99a3621cd42/docassemble_base/docassemble/base/standardformatter.py#L2108
|
|
1208
1264
|
|
|
1209
|
-
// What about something like foo[R'encoded1'][B'encoded2']? Is that a
|
|
1210
|
-
// thing? Can they be index numbers? Or just `foo['encoded1']`? What
|
|
1211
|
-
// would their format be? The above? `foo[R'actual_choice'][B'encoded']`?
|
|
1212
|
-
// `foo['something'][B'encoded']`?
|
|
1213
|
-
|
|
1214
1265
|
// =====================
|
|
1215
1266
|
// Ex: checkboxes_choices[B'Y2hlY2tib3hfb3RoZXJfb3B0XzI']
|
|
1216
1267
|
// Ex: checkboxes_choices[R'Y2hlY2tib3hfb3RoZXJfb3B0XzI']
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
let key_or_name =
|
|
1268
|
+
let possible = [];
|
|
1269
|
+
if ( before_and_in_brackets ) {
|
|
1270
|
+
let key_or_name = before_and_in_brackets[1];
|
|
1220
1271
|
// If this is of the format `_field_n`, we need to get the actual matching var name.
|
|
1221
|
-
|
|
1222
|
-
var_name = field_like_names[ key_or_name ];
|
|
1223
|
-
} else {
|
|
1224
|
-
var_name = key_or_name;
|
|
1225
|
-
}
|
|
1272
|
+
let var_name = field_like_names [ key_or_name ] || key_or_name;
|
|
1226
1273
|
|
|
1227
|
-
|
|
1228
|
-
if ( nota ) { var_names.push( `${ var_name }['None']` ); }
|
|
1229
|
-
else {
|
|
1230
|
-
// Get the choice name. E.g. option_1, option_2
|
|
1231
|
-
let box_layer_1_decoded = await scope.fromBase64( scope, { base64_str: checkbox_match[2] });
|
|
1232
|
-
var_names.push( `${ var_name }['${ box_layer_1_decoded }']` );
|
|
1274
|
+
let dictionary_key = before_and_in_brackets[2];
|
|
1233
1275
|
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1276
|
+
// Our own marker for a 'none of the above' checkbox choice
|
|
1277
|
+
if ( nota ) {
|
|
1278
|
+
possible.push( `${ var_name }['None']` );
|
|
1279
|
+
} else {
|
|
1280
|
+
if (dictionary_key.match(da_base64_regex)) {
|
|
1281
|
+
// Get the choice name. E.g. option_1, option_2
|
|
1282
|
+
let dictionary_key_decoded = fromBase64( dictionary_key );
|
|
1283
|
+
possible.push( `${ var_name }['${ dictionary_key_decoded }']` );
|
|
1284
|
+
if (dictionary_key_decoded.match(da_base64_regex)) {
|
|
1285
|
+
try {
|
|
1286
|
+
// The part inside `[B'encoded']` could need one more decoding.
|
|
1287
|
+
possible.push(`${ var_name }['${ fromBase64( dictionary_key_decoded ) }']`);
|
|
1288
|
+
} catch ( err ) {} // It wasn't double encoded. Do nothing.
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1240
1291
|
}
|
|
1241
1292
|
|
|
1242
1293
|
// =====================
|
|
1243
|
-
//
|
|
1294
|
+
// If bracket regex didn't match, just use var name
|
|
1244
1295
|
} else {
|
|
1245
|
-
|
|
1246
|
-
var_names.push(`${ layer_1_decoded }`);
|
|
1247
|
-
// // Values are sometimes encoded multiple times (check this happens with a plain var name)
|
|
1248
|
-
// let layer_2_decoded = await scope.fromBase64( layer_1_decoded );
|
|
1249
|
-
// names.var_names.push( layer_2_decoded );
|
|
1296
|
+
possible.push(`${ expr_str }`);
|
|
1250
1297
|
}
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
// https://stackoverflow.com/a/23377268
|
|
1254
|
-
|
|
1255
|
-
return var_names;
|
|
1256
|
-
}, // Ends scope.getPossibleVarNames()
|
|
1298
|
+
return possible;
|
|
1299
|
+
},
|
|
1257
1300
|
|
|
1258
1301
|
getOptionValues: async function ( scope, { $select }) {
|
|
1259
1302
|
/* Returns all the option node values of the select node. */
|
|
@@ -1261,35 +1304,11 @@ module.exports = {
|
|
|
1261
1304
|
let option_nodes = $select.find( `option` );
|
|
1262
1305
|
for ( let opt of option_nodes ) {
|
|
1263
1306
|
options.push( opt.attribs.value );
|
|
1264
|
-
//
|
|
1265
|
-
let decoded = await scope.fromBase64( scope, { base64_str: opt.attribs.value });
|
|
1266
|
-
options.push( decoded );
|
|
1307
|
+
// Dropdowns created w/ objects are base64 encoded; but it's handled in getPossibleTableRowMatches
|
|
1267
1308
|
}
|
|
1268
|
-
// TODO: These may be encoded? Just 'decode' and append those vals too.
|
|
1269
|
-
// TODO: Keep those decoded values somewhere for setting the right
|
|
1270
|
-
// option in the DOM. Not sure how that can be put together sensically.
|
|
1271
1309
|
return options;
|
|
1272
1310
|
}, // Ends scope.getOptionValues()
|
|
1273
1311
|
|
|
1274
|
-
fromBase64: async function ( scope, { base64_str }) {
|
|
1275
|
-
let buffer = Buffer.from( base64_str, 'base64' );
|
|
1276
|
-
return buffer.toString( `utf-8` );
|
|
1277
|
-
},
|
|
1278
|
-
|
|
1279
|
-
toBase64: async function ( scope, { utf8_str }, exclude_padding=true) {
|
|
1280
|
-
if ( typeof( utf8_str ) !== `string` ) { // Prevent an error
|
|
1281
|
-
return `Will+Never+Match+Existing+DOM+Node==`;
|
|
1282
|
-
}
|
|
1283
|
-
// Sometimes, converting to base64 results in padding characters ('=')
|
|
1284
|
-
// being added to the end. Docassemble does not use these padding
|
|
1285
|
-
// characters everywhere, so we allow for stripping them using
|
|
1286
|
-
// the exclude_padding argument. For more details, see
|
|
1287
|
-
// https://github.com/nodejs/node/issues/6107#issuecomment-207177131
|
|
1288
|
-
let buffer = Buffer.from( utf8_str, 'utf-8' );
|
|
1289
|
-
let base64str = buffer.toString( `base64` )
|
|
1290
|
-
return exclude_padding ? base64str.replace(/=/g, '') : base64str;
|
|
1291
|
-
},
|
|
1292
|
-
|
|
1293
1312
|
|
|
1294
1313
|
// TODO: Maybe add `from_story_table` to the var data table (array...)
|
|
1295
1314
|
getMatchingRows: async function ( scope, { field, var_data }) {
|
|
@@ -1481,7 +1500,12 @@ module.exports = {
|
|
|
1481
1500
|
await scope.addToReport(scope, { type: `warning`, value: multiple_matches_msg });
|
|
1482
1501
|
}
|
|
1483
1502
|
|
|
1484
|
-
if ( session_vars.get_debug() ) {
|
|
1503
|
+
if ( session_vars.get_debug() ) {
|
|
1504
|
+
console.log( `final_matching_rows:\n`, JSON.stringify( final_matching_rows ));
|
|
1505
|
+
if ( final_matching_rows.length == 0) {
|
|
1506
|
+
console.log(` field:\n`, JSON.stringify( field ) );
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1485
1509
|
return final_matching_rows;
|
|
1486
1510
|
}, // Ends scope.getMatchingRows()
|
|
1487
1511
|
|
|
@@ -1685,8 +1709,6 @@ module.exports = {
|
|
|
1685
1709
|
},
|
|
1686
1710
|
select: async function ( scope, { handle, answer }) {
|
|
1687
1711
|
// Note: I don't remember what's really going on in here.
|
|
1688
|
-
// I will note that values of `select` elements are strings,
|
|
1689
|
-
// not variables, so we don't need to check for variable names.
|
|
1690
1712
|
|
|
1691
1713
|
// A dropdown's option value can be one of two things
|
|
1692
1714
|
// Try to find the element using the first value
|
|
@@ -1707,7 +1729,7 @@ module.exports = {
|
|
|
1707
1729
|
// If that literal value isn't on the page, it should be a base64 encoded value
|
|
1708
1730
|
// TODO: Can these be double encoded? Can they be encoded like objects?
|
|
1709
1731
|
} else {
|
|
1710
|
-
let base64_name =
|
|
1732
|
+
let base64_name = toBase64( answer );
|
|
1711
1733
|
await handle.select( base64_name );
|
|
1712
1734
|
}
|
|
1713
1735
|
|
|
@@ -1783,35 +1805,53 @@ module.exports = {
|
|
|
1783
1805
|
/* Try to upload one or more files to a file-type input field.
|
|
1784
1806
|
* Does not submit, so no danger of timeout with server reload.
|
|
1785
1807
|
*/
|
|
1786
|
-
|
|
1787
|
-
// Tests
|
|
1788
|
-
// Makes an absolute path from the
|
|
1789
|
-
let
|
|
1790
|
-
let
|
|
1791
|
-
let
|
|
1792
|
-
|
|
1793
|
-
// Make sure one of the valid directories exist. This only allows
|
|
1794
|
-
// one directory to be used per Step or table row. We don't anticipate
|
|
1795
|
-
// future people having a `tests/features` folder, let alone both.
|
|
1808
|
+
|
|
1809
|
+
// Tests should be one place: docassemble/*/data/sources, where * is the only folder in `docassemble`.
|
|
1810
|
+
// Makes an absolute path from the folder in which `npm run` was used plus our internal folders
|
|
1811
|
+
let docassemble_pkg_path = `${ process.cwd() }/docassemble`;
|
|
1812
|
+
let subpackage_name = session_vars.get_package_name().substring(12);
|
|
1813
|
+
let pkg_paths = [];
|
|
1796
1814
|
try {
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
}
|
|
1815
|
+
fs.accessSync(docassemble_pkg_path);
|
|
1816
|
+
// https://stackoverflow.com/a/24594123/11416267
|
|
1817
|
+
let dirs = fs.readdirSync(docassemble_pkg_path, {withFileTypes: true}).filter(dirent => dirent.isDirectory()).map(dirent => dirent.name);
|
|
1818
|
+
if (dirs.length < 1) {
|
|
1819
|
+
let msg = `You can store files to upload in 'docassemble/${ subpackage_name }/data/source'. These tests could not find a folder like that starting at ${ process.cwd() }.`;
|
|
1820
|
+
await scope.addToReport( scope, { type: `warning`, value: msg});
|
|
1821
|
+
throw Error(msg); // Most people will want to know the sources folder path;
|
|
1822
|
+
}
|
|
1823
|
+
for (let dir of dirs) {
|
|
1824
|
+
pkg_paths.push(`${docassemble_pkg_path}/${dir}`);
|
|
1825
|
+
}
|
|
1826
|
+
} catch ( error_da ) {
|
|
1827
|
+
let msg = `You can store files to upload in 'docassemble/${ subpackage_name }/data/source'. ` +
|
|
1828
|
+
`These tests could not find a folder like that. The current directory is ` +
|
|
1829
|
+
` ${ process.cwd() }; is that in the top level folder of your docassemble package? (${ session_vars.get_package_name() })?`;
|
|
1830
|
+
await scope.addToReport( scope, { type: `warning`, value: msg});
|
|
1831
|
+
throw error_da; // Most people will want to know the sources folder path;
|
|
1832
|
+
}
|
|
1805
1833
|
|
|
1806
|
-
|
|
1834
|
+
let chosen_dir = null;
|
|
1835
|
+
let err_paths = [];
|
|
1836
|
+
for (let pkg_path of pkg_paths) {
|
|
1837
|
+
let dir = `${ pkg_path }/data/sources`;
|
|
1807
1838
|
try {
|
|
1808
|
-
fs.accessSync(
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1839
|
+
fs.accessSync(dir);
|
|
1840
|
+
chosen_dir = dir;
|
|
1841
|
+
break;
|
|
1842
|
+
} catch ( error_full ) {
|
|
1843
|
+
err_paths.push(`'${dir}'`);
|
|
1813
1844
|
}
|
|
1814
1845
|
}
|
|
1846
|
+
if (chosen_dir === null) {
|
|
1847
|
+
let msg = `You can store files to upload in ${err_paths.join(", or ")}. These tests could not find any of those folders.`;
|
|
1848
|
+
await scope.addToReport( scope, { type: `warning`, value: msg });
|
|
1849
|
+
throw Error(msg); // Most people will want to know the sources folder path;
|
|
1850
|
+
}
|
|
1851
|
+
|
|
1852
|
+
if (pkg_paths.length > 1 && pkg_paths.length - err_paths.length > 1) {
|
|
1853
|
+
await scope.addToReport( scope, { type: `warning`, value: `You have multiple folders in the 'docassemble' folder (${ pkg_paths }). These tests will use the first folder with a "data/sources" subfolder (${chosen_dir}).` });
|
|
1854
|
+
}
|
|
1815
1855
|
|
|
1816
1856
|
// Allow a typo where someone forgot to include a space after a comma
|
|
1817
1857
|
let file_names = answer.split(`,`);
|
|
@@ -1823,15 +1863,14 @@ module.exports = {
|
|
|
1823
1863
|
// If the developer correctly used a ", ", there will be a space at the
|
|
1824
1864
|
// start of the string. Remove it. If they forgot the space, that's fine too.
|
|
1825
1865
|
name = name.replace(/^\s/, '');
|
|
1826
|
-
let file_path = path.join(
|
|
1866
|
+
let file_path = path.join( chosen_dir, name );
|
|
1827
1867
|
|
|
1828
1868
|
try {
|
|
1829
1869
|
fs.accessSync( file_path );
|
|
1830
1870
|
paths.push( file_path );
|
|
1831
|
-
|
|
1832
1871
|
} catch ( err ) {
|
|
1833
1872
|
// TODO: Should this throw an error?
|
|
1834
|
-
await scope.addToReport( scope, { type: `warning`, value: `Could not find "${ name }" in "${
|
|
1873
|
+
await scope.addToReport( scope, { type: `warning`, value: `Could not find "${ name }" in "${ chosen_dir }"` });
|
|
1835
1874
|
}
|
|
1836
1875
|
}
|
|
1837
1876
|
|
|
@@ -2127,13 +2166,18 @@ module.exports = {
|
|
|
2127
2166
|
enhanced_var_data.push( special_row );
|
|
2128
2167
|
|
|
2129
2168
|
// Neutralize a `.there_is_another` row in a story table
|
|
2130
|
-
} else if ( from_story_table && var_datum.var.match( /\.there_is_another$/ ) ) {
|
|
2169
|
+
} else if ( from_story_table && var_datum.var.match( /\.there_is_another$/ ) && var_datum.value !== `False`) {
|
|
2131
2170
|
var_datum.invalid = true;
|
|
2132
2171
|
// Removing the row will just cause a different error that will take longer to fail and
|
|
2133
2172
|
// probably add a confusing message to the report, so mutating seems, sadly, more useful.
|
|
2134
2173
|
var_datum.value = `False`; // The original value is still preserved
|
|
2135
2174
|
// Warn the developer not to use `.there_is_another`.
|
|
2136
|
-
await scope.addToReport( scope, { type: `warning`,
|
|
2175
|
+
await scope.addToReport( scope, { type: `warning`,
|
|
2176
|
+
value: 'The attribute `.there_is_another` is invalid in story table tests. Replace it with '
|
|
2177
|
+
+ '`.target_number` in your `var` and `trigger` columns. Set the `value` to the number of items in '
|
|
2178
|
+
+ `that list. This test will now set this row's \`value\` to \`False\`. See `
|
|
2179
|
+
+ `https://suffolklitlab.github.io/docassemble-AssemblyLine-documentation/docs/automated_integrated_testing#there_is_another. `
|
|
2180
|
+
+ `The row data is\n${ JSON.stringify( var_datum.original )}` });
|
|
2137
2181
|
}
|
|
2138
2182
|
}
|
|
2139
2183
|
|
|
@@ -2821,4 +2865,24 @@ module.exports = {
|
|
|
2821
2865
|
|
|
2822
2866
|
return all_are_included;
|
|
2823
2867
|
}, // Ends scope.reportIncludesAllExpected()
|
|
2868
|
+
|
|
2869
|
+
reportDoesNotInclude: async function ( scope, { not_expected=[] }) {
|
|
2870
|
+
/* Tests the behavior of this testing framework.
|
|
2871
|
+
* Test whether the expected values are not included in the test report.
|
|
2872
|
+
*
|
|
2873
|
+
* @param not_expected {array} Arr of strs that should not appear in the report.
|
|
2874
|
+
*/
|
|
2875
|
+
let current_report_obj = scope.report.get( scope.scenario_id );
|
|
2876
|
+
let scenario = [ scope.scenario_id, current_report_obj ]; // Mimic how loop works with `Map`
|
|
2877
|
+
let report = await scope.getPrintableScenario( scope, { scenario });
|
|
2878
|
+
let none_included = true;
|
|
2879
|
+
for ( let one_expectation of not_expected ) {
|
|
2880
|
+
if ( report.includes( one_expectation )) {
|
|
2881
|
+
none_included = false;
|
|
2882
|
+
expect( report ).not.to.contain( one_expectation );
|
|
2883
|
+
}
|
|
2884
|
+
}
|
|
2885
|
+
|
|
2886
|
+
return none_included;
|
|
2887
|
+
},
|
|
2824
2888
|
};
|
package/lib/steps.js
CHANGED
|
@@ -115,6 +115,7 @@ Before(async (scenario) => {
|
|
|
115
115
|
scope.scenario_id = uuidv4();
|
|
116
116
|
scope.expected_status = null;
|
|
117
117
|
scope.expected_in_report = null;
|
|
118
|
+
scope.expected_not_in_report = null;
|
|
118
119
|
scope.server_reload_promise = null;
|
|
119
120
|
|
|
120
121
|
await scope.addReportHeading(scope, {scenario});
|
|
@@ -1068,6 +1069,19 @@ Given(/the Scenario report should include/i, async ( report_text ) => {
|
|
|
1068
1069
|
|
|
1069
1070
|
});
|
|
1070
1071
|
|
|
1072
|
+
Given(/the Scenario report should not include/i, async ( report_text ) => {
|
|
1073
|
+
/* WARNING: If a Step will fail, this Step must come first.
|
|
1074
|
+
*
|
|
1075
|
+
* Prepare to test that the Scenario report does not include `report_text`.
|
|
1076
|
+
* The actual test has to be done at the end of the Scenario as some text
|
|
1077
|
+
* may be added to the report there. */
|
|
1078
|
+
if ( !scope.expected_not_in_report ) {
|
|
1079
|
+
scope.expected_not_in_report = [];
|
|
1080
|
+
}
|
|
1081
|
+
scope.expected_not_in_report.push( report_text );
|
|
1082
|
+
|
|
1083
|
+
});
|
|
1084
|
+
|
|
1071
1085
|
Given(/the final Scenario status should be "(passed|failed)"/i, async ( expected_status ) => {
|
|
1072
1086
|
/* WARNING: If a Step will fail, this Step must come first.
|
|
1073
1087
|
*
|
|
@@ -1156,6 +1170,20 @@ After(async function(scenario) {
|
|
|
1156
1170
|
else { scenario.result.status = `FAILED`; }
|
|
1157
1171
|
}
|
|
1158
1172
|
|
|
1173
|
+
if (scope.expected_not_in_report && scope.expected_not_in_report.length > 0) {
|
|
1174
|
+
let not_expected = scope.expected_not_in_report;
|
|
1175
|
+
// Reset report values no matter what so they don't mess up future scenarios
|
|
1176
|
+
scope.expected_not_in_report = null;
|
|
1177
|
+
let all_were_not_there = await scope.reportDoesNotInclude( scope, { not_expected });
|
|
1178
|
+
|
|
1179
|
+
if ( all_were_not_there ) {
|
|
1180
|
+
scenario.result.status = `PASSED`;
|
|
1181
|
+
} else {
|
|
1182
|
+
scenario.result.status = `FAILED`;
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1159
1187
|
// If there is a page open, then sign out and close it
|
|
1160
1188
|
if ( scope.page ) {
|
|
1161
1189
|
// Catch a possible reload error.
|
package/lib/utils/files.js
CHANGED
|
@@ -11,14 +11,14 @@ files.readable_date = function() {
|
|
|
11
11
|
*/
|
|
12
12
|
let date = new Date(); // now
|
|
13
13
|
let day = ("0" + date.getUTCDate()).slice(-2);
|
|
14
|
-
let month = ("0" + date.getUTCMonth() + 1).slice(-2);
|
|
14
|
+
let month = ("0" + (date.getUTCMonth() + 1)).slice(-2);
|
|
15
15
|
let year = date.getUTCFullYear();
|
|
16
16
|
let hours = ("0" + date.getUTCHours()).slice(-2);
|
|
17
17
|
let mins = ("0" + date.getUTCMinutes()).slice(-2);
|
|
18
18
|
let secs = ("0" + date.getUTCSeconds()).slice(-2);
|
|
19
19
|
let msecs = ("00" + date.getUTCMilliseconds()).slice(-3);
|
|
20
20
|
|
|
21
|
-
let fancy_str = `${ year }-${ month }-${ day } at ${ hours }
|
|
21
|
+
let fancy_str = `${ year }-${ month }-${ day } at ${ hours }h${ mins }m${ secs }s${ msecs }ms UTC`;
|
|
22
22
|
return fancy_str;
|
|
23
23
|
}; // Ends files.readable_date()
|
|
24
24
|
|
|
@@ -31,7 +31,7 @@ files.make_artifacts_folder = function (folder_name) {
|
|
|
31
31
|
if (folder_name) {
|
|
32
32
|
folder_name = safe_filename( folder_name );
|
|
33
33
|
} else {
|
|
34
|
-
folder_name = `
|
|
34
|
+
folder_name = `alkiln-${ files.readable_date() }`
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
fs.mkdirSync( folder_name );
|
|
@@ -67,13 +67,15 @@ session_vars.get_branch_name = function () {
|
|
|
67
67
|
return branch_name;
|
|
68
68
|
};
|
|
69
69
|
|
|
70
|
-
session_vars.
|
|
70
|
+
session_vars.get_package_name = function () {
|
|
71
71
|
/* Make an un-incremented project name based on the repo name and branch name. */
|
|
72
72
|
let repo_url_without_trailing_slash = session_vars.get_repo_url().replace(/\/$/, '');
|
|
73
73
|
let repo_name_parts = repo_url_without_trailing_slash.split('/');
|
|
74
|
-
|
|
74
|
+
return repo_name_parts[ repo_name_parts.length - 1 ];
|
|
75
|
+
};
|
|
75
76
|
|
|
76
|
-
|
|
77
|
+
session_vars.get_project_base_name = function () {
|
|
78
|
+
let name = `testing${ session_vars.get_package_name() }${ session_vars.get_branch_name() }`;
|
|
77
79
|
let sanitized_name = name.replace( /[^A-Za-z0-9]/g, '' );
|
|
78
80
|
return sanitized_name;
|
|
79
81
|
};
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@suffolklitlab/alkiln",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.10.1",
|
|
4
4
|
"description": "Integrated automated end-to-end testing with docassemble, puppeteer, and cucumber.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "npm run unit && npm run langs_setup && npm run cucumber -- $@",
|
|
8
8
|
"cucumber_base": "run_cucumber(){ ./node_modules/.bin/cucumber-js \"$@\"; status=$?; ./lib/utils/clean_reports.js; return $status; }; run_cucumber",
|
|
9
|
-
"cucumber": "run_base(){ npm run cucumber_base -- \"$@\"
|
|
9
|
+
"cucumber": "run_base(){ npm run cucumber_base -- \"$@\" docassemble/*/data/sources/*.feature --retry 1; }; run_base",
|
|
10
10
|
"cucumber_external": "run_cucumber(){ tmp_path=`pwd`; ( new_path=\"$1\"; shift; cd \"$new_path\"; npm run --prefix \"${tmp_path}\" cucumber_base -- \"$@\" \"$new_path\"/docassemble/*/data/sources/*.feature;) }; run_cucumber",
|
|
11
|
-
"langs": "npm run langs_setup && ./node_modules/.bin/cucumber-js --require ./lib/index.js
|
|
12
|
-
"langs_setup": "./lib/utils/langs.js '
|
|
11
|
+
"langs": "npm run langs_setup && ./node_modules/.bin/cucumber-js --require ./lib/index.js docassemble/*/data/sources/*_lang*.feature",
|
|
12
|
+
"langs_setup": "./lib/utils/langs.js 'docassemble/*/data/sources/*.feature'",
|
|
13
13
|
"langs_local": "npm run langs_setup && npm run local",
|
|
14
14
|
"local": "npm run setup && npm run cucumber; npm run takedown",
|
|
15
15
|
"setup": "./lib/docassemble/setup.js",
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
"chai": "4.2.0",
|
|
43
43
|
"cheerio": "1.0.0-rc.10",
|
|
44
44
|
"dotenv": "8.2.0",
|
|
45
|
+
"deep-equal-in-any-order": "^2.0.0",
|
|
45
46
|
"mocha": "9.2.0",
|
|
46
47
|
"puppeteer": "13.1.3",
|
|
47
48
|
"qs": "6.10.2",
|