@allurereport/plugin-classic 3.0.0-beta.15 → 3.0.0-beta.17
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/categories.d.ts +3 -3
- package/dist/converters.js +1 -0
- package/dist/generators.d.ts +11 -11
- package/dist/generators.js +32 -16
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -2
- package/dist/model.d.ts +3 -3
- package/dist/plugin.d.ts +5 -5
- package/dist/plugin.js +29 -22
- package/dist/writer.d.ts +4 -4
- package/package.json +9 -9
package/dist/categories.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { TestStatus } from "@allurereport/core-api";
|
|
2
|
-
import type {
|
|
3
|
-
export declare const matchCategories: (categories:
|
|
2
|
+
import type { ClassicCategory } from "./model.js";
|
|
3
|
+
export declare const matchCategories: (categories: ClassicCategory[], result: {
|
|
4
4
|
message?: string;
|
|
5
5
|
trace?: string;
|
|
6
6
|
status: TestStatus;
|
|
7
7
|
flaky: boolean;
|
|
8
|
-
}) =>
|
|
8
|
+
}) => ClassicCategory[];
|
package/dist/converters.js
CHANGED
package/dist/generators.d.ts
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import { type AttachmentLink, type EnvironmentItem, type Statistic } from "@allurereport/core-api";
|
|
2
2
|
import { type AllureStore, type ReportFiles, type ResultFile } from "@allurereport/plugin-api";
|
|
3
3
|
import type { AwesomeTestResult } from "@allurereport/web-awesome";
|
|
4
|
-
import type {
|
|
5
|
-
import type {
|
|
4
|
+
import type { ClassicOptions, TemplateManifest } from "./model.js";
|
|
5
|
+
import type { ClassicDataWriter, ReportFile } from "./writer.js";
|
|
6
6
|
export declare const readTemplateManifest: (singleFileMode?: boolean) => Promise<TemplateManifest>;
|
|
7
|
-
export declare const generateTestResults: (writer:
|
|
8
|
-
export declare const generateTree: (writer:
|
|
9
|
-
export declare const generateEnvironmentJson: (writer:
|
|
10
|
-
export declare const generateStatistic: (writer:
|
|
11
|
-
export declare const generatePieChart: (writer:
|
|
12
|
-
export declare const generateAttachmentsFiles: (writer:
|
|
13
|
-
export declare const generateHistoryDataPoints: (writer:
|
|
14
|
-
export declare const generateStaticFiles: (payload:
|
|
7
|
+
export declare const generateTestResults: (writer: ClassicDataWriter, store: AllureStore) => Promise<AwesomeTestResult[]>;
|
|
8
|
+
export declare const generateTree: (writer: ClassicDataWriter, treeName: string, labels: string[], tests: AwesomeTestResult[]) => Promise<void>;
|
|
9
|
+
export declare const generateEnvironmentJson: (writer: ClassicDataWriter, env: EnvironmentItem[]) => Promise<void>;
|
|
10
|
+
export declare const generateStatistic: (writer: ClassicDataWriter, statistic: Statistic) => Promise<void>;
|
|
11
|
+
export declare const generatePieChart: (writer: ClassicDataWriter, statistic: Statistic) => Promise<void>;
|
|
12
|
+
export declare const generateAttachmentsFiles: (writer: ClassicDataWriter, attachmentLinks: AttachmentLink[], contentFunction: (id: string) => Promise<ResultFile | undefined>) => Promise<Map<string, string> | undefined>;
|
|
13
|
+
export declare const generateHistoryDataPoints: (writer: ClassicDataWriter, store: AllureStore) => Promise<Map<string, string>>;
|
|
14
|
+
export declare const generateStaticFiles: (payload: ClassicOptions & {
|
|
15
15
|
allureVersion: string;
|
|
16
16
|
reportFiles: ReportFiles;
|
|
17
17
|
reportDataFiles: ReportFile[];
|
|
18
18
|
reportUuid: string;
|
|
19
19
|
reportName: string;
|
|
20
20
|
}) => Promise<void>;
|
|
21
|
-
export declare const generateTreeByCategories: (writer:
|
|
21
|
+
export declare const generateTreeByCategories: (writer: ClassicDataWriter, treeName: string, tests: AwesomeTestResult[]) => Promise<void>;
|
package/dist/generators.js
CHANGED
|
@@ -113,14 +113,17 @@ export const generateTestResults = async (writer, store) => {
|
|
|
113
113
|
};
|
|
114
114
|
export const generateTree = async (writer, treeName, labels, tests) => {
|
|
115
115
|
const visibleTests = tests.filter((test) => !test.hidden);
|
|
116
|
-
const tree = createTreeByLabels(visibleTests, labels, ({ id, name, status, duration, flaky, start, retries }) => {
|
|
116
|
+
const tree = createTreeByLabels(visibleTests, labels, ({ id, name, status, duration, flaky, transition, start, retries }) => {
|
|
117
|
+
const retriesCount = retries?.length ?? 0;
|
|
117
118
|
return {
|
|
118
119
|
nodeId: id,
|
|
119
|
-
retry:
|
|
120
|
+
retry: Boolean(retriesCount),
|
|
121
|
+
retriesCount,
|
|
120
122
|
name,
|
|
121
123
|
status,
|
|
122
124
|
duration,
|
|
123
125
|
flaky,
|
|
126
|
+
transition,
|
|
124
127
|
start,
|
|
125
128
|
};
|
|
126
129
|
}, undefined, (group, leaf) => {
|
|
@@ -210,29 +213,42 @@ export const generateStaticFiles = async (payload) => {
|
|
|
210
213
|
allureVersion,
|
|
211
214
|
cacheKey: now.toString(),
|
|
212
215
|
};
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
216
|
+
try {
|
|
217
|
+
const html = compile({
|
|
218
|
+
headTags: headTags.join("\n"),
|
|
219
|
+
bodyTags: bodyTags.join("\n"),
|
|
220
|
+
reportFilesScript: createReportDataScript(reportDataFiles),
|
|
221
|
+
reportOptions: JSON.stringify(reportOptions),
|
|
222
|
+
analyticsEnable: true,
|
|
223
|
+
allureVersion,
|
|
224
|
+
reportUuid,
|
|
225
|
+
reportName,
|
|
226
|
+
singleFile: payload.singleFile,
|
|
227
|
+
});
|
|
228
|
+
await reportFiles.addFile("index.html", Buffer.from(html, "utf8"));
|
|
229
|
+
}
|
|
230
|
+
catch (err) {
|
|
231
|
+
if (err instanceof RangeError) {
|
|
232
|
+
console.error("The report is too large to be generated in the single file mode!");
|
|
233
|
+
process.exit(1);
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
throw err;
|
|
237
|
+
}
|
|
225
238
|
};
|
|
226
239
|
export const generateTreeByCategories = async (writer, treeName, tests) => {
|
|
227
240
|
const visibleTests = tests.filter((test) => !test.hidden);
|
|
228
|
-
const tree = createTreeByCategories(visibleTests, ({ id, name, status, duration, flaky, start, retries }) => {
|
|
241
|
+
const tree = createTreeByCategories(visibleTests, ({ id, name, status, duration, flaky, transition, start, retries }) => {
|
|
242
|
+
const retriesCount = retries?.length ?? 0;
|
|
229
243
|
return {
|
|
230
244
|
nodeId: id,
|
|
231
|
-
retry:
|
|
245
|
+
retry: Boolean(retriesCount),
|
|
246
|
+
retriesCount,
|
|
232
247
|
name,
|
|
233
248
|
status,
|
|
234
249
|
duration,
|
|
235
250
|
flaky,
|
|
251
|
+
transition,
|
|
236
252
|
start,
|
|
237
253
|
};
|
|
238
254
|
}, undefined, (group, leaf) => {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
export default
|
|
1
|
+
export type { ClassicPluginOptions } from "./model.js";
|
|
2
|
+
export { ClassicPlugin as default } from "./plugin.js";
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export default AwesomePlugin;
|
|
1
|
+
export { ClassicPlugin as default } from "./plugin.js";
|
package/dist/model.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { TestResult, TestStatus } from "@allurereport/core-api";
|
|
2
|
-
export type
|
|
2
|
+
export type ClassicOptions = {
|
|
3
3
|
reportName?: string;
|
|
4
4
|
singleFile?: boolean;
|
|
5
5
|
logo?: string;
|
|
@@ -14,8 +14,8 @@ export type AwesomeOptions = {
|
|
|
14
14
|
filter?: (tr: TestResult) => boolean;
|
|
15
15
|
};
|
|
16
16
|
export type TemplateManifest = Record<string, string>;
|
|
17
|
-
export type
|
|
18
|
-
export interface
|
|
17
|
+
export type ClassicPluginOptions = ClassicOptions;
|
|
18
|
+
export interface ClassicCategory {
|
|
19
19
|
name: string;
|
|
20
20
|
description?: string;
|
|
21
21
|
descriptionHtml?: string;
|
package/dist/plugin.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import type {
|
|
3
|
-
export declare class
|
|
1
|
+
import { type AllureStore, type Plugin, type PluginContext, type PluginSummary } from "@allurereport/plugin-api";
|
|
2
|
+
import type { ClassicPluginOptions } from "./model.js";
|
|
3
|
+
export declare class ClassicPlugin implements Plugin {
|
|
4
4
|
#private;
|
|
5
|
-
readonly options:
|
|
6
|
-
constructor(options?:
|
|
5
|
+
readonly options: ClassicPluginOptions;
|
|
6
|
+
constructor(options?: ClassicPluginOptions);
|
|
7
7
|
start: (context: PluginContext) => Promise<void>;
|
|
8
8
|
update: (context: PluginContext, store: AllureStore) => Promise<void>;
|
|
9
9
|
done: (context: PluginContext, store: AllureStore) => Promise<void>;
|
package/dist/plugin.js
CHANGED
|
@@ -9,38 +9,39 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
|
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
10
10
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
11
11
|
};
|
|
12
|
-
var
|
|
12
|
+
var _ClassicPlugin_writer, _ClassicPlugin_generate;
|
|
13
13
|
import { getWorstStatus } from "@allurereport/core-api";
|
|
14
|
+
import { convertToSummaryTestResult, } from "@allurereport/plugin-api";
|
|
14
15
|
import { preciseTreeLabels } from "@allurereport/plugin-api";
|
|
15
16
|
import { generateAttachmentsFiles, generateEnvironmentJson, generateHistoryDataPoints, generatePieChart, generateStaticFiles, generateStatistic, generateTestResults, generateTree, generateTreeByCategories, } from "./generators.js";
|
|
16
17
|
import { InMemoryReportDataWriter, ReportFileDataWriter } from "./writer.js";
|
|
17
|
-
export class
|
|
18
|
+
export class ClassicPlugin {
|
|
18
19
|
constructor(options = {}) {
|
|
19
20
|
this.options = options;
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
_ClassicPlugin_writer.set(this, void 0);
|
|
22
|
+
_ClassicPlugin_generate.set(this, async (context, store) => {
|
|
22
23
|
const { singleFile, groupBy = [] } = this.options ?? {};
|
|
23
24
|
const environmentItems = await store.metadataByKey("allure_environment");
|
|
24
25
|
const statistic = await store.testsStatistic();
|
|
25
26
|
const attachments = await store.allAttachments();
|
|
26
|
-
await generateStatistic(__classPrivateFieldGet(this,
|
|
27
|
-
await generatePieChart(__classPrivateFieldGet(this,
|
|
28
|
-
const convertedTrs = await generateTestResults(__classPrivateFieldGet(this,
|
|
27
|
+
await generateStatistic(__classPrivateFieldGet(this, _ClassicPlugin_writer, "f"), statistic);
|
|
28
|
+
await generatePieChart(__classPrivateFieldGet(this, _ClassicPlugin_writer, "f"), statistic);
|
|
29
|
+
const convertedTrs = await generateTestResults(__classPrivateFieldGet(this, _ClassicPlugin_writer, "f"), store);
|
|
29
30
|
const treeLabels = preciseTreeLabels(!groupBy.length ? ["parentSuite", "suite", "subSuite"] : groupBy, convertedTrs, ({ labels }) => labels.map(({ name }) => name));
|
|
30
31
|
const behaviorLabels = preciseTreeLabels(!groupBy.length ? ["epic", "feature", "story"] : groupBy, convertedTrs, ({ labels }) => labels.map(({ name }) => name));
|
|
31
32
|
const packagesLabels = preciseTreeLabels(!groupBy.length ? ["package"] : groupBy, convertedTrs, ({ labels }) => labels.map(({ name }) => name));
|
|
32
|
-
await generateTreeByCategories(__classPrivateFieldGet(this,
|
|
33
|
-
await generateTree(__classPrivateFieldGet(this,
|
|
34
|
-
await generateTree(__classPrivateFieldGet(this,
|
|
35
|
-
await generateTree(__classPrivateFieldGet(this,
|
|
36
|
-
await generateHistoryDataPoints(__classPrivateFieldGet(this,
|
|
33
|
+
await generateTreeByCategories(__classPrivateFieldGet(this, _ClassicPlugin_writer, "f"), "categories", convertedTrs);
|
|
34
|
+
await generateTree(__classPrivateFieldGet(this, _ClassicPlugin_writer, "f"), "tree", treeLabels, convertedTrs);
|
|
35
|
+
await generateTree(__classPrivateFieldGet(this, _ClassicPlugin_writer, "f"), "behaviors", behaviorLabels, convertedTrs);
|
|
36
|
+
await generateTree(__classPrivateFieldGet(this, _ClassicPlugin_writer, "f"), "packages", packagesLabels, convertedTrs);
|
|
37
|
+
await generateHistoryDataPoints(__classPrivateFieldGet(this, _ClassicPlugin_writer, "f"), store);
|
|
37
38
|
if (environmentItems?.length) {
|
|
38
|
-
await generateEnvironmentJson(__classPrivateFieldGet(this,
|
|
39
|
+
await generateEnvironmentJson(__classPrivateFieldGet(this, _ClassicPlugin_writer, "f"), environmentItems);
|
|
39
40
|
}
|
|
40
41
|
if (attachments?.length) {
|
|
41
|
-
await generateAttachmentsFiles(__classPrivateFieldGet(this,
|
|
42
|
+
await generateAttachmentsFiles(__classPrivateFieldGet(this, _ClassicPlugin_writer, "f"), attachments, (id) => store.attachmentContentById(id));
|
|
42
43
|
}
|
|
43
|
-
const reportDataFiles = singleFile ? __classPrivateFieldGet(this,
|
|
44
|
+
const reportDataFiles = singleFile ? __classPrivateFieldGet(this, _ClassicPlugin_writer, "f").reportFiles() : [];
|
|
44
45
|
await generateStaticFiles({
|
|
45
46
|
...this.options,
|
|
46
47
|
allureVersion: context.allureVersion,
|
|
@@ -53,27 +54,30 @@ export class AwesomePlugin {
|
|
|
53
54
|
this.start = async (context) => {
|
|
54
55
|
const { singleFile } = this.options;
|
|
55
56
|
if (singleFile) {
|
|
56
|
-
__classPrivateFieldSet(this,
|
|
57
|
+
__classPrivateFieldSet(this, _ClassicPlugin_writer, new InMemoryReportDataWriter(), "f");
|
|
57
58
|
return;
|
|
58
59
|
}
|
|
59
|
-
__classPrivateFieldSet(this,
|
|
60
|
+
__classPrivateFieldSet(this, _ClassicPlugin_writer, new ReportFileDataWriter(context.reportFiles), "f");
|
|
60
61
|
await Promise.resolve();
|
|
61
62
|
};
|
|
62
63
|
this.update = async (context, store) => {
|
|
63
|
-
if (!__classPrivateFieldGet(this,
|
|
64
|
+
if (!__classPrivateFieldGet(this, _ClassicPlugin_writer, "f")) {
|
|
64
65
|
throw new Error("call start first");
|
|
65
66
|
}
|
|
66
|
-
await __classPrivateFieldGet(this,
|
|
67
|
+
await __classPrivateFieldGet(this, _ClassicPlugin_generate, "f").call(this, context, store);
|
|
67
68
|
};
|
|
68
69
|
this.done = async (context, store) => {
|
|
69
|
-
if (!__classPrivateFieldGet(this,
|
|
70
|
+
if (!__classPrivateFieldGet(this, _ClassicPlugin_writer, "f")) {
|
|
70
71
|
throw new Error("call start first");
|
|
71
72
|
}
|
|
72
|
-
await __classPrivateFieldGet(this,
|
|
73
|
+
await __classPrivateFieldGet(this, _ClassicPlugin_generate, "f").call(this, context, store);
|
|
73
74
|
};
|
|
74
75
|
}
|
|
75
76
|
async info(context, store) {
|
|
76
77
|
const allTrs = (await store.allTestResults()).filter(this.options.filter ? this.options.filter : () => true);
|
|
78
|
+
const newTrs = await store.allNewTestResults();
|
|
79
|
+
const retryTrs = allTrs.filter((tr) => !!tr?.retries?.length);
|
|
80
|
+
const flakyTrs = allTrs.filter((tr) => !!tr?.flaky);
|
|
77
81
|
const duration = allTrs.reduce((acc, { duration: trDuration = 0 }) => acc + trDuration, 0);
|
|
78
82
|
const worstStatus = getWorstStatus(allTrs.map(({ status }) => status));
|
|
79
83
|
const createdAt = allTrs.reduce((acc, { stop }) => Math.max(acc, stop || 0), 0);
|
|
@@ -84,7 +88,10 @@ export class AwesomePlugin {
|
|
|
84
88
|
createdAt,
|
|
85
89
|
duration,
|
|
86
90
|
plugin: "Classic",
|
|
91
|
+
newTests: newTrs.map(convertToSummaryTestResult),
|
|
92
|
+
flakyTests: flakyTrs.map(convertToSummaryTestResult),
|
|
93
|
+
retryTests: retryTrs.map(convertToSummaryTestResult),
|
|
87
94
|
};
|
|
88
95
|
}
|
|
89
96
|
}
|
|
90
|
-
|
|
97
|
+
_ClassicPlugin_writer = new WeakMap(), _ClassicPlugin_generate = new WeakMap();
|
package/dist/writer.d.ts
CHANGED
|
@@ -4,13 +4,13 @@ export interface ReportFile {
|
|
|
4
4
|
name: string;
|
|
5
5
|
value: string;
|
|
6
6
|
}
|
|
7
|
-
export interface
|
|
7
|
+
export interface ClassicDataWriter {
|
|
8
8
|
writeData(fileName: string, data: any): Promise<void>;
|
|
9
9
|
writeWidget(fileName: string, data: any): Promise<void>;
|
|
10
10
|
writeTestCase(test: AwesomeTestResult): Promise<void>;
|
|
11
11
|
writeAttachment(source: string, file: ResultFile): Promise<void>;
|
|
12
12
|
}
|
|
13
|
-
export declare class FileSystemReportDataWriter implements
|
|
13
|
+
export declare class FileSystemReportDataWriter implements ClassicDataWriter {
|
|
14
14
|
private readonly output;
|
|
15
15
|
constructor(output: string);
|
|
16
16
|
writeData(fileName: string, data: any): Promise<void>;
|
|
@@ -18,7 +18,7 @@ export declare class FileSystemReportDataWriter implements AwesomeDataWriter {
|
|
|
18
18
|
writeTestCase(test: AwesomeTestResult): Promise<void>;
|
|
19
19
|
writeAttachment(source: string, file: ResultFile): Promise<void>;
|
|
20
20
|
}
|
|
21
|
-
export declare class InMemoryReportDataWriter implements
|
|
21
|
+
export declare class InMemoryReportDataWriter implements ClassicDataWriter {
|
|
22
22
|
#private;
|
|
23
23
|
writeData(fileName: string, data: any): Promise<void>;
|
|
24
24
|
writeWidget(fileName: string, data: any): Promise<void>;
|
|
@@ -26,7 +26,7 @@ export declare class InMemoryReportDataWriter implements AwesomeDataWriter {
|
|
|
26
26
|
writeAttachment(fileName: string, file: ResultFile): Promise<void>;
|
|
27
27
|
reportFiles(): ReportFile[];
|
|
28
28
|
}
|
|
29
|
-
export declare class ReportFileDataWriter implements
|
|
29
|
+
export declare class ReportFileDataWriter implements ClassicDataWriter {
|
|
30
30
|
readonly reportFiles: ReportFiles;
|
|
31
31
|
constructor(reportFiles: ReportFiles);
|
|
32
32
|
writeData(fileName: string, data: any): Promise<void>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@allurereport/plugin-classic",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.17",
|
|
4
4
|
"description": "The classic version of Allure HTML report",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"allure",
|
|
@@ -30,11 +30,11 @@
|
|
|
30
30
|
"test": "rimraf ./out && vitest run"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@allurereport/core-api": "3.0.0-beta.
|
|
34
|
-
"@allurereport/plugin-api": "3.0.0-beta.
|
|
35
|
-
"@allurereport/web-awesome": "3.0.0-beta.
|
|
36
|
-
"@allurereport/web-classic": "3.0.0-beta.
|
|
37
|
-
"@allurereport/web-commons": "3.0.0-beta.
|
|
33
|
+
"@allurereport/core-api": "3.0.0-beta.17",
|
|
34
|
+
"@allurereport/plugin-api": "3.0.0-beta.17",
|
|
35
|
+
"@allurereport/web-awesome": "3.0.0-beta.17",
|
|
36
|
+
"@allurereport/web-classic": "3.0.0-beta.17",
|
|
37
|
+
"@allurereport/web-commons": "3.0.0-beta.17",
|
|
38
38
|
"d3-shape": "^3.2.0",
|
|
39
39
|
"handlebars": "^4.7.8"
|
|
40
40
|
},
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
"@types/node": "^20.17.9",
|
|
46
46
|
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
47
47
|
"@typescript-eslint/parser": "^8.0.0",
|
|
48
|
-
"@vitest/runner": "^2.1.
|
|
49
|
-
"allure-vitest": "^3.0
|
|
48
|
+
"@vitest/runner": "^2.1.9",
|
|
49
|
+
"allure-vitest": "^3.3.0",
|
|
50
50
|
"eslint": "^8.57.0",
|
|
51
51
|
"eslint-config-prettier": "^9.1.0",
|
|
52
52
|
"eslint-plugin-import": "^2.29.1",
|
|
@@ -56,6 +56,6 @@
|
|
|
56
56
|
"eslint-plugin-prefer-arrow": "^1.2.3",
|
|
57
57
|
"rimraf": "^6.0.1",
|
|
58
58
|
"typescript": "^5.6.3",
|
|
59
|
-
"vitest": "^2.1.
|
|
59
|
+
"vitest": "^2.1.9"
|
|
60
60
|
}
|
|
61
61
|
}
|