@suffolklitlab/alkiln 5.10.4 → 5.11.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.
@@ -11,7 +11,7 @@ reports.addReportHeading = function (scope, { scenario }) {
11
11
  /** Return printable heading based on Scenario name and tags.
12
12
  * Allow characters from other languages.
13
13
  */
14
- if ( session_vars.get_debug() ) { console.log(`reports.addReportHeading(): ${scenario.pickle.name} \n`); }
14
+ if ( session_vars.get_debug() ) { console.log(`šŸ”Ž ALK0175 INFO: reports.addReportHeading(): ${scenario.pickle.name} \n`); }
15
15
 
16
16
  // Collect all tag names
17
17
  let tag_names = [];
@@ -29,36 +29,48 @@ reports.addReportHeading = function (scope, { scenario }) {
29
29
  heading += `\n---------------`;
30
30
 
31
31
  reports.addToReport( scope, {
32
- type: `heading`,
32
+ code: `ALK0176`,
33
+ type: `heading info`,
33
34
  value: heading,
34
35
  });
35
36
  }; // Ends reports.addReportHeading()
36
37
 
37
- reports.addToReport = function( scope, { type, value }) {
38
+ // TODO: Maybe return line so it can be used in error messages, etc.
39
+ reports.addToReport = function( scope, { type, code, value }) {
38
40
  /** Add an item to a specific list in a scenario's report.
39
41
  * Create report if necessary.
40
42
  *
41
43
  * The report has a key for each scenario and each of those
42
- * keys should correspond to a list containing the relevant data. */
43
- if ( session_vars.get_debug() ) { console.log(`reports.addToReport():\ntype: ${ type }, value: ${ value }\n`) }
44
- let scenario = makeSureReportPartsExist( scope );
45
- scenario.lines.push({ type, value });
44
+ * keys should correspond to a list containing the relevant data.
45
+ *
46
+ * @params code {string} (Optional) Error or warning code. Default
47
+ * is unspecified error or warning.
48
+ * */
49
+ // Debugging logs
50
+ let debug_line = getDebugLine({ type, code, value });
51
+ if ( session_vars.get_debug() ) {
52
+ console.log( `Report: ${ debug_line }` );
53
+ }
46
54
 
55
+ // Ensure default file path for saving internal unit test logs
47
56
  const MISC_ARTIFACTS_DIR = `_alkiln-misc_artifacts`;
48
- // Ensure filepath for saving local unit test logs
49
57
  if ( !scope.paths ) {
50
- // TODO: would it be useful to put in existing artifacts folder if possible.
51
58
  // Can this be usefully abstracted?
52
59
  scope.paths = { debug_log: `${ MISC_ARTIFACTS_DIR }/unit_tests_logs-${ files.readable_date() }.txt` };
53
60
  }
54
61
 
55
62
  try {
56
- fs.appendFileSync(scope.paths.debug_log, `\nReport:\ntype: ${ type }, value: ${ value }`);
57
- } catch (err) {
63
+ fs.appendFileSync( scope.paths.debug_log, `\nReport:\n${debug_line}` );
64
+ } catch ( err ) {
58
65
  fs.mkdirSync( MISC_ARTIFACTS_DIR );
59
- fs.appendFileSync(scope.paths.debug_log, `\nReport:\ntype: ${ type }, value: ${ value }`);
66
+ fs.appendFileSync( scope.paths.debug_log, `\nReport:\n${debug_line}` );
67
+ // An error in here should throw (for now)
60
68
  }
61
69
 
70
+ // Report stuff
71
+ let scenario = makeSureReportPartsExist( scope );
72
+ scenario.lines.push({ type, code, value });
73
+
62
74
  return scenario;
63
75
  }; // Ends reports.addToReport()
64
76
 
@@ -125,9 +137,9 @@ reports.getPrintableReport = function( scope ) {
125
137
  else { other_reports += report; }
126
138
  }; // ends for every scenario
127
139
 
128
- if ( failed_reports !== `` ) { report += `\n\n===============================\n===============================\nFailed scenarios:\n${ failed_reports }`; }
129
- if ( other_reports !== `` ) { report += `\n\n===============================\n===============================\nScenarios that did not pass:\n${ other_reports }`; }
130
- if ( passed_reports !== `` ) { report += `\n\n===============================\n===============================\nPassed scenarios:\n${ passed_reports }`; }
140
+ if ( failed_reports !== `` ) { report += `\n\n===============================\n===============================\nšŸ¤• Failed scenarios:\n${ failed_reports }`; }
141
+ if ( other_reports !== `` ) { report += `\n\n===============================\n===============================\nšŸ”Ž Scenarios that did not pass:\n${ other_reports }`; }
142
+ if ( passed_reports !== `` ) { report += `\n\n===============================\n===============================\n🌈 Passed scenarios:\n${ passed_reports }`; }
131
143
 
132
144
  return report;
133
145
  }; // Ends reports.getPrintableReport()
@@ -137,11 +149,56 @@ reports.getPrintableScenario = function( scenario ) {
137
149
  let [ scenario_id, data ] = scenario;
138
150
  let report = ``;
139
151
  for ( let line of data.lines ) {
140
- if ( line.type === `page_id` ) { report += `screen id: `; }
141
- else if ( line.type === `outcome` ) { report += `\n`; }
142
- else if ( line.type === `warning` ) { report += `WARNING: `; }
143
- else if ( line.type === `error` ) { report += `\nERROR: ` }
144
- report += `${ line.value }\n`;
152
+ let { type, code, value } = line;
153
+ report += `${ getLineText({ type, code, value }) }\n`;
145
154
  }
146
155
  return report;
147
156
  }; // Ends reports.getPrintableScenario()
157
+
158
+ let getLineText = function ({ type=`no type`, code=`ALK0000`, value=`` }) {
159
+ let start = ``;
160
+ if ( type.includes(`page_id`) ) { start += `screen id: `; }
161
+ else if ( type.includes(`outcome`) ) { start += `\n`; } // extra new line
162
+ else if ( type.includes(`warning`) ) { start += `šŸ”Ž ${ code } WARNING: `; }
163
+ else if ( type.includes(`error`) ) { start += `\nšŸ¤• ${ code } ERROR: `; } // extra new line
164
+ return `${ start }${ value }`;
165
+ }; // Ends getLine()
166
+
167
+ let getDebugLine = function ({ type=``, code=`ALK0000`, value=`` }) {
168
+ /** In debug log lines, include all the information possible. */
169
+
170
+ // `plain` is usually used for visual clarity and shouldn't have
171
+ // codes and such associated with it. Return right away.
172
+ if ( type.includes(`plain`) ) { return value; }
173
+
174
+ let start = ``;
175
+
176
+ // Get all the relevant emoji
177
+ if ( type.includes(`debug`) ) { start += `šŸž`; }
178
+ if ( type.includes(`info`) ) { start += `šŸ’”`; }
179
+ if ( type.includes(`success`) ) { start += `🌈`; }
180
+ if ( type.includes(`warning`) ) { start += `šŸ”Ž`; }
181
+ if ( type.includes(`error`) ) { start += `šŸ¤•`; }
182
+ // Default
183
+ if ( start === `` ) { start += `?`; }
184
+
185
+ start += ` ${ code }`;
186
+
187
+ // TODO: This doesn't take care
188
+ let extra_types = type.replace(/debug|info|success|warning|error/i, ``).replace(/ +/g, ' ').trim();
189
+ if ( extra_types.length > 0 ) { start += ` ${ extra_types } `; }
190
+
191
+ // Get all the relevant descriptive text
192
+ let description_parts = [];
193
+ if ( type.includes(`debug`) ) { description_parts.push( `DEBUG` ); }
194
+ if ( type.includes(`info`) ) { description_parts.push( `INFO` ); }
195
+ if ( type.includes(`success`) ) { description_parts.push( `SUCCESS` ); }
196
+ if ( type.includes(`warning`) ) { description_parts.push( `WARNING` ); }
197
+ if ( type.includes(`error`) ) { description_parts.push( `ERROR` ); }
198
+ // Default
199
+ if ( description_parts.length <= 0 ) { description_parts.push( `UNKNOWN` ); }
200
+
201
+ start = [ start, ...description_parts ].join(` `);
202
+
203
+ return `${ start }: ${ value }`;
204
+ }; // Ends getLine()
@@ -120,7 +120,7 @@ session_vars.save_project_name = function ( project_name ) {
120
120
  // Warn local developers if file already exists
121
121
  if ( fs.existsSync( runtime_config_path ) ) {
122
122
  let old_project_name = session_vars.get_project_name();
123
- let session_project_already_exists_msg = `ALKiln WARNING: `
123
+ let session_project_already_exists_msg = `šŸ”Ž ALK0035 WARNING: `
124
124
  + `This session had a project name already: ${ old_project_name }. `
125
125
  + `A new project has now been created called ${ project_name }. `
126
126
  + `Remember to delete ${ old_project_name }`;
@@ -136,7 +136,7 @@ session_vars.save_project_name = function ( project_name ) {
136
136
  let file = fs.writeFileSync( runtime_config_path, JSON.stringify( json, null, 2 ) );
137
137
 
138
138
  if ( session_vars.get_debug() ) {
139
- console.log( `ALKiln debug: Stored name of Project "${ project_name }" locally.` );
139
+ console.log( `šŸž ALK0036 DEBUG: Stored name of Project "${ project_name }" locally.` );
140
140
  }
141
141
  return file;
142
142
  }; // Ends save_project_name()
@@ -148,7 +148,7 @@ session_vars.get_project_name = function () {
148
148
  }
149
149
  let json = JSON.parse( fs.readFileSync( runtime_config_path ));
150
150
  let project_name = json[ project_name_key ] || null;
151
- if ( session_vars.get_debug() ) { console.log( `ALKiln debug: Project name from file is "${ project_name }".` ); }
151
+ if ( session_vars.get_debug() ) { console.log( `šŸž ALK0037 DEBUG: Project name from file is "${ project_name }".` ); }
152
152
  return project_name;
153
153
  }; // Ends get_project_name()
154
154
 
@@ -158,11 +158,11 @@ session_vars.delete_project_name = function () {
158
158
  // Get the json, changing it, and re-write the file from scratch
159
159
  let json = JSON.parse( fs.readFileSync( runtime_config_path ));
160
160
  json[ project_name_key ] = ``;
161
- console.log( `ALKiln: Deleted the data that stored the name of the Project.` );
161
+ console.log( `šŸ’” ALK0038 INFO: Deleted the data that stored the name of the Project.` );
162
162
  fs.writeFileSync( runtime_config_path, JSON.stringify( json, null, 2 ) );
163
163
  return true;
164
164
  } catch ( error ) {
165
- console.warn( `ALKiln WARNING: Could not delete the Project name data. Error: ${ error }.` );
165
+ console.warn( `šŸ”Ž ALK0039 WARNING: Could not delete the Project name data. Error: ${ error }.` );
166
166
  return false;
167
167
  }
168
168
  };
@@ -226,7 +226,7 @@ session_vars.save_runtime_config_var = function ({ key, value }) {
226
226
  let file = fs.writeFileSync( runtime_config_path, JSON.stringify( json, null, 2 ) );
227
227
 
228
228
  if ( session_vars.get_debug() ) {
229
- console.log( `ALKiln debug runtime config var: Stored "${key}" locally as "${value}".` );
229
+ console.log( `šŸž ALK0040 DEBUG: Stored runtime config var "${key}" locally as "${value}".` );
230
230
  }
231
231
  return file;
232
232
  }; // Ends session_vars.save_runtime_config_var()
@@ -242,7 +242,7 @@ session_vars.get_runtime_config_var = function ( key ) {
242
242
  let json = JSON.parse( fs.readFileSync( runtime_config_path ));
243
243
  let value = json[ key ];
244
244
  if ( session_vars.get_debug() ) {
245
- console.log( `ALKiln debug runtime config var: "${key}"" is "${value}".` );
245
+ console.log( `šŸž ALK0041 DEBUG: Runtime config var "${key}"" is "${value}".` );
246
246
  }
247
247
 
248
248
  return value;
@@ -280,13 +280,6 @@ session_vars.set_sources_paths = function ( paths ) {
280
280
  }
281
281
  }
282
282
 
283
- // Warn about missing paths
284
- if ( missing_paths.length > 0 ) {
285
- console.warn(
286
- `ALKiln WARNING: ALKiln can't find folders at "${ paths.join('", "') }".`
287
- );
288
- }
289
-
290
283
  // If no paths were valid
291
284
  if ( existing_paths.length <= 0 ) {
292
285
  session_vars._sources_paths = null;
@@ -294,7 +287,7 @@ session_vars.set_sources_paths = function ( paths ) {
294
287
  }
295
288
 
296
289
  console.info(
297
- `ALKiln SUCCESS: Did find "sources" file(s) at "${ existing_paths.join('", "') }".`
290
+ `🌈 ALK0042 SUCCESS: Did find "sources" file(s) at "${ existing_paths.join('", "') }".`
298
291
  )
299
292
 
300
293
  // Otherwise, store valid paths
@@ -334,7 +327,7 @@ session_vars.validateEnvironment = function() {
334
327
 
335
328
  let origin = session_vars.get_origin();
336
329
  if ( origin !== 'github' && origin !== 'local' && origin !== 'playground' ) {
337
- errorMessage += `\nThe _ORIGIN environment variable should be set to a valid value automatically. If you see this error, file an issue at https://github.com/suffolkLITLab/docassemble-ALKilnInThePlayground. It must be defined as either 'playground', 'github', or 'local', but its value was ${origin}`;
330
+ errorMessage += `\nThe _ORIGIN environment variable should be set to a valid value automatically. If you see this error, file an issue at https://github.com/SuffolkLITLab/docassemble-ALKilnInThePlayground. It must be defined as either 'playground', 'github', or 'local', but its value was ${origin}`;
338
331
 
339
332
  // If origin has one of the allowed values, we can do the rest of the validations
340
333
  } else {
@@ -358,10 +351,10 @@ session_vars.validateEnvironment = function() {
358
351
  // We're the ones ensuring these exist for Playground runs
359
352
  if ( origin === 'playground' ) {
360
353
  if ( !session_vars.get_user_project_name() ) {
361
- errorMessage += `\nThe _PROJECT_NAME environment variable should automatically exist. If you see this error, file an issue at https://github.com/suffolkLITLab/docassemble-ALKilnInThePlayground. It is the name of the Project the developer chose to test.`
354
+ errorMessage += `\nThe _PROJECT_NAME environment variable should automatically exist. If you see this error, file an issue at https://github.com/SuffolkLITLab/docassemble-ALKilnInThePlayground. It is the name of the Project the developer chose to test.`
362
355
  }
363
356
  if ( !session_vars.get_user_id() ) {
364
- errorMessage += `\nThe _USER_ID environment variable should automatically exist. If you see this error, file an issue at https://github.com/suffolkLITLab/docassemble-ALKilnInThePlayground. It is the user ID of the developer on the server.`
357
+ errorMessage += `\nThe _USER_ID environment variable should automatically exist. If you see this error, file an issue at https://github.com/SuffolkLITLab/docassemble-ALKilnInThePlayground. It is the user ID of the developer on the server.`
365
358
  }
366
359
  // Tags are optional
367
360
  } // ends Playground env vars
@@ -371,6 +364,6 @@ session_vars.validateEnvironment = function() {
371
364
  errorMessage = errorMessage.trim();
372
365
 
373
366
  if (errorMessage !== '') {
374
- throw new ReferenceError(`ALKiln error:\n${errorMessage}`);
367
+ throw new ReferenceError(`šŸ¤• ALK0043 ERROR:\n${errorMessage}`);
375
368
  }
376
369
  };
package/package.json CHANGED
@@ -1,16 +1,17 @@
1
1
  {
2
2
  "name": "@suffolklitlab/alkiln",
3
- "version": "5.10.4",
3
+ "version": "5.11.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
- "test": "npm run unit && npm run cucumber",
7
+ "test": "npm run unit && npm run codes && npm run cucumber",
8
8
  "cucumber": "./lib/run_cucumber.js",
9
9
  "local": "npm run setup && npm run cucumber; npm run takedown",
10
10
  "setup": "./lib/docassemble/setup.js",
11
11
  "takedown": "./lib/docassemble/takedown.js",
12
12
  "server_install": "./lib/docassemble/server_install.js",
13
- "unit": "mocha tests/unit_tests/*.test.*"
13
+ "unit": "mocha tests/unit_tests/*.test.*",
14
+ "codes": "tests/log_codes/check_codes.sh ."
14
15
  },
15
16
  "repository": {
16
17
  "type": "git",
@@ -0,0 +1,138 @@
1
+ #!/bin/bash
2
+
3
+ # Identify missing and duplicate message code issues
4
+
5
+ exit_code=0
6
+
7
+ # Check if the caller sent an argument to the script
8
+ if [ $# -eq 0 ]; then
9
+ # If there was no argument, set a default value
10
+ directory="../.."
11
+ else
12
+ # If there was an argument, use it
13
+ directory="$1"
14
+ fi
15
+
16
+ # The grepped files will include the list of all the codes that have been
17
+ # removed and are no longer used. Syntax used works with GitHub cli ([[:digit:]])
18
+ # https://stackoverflow.com/a/6901221
19
+ lines=$(grep -roh --exclude="tests/log_codes/check_codes.sh" --exclude="debug_log.txt" --exclude-dir="node_modules" --exclude-dir='alkiln-*' --exclude-dir='_alkiln*' 'ALK[[:digit:]][[:digit:]][[:digit:]][[:digit:]]' "$directory")
20
+ sorted=$(echo "$lines" | sort -n)
21
+
22
+
23
+ echo "=== Missing codes ==="
24
+
25
+ # # -- Version 1 --
26
+ # # More understandable version that doesn't yet come out with a final variable
27
+ # # Keeping it here for discussion
28
+ # nums=$(echo "$sorted" | sed 's/^ALK0*//')
29
+
30
+ # missing_numbers=()
31
+ # prev_number=0
32
+ # echo "$nums" | while read -r current_number; do
33
+
34
+ # diff=$((current_number - prev_number))
35
+ # # If the difference is more than 1, print the missing
36
+ # # numbers until we catch up with the current number
37
+ # if [ $diff -gt 1 ]; then
38
+ # for ((i=prev_number+1; i<current_number; i++)); do
39
+ # printf -v missing_number "ALK%04d" $i
40
+ # missing_numbers+=("$missing_number")
41
+ # echo $missing_number
42
+ # # missing_numbers+=$(echo "%04d\n" $missing_number)
43
+ # done
44
+ # echo "---"
45
+ # fi
46
+
47
+ # prev_number=$current_number
48
+
49
+ # done
50
+
51
+ # missing_numbers_str=$(printf '%s' "${missing_numbers[@]}")
52
+ # echo "missing: $missing_numbers_str"
53
+
54
+
55
+ # -- Version 2 --
56
+ # Version that is opaque, but generates a variable to check at the end
57
+
58
+ # 0's in front of numbers confuses bash about the number format. Remove them.
59
+ just_numbers=$(echo "$sorted" | sed 's/^ALK0*//')
60
+
61
+ # Convert the list into an array
62
+ IFS=$'\n' read -rd '' -a num_array <<<"$just_numbers"
63
+ # Find the minimum and maximum numbers in the array
64
+ min_num=$(printf "%s\n" "${num_array[@]}" | sort -n | head -n 1)
65
+ max_num=$(printf "%s\n" "${num_array[@]}" | sort -n | tail -n 1)
66
+
67
+ # Generate a sequence of numbers from min to max with leading zeros
68
+ expected_sequence=""
69
+ for ((i=min_num; i<=max_num; i++)); do
70
+ # Make sure these won't look like numbers to avoid confusing bash
71
+ expected_sequence+=$(printf "ALK%04d" $i)$'\n'
72
+ done
73
+ # # Alternative code for above. seq doesn't exist everywhere. Keep this
74
+ # till we look up installing seq to avoid loop)
75
+ # expected_sequence=$(printf "ALK%04d\n" $(seq $min_num $max_num))
76
+
77
+ # Compare the expected sequence with the actual numbers
78
+ missing_numbers=$(comm -23 <(printf "%s\n" "$expected_sequence" | sort -n) <(printf "%s\n" "$sorted"))
79
+ if [ -z "$missing_numbers" ]; then
80
+ echo "None"
81
+ else
82
+ echo "$missing_numbers"
83
+ ((exit_code+=2))
84
+ fi
85
+
86
+
87
+ echo "
88
+ === Duplicate codes ==="
89
+
90
+ # We know these duplicates are ok
91
+ accepted_duplicates="ALK0000
92
+ ALK0002
93
+ ALK0003
94
+ ALK0006
95
+ ALK0007
96
+ ALK0008
97
+ ALK0009
98
+ ALK0010
99
+ ALK0011
100
+ ALK0012
101
+ ALK0018
102
+ ALK0019
103
+ ALK0023
104
+ ALK0024
105
+ ALK0026
106
+ ALK0027
107
+ ALK0028
108
+ ALK0030
109
+ ALK0049"
110
+
111
+ # Use a sorted list. `uniq` only detects consecutive duplicates
112
+ duplicates=$(echo "$sorted" | uniq -d)
113
+ unaccepted_duplicates=$(echo "$duplicates" | grep -v -f <(echo "$accepted_duplicates"))
114
+
115
+ if [ -z "$unaccepted_duplicates" ]; then
116
+ echo "None"
117
+ else
118
+ echo "$unaccepted_duplicates"
119
+ ((exit_code+=20))
120
+ fi
121
+
122
+ # === Final messages ===
123
+ echo "
124
+ Exit code meanings:
125
+ - code 2: missing codes
126
+ - code 20: duplicate codes
127
+ - code 22: both
128
+ "
129
+
130
+ if test $exit_code -eq 0; then
131
+ echo "🌈 Passed! The codes for logs are as they should be."
132
+ highest=$(echo "$sorted" | tail -n 1)
133
+ echo "The highest log code is $highest"
134
+ else
135
+ echo "šŸ¤• ERROR: Log codes are messed up. Exited with exit code $exit_code. See above for more details."
136
+ fi
137
+
138
+ exit $exit_code
@@ -0,0 +1,8 @@
1
+ [
2
+ "== Actual deleted codes ==",
3
+ "None",
4
+ "== Tests ==",
5
+ "ALK test 0059",
6
+ "ALK test 0092",
7
+ "ALK test 0225"
8
+ ]