@suffolklitlab/alkiln 4.11.2 → 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.
- package/.github/workflows/test_tests.yml +2 -2
- package/CHANGELOG.md +11 -0
- package/action.yml +1 -1
- package/lib/docassemble/docassemble_api_interface.js +9 -8
- package/lib/docassemble/setup.js +1 -0
- package/lib/scope.js +32 -22
- package/lib/steps.js +11 -9
- package/lib/utils/files.js +1 -2
- package/lib/utils/session_vars.js +1 -1
- package/package.json +1 -1
- package/tests/unit_tests/getSafeScenarioBaseFilename.fixtures.js +3 -0
- package/tests/unit_tests/getSafeScenarioBaseFilename.test.js +6 -0
- package/tests/unit_tests/getSafeScenarioFilename.test.js +29 -5
- package/tests/unit_tests/names.fixtures.js +4 -1
|
@@ -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)
|
|
48
|
-
echo "UNIT_TESTS_ARTIFACT_NAME=_alkiln-misc-$(date +'%Y-%m-%d at %Hh%Mm%Ss' -u)
|
|
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,17 @@ 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
|
+
|
|
47
|
+
## [4.11.3] - 2023-04-06
|
|
48
|
+
### Changed
|
|
49
|
+
- Project name prefix now includes ALKiln in it for clarity
|
|
50
|
+
|
|
51
|
+
### Fixed
|
|
52
|
+
- Projects created in da each have a unique name. https://github.com/SuffolkLITLab/ALKiln/issues/663
|
|
53
|
+
|
|
43
54
|
## [4.11.2] - 2023-03-22
|
|
44
55
|
### Security
|
|
45
56
|
- Pass docassemble API keys through HTTP headers instead of as parameters.
|
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)
|
|
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 }}"
|
|
@@ -204,16 +204,17 @@ da_i.loop_to_create_project = async function( creation_options ) {
|
|
|
204
204
|
let wait_seconds = creation_options.wait_seconds || 5;
|
|
205
205
|
|
|
206
206
|
let project_name = null;
|
|
207
|
-
|
|
207
|
+
// Unlikely, but 2 devs could run locally and create the same Project name
|
|
208
|
+
let num_tries = 0;
|
|
208
209
|
|
|
209
210
|
// Try to create a project. If the project name is already taken, increment and loop again.
|
|
210
|
-
while (
|
|
211
|
-
|
|
211
|
+
while ( num_tries <= max_tries ) {
|
|
212
|
+
num_tries++;
|
|
212
213
|
try {
|
|
213
214
|
|
|
214
215
|
// Try next name that could be unique. Must remove all non-valid characters
|
|
215
216
|
// TODO: This sanitization is already done in session_vars, so remove it from here
|
|
216
|
-
project_name = session_vars.get_project_base_name().replace(/[^A-Za-z0-9]/g, '') +
|
|
217
|
+
project_name = session_vars.get_project_base_name().replace(/[^A-Za-z0-9]/g, '') + `${Date.now()}`;
|
|
217
218
|
log.info({ pre: `Trying to create a docassemble Project with the name ${ project_name }` });
|
|
218
219
|
let response = await _da_REST.create_project( project_name, timeout );
|
|
219
220
|
log.info({ pre: `The docassemble server is ready. Created a Project named ${ project_name }` });
|
|
@@ -226,7 +227,7 @@ da_i.loop_to_create_project = async function( creation_options ) {
|
|
|
226
227
|
|
|
227
228
|
if ( response && response.data ) {
|
|
228
229
|
if ( response.data.includes( `Invalid project` ) ) {
|
|
229
|
-
if (
|
|
230
|
+
if ( num_tries < max_tries ) {
|
|
230
231
|
// A non-unique project name. Try the next project name.
|
|
231
232
|
continue;
|
|
232
233
|
|
|
@@ -254,11 +255,11 @@ da_i.loop_to_create_project = async function( creation_options ) {
|
|
|
254
255
|
|
|
255
256
|
// If it's a timeout error, server is busy. Try again after waiting.
|
|
256
257
|
// Why are we using `max_tries` for timeout error as well?
|
|
257
|
-
if ( is_timeout_error( error ) &&
|
|
258
|
+
if ( is_timeout_error( error ) && num_tries < max_tries ) {
|
|
258
259
|
log.info({ pre: `The docassemble server was busy when we tried to `
|
|
259
|
-
+ `create the Project. Attempt ${
|
|
260
|
+
+ `create the Project. Attempt ${ num_tries } of `
|
|
260
261
|
+ `${ max_tries }. Will try again in ${ wait_seconds } seconds.` });
|
|
261
|
-
|
|
262
|
+
num_tries--; // Don't count this try
|
|
262
263
|
await time.waitForTimeout( wait_seconds * 1000 );
|
|
263
264
|
continue;
|
|
264
265
|
|
package/lib/docassemble/setup.js
CHANGED
|
@@ -25,6 +25,7 @@ const setup = async () => {
|
|
|
25
25
|
// avoids showing confusing node errors to users that they shouldn't have to fix
|
|
26
26
|
try {
|
|
27
27
|
project_name = await da_i.loop_to_create_project();
|
|
28
|
+
log.info({type: `setup`, pre: `Created a Project named ${ project_name }`});
|
|
28
29
|
} catch (error) {
|
|
29
30
|
log.error({type: `setup`, pre: `an unexpected error occurred while trying to create a docassemble project in the user's account`, data: JSON.stringify(error, null, 4)})
|
|
30
31
|
// we don't re-throw the exception, so make sure to exit with 1 to let Github Actions know the script failed
|
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
|
-
|
|
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
|
|
245
|
+
let short_name = `${ safe_name }`.substring(0, 70);
|
|
247
246
|
|
|
248
|
-
return
|
|
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
|
-
|
|
274
|
+
let short_id = `${ id }`.substring(0, 20);
|
|
275
|
+
name += `${ short_id }-`;
|
|
268
276
|
}
|
|
269
277
|
|
|
270
278
|
name += scope.base_filename;
|
|
271
|
-
name += `-${
|
|
279
|
+
name += `-${ Date.now() }`;
|
|
272
280
|
|
|
273
281
|
let safe_name = safe_filename( name, { replacement: `_` });
|
|
274
|
-
|
|
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
|
|
283
|
-
let json_path = path.join( scope.paths.scenario, `json_for-${
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
2328
|
+
pic_name = `pic_on-${ short_id }-${ timestamp }`;
|
|
2319
2329
|
}
|
|
2320
2330
|
|
|
2321
|
-
await scope.take_a_screenshot( scope, { path: `./${ scope.paths.scenario }/${
|
|
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 =
|
|
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
|
|
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 =
|
|
787
|
-
let random_input_path = `${ scope.paths.scenario }/
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
package/lib/utils/files.js
CHANGED
|
@@ -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 }
|
|
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
|
|
|
@@ -75,7 +75,7 @@ session_vars.get_package_name = function () {
|
|
|
75
75
|
};
|
|
76
76
|
|
|
77
77
|
session_vars.get_project_base_name = function () {
|
|
78
|
-
let name = `
|
|
78
|
+
let name = `ALKilnTest${ session_vars.get_package_name() }${ session_vars.get_branch_name() }`;
|
|
79
79
|
let sanitized_name = name.replace( /[^A-Za-z0-9]/g, '' );
|
|
80
80
|
return sanitized_name;
|
|
81
81
|
};
|
package/package.json
CHANGED
|
@@ -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.
|
|
11
|
+
let expected_name_regex_str = `^${ expected_prefix }-${ names.description }-\.{13}$`;
|
|
13
12
|
if ( expected_prefix == `` ) {
|
|
14
|
-
expected_name_regex_str = `^${ names.
|
|
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.
|
|
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.
|
|
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;
|