@suffolklitlab/alkiln 5.13.2 → 5.13.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.
Files changed (39) hide show
  1. package/.github/workflows/github_server.yml +7 -7
  2. package/.github/workflows/playground.yml +1 -1
  3. package/CHANGELOG.md +32 -1
  4. package/action.yml +70 -28
  5. package/action_for_github_server/action.yml +61 -29
  6. package/docs/4_environments.md +243 -0
  7. package/docs/artifacts_folder_name.md +135 -0
  8. package/docs/constrained_random_tests.md +347 -0
  9. package/docs/decisions/006_which_log_level_to_pick_2024_09_5.md +70 -0
  10. package/docs/decisions/007_getting_and_storing_logs.md +179 -0
  11. package/docs/decisions/move_runtime_config_to_sources_folder.md +3 -0
  12. package/docs/decisions/reports_and_logs_2024_08_11.md +161 -0
  13. package/docs/kinds_of_errors.md +26 -0
  14. package/docs/prioritize_constrained_random_tests.md +101 -0
  15. package/docs/seprate_file_generation_GitHub_action.md +11 -0
  16. package/lib/docassemble/docassemble_api_interface.js +77 -51
  17. package/lib/docassemble/server_install.js +32 -9
  18. package/lib/docassemble/setup.js +40 -25
  19. package/lib/docassemble/takedown.js +33 -10
  20. package/lib/parse.js +36 -0
  21. package/lib/run_cucumber.js +115 -36
  22. package/lib/scope.js +69 -77
  23. package/lib/steps.js +70 -42
  24. package/lib/utils/Log.js +982 -0
  25. package/lib/utils/files.js +18 -11
  26. package/lib/utils/get_sources_paths.js +162 -0
  27. package/lib/utils/parse.js +1 -0
  28. package/lib/utils/proccess_command_line_args.js +267 -0
  29. package/lib/utils/reports.js +64 -17
  30. package/lib/utils/session_vars.js +34 -21
  31. package/lib/utils/time.js +44 -0
  32. package/package.json +1 -1
  33. package/tests/log_codes/check_codes.sh +2 -1
  34. package/tests/log_codes/log_code_expected_instances.txt +33 -9
  35. package/tests/unit_tests/getAllFields.test.js +5 -0
  36. package/tests/unit_tests/getMatchingRows.test.js +5 -0
  37. package/tests/unit_tests/log.test.js +581 -0
  38. package/tests/unit_tests/normalizeTable.test.js +5 -0
  39. package/lib/utils/log.js +0 -96
