Skip to content

Commit

Permalink
feat(codeceptjs): add support for mocha reporters (fixes #1167, via #…
Browse files Browse the repository at this point in the history
  • Loading branch information
delatrie authored Nov 1, 2024
1 parent a84cc84 commit 72f85e1
Show file tree
Hide file tree
Showing 6 changed files with 206 additions and 15 deletions.
11 changes: 10 additions & 1 deletion packages/allure-codeceptjs/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,16 @@ import { AllureCodeceptJsReporter } from "./reporter.js";

const allurePlugin = (config: ReporterConfig) => {
const mocha = container.mocha();
mocha.reporter(AllureCodeceptJsReporter.prototype.constructor, { ...config });

// At this point the configured reporter's constructor has been initialized and is available via the _reporter field.
// See https://github.com/mochajs/mocha/blob/05097db4f2e0118f033978b8503aec36b1867c55/lib/mocha.js#L352
// The field is not public but there is no other option to get the constructor; this is covered by tests in reporters.test.ts.
// eslint-disable-next-line no-underscore-dangle
const currentReporter = mocha._reporter;
mocha.reporter(AllureCodeceptJsReporter.prototype.constructor, {
...config,
...(currentReporter ? { extraReporters: [currentReporter, mocha.options.reporterOptions] } : {}),
});

return {
...allureCodeceptJsLegacyApi,
Expand Down
9 changes: 5 additions & 4 deletions packages/allure-codeceptjs/test/spec/labels.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,7 @@ it("should not depend on CWD", async () => {
});
`,
},
{},
"nested",
{ cwd: "nested" },
);

expect(tests).toEqual(
Expand Down Expand Up @@ -141,8 +140,10 @@ it("should add labels from env variables", async () => {
`,
},
{
ALLURE_LABEL_A: "a",
ALLURE_LABEL_B: "b",
env: {
ALLURE_LABEL_A: "a",
ALLURE_LABEL_B: "b",
},
},
);

Expand Down
149 changes: 149 additions & 0 deletions packages/allure-codeceptjs/test/spec/reporters.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import { describe, expect, it } from "vitest";
import { issue } from "allure-js-commons";
import { runCodeceptJsInlineTest } from "../utils.js";

describe("mocha reporters", () => {
it("cli should be enabled by default", async () => {
const { tests, stdout } = await runCodeceptJsInlineTest({
"foo.test.js": `
Feature("foo")
Scenario('bar', () => {});
`,
});

expect(tests).toEqual([expect.objectContaining({ name: "bar" })]);
expect(stdout.join("").split("\n")).toEqual(expect.arrayContaining([expect.stringMatching(/^foo --/)]));
});

it("cli --steps should work out-of-box", async () => {
await issue("1167");

const { tests, stdout } = await runCodeceptJsInlineTest(
{
"foo.test.js": `
Feature("foo")
Scenario('bar', () => {});
`,
},
{ args: ["--steps"] },
);

expect(tests).toEqual([expect.objectContaining({ name: "bar" })]);
expect(stdout.join("").split("\n")).toEqual(
expect.arrayContaining([expect.stringMatching(/^foo --/), expect.stringMatching(/^ {2}bar/)]),
);
});

it("should support Mocha's built-in reporters", async () => {
const { tests, stdout } = await runCodeceptJsInlineTest({
"foo.test.js": `
Feature("foo")
Scenario('bar', () => {});
`,
"codecept.conf.js": `
const path = require("node:path");
exports.config = {
tests: "./**/*.test.js",
output: path.resolve(__dirname, "./output"),
plugins: {
allure: {
require: require.resolve("allure-codeceptjs"),
enabled: true,
},
},
mocha: {
reporter: "json",
},
};
`,
});

const stdoutLines = stdout.join("").split("\n");

expect(tests).toEqual([expect.objectContaining({ name: "bar" })]);
const jsonString = stdoutLines.slice(stdoutLines.indexOf("{")).join("");
expect(JSON.parse(jsonString)).toMatchObject({
stats: expect.objectContaining({
suites: 1,
tests: 1,
}),
});
expect(stdoutLines).not.toEqual(
// no default cli reporter
expect.arrayContaining([expect.stringMatching(/^foo --/)]),
);
});

it("should support local reporters", async () => {
const { tests, stdout } = await runCodeceptJsInlineTest({
"foo.test.js": `
Feature("foo")
Scenario('bar', () => {});
`,
"reporter.cjs": `
module.exports = function (r, o) {
r.on("start", () => {
console.log(JSON.stringify(o.reporterOptions));
});
};
`,
"codecept.conf.js": `
const path = require("node:path");
exports.config = {
tests: "./**/*.test.js",
output: path.resolve(__dirname, "./output"),
plugins: {
allure: {
require: require.resolve("allure-codeceptjs"),
enabled: true,
},
},
mocha: {
reporter: "reporter.cjs",
reporterOptions: { foo: "bar" },
},
};
`,
});

const stdoutLines = stdout.join("").split("\n");

expect(tests).toEqual([expect.objectContaining({ name: "bar" })]);
expect(stdoutLines).toEqual(expect.arrayContaining([String.raw`{"foo":"bar"}`]));
});

it("should support reporter constructors", async () => {
const { tests, stdout } = await runCodeceptJsInlineTest({
"foo.test.js": `
Feature("foo")
Scenario('bar', () => {});
`,
"codecept.conf.js": `
const path = require("node:path");
exports.config = {
tests: "./**/*.test.js",
output: path.resolve(__dirname, "./output"),
plugins: {
allure: {
require: require.resolve("allure-codeceptjs"),
enabled: true,
},
},
mocha: {
reporter: function (r, o) {
r.on("start", () => {
console.log(JSON.stringify(o.reporterOptions));
});
},
reporterOptions: { foo: { bar: "baz" } },
},
};
`,
});

const stdoutLines = stdout.join("").split("\n");

expect(tests).toEqual([expect.objectContaining({ name: "bar" })]);
expect(stdoutLines).toEqual(expect.arrayContaining([String.raw`{"foo":{"bar":"baz"}}`]));
});
});
2 changes: 1 addition & 1 deletion packages/allure-codeceptjs/test/spec/testplan.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ it("should support test plan", async () => {
[testPlanFilename]: `${JSON.stringify(exampleTestPlan)}`,
},
{
ALLURE_TESTPLAN_PATH: `./${testPlanFilename}`,
env: { ALLURE_TESTPLAN_PATH: `./${testPlanFilename}` },
},
);

Expand Down
34 changes: 26 additions & 8 deletions packages/allure-codeceptjs/test/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,21 @@ import { attachment, step } from "allure-js-commons";
import type { AllureResults } from "allure-js-commons/sdk";
import { MessageReader } from "allure-js-commons/sdk/reporter";

type RunOptions = {
env?: Record<string, string>;
cwd?: string;
args?: string[];
};

type RunResult = AllureResults & {
stdout: string[];
stderr: string[];
};

export const runCodeceptJsInlineTest = async (
files: Record<string, string | Buffer>,
env?: Record<string, string>,
cwd?: string,
): Promise<AllureResults> => {
{ env, cwd, args: extraCliArgs = [] }: RunOptions = {},
): Promise<RunResult> => {
const testFiles = {
// package.json is used to find project root in case of absolute file paths are used
// eslint-disable-next-line @stylistic/quotes
Expand Down Expand Up @@ -40,7 +50,7 @@ export const runCodeceptJsInlineTest = async (
const modulePath = await step("resolve codeceptjs", () => {
return require.resolve("codeceptjs/bin/codecept.js");
});
const args = ["run", "-c", testDir];
const args = ["run", "-c", testDir, ...extraCliArgs];
const testProcess = await step(`${modulePath} ${args.join(" ")}`, () => {
return fork(modulePath, args, {
env: {
Expand All @@ -53,23 +63,31 @@ export const runCodeceptJsInlineTest = async (
});
});

const stdout: string[] = [];
const stderr: string[] = [];

testProcess.stdout?.setEncoding("utf8").on("data", (chunk) => {
process.stdout.write(String(chunk));
stdout.push(String(chunk));
});
testProcess.stderr?.setEncoding("utf8").on("data", (chunk) => {
process.stderr.write(String(chunk));
stderr.push(String(chunk));
});
const messageReader = new MessageReader();

// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
testProcess.on("message", messageReader.handleMessage);

return new Promise((resolve) => {
testProcess.on("exit", async () => {
await messageReader.attachResults();
if (stdout.length) {
await attachment("stdout", stdout.join("\n"), { contentType: "text/plain" });
}
if (stderr.length) {
await attachment("stderr", stderr.join("\n"), { contentType: "text/plain" });
}
await rm(testDir, { recursive: true });

return resolve(messageReader.results);
return resolve({ ...messageReader.results, stdout, stderr });
});
});
};
16 changes: 15 additions & 1 deletion packages/allure-codeceptjs/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,21 @@ export default defineConfig({
fileParallelism: false,
testTimeout: 5000,
setupFiles: ["./vitest-setup.ts"],
reporters: ["default", ["allure-vitest/reporter", { resultsDir: "./out/allure-results" }]],
reporters: [
"default",
[
"allure-vitest/reporter",
{
resultsDir: "./out/allure-results",
links: {
issue: {
urlTemplate: "https://github.com/allure-framework/allure-js/issues/%s",
nameTemplate: "Issue %s",
},
},
},
],
],
typecheck: {
enabled: true,
tsconfig: "./test/tsconfig.json",
Expand Down

0 comments on commit 72f85e1

Please sign in to comment.