tracereports 0.4.0 → 0.4.1
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/src/index.js +10 -10
- package/src/mask.js +1 -1
- package/src/mirror.js +6 -6
- package/src/reporter.js +8 -8
- package/src/transport.js +4 -4
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -28,7 +28,7 @@ import { Mirror } from "./mirror.js";
|
|
|
28
28
|
import { Sender } from "./transport.js";
|
|
29
29
|
import { downloadBinary } from "./binary.js";
|
|
30
30
|
|
|
31
|
-
export const VERSION = "0.4.
|
|
31
|
+
export const VERSION = "0.4.1";
|
|
32
32
|
const STATUSES = new Set(["INFO", "PASS", "FAIL", "WARNING", "SKIP"]);
|
|
33
33
|
const truthy = (v) => ["1", "true", "yes"].includes(String(v || "").toLowerCase());
|
|
34
34
|
|
|
@@ -133,12 +133,12 @@ export class TraceReports {
|
|
|
133
133
|
try {
|
|
134
134
|
this.sender = new Recorder(dir);
|
|
135
135
|
} catch (err) {
|
|
136
|
-
console.warn(`tracereports:
|
|
136
|
+
console.warn(`tracereports: could not record locally in ${dir}: ${err.message}`);
|
|
137
137
|
return;
|
|
138
138
|
}
|
|
139
139
|
this.offlineDir = dir;
|
|
140
140
|
if (reason) {
|
|
141
|
-
console.warn(`tracereports: ${reason};
|
|
141
|
+
console.warn(`tracereports: ${reason}; recording the evidence in ${dir}`);
|
|
142
142
|
}
|
|
143
143
|
}
|
|
144
144
|
|
|
@@ -147,7 +147,7 @@ export class TraceReports {
|
|
|
147
147
|
try {
|
|
148
148
|
this.sender = new Mirror(this.sender, dir, this.baseUrl, runId, payload);
|
|
149
149
|
this.offlineDir = dir;
|
|
150
|
-
} catch (err) { console.warn(`tracereports:
|
|
150
|
+
} catch (err) { console.warn(`tracereports: could not start local copy in ${dir}: ${err.message}`); }
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
/** Arma el HTML con el binario instalado o el renderer verificado de la caché. */
|
|
@@ -163,7 +163,7 @@ export class TraceReports {
|
|
|
163
163
|
if (!fs.statSync(index).isFile()) throw Error("renderer did not create index.html");
|
|
164
164
|
this.offlineReport = index;
|
|
165
165
|
if (this.runId > 0) console.warn(`tracereports: server report: ${this.reportUrl}`);
|
|
166
|
-
console.warn(`tracereports:
|
|
166
|
+
console.warn(`tracereports: local report in ${this.offlineReport}`);
|
|
167
167
|
return this.offlineReport;
|
|
168
168
|
} catch (err) {
|
|
169
169
|
console.warn(`tracereports: local report unavailable (${err.message}); evidence retained in ${this.offlineDir}. ` +
|
|
@@ -234,14 +234,14 @@ export class TraceReports {
|
|
|
234
234
|
let created = res;
|
|
235
235
|
if (!created && this.enabled && ["auto", "both"].includes(this.offlineMode) && !this.recording) {
|
|
236
236
|
// sin servidor, caído o con el token equivocado: se graba en vez de perderlo todo
|
|
237
|
-
this.goOffline(`
|
|
237
|
+
this.goOffline(`could not create the run at ${this.baseUrl} (server down or wrong token)`);
|
|
238
238
|
if (this.recording) created = await this.request("POST", "/api/v1/runs", payload);
|
|
239
239
|
}
|
|
240
240
|
if (created?.run_id > 0 && this.offlineMode === "both" && !this.recording) this.goMirror(created.run_id, payload);
|
|
241
241
|
this.runId = created?.run_id ?? null;
|
|
242
242
|
this.runCreated = Boolean(this.runId);
|
|
243
243
|
if (this.enabled && !this.runId) {
|
|
244
|
-
console.warn(`tracereports:
|
|
244
|
+
console.warn(`tracereports: could not create the run at ${this.baseUrl}; tests will continue without reporting.`);
|
|
245
245
|
}
|
|
246
246
|
return this.runId;
|
|
247
247
|
}
|
|
@@ -287,8 +287,8 @@ export class TraceReports {
|
|
|
287
287
|
return res;
|
|
288
288
|
}
|
|
289
289
|
if (this.runNotClosed) {
|
|
290
|
-
console.warn(`tracereports:
|
|
291
|
-
`(
|
|
290
|
+
console.warn(`tracereports: the server did not confirm that run #${this.runId} finished: it stays open ` +
|
|
291
|
+
`(finish it with PATCH ${this.baseUrl}/api/v1/runs/${this.runId}/finish)`);
|
|
292
292
|
}
|
|
293
293
|
return res;
|
|
294
294
|
}
|
|
@@ -411,7 +411,7 @@ export class TraceTest {
|
|
|
411
411
|
}
|
|
412
412
|
}
|
|
413
413
|
if (body.length > 100 << 20) {
|
|
414
|
-
console.warn(`tracereports: ${name || kind}
|
|
414
|
+
console.warn(`tracereports: ${name || kind} is larger than 100 MB: not attached`);
|
|
415
415
|
return false;
|
|
416
416
|
}
|
|
417
417
|
const boundary = `----tracereports${Math.random().toString(16).slice(2)}`;
|
package/src/mask.js
CHANGED
|
@@ -90,7 +90,7 @@ export async function seleniumScreenshot(driver) {
|
|
|
90
90
|
await driver.executeScript(COVER_JS, selector, MASK_COLOR, OVERLAY_ATTR);
|
|
91
91
|
covered = true;
|
|
92
92
|
} catch (err) {
|
|
93
|
-
console.warn(`tracereports:
|
|
93
|
+
console.warn(`tracereports: could not cover ${JSON.stringify(selector)} before the screenshot: ${err?.message ?? err}`);
|
|
94
94
|
return null;
|
|
95
95
|
}
|
|
96
96
|
}
|
package/src/mirror.js
CHANGED
|
@@ -20,12 +20,12 @@ export class Mirror {
|
|
|
20
20
|
fs.mkdirSync(directory, { recursive: true, mode: 0o700 });
|
|
21
21
|
this.locked(() => {
|
|
22
22
|
const marker = path.join(directory, MARKER);
|
|
23
|
-
if (fs.existsSync(marker) && JSON.parse(fs.readFileSync(marker)).raw_removed) throw new Error("
|
|
23
|
+
if (fs.existsSync(marker) && JSON.parse(fs.readFileSync(marker)).raw_removed) throw new Error("the folder only contains the report; use another folder");
|
|
24
24
|
this.recorder = new Recorder(directory);
|
|
25
25
|
this.status = `status-${process.pid}-${this.recorder.tag}.json`;
|
|
26
26
|
this.write(this.status, { complete: false, reason: "active" });
|
|
27
27
|
const m = JSON.parse(fs.readFileSync(marker));
|
|
28
|
-
if (m.mirror && m.mirror.server !== server) throw new Error("
|
|
28
|
+
if (m.mirror && m.mirror.server !== server) throw new Error("the folder belongs to another server");
|
|
29
29
|
m.mirror ||= { server, runs: [], complete: false };
|
|
30
30
|
m.mirror.complete = false;
|
|
31
31
|
this.write(MARKER, m);
|
|
@@ -39,10 +39,10 @@ export class Mirror {
|
|
|
39
39
|
} else {
|
|
40
40
|
try {
|
|
41
41
|
local = Number(fs.readFileSync(mapping, "utf8"));
|
|
42
|
-
if (!Number.isSafeInteger(local) || local >= 0) throw new Error("
|
|
42
|
+
if (!Number.isSafeInteger(local) || local >= 0) throw new Error("invalid local id");
|
|
43
43
|
} catch (err) {
|
|
44
44
|
this.failed = true;
|
|
45
|
-
console.warn(`tracereports:
|
|
45
|
+
console.warn(`tracereports: missing local id for run #${runId}: ${err.message}`);
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
if (local) this.runs.set(runId, local);
|
|
@@ -57,7 +57,7 @@ export class Mirror {
|
|
|
57
57
|
if (n >= 50) {
|
|
58
58
|
let stale = false;
|
|
59
59
|
try { stale = Date.now() - fs.statSync(lock).mtimeMs > STALE_LOCK_MS; } catch { /* ya no existe */ }
|
|
60
|
-
if (!stale) throw new Error(`${lock}
|
|
60
|
+
if (!stale) throw new Error(`${lock} is held by another process (delete it if no run uses this folder)`);
|
|
61
61
|
try { fs.rmdirSync(lock); } catch { /* otro proceso lo retiró antes */ }
|
|
62
62
|
n = 0; // huérfano: se retira y se vuelve a intentar
|
|
63
63
|
}
|
|
@@ -83,7 +83,7 @@ export class Mirror {
|
|
|
83
83
|
|
|
84
84
|
diskError(err) {
|
|
85
85
|
this.failed = true;
|
|
86
|
-
if (!this.disabled) console.warn(`tracereports:
|
|
86
|
+
if (!this.disabled) console.warn(`tracereports: stopped local copy in ${this.directory}: ${err.message}`);
|
|
87
87
|
this.disabled = true;
|
|
88
88
|
}
|
|
89
89
|
|
package/src/reporter.js
CHANGED
|
@@ -181,18 +181,18 @@ export default class TraceReportsReporter {
|
|
|
181
181
|
const problems = this.cr.deliveryProblems() + (this.cr.recording && this.cr.runId < 0 && ["auto", "both"].includes(this.cr.offlineMode) ? 1 : 0);
|
|
182
182
|
if (this.cr.recording && this.cr.runId > 0) {
|
|
183
183
|
console.log(`TraceReports: ${this.cr.reportUrl}`);
|
|
184
|
-
console.log(`TraceReports
|
|
184
|
+
console.log(`TraceReports local copy: ${this.cr.offlineReport || `tracereports report ${this.cr.offlineDir}`}`);
|
|
185
185
|
} else if (this.cr.recording) {
|
|
186
|
-
console.log(`TraceReports (
|
|
187
|
-
(this.cr.reportUrl || `\`tracereports report ${this.cr.offlineDir} -o
|
|
188
|
-
`;
|
|
186
|
+
console.log(`TraceReports (no server): evidence in ${this.cr.offlineDir}; report: ` +
|
|
187
|
+
(this.cr.reportUrl || `\`tracereports report ${this.cr.offlineDir} -o report\``) +
|
|
188
|
+
`; to upload it: \`tracereports push ${this.cr.offlineDir}\``);
|
|
189
189
|
} else if (this.cr.runId) console.log(`TraceReports: ${this.cr.reportUrl}`);
|
|
190
190
|
if (problems && (!this.cr.recording || this.cr.runId > 0)) {
|
|
191
191
|
const d = this.cr.delivery;
|
|
192
|
-
console.warn(`TraceReports:
|
|
193
|
-
`(
|
|
194
|
-
(d.runNotClosed ? ";
|
|
195
|
-
(this.strict ? "
|
|
192
|
+
console.warn(`TraceReports: warning: ${problems - d.runNotClosed} evidence events did not reach the server ` +
|
|
193
|
+
`(sent ${d.sent}, rejected ${d.rejected}, dropped ${d.dropped}, lost ${d.lost})` +
|
|
194
|
+
(d.runNotClosed ? "; the server did not confirm that the run finished: it stays open" : "") +
|
|
195
|
+
(this.strict ? " - TRACEREPORTS_STRICT: the run fails" : ""));
|
|
196
196
|
}
|
|
197
197
|
if (this.strict && (problems || (this.cr.enabled && !this.cr.runId)) && result.status === "passed") {
|
|
198
198
|
return { status: "failed" };
|
package/src/transport.js
CHANGED
|
@@ -60,11 +60,11 @@ export class Sender {
|
|
|
60
60
|
return { kind: "ok", data: text ? JSON.parse(text) : {} };
|
|
61
61
|
}
|
|
62
62
|
if (RETRYABLE.has(res.status)) return { kind: "retry" };
|
|
63
|
-
const hint = res.status === 401 ? " (
|
|
63
|
+
const hint = res.status === 401 ? " (set the token: new TraceReports({ token }), the TRACEREPORTS_TOKEN variable or TRACEREPORTS_TOKEN in the project .env)" : "";
|
|
64
64
|
console.warn(`tracereports: ${item.method} ${item.path} -> HTTP ${res.status} ${text.slice(0, 300)}${hint}`);
|
|
65
65
|
return { kind: "reject" };
|
|
66
66
|
} catch (err) {
|
|
67
|
-
if (!this.serverDown()) console.warn(`tracereports: ${item.method} ${item.path}
|
|
67
|
+
if (!this.serverDown()) console.warn(`tracereports: ${item.method} ${item.path} failed: ${err.cause?.code || err.message}`);
|
|
68
68
|
this.downUntil = Date.now() + limits.circuitMs;
|
|
69
69
|
return { kind: "retry" };
|
|
70
70
|
}
|
|
@@ -92,7 +92,7 @@ export class Sender {
|
|
|
92
92
|
const size = body?.length ?? 0;
|
|
93
93
|
if (this.pending + 1 > this.maxItems || this.bytes + size > this.maxBytes) {
|
|
94
94
|
if (this.stats.dropped++ === 0) {
|
|
95
|
-
console.warn(`tracereports:
|
|
95
|
+
console.warn(`tracereports: the send queue is full (${this.maxItems} events); new events are dropped`);
|
|
96
96
|
}
|
|
97
97
|
return false;
|
|
98
98
|
}
|
|
@@ -178,7 +178,7 @@ export class Sender {
|
|
|
178
178
|
}
|
|
179
179
|
this.notify();
|
|
180
180
|
if (items.length) {
|
|
181
|
-
console.warn(`tracereports: ${items.length}
|
|
181
|
+
console.warn(`tracereports: ${items.length} evidence events could not be sent and were lost`);
|
|
182
182
|
}
|
|
183
183
|
return items.length;
|
|
184
184
|
}
|