@@ -0,0 +1,581 @@
1
+ const chai = require('chai');
2
+ const expect = chai.expect;
3
+ const fs = require(`fs`);
4
+
5
+ const Log = require('../../lib/utils/Log.js');
6
+
7
+ const path = `_alkiln-misc_artifacts/logs_${ Date.now() }`;
8
+ const log = new Log({ path, context: `unit_tests log_tests` });
9
+ const temp_log_path = `_alkiln-log_test_path`;
10
+
11
+ /**
12
+ * Discuss: How do we test with spies? Test:
13
+ * - Debug doesn't log to the console if nothing went wrong
14
+ * - An internal error fails with a log instead of actually throwing (see
15
+ * comments in "nonexistent file" test)
16
+ * - With a non-standard level, Log uses `.log`
17
+ * - `.stdout()` (which uses process.write, so may need a different method)
18
+ *
19
+ * Discuss: (Related) Stop our logs from showing up in the console
20
+ *
21
+ * Attempt: neutralize_console/restore_console in before/after/each hides
22
+ * chai's logs. Using neutralize_console/restore_console in each `it` causes
23
+ * errors to stop chai execution. I'm also not sure that these would be safe
24
+ * in parallel.
25
+ *
26
+ * let old_log;
27
+ * let old_info;
28
+ * let old_warn;
29
+ * let old_error;
30
+ * let old_stdout;
31
+ * let old_stderr;
32
+ * */
33
+
34
+ // TODO: break out each `expect`?
35
+
36
+ /** Discuss: Save a log folder for each of the tests? I'm not sure it would be
37
+ practical to look through.*/
38
+
39
+ describe(`An instance of log`, function () {
40
+
41
+ /** Creates the right files and folders */
42
+
43
+ it(`creates a folder at the given path`, async function() {
44
+ // neutralize_console();
45
+ // throw 'foo'; // with `neutralize_console`, stops chai execution
46
+ const temp_log1 = new Log({ path: temp_log_path });
47
+ const exists = fs.existsSync( temp_log_path );
48
+ expect( exists ).to.be.true;
49
+ // Clean up by deleting the folder
50
+ fs.rmSync(temp_log_path, { recursive: true, force: true });
51
+ // restore_console();
52
+ });
53
+
54
+ it(`creates a debug file at the given path`, async function() {
55
+ const temp_log2 = new Log({ path: temp_log_path });
56
+ const exists = fs.existsSync(`${temp_log2.path}/${temp_log2.debug_log_filename}`);
57
+ expect( exists ).to.be.true;
58
+ // Clean up by deleting the folder
59
+ fs.rmSync(temp_log_path, { recursive: true, force: true });
60
+ });
61
+
62
+ it(`creates an unexpected results file on error at the given path`, async function() {
63
+ const temp_log3 = new Log({ path: temp_log_path });
64
+ try {
65
+ temp_log3.throw({ error: new Error(`Unexpected results test error`) });
66
+ } catch ( error ) {
67
+ // Do nothing, go on to test the files
68
+ }
69
+ const exists = fs.existsSync(`${ temp_log3.path }/${ temp_log3.temp_unexpected_debug_log_filename }`);
70
+ expect( exists ).to.be.true;
71
+ // Clean up by deleting the folder
72
+ fs.rmSync(temp_log_path, { recursive: true, force: true });
73
+ });
74
+
75
+ /** Returns and/or throws and/or stores the right values with the given arguments */
76
+
77
+ describe(`with an empty .debug`, function () {
78
+ it(`returns the right values`, async function() {
79
+ let returned = log.debug();
80
+ expect( returned ).to.include(`🐛 ALK000d DEBUG`);
81
+ expect( returned ).to.not.include(`Skip`);
82
+ });
83
+ it(`stores the right values in the debug file`, async function() {
84
+ expect_debug_file_to_include(`🐛 ALK000d DEBUG`);
85
+ expect_debug_file_to_not_include(`Skip`);
86
+ });
87
+ })
88
+
89
+ describe(`given totally custom metadata`, function () {
90
+ it(`.debug returns the right values`, async function() {
91
+ let options = {
92
+ before: `custom_DEBUG_before~`,
93
+ level: `custom_DEBUG_level`,
94
+ icon: `custom_DEBUG_icon`,
95
+ code: `custom_DEBUG_code`,
96
+ context: `custom_DEBUG_context`,
97
+ // do_throw: true, // This prevents returning a value
98
+ };
99
+ let returned = log.debug( options, `custom_DEBUG_log` );
100
+ // Note the intentional lack of space with `before`
101
+ expect( returned ).to.include(`custom_DEBUG_before~custom_DEBUG_icon custom_DEBUG_code custom_DEBUG_context CUSTOM_DEBUG_LEVEL`);
102
+ expect( returned ).to.include(`custom_DEBUG_log`);
103
+ expect( returned ).to.not.include(`Skip`);
104
+ });
105
+ it(`.debug stores the right text in the debug file`, async function() {
106
+ expect_debug_file_to_include(`custom_DEBUG_before~custom_DEBUG_icon custom_DEBUG_code custom_DEBUG_context CUSTOM_DEBUG_LEVEL`);
107
+ expect_debug_file_to_include(`custom_DEBUG_log`);
108
+ expect_debug_file_to_not_include(`Skip`);
109
+ });
110
+ })
111
+
112
+ describe(`given logs with multiple empty strings`, function () {
113
+ it(`.debug returns multiple spaces`, async function() {
114
+ let returned = log.debug( {}, ``, ``, ``, `` );
115
+ expect( returned ).to.include(` `);
116
+ expect( returned ).to.not.include(`Skip`);
117
+ });
118
+ it(`.debug stores the right text in the debug file`, async function() {
119
+ expect_debug_file_to_include(` `);
120
+ expect_debug_file_to_not_include(`Skip`);
121
+ });
122
+ })
123
+
124
+ describe(`with an empty ._console`, function () {
125
+ it(`returns the right values`, async function() {
126
+ let returned = log._console();
127
+ expect( returned ).to.include(`* ALK000c LOG`);
128
+ expect( returned ).to.not.include(`Skip`);
129
+ });
130
+ it(`stores the right values in the debug file`, async function() {
131
+ expect_debug_file_to_include(`* ALK000c LOG`);
132
+ expect_debug_file_to_not_include(`Skip`);
133
+ });
134
+ })
135
+
136
+ describe(`given totally custom metadata`, function () {
137
+ it(`._console returns the right values`, async function() {
138
+ let options = {
139
+ before: `custom_CONSOLE_before~`,
140
+ level: `custom_CONSOLE_level`,
141
+ icon: `custom_CONSOLE_icon`,
142
+ code: `custom_CONSOLE_code`,
143
+ context: `custom_CONSOLE_context`,
144
+ // do_throw: true, // This prevents returning a value
145
+ };
146
+ let returned = log._console( options, `custom_CONSOLE_log` );
147
+ // Note the intentional lack of space with `before`
148
+ expect( returned ).to.include(`custom_CONSOLE_before~custom_CONSOLE_icon custom_CONSOLE_code custom_CONSOLE_context CUSTOM_CONSOLE_LEVEL`);
149
+ expect( returned ).to.include(`custom_CONSOLE_log`);
150
+ expect( returned ).to.not.include(`Skip`);
151
+ });
152
+ it(`._console stores the right text in the debug file`, async function() {
153
+ expect_debug_file_to_include(`custom_CONSOLE_before~custom_CONSOLE_icon custom_CONSOLE_code custom_CONSOLE_context CUSTOM_CONSOLE_LEVEL`);
154
+ expect_debug_file_to_include(`custom_CONSOLE_log`);
155
+ expect_debug_file_to_not_include(`Skip`);
156
+ });
157
+ })
158
+
159
+ describe(`with an empty log.success`, function () {
160
+ it(`returns the right values`, async function() {
161
+ let returned = log.success();
162
+ expect( returned ).to.include(`🌈 ALK000s SUCCESS`);
163
+ expect( returned ).to.not.include(`Skip`);
164
+ });
165
+ it(`stores the right values in the debug file`, async function() {
166
+ expect_debug_file_to_include(`🌈 ALK000s SUCCESS`);
167
+ expect_debug_file_to_not_include(`Skip`);
168
+ });
169
+ })
170
+
171
+ describe(`given totally custom metadata`, function () {
172
+ it(`.success overwrites the right values`, async function() {
173
+ let options = {
174
+ before: `custom_SUCCESS_before~`,
175
+ level: `custom_SUCCESS_level`,
176
+ icon: `custom_SUCCESS_icon`,
177
+ code: `custom_SUCCESS_code`,
178
+ context: `custom_SUCCESS_context`,
179
+ do_throw: true,
180
+ };
181
+ let returned = log.success( options, `custom_SUCCESS_log` );
182
+ // Note the intentional lack of space with `before`
183
+ expect( returned ).to.include(`custom_SUCCESS_before~🌈 custom_SUCCESS_code custom_SUCCESS_context SUCCESS`);
184
+ expect( returned ).to.include(`custom_SUCCESS_log`);
185
+ expect( returned ).to.not.include(`Skip`);
186
+ });
187
+ it(`.success stores the right text in the debug file`, async function() {
188
+ expect_debug_file_to_include(`custom_SUCCESS_before~🌈 custom_SUCCESS_code custom_SUCCESS_context SUCCESS`);
189
+ expect_debug_file_to_include(`custom_SUCCESS_log`);
190
+ expect_debug_file_to_not_include(`Skip`);
191
+ });
192
+ })
193
+
194
+ describe(`with an empty log.info`, function () {
195
+ it(`returns the right values`, async function() {
196
+ let returned = log.info();
197
+ expect( returned ).to.include(`💡 ALK000i INFO`);
198
+ expect( returned ).to.not.include(`Skip`);
199
+ });
200
+ it(`stores the right values in the debug file`, async function() {
201
+ expect_debug_file_to_include(`💡 ALK000i INFO`);
202
+ expect_debug_file_to_not_include(`Skip`);
203
+ });
204
+ })
205
+
206
+ describe(`given totally custom metadata`, function () {
207
+ it(`.info overwrites the right values`, async function() {
208
+ let options = {
209
+ before: `custom_INFO_before~`,
210
+ level: `custom_INFO_level`,
211
+ icon: `custom_INFO_icon`,
212
+ code: `custom_INFO_code`,
213
+ context: `custom_INFO_context`,
214
+ do_throw: true,
215
+ };
216
+ let returned = log.info( options, `custom_INFO_log` );
217
+ // Note the intentional lack of space with `before`
218
+ expect( returned ).to.include(`custom_INFO_before~💡 custom_INFO_code custom_INFO_context INFO`);
219
+ expect( returned ).to.include(`custom_INFO_log`);
220
+ expect( returned ).to.not.include(`Skip`);
221
+ });
222
+ it(`.info stores the right text in the debug file`, async function() {
223
+ expect_debug_file_to_include(`custom_INFO_before~💡 custom_INFO_code custom_INFO_context INFO`);
224
+ expect_debug_file_to_include(`custom_INFO_log`);
225
+ expect_debug_file_to_not_include(`Skip`);
226
+ });
227
+ })
228
+
229
+ describe(`with an empty log.warn`, function () {
230
+ it(`returns the right values`, async function() {
231
+ let returned = log.warn();
232
+ expect( returned ).to.include(`🔎 ALK000w WARNING`);
233
+ expect( returned ).to.not.include(`Skip`);
234
+ });
235
+ it(`stores the right values in the debug file`, async function() {
236
+ expect_debug_file_to_include(`🔎 ALK000w WARNING`);
237
+ expect_debug_file_to_not_include(`Skip`);
238
+ });
239
+ it(`stores the right values in the unexpected output file`, async function() {
240
+ expect_unexpected_output_file_to_include(`🔎 ALK000w WARNING`);
241
+ expect_unexpected_output_file_to_not_include(`Skip`);
242
+ });
243
+ })
244
+
245
+ describe(`given totally custom metadata`, function () {
246
+ it(`.warn overwrites the right values`, async function() {
247
+ let options = {
248
+ before: `custom_WARN_before~`,
249
+ level: `custom_WARN_level`,
250
+ icon: `custom_WARN_icon`,
251
+ code: `custom_WARN_code`,
252
+ context: `custom_WARN_context`,
253
+ do_throw: true,
254
+ };
255
+ let returned = log.warn( options, `custom_WARN_log` );
256
+ // Note the intentional lack of space with `before`
257
+ expect( returned ).to.include(`custom_WARN_before~🔎 custom_WARN_code custom_WARN_context WARNING`);
258
+ expect( returned ).to.include(`custom_WARN_log`);
259
+ expect( returned ).to.not.include(`Skip`);
260
+ });
261
+ it(`.warn stores the right text in the debug file`, async function() {
262
+ expect_debug_file_to_include(`custom_WARN_before~🔎 custom_WARN_code custom_WARN_context WARNING`);
263
+ expect_debug_file_to_include(`custom_WARN_log`);
264
+ expect_debug_file_to_not_include(`Skip`);
265
+ });
266
+ it(`.warn stores the right text in the unexpected output file`, async function() {
267
+ expect_unexpected_output_file_to_include(`custom_WARN_before~🔎 custom_WARN_code custom_WARN_context WARNING`);
268
+ expect_unexpected_output_file_to_include(`custom_WARN_log`);
269
+ expect_unexpected_output_file_to_not_include(`Skip`);
270
+ });
271
+ })
272
+
273
+ describe(`with an empty log.throw`, function () {
274
+ it(`throws default error message`, async function() {
275
+ let error_to_test;
276
+ try {
277
+ log.throw();
278
+ } catch ( error ) {
279
+ error_to_test = error;
280
+ }
281
+ expect( error_to_test.message ).to.equal(`ALKiln default error`);
282
+ expect( error_to_test.stack ).to.include(`at Log.throw`);
283
+ expect( error_to_test.stack ).to.not.include(`Skip`);
284
+ });
285
+ it(`stores an error message in the debug file`, async function() {
286
+ expect_debug_file_to_include(`🤕 ALK000t ERROR`);
287
+ expect_debug_file_to_include(`ALKiln default error`);
288
+ expect_debug_file_to_include(`at Log.throw`);
289
+ expect_debug_file_to_not_include(`Skip`);
290
+ });
291
+ it(`stores an error message in the unexpected output file`, async function() {
292
+ expect_unexpected_output_file_to_include(`🤕 ALK000t ERROR`);
293
+ expect_unexpected_output_file_to_include(`ALKiln default error`);
294
+ expect_unexpected_output_file_to_include(`at Log.throw`);
295
+ expect_unexpected_output_file_to_not_include(`Skip`);
296
+ });
297
+ })
298
+
299
+ describe(`with totally custom data and string as error for .throw()`, function () {
300
+ it(`overrides some data and keeps other data`, async function() {
301
+ let error_to_test;
302
+ try {
303
+ let options = {
304
+ before: `custom_THROW_before~`,
305
+ level: `custom_THROW_level`,
306
+ icon: `custom_THROW_icon`,
307
+ code: `custom_THROW_code`,
308
+ context: `custom_THROW_context`,
309
+ error: `CUSTOM_THROW_ERROR_STRING`,
310
+ do_throw: false, // Make sure it's overwritten
311
+ };
312
+ log.throw( options, `custom_THROW_log` );
313
+ } catch ( error ) {
314
+ error_to_test = error;
315
+ }
316
+ // Note: No metadata is included in the error so that we don't have
317
+ // to re-throw every error that comes in and they can keep their nice
318
+ // stack traces.
319
+ // Note: Also excludes logs from error message
320
+ expect( error_to_test.message ).to.include(`CUSTOM_THROW_ERROR_STRING`);
321
+ expect( error_to_test.stack ).to.include(`at Log.throw`);
322
+ expect( error_to_test.stack ).to.not.include(`Skip`);
323
+ });
324
+ it(`stores an error message in the debug file`, async function() {
325
+ expect_debug_file_to_include(`custom_THROW_before~🤕 custom_THROW_code custom_THROW_context ERROR`);
326
+ expect_debug_file_to_include(`custom_THROW_log`);
327
+ expect_debug_file_to_include(`CUSTOM_THROW_ERROR_STRING`);
328
+ expect_debug_file_to_include(`at Log.throw`); // a bit useless because it's a repeat
329
+ expect_debug_file_to_not_include(`Skip`);
330
+ });
331
+ it(`stores an error message in the unexpected output file`, async function() {
332
+ expect_unexpected_output_file_to_include(`custom_THROW_before~🤕 custom_THROW_code custom_THROW_context ERROR`);
333
+ expect_unexpected_output_file_to_include(`custom_THROW_log`);
334
+ expect_unexpected_output_file_to_include(`CUSTOM_THROW_ERROR_STRING`);
335
+ expect_unexpected_output_file_to_include(`at Log.throw`); // a bit useless because it's a repeat
336
+ expect_unexpected_output_file_to_not_include(`Skip`);
337
+ });
338
+ })
339
+
340
+ describe(`.throw() with an actual error`, function () {
341
+ it(`doesn't include ".Log" in its stack`, async function() {
342
+ let error_to_test;
343
+ try {
344
+ let options = {
345
+ error: new Error(`No ".Log" should be in this stack`),
346
+ do_throw: true, // Not really needed
347
+ };
348
+ log.throw( options, `custom_THROW_log` );
349
+ } catch ( error ) {
350
+ error_to_test = error;
351
+ }
352
+ expect( error_to_test.stack ).to.not.include(`at Log.throw`);
353
+ expect( error_to_test.stack ).to.not.include(`Skip`);
354
+ });
355
+ })
356
+
357
+ describe(`when given 1 option and no logs, ._console()`, function () {
358
+ it(`returns the right text`, async function() {
359
+ let returned = log._console({ icon: `test_icon` });
360
+ expect( returned ).to.include(`test_icon ALK000c LOG`);
361
+ expect( returned ).to.not.include(`Skip`);
362
+ });
363
+ it(`stores the right text in the debug log file`, async function() {
364
+ expect_debug_file_to_include(`test_icon ALK000c LOG`);
365
+ expect_debug_file_to_not_include(`Skip`);
366
+ });
367
+ })
368
+
369
+ describe(`when given multiple logs of multiple types, .debug()`, function () {
370
+ it(`returns the right text`, async function() {
371
+ let returned = log.debug({}, `log 1`, { log_2: `log_2` });
372
+ expect( returned ).to.include(`log 1\n{ log_2: 'log_2' }`);
373
+ expect( returned ).to.not.include(`Skip`);
374
+ });
375
+ it(`stores the right text in the debug log`, async function() {
376
+ expect_debug_file_to_include(`log 1\n{ log_2: 'log_2' }`);
377
+ expect_debug_file_to_not_include(`Skip`);
378
+ });
379
+ })
380
+
381
+ describe(`.stdout`, function () {
382
+ it(`stores in debug log`, async function() {
383
+ log.stdout({}, `test 1 stdout log~`, `test 2 stdout log\n`);
384
+ expect_debug_file_to_include(`test 1 stdout log~test 2 stdout log\n`); // Note no space.
385
+ expect_debug_file_to_not_include(`Skip`);
386
+ });
387
+ // Note: There's no way to test that multiple stdout calls
388
+ // would exclude a new line between them in the console. In
389
+ // debug, each gets its own metadata with its own line.
390
+ })
391
+
392
+ /** Circular references and behavior that adds "skip" messages,
393
+ * like when circular references trigger a JSON.stringify() try/catch.
394
+ * Discuss: Count the number of times "Skip" appears? Can we make these
395
+ * more robust?
396
+ * */
397
+
398
+ describe(`with circular reference to .debug()`, function () {
399
+ it(`fails silently`, function () {
400
+ let obj = { foo: [], test: `.debug circular reference log` };
401
+ obj.foo.push(obj);
402
+ let returned = log.debug({}, obj);
403
+ expect(returned).to.include(`Circular`);
404
+ expect( returned ).to.not.include(`Skip`);
405
+ })
406
+ it(`stores the right value in the debug file`, async function() {
407
+ expect_debug_file_to_include(`Circular`);
408
+ });
409
+ })
410
+
411
+ describe(`.throw()`, function () {
412
+ it(`completes throwing a circular reference error without stopping on another error`, function () {
413
+ let obj = { foo: [], test: `throw circular reference error` };
414
+ obj.foo.push(obj);
415
+ obj.foo.push(obj);
416
+ try {
417
+ log.throw({ error: obj }, `circular error`);
418
+ } catch ( error ) {
419
+ // Note: As expected, excludes metadata and logs from error. Add test?
420
+ expect( error.message ).to.include(`[Circular *1], [Circular *1]`);
421
+ }
422
+ })
423
+ it(`stores the right value in the debug file`, async function() {
424
+ expect_debug_file_to_include(`throw circular reference error`);
425
+ expect_debug_file_to_include(`circular error`);
426
+ expect_debug_file_to_include(`[Circular *1], [Circular *1]`);
427
+ expect_debug_file_to_include(`ALK0224`);
428
+ });
429
+ it(`stores the right value in the unexpected file`, async function() {
430
+ expect_unexpected_output_file_to_include(`throw circular reference error`);
431
+ expect_unexpected_output_file_to_include(`circular error`);
432
+ expect_unexpected_output_file_to_include(`[Circular *1], [Circular *1]`);
433
+ expect_unexpected_output_file_to_include(`ALK0224`);
434
+ });
435
+ })
436
+
437
+ describe(`with a value for \`error\` and no throw with .debug()`, function () {
438
+ it(`returns a value that excludes the error and the error stack`, async function() {
439
+ let options = { error: `custom_DEBUG_non_thrown_error`, };
440
+ let returned = log.debug( options );
441
+ expect( returned ).to.not.include(`custom_DEBUG_non_thrown_error`);
442
+ expect( returned ).to.not.include(`at Log.throw`);
443
+ });
444
+ it(`excludes the error in the debug file`, async function() {
445
+ expect_debug_file_to_not_include(`custom_DEBUG_non_thrown_error`);
446
+ });
447
+ it(`stores the warning code in the debug file`, async function() {
448
+ expect_debug_file_to_include(`ALK0223`);
449
+ });
450
+ it(`stores the text 'Skip' in the debug file`, async function() {
451
+ expect_debug_file_to_include(`Skip`);
452
+ });
453
+ it(`excludes the error in the unexpected output file`, async function() {
454
+ expect_unexpected_output_file_to_not_include(`custom_DEBUG_non_thrown_error`);
455
+ });
456
+ it(`stores the warning code in the unexpected output file`, async function() {
457
+ expect_unexpected_output_file_to_include(`ALK0223`);
458
+ });
459
+ it(`stores the text 'Skip' in the unexpected output file`, async function() {
460
+ expect_unexpected_output_file_to_include(`Skip`);
461
+ });
462
+ })
463
+
464
+ describe(`given an error without a do_throw`, function () {
465
+ it(`.debug saves a warning and ignores the error`, async function() {
466
+ let options = {
467
+ error: `Illegal error`,
468
+ do_throw: false,
469
+ };
470
+ let returned = log.debug( options, `DEBUG log with illegal error` );
471
+ expect( returned ).to.include(`DEBUG log with illegal error`);
472
+ expect( returned ).to.not.include(`Illegal error`);
473
+ // To not include `Illegal error`
474
+ });
475
+ it(`.debug stores and excludes the right text in the debug file`, async function() {
476
+ expect_debug_file_to_include(`ALK0223`);
477
+ expect_debug_file_to_include(`DEBUG log with illegal error`);
478
+ expect_debug_file_to_not_include(`Illegal error`);
479
+ });
480
+ })
481
+
482
+ /** Internal errors */
483
+
484
+ describe(`when a log file doesn't exist`, function () {
485
+ let temp_log4, returned, throw_behavior;
486
+
487
+ before(function () {
488
+ // // Spy on console.warn to make sure it gets called with the right value
489
+ // // This ruins console.warn for the rest of the test
490
+ // let warning = ``;
491
+ // let done_warning = false;
492
+ // let original_warn = console.warn;
493
+ // // can we return a promise? Probably. Does that help? We won't be calling the promise.
494
+ // console.warn = function () {
495
+ // done_warning = false
496
+ // warning = arguments[0];
497
+ // done_warning = true;
498
+ // }
499
+
500
+ temp_log4 = new Log({ path: temp_log_path });
501
+ // Trigger an error that should be silent
502
+ temp_log4.path = `non-existent`;
503
+
504
+ returned = null;
505
+ throw_behavior = `Did NOT throw.`;
506
+ try {
507
+ returned = temp_log4.debug({}, `No file, no save, no error` );
508
+ } catch ( this_should_not_error ) {
509
+ // Shouldn't throw
510
+ throw_behavior = `DID throw.`
511
+ }
512
+ })
513
+
514
+ it(`doesn't throw an error`, async function() {
515
+ expect( throw_behavior ).to.equal(`Did NOT throw.`);
516
+ })
517
+ it(`returns the error`, async function() {
518
+ expect( returned ).to.include(`No file, no save, no error`);
519
+ })
520
+ // No contents for log files since they don't exist.
521
+
522
+ after(function () {
523
+ fs.rmSync( temp_log_path, { recursive: true, force: true });
524
+
525
+ // // Wait for the async console.warn to finish, then test its value
526
+ // while ( !done_warning ) {
527
+ // await new Promise((resolve) => { setTimeout(resolve, 500) });
528
+ // }
529
+ // expect( warning ).to.include(`no such file or directory, open '${ temp_log4.path }/debug_log.txt'`);
530
+ // // Clean up
531
+ // console.warn = original_warn;
532
+ })
533
+ })
534
+
535
+ });
536
+
537
+
538
+ function expect_debug_file_to_include( text ) {
539
+ let from_file = fs.readFileSync(`${path}/${log.debug_log_filename}`, 'utf8');
540
+ expect( from_file ).to.include( text );
541
+ };
542
+ function expect_debug_file_to_not_include( text ) {
543
+ let from_file = fs.readFileSync(`${path}/${log.debug_log_filename}`, 'utf8');
544
+ expect( from_file ).to.not.include( text );
545
+ };
546
+
547
+
548
+ function expect_unexpected_output_file_to_include( text ) {
549
+ let from_file = fs.readFileSync(`${path}/${log.temp_unexpected_debug_log_filename}`, 'utf8');
550
+ expect( from_file ).to.include( text );
551
+ };
552
+ function expect_unexpected_output_file_to_not_include( text ) {
553
+ let from_file = fs.readFileSync(`${path}/${log.temp_unexpected_debug_log_filename}`, 'utf8');
554
+ expect( from_file ).to.not.include( text );
555
+ };
556
+
557
+ function neutralize_console() {
558
+ // old_log = console.log;
559
+ // old_info = console.info;
560
+ // old_warn = console.warn;
561
+ // old_error = console.error;
562
+ // console.log = function () { /* Do nothing */ };
563
+ // console.info = function () { /* Do nothing */ };
564
+ // console.warn = function () { /* Do nothing */ };
565
+ // console.error = function () { /* Do nothing */ };
566
+
567
+ // old_stdout = process.stdout.write;
568
+ // old_stderr = process.stderr.write;
569
+ // process.stdout.write = function() {};
570
+ // process.stderr.write = function() {};
571
+ }
572
+
573
+ function restore_console() {
574
+ // console.log = old_log;
575
+ // console.info = old_info;
576
+ // console.warn = old_warn;
577
+ // console.error = old_error;
578
+
579
+ // process.stdout.write = old_stdout;
580
+ // process.stderr.write = old_stderr;
581
+ }
@@ -5,6 +5,11 @@ const expect = chai.expect;
5
5
 
