Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add verification to cmsClient and add tests to it
Browse files Browse the repository at this point in the history
vuolen committed Aug 14, 2024
1 parent 67e0b06 commit 9099315
Showing 5 changed files with 137 additions and 24 deletions.
7 changes: 6 additions & 1 deletion hooks/useTranslate.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import translations from "./translations.json";
import { Language, useLanguage } from "../lib/LanguageContext";
import { z } from "zod";

export type TranslationKey = keyof typeof translations;
export const translationKeySchema = z.enum(
Object.keys(translations) as [keyof typeof translations],
);

export type TranslationKey = z.infer<typeof translationKeySchema>;

const translate = (key: TranslationKey, language: Language): string => {
const translation = translations[key];
54 changes: 54 additions & 0 deletions lib/cmsClient.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { describe, expect, it, vi } from "vitest";
import {
createClient,
getNavigationLinks,
NavigationLink,
navigationLinkSchema,
} from "./cmsClient";
import { generateMock } from "@anatine/zod-mock";
import { z } from "zod";
import { TranslationKey } from "../hooks/useTranslate";

describe("cmsClient", async () => {
it("returns valid data from the CMS", async () => {
const mockData = generateMock(z.array(navigationLinkSchema));
const client = createClient("http://mockUrl");
const mockRequest = vi.spyOn(client, "request").mockResolvedValue(mockData);
mockRequest.mockResolvedValue(mockData);

const data = await getNavigationLinks(client);

expect(mockRequest).toHaveBeenCalled();
expect(data).toEqual(mockData);
});

it("fails on invalid label key from the CMS", async () => {
const mockData: NavigationLink[] = [
{
label_key: "invalid" as TranslationKey,
url: "page",
category: "GENERAL",
},
];
const client = createClient("http://mockUrl");
const mockRequest = vi.spyOn(client, "request").mockResolvedValue(mockData);
mockRequest.mockResolvedValue(mockData);

expect(getNavigationLinks(client)).rejects.toThrow();
});

it("fails on invalid category from the CMS", async () => {
const mockData: NavigationLink[] = [
{
label_key: "general:nation",
url: "page",
category: "invalid" as "GENERAL",
},
];
const client = createClient("http://mockUrl");
const mockRequest = vi.spyOn(client, "request").mockResolvedValue(mockData);
mockRequest.mockResolvedValue(mockData);

expect(getNavigationLinks(client)).rejects.toThrow();
});
});
41 changes: 18 additions & 23 deletions lib/cmsClient.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,27 @@
import { TranslationKey } from "@/hooks/useTranslate";
import { createDirectus, rest } from "@directus/sdk";
import { translationKeySchema } from "../hooks/useTranslate";
import { createDirectus, readItems, rest } from "@directus/sdk";
import { z } from "zod";

type Schema = {
NavigationLink: NavigationLink[];
Translation: Translation[];
};

export type NavigationLink = {
label_key: TranslationKey;
url: string;
category: "GENERAL" | "FOR_MEMBERS";
};
export const navigationLinkSchema = z.object({
label_key: translationKeySchema,
url: z.string(),
category: z.enum(["GENERAL", "FOR_MEMBERS"]),
});

/*
* You shouldnt use this type, use the better typed one in useTranslate.tsx instead
*/
export type Translation = {
key: string;
fi: string;
en: string;
sv: string;
};
export type NavigationLink = z.infer<typeof navigationLinkSchema>;

type CmsClient = ReturnType<typeof createClient>;

const createClient = () => {
if (process.env.DIRECTUS_URL === undefined) {
throw Error("Environment variable DIRECTUS_URL not defined");
}
return createDirectus<Schema>(process.env.DIRECTUS_URL).with(rest());
export const createClient = (url: string) => {
return createDirectus<Schema>(url).with(rest());
};

export default createClient;
export const getNavigationLinks = async (client: CmsClient) => {
const links = await client.request(readItems("NavigationLink"));

return links.map((link) => navigationLinkSchema.parse(link));
};
57 changes: 57 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -15,9 +15,11 @@
"prepare": "husky && npm run fetchTranslations"
},
"dependencies": {
"@anatine/zod-mock": "^3.13.4",
"@directus/sdk": "^17.0.0",
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.5",
"@faker-js/faker": "^8.4.1",
"@googleapis/forms": "^2.0.7",
"@mui/material": "^5.15.20",
"dotenv": "^16.4.5",

0 comments on commit 9099315

Please sign in to comment.