Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/plugin-api/src/report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export type ReportOptions = {
ci?: CiDescriptor;
executor?: ReportExecutorInfo;
runSummary?: ReportRunSummary;
runSummaryByEnv?: Record<string, ReportRunSummary>;
stepTreeExpansion?: StepTreeExpansion;
defaultSortBy?: string;
};
Expand Down
3 changes: 3 additions & 0 deletions packages/plugin-awesome/src/generators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,7 @@ export const generateStaticFiles = async (
reportName: string;
executor?: ReportExecutorInfo;
runSummary?: ReportRunSummary;
runSummaryByEnv?: Record<string, ReportRunSummary>;
},
) => {
const {
Expand All @@ -692,6 +693,7 @@ export const generateStaticFiles = async (
ci,
executor,
runSummary,
runSummaryByEnv,
stepTreeExpansion,
defaultSortBy,
} = payload;
Expand Down Expand Up @@ -748,6 +750,7 @@ export const generateStaticFiles = async (
ci,
executor,
runSummary,
runSummaryByEnv,
layout,
allureVersion,
sections,
Expand Down
12 changes: 12 additions & 0 deletions packages/plugin-awesome/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { incrementStatistic, type EnvironmentItem, type Statistic, joinPosixPath
import {
type AllureStore,
type ReportExecutorInfo,
type ReportRunSummary,
type Plugin,
type PluginContext,
type PluginSummary,
Expand Down Expand Up @@ -135,6 +136,16 @@ export class AwesomePlugin implements Plugin {
}),
);

const runSummaryByEnv: Record<string, ReportRunSummary> = {};

for (const { id } of environments) {
const envRunSummary = getRunSummary(trsByEnvId.get(id) ?? []);

if (envRunSummary) {
runSummaryByEnv[id] = envRunSummary;
}
}

await generateStatistic(this.#writer!, {
stats: statistics,
statsByEnv: envStatistics,
Expand Down Expand Up @@ -239,6 +250,7 @@ export class AwesomePlugin implements Plugin {
ci: context.ci,
executor,
runSummary,
runSummaryByEnv,
reportDataFiles,
});
};
Expand Down
77 changes: 71 additions & 6 deletions packages/plugin-awesome/test/plugin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -753,20 +753,32 @@ describe("plugin", () => {
});

describe("report assets", () => {
const environmentIdOf = (tr: TestResult) => tr.environment ?? "default";

const makeSingleFileStore = (testResults: TestResult[], metadata: Record<string, unknown> = {}): AllureStore =>
({
metadataByKey: vi.fn(async (key: string) => metadata[key]),
allEnvironments: vi.fn().mockResolvedValue(["default"]),
allEnvironmentIdentities: vi
.fn()
.mockResolvedValue([{ id: "default", name: "default" } satisfies EnvironmentIdentity]),
allEnvironments: vi.fn(async () => [...new Set(testResults.map(environmentIdOf))]),
allEnvironmentIdentities: vi.fn(
async () =>
[...new Set(testResults.map(environmentIdOf))].map((id) => ({
id,
name: id,
})) satisfies EnvironmentIdentity[],
),
allAttachments: vi.fn().mockResolvedValue([]),
allTestResults: vi.fn(async (options?: { includeRetries?: boolean; filter?: (tr: TestResult) => boolean }) => {
const trs = options?.filter ? testResults.filter(options.filter) : testResults;
return trs;
}),
testResultsByEnvironmentId: vi.fn().mockResolvedValue(testResults),
environmentIdByTrId: vi.fn().mockResolvedValue("default"),
testResultsByEnvironmentId: vi.fn(async (envId: string) =>
testResults.filter((tr) => environmentIdOf(tr) === envId),
),
environmentIdByTrId: vi.fn(async (trId: string) => {
const tr = testResults.find(({ id }) => id === trId);

return tr ? environmentIdOf(tr) : undefined;
}),
testsStatistic: vi.fn(async (filter: (tr: TestResult) => boolean) => getTestResultsStats(testResults, filter)),
allTestEnvGroups: vi.fn().mockResolvedValue([]),
allGlobalAttachments: vi.fn().mockResolvedValue([]),
Expand Down Expand Up @@ -1034,5 +1046,58 @@ describe("plugin", () => {
});
expect(reportOptions.executor).toEqual(executor);
});

it("should include a separate launch interval for every environment", async () => {
const testResults: TestResult[] = [
{
id: "tr-staging",
name: "staging test",
status: "passed",
environment: "staging",
start: 1000,
stop: 3000,
labels: [],
},
{
id: "tr-staging-retry",
name: "staging test",
status: "failed",
environment: "staging",
isRetry: true,
start: 500,
stop: 900,
labels: [],
},
{
id: "tr-prod",
name: "prod test",
status: "passed",
environment: "prod",
start: 10_000,
stop: 12_500,
labels: [],
},
] as unknown as TestResult[];
const addedFiles = new Map<string, Buffer>();
const reportFiles: ReportFiles = {
addFile: vi.fn(async (path: string, data: Buffer) => {
addedFiles.set(path, data);
return path;
}),
};
const plugin = new AwesomePlugin({ singleFile: true });

await plugin.start(makeSingleFileContext(reportFiles));
await plugin.done(makeSingleFileContext(reportFiles), makeSingleFileStore(testResults));

const reportOptions = extractReportOptions(addedFiles.get("index.html")?.toString("utf-8") ?? "");

// The report-wide summary still spans everything, the per-environment ones must not.
expect(reportOptions.runSummary).toEqual({ start: 500, stop: 12_500, duration: 12_000 });
expect(reportOptions.runSummaryByEnv).toEqual({
staging: { start: 500, stop: 3000, duration: 2500 },
prod: { start: 10_000, stop: 12_500, duration: 2500 },
});
});
});
});
11 changes: 8 additions & 3 deletions packages/web-awesome/src/components/ReportHeader/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ReportHeaderLogo } from "@/components/ReportHeader/ReportHeaderLogo";
import { ReportHeaderPie } from "@/components/ReportHeader/ReportHeaderPie";
import { TrStatus } from "@/components/TestResult/TrStatus";
import { useI18n } from "@/stores";
import { currentEnvironment } from "@/stores/env";
import { globalsStore } from "@/stores/globals";
import { timestampToDate } from "@/utils/time";