6
6
  const tables = require('./tables.fixtures.js');
7
7
  const scope = require('../../lib/scope.js');
8
+
9
+ const Log = require(`../../lib/utils/Log.js`);
10
+ const log = new Log({ path: `_alkiln-misc_artifacts/normalize_table_${ Date.now() }`, context: `unit_tests normalizeTable` });
11
+ scope.set_log({ log_obj: log });
12
+
8
13
  const normalizeTable = scope.normalizeTable;
9
14
 
10
15
 
package/lib/utils/log.js DELETED
@@ -1,96 +0,0 @@
1
- const fs = require('fs');
2
- const session_vars = require( './session_vars' );
3
-
4
- // ? 🌈 💡 🔎 🤕 🐞
5
- // Alternatives: 🩹 ❤️‍🩹 🚑
6
- // TODO: return full message so it can be passed to manually
7
- // thrown errors if needed.
8
-
9
- let log = {};
10
- module.exports = log;
11
-
12
- let create_msg_start = function ( types, pre='', code=`? ALK0000` ) {
13
- // ? - unknown (fallback)
14
- let types_str = types.join(` `);
15
- if ( types_str.includes(`plain`) ) {
16
- return pre;
17
- } else {
18
- return `${ code } ${ types_str }: ${ pre }`;
19
- }
20
- };
21
-
22
- // Where is this used?
23
- log.success = function ({ type='', pre='', data='', post='', code=`ALK0000` }) {
24
- /** Log success msg with the given information and strings, prepended with `ALKiln`.
25
- * `type` is often something like 'setup', 'takedown', etc. */
26
- // √ - info (fallback)
27
- let start = create_msg_start([ type, `SUCCESS` ], pre, `🌈 ${code}` );
28
- // Log them each on a separate line
29
- console.info( `${ start }` );
30
- if ( data ) { console.info( data ); }
31
- if ( post ) { console.info( post ); }
32
- };
33
-
34
- // Where is this used?
35
- log.info = function ({ type='', pre='', data='', post='', code=`ALK0000` }) {
36
- /** Log info msg with the given information and strings, prepended with `ALKiln`.
37
- * `type` is often something like 'setup', 'takedown', etc. */
38
- // & - info (fallback)
39
- let start = create_msg_start([ type, `INFO` ], pre, `💡 ${code}` );
40
- // Log them each on a separate line
41
- console.info( `${ start }` );
42
- if ( data ) { console.info( data ); }
43
- if ( post ) { console.info( post ); }
44
- };
45
-
46
- // Where is this used?
47
- log.warn = function ({ type='', pre='', data='', post='', code=`ALK0000` }) {
48
- /** Log warning msg with the given information and strings, prepended with `ALKiln`.
49
- * `type` is often something like 'setup', 'takedown', etc. */
50
- // ! - warning (fallback)
51
- let start = create_msg_start([ type, `WARNING` ], pre, `🔎 ${code}` );
52
- // Log them each on a separate line
53
- console.warn( `${ start }` );
54
- if ( data ) { console.warn( data ); }
55
- if ( post ) { console.warn( post ); }
56
- };
57
-
58
- // Where is this used?
59
- log.error = function ({ type='', pre='', data='', post='', code=`ALK0000` }) {
60
- /** Log error msg with the given information and strings, prepended with `ALKiln`.
61
- * `type` is often something like 'setup', 'takedown', etc. */
62
- // X - error (fallback)
63
- let start = create_msg_start([ type, `ERROR` ], pre, `🤕 ${code}` );
64
- // Log them each on a separate line with extra new lines around the whole thing
65
- console.error( `\n${ start }` );
66
- if ( data ) { console.error( data ); }
67
- if ( post ) { console.error( post, `\n` ); }
68
- };
69
-
70
- log.debug = function ({ type='', pre='', data='', post='', verbose=false, code=`ALK0000` }) {
71
- /** If debugging is turned on, log a message that includes `ALKiln` and `debug` */
72
- // @ - debug (fallback)
73
- let start = create_msg_start([ type, `DEBUG` ], pre, `🐞 ${ code }` );
74
- let full = `\n${ start }`;
75
- if ( data ) { full += `\n${ data }`; }
76
- if ( post ) { full += `\n${ post }`; }
77
-
78
- // TODO: Make a verbose log instead of adding to the debug one and always add to it
79
- if ( verbose ) {
80
- log.add_to_debug_log( full );
81
- }
82
-
83
- if ( session_vars.get_debug() ) {
84
- // Log them each on a separate line
85
- console.log( `\n${ start }` );
86
- console.log( data );
87
- console.log( post );
88
- }
89
- };
90
-
91
- log.add_to_debug_log = function(value) {
92
- fs.appendFileSync(log.debug_log_file, value);
93
- };
94
-
95
- log.debug_log_file = `debug_log.txt`;
96
- log.unexpected_filename = `unexpected_results.txt`;