diff --git a/apps/web/src/app/(pages)/(dashboard)/roles/page.tsx b/apps/web/src/app/(pages)/(dashboard)/roles/page.tsx index 59a827b..b908bcc 100644 --- a/apps/web/src/app/(pages)/(dashboard)/roles/page.tsx +++ b/apps/web/src/app/(pages)/(dashboard)/roles/page.tsx @@ -3,13 +3,12 @@ import { useEffect, useState } from "react"; import { z } from "zod"; -import { +import type { ReviewType, - WorkEnvironment, WorkEnvironmentType, - WorkTerm, WorkTermType, } from "@cooper/db/schema"; +import { WorkEnvironment, WorkTerm } from "@cooper/db/schema"; import { cn } from "@cooper/ui"; import { useToast } from "@cooper/ui/hooks/use-toast"; @@ -60,7 +59,12 @@ export default function Roles({ variant: "destructive", }); } - }, [toast, mounted]); + }, [ + toast, + mounted, + validationResult.success, + validationResult.error?.issues, + ]); const reviews = api.review.list.useQuery({ options: validationResult.success ? validationResult.data : {}, diff --git a/packages/api/package.json b/packages/api/package.json index dfca51e..e5d57ef 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -13,6 +13,7 @@ "scripts": { "build": "tsc", "dev": "tsc --watch", + "test": "vitest", "clean": "rm -rf .turbo dist node_modules", "format": "prettier --check . --ignore-path ../../.gitignore", "lint": "eslint", diff --git a/packages/api/tests/mocks/review.ts b/packages/api/tests/mocks/review.ts new file mode 100644 index 0000000..4cdce65 --- /dev/null +++ b/packages/api/tests/mocks/review.ts @@ -0,0 +1,5 @@ +export const data = [ + { id: "1", workTerm: "SPRING", workEnvironment: "REMOTE" }, + { id: "2", workTerm: "FALL", workEnvironment: "INPERSON" }, + { id: "3", workTerm: "SUMMER", workEnvironment: "HYBRID" }, +]; diff --git a/packages/api/tests/review.test.ts b/packages/api/tests/review.test.ts new file mode 100644 index 0000000..6016eb5 --- /dev/null +++ b/packages/api/tests/review.test.ts @@ -0,0 +1,102 @@ +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ +/* eslint-disable @typescript-eslint/unbound-method */ +import { beforeEach, describe, expect, test, vi } from "vitest"; + +import type { Session } from "@cooper/auth"; +import type { ReviewType } from "@cooper/db/schema"; +import { and, eq } from "@cooper/db"; +import { db } from "@cooper/db/client"; +import { Review } from "@cooper/db/schema"; + +import { appRouter } from "../src/root"; +import { createCallerFactory, createTRPCContext } from "../src/trpc"; +import { data } from "./mocks/review"; + +vi.mock("@cooper/db/client", () => ({ + db: { + query: { + Review: { + findMany: vi.fn(), + }, + }, + }, +})); + +vi.mock("@cooper/auth", () => ({ + auth: vi.fn(), +})); + +describe("Review Router", async () => { + beforeEach(() => { + vi.restoreAllMocks(); + vi.mocked(db.query.Review.findMany).mockResolvedValue(data as ReviewType[]); + }); + + const session: Session = { + user: { + id: "1", + }, + expires: "1", + }; + + const ctx = await createTRPCContext({ + session, + headers: new Headers(), + }); + + const caller = createCallerFactory(appRouter)(ctx); + + test("list endpoint returns all reviews", async () => { + const reviews = await caller.review.list({}); + + expect(reviews).toEqual(data); + + expect(db.query.Review.findMany).toHaveBeenCalledWith({ + orderBy: expect.anything(), + where: undefined, + }); + }); + + test("list endpoint with cycle filter", async () => { + await caller.review.list({ + options: { + cycle: "SPRING", + }, + }); + + expect(db.query.Review.findMany).toHaveBeenCalledWith({ + orderBy: expect.anything(), + where: and(eq(Review.workTerm, "SPRING")), + }); + }); + + test("list endpoint with term filter", async () => { + await caller.review.list({ + options: { + term: "REMOTE", + }, + }); + + expect(db.query.Review.findMany).toHaveBeenCalledWith({ + orderBy: expect.anything(), + where: and(eq(Review.workEnvironment, "REMOTE")), + }); + }); + + test("list endpoint with cycle and term filter", async () => { + await caller.review.list({ + options: { + cycle: "SPRING", + term: "REMOTE", + }, + }); + + expect(db.query.Review.findMany).toHaveBeenCalledWith({ + orderBy: expect.anything(), + where: and( + eq(Review.workTerm, "SPRING"), + eq(Review.workEnvironment, "REMOTE"), + ), + }); + }); +}); diff --git a/packages/api/tsconfig.json b/packages/api/tsconfig.json index c97abb4..15703de 100644 --- a/packages/api/tsconfig.json +++ b/packages/api/tsconfig.json @@ -4,6 +4,6 @@ "outDir": "dist", "tsBuildInfoFile": "node_modules/.cache/tsbuildinfo.json" }, - "include": ["src"], + "include": ["src", "tests"], "exclude": ["node_modules"] } diff --git a/turbo.json b/turbo.json index 7d054a4..7b739a4 100644 --- a/turbo.json +++ b/turbo.json @@ -60,6 +60,10 @@ "start": { "cache": false, "interactive": true + }, + "test": { + "cache": true, + "interactive": true } }, "globalEnv": [