@suffolklitlab/alkiln 4.3.1 → 4.4.0

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/CHANGELOG.md CHANGED
@@ -40,6 +40,14 @@ Format:
40
40
  -->
41
41
  <!-- ## [Unreleased] -->
42
42
 
43
+ ## [4.4.0] - 2022-05-23
44
+ ### Added
45
+ - Appends the results of the cucumber [summary formatter](https://github.com/cucumber/cucumber-js/blob/main/docs/formatters.md#summary) to the `debug_log.txt`, which includes useful stack traces into the Kiln code when tests fail.
46
+
47
+ ### Fixed
48
+ - Prevent login info from being saved in the report or screenshots being taken on error. [#599](https://github.com/SuffolkLITLab/ALKiln/issues/559).
49
+ - Prevent error screenshots of screens that used a secret.
50
+
43
51
  ## [4.3.0] - 2022-04-07
44
52
  ### Added
45
53
  - GitHub environment variable `MAX_SECONDS_FOR_SETUP` to set a custom maximum time for setup and takedown for packages that take a long time to load.
package/action.yml CHANGED
@@ -86,6 +86,13 @@ runs:
86
86
  "@suffolklitlab/alkiln": "$ALKILN_VERSION"
87
87
  }
88
88
  }
89
+ EOF
90
+ # Keep in sync with the cucumber.js in root
91
+ cat << EOF > "cucumber.js"
92
+ module.exports = {
93
+ default: "--require ./lib/index.js --format progress --format summary:cucumber-report.txt"
94
+ }
95
+ EOF
89
96
  shell: bash
90
97
 
91
98
  # Install node
package/cucumber.js ADDED
@@ -0,0 +1,3 @@
1
+ module.exports = {
2
+ default: "--require ./lib/index.js --format progress --format summary:cucumber-report.txt"
3
+ }
package/lib/scope.js CHANGED
@@ -276,9 +276,15 @@ module.exports = {
276
276
  if ( options.waitForShowIf ) { await scope.waitForShowIf( scope ); }
277
277
  } // ends if scope.page
278
278
 
279
- // Reset navigation (TODO: discuss use for observational steps)
280
- if ( options.navigated ) { scope.navigated = true; } // Consider `daPageLoad` event
281
- else { scope.navigated = false; }
279
+ if ( options.navigated ) {
280
+ // Reset navigation (TODO: discuss use for observational steps)
281
+ // TODO: Consider `daPageLoad` event
282
+ scope.navigated = true;
283
+ // Allow screenshots of the next page (may have been disabled in order to hide secret values)
284
+ scope.disable_error_screenshot = false;
285
+ } else {
286
+ scope.navigated = false;
287
+ }
282
288
 
283
289
  // Plain old waiting. Here to avoid doing this in each individual place
284
290
  if ( options.waitForTimeout ) { await time.waitForTimeout( options.waitForTimeout ); }
