From 81618272071276b1ad0581f8761742997e5be1e4 Mon Sep 17 00:00:00 2001 From: "Hans Gabriel B. Daduya" Date: Mon, 18 Dec 2023 01:13:00 +0800 Subject: [PATCH] TES-306: Create test server for API routes (#298) * Add mock auth context * Improve API endpoints * Add more meta routes * Change to use headers * Fix create type check error for collection * Add context inner type --- apps/expo/app.config.ts | 5 ++++- .../src/components/search/SearchField.tsx | 1 - packages/api/src/context.ts | 12 +++++++++++ packages/api/src/router/algoliaSearch.ts | 12 +++++------ packages/api/src/router/collection.ts | 7 +++++++ packages/api/src/router/gptApi.ts | 8 +++++++ packages/api/src/router/pdfTextExtraction.ts | 7 +++++++ packages/api/src/router/reviewer.ts | 9 ++++++-- packages/api/src/router/user.ts | 21 ++++++++++++++++++- 9 files changed, 71 insertions(+), 11 deletions(-) diff --git a/apps/expo/app.config.ts b/apps/expo/app.config.ts index 6321773c..ad3b9781 100644 --- a/apps/expo/app.config.ts +++ b/apps/expo/app.config.ts @@ -1,10 +1,13 @@ import { ExpoConfig, ConfigContext } from "@expo/config"; +type ENV = "development" | "production"; + const CLERK_PUBLISHABLE_KEY = "pk_test_Z3Jvd2luZy1kb2Jlcm1hbi04OC5jbGVyay5hY2NvdW50cy5kZXYk"; const SERVER_URL = "https://test-trek-prod.vercel.app"; -const SERVER_ENV: "development" | "production" = "development"; +const SERVER_ENV: ENV = "development"; +// eslint-disable-next-line @typescript-eslint/no-unused-vars const defineConfig = (_ctx: ConfigContext): ExpoConfig => ({ name: "TestTrek", slug: "testtrek", diff --git a/apps/expo/src/components/search/SearchField.tsx b/apps/expo/src/components/search/SearchField.tsx index 875dc8eb..07fd86ec 100644 --- a/apps/expo/src/components/search/SearchField.tsx +++ b/apps/expo/src/components/search/SearchField.tsx @@ -108,7 +108,6 @@ export const SearchField: FC = ({ containerStyle={{ backgroundColor: "transparent", borderBottomColor: "transparent", - borderTopColor: "transparent", borderLeftColor: "transparent", borderRightColor: "transparent", width: "80%", // Adjusted width diff --git a/packages/api/src/context.ts b/packages/api/src/context.ts index 72b918d6..37f16738 100644 --- a/packages/api/src/context.ts +++ b/packages/api/src/context.ts @@ -3,6 +3,8 @@ import { type inferAsyncReturnType } from "@trpc/server"; import { type CreateNextContextOptions } from "@trpc/server/adapters/next"; import { getAuth } from "@clerk/nextjs/server"; +const isTest = process.env.SERVER_ENV === "test"; + /** * Replace this with an object if you want to pass things to createContextInner */ @@ -22,11 +24,21 @@ export const createContextInner = async ({ auth }: AuthContextProps) => { }; }; +type ContextInner = inferAsyncReturnType; + /** * This is the actual context you'll use in your router * @link https://trpc.io/docs/context **/ export const createContext = async (opts: CreateNextContextOptions) => { + if (isTest) { + return { + auth: { + userId: opts.req.headers["authorization"], + }, + prisma, + } as ContextInner; + } return await createContextInner({ auth: getAuth(opts.req) }); }; diff --git a/packages/api/src/router/algoliaSearch.ts b/packages/api/src/router/algoliaSearch.ts index fa6e8d78..743277d8 100644 --- a/packages/api/src/router/algoliaSearch.ts +++ b/packages/api/src/router/algoliaSearch.ts @@ -9,12 +9,12 @@ import { export const algoliaSearch = router({ algoliaSearch: protectedProcedure - // .meta({ - // openapi: { - // method: "POST", - // path: "/algolia/search", - // }, - // }) + .meta({ + openapi: { + method: "POST", + path: "/algolia/search", + }, + }) .input(algoliaQueries) .output(z.any()) .query(async ({ ctx, input }) => { diff --git a/packages/api/src/router/collection.ts b/packages/api/src/router/collection.ts index 12a680f5..8bb09253 100644 --- a/packages/api/src/router/collection.ts +++ b/packages/api/src/router/collection.ts @@ -369,6 +369,13 @@ export const collectionRouter = router({ const userId = ctx.auth.userId; + if (!userId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to create a collection", + }); + } + const newCollection = await ctx.prisma.collection.create({ data: { title, diff --git a/packages/api/src/router/gptApi.ts b/packages/api/src/router/gptApi.ts index efb5c881..73577892 100644 --- a/packages/api/src/router/gptApi.ts +++ b/packages/api/src/router/gptApi.ts @@ -1,3 +1,4 @@ +import { z } from "zod"; import { protectedProcedure, router } from "../trpc"; import { parseMultipleChoiceResponse, @@ -122,7 +123,14 @@ export const gptApiRouter = router({ }), generateMultipleRandomQuestions: protectedProcedure + .meta({ + openapi: { + method: "POST", + path: "/gpt/random-questions", + }, + }) .input(multipleRandomQuestionsPromptInput) + .output(z.any()) .mutation(async ({ input }) => { const { message, numOfQuestions, messageType } = input; diff --git a/packages/api/src/router/pdfTextExtraction.ts b/packages/api/src/router/pdfTextExtraction.ts index 4766dd07..d9380d25 100644 --- a/packages/api/src/router/pdfTextExtraction.ts +++ b/packages/api/src/router/pdfTextExtraction.ts @@ -77,12 +77,19 @@ const processOcrResult = (data: any) => { export const textExtractionRouter = router({ extractText: protectedProcedure + .meta({ + openapi: { + method: "POST", + path: "/text-extraction", + }, + }) .input( z.object({ file: z.string(), fileType: z.string(), }), ) + .output(z.any()) .mutation(async ({ input }) => { const { file, fileType } = input; let ocrResult = ""; diff --git a/packages/api/src/router/reviewer.ts b/packages/api/src/router/reviewer.ts index df045f67..52958f40 100644 --- a/packages/api/src/router/reviewer.ts +++ b/packages/api/src/router/reviewer.ts @@ -13,6 +13,12 @@ import { export const reviewerRouter = router({ getDiscoverReviewers: protectedProcedure + .meta({ + openapi: { + method: "GET", + path: "/reviewers/discover", + }, + }) .input(highLightReviewersInput) .output(z.any()) .query(({ ctx, input }) => { @@ -219,8 +225,7 @@ export const reviewerRouter = router({ if (isUserPremium && userReviewersCount >= 30) { throw new TRPCError({ code: "FORBIDDEN", - message: - "Maximum amount of reviewers reached.", + message: "Maximum amount of reviewers reached.", }); } diff --git a/packages/api/src/router/user.ts b/packages/api/src/router/user.ts index 5f749db4..4f2874de 100644 --- a/packages/api/src/router/user.ts +++ b/packages/api/src/router/user.ts @@ -64,7 +64,7 @@ export const useRouter = router({ .meta({ openapi: { method: "GET", - path: "/users/me", + path: "/users/me/details", }, }) .input(z.void()) @@ -210,6 +210,12 @@ export const useRouter = router({ }), getTotalPoints: protectedProcedure + .meta({ + openapi: { + method: "GET", + path: "/users/me/points", + }, + }) .input(z.void()) .output(z.any()) .query(async ({ ctx }) => { @@ -227,6 +233,12 @@ export const useRouter = router({ }), getNewBadges: protectedProcedure + .meta({ + openapi: { + method: "GET", + path: "/users/me/badges/new", + }, + }) .input(z.void()) .output(z.any()) .query(async ({ ctx }) => { @@ -306,6 +318,12 @@ export const useRouter = router({ }), getBadges: protectedProcedure + .meta({ + openapi: { + method: "GET", + path: "/users/me/badges", + }, + }) .input(z.void()) .output(z.any()) .query(async ({ ctx }) => { @@ -533,6 +551,7 @@ export const useRouter = router({ path: "/users/me/premium", }, }) + .input(z.void()) .output(z.any()) .mutation(async ({ ctx }) => { const premiumStatus = await ctx.prisma.user