@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.
- package/.github/workflows/github_server.yml +7 -7
- package/.github/workflows/playground.yml +1 -1
- package/CHANGELOG.md +32 -1
- package/action.yml +70 -28
- package/action_for_github_server/action.yml +61 -29
- package/docs/4_environments.md +243 -0
- package/docs/artifacts_folder_name.md +135 -0
- package/docs/constrained_random_tests.md +347 -0
- package/docs/decisions/006_which_log_level_to_pick_2024_09_5.md +70 -0
- package/docs/decisions/007_getting_and_storing_logs.md +179 -0
- package/docs/decisions/move_runtime_config_to_sources_folder.md +3 -0
- package/docs/decisions/reports_and_logs_2024_08_11.md +161 -0
- package/docs/kinds_of_errors.md +26 -0
- package/docs/prioritize_constrained_random_tests.md +101 -0
- package/docs/seprate_file_generation_GitHub_action.md +11 -0
- package/lib/docassemble/docassemble_api_interface.js +77 -51
- package/lib/docassemble/server_install.js +32 -9
- package/lib/docassemble/setup.js +40 -25
- package/lib/docassemble/takedown.js +33 -10
- package/lib/parse.js +36 -0
- package/lib/run_cucumber.js +115 -36
- package/lib/scope.js +69 -77
- package/lib/steps.js +70 -42
- package/lib/utils/Log.js +982 -0
- package/lib/utils/files.js +18 -11
- package/lib/utils/get_sources_paths.js +162 -0
- package/lib/utils/parse.js +1 -0
- package/lib/utils/proccess_command_line_args.js +267 -0
- package/lib/utils/reports.js +64 -17
- package/lib/utils/session_vars.js +34 -21
- package/lib/utils/time.js +44 -0
- package/package.json +1 -1
- package/tests/log_codes/check_codes.sh +2 -1
- package/tests/log_codes/log_code_expected_instances.txt +33 -9
- package/tests/unit_tests/getAllFields.test.js +5 -0
- package/tests/unit_tests/getMatchingRows.test.js +5 -0
- package/tests/unit_tests/log.test.js +581 -0
- package/tests/unit_tests/normalizeTable.test.js +5 -0
- 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`;
|