@suffolklitlab/alkiln 4.11.3 → 4.11.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.
@@ -44,8 +44,8 @@ jobs:
44
44
  - name: Set name of artifact folder with date and UTC time
45
45
  # https://www.shell-tips.com/linux/how-to-format-date-and-time-in-linux-macos-and-bash/#how-to-format-a-date-in-bash
46
46
  run: |
47
- echo "ARTIFACT_NAME=alkiln-$(date +'%Y-%m-%d at %Hh%Mm%Ss' -u) UTC" >> $GITHUB_ENV
48
- echo "UNIT_TESTS_ARTIFACT_NAME=_alkiln-misc-$(date +'%Y-%m-%d at %Hh%Mm%Ss' -u) UTC" >> $GITHUB_ENV
47
+ echo "ARTIFACT_NAME=alkiln-$(date +'%Y-%m-%d at %Hh%Mm%Ss' -u)UTC" >> $GITHUB_ENV
48
+ echo "UNIT_TESTS_ARTIFACT_NAME=_alkiln-misc-$(date +'%Y-%m-%d at %Hh%Mm%Ss' -u)UTC" >> $GITHUB_ENV
49
49
  - name: Set languages
50
50
  run: echo "EXTRA_LANGUAGES=${{ github.event.inputs.extra_languages }}" >> $GITHUB_ENV
51
51
  if: ${{ github.event.inputs.extra_languages != '' }}
package/CHANGELOG.md CHANGED
@@ -40,6 +40,10 @@ Format:
40
40
  -->
41
41
  <!-- ## [Unreleased] -->
42
42
 
43
+ ## [4.11.4] - 2023-04-19
44
+ ### Fixed
45
+ - Shorten path names to try to accommodate limitations of windows systems while still keeping enough useful information to help devs identify the test outputs. https://github.com/SuffolkLITLab/ALKiln/issues/618
46
+
43
47
  ## [4.11.3] - 2023-04-06
44
48
  ### Changed
45
49
  - Project name prefix now includes ALKiln in it for clarity
package/action.yml CHANGED
@@ -43,7 +43,7 @@ runs:
43
43
  # Human-readable date/time:
44
44
  # https://www.shell-tips.com/linux/how-to-format-date-and-time-in-linux-macos-and-bash/#how-to-format-a-date-in-bash
45
45
  run: |
46
- echo "ARTIFACT_NAME=alkiln-$(date +'%Y-%m-%d at %Hh%Mm%Ss' -u) UTC" >> $GITHUB_ENV
46
+ echo "ARTIFACT_NAME=alkiln-$(date +'%Y-%m-%d at %Hh%Mm%Ss' -u)UTC" >> $GITHUB_ENV
47
47
  if ${{ github.event.inputs.extra_languages != '' }}
48
48
  then
49
49
  echo "Manually set languages: ${{ github.event.inputs.extra_languages }}"
