Skip to content

Commit

Permalink
refactor: tests
Browse files Browse the repository at this point in the history
  • Loading branch information
bastiensun committed Nov 2, 2023
1 parent ab96c9b commit 8019695
Show file tree
Hide file tree
Showing 9 changed files with 174 additions and 72 deletions.
127 changes: 89 additions & 38 deletions src/app.test.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,15 @@
// eslint-disable-next-line import/no-unassigned-import
import "@testing-library/jest-dom/vitest";
import { App } from "./app";
import { cleanup, render, screen } from "@testing-library/react";
import { render, renderWithRouter, screen } from "@/lib/test-utils";
import { routes } from "@/routes";
import { userEvent } from "@testing-library/user-event";
import { MemoryRouter } from "react-router-dom";
import { afterEach, expect, test, vi } from "vitest";

afterEach(() => {
cleanup();
vi.clearAllMocks();
vi.resetAllMocks();
vi.restoreAllMocks();
});
import { createMemoryRouter, RouterProvider } from "react-router-dom";
import { describe, expect, it, test } from "vitest";

test("happy path", async () => {
// Arrange
const user = userEvent.setup();

// Act
render(
<MemoryRouter>
<App />
</MemoryRouter>,
);
renderWithRouter();

// Assert
expect(
Expand Down Expand Up @@ -77,11 +64,7 @@ test("on paste on success", async () => {
const formattedCode = "class HelloWorld { }";

// Act
render(
<MemoryRouter>
<App />
</MemoryRouter>,
);
renderWithRouter();

const unformattedCodeTextarea = screen.getByRole("textbox");
await user.click(unformattedCodeTextarea);
Expand All @@ -107,11 +90,7 @@ test("on paste on error", async () => {
const invalidCode = "invalid code";

// Act
render(
<MemoryRouter>
<App />
</MemoryRouter>,
);
renderWithRouter();

const unformattedCodeTextarea = screen.getByRole("textbox");
await user.click(unformattedCodeTextarea);
Expand Down Expand Up @@ -139,11 +118,7 @@ test("tooltip", async () => {
const user = userEvent.setup();

// Act
render(
<MemoryRouter>
<App />
</MemoryRouter>,
);
renderWithRouter();
const formattedCode = await screen.findByRole("button", {
name: 'class HelloWorld { public static void main ( String [ ] args ) { System . out . println ( "Hello, World!" ) ; } }',
});
Expand Down Expand Up @@ -185,13 +160,10 @@ test("tooltip", async () => {
test("diff view", async () => {
// Arrange
const user = userEvent.setup();
const router = createMemoryRouter(routes);

// Act
render(
<MemoryRouter>
<App />
</MemoryRouter>,
);
render(<RouterProvider router={router} />);

// Assert
const diffViewSwitch = screen.getByRole("switch", { name: /diff view/iu });
Expand All @@ -202,6 +174,9 @@ test("diff view", async () => {

// Assert
expect(diffViewSwitch).toBeChecked();
expect(router.state.location.search).toEqual(
`?${new URLSearchParams({ diff: "true" }).toString()}`,
);
expect(screen.queryByRole("textbox")).not.toBeInTheDocument();
expect(screen.getAllByRole("table")).toHaveLength(2);

Expand All @@ -210,6 +185,7 @@ test("diff view", async () => {

// Assert
expect(diffViewSwitch).not.toBeChecked();
expect(router.state.location.search).toEqual("");
expect(screen.getByRole("textbox")).toBeVisible();
expect(screen.queryByRole("table")).not.toBeInTheDocument();

Expand All @@ -224,3 +200,78 @@ test("diff view", async () => {
// Assert
expect(diffViewSwitch).not.toBeChecked();
});

describe("data query string", () => {
it("should not be decoded when it cannot be decoded", async () => {
// Arrange
const urlSearchParameters = new URLSearchParams({
data: "undefined",
});
const router = createMemoryRouter(routes, {
initialEntries: [`/?${urlSearchParameters.toString()}`],
});

// Act
render(<RouterProvider router={router} />);

// Assert
expect(screen.getByRole("textbox")).toHaveDisplayValue("");
});

it("should not be set when unformatted code is empty", async () => {
// Arrange
const user = userEvent.setup();
const router = createMemoryRouter(routes);

// Act
render(<RouterProvider router={router} />);

await user.clear(screen.getByRole("textbox"));

// Assert
expect(router.state.location.search).toEqual("");
expect(screen.getByRole("textbox")).toHaveDisplayValue("");
});

it("should not be set when unformatted code cannot be encoded", async () => {
// Arrange
const user = userEvent.setup();
const router = createMemoryRouter(routes);

// Act
render(<RouterProvider router={router} />);

const unformattedCodeTextarea = screen.getByRole("textbox");
await user.clear(unformattedCodeTextarea);
await user.type(unformattedCodeTextarea, "☀️");

// Assert
expect(router.state.location.search).toEqual("");
expect(unformattedCodeTextarea).toHaveDisplayValue("");
});

it("should be updated when unformatted code is updated", async () => {
// Arrange
const user = userEvent.setup();
const router = createMemoryRouter(routes);

const expectedUpdatedUnformattedCode = "record HelloWorld()";

// Act
render(<RouterProvider router={router} />);

const unformattedCodeTextarea = screen.getByRole("textbox");
await user.clear(unformattedCodeTextarea);
await user.type(unformattedCodeTextarea, expectedUpdatedUnformattedCode);

// Assert
expect(router.state.location.search).toEqual(
`?${new URLSearchParams({
data: btoa(expectedUpdatedUnformattedCode),
}).toString()}`,
);
expect(screen.getByRole("textbox")).toHaveDisplayValue(
expectedUpdatedUnformattedCode,
);
});
});
37 changes: 16 additions & 21 deletions src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import { CodeDisplay } from "@/components/code-display";
import { Title } from "@/components/title";
import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";
import { Toaster } from "@/components/ui/toaster";
import { TooltipProvider } from "@/components/ui/tooltip";
import { useDiffView } from "@/lib/use-diff-view";
import { type JSX } from "react";

Expand All @@ -13,25 +11,22 @@ export const App = (): JSX.Element => {
const disableDiffView = (): void => setIsDiffView(false);

return (
<TooltipProvider>
<div className="m-10">
<Title />
<div className="mt-12 flex items-center space-x-2">
<Switch
checked={isDiffView}
id="airplane-mode"
onCheckedChange={(checked): void => setIsDiffView(checked)}
/>
<Label htmlFor="airplane-mode">Diff View</Label>
</div>
<div className="mt-6">
<CodeDisplay
disableDiffView={disableDiffView}
isDiffView={isDiffView}
/>
</div>
<div className="m-10">
<Title />
<div className="mt-12 flex items-center space-x-2">
<Switch
checked={isDiffView}
id="airplane-mode"
onCheckedChange={(checked): void => setIsDiffView(checked)}
/>
<Label htmlFor="airplane-mode">Diff View</Label>
</div>
<Toaster />
</TooltipProvider>
<div className="mt-6">
<CodeDisplay
disableDiffView={disableDiffView}
isDiffView={isDiffView}
/>
</div>
</div>
);
};
13 changes: 13 additions & 0 deletions src/components/providers.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Toaster } from "@/components/ui/toaster";
import { TooltipProvider } from "@/components/ui/tooltip";
import { type JSX, type ReactNode } from "react";

type ProvidersProps = {
readonly children: ReactNode;
};
export const Providers = ({ children }: ProvidersProps): JSX.Element => (
<TooltipProvider>
{children}
<Toaster />
</TooltipProvider>
);
26 changes: 26 additions & 0 deletions src/lib/test-utils.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Providers } from "@/components/providers";
import { routes } from "@/routes";
import {
render as reactTestingLibraryRender,
type RenderOptions,
} from "@testing-library/react";
import { type ReactElement } from "react";
import { createMemoryRouter, RouterProvider } from "react-router-dom";

const customRender = (
ui: ReactElement,
options?: Omit<RenderOptions, "wrapper">,
): ReturnType<typeof reactTestingLibraryRender> =>
reactTestingLibraryRender(ui, { wrapper: Providers, ...options });

// eslint-disable-next-line import/export
export * from "@testing-library/react";
// eslint-disable-next-line import/export
export { customRender as render };

export const renderWithRouter = (): ReturnType<
typeof reactTestingLibraryRender
> => {
const router = createMemoryRouter(routes);
return customRender(<RouterProvider router={router} />);
};
21 changes: 9 additions & 12 deletions src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
import "./index.css";
import { App } from "./app";
// eslint-disable-next-line import/default
import React from "react";
import { Providers } from "@/components/providers";
import { routes } from "@/routes";
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { createBrowserRouter, RouterProvider } from "react-router-dom";

const router = createBrowserRouter([
{
element: <App />,
path: "/",
},
]);
const router = createBrowserRouter(routes);

// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
createRoot(document.querySelector("#root")!).render(
<React.StrictMode>
<RouterProvider router={router} />
</React.StrictMode>,
<StrictMode>
<Providers>
<RouterProvider router={router} />
</Providers>
</StrictMode>,
);
8 changes: 8 additions & 0 deletions src/routes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { App } from "@/app";

export const routes = [
{
element: <App />,
path: "/",
},
];
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@
"@/*": ["./src/*"]
}
},
"include": ["src"],
"include": ["src", "vitest.setup.ts"],
"references": [{ "path": "./tsconfig.node.json" }]
}
4 changes: 4 additions & 0 deletions vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ export default defineConfig({
},
},
test: {
clearMocks: true,
environment: "jsdom",
mockReset: true,
restoreMocks: true,
setupFiles: ["vitest.setup.ts"],
},
});
8 changes: 8 additions & 0 deletions vitest.setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// eslint-disable-next-line import/no-unassigned-import
import "@testing-library/jest-dom/vitest";
import { cleanup } from "./src/lib/test-utils";
import { afterEach } from "vitest";

afterEach(() => {
cleanup();
});

0 comments on commit 8019695

Please sign in to comment.