Skip to content

Commit

Permalink
add vitest package
Browse files Browse the repository at this point in the history
  • Loading branch information
epszaw committed Jan 11, 2024
1 parent 80b475e commit 69bad42
Show file tree
Hide file tree
Showing 61 changed files with 2,191 additions and 6 deletions.
3 changes: 2 additions & 1 deletion .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

957 changes: 957 additions & 0 deletions .pnp.cjs

Large diffs are not rendered by default.

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
36 changes: 36 additions & 0 deletions packages/allure-vitest/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# vitest-allure

Allure integration for Vitest. Based on code from this thread: https://github.com/allure-framework/allure-js/issues/415

## Configuration

Add this reporter to the [`reporters` section](https://vitest.dev/config/#reporters) of Vitest config

```js
export default defineConfig({
test: {
// do not forget to keep the "default" if you want to see something in the console
reporters: ["default", "TODO-VITEST-ALLURE-PACKAGE"],
// optional, if you want to write results to a different directory
outputFile: {
allure: "allure-results",
},
},
});
```

## API

To use advanced test instrumentation features, use `allureTest` API. Powered by Vitest's [test context feature](https://vitest.dev/guide/test-context.html#extend-test-context):

```js
import { allureTest } from "TODO-VITEST-ALLURE-PACKAGE/test";

allureTest("labels", ({ allure }) => {
allure.label("demo", "works");
});
```

Currently, only labels, steps and attachments are supported.

See the `test/features.test.ts` for more examples.
58 changes: 58 additions & 0 deletions packages/allure-vitest/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"name": "allure-vitest",
"version": "2.10.0",
"description": "Allure Vitest integration",
"license": "Apache-2.0",
"author": {
"name": "Qameta Software",
"email": "[email protected]",
"url": "https://qameta.io/"
},
"repository": {
"type": "git",
"url": "https://github.com/allure-framework/allure-js.git",
"directory": "packages/allure-vitest"
},
"keywords": [
"vitest",
"allure"
],
"type": "module",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"clean": "rimraf ./dist ./out",
"compile": "tsc",
"generate-report": "allure generate ./out/allure-results -o ./out/allure-report --clean",
"allure-report": "allure serve ./out/allure-results",
"pretest": "run compile",
"test": "vitest run test",
"lint": "eslint ./src --ext .ts",
"lint:fix": "eslint ./src --ext .ts --fix"
},
"exports": {
".": "./dist/src/reporter.js",
"./test": "./dist/src/test.js"
},
"dependencies": {
"allure-js-commons": "workspace:*"
},
"devDependencies": {
"@types/eslint": "^8",
"@types/node": "^20.6.3",
"@typescript-eslint/eslint-plugin": "^6.7.0",
"@typescript-eslint/parser": "^6.7.0",
"eslint": "^8.49.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-import": "^2.28.1",
"eslint-plugin-jsdoc": "^46.6.0",
"eslint-plugin-no-null": "^1.0.2",
"eslint-plugin-prefer-arrow": "^1.2.3",
"rimraf": "^5.0.1",
"typescript": "^5.2.2",
"vitest": "^1.1.3"
}
}
33 changes: 33 additions & 0 deletions packages/allure-vitest/src/model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { AttachmentOptions, Status, StatusDetails } from "allure-js-commons";

export interface AllureAttachment {
name: string;
contentType: string;
fileExtension?: string;
content: Buffer | string;
}

export interface AllureStep {
name: string;
start?: number;
stop?: number;
status?: Status;
attachments: AllureAttachment[];
steps: AllureStep[];
statusDetails?: StatusDetails;
}

export interface AllureTest extends AllureStep {
labels: { name: string; value: string }[];
}

export interface AllureMeta {
currentTest: AllureTest;
currentStep: AllureStep;
}

export interface AllureApi {
label: (name: string, value: string) => void;
attachment: (name: string, content: Buffer | string, options: string | AttachmentOptions) => void;
step: <T>(name: string, body: () => Promise<T>) => Promise<T>;
}
111 changes: 111 additions & 0 deletions packages/allure-vitest/src/reporter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import {
AllureGroup,
AllureRuntime,
ExecutableItem,
LabelName,
Stage,
Status,
} from "allure-js-commons";
import { File, Reporter, Task } from "vitest";
import { AllureMeta, AllureStep } from "./model.js";

