Skip to content

Commit

Permalink
back compatibility with old style cucumberjs runtime api (via #952)
Browse files Browse the repository at this point in the history
  • Loading branch information
epszaw authored May 21, 2024
1 parent 6457fa2 commit 3d23cc1
Show file tree
Hide file tree
Showing 22 changed files with 665 additions and 198 deletions.
39 changes: 36 additions & 3 deletions packages/allure-cucumberjs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ Install the required packages using your favorite package manager:

```shell
# using npm
npm install --save-dev allure-js-commons allure-cucumberjs
npm install --save-dev allure-cucumberjs
# using yarn
yarn add -D allure-js-commons allure-cucumberjs
yarn add -D allure-cucumberjs
# using pnpm
pnpm add -D allure-js-commons allure-cucumberjs
pnpm add -D allure-cucumberjs
```

Create `reporter.js` with following content:
Expand Down Expand Up @@ -86,6 +86,39 @@ Given(/my step/, async () => {
});
```

### Using Allure Cucumber World

If you prefer to use custom Allure World instead of global Allure API, you can use `AllureCucumberWorld` class:

```js
import { AllureCucumberWorld } from "allure-cucumberjs";
import { setWorldConstructor } from "@cucumber/cucumber";

setWorldConstructor(AllureCucumberWorld);
```

Then you'll be able to use Allure Runtime API through `this` in your step definition files:

```js
import { Given } from "@cucumber/cucumber";

Given(/my step/, async function() {
const self = this;

await self.step("step can have anonymous body function", async function() {
await self.label("label_name", "label_value");
await self.attachment(JSON.stringify({ foo: "bar " }), "application/json");
});

await self.step("by the way, body function can be arrow one", async function() {
await self.label("label_name", "label_value");
await self.attachment(JSON.stringify({ foo: "bar " }), "application/json");
});
});
```

If you run your Cucumber features using single thread mode, `AllureCucumberWorld` is set automatically.

### Parameters usage

```ts
Expand Down
185 changes: 5 additions & 180 deletions packages/allure-cucumberjs/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,186 +1,9 @@
import { Before, World } from "@cucumber/cucumber";
import { ALLURE_RUNTIME_MESSAGE_CONTENT_TYPE } from "allure-js-commons/internal";
import {
ContentType,
Label,
LabelName,
Link,
LinkType,
MessagesHolder,
ParameterOptions,
RuntimeMessage,
Stage,
Status,
TestRuntime,
getStatusFromError,
setGlobalTestRuntime,
} from "allure-js-commons/sdk/node";

export class AllureCucumberTestRuntime extends World implements TestRuntime {
messagesHolder = new MessagesHolder();

async label(name: LabelName | string, value: string) {
await this.sendMessage({
type: "metadata",
data: {
labels: [{ name, value }],
},
});
}

async labels(...labels: Label[]) {
await this.sendMessage({
type: "metadata",
data: {
labels,
},
});
}

async link(url: string, type?: LinkType | string, name?: string) {
await this.sendMessage({
type: "metadata",
data: {
links: [{ type, url, name }],
},
});
}

async links(...links: Link[]) {
await this.sendMessage({
type: "metadata",
data: {
links,
},
});
}

async parameter(name: string, value: string, options?: ParameterOptions) {
await this.sendMessage({
type: "metadata",
data: {
parameters: [
{
name,
value,
...options,
},
],
},
});
}

async description(markdown: string) {
await this.sendMessage({
type: "metadata",
data: {
description: markdown,
},
});
}

async descriptionHtml(html: string) {
await this.sendMessage({
type: "metadata",
data: {
descriptionHtml: html,
},
});
}

async displayName(name: string) {
await this.sendMessage({
type: "metadata",
data: {
displayName: name,
},
});
}

async historyId(value: string) {
await this.sendMessage({
type: "metadata",
data: {
historyId: value,
},
});
}

async testCaseId(value: string) {
await this.sendMessage({
type: "metadata",
data: {
testCaseId: value,
},
});
}

async attachment(name: string, content: Buffer | string, type: string | ContentType) {
await this.sendMessage({
type: "raw_attachment",
data: {
name,
content: Buffer.from(content).toString("base64"),
contentType: type,
encoding: "base64",
},
});
}

async step(name: string, body: () => void | PromiseLike<void>) {
await this.sendMessage({
type: "step_start",
data: {
name,
start: Date.now(),
},
});

try {
await body();

await this.sendMessage({
type: "step_stop",
data: {
status: Status.PASSED,
stage: Stage.FINISHED,
stop: Date.now(),
},
});
} catch (err) {
const status = getStatusFromError(err as Error);

await this.sendMessage({
type: "step_stop",
data: {
status,
stage: Stage.FINISHED,
stop: Date.now(),
statusDetails: {
message: (err as Error).message,
trace: (err as Error).stack,
},
},
});

throw err;
}
}

async stepDisplayName() {}

async stepParameter() {}

sendMessage(message: RuntimeMessage) {
this.attach(JSON.stringify(message), ALLURE_RUNTIME_MESSAGE_CONTENT_TYPE as string);

return Promise.resolve();
}
}
import { Before } from "@cucumber/cucumber";
import { setGlobalTestRuntime } from "allure-js-commons/sdk/node";
import { AllureCucumberTestRuntime } from "./runtime.js";

Before(function () {
// TODO: we can implement testplan logic there

setGlobalTestRuntime(
new AllureCucumberTestRuntime({
attach: this.attach,
Expand All @@ -189,3 +12,5 @@ Before(function () {
}),
);
});

export { AllureCucumberTestRuntime };
11 changes: 9 additions & 2 deletions packages/allure-cucumberjs/src/reporter.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Formatter, IFormatterOptions, TestCaseHookDefinition } from "@cucumber/cucumber";
import { Formatter, IFormatterOptions, TestCaseHookDefinition, World } from "@cucumber/cucumber";
import * as messages from "@cucumber/messages";
import { PickleTag, Tag, TestStepResult, TestStepResultStatus } from "@cucumber/messages";
import os from "node:os";
Expand All @@ -19,7 +19,8 @@ import {
createStepResult,
getWorstStepResultStatus,
} from "allure-js-commons/sdk/node";
import { AllureCucumberReporterConfig, LabelConfig, LinkConfig } from "./model";
import { AllureCucumberReporterConfig, LabelConfig, LinkConfig } from "./model.js";
import { AllureCucumberTestRuntime } from "./runtime.js";

const { ALLURE_THREAD_NAME } = process.env;

Expand Down Expand Up @@ -71,6 +72,12 @@ export default class AllureCucumberReporter extends Formatter {

this.beforeHooks = options.supportCodeLibrary.beforeTestCaseHookDefinitions;
this.afterHooks = options.supportCodeLibrary.afterTestCaseHookDefinitions;

// set custom Allure World for single thread mode
if (options.supportCodeLibrary.World === World) {
// @ts-ignore
options.supportCodeLibrary.World = AllureCucumberTestRuntime;
}
}

private get tagsIgnorePatterns(): RegExp[] {
Expand Down
Loading

0 comments on commit 3d23cc1

Please sign in to comment.