Skip to content

Commit

Permalink
allow to attach cypress videos only for failed or broken tests
Browse files Browse the repository at this point in the history
  • Loading branch information
epszaw committed Jul 5, 2024
1 parent 7a01d04 commit b7650a7
Show file tree
Hide file tree
Showing 4 changed files with 232 additions and 33 deletions.
22 changes: 22 additions & 0 deletions packages/allure-cypress/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,28 @@ module.exports = {
};
```

## Write video attachments for failed tests only

If you want to see Cypress videos only for failed or broken tests in your Allure report, you can use the `videoOnFailOnly` option:

```diff
const { allureCypress } = require("allure-cypress/reporter");

module.exports = {
// ...
e2e: {
+ video: true,
setupNodeEvents: (on, config) => {
allureCypress(on, {
+ videoOnFailOnly: true,
});

return config;
},
},
};
```

## Known issues

### Global hooks reporting
Expand Down
5 changes: 5 additions & 0 deletions packages/allure-cypress/src/model.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import type { Status, StatusDetails } from "allure-js-commons";
import type { RuntimeMessage } from "allure-js-commons/sdk";
import type { Config } from "allure-js-commons/sdk/reporter";

export const ALLURE_REPORT_SYSTEM_HOOK = "__allure_report_system_hook__";

export const ALLURE_REPORT_STEP_COMMAND = "__allure_report_step_command__";

export type AllureCypressConfig = Config & {
videoOnFailOnly?: boolean;
};

export type CypressTest = Mocha.Test & {
wallClockStartedAt?: Date;
hookName?: string;
Expand Down
18 changes: 13 additions & 5 deletions packages/allure-cypress/src/reporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import {
getSuiteLabels,
parseTestPlan,
} from "allure-js-commons/sdk/reporter";
import type { Config } from "allure-js-commons/sdk/reporter";
import type {
AllureCypressConfig,
CypressHookEndMessage,
CypressHookStartMessage,
CypressMessage,
Expand All @@ -23,10 +23,12 @@ export class AllureCypress {
messagesByAbsolutePath = new Map<string, CypressMessage[]>();
runContextByAbsolutePath = new Map<string, RunContextByAbsolutePath>();
globalHooksMessages: CypressMessage[] = [];
videoOnFailOnly: boolean = false;

constructor(config?: Config) {
const { resultsDir = "./allure-results", ...rest } = config || {};
constructor(config?: AllureCypressConfig) {
const { resultsDir = "./allure-results", videoOnFailOnly = false, ...rest } = config || {};

this.videoOnFailOnly = videoOnFailOnly;
this.allureRuntime = new ReporterRuntime({
writer: new FileSystemWriter({
resultsDir,
Expand Down Expand Up @@ -76,6 +78,12 @@ export class AllureCypress {
endSpec(spec: Cypress.Spec, cypressVideoPath?: string) {
const specMessages = this.messagesByAbsolutePath.get(spec.absolute) ?? [];
const runContext = this.runContextByAbsolutePath.get(spec.absolute)!;
const isSpecFailed = specMessages.some(
(message) =>
message.type === "cypress_test_end" &&
(message.data.status === Status.FAILED || message.data.status === Status.BROKEN),
);
const shouldVideoBeAttached = (!this.videoOnFailOnly || isSpecFailed) && cypressVideoPath;

specMessages.forEach((message, i) => {
// we add cypressTestId to messages where it's possible because the field is very useful to glue data
Expand Down Expand Up @@ -233,7 +241,7 @@ export class AllureCypress {
this.allureRuntime.applyRuntimeMessages(last(runContext.executables)!, [message] as RuntimeMessage[]);
});

if (cypressVideoPath) {
if (shouldVideoBeAttached) {
const fixtureUuid = this.allureRuntime.startFixture(runContext.scopes[0], "after", {
name: "Cypress video",
status: Status.PASSED,
Expand Down Expand Up @@ -277,7 +285,7 @@ export class AllureCypress {
}
}

export const allureCypress = (on: Cypress.PluginEvents, allureConfig?: Config) => {
export const allureCypress = (on: Cypress.PluginEvents, allureConfig?: AllureCypressConfig) => {
const allureCypressReporter = new AllureCypress(allureConfig);

allureCypressReporter.attachToCypress(on);
Expand Down
220 changes: 192 additions & 28 deletions packages/allure-cypress/test/spec/video.test.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { expect, it } from "vitest";
import { describe, expect, it } from "vitest";
import { ContentType } from "allure-js-commons";
import { runCypressInlineTest } from "../utils.js";

it("attaches same video to each spec in a test", async () => {
const { tests, groups } = await runCypressInlineTest({
"cypress/e2e/sample.cy.js": () => `
it("foo", () => {});
describe("write video for every test", () => {
it("attaches same video to each spec in a test", async () => {
const { tests, groups } = await runCypressInlineTest({
"cypress/e2e/sample.cy.js": () => `
it("foo", () => {});
it("bar", () => {});
`,
"cypress.config.js": () =>
`
it("bar", () => {});
`,
"cypress.config.js": () =>
`
const { allureCypress } = require("allure-cypress/reporter");
module.exports = {
Expand All @@ -37,25 +38,188 @@ it("attaches same video to each spec in a test", async () => {
},
};
`,
});

expect(tests).toHaveLength(2);
expect(groups).toHaveLength(1);
expect(groups[0]).toEqual(
expect.objectContaining({
name: "Cypress video",
children: expect.arrayContaining([tests[0].uuid, tests[1].uuid]),
afters: [
expect.objectContaining({
name: "Cypress video",
attachments: [
expect.objectContaining({
name: "Cypress video",
type: ContentType.MP4,
}),
],
}),
],
}),
);
});
});

