Skip to content

Commit

Permalink
fix: if component with tests (#1730)
Browse files Browse the repository at this point in the history
  • Loading branch information
abvthecity authored Oct 26, 2024
1 parent 9e12414 commit e763510
Show file tree
Hide file tree
Showing 3 changed files with 263 additions and 8 deletions.
13 changes: 10 additions & 3 deletions packages/ui/app/src/atoms/auth.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import type { FernUser } from "@fern-ui/fern-docs-auth";
import { isEqual } from "es-toolkit/predicate";
import { useAtomValue } from "jotai";
import { Atom, useAtomValue } from "jotai";
import { selectAtom } from "jotai/utils";
import { DOCS_ATOM } from "./docs";

export const FERN_USER_ATOM = selectAtom(DOCS_ATOM, (docs) => docs.user, isEqual);

FERN_USER_ATOM.debugLabel = "FERN_USER_ATOM";

export function useFernUser(): FernUser | undefined {
return useAtomValue(FERN_USER_ATOM);
interface UseFernUserOptions {
/**
* A fern user atom for testing purposes only
*/
__test_fern_user_atom?: Atom<FernUser | undefined>;
}

export function useFernUser({ __test_fern_user_atom }: UseFernUserOptions = {}): FernUser | undefined {
return useAtomValue(__test_fern_user_atom ?? FERN_USER_ATOM);
}
220 changes: 220 additions & 0 deletions packages/ui/app/src/mdx/components/if/If.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
/**
* @vitest-environment jsdom
*/

import { FernUser } from "@fern-ui/fern-docs-auth";
import { EVERYONE_ROLE } from "@fern-ui/fern-docs-utils";
import { render } from "@testing-library/react";
import { Atom, atom } from "jotai";
import { freezeAtom } from "jotai/utils";
import { If } from "./If";

function createTestFernUserAtom(roles: string[] | false): Atom<FernUser | undefined> {
return freezeAtom(atom(roles ? { roles } : undefined));
}

describe("If", () => {
it("renders when the roles=[], and the user is logged with roles=[]", async () => {
const { findByText } = render(
<If roles={[]} __test_fern_user_atom={createTestFernUserAtom([])}>
capture_the_flag
</If>,
);
await expect(findByText("capture_the_flag")).resolves.toBeDefined();
});

it("renders when user matches role exactly", async () => {
const { findByText } = render(
<If roles={["beta-users"]} __test_fern_user_atom={createTestFernUserAtom(["beta-users"])}>
capture_the_flag
</If>,
);

await expect(findByText("capture_the_flag")).resolves.toBeDefined();
});

it("renders when user overlaps with one of the roles", async () => {
const { findByText } = render(
<If
roles={["beta-users", "alpha-users"]}
__test_fern_user_atom={createTestFernUserAtom(["beta-users", "theta-users"])}
>
capture_the_flag
</If>,
);

await expect(findByText("capture_the_flag")).resolves.toBeDefined();
});

it("hides when the user does not overlap with any of the roles", async () => {
const { findByText } = render(
<If roles={["beta-users"]} __test_fern_user_atom={createTestFernUserAtom(["alpha-users"])}>
capture_the_flag
</If>,
);

await expect(findByText("capture_the_flag", { exact: false })).rejects.toThrow();
});

it("renders when the roles=[], and the user exists", async () => {
const { findByText } = render(
<If roles={[]} __test_fern_user_atom={createTestFernUserAtom([])}>
capture_the_flag
</If>,
);
await expect(findByText("capture_the_flag")).resolves.toBeDefined();
});

it("renders when the roles=[], and the user exists and has a role", async () => {
const { findByText } = render(
<If roles={[]} __test_fern_user_atom={createTestFernUserAtom(["beta-users"])}>
capture_the_flag
</If>,
);
await expect(findByText("capture_the_flag")).resolves.toBeDefined();
});

it("hides when the roles=[], and the user is not logged in", async () => {
const { findByText } = render(
<If roles={[]} __test_fern_user_atom={createTestFernUserAtom(false)}>
capture_the_flag
</If>,
);
await expect(findByText("capture_the_flag")).rejects.toThrow();
});

it("renders when the roles=undefined, and the user exists", async () => {
const { findByText } = render(<If __test_fern_user_atom={createTestFernUserAtom([])}>capture_the_flag</If>);
await expect(findByText("capture_the_flag")).resolves.toBeDefined();
});

it("renders when the roles=undefined, and the user does not exist", async () => {
const { findByText } = render(<If __test_fern_user_atom={createTestFernUserAtom(false)}>capture_the_flag</If>);
await expect(findByText("capture_the_flag")).resolves.toBeDefined();
});

it("hides when the not=true, and user is not logged in", async () => {
const { findByText } = render(
<If not __test_fern_user_atom={createTestFernUserAtom(false)}>
capture_the_flag
</If>,
);
await expect(findByText("capture_the_flag")).rejects.toThrow();
});

it("hides when the not=true, and user is logged in", async () => {
const { findByText } = render(
<If not __test_fern_user_atom={createTestFernUserAtom([])}>
capture_the_flag
</If>,
);
await expect(findByText("capture_the_flag")).rejects.toThrow();
});

it("renders when loggedIn=true", async () => {
const { findByText } = render(
<If loggedIn __test_fern_user_atom={createTestFernUserAtom([])}>
capture_the_flag
</If>,
);
await expect(findByText("capture_the_flag")).resolves.toBeDefined();
});

it("hides when loggedIn=true, and user is not logged in", async () => {
const { findByText } = render(
<If loggedIn __test_fern_user_atom={createTestFernUserAtom(false)}>
capture_the_flag
</If>,
);
await expect(findByText("capture_the_flag")).rejects.toThrow();
});

it("renders when not loggedIn=true, and user is not logged in", async () => {
const { findByText } = render(
<If not loggedIn __test_fern_user_atom={createTestFernUserAtom(false)}>
capture_the_flag
</If>,
);
await expect(findByText("capture_the_flag")).resolves.toBeDefined();
});

it("hides when not loggedIn=true, and user is logged in", async () => {
const { findByText } = render(
<If not loggedIn __test_fern_user_atom={createTestFernUserAtom([])}>
capture_the_flag
</If>,
);
await expect(findByText("capture_the_flag")).rejects.toThrow();
});

it("renders when the role is everyone, including when the user is not logged in", async () => {
const { findByText } = render(
<If roles={[EVERYONE_ROLE]} __test_fern_user_atom={createTestFernUserAtom(false)}>
capture_the_flag
</If>,
);
await expect(findByText("capture_the_flag")).resolves.toBeDefined();
});

it("renders when the role is everyone, and the user is logged in", async () => {
const { findByText } = render(
<If roles={[EVERYONE_ROLE]} __test_fern_user_atom={createTestFernUserAtom([])}>
capture_the_flag
</If>,
);
await expect(findByText("capture_the_flag")).resolves.toBeDefined();
});

it("hides when the user matches role and the not=true", async () => {
const { findByText } = render(
<If
not
roles={["beta-users"]}
__test_fern_user_atom={createTestFernUserAtom(["beta-users", "beta-users-2"])}
>
capture_the_flag
</If>,
);
await expect(findByText("capture_the_flag")).rejects.toThrow();
});

it("renders when the user does not match a role and not=true", async () => {
const { findByText } = render(
<If
not
roles={["beta-users"]}
__test_fern_user_atom={createTestFernUserAtom(["alpha-users", "theta-users"])}
>
capture_the_flag
</If>,
);
await expect(findByText("capture_the_flag")).resolves.toBeDefined();
});

it("renders when not=true && roles=[], and the user's roles do not overlap", async () => {
const { findByText } = render(
<If not roles={[]} __test_fern_user_atom={createTestFernUserAtom(["beta-users"])}>
capture_the_flag
</If>,
);
await expect(findByText("capture_the_flag")).resolves.toBeDefined();
});

it("hides when not=true && roles=[], and the user has role=[], and not=true", async () => {
const { findByText } = render(
<If not roles={[]} __test_fern_user_atom={createTestFernUserAtom([])}>
capture_the_flag
</If>,
);
await expect(findByText("capture_the_flag")).rejects.toThrow();
});

it("renders when not=true && roles=[], and the user is not logged in", async () => {
const { findByText } = render(
<If not roles={[]} __test_fern_user_atom={createTestFernUserAtom(false)}>
capture_the_flag
</If>,
);
await expect(findByText("capture_the_flag")).resolves.toBeDefined();
});
});
38 changes: 33 additions & 5 deletions packages/ui/app/src/mdx/components/if/If.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { FernUser } from "@fern-ui/fern-docs-auth";
import { EVERYONE_ROLE } from "@fern-ui/fern-docs-utils";
import { Atom } from "jotai";
import { PropsWithChildren, ReactNode } from "react";
import { useFernUser } from "../../../atoms";

Expand All @@ -12,6 +14,16 @@ export interface IfProps {
* Invert the role check
*/
not?: boolean;

/**
* Whether the user is logged in
*/
loggedIn?: boolean;

/**
* A fern user atom for testing purposes only
*/
__test_fern_user_atom?: Atom<FernUser | undefined>;
}

/**
Expand All @@ -27,13 +39,29 @@ export interface IfProps {
* some content
*/

export function If({ not, roles, children }: PropsWithChildren<IfProps>): ReactNode {
const user = useFernUser();
export function If({ not, roles, loggedIn, children, __test_fern_user_atom }: PropsWithChildren<IfProps>): ReactNode {
const user = useFernUser({ __test_fern_user_atom });

const userRoles = user?.roles ?? [];

const show =
roles?.some((roles) => userRoles.some((role) => roles.includes(role) || role === EVERYONE_ROLE)) ?? false;
if (not && roles?.length === 0 && userRoles.length > 0) {
return children;
}

const shouldShow = () => {
if (roles != null) {
if (roles.length === 0) {
return user != null;
}
return roles.some((role) => userRoles.includes(role) || role === EVERYONE_ROLE);
}
if (loggedIn != null) {
return loggedIn === (user != null);
}
return true;
};

const show = not ? !shouldShow() : shouldShow();

return not ? !show && children : show && children;
return show ? children : null;
}

0 comments on commit e763510

Please sign in to comment.