Skip to content

Commit

Permalink
add vitest
Browse files Browse the repository at this point in the history
  • Loading branch information
RenauxLeaInsee committed Apr 15, 2024
1 parent 5cd8d4b commit 9ef733b
Show file tree
Hide file tree
Showing 9 changed files with 2,819 additions and 37 deletions.
15 changes: 13 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
{
"name": "sonor",
"private": true,
"version": "2.0.26",
"version": "2.0.27",
"type": "module",
"scripts": {
"dev": "vite",
"test": "vitest",
"openapi": "o2ts ./openapi.json src/types/api.ts",
"build": "tsc && vite build",
"check": "tsc",
Expand Down Expand Up @@ -36,15 +37,25 @@
},
"devDependencies": {
"@grafikart/o2ts": "^0.1.15",
"@testing-library/jest-dom": "^6.4.2",
"@testing-library/react": "^15.0.1",
"@testing-library/user-event": "^14.5.2",
"@types/jest": "^29.5.12",
"@types/react": "^18.2.56",
"@types/react-dom": "^18.2.19",
"@typescript-eslint/eslint-plugin": "^7.0.2",
"@typescript-eslint/parser": "^7.0.2",
"@vitejs/plugin-react": "^4.2.1",
"@vitest/coverage-v8": "^1.5.0",
"eslint": "^8.56.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.5",
"jest": "^29.7.0",
"jest-sonar-reporter": "^2.0.0",
"jsdom": "^24.0.0",
"typescript": "^5.2.2",
"vite": "^5.1.4"
"vite": "^5.1.4",
"vite-tsconfig-paths": "^4.3.2",
"vitest": "^1.5.0"
}
}
1 change: 1 addition & 0 deletions setupTest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import '@testing-library/jest-dom';
19 changes: 19 additions & 0 deletions src/WrappedRender.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { render } from "@testing-library/react";
import { BrowserRouter as Router, createBrowserRouter } from "react-router-dom";
import { routes } from "./routes";
import { messagesFr } from "./i18n-fr";
import { IntlProvider } from "react-intl";
import { ReactElement } from "react";
import { SonorTheme } from "./theme";

const router = createBrowserRouter(routes);

export const WrappedRender = (children: ReactElement) => {
return render(
<SonorTheme>
<IntlProvider locale="fr" messages={messagesFr}>
<Router {...router}>{children}</Router>
</IntlProvider>
</SonorTheme>,
);
};
43 changes: 43 additions & 0 deletions src/ui/Header.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { fireEvent, screen } from "@testing-library/react";
import { Header } from "./Header";
import { WrappedRender } from "../WrappedRender";
import * as hooks from "../hooks/useAuth";

describe("Header component", () => {
beforeAll(() => {
vi.spyOn(hooks, "useUser").mockImplementation(() => {
return { name: "John Doe", inseegroupedefaut: ["gr"], preferred_username: "username" };
});
vi.spyOn(hooks, "useLogout").mockImplementation(vi.fn());
});

it("should render labels and user name in Header ", () => {
WrappedRender(<Header />);

expect(screen.getByText("Sabiane Gestion")).toBeInTheDocument();
expect(screen.getByText("Suivre")).toBeInTheDocument();
expect(screen.getByText("Lire")).toBeInTheDocument();
expect(screen.getByText("Clore")).toBeInTheDocument();
expect(screen.getByText("Notifier")).toBeInTheDocument();
expect(screen.getByText("Réaffectation")).toBeInTheDocument();
expect(screen.getByText("Organisation des collectes")).toBeInTheDocument();
expect(screen.getByText("John Doe")).toBeInTheDocument();
});

it("should open account menu and call logout", () => {
const logoutMock = vi.fn();
vi.spyOn(hooks, "useLogout").mockImplementation(() => {
return logoutMock;
});
WrappedRender(<Header />);

fireEvent.click(screen.getByText("John Doe"));

const logoutButton = screen.getByText("Se déconnecter");
expect(logoutButton).toBeInTheDocument();

fireEvent.click(logoutButton);

expect(logoutMock).toHaveBeenCalled();
});
});
35 changes: 35 additions & 0 deletions src/ui/Link.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { fireEvent, render, screen } from "@testing-library/react";
import { Link } from "./Link";
import { Route, BrowserRouter as Router, Routes } from "react-router-dom";