export default class AllureReporter implements Reporter {
private allureRuntime: AllureRuntime;

onInit(ctx) {
this.allureRuntime = new AllureRuntime({
resultsDir: ctx.config.outputFile.allure ?? "allure-results",
});
}

onFinished(files?: File[]) {
const rootSuite = this.allureRuntime.startGroup(undefined);
for (const file of files || []) {
const group = rootSuite.startGroup(file.name);
group.name = file.name;
for (const task of file.tasks) {
this.handleTask(group, task);
}
group.endGroup();
}
rootSuite.endGroup();
}

handleStep(step: AllureStep): ExecutableItem {
return {
name: step.name,
start: step.start,
stop: step.stop,
status: step.status,
stage: Stage.FINISHED,
attachments: step.attachments.map((attachment) => {
const filename = this.allureRuntime.writeAttachment(attachment.content, {
contentType: attachment.contentType,
fileExtension: attachment.fileExtension,
});
return {
name: attachment.name,
type: attachment.contentType,
source: filename,
};
}),
steps: step.steps.map((s) => this.handleStep(s)),
statusDetails: step.statusDetails,
parameters: [],
};
}

handleTask(parent: AllureGroup, task: Task) {
if (task.type === "suite") {
const group = parent.startGroup(task.name);
group.name = task.name;
for (const innerTask of task.tasks) {
this.handleTask(group, innerTask);
}
group.endGroup();
} else {
const test = parent.startTest(task.name, 0);
test.name = task.name;
test.fullName = `${task.file!.name}#${task.name}`;
const { allure } = task.meta as { allure: AllureMeta };
if (allure) {
for (const step of allure.currentTest.steps) {
test.addStep(this.handleStep(step));
}
for (const attachment of allure.currentTest.attachments) {
const filename = this.allureRuntime.writeAttachment(attachment.content, {
contentType: attachment.contentType,
fileExtension: attachment.fileExtension,
});
test.addAttachment(attachment.name, attachment.contentType, filename);
}
for (const label of allure.currentTest.labels) {
test.addLabel(label.name, label.value);
}
}

switch (task.result?.state) {
case "fail": {
test.detailsMessage = task.result.errors[0].message;
test.detailsTrace = task.result.errors[0].stack;
test.status = Status.FAILED;
break;
}
case "pass": {
test.status = Status.PASSED;
break;
}
case "skip": {
test.status = Status.SKIPPED;
break;
}
}
test.addLabel(LabelName.SUITE, parent.name);
if (task.suite.suite?.name) {
test.addLabel(LabelName.PARENT_SUITE, task.suite.suite.name);
}
test.historyId = task.id;
test.endTest(task.result?.duration);
}
}
}
38 changes: 38 additions & 0 deletions packages/allure-vitest/src/test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Status } from "allure-js-commons";
import { test } from "vitest";
import { AllureApi, AllureMeta, AllureStep } from "./model.js";

export const allureTest = test.extend<{ allure: AllureApi }>({
allure: async ({ task }, use) => {
const meta = task.meta as { allure: AllureMeta };
const currentTest = { name: "root-test", labels: [], attachments: [], steps: [] };
meta.allure = { currentStep: currentTest, currentTest: currentTest };
await use({
attachment: (name, content, options) => {
const parsedOptions = typeof options === "string" ? { contentType: options } : options;
meta.allure.currentStep.attachments.push({ name, content, ...parsedOptions });
},
label: (name, value) => meta.allure.currentTest.labels.push({ name, value }),
step: async (name, body) => {
const prevStep = meta.allure.currentStep;
const nextStep: AllureStep = { name, attachments: [], steps: [], start: Date.now() };
prevStep.steps.push(nextStep);
meta.allure.currentStep = nextStep;
try {
const result = await body();
nextStep.status = Status.PASSED;
return result;
} catch (error) {
nextStep.status = Status.FAILED;
if (error instanceof Error) {
nextStep.statusDetails = { message: error.message, trace: error.stack };
}
throw error;
} finally {
nextStep.stop = Date.now();
meta.allure.currentStep = prevStep;
}
},
});
},
});
33 changes: 33 additions & 0 deletions packages/allure-vitest/test/featurtes.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { describe, expect } from "vitest";
import { allureTest } from "../src/test.js";

allureTest("labels", ({ allure }) => {
allure.label("demo", "works");
expect(1 + 1).toBe(2);
});

describe("steps & attachments", () => {
allureTest("simple steps", async ({ allure }) => {
await allure.step("step 1", async () => {});
await allure.step("step 2", async () => {});
});

allureTest("simple attachments", ({ allure }) => {
allure.attachment("text", "some-text", "text/plain");
allure.attachment("json", "{foo: true}", "application/json");
});

allureTest("nested steps with attachments", async ({ allure }) => {
allure.attachment("text", "level-1", "text/plain");

await allure.step("step 1", async () => {
allure.attachment("text", "level-2", "text/plain");

await allure.step("step 1-1", async () => {
allure.attachment("text", "level-3", "text/plain");
});
});

await allure.step("step 2", async () => {});
});
});
11 changes: 11 additions & 0 deletions packages/allure-vitest/test/simple.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { describe, expect, test } from "vitest";

test("simple", () => {
expect(1 + 1).toBe(2);
});

describe("suite", () => {
test("inner test", () => {
expect(1 + 1).toBe(2);
});
});
14 changes: 14 additions & 0 deletions packages/allure-vitest/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"compilerOptions": {
"target": "es2022",
"lib": ["es2022"],
"types": [],
"skipLibCheck": true,
"module": "nodenext",
"moduleResolution": "nodenext",
"declaration": true,
"rootDir": ".",
"outDir": "dist"
},
"include": ["src"]
}
7 changes: 7 additions & 0 deletions packages/allure-vitest/tsconfig.test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extends": "./tsconfig",
"compilerOptions": {
"noEmit": true
},
"include": ["test"]
}
10 changes: 10 additions & 0 deletions packages/allure-vitest/vitest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { defineConfig } from "vitest/config";

export default defineConfig({
test: {
reporters: ["default", "./src/reporter"],
outputFile: {
allure: "build/results",
},
},
});
Loading

0 comments on commit 69bad42

Please sign in to comment.