Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test for performance analysis comparison table #420

Merged
merged 6 commits into from
Feb 24, 2023
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,13 @@ describe("PerturbationTestingPreview", () => {
renderPerturbationTestingPreview({ train: true, eval: true });
const header = screen.getByRole("columnheader", { name: /Failure Rate/ });
// before toggle changes
expect(header).toHaveTextContent("Evaluation Set");
expect(header.textContent).toBe("FR on Evaluation Set");
expect(
screen.getByLabelText("Failure Rate on Evaluation Set")
).toBeInTheDocument();
// after toggle changes
fireEvent.click(screen.getByRole("button", { pressed: false }));
expect(header).toHaveTextContent("Training Set");
expect(header.textContent).toBe("FR on Training Set");
expect(
screen.getByLabelText("Failure Rate on Training Set")
).toBeInTheDocument();
Expand Down
2 changes: 1 addition & 1 deletion webapp/src/components/Analysis/PreviewCard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ describe("PreviewCard", () => {
).toBeVisible();
// verify the documentation link
const link: HTMLAnchorElement = screen.getByRole("link");
expect(link).toHaveTextContent("Learn more");
expect(link.textContent).toBe("Learn more");
expect(link.href).toContain("/#performance-analysis");
expect(screen.getByTestId("OpenInNewIcon")).toBeInTheDocument();
// verify if the view details is not displayed if 'to' param is unavailable
Expand Down
44 changes: 44 additions & 0 deletions webapp/src/components/Metrics/DeltaComputationBar.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { screen } from "@testing-library/react";
import { renderWithTheme } from "mocks/utils";
import DeltaComputationBar from "./DeltaComputationBar";

const renderDeltaComputationBar = (
value: number,
formattedValue: string,
width: number
) =>
renderWithTheme(
<DeltaComputationBar
formattedValue={formattedValue}
value={value}
width={width}
/>
);

describe("DeltaComputationBar", () => {
it("should display the bar and the formatter value with expected bgcolor, width and position if the value is greater than 0", () => {
renderDeltaComputationBar(45.5, "45.5", 45.5);
expect(screen.getByTestId("delta-computation-bar")).toHaveStyle(
"width:45.5%;background-color:rgba(99, 204, 255, 0.8);left:50%"
);
expect(screen.getByTestId("delta-computation-value").textContent).toBe(
"+45.5"
JosephMarinier marked this conversation as resolved.
Show resolved Hide resolved
);
expect(screen.getByTestId("delta-computation-value")).toHaveStyle(
"color:rgb(0, 109, 179);right:55%"
);
});

it("should display the bar with expected bgcolor, width and position if the value is less than 0", () => {
renderDeltaComputationBar(-45.5, "-45.5", 45.5);
expect(screen.getByTestId("delta-computation-bar")).toHaveStyle(
"width:45.5%;background-color:rgba(37, 36, 54, 0.6);right:50%"
);
expect(screen.getByTestId("delta-computation-value").textContent).toBe(
"-45.5"
);
expect(screen.getByTestId("delta-computation-value")).toHaveStyle(
"color: rgb(37, 36, 54);left:55%"
);
});
});
2 changes: 2 additions & 0 deletions webapp/src/components/Metrics/DeltaComputationBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const DeltaComputationBar: React.FC<Props> = ({
{value ? (
<Box width="100%" flex="1" position="relative" marginY={1}>
<Box
data-testid="delta-computation-bar"
component={motion.div}
position="absolute"
overflow="auto"
Expand All @@ -49,6 +50,7 @@ const DeltaComputationBar: React.FC<Props> = ({
></Box>

<Typography
data-testid="delta-computation-value"
position="absolute"
sx={{
...(value > 0 ? { right: "55%" } : { left: "55%" }),
Expand Down
6 changes: 3 additions & 3 deletions webapp/src/components/Metrics/PerformanceAnalysis.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ describe("PerformanceAnalysis", () => {
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

it("should have two toggle buttons for the train and test", () => {
it("should display two toggle buttons for the train and test", () => {
renderPerformanceAnalysis({ train: true, eval: true });
// verify if the toggles displayed with correct names
expect(
Expand Down Expand Up @@ -65,7 +65,7 @@ describe("PerformanceAnalysis", () => {
expectedColumnHeaders.forEach((name, index) => {
name.includes("&")
? within(actualColumnHeaders[index]).getByLabelText(name)
: expect(actualColumnHeaders[index]).toHaveTextContent(name);
: expect(actualColumnHeaders[index].textContent).toBe(name);
});
});
});
Expand Down Expand Up @@ -95,7 +95,7 @@ describe("PerformanceAnalysis", () => {
];
expect(filterList).toHaveLength(expectedList.length);
filterList.forEach((item, index) => {
expect(item).toHaveTextContent(expectedList[index]);
expect(item.textContent).toBe(expectedList[index]);
});

expect(screen.getByRole("option", { name: "Smart Tags" })).toHaveAttribute(
Expand Down
207 changes: 207 additions & 0 deletions webapp/src/components/Metrics/PerformanceAnalysisTable.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
import { fireEvent, screen, waitFor, within } from "@testing-library/react";
import { renderWithRouterAndRedux } from "mocks/utils";
import PerformanceAnalysisTable from "./PerformanceAnalysisTable";
import { AvailableDatasetSplits, DatasetSplitName } from "types/api";
import { setupServer } from "msw/node";
import {
getCustomMetricInfoAPIResponse,
getMetricsPerFilterAPIResponse,
getMetricsPerFilterAPIWithFailureResponse,
} from "mocks/api/mockMetricsAPI";
import {
getConfigAPIResponse,
getConfigMultipipelineAPIResponse,
} from "mocks/api/mockConfigAPI";

const setDatasetSplitName = jest.fn();
const renderPerformanceAnalysisTable = (
availableDatasetSplits: AvailableDatasetSplits,
datasetSplitName: DatasetSplitName
) =>
renderWithRouterAndRedux(
<PerformanceAnalysisTable
jobId="local"
pipeline={{ pipelineIndex: 0 }}
availableDatasetSplits={availableDatasetSplits}
isLoading={false}
datasetSplitName={datasetSplitName}
setDatasetSplitName={setDatasetSplitName}
/>,
{ route: "/local?pipeline_index=0", path: "/:jobId?:pipeline" }
);

describe("PerformanceAnalysisComparisonTableWithNoComparedPipeline", () => {
const handlers = [
getConfigAPIResponse,
getCustomMetricInfoAPIResponse,
getMetricsPerFilterAPIResponse,
];
const server = setupServer(...handlers);

beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

it("should display two toggle buttons for the train and test", () => {
renderPerformanceAnalysisTable({ train: true, eval: true }, "eval");
// verify if the toggles displayed with correct names
expect(
screen.getByRole("button", { name: "Evaluation Set", pressed: true })
).toHaveValue("eval");
expect(
screen.getByRole("button", { name: "Training Set", pressed: false })
).toHaveValue("train");
});

it("should display the expected columns", async () => {
renderPerformanceAnalysisTable({ train: true, eval: true }, "eval");
await waitFor(() => {
const expectedColumnHeaders = [
"filterValue",
"Total",
"Correct & Predicted",
"Correct & Rejected",
"Incorrect & Rejected",
"Incorrect & Predicted",
"Accuracy",
"Precision",
"Recall",
"F1",
"ECE",
];
const actualColumnHeaders = screen.getAllByRole("columnheader");
expectedColumnHeaders.forEach((name, index) => {
name.includes("&")
? within(actualColumnHeaders[index]).getByLabelText(name)
: expect(actualColumnHeaders[index].textContent).toBe(name);
});
});
});

it("should display the default sort as desc for colum header 'Total number of utterances'", () => {
renderPerformanceAnalysisTable({ train: true, eval: true }, "eval");
const header = screen.getByRole("columnheader", { name: /Total/ });
expect(header).toHaveAttribute("aria-sort", "descending");
});

it("should display the list of options if the user click on the column header 'filterValue'", () => {
renderPerformanceAnalysisTable({ train: true, eval: true }, "eval");
fireEvent.mouseDown(screen.getByRole("button", { name: "Label" }));
const filterList = screen.getAllByRole("option");

const expectedList = [
"Label",
"Prediction",
"Smart Tags",
"Extreme Length",
"Partial Syntax",
"Dissimilar",
"Almost Correct",
"Behavioral Testing",
"Pipeline Comparison",
"Uncertain",
];
expect(filterList).toHaveLength(expectedList.length);
filterList.forEach((item, index) => {
expect(item.textContent).toBe(expectedList[index]);
});

expect(screen.getByRole("option", { name: "Smart Tags" })).toHaveAttribute(
"aria-selected",
"false"
);
});
});

describe("PerformanceAnalysisComparisonTableWithMultiPipeline", () => {
const handlers = [
getConfigMultipipelineAPIResponse,
getCustomMetricInfoAPIResponse,
getMetricsPerFilterAPIResponse,
];
const server = setupServer(...handlers);

beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

it("should display pipeline select component if the config has more than one pipeline", async () => {
renderPerformanceAnalysisTable({ train: true, eval: true }, "eval");
await screen.findByText("Compare Baseline (Pipeline_0) with:");
});

it("should display list of pipelines", async () => {
renderPerformanceAnalysisTable({ train: true, eval: true }, "eval");

await waitFor(() => {
fireEvent.mouseDown(screen.getByRole("button", { name: "No pipeline" }));
const pipelineList = screen.getAllByRole("option");
const expectedPipelineList = [
"No pipeline",
"Pipeline_0",
"Pipeline_1",
"Pipeline_2",
"Pipeline_3",
];
expect(pipelineList).toHaveLength(expectedPipelineList.length);
pipelineList.forEach((item, index) => {
expect(item.textContent).toBe(expectedPipelineList[index]);
});
expect(screen.getByRole("option", { name: "Pipeline_0" })).toHaveClass(
"Mui-disabled"
);
});
});

it("should display the expected columns", async () => {
renderPerformanceAnalysisTable({ train: true, eval: true }, "eval");
fireEvent.mouseDown(
await screen.findByRole("button", { name: "No pipeline" })
);
fireEvent.click(await screen.findByRole("option", { name: "Pipeline_1" }));
await waitFor(() => {
const expectedColumnHeaders = [
"filterValue",
"Total",
...[
"Correct & Predicted",
"Correct & Rejected",
"Incorrect & Rejected",
"Incorrect & Predicted",
"Accuracy",
"Precision",
"Recall",
"F1",
"ECE",
].flatMap((header) => ["Pipeline_0" + header, "Pipeline_1", "Delta"]),
];
const actualColumnHeaders = screen.getAllByRole("columnheader");
expectedColumnHeaders.forEach((name, index) => {
expect(actualColumnHeaders[index].textContent).toBe(name);
});
});
});
});

describe("MetricsPerFilterAPIWithFailureResponse", () => {
const handlers = [
getMetricsPerFilterAPIWithFailureResponse,
getCustomMetricInfoAPIResponse,
getConfigAPIResponse,
];
const server = setupServer(...handlers);

beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

it("should display the error message if the API fails", async () => {
renderPerformanceAnalysisTable({ train: true, eval: true }, "eval");
await waitFor(() => {
// expected error message
expect(
screen.getByText("Something went wrong fetching metrics per filter")
).toBeVisible();
});
});
});
39 changes: 39 additions & 0 deletions webapp/src/components/PipelineSelect.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { fireEvent, screen, waitFor, within } from "@testing-library/react";
import PipelineSelect from "./PipelineSelect";
import { renderWithTheme } from "mocks/utils";

const handleOnChange = jest.fn();

describe("PipelineSelect", () => {
const pipelines = [
{ name: "Pipeline_0" },
{ name: "Pipeline_1" },
{ name: "Pipeline_2" },
];
const allPipelines = [
"No pipeline",
"Pipeline_0",
"Pipeline_1",
"Pipeline_2",
];
it("should list all the pipelines", () => {
renderWithTheme(
<PipelineSelect
selectedPipeline={undefined}
onChange={handleOnChange}
pipelines={pipelines}
disabledPipelines={[]}
/>
);
fireEvent.mouseDown(screen.getByRole("button", { name: "No pipeline" }));
const pipelineListOptions = screen.getAllByRole("option");

expect(pipelineListOptions).toHaveLength(allPipelines.length);
pipelineListOptions.forEach((item, index) => {
expect(item.textContent).toBe(allPipelines[index]);
});

fireEvent.click(screen.getByRole("option", { name: "Pipeline_0" }));
expect(handleOnChange).toBeCalledWith(0);
});
});
Loading