@@ -1836,6 +1842,8 @@ module.exports = {
1836
1842
 
1837
1843
  set_secret_var: async ( scope, var_name, set_to_env_name ) => {
1838
1844
  /** Sets a non-story table variable to a "secret" value (i.e. an env var) */
1845
+ // Prevent pictures of a screen with a secret.
1846
+ scope.disable_error_screenshot = true;
1839
1847
  let var_data = await scope.normalizeTable( scope, {
1840
1848
  var_data: [{
1841
1849
  var: var_name,
@@ -1963,6 +1971,9 @@ module.exports = {
1963
1971
  /** Allow the developer to log a user into their server using GitHub
1964
1972
  * secrets to authenticate.
1965
1973
  */
1974
+ // Don't take a picture of a failed login in case one of the inputs is correct
1975
+ scope.disable_error_screenshot = true;
1976
+
1966
1977
  // If there is no browser open, start a new one
1967
1978
  if (!scope.browser) {
1968
1979
  scope.browser = await scope.driver.launch({ headless: !session_vars.DEBUG });
@@ -2003,8 +2014,10 @@ module.exports = {
2003
2014
 
2004
2015
  await scope.addToReport( scope, {
2005
2016
  type: `row`,
2006
- value: `Logged into ${ session_vars.get_da_server_url() }/user/sign-in as a ${ email } with ${ password }.`
2017
+ value: `Signed into ${ session_vars.get_da_server_url() }/user/sign-in successfully.`
2007
2018
  });
2019
+
2020
+ await scope.afterStep(scope, {waitForShowIf: false});
2008
2021
  }, // Ends sign_in
2009
2022
 
2010
2023
  }, // ends scope.steps
package/lib/steps.js CHANGED
@@ -83,6 +83,7 @@ Before(async (scenario) => {
83
83
  // Device interaction
84
84
  scope.device = 'pc';
85
85
  scope.activate = click_with[ scope.device ];
86
+ scope.disable_error_screenshot = false;
86
87
 
87
88
  scope.page_id = null;
88
89
 
@@ -882,11 +883,19 @@ After(async function(scenario) {
882
883
 
883
884
  await scope.addToReport(scope, { type: `outcome`, value: `**-- Scenario Failed --**` });
884
885
  if ( scope.page ) {
885
- // Save/download a picture of the screen that's showing during the unexpected status
886
- let safe_filename = await scope.getSafeScenarioFilename( scope, { prefix: `error` });
887
- await scope.page.screenshot({ path: `${ safe_filename }.jpg`, type: `jpeg`, fullPage: true });
888
- }
889
- } // Ends if not passed
886
+ if ( scope.disable_error_screenshot ) {
887
+ scope.addToReport(scope, {
888
+ type: `row`,
889
+ value: `For security, ALKiln will not create a screenshot for this error. It's possible a secret is being used on this screen.`
890
+ });
891
+ } else {
892
+ // Save/download a picture of the screen that's showing during the unexpected status
893
+ let safe_filename = await scope.getSafeScenarioFilename( scope, { prefix: `error` });
894
+ await scope.page.screenshot({ path: `${ safe_filename }.jpg`, type: `jpeg`, fullPage: true });
895
+ } // ends if scope.disable_error_screenshot
896
+ } // ends if scope.page exists
897
+
898
+ } // ends if not passed
890
899
 
891
900
  if (scenario.result.status === `FAILED`) {
892
901
  await scope.addToReport(scope, { type: `outcome`, value: `**-- Scenario Failed --**` });
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+
5
+ // This is hardcoded information from `cucumber.js`. Once we move to cucumber 8, we should
6
+ // change that the cucumber.json and actually parse the info from it.
7
+ let summary_file_name = 'cucumber-report.txt';
8
+ fs.readFile(summary_file_name, 'utf8', (err, data) => {
9
+ if (err) {
10
+ console.error(err);
11
+ return;
12
+ }
13
+ // Replace terminal color codes, if present
14
+ // https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797#colors--graphics-mode
15
+ data = data.replace(/\x1b\[[0-9][0-9]?[0-9]?m/g, '');
16
+ const debug_log_file = 'debug_log.txt';
17
+ fs.appendFile(debug_log_file, data, err => {
18
+ if (err) {
19
+ console.error(err);
20
+ return;
21
+ }
22
+ });
23
+ });
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@suffolklitlab/alkiln",
3
- "version": "4.3.1",
3
+ "version": "4.4.0",
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
- "cucumber_base": "./node_modules/.bin/cucumber-js --require ./lib/index.js",
9
- "cucumber": "run_cucumber(){ npm run cucumber_base -- \"$@\" tests/features/*.feature; }; run_cucumber",
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 -- \"$@\" tests/features/*.feature; }; run_base",
10
10
  "langs": "npm run langs_setup && ./node_modules/.bin/cucumber-js --require ./lib/index.js tests/features/*_lang*.feature",
11
11
  "langs_setup": "./lib/utils/langs.js 'tests/features/*.feature'",
12
12
  "langs_local": "npm run langs_setup && npm run local",
@@ -346,7 +346,7 @@ Scenario: I can't match JSON page var to str
346
346
  """
347
347
 
348
348
  @fast @rf22 @signin
349
- Scenario: Fail with wrong email secret
349
+ Scenario: Fail with wrong email secret name
350
350
  Given the final Scenario status should be "failed"
351
351
  Given the Scenario report should include:
352
352
  """
@@ -355,7 +355,7 @@ Scenario: Fail with wrong email secret
355
355
    Given I log on with the email "WRONG_EMAIL_NAME" and the password "USER1_PASSWORD"
356
356
 
357
357
  @fast @rf23 @signin
358
- Scenario: Fail with wrong password secret
358
+ Scenario: Fail with wrong password secret name
359
359
  Given the final Scenario status should be "failed"
360
360
  Given the Scenario report should include:
361
361
  """
@@ -364,7 +364,7 @@ Scenario: Fail with wrong password secret
364
364
    Given I sign in with the email "USER1_EMAIL" and the password "WRONG_PASSWORD_NAME"
365
365
 
366
366
  @fast @rf24 @signin
367
- Scenario: Fail with 2 wrong signin secrets
367
+ Scenario: Fail with 2 wrong signin secret names
368
368
  Given the final Scenario status should be "failed"
369
369
  Given the Scenario report should include:
370
370
  """
@@ -393,6 +393,10 @@ Scenario: Fail to find var while keeping value secret
393
393
  """
394
394
  Did not find a field on this page for the variable "missing_var" that could be set to "SECRET_FOR_MISSING_FIELD"
395
395
  """
396
+ And the Scenario report should include:
397
+ """
398
+ For security, ALKiln will not create a screenshot for this error.
399
+ """
396
400
  And I start the interview at "test_secret_vars"
397
401
  And I set the var "missing_var" to the secret "SECRET_FOR_MISSING_FIELD"
398
402
 
@@ -518,3 +522,11 @@ Scenario: Report lists unused table rows
518
522
  | button_continue | True | |
519
523
  | buttons_other | button_2 | |
520
524
  | buttons_yesnomaybe | True | |
525
+
526
+ @fast @rp3 @signin
527
+ Scenario: Sign in to server successfully
528
+ Given the Scenario report should include:
529
+ """
530
+ Signed in
531
+ """
532
+   Given I sign in with the email "USER1_EMAIL" and the password "USER1_PASSWORD"