Skip to content

Commit

Permalink
Merge pull request #500 from huwshimi/clientlist-tests
Browse files Browse the repository at this point in the history
WD-17059 - chore(tests): add tests for the client list
  • Loading branch information
huwshimi authored Jan 23, 2025
2 parents 445a40b + d3336f7 commit e1c4cf4
Show file tree
Hide file tree
Showing 10 changed files with 129 additions and 19 deletions.
97 changes: 97 additions & 0 deletions ui/src/pages/clients/ClientList/ClientList.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { screen, within } from "@testing-library/dom";
import MockAdapter from "axios-mock-adapter";
import userEvent from "@testing-library/user-event";

import { axiosInstance } from "api/axios";
import { customWithin } from "test/queries/within";
import { isoTimeToString } from "util/date";
import { LoaderTestId } from "components/Loader";
import { mockClient } from "test/mocks/clients";
import { mockPaginatedResponse } from "test/mocks/responses";
import { PAGE_SIZE } from "util/api";
import { renderComponent } from "test/utils";

import { DeleteClientBtnTestId } from "../DeleteClientBtn";
import { EditClientBtnTestId } from "../EditClientBtn";

import { Label } from "./types";
import ClientList from "./ClientList";
import { Location } from "react-router-dom";
import { panels } from "util/usePanelParams";

const mock = new MockAdapter(axiosInstance);

beforeEach(() => {
mock.reset();
mock
.onGet(`/clients?page_token=&page_size=${PAGE_SIZE}`)
.reply(200, mockPaginatedResponse([], { _meta: {} }));
});

test("displays loading state", () => {
renderComponent(<ClientList />);
expect(screen.getByTestId(LoaderTestId.COMPONENT)).toBeInTheDocument();
});

test("displays empty state", async () => {
renderComponent(<ClientList />);
expect(
await within(await screen.findByRole("grid")).findByText(Label.NO_DATA),
).toBeInTheDocument();
});

test("displays client rows", async () => {
const client = mockClient();
const clients = [client];
mock
.onGet(`/clients?page_token=&size=${PAGE_SIZE}`)
.reply(200, mockPaginatedResponse(clients, { _meta: {} }));
renderComponent(<ClientList />);
const row = await screen.findByRole("row", {
name: new RegExp(client.client_id),
});
expect(
customWithin(row).getCellByHeader(Label.HEADER_ID, { role: "rowheader" }),
).toHaveTextContent(client.client_id);
expect(
customWithin(row).getCellByHeader(Label.HEADER_NAME, {
role: "gridcell",
hasRowHeader: true,
}),
).toHaveTextContent(client.client_name);
expect(
customWithin(row).getCellByHeader(Label.HEADER_DATE, {
role: "gridcell",
hasRowHeader: true,
}),
).toHaveTextContent(
`Created: ${isoTimeToString(client.created_at)}Updated: ${isoTimeToString(client.updated_at)}`,
);
});

test("opens add client panel", async () => {
let location: Location | null = null;
renderComponent(<ClientList />, {
setLocation: (newLocation) => {
location = newLocation;
},
});
await userEvent.click(screen.getByRole("button", { name: Label.ADD }));
expect((location as Location | null)?.search).toBe(
`?panel=${panels.clientCreate}`,
);
});

test("displays edit and delete buttons", async () => {
const clients = [mockClient()];
mock
.onGet(`/clients?page_token=&size=${PAGE_SIZE}`)
.reply(200, mockPaginatedResponse(clients, { _meta: {} }));
renderComponent(<ClientList />);
expect(
await screen.findByTestId(EditClientBtnTestId.COMPONENT),
).toBeInTheDocument();
expect(
await screen.findByTestId(DeleteClientBtnTestId.COMPONENT),
).toBeInTheDocument();
});
24 changes: 7 additions & 17 deletions ui/src/pages/clients/ClientList/ClientList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import DeleteClientBtn from "pages/clients/DeleteClientBtn";
import Loader from "components/Loader";
import Pagination from "components/Pagination";
import { usePagination } from "util/usePagination";
import { Label } from "./types";