describe("Link component", () => {
const label = "Link text";
const otherPage = "Other page";

it("should render Link", () => {
render(
<Router>
<Link to={"/path"}>{label}</Link>
</Router>,
);

expect(screen.getByText(label)).toBeInTheDocument();
});

it("should navigate", () => {
render(
<Router>
<Routes>
<Route path="/" element={<Link to={"/path"}>{label}</Link>} />
<Route path="/path" element={<Link to={"/"}>{otherPage}</Link>} />
</Routes>
</Router>,
);

expect(screen.getByText(label)).toBeInTheDocument();

fireEvent.click(screen.getByText(label));

expect(screen.getByText(otherPage)).toBeInTheDocument();
});
});
127 changes: 127 additions & 0 deletions src/ui/SelectWithCheckbox.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { fireEvent, screen, waitFor, waitForElementToBeRemoved } from "@testing-library/react";
import { WrappedRender } from "../WrappedRender";
import { SelectWithCheckbox } from "./SelectWithCheckbox";
import userEvent from "@testing-library/user-event";

describe("SelectWithCheckbox component", () => {
it("should render select without search field ", () => {
const interviewersMock = [
{
label: "john Doe",
value: "1",
},
{ label: "james Doe", value: "2" },
{ label: "Jean Dupont", value: "3" },
];
const label = "interviewer";

const toggleSearchFilterMock = vi.fn();
WrappedRender(
<SelectWithCheckbox
label={label}
name={"interviewer"}
options={interviewersMock}
toggleSearchFilter={toggleSearchFilterMock}
filters={{
campaigns: [],
ssech: [],
interviewer: [],
states: [],
closingCause: [],
priority: [],
all: [],
}}
/>,
);

const select = screen.getByText(label);

expect(select).toBeInTheDocument();

fireEvent.click(select);

expect(screen.getByText("john Doe")).toBeInTheDocument();
expect(screen.getByText("james Doe")).toBeInTheDocument();
// verify if search field label is not in the document
expect(screen.queryByText("Recherche")).not.toBeInTheDocument();
});

it("should render select with search field and filtered", async () => {
const interviewersMock = [
{
label: "John Doe",
value: "1",
},
{ label: "Paul Dupont", value: "2" },
];
const label = "interviewer";

const toggleSearchFilterMock = vi.fn();
WrappedRender(
<SelectWithCheckbox
label={label}
name={"interviewer"}
options={interviewersMock}
toggleSearchFilter={toggleSearchFilterMock}
filters={{
campaigns: [],
ssech: [],
interviewer: [],
states: [],
closingCause: [],
priority: [],
all: [],
}}
canSearch={true}
/>,
);

fireEvent.click(screen.getByText(label));

expect(screen.getByText("John Doe")).toBeInTheDocument();
expect(screen.getByText("Paul Dupont")).toBeInTheDocument();
await waitFor(() => userEvent.type(screen.getByRole("textbox"), "J"));
await waitForElementToBeRemoved(screen.queryByText("Paul Dupont"));

expect(screen.queryByText("Paul Dupont")).not.toBeInTheDocument();
expect(screen.getByText("John Doe")).toBeInTheDocument();
});

it("should correctly call toggleSearchFilter", () => {
const interviewersMock = [
{
label: "John Doe",
value: "1",
},
{ label: "Paul Dupont", value: "2" },
];
const label = "interviewer";

const toggleSearchFilterMock = vi.fn();
WrappedRender(
<SelectWithCheckbox
label={label}
name={"interviewer"}
options={interviewersMock}
toggleSearchFilter={toggleSearchFilterMock}
filters={{
campaigns: [],
ssech: [],
interviewer: [],
states: [],
closingCause: [],
priority: [],
all: [],
}}
canSearch={true}
/>,
);

fireEvent.click(screen.getByText(label));
expect(screen.getByText("John Doe")).toBeInTheDocument();
expect(screen.getByText("Paul Dupont")).toBeInTheDocument();

fireEvent.click(screen.getByText("John Doe"));
expect(toggleSearchFilterMock).toHaveBeenCalledWith("interviewer", "1");
});
});
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,

"types": ["@testing-library/jest-dom", "vitest/globals"],
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
Expand Down
23 changes: 19 additions & 4 deletions vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,22 @@
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import type { InlineConfig } from "vitest";
import type { UserConfig } from "vite";
import tsconfigPaths from "vite-tsconfig-paths";

// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
});
type ViteConfig = UserConfig & { test: InlineConfig };

const config: ViteConfig = {
plugins: [react(), tsconfigPaths()],
test: {
globals: true,
environment: "jsdom",
setupFiles: "./setupTest.js",
coverage: {
reporter: ["text", "html"],
exclude: ["node_modules/", "./setupTest.js"],
},
},
};

export default defineConfig(config);
Loading

0 comments on commit 9ef733b

Please sign in to comment.