Expand All @@ -22,11 +23,15 @@ const reportDateOptions: Intl.DateTimeFormatOptions = {
};

export const ReportHeader = () => {
const { reportName, createdAt, runSummary } = getReportOptions<ReportOptions>() ?? {};
const { reportName, createdAt, runSummary, runSummaryByEnv } = getReportOptions<ReportOptions>() ?? {};
const { t } = useI18n("ui");
const environmentId = currentEnvironment.value;
// With a single environment selected, show that environment's own launch interval instead of the
// report-wide one, which spans the earliest start and the latest stop across all environments.
const selectedRunSummary = environmentId ? runSummaryByEnv?.[environmentId] : runSummary;
const formattedCreatedAt = timestampToDate(createdAt as number, reportDateOptions);
const formattedReportTime = runSummary
? `${timestampToDate(runSummary.start, reportDateOptions)} (${formatDuration(runSummary.duration)})`
const formattedReportTime = selectedRunSummary
? `${timestampToDate(selectedRunSummary.start, reportDateOptions)} (${formatDuration(selectedRunSummary.duration)})`
: formattedCreatedAt;

return (
Expand Down
39 changes: 39 additions & 0 deletions packages/web-awesome/test/components/ReportHeader.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,18 @@ vi.mock("@/stores", () => ({
}),
}));

const { currentEnvironment } = vi.hoisted(() => ({ currentEnvironment: { value: "" } }));

vi.mock("@/stores/env", () => ({ currentEnvironment }));

vi.mock("@/utils/time", () => ({
timestampToDate: (value: number, options?: Intl.DateTimeFormatOptions) =>
`${options?.month === "long" ? "long" : "default"}:${value}`,
}));

beforeEach(() => {
vi.clearAllMocks();
currentEnvironment.value = "";
});

describe("components > ReportHeader", () => {
Expand Down Expand Up @@ -74,4 +79,38 @@ describe("components > ReportHeader", () => {

expect(screen.getByTestId("report-data")).toHaveTextContent("long:10");
});

it("should render the selected environment's launch start time instead of the report-wide one", () => {
(getReportOptions as Mock).mockReturnValue({
reportName: "Wrike report",
createdAt: 42,
runSummary: { start: 1000, stop: 12_500, duration: 11_500 },
runSummaryByEnv: {
staging: { start: 1000, stop: 3000, duration: 2000 },
prod: { start: 10_000, stop: 12_500, duration: 2500 },
},
});
currentEnvironment.value = "prod";

render(<ReportHeader />);

// "long:1000" (the report-wide start) is not a substring of the rendered "long:10000".
expect(screen.getByTestId("report-data")).toHaveTextContent("long:10000");
});

it("should fall back to generated time when the selected environment has no launch interval", () => {
(getReportOptions as Mock).mockReturnValue({
reportName: "Wrike report",
createdAt: 42,
runSummary: { start: 1000, stop: 12_500, duration: 11_500 },
runSummaryByEnv: {
staging: { start: 1000, stop: 3000, duration: 2000 },
},
});
currentEnvironment.value = "prod";

render(<ReportHeader />);

expect(screen.getByTestId("report-data")).toHaveTextContent("long:42");
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ describe("components > TestResult > PwTraceButton", () => {

expect(fetchFromUrl).toHaveBeenCalledTimes(1);
expect(openModal).not.toHaveBeenCalled();
});
}, 15000);

it("shows popup-blocked modal when new tab cannot be opened", async () => {
const { fetchFromUrl, openModal, openPlaywrightTraceInNewTab } = await setup({
Expand All @@ -103,7 +103,7 @@ describe("components > TestResult > PwTraceButton", () => {
title: "Playwright Trace Viewer | trace.zip",
}),
);
});
}, 15000);

it("starts loading trace attachment after opening the popup", async () => {
const { fetchFromUrl, openModal, openPlaywrightTraceInNewTab } = await setup({
Expand All @@ -117,5 +117,5 @@ describe("components > TestResult > PwTraceButton", () => {

expect(openPlaywrightTraceInNewTab).toHaveBeenCalledTimes(1);
expect(openModal).not.toHaveBeenCalled();
});
}, 15000);
});
2 changes: 1 addition & 1 deletion packages/web-awesome/test/components/Timeline.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,5 +108,5 @@ describe("components > Timeline", () => {

expect(screen.getByTestId("timeline-shared-host")).toHaveTextContent("tr-qa-a");
expect(screen.getByTestId("timeline-shared-host")).not.toHaveTextContent("tr-qa-b");
});
}, 15000);
});
Loading