const ClientList: FC = () => {
const panelParams = usePanelParams();
Expand All @@ -34,7 +35,7 @@ const ClientList: FC = () => {
</div>
<div className="p-panel__controls">
<Button appearance="positive" onClick={panelParams.openClientCreate}>
Add client
{Label.ADD}
</Button>
</div>
</div>
Expand All @@ -46,23 +47,20 @@ const ClientList: FC = () => {
className="u-table-layout--auto"
responsive
headers={[
{ content: "Id" },
{ content: "Name" },
{ content: "Date" },
{ content: "Actions" },
{ content: Label.HEADER_ID },
{ content: Label.HEADER_NAME },
{ content: Label.HEADER_DATE },
{ content: Label.HEADER_ACTIONS },
]}
rows={response?.data.map((client) => {
return {
columns: [
{
content: client.client_id,
role: "rowheader",
"aria-label": "Id",
},
{
content: client.client_name,
role: "rowheader",
"aria-label": "Name",
},
{
content: (
Expand All @@ -75,8 +73,6 @@ const ClientList: FC = () => {
</div>
</>
),
role: "rowheader",
"aria-label": "Created",
},
{
content: (
Expand All @@ -85,18 +81,12 @@ const ClientList: FC = () => {
<DeleteClientBtn client={client} />
</>
),
role: "rowheader",
"aria-label": "Actions",
},
],
};
})}
emptyStateMsg={
isLoading ? (
<Loader text="Loading clients..." />
) : (
"No data to display"
)
isLoading ? <Loader text="Loading clients..." /> : Label.NO_DATA
}
/>
<Pagination response={response} />
Expand Down
8 changes: 8 additions & 0 deletions ui/src/pages/clients/ClientList/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export enum Label {
ADD = "Add client",
HEADER_ACTIONS = "Actions",
HEADER_DATE = "Date",
HEADER_ID = "Id",
HEADER_NAME = "Name",
NO_DATA = "No data to display",
}
3 changes: 3 additions & 0 deletions ui/src/pages/clients/DeleteClientBtn/DeleteClientBtn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { Client } from "types/client";
import DeletePanelButton from "components/DeletePanelButton";
import { urls } from "urls";
import { Label } from "./types";
import { testId } from "test/utils";
import { TestId } from "./test-types";

interface Props {
client: Client;
Expand All @@ -24,6 +26,7 @@ const DeleteClientBtn: FC<Props> = ({ client }) => {
onDelete={() => deleteClient(client.client_id)}
successPath={urls.clients.index}
successMessage={`Client ${client.client_name} deleted.`}
{...testId(TestId.COMPONENT)}
/>
);
};
Expand Down
1 change: 1 addition & 0 deletions ui/src/pages/clients/DeleteClientBtn/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { default } from "./DeleteClientBtn";
export { TestId as DeleteClientBtnTestId } from "./test-types";
3 changes: 3 additions & 0 deletions ui/src/pages/clients/DeleteClientBtn/test-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export enum TestId {
COMPONENT = "DeleteClientBtn",
}
4 changes: 4 additions & 0 deletions ui/src/pages/clients/EditClientBtn/EditClientBtn.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { FC } from "react";

import EditPanelButton from "components/EditPanelButton";
import { testId } from "test/utils";

import { TestId } from "./test-types";

interface Props {
clientId: string;
Expand All @@ -10,6 +13,7 @@ const EditClientBtn: FC<Props> = ({ clientId }) => {
return (
<EditPanelButton
openPanel={(panelParams) => panelParams.openClientEdit(clientId)}
{...testId(TestId.COMPONENT)}
/>
);
};
Expand Down
1 change: 1 addition & 0 deletions ui/src/pages/clients/EditClientBtn/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { default } from "./EditClientBtn";
export { TestId as EditClientBtnTestId } from "./test-types";
3 changes: 3 additions & 0 deletions ui/src/pages/clients/EditClientBtn/test-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export enum TestId {
COMPONENT = "EditClientBtn",
}
4 changes: 2 additions & 2 deletions ui/src/test/mocks/clients.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const mockClient = (overrides?: Partial<Client>): Client => ({
client_secret_expires_at: faker.number.int(),
client_uri: faker.word.sample(),
contacts: [],
created_at: faker.word.sample(),
created_at: faker.date.anytime().toISOString(),
grant_types: [],
logo_uri: faker.word.sample(),
owner: faker.word.sample(),
Expand All @@ -23,7 +23,7 @@ export const mockClient = (overrides?: Partial<Client>): Client => ({
subject_type: faker.word.sample(),
token_endpoint_auth_method: faker.word.sample(),
tos_uri: faker.word.sample(),
updated_at: faker.word.sample(),
updated_at: faker.date.anytime().toISOString(),
userinfo_signed_response_alg: faker.word.sample(),
...overrides,
});

0 comments on commit e1c4cf4

Please sign in to comment.