@allurereport/plugin-csv 3.0.0-beta.3

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 ADDED
@@ -0,0 +1,56 @@
1
+ # CSV Plugin
2
+
3
+ [<img src="https://allurereport.org/public/img/allure-report.svg" height="85px" alt="Allure Report logo" align="right" />](https://allurereport.org "Allure Report")
4
+
5
+ - Learn more about Allure Report at https://allurereport.org
6
+ - 📚 [Documentation](https://allurereport.org/docs/) – discover official documentation for Allure Report
7
+ - ❓ [Questions and Support](https://github.com/orgs/allure-framework/discussions/categories/questions-support) – get help from the team and community
8
+ - 📢 [Official announcements](https://github.com/orgs/allure-framework/discussions/categories/announcements) – be in touch with the latest updates
9
+ - 💬 [General Discussion ](https://github.com/orgs/allure-framework/discussions/categories/general-discussion) – engage in casual conversations, share insights and ideas with the community
10
+
11
+ ---
12
+
13
+ ## Overview
14
+
15
+ This plugin generates the Allure Report in CSV file format.
16
+
17
+ ## Install
18
+
19
+ Use your favorite package manager to install the package:
20
+
21
+ ```shell
22
+ npm add @allurereport/plugin-csv
23
+ yarn add @allurereport/plugin-csv
24
+ pnpm add @allurereport/plugin-csv
25
+ ```
26
+
27
+ Then, add the plugin to the Allure configuration file:
28
+
29
+ ```diff
30
+ import { defineConfig } from "allure";
31
+
32
+ export default defineConfig({
33
+ name: "Allure Report",
34
+ output: "./allure-report",
35
+ historyPath: "./history.jsonl",
36
+ plugins: {
37
+ + csv: {
38
+ + options: {
39
+ + fileName: "my-report.csv",
40
+ + },
41
+ + },
42
+ },
43
+ });
44
+ ```
45
+
46
+ ## Options
47
+
48
+ The plugin accepts the following options:
49
+
50
+ | Option | Description | Type | Default |
51
+ |------------|---------------------------------|-----------------------------------------------------------------------------------|---------------------|
52
+ | `fileName` | Name of the report file | `string` | `allure-report.csv` |
53
+ | `fields` | Fields to include in the report | `{ header: string; accessor: keyof T \| ((result: T) => string \| undefined) }[]` | All fields |
54
+ | `sort` | Sorting function | `(a: T, b: T) => number` | Default order |
55
+ | `filter` | Filtering function | `(a: T) => boolean` | No filtering |
56
+
package/dist/csv.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ import type { CsvField, CsvOptions } from "./model.js";
2
+ export declare const generateCsv: <T>(rows: T[], fields: CsvField<T>[], sort?: (a: T, b: T) => number, filter?: (a: T) => boolean, options?: CsvOptions) => Promise<string>;
package/dist/csv.js ADDED
@@ -0,0 +1,18 @@
1
+ export const generateCsv = async (rows, fields, sort = () => 0, filter = () => true, options = {}) => {
2
+ const { disableHeaders = false, separator = "," } = options;
3
+ const content = [...rows]
4
+ .filter(filter)
5
+ .sort(sort)
6
+ .map((tr) => {
7
+ return fields
8
+ .map(({ accessor }) => (typeof accessor === "function" ? accessor(tr) : tr[accessor]))
9
+ .map(forceEscapeCsv)
10
+ .join(separator);
11
+ })
12
+ .join("\n");
13
+ const header = disableHeaders ? "" : fields.map((f) => f.header).join(separator) + "\n";
14
+ return header + content;
15
+ };
16
+ const forceEscapeCsv = (value) => {
17
+ return value ? '"' + `${value}`.replaceAll('"', '""') + '"' : "";
18
+ };
@@ -0,0 +1,2 @@
1
+ import { CsvPlugin } from "./plugin.js";
2
+ export default CsvPlugin;
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ import { CsvPlugin } from "./plugin.js";
2
+ export default CsvPlugin;
@@ -0,0 +1,15 @@
1
+ import type { TestResult } from "@allurereport/core-api";
2
+ export type CsvOptions = {
3
+ separator?: string;
4
+ disableHeaders?: boolean;
5
+ };
6
+ export type CsvField<T> = {
7
+ header: string;
8
+ accessor: keyof T | ((result: T) => string | undefined);
9
+ };
10
+ export type CsvPluginOptions = {
11
+ fileName?: string;
12
+ fields?: CsvField<TestResult>[];
13
+ sort?: (a: TestResult, b: TestResult) => number;
14
+ filter?: (a: TestResult) => boolean;
15
+ } & CsvOptions;
package/dist/model.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,7 @@
1
+ import type { AllureStore, Plugin, PluginContext } from "@allurereport/plugin-api";
2
+ import type { CsvPluginOptions } from "./model.js";
3
+ export declare class CsvPlugin implements Plugin {
4
+ readonly options: CsvPluginOptions;
5
+ constructor(options?: CsvPluginOptions);
6
+ done: (context: PluginContext, store: AllureStore) => Promise<void>;
7
+ }
package/dist/plugin.js ADDED
@@ -0,0 +1,41 @@
1
+ import { formatDuration } from "@allurereport/core-api";
2
+ import { generateCsv } from "./csv.js";
3
+ import { formatSteps, labelValue } from "./utils.js";
4
+ const defaultFields = [
5
+ { header: "Full Name", accessor: "fullName" },
6
+ {
7
+ header: "Name",
8
+ accessor: "name",
9
+ },
10
+ {
11
+ header: "Status",
12
+ accessor: "status",
13
+ },
14
+ {
15
+ header: "Duration",
16
+ accessor: (result) => formatDuration(result.duration),
17
+ },
18
+ { header: "Error", accessor: "message" },
19
+ { header: "Stack Trace", accessor: "trace" },
20
+ { header: "Steps", accessor: formatSteps },
21
+ { header: "Parent Suite", accessor: labelValue("parentSuite") },
22
+ { header: "Suite", accessor: labelValue("suite") },
23
+ { header: "Sub Suite", accessor: labelValue("subSuite") },
24
+ { header: "Epic", accessor: labelValue("epic") },
25
+ { header: "Feature", accessor: labelValue("feature") },
26
+ { header: "Story", accessor: labelValue("story") },
27
+ ];
28
+ const defaultSort = (a, b) => a.name.localeCompare(b.name);
29
+ export class CsvPlugin {
30
+ constructor(options = {}) {
31
+ this.options = options;
32
+ this.done = async (context, store) => {
33
+ const { reportFiles } = context;
34
+ const testResults = await store.allTestResults();
35
+ const { fields = defaultFields, sort = defaultSort, filter, fileName = "report.csv" } = this.options;
36
+ const content = await generateCsv(testResults, fields, sort, filter, this.options);
37
+ const result = Buffer.from(content, "utf-8");
38
+ await reportFiles.addFile(fileName, result);
39
+ };
40
+ }
41
+ }
@@ -0,0 +1,3 @@
1
+ import type { TestResult } from "@allurereport/core-api";
2
+ export declare const formatSteps: (tr: TestResult) => string | undefined;
3
+ export declare const labelValue: (name: string) => ((result: TestResult) => string | undefined);
package/dist/utils.js ADDED
@@ -0,0 +1,30 @@
1
+ import { formatDuration } from "@allurereport/core-api";
2
+ export const formatSteps = (tr) => {
3
+ if (tr.steps.length === 0) {
4
+ return undefined;
5
+ }
6
+ return tr.steps
7
+ .map(formatStep)
8
+ .filter((s) => s)
9
+ .join("\n");
10
+ };
11
+ const formatStep = (step, indent = 0) => {
12
+ if (step.type !== "step") {
13
+ return undefined;
14
+ }
15
+ const prefix = " ".repeat(indent);
16
+ const res = [
17
+ prefix + step.name + " " + step.status + ` (${formatDuration(step.duration)})`,
18
+ ...step.steps.map((s) => formatStep(s, indent + 2)).filter((s) => s),
19
+ ];
20
+ return res.join("\n");
21
+ };
22
+ export const labelValue = (name) => {
23
+ return (result) => result.labels
24
+ .filter((l) => l.name === name)
25
+ .map((l) => l.value)
26
+ .filter((v) => v)
27
+ .map((v) => v)
28
+ .sort()
29
+ .join(",");
30
+ };
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@allurereport/plugin-csv",
3
+ "version": "3.0.0-beta.3",
4
+ "description": "Allure CSV report",
5
+ "keywords": [
6
+ "allure",
7
+ "testing",
8
+ "report",
9
+ "plugin",
10
+ "csv"
11
+ ],
12
+ "repository": "https://github.com/allure-framework/allure3",
13
+ "license": "Apache-2.0",
14
+ "author": "Qameta Software",
15
+ "type": "module",
16
+ "exports": {
17
+ ".": "./dist/index.js"
18
+ },
19
+ "main": "./dist/index.js",
20
+ "module": "./dist/index.js",
21
+ "types": "./dist/index.d.ts",
22
+ "files": [
23
+ "./dist"
24
+ ],
25
+ "scripts": {
26
+ "build": "run clean && tsc --project ./tsconfig.json",
27
+ "clean": "rimraf ./dist",
28
+ "test": "rimraf ./out && vitest run"
29
+ },
30
+ "dependencies": {
31
+ "@allurereport/core-api": "3.0.0-beta.3",
32
+ "@allurereport/plugin-api": "3.0.0-beta.3"
33
+ },
34
+ "devDependencies": {
35
+ "@stylistic/eslint-plugin": "^2.6.1",
36
+ "@types/eslint": "^8.56.11",
37
+ "@types/node": "^20.17.9",
38
+ "@typescript-eslint/eslint-plugin": "^8.0.0",
39
+ "@typescript-eslint/parser": "^8.0.0",
40
+ "@vitest/runner": "^2.1.8",
41
+ "allure-vitest": "^3.0.7",
42
+ "eslint": "^8.57.0",
43
+ "eslint-config-prettier": "^9.1.0",
44
+ "eslint-plugin-import": "^2.29.1",
45
+ "eslint-plugin-jsdoc": "^50.0.0",
46
+ "eslint-plugin-n": "^17.10.1",
47
+ "eslint-plugin-no-null": "^1.0.2",
48
+ "eslint-plugin-prefer-arrow": "^1.2.3",
49
+ "rimraf": "^6.0.1",
50
+ "typescript": "^5.6.3",
51
+ "vitest": "^2.1.8"
52
+ }
53
+ }