@allurereport/reader-api 3.0.0-beta.8 → 3.0.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/dist/index.d.ts CHANGED
@@ -3,3 +3,5 @@ export type * from "./reader.js";
3
3
  export * from "./resultFile.js";
4
4
  export { detectContentType } from "./detect.js";
5
5
  export { extension, lookupContentType } from "./utils.js";
6
+ export * from "./validation.js";
7
+ export * from "./toolRunner.js";
package/dist/index.js CHANGED
@@ -1,3 +1,5 @@
1
1
  export * from "./resultFile.js";
2
2
  export { detectContentType } from "./detect.js";
3
3
  export { extension, lookupContentType } from "./utils.js";
4
+ export * from "./validation.js";
5
+ export * from "./toolRunner.js";
package/dist/model.d.ts CHANGED
@@ -13,7 +13,10 @@ export interface RawFixtureResult {
13
13
  status?: RawTestStatus;
14
14
  message?: string;
15
15
  trace?: string;
16
+ expected?: string;
17
+ actual?: string;
16
18
  steps?: RawStep[];
19
+ titlePath?: string[];
17
20
  }
18
21
  export interface RawTestResult {
19
22
  uuid?: string;
@@ -34,6 +37,8 @@ export interface RawTestResult {
34
37
  duration?: number;
35
38
  message?: string;
36
39
  trace?: string;
40
+ expected?: string;
41
+ actual?: string;
37
42
  flaky?: boolean;
38
43
  muted?: boolean;
39
44
  known?: boolean;
@@ -43,6 +48,7 @@ export interface RawTestResult {
43
48
  steps?: RawStep[];
44
49
  labels?: RawTestLabel[];
45
50
  links?: RawTestLink[];
51
+ titlePath?: string[];
46
52
  }
47
53
  export interface RawTestLabel {
48
54
  name?: string;
@@ -66,6 +72,8 @@ export interface RawTestStepResult {
66
72
  status?: RawTestStatus;
67
73
  message?: string;
68
74
  trace?: string;
75
+ actual?: string;
76
+ expected?: string;
69
77
  start?: number;
70
78
  stop?: number;
71
79
  duration?: number;
@@ -70,7 +70,7 @@ export class BufferResultFile extends BaseResultFile {
70
70
  this.buffer = buffer;
71
71
  }
72
72
  getContent() {
73
- return ReadStream.from(this.buffer, { encoding: "utf8" });
73
+ return ReadStream.from(this.buffer);
74
74
  }
75
75
  readMagicHeader() {
76
76
  return this.buffer.subarray(0, magicHeaderLength);
@@ -0,0 +1,17 @@
1
+ import type { Unknown } from "./validation.js";
2
+ export type ProcessRunOptions = {
3
+ exitCode?: number | ((code: number) => boolean);
4
+ encoding?: BufferEncoding;
5
+ stderrEncoding?: BufferEncoding;
6
+ timeout?: number;
7
+ timeoutSignal?: NodeJS.Signals;
8
+ ignoreStderr?: boolean;
9
+ };
10
+ export declare const invokeCliTool: (executable: string, args: readonly string[], { timeout, timeoutSignal, ignoreStderr, encoding, exitCode: expectedExitCode }?: ProcessRunOptions) => Promise<void>;
11
+ type ResolveCliOutput<T> = T extends {
12
+ encoding: BufferEncoding;
13
+ } ? string : Buffer;
14
+ export declare const invokeStdoutCliTool: <T extends ProcessRunOptions | undefined>(executable: string, args: readonly string[], options?: T) => AsyncGenerator<ResolveCliOutput<T>, void, unknown>;
15
+ export declare const collectCliToolStdoutText: (executable: string, args: readonly string[], options?: ProcessRunOptions) => Promise<string>;
16
+ export declare const invokeJsonCliTool: <T>(tool: string, args: readonly string[], options?: ProcessRunOptions) => Promise<Unknown<T>>;
17
+ export {};
@@ -0,0 +1,145 @@
1
+ import { spawn } from "node:child_process";
2
+ const LINE_SPLIT_PATTERN = /\r\n|\r|\n/;
3
+ export const invokeCliTool = async (executable, args, { timeout, timeoutSignal, ignoreStderr, encoding, exitCode: expectedExitCode = 0 } = {}) => {
4
+ const toolProcess = spawn(executable, args, {
5
+ stdio: ["ignore", "ignore", ignoreStderr ? "ignore" : "pipe"],
6
+ shell: false,
7
+ timeout,
8
+ killSignal: timeoutSignal,
9
+ });
10
+ const stderr = [];
11
+ if (!ignoreStderr) {
12
+ toolProcess.stderr?.setEncoding(encoding ?? "utf-8").on("data", (chunk) => stderr.push(String(chunk)));
13
+ }
14
+ let onSuccess;
15
+ let onError;
16
+ const resultPromise = new Promise((resolve, reject) => {
17
+ onSuccess = resolve;
18
+ onError = reject;
19
+ });
20
+ toolProcess.on("exit", (code, signal) => {
21
+ if (signal) {
22
+ onError(new Error(timeout && toolProcess.killed
23
+ ? `${executable} was terminated by timeout (${timeout} ms)`
24
+ : `${executable} was terminated with ${signal}`));
25
+ return;
26
+ }
27
+ if (typeof expectedExitCode === "number" ? code !== expectedExitCode : expectedExitCode(code)) {
28
+ onError(new Error(`${executable} finished with an unexpected exit code ${code}`));
29
+ return;
30
+ }
31
+ onSuccess();
32
+ });
33
+ return await resultPromise;
34
+ };
35
+ export const invokeStdoutCliTool = async function* (executable, args, options) {
36
+ const { timeout, timeoutSignal, encoding, stderrEncoding, exitCode: expectedExitCode = 0, ignoreStderr, } = options ?? {};
37
+ const emitTextChunk = (chunk) => {
38
+ const lines = (unfinishedLineBuffer + chunk).split(LINE_SPLIT_PATTERN);
39
+ if (lines.length) {
40
+ unfinishedLineBuffer = lines.at(-1);
41
+ stdoutChunks.push(...lines.slice(0, -1));
42
+ maybeContinueConsumption();
43
+ }
44
+ };
45
+ const emitFinalTextChunk = () => {
46
+ if (unfinishedLineBuffer) {
47
+ stdoutChunks.push(unfinishedLineBuffer);
48
+ unfinishedLineBuffer = "";
49
+ maybeContinueConsumption();
50
+ }
51
+ };
52
+ const emitBinaryChunk = (chunk) => {
53
+ stdoutChunks.push(chunk);
54
+ maybeContinueConsumption();
55
+ };
56
+ const emitError = (message) => {
57
+ if (stderrChunks.length) {
58
+ message = `${message}\n\nStandard error:\n\n${stderrChunks.join("")}`;
59
+ }
60
+ bufferedError = new Error(message);
61
+ maybeContinueConsumption();
62
+ };
63
+ const checkExitCode = (code) => {
64
+ if (typeof expectedExitCode === "number") {
65
+ return code === expectedExitCode;
66
+ }
67
+ return expectedExitCode(code);
68
+ };
69
+ const maybeContinueConsumption = () => {
70
+ if (continueConsumption) {
71
+ const continueConsumptionLocal = continueConsumption;
72
+ continueConsumption = undefined;
73
+ continueConsumptionLocal();
74
+ }
75
+ };
76
+ const stdoutChunks = [];
77
+ let unfinishedLineBuffer = "";
78
+ let done = false;
79
+ let bufferedError;
80
+ const stderrChunks = [];
81
+ let continueConsumption;
82
+ const toolProcess = spawn(executable, args, {
83
+ stdio: ["ignore", "pipe", ignoreStderr ? "ignore" : "pipe"],
84
+ shell: false,
85
+ timeout,
86
+ killSignal: timeoutSignal,
87
+ });
88
+ const { stdout, stderr } = toolProcess;
89
+ if (stdout) {
90
+ if (encoding) {
91
+ stdout.setEncoding(encoding).on("data", emitTextChunk);
92
+ }
93
+ else {
94
+ stdout.on("data", emitBinaryChunk);
95
+ }
96
+ }
97
+ if (stderr) {
98
+ stderr.setEncoding(stderrEncoding ?? encoding ?? "utf-8").on("data", stderrChunks.push.bind(stderrChunks));
99
+ }
100
+ toolProcess.on("exit", (code, signal) => {
101
+ emitFinalTextChunk();
102
+ done = true;
103
+ if (bufferedError) {
104
+ return;
105
+ }
106
+ if (signal) {
107
+ emitError(timeout && toolProcess.killed
108
+ ? `${executable} was terminated by timeout (${timeout} ms)`
109
+ : `${executable} was terminated with ${signal}`);
110
+ return;
111
+ }
112
+ if (!checkExitCode(code)) {
113
+ emitError(`${executable} finished with an unexpected exit code ${code}`);
114
+ return;
115
+ }
116
+ continueConsumption?.();
117
+ });
118
+ while (true) {
119
+ if (stdoutChunks.length) {
120
+ yield* stdoutChunks;
121
+ stdoutChunks.splice(0);
122
+ }
123
+ if (bufferedError) {
124
+ throw bufferedError;
125
+ }
126
+ if (done) {
127
+ return;
128
+ }
129
+ await new Promise((resolve) => {
130
+ continueConsumption = resolve;
131
+ });
132
+ }
133
+ };
134
+ export const collectCliToolStdoutText = async (executable, args, options = {}) => {
135
+ const { encoding = "utf-8", ...rest } = options;
136
+ const chunks = [];
137
+ for await (const chunk of invokeStdoutCliTool(executable, args, rest)) {
138
+ chunks.push(chunk);
139
+ }
140
+ return Buffer.concat(chunks).toString(encoding);
141
+ };
142
+ export const invokeJsonCliTool = async (tool, args, options = {}) => {
143
+ const text = await collectCliToolStdoutText(tool, args, options);
144
+ return JSON.parse(text);
145
+ };
@@ -0,0 +1,45 @@
1
+ declare const unknownKey: unique symbol;
2
+ export type Unknown<T> = typeof unknownKey | ShallowKnown<T> | undefined | null;
3
+ export type ShallowKnown<T> = T extends object ? T extends (...v: any[]) => any ? T : {
4
+ [key in keyof T]: Unknown<T[key]>;
5
+ } : T;
6
+ export type IsSuper<SuperType, SubType> = [SubType] extends [never] ? never : [SubType] extends [SuperType] ? SuperType : never;
7
+ export type Narrow<SuperType, SubType> = [SubType] extends [never] ? never : [SubType] extends [SuperType] ? SubType : never;
8
+ export type ArrayElement<T> = T extends readonly (infer E)[] ? E : never;
9
+ export type IsHomogeneousObject<T> = T extends object ? T extends readonly any[] ? never : T extends {
10
+ [key in keyof T]: infer U;
11
+ } ? {
12
+ [key in keyof T]: U;
13
+ } extends T ? T : never : never : never;
14
+ export type NarrowHomogeneousObject<T, R> = T extends object ? T extends readonly any[] ? never : T extends {
15
+ [key in keyof T]: infer U;
16
+ } ? {
17
+ [key in keyof T]: U;
18
+ } extends T ? {
19
+ [key in keyof T]?: R;
20
+ } : never : never : never;
21
+ export type HomogeneousObjectItem<T> = T extends object ? T extends readonly any[] ? never : T extends {
22
+ [key in keyof T]: infer U;
23
+ } ? {
24
+ [key in keyof T]: U;
25
+ } extends T ? U : never : never : never;
26
+ export type ConditionalUnion<CA, A, CB, B> = [CA] extends [never] ? B : [CB] extends [never] ? A : A | B;
27
+ export declare const isDefined: <T>(value: T | undefined) => value is T;
28
+ export declare const isString: <T>(value: Unknown<IsSuper<T, string>>) => value is ShallowKnown<Narrow<T, string>>;
29
+ export declare const isNumber: <T>(value: Unknown<IsSuper<T, number>>) => value is ShallowKnown<Narrow<T, number>>;
30
+ export declare const isBoolean: <T>(value: Unknown<IsSuper<T, boolean>>) => value is ShallowKnown<Narrow<T, boolean>>;
31
+ export declare const isArray: <T>(value: Unknown<IsSuper<T, Extract<T, readonly any[]>>>) => value is ShallowKnown<Extract<Narrow<T, Extract<T, readonly any[]>>, readonly any[]>>;
32
+ export declare const isObject: <T>(value: Unknown<IsSuper<T, Extract<Exclude<T, readonly any[]>, object>>>) => value is ShallowKnown<Narrow<T, Extract<Exclude<T, readonly any[]>, object>>>;
33
+ export declare const isLiteral: <T, const L extends readonly any[]>(value: Unknown<IsSuper<T, L[number]>>, literals: L) => value is ShallowKnown<L[number]>;
34
+ export declare const ensureString: <T>(value: Unknown<T>) => string | undefined;
35
+ export declare const ensureNumber: <T>(value: Unknown<T>) => number | undefined;
36
+ export declare const ensureBoolean: <T>(value: Unknown<T>) => boolean | undefined;
37
+ export declare const ensureInt: <T>(value: Unknown<T>) => number | undefined;
38
+ export declare const ensureFloat: <T>(value: Unknown<T>) => number | undefined;
39
+ export declare const ensureArray: <T>(value: Unknown<IsSuper<T, Extract<T, readonly any[]>>>) => ShallowKnown<Extract<Narrow<T, Extract<T, readonly any[]>>, readonly any[]>> | undefined;
40
+ export declare const ensureObject: <T>(value: Unknown<IsSuper<T, Extract<Exclude<T, readonly any[]>, object>>>) => ShallowKnown<Narrow<T, Extract<Exclude<T, readonly any[]>, object>>> | undefined;
41
+ export declare const ensureLiteral: <T, const L extends readonly any[]>(value: Unknown<T>, literals: L) => ShallowKnown<L[number]> | undefined;
42
+ export declare const ensureArrayWithItems: <T, R extends ShallowKnown<ArrayElement<T>>>(value: Unknown<IsSuper<T, Extract<T, ArrayElement<T>[]>>>, guard: (v: Unknown<ArrayElement<T>>) => v is R) => R[] | undefined;
43
+ export declare const ensureObjectWithProps: <T, R extends ShallowKnown<HomogeneousObjectItem<T>>>(value: Unknown<IsSuper<T, Extract<T, IsHomogeneousObject<T>>>>, guard: (v: Unknown<HomogeneousObjectItem<T>>) => v is R) => NarrowHomogeneousObject<T, R> | undefined;
44
+ export declare const ensureItems: <T, R extends ShallowKnown<HomogeneousObjectItem<T> | ArrayElement<T>>>(value: Unknown<IsSuper<T, Extract<T, IsHomogeneousObject<T> | ArrayElement<T>[]>>>, guard: (v: Unknown<HomogeneousObjectItem<T> | ArrayElement<T>>) => v is R) => ConditionalUnion<ArrayElement<T>, R[], IsHomogeneousObject<T>, NarrowHomogeneousObject<T, R>> | undefined;
45
+ export {};
@@ -0,0 +1,51 @@
1
+ const unknownKey = Symbol("This must be an Unknown<T>");
2
+ export const isDefined = (value) => typeof value !== "undefined";
3
+ export const isString = (value) => typeof value === "string";
4
+ export const isNumber = (value) => typeof value === "number";
5
+ export const isBoolean = (value) => typeof value === "boolean";
6
+ export const isArray = (value) => Array.isArray(value);
7
+ export const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
8
+ export const isLiteral = (value, literals) => literals.includes(value);
9
+ export const ensureString = (value) => typeof value === "string" ? value : undefined;
10
+ export const ensureNumber = (value) => typeof value === "number" ? value : undefined;
11
+ export const ensureBoolean = (value) => typeof value === "boolean" ? value : undefined;
12
+ export const ensureInt = (value) => {
13
+ if (typeof value === "number") {
14
+ return Math.floor(value);
15
+ }
16
+ if (typeof value === "string") {
17
+ const parsed = parseInt(value, 10);
18
+ if (!isNaN(parsed)) {
19
+ return parsed;
20
+ }
21
+ }
22
+ };
23
+ export const ensureFloat = (value) => {
24
+ if (typeof value === "number") {
25
+ return value;
26
+ }
27
+ if (typeof value === "string") {
28
+ const parsed = parseFloat(value);
29
+ if (!isNaN(parsed)) {
30
+ return parsed;
31
+ }
32
+ }
33
+ };
34
+ export const ensureArray = (value) => isArray(value) ? value : undefined;
35
+ export const ensureObject = (value) => isObject(value) ? value : undefined;
36
+ export const ensureLiteral = (value, literals) => literals.includes(value) ? value : undefined;
37
+ export const ensureArrayWithItems = (value, guard) => ensureArray(value)?.filter(guard);
38
+ export const ensureObjectWithProps = (value, guard) => {
39
+ const obj = ensureObject(value);
40
+ if (obj) {
41
+ return Object.entries(obj).reduce((a, [k, v]) => {
42
+ if (guard(v)) {
43
+ a[k] = v;
44
+ }
45
+ return a;
46
+ }, {});
47
+ }
48
+ };
49
+ export const ensureItems = (value, guard) => {
50
+ return ensureArrayWithItems(value, guard) ?? ensureObjectWithProps(value, guard);
51
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allurereport/reader-api",
3
- "version": "3.0.0-beta.8",
3
+ "version": "3.0.0",
4
4
  "description": "Allure Reader API",
5
5
  "keywords": [
6
6
  "allure",
@@ -27,8 +27,8 @@
27
27
  "test": "rimraf ./out && vitest run"
28
28
  },
29
29
  "dependencies": {
30
- "@allurereport/core-api": "3.0.0-beta.8",
31
- "@allurereport/plugin-api": "3.0.0-beta.8",
30
+ "@allurereport/core-api": "3.0.0",
31
+ "@allurereport/plugin-api": "3.0.0",
32
32
  "mime-types": "^2.1.35"
33
33
  },
34
34
  "devDependencies": {
@@ -38,8 +38,8 @@
38
38
  "@types/node": "^20.17.9",
39
39
  "@typescript-eslint/eslint-plugin": "^8.0.0",
40
40
  "@typescript-eslint/parser": "^8.0.0",
41
- "@vitest/runner": "^2.1.8",
42
- "allure-vitest": "^3.0.9",
41
+ "@vitest/runner": "^2.1.9",
42
+ "allure-vitest": "^3.3.3",
43
43
  "eslint": "^8.57.0",
44
44
  "eslint-config-prettier": "^9.1.0",
45
45
  "eslint-plugin-import": "^2.29.1",
@@ -51,6 +51,6 @@
51
51
  "ts-node": "^10.9.2",
52
52
  "tslib": "^2.7.0",
53
53
  "typescript": "^5.6.3",
54
- "vitest": "^2.1.8"
54
+ "vitest": "^2.1.9"
55
55
  }
56
56
  }