doc-detective 1.0.4 → 1.0.6
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/package.json +1 -1
- package/sample/config.json +6 -4
- package/sample/doc-content.md +15 -15
- package/sample/failedTests/failed-test-recordings-go-here +0 -0
- package/sample/tests.json +2 -0
- package/src/config.json +6 -4
- package/src/lib/tests/httpRequest.js +0 -2
- package/src/lib/tests/record.js +32 -8
- package/src/lib/tests/screenshot.js +48 -25
- package/src/lib/tests.js +61 -13
- package/src/lib/utils.js +83 -5
package/package.json
CHANGED
package/sample/config.json
CHANGED
|
@@ -14,14 +14,16 @@
|
|
|
14
14
|
".json"
|
|
15
15
|
],
|
|
16
16
|
"mediaDirectory": "sample",
|
|
17
|
+
"saveFailedTestRecordings": true,
|
|
18
|
+
"failedTestDirectory": "sample/failedTests",
|
|
17
19
|
"fileTypes": [
|
|
18
20
|
{
|
|
19
21
|
"extensions": [
|
|
20
22
|
".md",
|
|
21
23
|
".mdx"
|
|
22
24
|
],
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
+
"openActionStatement": "[comment]: # (action",
|
|
26
|
+
"closeActionStatement": ")"
|
|
25
27
|
},
|
|
26
28
|
{
|
|
27
29
|
"extensions": [
|
|
@@ -29,8 +31,8 @@
|
|
|
29
31
|
".htm",
|
|
30
32
|
".xml"
|
|
31
33
|
],
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
+
"openActionStatement": "<!-- action",
|
|
35
|
+
"closeActionStatement": "-->"
|
|
34
36
|
}
|
|
35
37
|
],
|
|
36
38
|
"browserOptions": {
|
package/sample/doc-content.md
CHANGED
|
@@ -4,19 +4,19 @@ To use Google Search to find information on kittens,
|
|
|
4
4
|
|
|
5
5
|
1. Open [Google Search](https://www.google.com).
|
|
6
6
|
|
|
7
|
-
[comment]: # (
|
|
8
|
-
[comment]: # (
|
|
7
|
+
[comment]: # (action {"testId":"process-search-kittens", "action":"startRecording", "overwrite":false, "filename":"results.gif", "fps":15})
|
|
8
|
+
[comment]: # (action {"testId":"process-search-kittens", "action":"goTo", "uri":"www.google.com"})
|
|
9
9
|
|
|
10
10
|
2. In the search bar, enter "kittens", then press Enter.
|
|
11
11
|
|
|
12
|
-
[comment]: # (
|
|
13
|
-
[comment]: # (
|
|
14
|
-
[comment]: # (
|
|
15
|
-
[comment]: # (
|
|
16
|
-
[comment]: # (
|
|
17
|
-
[comment]: # (
|
|
18
|
-
[comment]: # (
|
|
19
|
-
[comment]: # (
|
|
12
|
+
[comment]: # (action {"testId":"process-search-kittens", "action":"moveMouse", "css":"#gbqfbb", "alignH": "center", "alignV": "center"})
|
|
13
|
+
[comment]: # (action {"testId":"process-search-kittens", "action":"wait", "duration":"5000"})
|
|
14
|
+
[comment]: # (action {"testId":"process-search-kittens", "action":"moveMouse", "css":"[title=Search]", "alignV": "center"})
|
|
15
|
+
[comment]: # (action {"testId":"process-search-kittens", "action":"type", "css":"[title=Search]", "keys":"kittens", "trailingSpecialKey":"Enter"})
|
|
16
|
+
[comment]: # (action {"testId":"process-search-kittens", "action":"wait", "duration":"5000"})
|
|
17
|
+
[comment]: # (action {"testId":"process-search-kittens", "action":"scroll", "y": 300})
|
|
18
|
+
[comment]: # (action {"testId":"process-search-kittens", "action":"stopRecording"})
|
|
19
|
+
[comment]: # (action {"testId":"process-search-kittens", "action":"screenshot", "filename":"results.png", "matchPrevious": true, "matchThreshold": 0.1})
|
|
20
20
|
|
|
21
21
|
Search results appear on the page.
|
|
22
22
|
|
|
@@ -26,17 +26,17 @@ Search results appear on the page.
|
|
|
26
26
|
|
|
27
27
|
To go directly to a recommended result for your search, use the **I'm Feeling Lucky** button. If you're searching for american shorthair information,
|
|
28
28
|
|
|
29
|
-
[comment]: # (
|
|
30
|
-
[comment]: # (
|
|
29
|
+
[comment]: # (action {"testId":"text-match-lucky", "action":"goTo", "uri":"www.google.com"})
|
|
30
|
+
[comment]: # (action {"testId":"text-match-lucky", "action":"matchText", "css":"#gbqfbb", "text":"I'm Feeling Lucky"})
|
|
31
31
|
|
|
32
32
|
1. Open [Google Search](https://www.google.com).
|
|
33
33
|
|
|
34
|
-
[comment]: # (
|
|
34
|
+
[comment]: # (action {"testId":"process-lucky-shorthair", "action":"goTo", "uri":"www.google.com"})
|
|
35
35
|
|
|
36
36
|
2. In the search bar, enter "american shorthair cats".
|
|
37
37
|
|
|
38
|
-
[comment]: # (
|
|
38
|
+
[comment]: # (action {"testId":"process-lucky-shorthair", "action":"type", "css":"[title=Search]", "keys":"american shorthair cats"})
|
|
39
39
|
|
|
40
40
|
3. Click **I'm Feeling Lucky**.
|
|
41
41
|
|
|
42
|
-
[comment]: # (
|
|
42
|
+
[comment]: # (action {"testId":"process-lucky-shorthair", "action":"click", "css":"#gbqfbb"})
|
|
File without changes
|
package/sample/tests.json
CHANGED
package/src/config.json
CHANGED
|
@@ -14,14 +14,16 @@
|
|
|
14
14
|
".json"
|
|
15
15
|
],
|
|
16
16
|
"mediaDirectory": ".",
|
|
17
|
+
"saveFailedTestRecordings": true,
|
|
18
|
+
"failedTestDirectory": ".",
|
|
17
19
|
"fileTypes": [
|
|
18
20
|
{
|
|
19
21
|
"extensions": [
|
|
20
22
|
".md",
|
|
21
23
|
".mdx"
|
|
22
24
|
],
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
+
"openActionStatement": "[comment]: # (action",
|
|
26
|
+
"closeActionStatement": ")"
|
|
25
27
|
},
|
|
26
28
|
{
|
|
27
29
|
"extensions": [
|
|
@@ -29,8 +31,8 @@
|
|
|
29
31
|
".htm",
|
|
30
32
|
".xml"
|
|
31
33
|
],
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
+
"openActionStatement": "<!-- action",
|
|
35
|
+
"closeActionStatement": "-->"
|
|
34
36
|
}
|
|
35
37
|
],
|
|
36
38
|
"browserOptions": {
|
package/src/lib/tests/record.js
CHANGED
|
@@ -87,12 +87,17 @@ async function startRecording(action, page, config) {
|
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
// Set FPS
|
|
90
|
-
|
|
90
|
+
targetFps = action.fps || action.gifFps || defaultPayload.fps;
|
|
91
91
|
try {
|
|
92
|
-
|
|
92
|
+
targetFps = Number(targetFps);
|
|
93
|
+
if (targetFps >= 30) {
|
|
94
|
+
fps = targetFps;
|
|
95
|
+
} else {
|
|
96
|
+
fps = 30;
|
|
97
|
+
}
|
|
93
98
|
} catch {
|
|
94
|
-
|
|
95
|
-
log(config, "warning", `Invalid FPS. Reverting to default: ${
|
|
99
|
+
targetFps = defaultPayload.fps;
|
|
100
|
+
log(config, "warning", `Invalid FPS. Reverting to default: ${targetFps}`);
|
|
96
101
|
}
|
|
97
102
|
|
|
98
103
|
// Set height
|
|
@@ -126,6 +131,7 @@ async function startRecording(action, page, config) {
|
|
|
126
131
|
filepath,
|
|
127
132
|
tempFilepath,
|
|
128
133
|
fps,
|
|
134
|
+
targetFps,
|
|
129
135
|
height,
|
|
130
136
|
width,
|
|
131
137
|
};
|
|
@@ -143,12 +149,30 @@ async function stopRecording(videoDetails, config) {
|
|
|
143
149
|
let status;
|
|
144
150
|
let description;
|
|
145
151
|
let result;
|
|
152
|
+
|
|
153
|
+
if (typeof videoDetails.recorder === "undefined") {
|
|
154
|
+
status = "PASS";
|
|
155
|
+
description = `Skipping action. No action-defined recording in progress.`;
|
|
156
|
+
result = { status, description };
|
|
157
|
+
return { result };
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
recorder = videoDetails.recorder;
|
|
161
|
+
targetExtension = videoDetails.targetExtension;
|
|
162
|
+
height = videoDetails.height;
|
|
163
|
+
width = videoDetails.width;
|
|
164
|
+
filepath = videoDetails.filepath;
|
|
165
|
+
tempFilepath = videoDetails.tempFilepath;
|
|
166
|
+
fps = videoDetails.fps;
|
|
167
|
+
targetFps = videoDetails.targetFps;
|
|
168
|
+
|
|
146
169
|
try {
|
|
147
|
-
await
|
|
170
|
+
await recorder.stop();
|
|
148
171
|
if (
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
172
|
+
targetExtension === ".gif" ||
|
|
173
|
+
height != config.browserOptions.height ||
|
|
174
|
+
width != config.browserOptions.width ||
|
|
175
|
+
targetFps != fps
|
|
152
176
|
) {
|
|
153
177
|
let output = await convertVideo(config, videoDetails);
|
|
154
178
|
filepath = output;
|
|
@@ -87,36 +87,59 @@ async function screenshot(action, page, config) {
|
|
|
87
87
|
if (action.matchPrevious) {
|
|
88
88
|
const expected = PNG.sync.read(fs.readFileSync(previousFilePath));
|
|
89
89
|
const actual = PNG.sync.read(fs.readFileSync(filePath));
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
90
|
+
try {
|
|
91
|
+
const numDiffPixels = pixelmatch(
|
|
92
|
+
expected.data,
|
|
93
|
+
actual.data,
|
|
94
|
+
null,
|
|
95
|
+
expected.width,
|
|
96
|
+
expected.height,
|
|
97
|
+
{
|
|
98
|
+
threshold: action.matchThreshold,
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
fs.unlink(filePath, function (err) {
|
|
102
|
+
if (err) {
|
|
103
|
+
log(
|
|
104
|
+
config,
|
|
105
|
+
"warning",
|
|
106
|
+
`Couldn't delete intermediate file: ${filePath}`
|
|
107
|
+
);
|
|
108
|
+
} else {
|
|
109
|
+
log(config, "debug", `Deleted intermediate file: ${filePath}`);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
if (numDiffPixels) {
|
|
113
|
+
// FAIL: Couldn't capture screenshot
|
|
114
|
+
const diffPercentage =
|
|
115
|
+
numDiffPixels / (expected.width * expected.height);
|
|
116
|
+
status = "FAIL";
|
|
117
|
+
description = `Screenshot comparison had larger diff (${diffPercentage}) than threshold (${action.matchThreshold}).`;
|
|
118
|
+
result = { status, description };
|
|
119
|
+
return { result };
|
|
103
120
|
} else {
|
|
104
|
-
|
|
121
|
+
// PASS
|
|
122
|
+
status = "PASS";
|
|
123
|
+
description = `Screenshot matches previously captured image.`;
|
|
124
|
+
result = { status, description, image: previousFilePath };
|
|
125
|
+
return { result };
|
|
105
126
|
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
127
|
+
} catch {
|
|
128
|
+
fs.unlink(filePath, function (err) {
|
|
129
|
+
if (err) {
|
|
130
|
+
log(
|
|
131
|
+
config,
|
|
132
|
+
"warning",
|
|
133
|
+
`Couldn't delete intermediate file: ${filePath}`
|
|
134
|
+
);
|
|
135
|
+
} else {
|
|
136
|
+
log(config, "debug", `Deleted intermediate file: ${filePath}`);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
110
139
|
status = "FAIL";
|
|
111
|
-
description = `
|
|
140
|
+
description = `Image sizes don't match.`;
|
|
112
141
|
result = { status, description };
|
|
113
142
|
return { result };
|
|
114
|
-
} else {
|
|
115
|
-
// PASS
|
|
116
|
-
status = "PASS";
|
|
117
|
-
description = `Screenshot matches previously captured image.`;
|
|
118
|
-
result = { status, description, image: previousFilePath };
|
|
119
|
-
return { result };
|
|
120
143
|
}
|
|
121
144
|
}
|
|
122
145
|
}
|
package/src/lib/tests.js
CHANGED
|
@@ -2,7 +2,7 @@ const puppeteer = require("puppeteer");
|
|
|
2
2
|
const fs = require("fs");
|
|
3
3
|
const { exit, stdout, exitCode } = require("process");
|
|
4
4
|
const { installMouseHelper } = require("./install-mouse-helper");
|
|
5
|
-
const { setEnvs, log } = require("./utils");
|
|
5
|
+
const { setEnvs, log, timestamp } = require("./utils");
|
|
6
6
|
const util = require("util");
|
|
7
7
|
const exec = util.promisify(require("child_process").exec);
|
|
8
8
|
const axios = require("axios");
|
|
@@ -88,33 +88,54 @@ async function runTests(config, tests) {
|
|
|
88
88
|
let pass = 0;
|
|
89
89
|
let warning = 0;
|
|
90
90
|
let fail = 0;
|
|
91
|
-
|
|
91
|
+
config.videoDetails = {};
|
|
92
|
+
config.debugRecording = {};
|
|
92
93
|
// Instantiate page
|
|
93
94
|
const page = await browser.newPage();
|
|
95
|
+
if (
|
|
96
|
+
test.saveFailedTestRecordings ||
|
|
97
|
+
(config.saveFailedTestRecordings &&
|
|
98
|
+
test.saveFailedTestRecordings != false)
|
|
99
|
+
) {
|
|
100
|
+
failedTestDirectory =
|
|
101
|
+
test.failedTestDirectory || config.failedTestDirectory;
|
|
102
|
+
debugRecordingOptions = {
|
|
103
|
+
action: "startRecording",
|
|
104
|
+
mediaDirectory: failedTestDirectory,
|
|
105
|
+
filename: `${test.id}-${timestamp()}.mp4`,
|
|
106
|
+
overwrite: true,
|
|
107
|
+
};
|
|
108
|
+
config.debugRecording = await startRecording(
|
|
109
|
+
debugRecordingOptions,
|
|
110
|
+
page,
|
|
111
|
+
config
|
|
112
|
+
);
|
|
113
|
+
}
|
|
94
114
|
// Instantiate mouse cursor
|
|
95
115
|
await installMouseHelper(page);
|
|
96
116
|
// Iterate through actions
|
|
97
117
|
for (const action of test.actions) {
|
|
98
118
|
log(config, "debug", `ACTION: ${JSON.stringify(action)}`);
|
|
99
|
-
action.result = await runAction(
|
|
119
|
+
action.result = await runAction(
|
|
120
|
+
config,
|
|
121
|
+
action,
|
|
122
|
+
page,
|
|
123
|
+
config.videoDetails
|
|
124
|
+
);
|
|
100
125
|
if (action.result.videoDetails) {
|
|
101
|
-
videoDetails = action.result.videoDetails;
|
|
126
|
+
config.videoDetails = action.result.videoDetails;
|
|
102
127
|
}
|
|
103
128
|
action.result = action.result.result;
|
|
104
129
|
if (action.result.status === "FAIL") fail++;
|
|
105
130
|
if (action.result.status === "WARNING") warning++;
|
|
106
131
|
if (action.result.status === "PASS") pass++;
|
|
107
|
-
log(
|
|
132
|
+
log(
|
|
133
|
+
config,
|
|
134
|
+
"debug",
|
|
135
|
+
`RESULT: ${action.result.status}. ${action.result.description}`
|
|
136
|
+
);
|
|
108
137
|
}
|
|
109
138
|
|
|
110
|
-
// Close open recorders/pages
|
|
111
|
-
if (videoDetails) {
|
|
112
|
-
await runAction("", { action: "stopRecording" }, "", videoDetails);
|
|
113
|
-
}
|
|
114
|
-
try {
|
|
115
|
-
await page.close();
|
|
116
|
-
} catch {}
|
|
117
|
-
|
|
118
139
|
// Calc overall test result
|
|
119
140
|
if (fail) {
|
|
120
141
|
test.status = "FAIL";
|
|
@@ -126,6 +147,33 @@ async function runTests(config, tests) {
|
|
|
126
147
|
console.log("Error: Couldn't read test action results.");
|
|
127
148
|
exit(1);
|
|
128
149
|
}
|
|
150
|
+
|
|
151
|
+
// Close open recorders/pages
|
|
152
|
+
if (config.debugRecording.videoDetails) {
|
|
153
|
+
await stopRecording(config.debugRecording.videoDetails, config);
|
|
154
|
+
if (!fail) {
|
|
155
|
+
fs.unlink(config.debugRecording.videoDetails.filepath, function (err) {
|
|
156
|
+
if (err) {
|
|
157
|
+
log(
|
|
158
|
+
config,
|
|
159
|
+
"warning",
|
|
160
|
+
`Couldn't delete debug recording: ${config.debugRecording.videoDetails.filepath}`
|
|
161
|
+
);
|
|
162
|
+
} else {
|
|
163
|
+
log(
|
|
164
|
+
config,
|
|
165
|
+
"debug",
|
|
166
|
+
`Deleted debug recording: ${config.debugRecording.videoDetails.filepath}`
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Close page
|
|
174
|
+
try {
|
|
175
|
+
await page.close();
|
|
176
|
+
} catch {}
|
|
129
177
|
}
|
|
130
178
|
await browser.close();
|
|
131
179
|
return tests;
|
package/src/lib/utils.js
CHANGED
|
@@ -16,6 +16,7 @@ exports.outputResults = outputResults;
|
|
|
16
16
|
exports.setEnvs = setEnvs;
|
|
17
17
|
exports.loadEnvsForObject = loadEnvsForObject;
|
|
18
18
|
exports.log = log;
|
|
19
|
+
exports.timestamp = timestamp;
|
|
19
20
|
|
|
20
21
|
const analyticsRequest =
|
|
21
22
|
"Thanks for using Doc Detective! If you want to contribute to the project, consider sending analytics to help us understand usage patterns and functional gaps. To turn on analytics, set 'analytics.send = true' in your config, or use the '-a true' argument. See https://github.com/hawkeyexl/doc-detective#analytics";
|
|
@@ -284,6 +285,67 @@ function setMediaDirectory(config, argv) {
|
|
|
284
285
|
return config;
|
|
285
286
|
}
|
|
286
287
|
|
|
288
|
+
function setFailedTestRecording(config, argv) {
|
|
289
|
+
config.saveFailedTestRecordings =
|
|
290
|
+
argv.saveFailedTestRecordings ||
|
|
291
|
+
process.env.DOC_SAVE_FAILED_RECORDINGS ||
|
|
292
|
+
config.saveFailedTestRecordings;
|
|
293
|
+
switch (config.saveFailedTestRecordings) {
|
|
294
|
+
case true:
|
|
295
|
+
case "true":
|
|
296
|
+
config.saveFailedTestRecordings = true;
|
|
297
|
+
log(
|
|
298
|
+
config,
|
|
299
|
+
"debug",
|
|
300
|
+
`Save failed test recordings set: ${config.saveFailedTestRecordings}`
|
|
301
|
+
);
|
|
302
|
+
break;
|
|
303
|
+
case false:
|
|
304
|
+
case "false":
|
|
305
|
+
config.saveFailedTestRecordings = false;
|
|
306
|
+
log(
|
|
307
|
+
config,
|
|
308
|
+
"debug",
|
|
309
|
+
`Save failed test recordings set: ${config.saveFailedTestRecordings}`
|
|
310
|
+
);
|
|
311
|
+
log(config, "info", analyticsRequest);
|
|
312
|
+
break;
|
|
313
|
+
default:
|
|
314
|
+
config.saveFailedTestRecordings = defaultConfig.saveFailedTestRecordings;
|
|
315
|
+
log(
|
|
316
|
+
config,
|
|
317
|
+
"warning",
|
|
318
|
+
`Invalid save failed test recordings value. Reverted to default: ${config.saveFailedTestRecordings}`
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
return config;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function setFailedTestDirectory(config, argv) {
|
|
325
|
+
config.failedTestDirectory =
|
|
326
|
+
argv.failedTestDirectory ||
|
|
327
|
+
process.env.DOC_FAILED_TEST_DIRECTORY_PATH ||
|
|
328
|
+
config.failedTestDirectory;
|
|
329
|
+
config.failedTestDirectory = path.resolve(config.failedTestDirectory);
|
|
330
|
+
if (fs.existsSync(config.failedTestDirectory)) {
|
|
331
|
+
log(
|
|
332
|
+
config,
|
|
333
|
+
"debug",
|
|
334
|
+
`Failed test directory set: ${config.failedTestDirectory}`
|
|
335
|
+
);
|
|
336
|
+
} else {
|
|
337
|
+
config.failedTestDirectory = path.resolve(
|
|
338
|
+
defaultConfig.failedTestDirectory
|
|
339
|
+
);
|
|
340
|
+
log(
|
|
341
|
+
config,
|
|
342
|
+
"warning",
|
|
343
|
+
`Invalid failed test directory. Reverted to default: ${config.failedTestDirectory}`
|
|
344
|
+
);
|
|
345
|
+
}
|
|
346
|
+
return config;
|
|
347
|
+
}
|
|
348
|
+
|
|
287
349
|
function setRecursion(config, argv) {
|
|
288
350
|
config.recursive =
|
|
289
351
|
argv.recursive || process.env.DOC_RECURSIVE || config.recursive;
|
|
@@ -537,6 +599,10 @@ function setConfig(config, argv) {
|
|
|
537
599
|
|
|
538
600
|
config = setMediaDirectory(config, argv);
|
|
539
601
|
|
|
602
|
+
config = setFailedTestRecording(config, argv);
|
|
603
|
+
|
|
604
|
+
config = setFailedTestDirectory(config, argv);
|
|
605
|
+
|
|
540
606
|
config = setRecursion(config, argv);
|
|
541
607
|
|
|
542
608
|
config = setTestFileExtensions(config, argv);
|
|
@@ -654,16 +720,16 @@ function parseFiles(config, files) {
|
|
|
654
720
|
let lineJson = "";
|
|
655
721
|
let subStart = "";
|
|
656
722
|
let subEnd = "";
|
|
657
|
-
if (line.includes(fileType.
|
|
723
|
+
if (line.includes(fileType.openActionStatement)) {
|
|
658
724
|
const lineAscii = line.toString("ascii");
|
|
659
|
-
if (fileType.
|
|
660
|
-
subEnd = lineAscii.lastIndexOf(fileType.
|
|
725
|
+
if (fileType.closeActionStatement) {
|
|
726
|
+
subEnd = lineAscii.lastIndexOf(fileType.closeActionStatement);
|
|
661
727
|
} else {
|
|
662
728
|
subEnd = lineAscii.length;
|
|
663
729
|
}
|
|
664
730
|
subStart =
|
|
665
|
-
lineAscii.indexOf(fileType.
|
|
666
|
-
fileType.
|
|
731
|
+
lineAscii.indexOf(fileType.openActionStatement) +
|
|
732
|
+
fileType.openActionStatement.length;
|
|
667
733
|
lineJson = JSON.parse(lineAscii.substring(subStart, subEnd));
|
|
668
734
|
if (!lineJson.testId) {
|
|
669
735
|
lineJson.testId = id;
|
|
@@ -692,6 +758,7 @@ async function outputResults(config, results) {
|
|
|
692
758
|
log(config, "info", "RESULTS:");
|
|
693
759
|
log(config, "info", results);
|
|
694
760
|
log(config, "info", `See detailed results at ${config.output}`);
|
|
761
|
+
log(config, "info", "Cleaning up and finishing post-processing.");
|
|
695
762
|
}
|
|
696
763
|
|
|
697
764
|
async function setEnvs(envsFile) {
|
|
@@ -759,3 +826,14 @@ function loadEnvsForObject(object) {
|
|
|
759
826
|
});
|
|
760
827
|
return object;
|
|
761
828
|
}
|
|
829
|
+
|
|
830
|
+
function timestamp() {
|
|
831
|
+
let timestamp = new Date();
|
|
832
|
+
return `${timestamp.getFullYear()}${("0" + (timestamp.getMonth() + 1)).slice(
|
|
833
|
+
-2
|
|
834
|
+
)}${("0" + timestamp.getDate()).slice(-2)}-${(
|
|
835
|
+
"0" + timestamp.getHours()
|
|
836
|
+
).slice(-2)}${("0" + timestamp.getMinutes()).slice(-2)}${(
|
|
837
|
+
"0" + timestamp.getSeconds()
|
|
838
|
+
).slice(-2)}`;
|
|
839
|
+
}
|