Skip to content

Commit

Permalink
Test for performance analysis comparison table (#420)
Browse files Browse the repository at this point in the history
* Test script for PipelineSelect,DeltaComputationBar

* Test script for Performance comparison table

* Review comments - code simplified, typo correction

* Review comments - code simplified, typo correction, add test case for negative delta values

* mock API data corrected to latest

* Review comments - corrected passing arguments to deltacomputation, replaced toHaveTextContent to textcontent
  • Loading branch information
nandhinibsn authored Feb 24, 2023
1 parent 9233a51 commit fb6bf4e
Show file tree
Hide file tree
Showing 10 changed files with 712 additions and 6 deletions.
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"
);
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

0 comments on commit fb6bf4e

Please sign in to comment.