Skip to content

Commit

Permalink
🧪 test(layouts): add tests for layout
Browse files Browse the repository at this point in the history
  • Loading branch information
thrownullexception committed Nov 13, 2023
1 parent 857d73c commit 7fb9f13
Show file tree
Hide file tree
Showing 31 changed files with 292 additions and 340 deletions.
2 changes: 2 additions & 0 deletions src/__tests__/_/api-handlers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { dashboardApiHandlers } from "./dashboard";
import { integrationsApiHandlers } from "./integrations";
import { versionApiHandlers } from "./versions";
import { portalApiHandlers } from "./portal";
import { menuApiHandlers } from "./menu";

export const apiHandlers = [
...setupApiHandlers,
Expand All @@ -22,4 +23,5 @@ export const apiHandlers = [
...dashboardApiHandlers,
...versionApiHandlers,
...portalApiHandlers,
...menuApiHandlers,
];
18 changes: 18 additions & 0 deletions src/__tests__/_/api-handlers/menu.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { rest } from "msw";
import { INavigationMenuItem, NavigationMenuItemType } from "shared/types/menu";
import { BASE_TEST_URL } from "./_utils";

const MENU: INavigationMenuItem[] = [
{
id: "1",
title: "Menu Item 1",
type: NavigationMenuItemType.ExternalLink,
link: "https://somewhere.com",
},
];

export const menuApiHandlers = [
rest.get(BASE_TEST_URL("/api/menu"), async (_, res, ctx) => {
return res(ctx.json(MENU));
}),
];
3 changes: 2 additions & 1 deletion src/__tests__/_/setupApihandlers.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { setupServer } from "msw/node";
import { JWT_TOKEN_STORAGE_KEY } from "frontend/hooks/auth/auth.store";
import { apiHandlers } from "./api-handlers";

export const server = setupServer(...apiHandlers);

export function setupApiHandlers() {
beforeAll(() => {
localStorage.setItem("__auth-token__", "foo");
localStorage.setItem(JWT_TOKEN_STORAGE_KEY, "foo");
server.listen();
});

Expand Down
3 changes: 2 additions & 1 deletion src/__tests__/account/logout.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import userEvent from "@testing-library/user-event";
import AccountPassword from "pages/account/password";

import { setupApiHandlers } from "__tests__/_/setupApihandlers";
import { JWT_TOKEN_STORAGE_KEY } from "frontend/hooks/auth/auth.store";

setupApiHandlers();

Expand Down Expand Up @@ -33,6 +34,6 @@ describe("pages/account/logout", () => {
await waitFor(() => {
expect(replaceMock).toHaveBeenCalledWith("/auth");
});
expect(localStorage.getItem("__auth-token__")).toBeNull();
expect(localStorage.getItem(JWT_TOKEN_STORAGE_KEY)).toBeNull();
});
});
50 changes: 50 additions & 0 deletions src/__tests__/api/data/[entity]/[id]/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,56 @@ describe("/api/data/[entity]/[id]/index", () => {
`);
});

it("should query data by the column when present", async () => {
const { req, res } = createAuthenticatedMocks({
method: "GET",
query: {
entity: "tests",
id: "Jane Doe",
column: "name",
},
});

await handler(req, res);

expect(res._getStatusCode()).toBe(200);
expect(res._getJSONData()).toMatchInlineSnapshot(`
{
"age": 9,
"createdAt": 1631878197330,
"id": 2,
"name": "Jane Doe",
"referenceId": 5,
"status": "opened",
"verified": 0,
}
`);
});

it("should validate the column param", async () => {
const { req, res } = createAuthenticatedMocks({
method: "GET",
query: {
entity: "tests",
id: "Jane Doe",
column: "invalid-field",
},
});

await handler(req, res);

expect(res._getStatusCode()).toBe(400);
expect(res._getJSONData()).toMatchInlineSnapshot(`
{
"message": "Invalid field 'invalid-field' for 'tests'",
"method": "GET",
"name": "BadRequestError",
"path": "",
"statusCode": 400,
}
`);
});

it("should hide hidden columns from details data", async () => {
await setupAppConfigTestData({
hidden_entity_details_columns__tests: ["createdAt", "verified"],
Expand Down
9 changes: 6 additions & 3 deletions src/__tests__/auth/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ApplicationRoot } from "frontend/components/ApplicationRoot";
import { setupApiHandlers } from "__tests__/_/setupApihandlers";
import SignIn from "pages/auth";
import userEvent from "@testing-library/user-event";
import { JWT_TOKEN_STORAGE_KEY } from "frontend/hooks/auth/auth.store";

setupApiHandlers();

Expand All @@ -13,7 +14,7 @@ describe("pages/auth", () => {
});

it("should redirect to dashboard when user is authenticated", async () => {
localStorage.setItem("__auth-token__", "foo");
localStorage.setItem(JWT_TOKEN_STORAGE_KEY, "foo");
const useRouter = jest.spyOn(require("next/router"), "useRouter");

const replaceMock = jest.fn();
Expand Down Expand Up @@ -64,7 +65,7 @@ describe("pages/auth", () => {
"Invalid Login"
);

expect(localStorage.getItem("__auth-token__")).toBeNull();
expect(localStorage.getItem(JWT_TOKEN_STORAGE_KEY)).toBeNull();

expect(pushMock).not.toHaveBeenCalled();
});
Expand All @@ -90,7 +91,9 @@ describe("pages/auth", () => {

await userEvent.click(screen.getByRole("button", { name: "Sign In" }));

expect(localStorage.getItem("__auth-token__")).toBe("some valid jwt token");
expect(localStorage.getItem(JWT_TOKEN_STORAGE_KEY)).toBe(
"some valid jwt token"
);

expect(pushMock).toHaveBeenCalledWith("/");
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import userEvent from "@testing-library/user-event";
import { useUserAuthenticatedState } from "frontend/hooks/auth/useAuthenticateUser";
import { IAuthenticatedUserBag } from "shared/types/user";
import { USER_PERMISSIONS } from "shared/constants/user";
import { JWT_TOKEN_STORAGE_KEY } from "frontend/hooks/auth/auth.store";

const server = setupApiHandlers();

Expand All @@ -24,7 +25,7 @@ function AuthenticatedApplicationRoot({ children }: { children: ReactNode }) {
describe("pages/integrations/variables => credentials -- non admin", () => {
const useRouter = jest.spyOn(require("next/router"), "useRouter");
beforeAll(() => {
localStorage.setItem("__auth-token__", "foo");
localStorage.setItem(JWT_TOKEN_STORAGE_KEY, "foo");
useRouter.mockImplementation(() => ({
asPath: "/",
query: {
Expand Down
3 changes: 2 additions & 1 deletion src/__tests__/integrations/variables__credentials.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import ManageVariables from "pages/admin/settings/variables";
import { setupApiHandlers } from "__tests__/_/setupApihandlers";
import userEvent from "@testing-library/user-event";
import { useUserAuthenticatedState } from "frontend/hooks/auth/useAuthenticateUser";
import { JWT_TOKEN_STORAGE_KEY } from "frontend/hooks/auth/auth.store";

setupApiHandlers();

Expand All @@ -20,7 +21,7 @@ function AuthenticatedApplicationRoot({ children }: { children: ReactNode }) {
describe("pages/integrations/variables => credentials", () => {
const useRouter = jest.spyOn(require("next/router"), "useRouter");
beforeAll(() => {
localStorage.setItem("__auth-token__", "foo");
localStorage.setItem(JWT_TOKEN_STORAGE_KEY, "foo");
useRouter.mockImplementation(() => ({
asPath: "/",
query: {
Expand Down
3 changes: 2 additions & 1 deletion src/frontend/_layouts/app/LayoutImpl/Profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,12 @@ export function ProfileOnNavigation({ isFullWidth }: IProps) {
return (
<ProfileRoot justify="space-between" align="center">
<Name weight="bold">
Hi, {currentUser.isLoading ? "User" : currentUser.data?.name}
Hi, {currentUser.isLoading ? "There" : currentUser.data?.name}
</Name>
<Dropdown
width={250}
preserveVisibiltyOnClick
ariaLabel="Toggle Profile Menu"
align="right"
target={<MoreVertical size={16} style={{ cursor: "pointer" }} />}
>
Expand Down
21 changes: 10 additions & 11 deletions src/frontend/_layouts/app/LayoutImpl/SideBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { useThemeColorShade } from "frontend/design-system/theme/useTheme";
import { Stack } from "frontend/design-system/primitives/Stack";
import { useStorageApi } from "frontend/lib/data/useApi";
import { INavigationMenuItem } from "shared/types/menu";
import { PlainButton } from "frontend/design-system/components/Button/TextButton";
import {
NAVIGATION_MENU_ENDPOINT,
SIDE_BAR_WIDTH_VARIATIONS,
Expand Down Expand Up @@ -65,15 +66,9 @@ const IconRoot = styled.span<{ $isFullWidth: boolean }>`
${(props) => props.$isFullWidth && "transform: rotate(180deg);"}
`;

export const PlainButton = styled.button`
&:focus {
outline: 0;
}
const ToggleSideBarButton = styled(PlainButton)`
height: 36px;
background: ${USE_ROOT_COLOR("primary-color")};
border: 0;
cursor: pointer;
padding: 0;
`;

const Scroll = styled.div`
Expand All @@ -91,7 +86,7 @@ interface IProps {
setIsFullWidth: (value: boolean) => void;
}

export const useNavigationMenuItems = () => {
const useNavigationMenuItems = () => {
return useStorageApi<INavigationMenuItem[]>(NAVIGATION_MENU_ENDPOINT, {
errorMessage: "Could not load navigation menu",
defaultData: [],
Expand Down Expand Up @@ -143,14 +138,18 @@ export function SideBar({ isFullWidth, setIsFullWidth }: IProps) {
</ViewStateMachine>
</Scroll>

<PlainButton
<ToggleSideBarButton
style={{
backgroundColor: getThemeColorShade("primary-color", 30),
}}
onClick={() => setIsFullWidth(!isFullWidth)}
>
<IconRoot as={ChevronRight} $isFullWidth={isFullWidth} />
</PlainButton>
<IconRoot
aria-label="Toggle Side Bar"
as={ChevronRight}
$isFullWidth={isFullWidth}
/>
</ToggleSideBarButton>
</Stack>
</Root>
);
Expand Down
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { useRouter } from "next/router";
import { useNavigationStack } from "frontend/lib/routing/useNavigationStack";
import { usePageDetailsStore } from "frontend/lib/routing/usePageDetails";
import { usePageRequiresPermission } from "frontend/hooks/auth/user.store";
import { GitHub, Globe, Twitter, Users } from "react-feather";
import {
DropDownMenu,
IDropDownMenuItem,
Expand All @@ -15,18 +14,19 @@ import { Typo } from "frontend/design-system/primitives/Typo";
import { Spacer } from "frontend/design-system/primitives/Spacer";
import { useSiteConfig } from "frontend/hooks/app/site.config";
import { GoogleTagManager } from "../scripts/GoogleTagManager";
import { DEMO_LINKS } from "./constant";

export interface IBaseLayoutProps {
export interface IMainContentProps {
children: ReactNode;
actionItems?: IDropDownMenuItem[];
secondaryActionItems?: IDropDownMenuItem[];
}

export function BaseLayout({
export function MainContent({
children,
actionItems = [],
secondaryActionItems = [],
}: IBaseLayoutProps) {
}: IMainContentProps) {
const siteConfig = useSiteConfig();
const { history, pushToStack, goToLinkIndex } = useNavigationStack();
const router = useRouter();
Expand Down Expand Up @@ -59,11 +59,6 @@ export function BaseLayout({
...pageSecondaryActionItems,
];

// Interfering with the tests
// if (isLoading) {
// return <ComponentIsLoading />;
// }

return (
<>
<Head>
Expand All @@ -87,44 +82,10 @@ export function BaseLayout({
) : null}
{process.env.NEXT_PUBLIC_IS_DEMO && (
<DropDownMenu
menuItems={[
{
id: "github",
IconComponent: GitHub,
label: "Star us on Github",
description: `Tell us DashPress is a useful project by dropping us a star`,
onClick: () => {
window.open("https://github.com/dashpresshq/dashpress");
},
},
{
id: "twitter",
IconComponent: Twitter,
label: "Follow us on Twitter",
description: `Tweet at @dashpressHQ if you know others will benefit using DashPress`,
onClick: () => {
window.open("https://twitter.com/dashpressHQ");
},
},
{
id: "users",
IconComponent: Users,
label: "Join our Discord community",
description: `Ask your questions here`,
onClick: () => {
window.open("https://discord.gg/aV6DxwXhzN");
},
},
{
id: "website",
IconComponent: Globe,
label: "Visit our website",
description: `For more links on documentation, roadmap, blog etc`,
onClick: () => {
window.open("https://dashpress.io");
},
},
]}
menuItems={DEMO_LINKS.map((link) => ({
...link,
onClick: () => window.open(link.link),
}))}
/>
)}
</Stack>
Expand Down
Loading

0 comments on commit 7fb9f13

Please sign in to comment.