Download packages/api/src/__tests__/package.integration.test.ts from Atmint/cpns: direct link, hf CLI and curl.
- Browser
- Download file 7.88 kB
-
https://huggingface.co/spaces/Atmint/cpns/resolve/main/packages/api/src/__tests__/package.integration.test.ts
- Command line
-
hf download hf://spaces/Atmint/cpns/packages/api/src/__tests__/package.integration.test.ts
-
curl -L -o package.integration.test.ts https://huggingface.co/spaces/Atmint/cpns/resolve/main/packages/api/src/__tests__/package.integration.test.ts
7.88 kB
| import { describe, expect, it, beforeAll, afterAll, mock } from "bun:test"; | |
| import { eq } from "drizzle-orm"; | |
| import { drizzle } from "drizzle-orm/pglite"; | |
| import * as schema from "../../../db/src/schema"; | |
| import { closeTestPGlite, getTestPGlite } from "./test-setup"; | |
| mock.module("@pram/env/server", () => ({ | |
| env: { | |
| DATABASE_URL: "postgres://localhost:5432/test", | |
| BETTER_AUTH_SECRET: "a".repeat(32), | |
| BETTER_AUTH_URL: "http://localhost:3000", | |
| CORS_ORIGIN: "http://localhost:5173", | |
| API_KEY_ENCRYPTION_KEY: "z".repeat(32), | |
| REDIS_URL: "redis://localhost:6379", | |
| SMTP_HOST: "localhost", | |
| SMTP_USER: "test", | |
| SMTP_PASS: "test", | |
| SMTP_FROM: "test@test.com", | |
| }, | |
| })); | |
| describe("package router", () => { | |
| let packageRouter: any; | |
| let caller: any; | |
| let protectedCaller: any; | |
| let testDb: any; | |
| let ownerId: string; | |
| let pkgId: string; | |
| let sectionId: string; | |
| let questionId: string; | |
| beforeAll(async () => { | |
| const pg = await getTestPGlite(); | |
| testDb = drizzle(pg, { schema }); | |
| mock.module("@pram/db", () => ({ | |
| __esModule: true, | |
| ...schema, | |
| db: testDb, | |
| })); | |
| await testDb.insert(schema.examType).values([ | |
| { id: "IELTS", name: "IELTS", language: "English" }, | |
| ]); | |
| await testDb.insert(schema.sectionType).values([ | |
| { id: "READING", name: "Reading" }, | |
| { id: "WRITING", name: "Writing" }, | |
| ]); | |
| ownerId = "pkg-owner"; | |
| await testDb.insert(schema.user).values({ id: ownerId, name: "Owner", email: "owner@test.com" }); | |
| const mod = await import("../routers/package"); | |
| packageRouter = mod.packageRouter; | |
| caller = packageRouter.createCaller({ session: null, auth: null }); | |
| protectedCaller = packageRouter.createCaller({ | |
| session: { user: { id: ownerId }, expiresAt: new Date() }, | |
| auth: null, | |
| }); | |
| }); | |
| afterAll(async () => { | |
| await closeTestPGlite(); | |
| }); | |
| it("create makes a new package", async () => { | |
| const result = await protectedCaller.create({ | |
| title: "My IELTS Pack", | |
| examTypeId: "IELTS", | |
| isPublic: false, | |
| }); | |
| expect(result).toHaveProperty("id"); | |
| expect(result.title).toBe("My IELTS Pack"); | |
| pkgId = result.id; | |
| }); | |
| it("getById returns package with sections", async () => { | |
| const result = await protectedCaller.getById({ id: pkgId }); | |
| expect(result).not.toBeNull(); | |
| expect(result.title).toBe("My IELTS Pack"); | |
| expect(result.sections).toEqual([]); | |
| }); | |
| it("getById returns null for non-existent", async () => { | |
| const { randomUUID } = await import("node:crypto"); | |
| const result = await caller.getById({ id: randomUUID() }); | |
| expect(result).toBeNull(); | |
| }); | |
| it("list returns public packages", async () => { | |
| // Make it public first | |
| await testDb.update(schema.testPackage).set({ isPublic: true }).where(eq(schema.testPackage.id, pkgId)); | |
| const result = await caller.list(); | |
| expect(result.packages.length).toBeGreaterThan(0); | |
| expect(result.packages[0].id).toBe(pkgId); | |
| // Set back to private for upcoming tests | |
| await testDb.update(schema.testPackage).set({ isPublic: false }).where(eq(schema.testPackage.id, pkgId)); | |
| }); | |
| it("list hides private packages from anonymous users", async () => { | |
| const result = await caller.list(); | |
| const ids = result.packages.map((p: any) => p.id); | |
| expect(ids).not.toContain(pkgId); | |
| }); | |
| it("list shows private packages to owner via auth", async () => { | |
| const result = await protectedCaller.list(); | |
| const ids = result.packages.map((p: any) => p.id); | |
| expect(ids).toContain(pkgId); | |
| }); | |
| it("list filters by examTypeId", async () => { | |
| await testDb.update(schema.testPackage).set({ isPublic: true }).where(eq(schema.testPackage.id, pkgId)); | |
| const result = await caller.list({ examTypeId: "TOEFL" }); | |
| expect(result.packages).toHaveLength(0); | |
| }); | |
| it("update changes package fields", async () => { | |
| const result = await protectedCaller.update({ | |
| id: pkgId, | |
| title: "Updated Pack", | |
| }); | |
| expect(result.title).toBe("Updated Pack"); | |
| }); | |
| it("update rejects non-owner", async () => { | |
| const otherCaller = packageRouter.createCaller({ | |
| session: { user: { id: "other-user" }, expiresAt: new Date() }, | |
| auth: null, | |
| }); | |
| expect(otherCaller.update({ id: pkgId, title: "Hacked" })).rejects.toThrow("Forbidden"); | |
| }); | |
| it("addSection creates a section", async () => { | |
| const result = await protectedCaller.addSection({ | |
| packageId: pkgId, | |
| sectionTypeId: "READING", | |
| title: "Reading Section", | |
| orderIndex: 0, | |
| }); | |
| expect(result).toHaveProperty("id"); | |
| sectionId = result.id; | |
| }); | |
| it("addSection rejects non-owner", async () => { | |
| const otherCaller = packageRouter.createCaller({ | |
| session: { user: { id: "other-user" }, expiresAt: new Date() }, | |
| auth: null, | |
| }); | |
| expect(otherCaller.addSection({ packageId: pkgId, sectionTypeId: "READING", title: "X" })).rejects.toThrow("Forbidden"); | |
| }); | |
| it("getById includes sections after adding", async () => { | |
| const result = await caller.getById({ id: pkgId }); | |
| expect(result.sections).toHaveLength(1); | |
| expect(result.sections[0].sectionTypeId).toBe("READING"); | |
| }); | |
| it("addQuestion adds question to section", async () => { | |
| const [q] = await testDb.insert(schema.question).values({ | |
| examTypeId: "IELTS", sectionTypeId: "READING", format: "multiple_choice", | |
| passageText: "Q".repeat(60), questionText: "Test?", | |
| options: [{ key: "A", text: "A" }, { key: "B", text: "B" }], | |
| correctAnswer: "A", explanation: "Exp", difficulty: 1, | |
| skillTags: ["test"], creatorUserId: ownerId, isPublic: true, | |
| }).returning(); | |
| questionId = q.id; | |
| const result = await protectedCaller.addQuestion({ | |
| sectionId, | |
| questionId: q.id, | |
| orderIndex: 0, | |
| }); | |
| expect(result).toHaveProperty("id"); | |
| }); | |
| it("getById shows questions for owner, strips answers for guests", async () => { | |
| const ownerResult = await protectedCaller.getById({ id: pkgId }); | |
| const section = ownerResult.sections.find((s: any) => s.id === sectionId); | |
| expect(section.questions).toHaveLength(1); | |
| expect(section.questions[0].correctAnswer).toBe("A"); | |
| const guestResult = await caller.getById({ id: pkgId }); | |
| const guestSection = guestResult.sections.find((s: any) => s.id === sectionId); | |
| expect(guestSection.questions[0].correctAnswer).toBeUndefined(); | |
| }); | |
| it("myPackages returns owned packages", async () => { | |
| const result = await protectedCaller.myPackages(); | |
| expect(result.packages.length).toBeGreaterThan(0); | |
| const ids = result.packages.map((p: any) => p.id); | |
| expect(ids).toContain(pkgId); | |
| }); | |
| it("featured returns empty when no featured packages", async () => { | |
| const result = await caller.featured(); | |
| expect(result).toEqual([]); | |
| }); | |
| it("trending returns public packages sorted by usage", async () => { | |
| await testDb.update(schema.testPackage).set({ isPublic: true }).where(eq(schema.testPackage.id, pkgId)); | |
| const result = await caller.trending(); | |
| expect(result.length).toBeGreaterThan(0); | |
| }); | |
| it("removeQuestion removes question from section", async () => { | |
| const sq = await protectedCaller.addQuestion({ | |
| sectionId, questionId, orderIndex: 0, | |
| }); | |
| const result = await protectedCaller.removeQuestion({ sectionQuestionId: sq.id }); | |
| expect(result.success).toBe(true); | |
| }); | |
| it("removeSection removes section", async () => { | |
| const result = await protectedCaller.removeSection({ sectionId }); | |
| expect(result.success).toBe(true); | |
| }); | |
| it("delete removes package", async () => { | |
| const result = await protectedCaller.delete({ id: pkgId }); | |
| expect(result.success).toBe(true); | |
| const fetched = await caller.getById({ id: pkgId }); | |
| expect(fetched).toBeNull(); | |
| }); | |
| }); | |