package/lib/scope.js CHANGED
@@ -121,8 +121,7 @@ module.exports = {
121
121
  * create it. */
122
122
  if ( !scope.report ) { scope.report = new Map(); }
123
123
  if ( !scope.scenario_id ) {
124
- let date = files.readable_date();
125
- scope.scenario_id = `_report_${ date }`;
124
+ scope.scenario_id = `_report_${ Date.now() }`;
126
125
  }
127
126
  if ( !scope.report.get( scope.scenario_id )) {
128
127
  scope.report.set( scope.scenario_id, {} )
@@ -243,9 +242,9 @@ module.exports = {
243
242
  let filename = name_parts.join(`-`);
244
243
  let safe_name = safe_filename( filename, { replacement: `_` });
245
244
  // Allow room for extensions, date, etc.
246
- let safer_name = safe_name.substring(0, (255 - 45));
245
+ let short_name = `${ safe_name }`.substring(0, 70);
247
246
 
248
- return safer_name;
247
+ return short_name;
249
248
  }, // Ends scope.getSafeScenarioBaseFilename()
250
249
 
251
250
  // TODO: Does this need a name change? getSafeScenarioBasedFilename?
@@ -254,6 +253,14 @@ module.exports = {
254
253
  * a prefix the caller wants, and the base filename. We hope it can
255
254
  * contain non-english characters too. We do not offer a suffix option
256
255
  * because it may be cut off if the filename is too long.
256
+ *
257
+ * @Examples
258
+ * Return value possible formats
259
+ * prefix-id-scenario_description-timestamp
260
+ * id-scenario_description-timestamp
261
+ * scenario_description-timestamp
262
+ *
263
+ * @returns str
257
264
  */
258
265
  let name = options.prefix || '';
259
266
 
@@ -264,23 +271,22 @@ module.exports = {
264
271
 
265
272
  if ( scope.page ) {
266
273
  let { id } = await scope.examinePageID( scope, 'none to match' );
267
- name += `${ id }-`;
274
+ let short_id = `${ id }`.substring(0, 20);
275
+ name += `${ short_id }-`;
268
276
  }
269
277
 
270
278
  name += scope.base_filename;
271
- name += `-${ files.readable_date() }`;
279
+ name += `-${ Date.now() }`;
272
280
 
273
281
  let safe_name = safe_filename( name, { replacement: `_` });
274
- // Allow room for extensions, etc.
275
- let safer_name = safe_name.substring(0, (255 - 10));
276
- return safer_name;
282
+ return safe_name;
277
283
  }, // Ends scope.getSafeScenarioFilename()
278
284
 
279
285
  getJSONFilename: async function( scope ) {
280
286
  // Get a unique path for a json file
281
287
  let { id } = await scope.examinePageID( scope, 'none to match' );
282
- let date = files.readable_date();
283
- let json_path = path.join( scope.paths.scenario, `json_for-${ id }-${ date }.json` );
288
+ let short_id = `${ id }`.substring(0, 20);
289
+ let json_path = path.join( scope.paths.scenario, `json_for-${ short_id }-${ Date.now() }.json` );
284
290
  return json_path;
285
291
  },
286
292
 
@@ -840,7 +846,7 @@ module.exports = {
840
846
 
841
847
  // Error types we haven't accounted for
842
848
  } else {
843
- result.error = "Docassemble ran into an error on the page, but ALKiln does not know what the error is. If a screenshot was taken, check the screenshot";
849
+ result.error = "Docassemble ran into an error on the page, but ALKiln does not know what the error is. Check the picture of this page. If a secret variable was used, there will be no picture.";
844
850
  } // ends if error_elem !== null
845
851
  } // ends if error_id_elem
846
852
 
@@ -1890,7 +1896,10 @@ module.exports = {
1890
1896
  examinePageID: async function ( scope, question_id = '' ) {
1891
1897
  /* Looks for a sanitized version of the question id as it's written
1892
1898
  * in the .yml. docassemble's way in python:
1893
- * re.sub(r'[^A-Za-z0-9]+', '-', interview_status.question.id.lower()) */
1899
+ * re.sub(r'[^A-Za-z0-9]+', '-', interview_status.question.id.lower())
1900
+ *
1901
+ * @returns { question_has_id: bool, id: str, id_matches: bool }
1902
+ */
1894
1903
  let id_as_class = question_id.toLowerCase().replace(/[^A-Za-z0-9]+/g, '-');
1895
1904
  // `.className` is the node's list of classes as a string, separated by spaces
1896
1905
  let classes_str = await scope.page.$eval(`body`, function (elem) { return elem.className });
@@ -2225,7 +2234,7 @@ module.exports = {
2225
2234
  error = await scope.checkForError( scope );
2226
2235
  }
2227
2236
 
2228
- let timeout_err_message = `The test tried to continue to the next page, but it took longer than ${ (scope.timeout/1000)/60 } min. Check the screenshot.`
2237
+ let timeout_err_message = `The test tried to continue to the next page, but it took longer than ${ (scope.timeout/1000)/60 } min. Check the picture of this page. If a secret variable was used, there will be no picture.`
2229
2238
  if ( timedOut ) { await scope.addToReport(scope, { type: `error`, value: timeout_err_message }); }
2230
2239
  expect( timedOut, timeout_err_message ).to.be.false;
2231
2240
 
@@ -2265,13 +2274,13 @@ module.exports = {
2265
2274
  throwPageError: async function ( scope, { error_handlers = {}, id = '' }) {
2266
2275
  /* Throw a cucumber error with the error that appeared on the page. */
2267
2276
  if ( error_handlers.system_error !== undefined ) {
2268
- let sys_err_message = `The test tried to continue to the next page after ${ id }, but there was a system error. Check the screenshot.`
2277
+ let sys_err_message = `The test tried to continue to the next page after ${ id }, but there was a system error. Check the picture of this page.`
2269
2278
  await scope.addToReport(scope, { type: `error`, value: sys_err_message });
2270
2279
  expect( was_system_error, sys_err_message ).to.be.false;
2271
2280
 
2272
2281
  } else {
2273
2282
  // If it wasn't a system error, it was a user error
2274
- let user_err_message = `The test tried to continue to the next page after ${ id }, but the user got an error. Check the screenshot.`
2283
+ let user_err_message = `The test tried to continue to the next page after ${ id }, but the user got an error. Check the picture of this page.`
2275
2284
  await scope.addToReport(scope, { type: `error`, value: user_err_message });
2276
2285
  expect( true, user_err_message ).to.be.false;
2277
2286
  }
@@ -2307,18 +2316,19 @@ module.exports = {
2307
2316
  screenshot: async ( scope, name ) => {
2308
2317
  /* Download and save a screenshot. `name` does not have to be
2309
2318
  * unique as the filename will be made unique. */
2310
- name = name || '';
2311
2319
 
2312
- let date = files.readable_date();
2320
+ let timestamp = Date.now();
2313
2321
  let { id } = await scope.examinePageID( scope, 'none to match' );
2322
+ let short_id = `${ id }`.substring(0, 20);
2314
2323
  // Include the custom name if it has one
2315
- if ( name.length > 0 ) {
2316
- name = `screenshot-${ name }-on-${ id }-${ date }`;
2324
+ if ( name && name.length > 0 ) {
2325
+ let short_name = `${ name }`.substring(0, 70);
2326
+ pic_name = `pic-${ short_name }-on-${ short_id }-${ timestamp }`;
2317
2327
  } else {
2318
- name = `screenshot_on-${ id }-${ date }`;
2328
+ pic_name = `pic_on-${ short_id }-${ timestamp }`;
2319
2329
  }
2320
2330
 
2321
- await scope.take_a_screenshot( scope, { path: `./${ scope.paths.scenario }/${ name }.jpg` });
2331
+ await scope.take_a_screenshot( scope, { path: `./${ scope.paths.scenario }/${ pic_name }.jpg` });
2322
2332
 
2323
2333
  await scope.afterStep( scope );
2324
2334
  }, // Ends scope.steps.screenshot()
package/lib/steps.js CHANGED
@@ -122,7 +122,7 @@ Before(async (scenario) => {
122
122
  // Make folder for this Scenario in the all-tests artifacts folder
123
123
  scope.base_filename = await scope.getSafeScenarioBaseFilename(scope, {scenario});
124
124
  // Add a date for uniqueness in case dev has accidentally copied a Scenario description
125
- let date = files.readable_date();
125
+ let date = Date.now();
126
126
  scope.paths.scenario = `${ scope.paths.artifacts }/${ scope.base_filename }-${ date }`;
127
127
  fs.mkdirSync( scope.paths.scenario );
128
128
  // Store path name for this Scenario's individualized report
@@ -443,7 +443,7 @@ When(/I wait ?(?:for)? (\d*\.?\d+) seconds?/, { timeout: -1 }, async ( seconds )
443
443
  );
444
444
  });
445
445
 
446
- Then(/I take a screenshot ?(?:named "([^"]+)")?/, { timeout: -1 }, async ( name ) => {
446
+ Then(/I take a (?:screenshot|pic) ?(?:named "([^"]+)")?/, { timeout: -1 }, async ( name ) => {
447
447
  /* Download and save a screenshot. `name` does not have to be
448
448
  * unique as the filename will be made unique. */
449
449
  return wrapPromiseWithTimeout(
@@ -578,7 +578,7 @@ Then('I will be told an answer is invalid', async () => { // √
578
578
  expect( was_found, no_error_msg ).to.be.true;
579
579
 
580
580
  let was_user_error = error_handlers.complex_user_error !== undefined || error_handlers.simple_user_error !== undefined;
581
- let not_user_error_msg = `The error was a system error, not an error message to the user. Check the error screenshot.`;
581
+ let not_user_error_msg = `The error was a system error, not an invalid user answer. Check for the picture of the page's error if the step did not use any secret variables.`;
582
582
  if ( !was_user_error ) { await scope.addToReport(scope, { type: `error`, value: not_user_error_msg }); }
583
583
  expect( was_user_error, not_user_error_msg ).to.be.true;
584
584
 
@@ -783,8 +783,8 @@ When(/I answer randomly for at most ([0-9]+) (?:page(?:s)?|screen(?:s)?)/, { tim
783
783
  */
784
784
  // Give each screenshots folder a time-stamped name in case the dev gets clever
785
785
  // and use the same Scenario to run multiple randomized tests.
786
- let timestamp = files.readable_date();
787
- let random_input_path = `${ scope.paths.scenario }/random_answers_screenshots-${ timestamp }`
786
+ let timestamp = Date.now();
787
+ let random_input_path = `${ scope.paths.scenario }/random${ timestamp }`
788
788
  scope.paths.random_screenshots = random_input_path;
789
789
  fs.mkdirSync( scope.paths.random_screenshots );
790
790
  await scope.addToReport( scope, {
@@ -806,7 +806,7 @@ When(/I answer randomly for at most ([0-9]+) (?:page(?:s)?|screen(?:s)?)/, { tim
806
806
 
807
807
  let no_content_err = `The interview seemed to run into an error page`
808
808
  + ` after the page with the question id "${ id }".`
809
- + ` See the screenshot in "${ random_input_path }".`;
809
+ + ` See the picture of the page in "${ random_input_path }".`;
810
810
 
811
811
  let has_thrown = false;
812
812
  // Ensure no infinite loop, but each page has a full timeout to run
@@ -846,7 +846,8 @@ When(/I answer randomly for at most ([0-9]+) (?:page(?:s)?|screen(?:s)?)/, { tim
846
846
  let buttons = await scope.steps.set_random_page_vars( scope );
847
847
 
848
848
  // Take a screenshot of the page before continuing or ending
849
- let path = `${ scope.paths.random_screenshots }/random-${ Date.now() }.jpg`;
849
+ let short_id = `${ id }`.substring(0, 20);
850
+ let path = `${ scope.paths.random_screenshots }/random-${ short_id }${ Date.now() }.jpg`;
850
851
  await scope.take_a_screenshot( scope, { path: path });
851
852
 
852
853
  // Prep for the next loop to possibly stop. Signature page buttons
@@ -1116,7 +1117,7 @@ After(async function(scenario) {
1116
1117
  if ( !!scope.disable_error_screenshot ) {
1117
1118
  scope.addToReport(scope, {
1118
1119
  type: `row`,
1119
- value: `For security, ALKiln will avoid creating a screenshot for this error. It's possible a secret is being used on this screen.`
1120
+ value: `For security, ALKiln will avoid creating a picture of the page for this error. It's possible a secret is being used on this screen.`
1120
1121
  });
1121
1122
  } else {
1122
1123
 
@@ -1129,7 +1130,8 @@ After(async function(scenario) {
1129
1130
  // Save another copy in the artifact's Scenario folder
1130
1131
  let screenshot_name = `error_on`;
1131
1132
  let { id } = await scope.examinePageID( scope, 'none to match' );
1132
- screenshot_name += `-${ id }`;
1133
+ let short_id = `${ id }`.substring(0, 20);
1134
+ screenshot_name += `-${ short_id }`;
1133
1135
  let path_scenario = `${ scope.paths.scenario }/${ screenshot_name }.jpg`;
1134
1136
  await scope.take_a_screenshot( scope, { path: path_scenario });
1135
1137
 
@@ -16,9 +16,8 @@ files.readable_date = function() {
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
- let msecs = ("00" + date.getUTCMilliseconds()).slice(-3);
20
19
 
21
- let fancy_str = `${ year }-${ month }-${ day } at ${ hours }h${ mins }m${ secs }s${ msecs }ms UTC`;
20
+ let fancy_str = `${ year }-${ month }-${ day } at ${ hours }h${ mins }m${ secs }sUTC`;
22
21
  return fancy_str;
23
22
  }; // Ends files.readable_date()
24
23
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@suffolklitlab/alkiln",
3
- "version": "4.11.3",
3
+ "version": "4.11.4",
4
4
  "description": "Integrated automated end-to-end testing with docassemble, puppeteer, and cucumber.",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {
@@ -7,4 +7,7 @@ names.non_english_chars = `是汉字`;
7
7
  names.colon_input = `invalid:colon`;
8
8
  names.colon_output = `invalid_colon`;
9
9
 
10
+ names.long_input = `Longest scenario description should be 70 characters or less 0123456789`;
11
+ names.long_output = `Longest scenario description should be 70 characters or less 012345678`;
12
+
10
13
  module.exports = names;
@@ -39,6 +39,12 @@ describe(`When I use scope.getSafeScenarioBaseFilename()`, function() {
39
39
  expect( result ).to.equal( names.colon_output );
40
40
  });
41
41
 
42
+ it(`shortens a name over 70 chars`, async function() {
43
+ let scenario = mock_scenario( names.long_input );
44
+ let result = await getSafeScenarioBaseFilename( scope, { scenario });
45
+ expect( result ).to.equal( names.long_output );
46
+ });
47
+
42
48
  // language
43
49
  it(`adds a language correctly to a description`, async function() {
44
50
  scope.language = names.non_english_chars;
@@ -5,13 +5,12 @@
5
5
  const names = require('./names.fixtures.js');
6
6
  const scope = require('../../lib/scope.js');
7
7
  const getSafeScenarioFilename = scope.getSafeScenarioFilename;
8
-
9
-
8
+
10
9
  let test_filename = function ( expected_prefix, result ) {
11
10
  /* Test a name to see if it's valid output with a language defined. */
12
- let expected_name_regex_str = `^${ expected_prefix }-${ names.base_filename }-\.{32}$`;
11
+ let expected_name_regex_str = `^${ expected_prefix }-${ names.description }-\.{13}$`;
13
12
  if ( expected_prefix == `` ) {
14
- expected_name_regex_str = `^${ names.base_filename }-\.{32}$`;
13
+ expected_name_regex_str = `^${ names.description }-\.{13}$`;
15
14
  }
16
15
  let regex = new RegExp( expected_name_regex_str );
17
16
 
@@ -29,7 +28,7 @@ let test_filename = function ( expected_prefix, result ) {
29
28
  describe(`When I use scope.getSafeScenarioFilename()`, function() {
30
29
 
31
30
  beforeEach(function() {
32
- scope.base_filename = names.base_filename;
31
+ scope.base_filename = names.description;
33
32
  });
34
33
 
35
34
  it(`preserves chinese characters`, async function() {
@@ -81,6 +80,31 @@ let test_filename = function ( expected_prefix, result ) {
81
80
  let result = await getSafeScenarioFilename( scope, { prefix: names.numerical_input });
82
81
  test_filename( names.numerical_output, result );
83
82
  });
83
+
84
+ it(`handles a missing prefix`, async function() {
85
+ let result = await getSafeScenarioFilename( scope );
86
+ test_filename( ``, result );
87
+ });
88
+
89
+ it(`shortens ids over 20 chars long`, async function() {
90
+ // Necessary to set id correctly
91
+ scope.page = true;
92
+ let old_examine = scope.examinePageID;
93
+ scope.examinePageID = function () { return {id: names.long_id_input}; }
94
+ let result = await getSafeScenarioFilename( scope );
95
+ scope.examinePageID = old_examine;
96
+
97
+ let regext_str = `^${ names.long_id_output }-${ scope.base_filename }-\.*$`;
98
+ let regex = new RegExp( regext_str );
99
+
100
+ // Log more info if it failed
101
+ let found_match = regex.test( result );
102
+ if ( !found_match ) {
103
+ console.log( 'regex:', regex.source );
104
+ console.log( 'result:', result );
105
+ }
106
+ expect( found_match ).to.be.true;
107
+ });
84
108
 
85
109
  });
86
110
 
@@ -1,6 +1,6 @@
1
1
  let names = {};
2
2
 
3
- names.base_filename = `a_safe_id`;
3
+ names.description = `a_safe_scenario_description`;
4
4
 
5
5
  names.chinese_input = `是汉字`;
6
6
  names.chinese_output = `是汉字`;
@@ -32,4 +32,7 @@ names.two_consecutive_invalid_output = `two_consecutive__invalid`;
32
32
  names.numerical_input = `scenario_w1th_number00`;
33
33
  names.numerical_output = `scenario_w1th_number00`;
34
34
 
35
+ names.long_id_input = `over_20_chars_123456789`;
36
+ names.long_id_output = `over_20_chars_123456`;
37
+
35
38
  module.exports = names;