@nzila/sdk 0.1.3 → 0.1.5
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/README.md +21 -0
- package/dist/collect-vitest-tests.d.ts +5 -0
- package/dist/collect-vitest-tests.d.ts.map +1 -0
- package/dist/collect-vitest-tests.js +53 -0
- package/dist/deliver.d.ts +2 -0
- package/dist/deliver.d.ts.map +1 -1
- package/dist/deliver.js +12 -1
- package/dist/jest-reporter.d.ts.map +1 -1
- package/dist/jest-reporter.js +8 -3
- package/dist/reporter-options.d.ts +6 -0
- package/dist/reporter-options.d.ts.map +1 -0
- package/dist/reporter-options.js +10 -0
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/vitest-reporter.d.ts +6 -22
- package/dist/vitest-reporter.d.ts.map +1 -1
- package/dist/vitest-reporter.js +30 -29
- package/jest.cjs +29 -0
- package/jest.d.ts +2 -0
- package/mocha.d.ts +2 -0
- package/package.json +32 -11
- package/react.d.ts +1 -0
- package/runtime.d.ts +1 -0
- package/vitest.d.ts +2 -0
package/README.md
CHANGED
|
@@ -11,6 +11,27 @@ npm install @nzila/sdk
|
|
|
11
11
|
# Vitest projects also need vitest as a peer
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
+
### TypeScript
|
|
15
|
+
|
|
16
|
+
Subpaths such as `@nzila/sdk/vitest` need **`moduleResolution`** set to **`bundler`**, **`node16`**, or **`nodenext`** (recommended for Vitest/Vite repos). If you still use legacy `"node"` resolution, upgrade to one of those options in `tsconfig.json`:
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"compilerOptions": {
|
|
21
|
+
"moduleResolution": "bundler"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`@nzila/sdk@0.1.4+` also ships root `.d.ts` shims and `typesVersions` for broader editor support.
|
|
27
|
+
|
|
28
|
+
### Reporters not sending?
|
|
29
|
+
|
|
30
|
+
1. Set **`NZILA_WEBHOOK_URL`**, **`NZILA_API_KEY`**, and **`NZILA_APP_NAME`** (must match the project app name in the dashboard), or pass them in the reporter constructor.
|
|
31
|
+
2. Run with **`NZILA_DEBUG=1`** to see skip/send messages on stderr (reporters are silent by default).
|
|
32
|
+
3. **Vitest 3+** uses `onTestRunEnd` — use `@nzila/sdk@0.1.5+`.
|
|
33
|
+
4. **Jest** with `jest.config.cjs`: use `reporters: [["@nzila/sdk/jest", { … }]]` (CJS entry is included).
|
|
34
|
+
|
|
14
35
|
## CLI (onboarding)
|
|
15
36
|
|
|
16
37
|
`npx @nzila/sdk` opens the [Nzila dashboard](https://nzila-kappa.vercel.app) and prints setup commands. No separate CLI package.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { TestModule } from "vitest/node";
|
|
2
|
+
import type { NzilaClientOptions, NzilaTestCase } from "./types.js";
|
|
3
|
+
/** Collect finished tests from Vitest 3+ `TestModule` reporters API. */
|
|
4
|
+
export declare function collectTestsFromVitestModules(modules: ReadonlyArray<TestModule>, options: NzilaClientOptions, runStartedAt: Date): NzilaTestCase[];
|
|
5
|
+
//# sourceMappingURL=collect-vitest-tests.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collect-vitest-tests.d.ts","sourceRoot":"","sources":["../src/collect-vitest-tests.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAY,UAAU,EAAa,MAAM,aAAa,CAAC;AACnE,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAmB,MAAM,YAAY,CAAC;AAmBrF,wEAAwE;AACxE,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,aAAa,CAAC,UAAU,CAAC,EAClC,OAAO,EAAE,kBAAkB,EAC3B,YAAY,EAAE,IAAI,GACjB,aAAa,EAAE,CAuCjB"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
function describePathFor(test) {
|
|
2
|
+
const path = [];
|
|
3
|
+
let parent = test.parent;
|
|
4
|
+
while (parent.type === "suite") {
|
|
5
|
+
path.unshift(parent.name);
|
|
6
|
+
parent = parent.parent;
|
|
7
|
+
}
|
|
8
|
+
return path;
|
|
9
|
+
}
|
|
10
|
+
function mapStatus(state) {
|
|
11
|
+
if (state === "passed")
|
|
12
|
+
return "passed";
|
|
13
|
+
if (state === "failed")
|
|
14
|
+
return "failed";
|
|
15
|
+
if (state === "skipped")
|
|
16
|
+
return "skipped";
|
|
17
|
+
return "pending";
|
|
18
|
+
}
|
|
19
|
+
/** Collect finished tests from Vitest 3+ `TestModule` reporters API. */
|
|
20
|
+
export function collectTestsFromVitestModules(modules, options, runStartedAt) {
|
|
21
|
+
const framework = options.framework ?? "vitest";
|
|
22
|
+
const tests = [];
|
|
23
|
+
const now = new Date().toISOString();
|
|
24
|
+
for (const mod of modules) {
|
|
25
|
+
for (const test of mod.children.allTests()) {
|
|
26
|
+
const result = test.result();
|
|
27
|
+
if (result.state === "pending")
|
|
28
|
+
continue;
|
|
29
|
+
const describePath = describePathFor(test);
|
|
30
|
+
const feature = options.mapFeature?.(describePath, test.name) ??
|
|
31
|
+
describePath[0] ??
|
|
32
|
+
"general";
|
|
33
|
+
const errors = result.errors?.map((e) => ({
|
|
34
|
+
message: e.message ?? String(e),
|
|
35
|
+
stack: e.stack,
|
|
36
|
+
})) ?? [];
|
|
37
|
+
tests.push({
|
|
38
|
+
appName: options.appName,
|
|
39
|
+
framework,
|
|
40
|
+
startedAt: runStartedAt.toISOString(),
|
|
41
|
+
finishedAt: now,
|
|
42
|
+
describePath,
|
|
43
|
+
feature,
|
|
44
|
+
context: { layer: options.appName },
|
|
45
|
+
testName: test.name,
|
|
46
|
+
status: mapStatus(result.state),
|
|
47
|
+
duration: test.diagnostic()?.duration ?? 0,
|
|
48
|
+
errors,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return tests;
|
|
53
|
+
}
|
package/dist/deliver.d.ts
CHANGED
package/dist/deliver.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deliver.d.ts","sourceRoot":"","sources":["../src/deliver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGlD,wCAAwC;AACxC,MAAM,MAAM,cAAc,GAAG;IAC3B,iEAAiE;IACjE,UAAU,EAAE,MAAM,CAAC;IACnB,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"deliver.d.ts","sourceRoot":"","sources":["../src/deliver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGlD,wCAAwC;AACxC,MAAM,MAAM,cAAc,GAAG;IAC3B,iEAAiE;IACjE,UAAU,EAAE,MAAM,CAAC;IACnB,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yDAAyD;IACzD,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAQF;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,IAAI,CAAC,CAgDf;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,CAAC,EAAE,MAAM,GAChB,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,CAOvC"}
|
package/dist/deliver.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { nzilaSafeAsync } from "./silent.js";
|
|
2
|
+
function nzilaLog(message, debug) {
|
|
3
|
+
if (debug || process.env.NZILA_DEBUG === "1") {
|
|
4
|
+
console.warn(`[nzila] ${message}`);
|
|
5
|
+
}
|
|
6
|
+
}
|
|
2
7
|
/**
|
|
3
8
|
* POST a completed test run payload to Nzila.
|
|
4
9
|
* Never throws and never logs — failures are ignored so CI and apps stay unaffected.
|
|
@@ -10,10 +15,13 @@ export async function sendNzilaRun(payload, options) {
|
|
|
10
15
|
await nzilaSafeAsync(async () => {
|
|
11
16
|
const webhookUrl = options?.webhookUrl?.trim();
|
|
12
17
|
const apiKey = options?.apiKey?.trim();
|
|
13
|
-
if (!webhookUrl || !apiKey)
|
|
18
|
+
if (!webhookUrl || !apiKey) {
|
|
19
|
+
nzilaLog("Skipped webhook: set webhookUrl + apiKey (or NZILA_WEBHOOK_URL + NZILA_API_KEY).", options.debug);
|
|
14
20
|
return;
|
|
21
|
+
}
|
|
15
22
|
const maxRetries = options.maxRetries ?? 3;
|
|
16
23
|
let attempt = 0;
|
|
24
|
+
let lastStatus;
|
|
17
25
|
while (attempt < maxRetries) {
|
|
18
26
|
attempt += 1;
|
|
19
27
|
try {
|
|
@@ -25,7 +33,9 @@ export async function sendNzilaRun(payload, options) {
|
|
|
25
33
|
},
|
|
26
34
|
body: JSON.stringify(payload),
|
|
27
35
|
});
|
|
36
|
+
lastStatus = res.status;
|
|
28
37
|
if (res.ok || res.status === 200 || res.status === 202) {
|
|
38
|
+
nzilaLog(`Sent run ${payload.runId} (${payload.tests.length} tests) → ${res.status}`, options.debug);
|
|
29
39
|
return;
|
|
30
40
|
}
|
|
31
41
|
}
|
|
@@ -34,6 +44,7 @@ export async function sendNzilaRun(payload, options) {
|
|
|
34
44
|
}
|
|
35
45
|
await new Promise((r) => setTimeout(r, attempt * 1000));
|
|
36
46
|
}
|
|
47
|
+
nzilaLog(`Webhook failed after ${maxRetries} attempts${lastStatus != null ? ` (last HTTP ${lastStatus})` : ""}.`, options.debug);
|
|
37
48
|
});
|
|
38
49
|
}
|
|
39
50
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jest-reporter.d.ts","sourceRoot":"","sources":["../src/jest-reporter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"jest-reporter.d.ts","sourceRoot":"","sources":["../src/jest-reporter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,kBAAkB,EAInB,MAAM,YAAY,CAAC;AAEpB,KAAK,aAAa,GAAG;IAAE,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAEpD,KAAK,cAAc,GAAG;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,UAAU,CAAC;IAC1E,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B,CAAC;AAEF,KAAK,cAAc,GAAG;IACpB,WAAW,EAAE;QACX,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,GAAG,EAAE,MAAM,CAAA;SAAE,CAAC;QAC1C,WAAW,EAAE,cAAc,EAAE,CAAC;KAC/B,EAAE,CAAC;CACL,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,CAAC,OAAO,OAAO,iBAAiB;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0C;IAClE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,IAAI,CAAS;gBAET,OAAO,EAAE,kBAAkB,EAAE,aAAa,CAAC,EAAE,OAAO;IAKhE,aAAa,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc;IAmDzD,OAAO,CAAC,SAAS;CAQlB;AAED,4CAA4C;AAC5C,YAAY,EAAE,aAAa,EAAE,CAAC"}
|
package/dist/jest-reporter.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { sendNzilaRun, resolveLocale } from "./deliver.js";
|
|
3
|
+
import { resolveClientOptions } from "./reporter-options.js";
|
|
3
4
|
/**
|
|
4
5
|
* Jest reporter: aggregates results and POSTs one {@link sendNzilaRun} payload on `onRunComplete`.
|
|
5
6
|
*
|
|
@@ -11,8 +12,8 @@ import { sendNzilaRun, resolveLocale } from "./deliver.js";
|
|
|
11
12
|
export default class NzilaJestReporter {
|
|
12
13
|
constructor(options, _globalConfig) {
|
|
13
14
|
this.sent = false;
|
|
14
|
-
this.options = options;
|
|
15
|
-
this.runId = options.runId ?? randomUUID();
|
|
15
|
+
this.options = resolveClientOptions(options);
|
|
16
|
+
this.runId = this.options.runId ?? randomUUID();
|
|
16
17
|
}
|
|
17
18
|
onRunComplete(_contexts, results) {
|
|
18
19
|
if (this.sent)
|
|
@@ -41,8 +42,12 @@ export default class NzilaJestReporter {
|
|
|
41
42
|
});
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
|
-
if (!tests.length)
|
|
45
|
+
if (!tests.length) {
|
|
46
|
+
if (this.options.debug) {
|
|
47
|
+
console.warn("[nzila] No Jest test results to send.");
|
|
48
|
+
}
|
|
45
49
|
return;
|
|
50
|
+
}
|
|
46
51
|
const locale = resolveLocale(this.options.locale);
|
|
47
52
|
const payload = {
|
|
48
53
|
runId: this.runId,
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { NzilaClientOptions } from "./types.js";
|
|
2
|
+
/** Merge reporter options with `NZILA_*` environment variables. */
|
|
3
|
+
export declare function resolveClientOptions(options: NzilaClientOptions): NzilaClientOptions & {
|
|
4
|
+
debug: boolean;
|
|
5
|
+
};
|
|
6
|
+
//# sourceMappingURL=reporter-options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporter-options.d.ts","sourceRoot":"","sources":["../src/reporter-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,mEAAmE;AACnE,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,kBAAkB,GAC1B,kBAAkB,GAAG;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,CAQzC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Merge reporter options with `NZILA_*` environment variables. */
|
|
2
|
+
export function resolveClientOptions(options) {
|
|
3
|
+
return {
|
|
4
|
+
...options,
|
|
5
|
+
webhookUrl: options.webhookUrl?.trim() || process.env.NZILA_WEBHOOK_URL?.trim() || "",
|
|
6
|
+
apiKey: options.apiKey?.trim() || process.env.NZILA_API_KEY?.trim() || "",
|
|
7
|
+
appName: options.appName?.trim() || process.env.NZILA_APP_NAME?.trim() || "",
|
|
8
|
+
debug: options.debug === true || process.env.NZILA_DEBUG === "1",
|
|
9
|
+
};
|
|
10
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -49,5 +49,7 @@ export type NzilaClientOptions = {
|
|
|
49
49
|
* Default: `describePath[0] ?? "general"`.
|
|
50
50
|
*/
|
|
51
51
|
mapFeature?: (describePath: string[], testName: string) => string;
|
|
52
|
+
/** Log delivery skips/success to stderr (or set `NZILA_DEBUG=1`). */
|
|
53
|
+
debug?: boolean;
|
|
52
54
|
};
|
|
53
55
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,eAAO,MAAM,qBAAqB,yGAUxB,CAAC;AAEX,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAC;AAExE,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;AAE1E,kEAAkE;AAClE,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEpD,oDAAoD;AACpD,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,kBAAkB,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,kFAAkF;IAClF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,eAAe,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC/C,CAAC;AAEF,sEAAsE;AACtE,MAAM,MAAM,eAAe,GAAG;IAC5B,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,kBAAkB,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,wEAAwE;AACxE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B,uDAAuD;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,eAAO,MAAM,qBAAqB,yGAUxB,CAAC;AAEX,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAC;AAExE,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;AAE1E,kEAAkE;AAClE,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEpD,oDAAoD;AACpD,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,kBAAkB,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,kFAAkF;IAClF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,eAAe,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC/C,CAAC;AAEF,sEAAsE;AACtE,MAAM,MAAM,eAAe,GAAG;IAC5B,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,kBAAkB,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,wEAAwE;AACxE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B,uDAAuD;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;IAClE,qEAAqE;IACrE,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC"}
|
|
@@ -1,37 +1,21 @@
|
|
|
1
1
|
import type { File } from "@vitest/runner";
|
|
2
|
+
import type { Reporter, TestModule } from "vitest/node";
|
|
2
3
|
import type { NzilaClientOptions } from "./types.js";
|
|
3
|
-
interface VitestReporter {
|
|
4
|
-
onFinished?: (files?: File[], errors?: unknown[]) => void;
|
|
5
|
-
}
|
|
6
4
|
/**
|
|
7
5
|
* Vitest reporter that POSTs one webhook per finished run via {@link sendNzilaRun}.
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* ```ts
|
|
11
|
-
* reporters: [
|
|
12
|
-
* "default",
|
|
13
|
-
* new NzilaVitestReporter({
|
|
14
|
-
* webhookUrl: process.env.NZILA_WEBHOOK_URL!,
|
|
15
|
-
* apiKey: process.env.NZILA_API_KEY!,
|
|
16
|
-
* appName: "checkout-api",
|
|
17
|
-
* mapFeature: (path) => path[0] ?? "general",
|
|
18
|
-
* }),
|
|
19
|
-
* ],
|
|
20
|
-
* ```
|
|
6
|
+
* Supports Vitest 3+ (`onTestRunEnd`) and legacy `onFinished` file tasks.
|
|
21
7
|
*/
|
|
22
|
-
export default class NzilaVitestReporter implements
|
|
8
|
+
export default class NzilaVitestReporter implements Reporter {
|
|
23
9
|
private readonly options;
|
|
24
10
|
private startedAt;
|
|
25
11
|
private sent;
|
|
26
12
|
private readonly runId;
|
|
27
|
-
private tests;
|
|
28
|
-
/**
|
|
29
|
-
* @param options - Webhook URL, API key, and project `appName` (required).
|
|
30
|
-
*/
|
|
31
13
|
constructor(options: NzilaClientOptions);
|
|
14
|
+
onTestRunEnd(testModules: ReadonlyArray<TestModule>): void;
|
|
15
|
+
/** @deprecated Vitest 2 — still invoked in some setups */
|
|
32
16
|
onFinished(files?: File[], _errors?: unknown[]): void;
|
|
17
|
+
private sendPayload;
|
|
33
18
|
private walkTasks;
|
|
34
19
|
private mapStatus;
|
|
35
20
|
}
|
|
36
|
-
export {};
|
|
37
21
|
//# sourceMappingURL=vitest-reporter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vitest-reporter.d.ts","sourceRoot":"","sources":["../src/vitest-reporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAQ,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"vitest-reporter.d.ts","sourceRoot":"","sources":["../src/vitest-reporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAQ,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAKxD,OAAO,KAAK,EAAE,kBAAkB,EAAmD,MAAM,YAAY,CAAC;AAEtG;;;GAGG;AACH,MAAM,CAAC,OAAO,OAAO,mBAAoB,YAAW,QAAQ;IAC1D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0C;IAClE,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBAEnB,OAAO,EAAE,kBAAkB;IAKvC,YAAY,CAAC,WAAW,EAAE,aAAa,CAAC,UAAU,CAAC;IAKnD,0DAA0D;IAC1D,UAAU,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE;YAQhC,WAAW;IA2BzB,OAAO,CAAC,SAAS;IAyCjB,OAAO,CAAC,SAAS;CAMlB"}
|
package/dist/vitest-reporter.js
CHANGED
|
@@ -1,42 +1,41 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { collectTestsFromVitestModules } from "./collect-vitest-tests.js";
|
|
2
3
|
import { sendNzilaRun, resolveLocale } from "./deliver.js";
|
|
4
|
+
import { resolveClientOptions } from "./reporter-options.js";
|
|
3
5
|
/**
|
|
4
6
|
* Vitest reporter that POSTs one webhook per finished run via {@link sendNzilaRun}.
|
|
5
|
-
*
|
|
6
|
-
* @example
|
|
7
|
-
* ```ts
|
|
8
|
-
* reporters: [
|
|
9
|
-
* "default",
|
|
10
|
-
* new NzilaVitestReporter({
|
|
11
|
-
* webhookUrl: process.env.NZILA_WEBHOOK_URL!,
|
|
12
|
-
* apiKey: process.env.NZILA_API_KEY!,
|
|
13
|
-
* appName: "checkout-api",
|
|
14
|
-
* mapFeature: (path) => path[0] ?? "general",
|
|
15
|
-
* }),
|
|
16
|
-
* ],
|
|
17
|
-
* ```
|
|
7
|
+
* Supports Vitest 3+ (`onTestRunEnd`) and legacy `onFinished` file tasks.
|
|
18
8
|
*/
|
|
19
9
|
export default class NzilaVitestReporter {
|
|
20
|
-
/**
|
|
21
|
-
* @param options - Webhook URL, API key, and project `appName` (required).
|
|
22
|
-
*/
|
|
23
10
|
constructor(options) {
|
|
24
11
|
this.startedAt = new Date();
|
|
25
12
|
this.sent = false;
|
|
26
|
-
this.
|
|
27
|
-
this.
|
|
28
|
-
this.runId = options.runId ?? randomUUID();
|
|
13
|
+
this.options = resolveClientOptions(options);
|
|
14
|
+
this.runId = this.options.runId ?? randomUUID();
|
|
29
15
|
}
|
|
16
|
+
onTestRunEnd(testModules) {
|
|
17
|
+
const tests = collectTestsFromVitestModules(testModules, this.options, this.startedAt);
|
|
18
|
+
void this.sendPayload(tests);
|
|
19
|
+
}
|
|
20
|
+
/** @deprecated Vitest 2 — still invoked in some setups */
|
|
30
21
|
onFinished(files, _errors) {
|
|
22
|
+
const tests = [];
|
|
23
|
+
for (const file of files ?? []) {
|
|
24
|
+
this.walkTasks(file.tasks, file.name.split("/").slice(0, -1), tests);
|
|
25
|
+
}
|
|
26
|
+
void this.sendPayload(tests);
|
|
27
|
+
}
|
|
28
|
+
async sendPayload(tests) {
|
|
29
|
+
if (!tests.length) {
|
|
30
|
+
if (this.options.debug) {
|
|
31
|
+
console.warn("[nzila] No finished tests to send (check that tests ran).");
|
|
32
|
+
}
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
31
35
|
if (this.sent)
|
|
32
36
|
return;
|
|
33
37
|
this.sent = true;
|
|
34
38
|
const finishedAt = new Date();
|
|
35
|
-
for (const file of files ?? []) {
|
|
36
|
-
this.walkTasks(file.tasks, file.name.split("/").slice(0, -1));
|
|
37
|
-
}
|
|
38
|
-
if (!this.tests.length)
|
|
39
|
-
return;
|
|
40
39
|
const framework = this.options.framework ?? "vitest";
|
|
41
40
|
const locale = resolveLocale(this.options.locale);
|
|
42
41
|
const payload = {
|
|
@@ -45,22 +44,24 @@ export default class NzilaVitestReporter {
|
|
|
45
44
|
framework,
|
|
46
45
|
startedAt: this.startedAt.toISOString(),
|
|
47
46
|
finishedAt: finishedAt.toISOString(),
|
|
48
|
-
tests
|
|
47
|
+
tests,
|
|
49
48
|
...(locale ? { locale } : {}),
|
|
50
49
|
};
|
|
51
|
-
|
|
50
|
+
await sendNzilaRun(payload, this.options);
|
|
52
51
|
}
|
|
53
|
-
walkTasks(tasks, describePath) {
|
|
52
|
+
walkTasks(tasks, describePath, out) {
|
|
54
53
|
const framework = this.options.framework ?? "vitest";
|
|
55
54
|
const now = new Date().toISOString();
|
|
56
55
|
for (const task of tasks) {
|
|
57
56
|
if (task.type === "suite") {
|
|
58
|
-
this.walkTasks(task.tasks, [...describePath, task.name]);
|
|
57
|
+
this.walkTasks(task.tasks, [...describePath, task.name], out);
|
|
59
58
|
continue;
|
|
60
59
|
}
|
|
61
60
|
if (task.type !== "test")
|
|
62
61
|
continue;
|
|
63
62
|
const result = task?.result;
|
|
63
|
+
if (!result?.state || result.state === "skip")
|
|
64
|
+
continue;
|
|
64
65
|
const errors = result?.errors?.map((e) => ({
|
|
65
66
|
message: e?.message ?? String(e),
|
|
66
67
|
stack: e?.stack,
|
|
@@ -68,7 +69,7 @@ export default class NzilaVitestReporter {
|
|
|
68
69
|
const feature = this.options.mapFeature?.(describePath, task.name) ??
|
|
69
70
|
describePath[0] ??
|
|
70
71
|
"general";
|
|
71
|
-
|
|
72
|
+
out.push({
|
|
72
73
|
appName: this.options.appName,
|
|
73
74
|
framework,
|
|
74
75
|
startedAt: this.startedAt.toISOString(),
|
package/jest.cjs
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Jest loads reporters via `require()` — this CJS entry delegates to the ESM implementation.
|
|
3
|
+
*/
|
|
4
|
+
let reporterModulePromise;
|
|
5
|
+
|
|
6
|
+
function loadReporter() {
|
|
7
|
+
if (!reporterModulePromise) {
|
|
8
|
+
reporterModulePromise = import("./dist/jest-reporter.js");
|
|
9
|
+
}
|
|
10
|
+
return reporterModulePromise;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
class NzilaJestReporter {
|
|
14
|
+
constructor(options, globalConfig) {
|
|
15
|
+
this._options = options;
|
|
16
|
+
this._globalConfig = globalConfig;
|
|
17
|
+
this._delegate = null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async onRunComplete(contexts, results) {
|
|
21
|
+
if (!this._delegate) {
|
|
22
|
+
const mod = await loadReporter();
|
|
23
|
+
this._delegate = new mod.default(this._options, this._globalConfig);
|
|
24
|
+
}
|
|
25
|
+
return this._delegate.onRunComplete(contexts, results);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
module.exports = NzilaJestReporter;
|
package/jest.d.ts
ADDED
package/mocha.d.ts
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nzila/sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Send test runs to Nzila, trace live feature errors, and onboard via npx @nzila/sdk.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -14,9 +14,24 @@
|
|
|
14
14
|
},
|
|
15
15
|
"files": [
|
|
16
16
|
"dist",
|
|
17
|
+
"vitest.d.ts",
|
|
18
|
+
"jest.d.ts",
|
|
19
|
+
"jest.cjs",
|
|
20
|
+
"mocha.d.ts",
|
|
21
|
+
"runtime.d.ts",
|
|
22
|
+
"react.d.ts",
|
|
17
23
|
"README.md",
|
|
18
24
|
"examples"
|
|
19
25
|
],
|
|
26
|
+
"typesVersions": {
|
|
27
|
+
"*": {
|
|
28
|
+
"vitest": ["./dist/vitest-reporter.d.ts"],
|
|
29
|
+
"jest": ["./dist/jest-reporter.d.ts"],
|
|
30
|
+
"mocha": ["./dist/mocha-reporter.d.ts"],
|
|
31
|
+
"runtime": ["./dist/runtime/index.d.ts"],
|
|
32
|
+
"react": ["./dist/react/index.d.ts"]
|
|
33
|
+
}
|
|
34
|
+
},
|
|
20
35
|
"main": "./dist/index.js",
|
|
21
36
|
"types": "./dist/index.d.ts",
|
|
22
37
|
"bin": {
|
|
@@ -28,24 +43,30 @@
|
|
|
28
43
|
"import": "./dist/index.js"
|
|
29
44
|
},
|
|
30
45
|
"./vitest": {
|
|
31
|
-
"types": "./
|
|
32
|
-
"import": "./dist/vitest-reporter.js"
|
|
46
|
+
"types": "./vitest.d.ts",
|
|
47
|
+
"import": "./dist/vitest-reporter.js",
|
|
48
|
+
"default": "./dist/vitest-reporter.js"
|
|
33
49
|
},
|
|
34
50
|
"./jest": {
|
|
35
|
-
"types": "./
|
|
36
|
-
"import": "./dist/jest-reporter.js"
|
|
51
|
+
"types": "./jest.d.ts",
|
|
52
|
+
"import": "./dist/jest-reporter.js",
|
|
53
|
+
"require": "./jest.cjs",
|
|
54
|
+
"default": "./dist/jest-reporter.js"
|
|
37
55
|
},
|
|
38
56
|
"./mocha": {
|
|
39
|
-
"types": "./
|
|
40
|
-
"import": "./dist/mocha-reporter.js"
|
|
57
|
+
"types": "./mocha.d.ts",
|
|
58
|
+
"import": "./dist/mocha-reporter.js",
|
|
59
|
+
"default": "./dist/mocha-reporter.js"
|
|
41
60
|
},
|
|
42
61
|
"./runtime": {
|
|
43
|
-
"types": "./
|
|
44
|
-
"import": "./dist/runtime/index.js"
|
|
62
|
+
"types": "./runtime.d.ts",
|
|
63
|
+
"import": "./dist/runtime/index.js",
|
|
64
|
+
"default": "./dist/runtime/index.js"
|
|
45
65
|
},
|
|
46
66
|
"./react": {
|
|
47
|
-
"types": "./
|
|
48
|
-
"import": "./dist/react/index.js"
|
|
67
|
+
"types": "./react.d.ts",
|
|
68
|
+
"import": "./dist/react/index.js",
|
|
69
|
+
"default": "./dist/react/index.js"
|
|
49
70
|
}
|
|
50
71
|
},
|
|
51
72
|
"scripts": {
|
package/react.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./dist/react/index.js";
|
package/runtime.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./dist/runtime/index.js";
|
package/vitest.d.ts
ADDED