describe("write video for failed tests only", () => {
it("doesn't attach video for passed tests", async () => {
const { tests, groups } = await runCypressInlineTest({
"cypress/e2e/sample.cy.js": () => `
it("foo", () => {});
`,
"cypress.config.js": () =>
`
const { allureCypress } = require("allure-cypress/reporter");
module.exports = {
e2e: {
baseUrl: "https://allurereport.org",
viewportWidth: 1240,
video: true,
setupNodeEvents: (on, config) => {
allureCypress(on, {
videoOnFailOnly: true,
links: [
{
type: "issue",
urlTemplate: "https://allurereport.org/issues/%s"
},
{
type: "tms",
urlTemplate: "https://allurereport.org/tasks/%s"
},
]
});
return config;
},
},
};
`,
});

expect(tests).toHaveLength(1);
expect(groups).toHaveLength(0);
});

it("attaches video for failed tests", async () => {
const { tests, groups } = await runCypressInlineTest({
"cypress/e2e/sample.cy.js": () => `
it("foo", () => {
cy.wrap(1).eq(2);
});
`,
"cypress.config.js": () =>
`
const { allureCypress } = require("allure-cypress/reporter");
expect(tests).toHaveLength(2);
expect(groups).toHaveLength(1);
expect(groups[0]).toEqual(
expect.objectContaining({
name: "Cypress video",
children: expect.arrayContaining([tests[0].uuid, tests[1].uuid]),
afters: [
expect.objectContaining({
name: "Cypress video",
attachments: [
expect.objectContaining({
name: "Cypress video",
type: ContentType.MP4,
}),
],
}),
],
}),
);
module.exports = {
e2e: {
baseUrl: "https://allurereport.org",
viewportWidth: 1240,
video: true,
testTimeout: 500,
setupNodeEvents: (on, config) => {
allureCypress(on, {
videoOnFailOnly: true,
links: [
{
type: "issue",
urlTemplate: "https://allurereport.org/issues/%s"
},
{
type: "tms",
urlTemplate: "https://allurereport.org/tasks/%s"
},
]
});
return config;
},
},
};
`,
});

expect(tests).toHaveLength(1);
expect(groups).toHaveLength(1);
expect(groups[0]).toEqual(
expect.objectContaining({
name: "Cypress video",
children: expect.arrayContaining([tests[0].uuid]),
afters: [
expect.objectContaining({
name: "Cypress video",
attachments: [
expect.objectContaining({
name: "Cypress video",
type: ContentType.MP4,
}),
],
}),
],
}),
);
});

it("attaches video for broken tests", async () => {
const { tests, groups } = await runCypressInlineTest({
"cypress/e2e/sample.cy.js": () => `
it("foo", () => {
throw new Error("foo");
});
`,
"cypress.config.js": () =>
`
const { allureCypress } = require("allure-cypress/reporter");
module.exports = {
e2e: {
baseUrl: "https://allurereport.org",
viewportWidth: 1240,
video: true,
testTimeout: 500,
setupNodeEvents: (on, config) => {
allureCypress(on, {
videoOnFailOnly: true,
links: [
{
type: "issue",
urlTemplate: "https://allurereport.org/issues/%s"
},
{
type: "tms",
urlTemplate: "https://allurereport.org/tasks/%s"
},
]
});
return config;
},
},
};
`,
});

expect(tests).toHaveLength(1);
expect(groups).toHaveLength(1);
expect(groups[0]).toEqual(
expect.objectContaining({
name: "Cypress video",
children: expect.arrayContaining([tests[0].uuid]),
afters: [
expect.objectContaining({
name: "Cypress video",
attachments: [
expect.objectContaining({
name: "Cypress video",
type: ContentType.MP4,
}),
],
}),
],
}),
);
});
});

0 comments on commit b7650a7

Please sign in to comment.