@mostajs/mjs-unit 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.mjs +40 -3
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -2
- package/dist/index.js.map +1 -1
- package/dist/report.d.ts +36 -0
- package/dist/report.d.ts.map +1 -0
- package/dist/report.js +67 -0
- package/dist/report.js.map +1 -0
- package/llms.txt +18 -3
- package/package.json +9 -3
package/bin/cli.mjs
CHANGED
|
@@ -2,24 +2,61 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* @mostajs/mjs-unit — runner CLI. Active le resolver (imports sans extension), importe les fichiers
|
|
4
4
|
* de test passés en argument (chacun enregistre ses cas via `test()`), puis exécute.
|
|
5
|
-
*
|
|
5
|
+
*
|
|
6
|
+
* Usage : mjs-unit <fichier-de-test...> [options]
|
|
7
|
+
* --report[=fichier] écrit une preuve HTML (défaut : test-report.html)
|
|
8
|
+
* --json[=fichier] écrit un rapport JSON (défaut : test-report.json)
|
|
9
|
+
* --title="…" titre du rapport HTML
|
|
10
|
+
*
|
|
6
11
|
* @author Dr Hamid MADANI <drmdh@msn.com> · AGPL-3.0-or-later
|
|
7
12
|
*/
|
|
8
13
|
import { register } from "node:module";
|
|
9
14
|
import { pathToFileURL } from "node:url";
|
|
15
|
+
import { writeFileSync } from "node:fs";
|
|
10
16
|
|
|
11
17
|
register(new URL("../loader.mjs", import.meta.url));
|
|
12
18
|
const { run, pending } = await import("../dist/index.js");
|
|
13
19
|
|
|
14
|
-
|
|
15
|
-
|
|
20
|
+
// ── Découpe arguments / options ──────────────────────────────────────────────
|
|
21
|
+
const argv = process.argv.slice(2);
|
|
22
|
+
const opt = (name) => {
|
|
23
|
+
const hit = argv.find((a) => a === `--${name}` || a.startsWith(`--${name}=`));
|
|
24
|
+
if (!hit) return undefined;
|
|
25
|
+
const eq = hit.indexOf("=");
|
|
26
|
+
return eq === -1 ? "" : hit.slice(eq + 1);
|
|
27
|
+
};
|
|
28
|
+
const htmlOut = opt("report"); // "" si présent sans valeur, undefined si absent
|
|
29
|
+
const jsonOut = opt("json");
|
|
30
|
+
const title = opt("title");
|
|
31
|
+
const files = argv.filter((a) => !a.startsWith("--"));
|
|
32
|
+
if (!files.length) { console.error("usage: mjs-unit <fichier-de-test...> [--report[=f]] [--json[=f]]"); process.exit(2); }
|
|
16
33
|
|
|
34
|
+
// ── Exécution, une suite par fichier ─────────────────────────────────────────
|
|
17
35
|
let totalFail = 0;
|
|
36
|
+
const suites = [];
|
|
18
37
|
for (const f of files) {
|
|
19
38
|
await import(pathToFileURL(f).href); // le fichier enregistre ses cas (et peut appeler run() lui-même)
|
|
20
39
|
if (pending() > 0) { // sinon, on exécute les cas restants groupés par fichier
|
|
21
40
|
const r = await run(f);
|
|
22
41
|
totalFail += r.failed;
|
|
42
|
+
suites.push({ file: f, results: r.results });
|
|
23
43
|
}
|
|
24
44
|
}
|
|
45
|
+
|
|
46
|
+
// ── Reporters optionnels ─────────────────────────────────────────────────────
|
|
47
|
+
if (htmlOut !== undefined || jsonOut !== undefined) {
|
|
48
|
+
const { renderHtmlReport, renderJsonReport } = await import("../dist/report.js");
|
|
49
|
+
const report = { suites, generatedAt: new Date().toISOString(), title: title || undefined };
|
|
50
|
+
if (htmlOut !== undefined) {
|
|
51
|
+
const out = htmlOut || "test-report.html";
|
|
52
|
+
writeFileSync(out, renderHtmlReport(report));
|
|
53
|
+
console.log(`\n📄 Preuve HTML : ${out}`);
|
|
54
|
+
}
|
|
55
|
+
if (jsonOut !== undefined) {
|
|
56
|
+
const out = jsonOut || "test-report.json";
|
|
57
|
+
writeFileSync(out, renderJsonReport(report));
|
|
58
|
+
console.log(`📄 Rapport JSON : ${out}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
25
62
|
if (totalFail > 0) process.exitCode = 1;
|
package/dist/index.d.ts
CHANGED
|
@@ -31,10 +31,19 @@ export declare function expect(actual: unknown): {
|
|
|
31
31
|
toBeFalsy: (m?: string) => void;
|
|
32
32
|
toContain: (sub: string, m?: string) => void;
|
|
33
33
|
};
|
|
34
|
+
/** Issue d'un cas de test (consommé par les reporters, ex. `./report`). */
|
|
35
|
+
export interface TestResult {
|
|
36
|
+
name: string;
|
|
37
|
+
status: "pass" | "fail" | "skip";
|
|
38
|
+
error?: string;
|
|
39
|
+
durationMs: number;
|
|
40
|
+
}
|
|
34
41
|
export interface RunResult {
|
|
35
42
|
passed: number;
|
|
36
43
|
failed: number;
|
|
37
44
|
skipped: number;
|
|
45
|
+
label: string;
|
|
46
|
+
results: TestResult[];
|
|
38
47
|
}
|
|
39
48
|
/** Exécute les tests enregistrés, affiche le rapport, positionne `process.exitCode` si échec. */
|
|
40
49
|
export declare function run(label?: string): Promise<RunResult>;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,QAAQ;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE;AAI1F,gDAAgD;AAChD,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAEvE;yBAFe,IAAI;qBAID,MAAM,MAAM,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAG,IAAI;;AAEhE,yCAAyC;AACzC,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,IAAI,GAAG,IAAI,CAI9D;AAMD,wBAAgB,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,SAAiB,GAAG,IAAI,CAEhE;AACD,wBAAgB,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAEhF;AACD,wBAAgB,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAEpF;AACD,wBAAsB,WAAW,CAAC,EAAE,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,SAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAGrG;AACD,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,SAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAElH;AAED,2FAA2F;AAC3F,wBAAgB,MAAM,CAAC,MAAM,EAAE,OAAO;cAExB,OAAO,MAAM,MAAM;iBAChB,OAAO,MAAM,MAAM;qBACf,MAAM;oBACP,MAAM;qBACL,MAAM,MAAM,MAAM;EAEtC;AAGD,MAAM,WAAW,SAAS;IAAG,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,QAAQ;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE;AAI1F,gDAAgD;AAChD,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAEvE;yBAFe,IAAI;qBAID,MAAM,MAAM,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAG,IAAI;;AAEhE,yCAAyC;AACzC,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,IAAI,GAAG,IAAI,CAI9D;AAMD,wBAAgB,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,SAAiB,GAAG,IAAI,CAEhE;AACD,wBAAgB,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAEhF;AACD,wBAAgB,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAEpF;AACD,wBAAsB,WAAW,CAAC,EAAE,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,SAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAGrG;AACD,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,SAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAElH;AAED,2FAA2F;AAC3F,wBAAgB,MAAM,CAAC,MAAM,EAAE,OAAO;cAExB,OAAO,MAAM,MAAM;iBAChB,OAAO,MAAM,MAAM;qBACf,MAAM;oBACP,MAAM;qBACL,MAAM,MAAM,MAAM;EAEtC;AAGD,2EAA2E;AAC3E,MAAM,WAAW,UAAU;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE;AAClH,MAAM,WAAW,SAAS;IAAG,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,UAAU,EAAE,CAAA;CAAE;AAIpH,iGAAiG;AACjG,wBAAsB,GAAG,CAAC,KAAK,SAAK,GAAG,OAAO,CAAC,SAAS,CAAC,CAcxD;AAED,+CAA+C;AAC/C,wBAAgB,OAAO,IAAI,MAAM,CAA0B"}
|
package/dist/index.js
CHANGED
|
@@ -69,32 +69,41 @@ export function expect(actual) {
|
|
|
69
69
|
toContain: (sub, m) => ok(typeof actual === "string" && actual.includes(sub), m ?? `« ${fmt(actual)} » ne contient pas « ${sub} »`),
|
|
70
70
|
};
|
|
71
71
|
}
|
|
72
|
+
const _now = () => (typeof performance !== "undefined" ? performance.now() : Date.now());
|
|
72
73
|
/** Exécute les tests enregistrés, affiche le rapport, positionne `process.exitCode` si échec. */
|
|
73
74
|
export async function run(label = "") {
|
|
74
75
|
let passed = 0, failed = 0, skipped = 0;
|
|
76
|
+
const results = [];
|
|
75
77
|
if (label)
|
|
76
78
|
console.log(`\n▶ ${label}`);
|
|
77
79
|
for (const t of _suite) {
|
|
78
80
|
if (t.skip) {
|
|
79
81
|
console.log(` ⊘ ${t.name} (ignoré)`);
|
|
80
82
|
skipped++;
|
|
83
|
+
results.push({ name: t.name, status: "skip", durationMs: 0 });
|
|
81
84
|
continue;
|
|
82
85
|
}
|
|
86
|
+
const t0 = _now();
|
|
83
87
|
try {
|
|
84
88
|
await t.fn();
|
|
89
|
+
const d = _now() - t0;
|
|
85
90
|
console.log(` ✓ ${t.name}`);
|
|
86
91
|
passed++;
|
|
92
|
+
results.push({ name: t.name, status: "pass", durationMs: d });
|
|
87
93
|
}
|
|
88
94
|
catch (e) {
|
|
89
|
-
|
|
95
|
+
const d = _now() - t0;
|
|
96
|
+
const msg = e?.message ?? String(e);
|
|
97
|
+
console.log(` ✗ ${t.name}\n ${msg}`);
|
|
90
98
|
failed++;
|
|
99
|
+
results.push({ name: t.name, status: "fail", error: msg, durationMs: d });
|
|
91
100
|
}
|
|
92
101
|
}
|
|
93
102
|
console.log(`\n${failed === 0 ? "✅" : "❌"} ${passed} passé(s), ${failed} échoué(s)${skipped ? `, ${skipped} ignoré(s)` : ""}`);
|
|
94
103
|
if (failed > 0 && typeof process !== "undefined")
|
|
95
104
|
process.exitCode = 1;
|
|
96
105
|
_suite.length = 0; // réinitialise pour un éventuel run suivant
|
|
97
|
-
return { passed, failed, skipped };
|
|
106
|
+
return { passed, failed, skipped, label, results };
|
|
98
107
|
}
|
|
99
108
|
/** Nombre de tests en attente (diagnostic). */
|
|
100
109
|
export function pending() { return _suite.length; }
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,MAAM,GAAe,EAAE,CAAC;AAE9B,gDAAgD;AAChD,MAAM,UAAU,IAAI,CAAC,IAAY,EAAE,EAA8B;IAC/D,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;AAC5B,CAAC;AACD,mCAAmC;AACnC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAY,EAAE,EAA8B,EAAQ,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAE/G,yCAAyC;AACzC,MAAM,UAAU,QAAQ,CAAC,KAAa,EAAE,IAAgB;IACtD,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC;IAC5B,IAAI,EAAE,CAAC;IACP,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,GAAG,KAAK,MAAM,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AAC9F,CAAC;AAED,gFAAgF;AAChF,MAAM,cAAe,SAAQ,KAAK;IAAG,YAAY,CAAS,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC,CAAC,CAAC;CAAE;AACzG,MAAM,GAAG,GAAG,CAAC,CAAU,EAAE,EAAE,GAAG,IAAI,CAAC;IAAC,OAAO,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAAC,CAAC;AAAC,MAAM,CAAC;IAAC,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;AAAC,CAAC,CAAC,CAAC,CAAC;AAE1H,MAAM,UAAU,EAAE,CAAC,IAAa,EAAE,OAAO,GAAG,cAAc;IACxD,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,cAAc,CAAC,OAAO,CAAC,CAAC;AAC/C,CAAC;AACD,MAAM,UAAU,KAAK,CAAC,MAAe,EAAE,QAAiB,EAAE,OAAgB;IACxE,IAAI,MAAM,KAAK,QAAQ;QAAE,MAAM,IAAI,cAAc,CAAC,OAAO,IAAI,WAAW,GAAG,CAAC,QAAQ,CAAC,UAAU,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAChH,CAAC;AACD,MAAM,UAAU,SAAS,CAAC,MAAe,EAAE,QAAiB,EAAE,OAAgB;IAC5E,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;QAAE,MAAM,IAAI,cAAc,CAAC,OAAO,IAAI,WAAW,GAAG,CAAC,QAAQ,CAAC,UAAU,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAChJ,CAAC;AACD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,EAA0B,EAAE,OAAO,GAAG,cAAc;IACpF,IAAI,CAAC;QAAC,MAAM,EAAE,EAAE,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO;IAAC,CAAC;IACrC,MAAM,IAAI,cAAc,CAAC,OAAO,CAAC,CAAC;AACpC,CAAC;AACD,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,EAA0B,EAAE,OAAO,GAAG,qBAAqB;IACjG,IAAI,CAAC;QAAC,MAAM,EAAE,EAAE,CAAC;IAAC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QAAC,MAAM,IAAI,cAAc,CAAC,GAAG,OAAO,MAAO,CAAW,EAAE,OAAO,EAAE,CAAC,CAAC;IAAC,CAAC;AACtG,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,MAAM,CAAC,MAAe;IACpC,OAAO;QACL,IAAI,EAAE,CAAC,CAAU,EAAE,CAAU,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;QACrD,OAAO,EAAE,CAAC,CAAU,EAAE,CAAU,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;QAC5D,UAAU,EAAE,CAAC,CAAU,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC;QACzC,SAAS,EAAE,CAAC,CAAU,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,eAAe,CAAC;QAC5D,SAAS,EAAE,CAAC,GAAW,EAAE,CAAU,EAAE,EAAE,CAAC,EAAE,CAAC,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,KAAK,GAAG,CAAC,MAAM,CAAC,wBAAwB,GAAG,IAAI,CAAC;KACrJ,CAAC;AACJ,CAAC;AAOD,MAAM,IAAI,GAAG,GAAW,EAAE,CAAC,CAAC,OAAO,WAAW,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;AAEjG,iGAAiG;AACjG,MAAM,CAAC,KAAK,UAAU,GAAG,CAAC,KAAK,GAAG,EAAE;IAClC,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC;IACxC,MAAM,OAAO,GAAiB,EAAE,CAAC;IACjC,IAAI,KAAK;QAAE,OAAO,CAAC,GAAG,CAAC,OAAO,KAAK,EAAE,CAAC,CAAC;IACvC,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;YAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,WAAW,CAAC,CAAC;YAAC,OAAO,EAAE,CAAC;YAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;YAAC,SAAS;QAAC,CAAC;QAC1I,MAAM,EAAE,GAAG,IAAI,EAAE,CAAC;QAClB,IAAI,CAAC;YAAC,MAAM,CAAC,CAAC,EAAE,EAAE,CAAC;YAAC,MAAM,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,CAAC;YAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YAAC,MAAM,EAAE,CAAC;YAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;QAAC,CAAC;QACnJ,OAAO,CAAC,EAAE,CAAC;YAAC,MAAM,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,CAAC;YAAC,MAAM,GAAG,GAAI,CAAW,EAAE,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;YAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,WAAW,GAAG,EAAE,CAAC,CAAC;YAAC,MAAM,EAAE,CAAC;YAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;QAAC,CAAC;IACvN,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,MAAM,cAAc,MAAM,aAAa,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC/H,IAAI,MAAM,GAAG,CAAC,IAAI,OAAO,OAAO,KAAK,WAAW;QAAE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,4CAA4C;IAC/D,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AACrD,CAAC;AAED,+CAA+C;AAC/C,MAAM,UAAU,OAAO,KAAa,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC"}
|
package/dist/report.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @mostajs/mjs-unit/report — Reporters de preuve de test (HTML & JSON).
|
|
3
|
+
*
|
|
4
|
+
* Fonctions PURES : prennent un agrégat de résultats (`TestReport`) et rendent
|
|
5
|
+
* une chaîne. Aucune E/S, aucun accès disque — l'appelant (CLI ou script) écrit
|
|
6
|
+
* le fichier. Réutilisable par tout module @mostajs/* : plus de `report.mjs`
|
|
7
|
+
* dupliqué par dépôt.
|
|
8
|
+
*
|
|
9
|
+
* @author Dr Hamid MADANI <drmdh@msn.com>
|
|
10
|
+
* @license AGPL-3.0-or-later
|
|
11
|
+
*/
|
|
12
|
+
import type { TestResult } from "./index";
|
|
13
|
+
/** Une suite = les résultats d'un fichier de test. */
|
|
14
|
+
export interface ReportSuite {
|
|
15
|
+
file: string;
|
|
16
|
+
results: TestResult[];
|
|
17
|
+
}
|
|
18
|
+
/** Agrégat rendu par les reporters. */
|
|
19
|
+
export interface TestReport {
|
|
20
|
+
suites: ReportSuite[];
|
|
21
|
+
generatedAt: string;
|
|
22
|
+
title?: string;
|
|
23
|
+
}
|
|
24
|
+
/** Totaux sur l'ensemble des suites. */
|
|
25
|
+
export declare function summarize(report: TestReport): {
|
|
26
|
+
total: number;
|
|
27
|
+
suites: number;
|
|
28
|
+
passed: number;
|
|
29
|
+
failed: number;
|
|
30
|
+
skipped: number;
|
|
31
|
+
};
|
|
32
|
+
/** Rapport JSON structuré (machine-lisible, ex. CI). */
|
|
33
|
+
export declare function renderJsonReport(report: TestReport): string;
|
|
34
|
+
/** Rapport HTML autonome (thème sombre, cartes de synthèse + tables par suite). */
|
|
35
|
+
export declare function renderHtmlReport(report: TestReport): string;
|
|
36
|
+
//# sourceMappingURL=report.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C,sDAAsD;AACtD,MAAM,WAAW,WAAW;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,UAAU,EAAE,CAAA;CAAE;AACpE,uCAAuC;AACvC,MAAM,WAAW,UAAU;IAAG,MAAM,EAAE,WAAW,EAAE,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE;AAW1F,wCAAwC;AACxC,wBAAgB,SAAS,CAAC,MAAM,EAAE,UAAU;;;;;;EAG3C;AAED,wDAAwD;AACxD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAE3D;AAED,mFAAmF;AACnF,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAmD3D"}
|
package/dist/report.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
const esc = (s) => String(s).replace(/[&<>"]/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """ }[c]));
|
|
2
|
+
const tally = (results) => ({
|
|
3
|
+
passed: results.filter((r) => r.status === "pass").length,
|
|
4
|
+
failed: results.filter((r) => r.status === "fail").length,
|
|
5
|
+
skipped: results.filter((r) => r.status === "skip").length,
|
|
6
|
+
});
|
|
7
|
+
/** Totaux sur l'ensemble des suites. */
|
|
8
|
+
export function summarize(report) {
|
|
9
|
+
const all = report.suites.flatMap((s) => s.results);
|
|
10
|
+
return { ...tally(all), total: all.length, suites: report.suites.length };
|
|
11
|
+
}
|
|
12
|
+
/** Rapport JSON structuré (machine-lisible, ex. CI). */
|
|
13
|
+
export function renderJsonReport(report) {
|
|
14
|
+
return JSON.stringify({ ...report, summary: summarize(report) }, null, 2);
|
|
15
|
+
}
|
|
16
|
+
/** Rapport HTML autonome (thème sombre, cartes de synthèse + tables par suite). */
|
|
17
|
+
export function renderHtmlReport(report) {
|
|
18
|
+
const sum = summarize(report);
|
|
19
|
+
const title = report.title ?? "@mostajs — Preuve de test";
|
|
20
|
+
const accent = sum.failed ? "#ef4444" : "#22c55e";
|
|
21
|
+
const icon = (s) => (s === "pass" ? "✓" : s === "fail" ? "✗" : "⊘");
|
|
22
|
+
const suiteHtml = report.suites
|
|
23
|
+
.map((s) => {
|
|
24
|
+
const t = tally(s.results);
|
|
25
|
+
const ok = t.failed === 0;
|
|
26
|
+
const rows = s.results
|
|
27
|
+
.map((r) => {
|
|
28
|
+
const dur = r.durationMs ? `<span class="dur">${r.durationMs.toFixed(1)} ms</span>` : "";
|
|
29
|
+
const main = `<tr class="${r.status}"><td>${icon(r.status)}</td><td>${esc(r.name)} ${dur}</td></tr>`;
|
|
30
|
+
return r.status === "fail" ? main + `<tr class="err"><td></td><td>${esc(r.error ?? "")}</td></tr>` : main;
|
|
31
|
+
})
|
|
32
|
+
.join("");
|
|
33
|
+
return `<section><h2>${esc(s.file)} <span class="badge ${ok ? "ok" : "ko"}">${t.passed}/${s.results.length}</span></h2><table>${rows}</table></section>`;
|
|
34
|
+
})
|
|
35
|
+
.join("");
|
|
36
|
+
return `<!doctype html><html lang="fr"><head><meta charset="utf-8">
|
|
37
|
+
<title>${esc(title)}</title>
|
|
38
|
+
<style>
|
|
39
|
+
body{font-family:system-ui,Segoe UI,Arial,sans-serif;margin:0;background:#0f172a;color:#e2e8f0}
|
|
40
|
+
header{padding:24px 32px;background:#1e293b;border-bottom:3px solid ${accent}}
|
|
41
|
+
h1{margin:0 0 4px;font-size:1.3rem}.sub{color:#94a3b8;font-size:.85rem}
|
|
42
|
+
.summary{display:flex;gap:16px;margin-top:16px;flex-wrap:wrap}
|
|
43
|
+
.card{background:#0b1220;border:1px solid #334155;border-radius:10px;padding:12px 18px;min-width:90px}
|
|
44
|
+
.card .n{font-size:1.6rem;font-weight:700}.card.ok .n{color:#22c55e}.card.ko .n{color:#ef4444}
|
|
45
|
+
main{padding:24px 32px;max-width:960px}section{margin-bottom:20px}
|
|
46
|
+
h2{font-size:1rem;border-bottom:1px solid #334155;padding-bottom:6px}
|
|
47
|
+
.badge{font-size:.75rem;padding:2px 8px;border-radius:999px;background:#22c55e22;color:#22c55e}.badge.ko{background:#ef444422;color:#ef4444}
|
|
48
|
+
table{width:100%;border-collapse:collapse;font-size:.9rem}td{padding:4px 8px;border-bottom:1px solid #1e293b;vertical-align:top}
|
|
49
|
+
td:first-child{width:24px;text-align:center;font-weight:700}
|
|
50
|
+
tr.pass td:first-child{color:#22c55e}tr.fail td:first-child{color:#ef4444}tr.skip td:first-child{color:#94a3b8}
|
|
51
|
+
tr.err td{color:#fca5a5;font-family:monospace;font-size:.8rem}.dur{color:#64748b;font-size:.75rem}
|
|
52
|
+
footer{padding:16px 32px;color:#64748b;font-size:.8rem}
|
|
53
|
+
</style></head><body>
|
|
54
|
+
<header><h1>${esc(title)}</h1>
|
|
55
|
+
<div class="sub">Généré le ${esc(report.generatedAt)} · moteur @mostajs/mjs-unit</div>
|
|
56
|
+
<div class="summary">
|
|
57
|
+
<div class="card"><div class="n">${sum.total}</div><div>tests</div></div>
|
|
58
|
+
<div class="card ok"><div class="n">${sum.passed}</div><div>réussis</div></div>
|
|
59
|
+
<div class="card ko"><div class="n">${sum.failed}</div><div>échoués</div></div>
|
|
60
|
+
${sum.skipped ? `<div class="card"><div class="n">${sum.skipped}</div><div>ignorés</div></div>` : ""}
|
|
61
|
+
<div class="card"><div class="n">${sum.suites}</div><div>suites</div></div>
|
|
62
|
+
</div></header>
|
|
63
|
+
<main>${suiteHtml}</main>
|
|
64
|
+
<footer>Auteur : Dr Hamid MADANI <drmdh@msn.com> · AGPL-3.0-or-later</footer>
|
|
65
|
+
</body></html>`;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"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"}
|
package/llms.txt
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> Micro-framework de test ZÉRO DÉPENDANCE pour l'écosystème @mostajs/* : API test/expect, runner CLI,
|
|
4
4
|
> et un resolver ESM qui exécute sous Node les dist à imports SANS extension (moduleResolution=bundler).
|
|
5
5
|
|
|
6
|
-
- Version: 0.
|
|
6
|
+
- Version: 0.3.0 · Licence: AGPL-3.0-or-later · Auteur: Dr Hamid MADANI <drmdh@msn.com>
|
|
7
7
|
- Chemin: mostajs/mosta-mjs-unit
|
|
8
8
|
|
|
9
9
|
## RÔLE
|
|
@@ -14,13 +14,20 @@ réécrit `./x` → `./x.js` puis `./x/index.js`.
|
|
|
14
14
|
|
|
15
15
|
## EXPORTS
|
|
16
16
|
- `.` (dist/index.js) : test, test.skip, describe, expect, ok, equal, deepEqual, throwsAsync,
|
|
17
|
-
doesNotThrowAsync, run, pending ;
|
|
17
|
+
doesNotThrowAsync, run, pending ; types TestCase, RunResult, TestResult.
|
|
18
|
+
`run()` retourne désormais `results: TestResult[]` (name, status pass|fail|skip, error?, durationMs).
|
|
19
|
+
- `./report` (dist/report.js) : reporters de PREUVE de test, fonctions PURES (zéro E/S) —
|
|
20
|
+
renderHtmlReport(report), renderJsonReport(report), summarize(report) ;
|
|
21
|
+
types TestReport {suites:{file,results}[], generatedAt, title?}, ReportSuite.
|
|
22
|
+
Centralise la génération de `test-report.html` : plus de `report.mjs` dupliqué par dépôt.
|
|
18
23
|
- `./web` (dist/web.js) : moteur de test web GÉNÉRIQUE, zéro dépendance (node:http/net) —
|
|
19
24
|
startServer, createHttpTester, fetchRequest, waitForEvent ; types TestServer, HttpTester,
|
|
20
25
|
TestResponse, RequestOptions, MinimalEmitter.
|
|
21
26
|
- `./register` (register.mjs) : enregistre le resolver via `node --import`.
|
|
22
27
|
- `./loader` (loader.mjs) : le hook `resolve` (pour usage avancé).
|
|
23
28
|
- bin `mjs-unit` (bin/cli.mjs) : runner — active le resolver, importe les fichiers, exécute.
|
|
29
|
+
Options : `--report[=fichier]` (preuve HTML, défaut test-report.html), `--json[=fichier]`,
|
|
30
|
+
`--title="…"`. Ex. : `mjs-unit test-scripts/*.test.mjs --report --title="Mon module"`.
|
|
24
31
|
|
|
25
32
|
## API
|
|
26
33
|
- test(name, fn): void // fn sync ou async ; enregistre un cas
|
|
@@ -29,9 +36,17 @@ réécrit `./x` → `./x.js` puis `./x/index.js`.
|
|
|
29
36
|
- expect(v): { toBe(e), toEqual(e), toBeTruthy(), toBeFalsy(), toContain(sub) }
|
|
30
37
|
- ok(cond, msg?) · equal(a, e, msg?) · deepEqual(a, e, msg?)
|
|
31
38
|
- throwsAsync(fn, msg?) · doesNotThrowAsync(fn, msg?)
|
|
32
|
-
- run(label?): Promise<{passed, failed, skipped}> // exécute les cas
|
|
39
|
+
- run(label?): Promise<{passed, failed, skipped, label, results}> // exécute les cas ; exitCode=1 si échec
|
|
40
|
+
results: { name, status: 'pass'|'fail'|'skip', error?, durationMs }[] // consommé par ./report
|
|
33
41
|
- pending(): number
|
|
34
42
|
|
|
43
|
+
## API — REPORT (./report, preuve de test, fonctions pures)
|
|
44
|
+
- renderHtmlReport(report: TestReport): string // document HTML autonome (thème sombre, cartes + tables par suite, durées, échappement anti-injection)
|
|
45
|
+
- renderJsonReport(report: TestReport): string // JSON { ...report, summary }
|
|
46
|
+
- summarize(report): { passed, failed, skipped, total, suites }
|
|
47
|
+
- TestReport = { suites: { file, results: TestResult[] }[], generatedAt: string, title?: string }
|
|
48
|
+
L'appelant écrit le fichier ; le CLI le fait via `--report`/`--json`.
|
|
49
|
+
|
|
35
50
|
## API — WEB (./web, générique, zéro dépendance)
|
|
36
51
|
- startServer(target): Promise<TestServer> // target = http.Server | RequestListener | app Express
|
|
37
52
|
→ { url, port, server, close() } ; écoute sur 127.0.0.1:0 ; close() ne ferme que les serveurs créés par mjs-unit
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mostajs/mjs-unit",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Micro-framework de test pour l'écosystème @mostajs/* : zéro dépendance, API minimale (test/expect/run), runner CLI, et un resolver ESM qui exécute sous Node les dist à imports sans extension (convention moduleResolution=bundler).",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Micro-framework de test pour l'écosystème @mostajs/* : zéro dépendance, API minimale (test/expect/run), runner CLI (preuves HTML/JSON via --report), reporters réutilisables (./report), et un resolver ESM qui exécute sous Node les dist à imports sans extension (convention moduleResolution=bundler).",
|
|
5
5
|
"author": "Dr Hamid MADANI <drmdh@msn.com>",
|
|
6
6
|
"license": "AGPL-3.0-or-later",
|
|
7
7
|
"type": "module",
|
|
@@ -21,6 +21,11 @@
|
|
|
21
21
|
"import": "./dist/web.js",
|
|
22
22
|
"default": "./dist/web.js"
|
|
23
23
|
},
|
|
24
|
+
"./report": {
|
|
25
|
+
"types": "./dist/report.d.ts",
|
|
26
|
+
"import": "./dist/report.js",
|
|
27
|
+
"default": "./dist/report.js"
|
|
28
|
+
},
|
|
24
29
|
"./register": {
|
|
25
30
|
"default": "./register.mjs"
|
|
26
31
|
},
|
|
@@ -39,7 +44,8 @@
|
|
|
39
44
|
],
|
|
40
45
|
"scripts": {
|
|
41
46
|
"build": "tsc -p tsconfig.json",
|
|
42
|
-
"test": "bash test-scripts/run-tests.sh"
|
|
47
|
+
"test": "bash test-scripts/run-tests.sh",
|
|
48
|
+
"report": "npm run build && node bin/cli.mjs test-scripts/*.test.mjs --report=test-report.html --title=\"@mostajs/mjs-unit — auto-preuve\""
|
|
43
49
|
},
|
|
44
50
|
"devDependencies": {
|
|
45
51
|
"typescript": "^5.6.0",
|