@suffolklitlab/alkiln 4.1.0 → 4.1.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.
|
@@ -31,6 +31,9 @@ jobs:
|
|
|
31
31
|
REPO_URL: https://github.com/plocket/docassemble-ALAutomatedTestingTests
|
|
32
32
|
USER1_EMAIL: ${{ secrets.USER1_EMAIL }}
|
|
33
33
|
USER1_PASSWORD: ${{ secrets.USER1_PASSWORD }}
|
|
34
|
+
SECRET_VAR1: secret-var1-value
|
|
35
|
+
SECRET_VAR2: secret-var2-value
|
|
36
|
+
SECRET_FOR_MISSING_FIELD: secret for missing field
|
|
34
37
|
|
|
35
38
|
name: Run Puppeteer tests
|
|
36
39
|
steps:
|
package/CHANGELOG.md
CHANGED
|
@@ -39,7 +39,7 @@ Format:
|
|
|
39
39
|
-
|
|
40
40
|
-->
|
|
41
41
|
<!-- ## [Unreleased] -->
|
|
42
|
-
## [4.1.
|
|
42
|
+
## [4.1.1] - 2022-04-01
|
|
43
43
|
### Added
|
|
44
44
|
- Step to set vars to secret variables. That is, using environment variables while hiding the names of those variables in the report, errors, and console logs.
|
|
45
45
|
|
package/lib/scope.js
CHANGED
|
@@ -22,6 +22,30 @@ let escape_regex = function( to_escape ) {
|
|
|
22
22
|
return to_escape.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
+
let get_original_row = function (row) {
|
|
26
|
+
/* `row` might be a row, a source row, or an original row. */
|
|
27
|
+
|
|
28
|
+
// Until we flatten row data a litte, we need to find the `orignal` row, which has the flags
|
|
29
|
+
let source_row = row.source || row;
|
|
30
|
+
let original = source_row.original || source_row;
|
|
31
|
+
return original;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
let printable_var_value = function(row) {
|
|
35
|
+
/* `row` might be a row, a source row, or an original row. */
|
|
36
|
+
let original = get_original_row(row);
|
|
37
|
+
if ( is_secret_var(original) ) {
|
|
38
|
+
return original.flags.secret_name;
|
|
39
|
+
}
|
|
40
|
+
return row.value;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
let is_secret_var = function(row) {
|
|
44
|
+
/* `row` might be a row, a source row, or an original row. */
|
|
45
|
+
let original = get_original_row(row);
|
|
46
|
+
return original.flags !== undefined && original.flags.secret_name !== undefined;
|
|
47
|
+
}
|
|
48
|
+
|
|
25
49
|
let proxies_regex = /(\bx\.)|(\bx\[)|(\[[ijklmn]\])/g;
|
|
26
50
|
|
|
27
51
|
module.exports = {
|
|
@@ -467,19 +491,29 @@ module.exports = {
|
|
|
467
491
|
|
|
468
492
|
normalizeTable: async function ( scope, { var_data, from_story_table=true }) {
|
|
469
493
|
/* Return data derived from cucumber variable-setting data.
|
|
470
|
-
|
|
494
|
+
* Table must have headers. Arrays are not supported. */
|
|
471
495
|
|
|
472
496
|
// Support tables with no 'trigger' column
|
|
473
497
|
let supported_table = [];
|
|
474
498
|
for ( let row of var_data ) {
|
|
475
499
|
// See tests > unit_tests > tables.fixtures.js > tables.old_to_current_formatting
|
|
500
|
+
let actual_var_value = row.value;
|
|
501
|
+
if (is_secret_var(row)) {
|
|
502
|
+
actual_var_value = process.env[row.flags.secret_name];
|
|
503
|
+
if ( actual_var_value === undefined ) {
|
|
504
|
+
let not_in_env_msg = `The GitHub SECRET "${ row.flags.secret_name }" doesn't exist. Check for a typo and check your workflow file.`;
|
|
505
|
+
await scope.addToReport( scope, { type: `error`, value: not_in_env_msg })
|
|
506
|
+
throw ReferenceError(`Could not find "${row.flags.secret_name }": ${not_in_env_msg}.`)
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
476
510
|
let result = {
|
|
477
511
|
original: row,
|
|
478
512
|
// Give fake data if needed to prevent some kind of hidden input field from being found
|
|
479
513
|
// See bug at https://github.com/plocket/docassemble-cucumber/issues/79
|
|
480
514
|
// May be able to remove this once converted to `getAllFields`
|
|
481
515
|
var: row.var || 'al_no_var_name',
|
|
482
|
-
value:
|
|
516
|
+
value: actual_var_value,
|
|
483
517
|
trigger: row.trigger || '',
|
|
484
518
|
times_used: 0,
|
|
485
519
|
}
|
|
@@ -487,7 +521,9 @@ module.exports = {
|
|
|
487
521
|
supported_table.push( result );
|
|
488
522
|
}
|
|
489
523
|
|
|
490
|
-
if ( session_vars.get_debug() ) {
|
|
524
|
+
if ( session_vars.get_debug() ) {
|
|
525
|
+
console.log( 'scope.normalizedTable():\n', JSON.stringify( supported_table ));
|
|
526
|
+
}
|
|
491
527
|
|
|
492
528
|
return supported_table;
|
|
493
529
|
}, // Ends scope.normalizeTable()
|
|
@@ -1506,9 +1542,10 @@ module.exports = {
|
|
|
1506
1542
|
if ( row.times_used === 0 ) {
|
|
1507
1543
|
num_unused_rows += 1;
|
|
1508
1544
|
let source_row = row;
|
|
1545
|
+
// TODO: Make the row object flatter so we don't need to dig in this way
|
|
1509
1546
|
if ( row.source ) { source_row = row.source; }
|
|
1510
1547
|
let original_row = source_row.original;
|
|
1511
|
-
let msg = `Did not find a field on this page for the variable
|
|
1548
|
+
let msg = `Did not find a field on this page for the variable "${ original_row.var }" that could be set to "${ original_row.value }"`;
|
|
1512
1549
|
await scope.addToReport(scope, { type: `warning`, value: msg });
|
|
1513
1550
|
}
|
|
1514
1551
|
}
|
|
@@ -1610,20 +1647,24 @@ module.exports = {
|
|
|
1610
1647
|
* This may in future be used to normalize all values that need `True`/`False`
|
|
1611
1648
|
* normalization.
|
|
1612
1649
|
*/
|
|
1613
|
-
let value = row.value;
|
|
1650
|
+
let value = row.value.toLowerCase();
|
|
1651
|
+
let val_to_print = printable_var_value(row);
|
|
1614
1652
|
let int_val = parseInt( value );
|
|
1615
1653
|
|
|
1616
1654
|
// Step stuff. Take into account a lot of possible values
|
|
1617
1655
|
if ( value.match( /(false|no|unchecked|uncheck|deselected|deselect)/i )) {
|
|
1656
|
+
// Should this also contain a warning if this is trying to set `target_number`?
|
|
1618
1657
|
return `False`;
|
|
1619
1658
|
|
|
1620
1659
|
} else if ( value.match( /(true|yes|checked|check|selected|select)/i )) {
|
|
1621
1660
|
if ( from_story_table ) {
|
|
1622
|
-
// Just in case, but this should never happen.
|
|
1623
1661
|
if ( row.var.match( /\.there_is_another$/ ) ) {
|
|
1662
|
+
// `.there_is_another` should never get in here, but just in case
|
|
1624
1663
|
await scope.addToReport( scope, { type: `warning`, value: `The attribute \`.there_is_another\` is invalid in story table tests. Replace it with \`.target_number\` in your \`var\` column. Set the \`value\` to the number of items in that list. This test will now set this row's \`value\` to \`False\`. See https://suffolklitlab.github.io/docassemble-AssemblyLine-documentation/docs/automated_integrated_testing#there_is_another-loop. The row data is\n${ JSON.stringify( row.original )}` });
|
|
1625
1664
|
} else {
|
|
1626
|
-
|
|
1665
|
+
// If `target_number` is set to True instead of a number
|
|
1666
|
+
// Since secret vars can't be passed in a table, this should never be a secret var
|
|
1667
|
+
await scope.addToReport( scope, { type: `warning`, value: `${ val_to_print } value is not a valid value for ${ row.var } here. This test will default to \`False\` to avoid problems.` });
|
|
1627
1668
|
}
|
|
1628
1669
|
return `False`;
|
|
1629
1670
|
} else { return `True`; }
|
|
@@ -1638,7 +1679,8 @@ module.exports = {
|
|
|
1638
1679
|
return `False`;
|
|
1639
1680
|
|
|
1640
1681
|
} else if ( isNaN( parseInt( value )) ) { // Loop will end
|
|
1641
|
-
|
|
1682
|
+
// I can't figure out how to trigger this warning either
|
|
1683
|
+
await scope.addToReport( scope, { type: `warning`, value: `${ val_to_print } value is not a valid value for ${ row.var } here. This test will default to \`False\` to avoid problems.` });
|
|
1642
1684
|
return `False`;
|
|
1643
1685
|
|
|
1644
1686
|
} else { // It's a number. Loop will continue.
|
|
@@ -1792,6 +1834,21 @@ module.exports = {
|
|
|
1792
1834
|
await scope.setFields( scope, { var_data, ensure_navigation: false, ensure_all_vars_used: true });
|
|
1793
1835
|
}, // Ends set_regular_var()
|
|
1794
1836
|
|
|
1837
|
+
set_secret_var: async ( scope, var_name, set_to_env_name ) => {
|
|
1838
|
+
/** Sets a non-story table variable to a "secret" value (i.e. an env var) */
|
|
1839
|
+
let var_data = await scope.normalizeTable( scope, {
|
|
1840
|
+
var_data: [{
|
|
1841
|
+
var: var_name,
|
|
1842
|
+
value: set_to_env_name,
|
|
1843
|
+
trigger: scope.trigger_not_needed_flag,
|
|
1844
|
+
flags: {secret_name: set_to_env_name}
|
|
1845
|
+
}],
|
|
1846
|
+
});
|
|
1847
|
+
// Don't continue if the variable doesn't cause navigation itself. Also,
|
|
1848
|
+
// if this variable cannot be set on this page, trigger an error
|
|
1849
|
+
await scope.setFields( scope, { var_data, ensure_navigation: false, ensure_all_vars_used: true });
|
|
1850
|
+
},
|
|
1851
|
+
|
|
1795
1852
|
tap_term: async ( scope, phrase ) => {
|
|
1796
1853
|
/** Tap a link that doesn't navigate. Depends on the language of the text. */
|
|
1797
1854
|
const [link] = await scope.page.$x(`//a[contains(text(), "${phrase}")]`);
|
package/lib/steps.js
CHANGED
|
@@ -14,13 +14,11 @@ const wrapPromiseWithTimeout = require('./cucumber_8_shim');
|
|
|
14
14
|
const fs = require('fs');
|
|
15
15
|
const path = require('path');
|
|
16
16
|
const { expect } = require('chai');
|
|
17
|
-
const puppeteer = require('puppeteer');
|
|
18
17
|
const { v4: uuidv4 } = require('uuid');
|
|
19
18
|
|
|
20
19
|
// Ours
|
|
21
20
|
const scope = require('./scope');
|
|
22
21
|
const session_vars = require('./utils/session_vars');
|
|
23
|
-
|
|
24
22
|
/* Of Note:
|
|
25
23
|
- We're using `*=` because sometimes da text has funny characters in it that are hard to anticipate
|
|
26
24
|
*/
|
|
@@ -735,6 +733,15 @@ When(/I set the var(?:iable)? "([^"]+)" to "([^"]+)"/, { timeout: -1 }, async (
|
|
|
735
733
|
);
|
|
736
734
|
});
|
|
737
735
|
|
|
736
|
+
When(/I set the var(?:iable)? "([^"]+)" to ?(?:the)? ?(?:GitHub)? secret "([^"]+)"/i, { timeout: -1 }, async ( var_name, set_to_env_name ) => {
|
|
737
|
+
/* Set a non-story table variable to a secrete value. Same as the above, but reads the value from `process.env` */
|
|
738
|
+
return wrapPromiseWithTimeout(
|
|
739
|
+
scope.steps.set_secret_var( scope, var_name, set_to_env_name ),
|
|
740
|
+
scope.timeout
|
|
741
|
+
);
|
|
742
|
+
});
|
|
743
|
+
|
|
744
|
+
|
|
738
745
|
Then(/I upload "([^"]+)" to "([^"]+)"/, { timeout: -1 }, async ( filenames, var_name ) => {
|
|
739
746
|
/* Uploads file (docx, jpg, etc) in same folder to input var. Can actually use
|
|
740
747
|
* 'I set the var "" to ""', but this is more explicit if it's desired. */
|
package/package.json
CHANGED
|
@@ -83,3 +83,21 @@ Scenario: I set text-type values
|
|
|
83
83
|
And I tap to continue
|
|
84
84
|
# Next page
|
|
85
85
|
Then the question id should be "the end"
|
|
86
|
+
|
|
87
|
+
@fast @i2 @secret
|
|
88
|
+
Scenario: handles settings from Github secrets
|
|
89
|
+
Given the final Scenario status should be "failed"
|
|
90
|
+
And the Scenario report should include:
|
|
91
|
+
"""
|
|
92
|
+
The GitHub SECRET "SECRET_NOT_THERE" doesn't exist
|
|
93
|
+
"""
|
|
94
|
+
Given I start the interview at "test_secret_vars"
|
|
95
|
+
When I set the var "first_text_entry" to the secret "SECRET_VAR1"
|
|
96
|
+
And I tap to continue
|
|
97
|
+
Then I see the phrase "secret-var1-value"
|
|
98
|
+
When I tap to continue
|
|
99
|
+
And I set the var "second_text_entry" to the github secret "SECRET_VAR2"
|
|
100
|
+
And I tap to continue
|
|
101
|
+
Then I see the phrase "secret-var2-value"
|
|
102
|
+
When I tap to continue
|
|
103
|
+
And I set the variable "third_text_entry" to secret "SECRET_NOT_THERE"
|
|
@@ -386,6 +386,17 @@ Scenario: Fail with could not find files
|
|
|
386
386
|
Given I start the interview at "all_tests"
|
|
387
387
|
And I upload "nonexistant1.pdf, nonexistant2.pdf" to "upload_files_visible"
|
|
388
388
|
|
|
389
|
+
@fast @rf26 @secret @error
|
|
390
|
+
Scenario: Fail to find var while keeping value secret
|
|
391
|
+
Given the final Scenario status should be "failed"
|
|
392
|
+
Given the Scenario report should include:
|
|
393
|
+
"""
|
|
394
|
+
Did not find a field on this page for the variable "missing_var" that could be set to "SECRET_FOR_MISSING_FIELD"
|
|
395
|
+
"""
|
|
396
|
+
And I start the interview at "test_secret_vars"
|
|
397
|
+
And I set the var "missing_var" to the secret "SECRET_FOR_MISSING_FIELD"
|
|
398
|
+
|
|
399
|
+
|
|
389
400
|
# scope.js
|
|
390
401
|
# I upload "___" to "___"
|
|
391
402
|
# No need to test wrong var name
|
|
@@ -409,6 +420,7 @@ Scenario: Warn when there are too many names
|
|
|
409
420
|
And I set the name of "users[0]" to "Uli Udo User Sampson Jr"
|
|
410
421
|
And I tap to continue
|
|
411
422
|
|
|
423
|
+
|
|
412
424
|
# ===============================
|
|
413
425
|
# Reports for "passed" Scenarios
|
|
414
426
|
# ===============================
|