aboutsummaryrefslogtreecommitdiff
path: root/apps/backend/test
diff options
context:
space:
mode:
authorDhravya Shah <[email protected]>2025-01-23 19:05:33 -0700
committerDhravya Shah <[email protected]>2025-01-23 19:05:33 -0700
commit12b26382094c0faf27bfb94ec50564e966a22993 (patch)
tree1841c3a6d59dd662e3c065422fe01ba4937008be /apps/backend/test
parentimport tools: CSV and markdown (obsidian) (diff)
downloadsupermemory-chunking-and-retrieval.tar.xz
supermemory-chunking-and-retrieval.zip
De duplication and updating chunkschunking-and-retrieval
Diffstat (limited to 'apps/backend/test')
-rw-r--r--apps/backend/test/routes/memories.test.ts247
-rw-r--r--apps/backend/test/setup.ts32
2 files changed, 279 insertions, 0 deletions
diff --git a/apps/backend/test/routes/memories.test.ts b/apps/backend/test/routes/memories.test.ts
new file mode 100644
index 00000000..c7a8f21d
--- /dev/null
+++ b/apps/backend/test/routes/memories.test.ts
@@ -0,0 +1,247 @@
+import { describe, it, expect, beforeAll, afterAll } from "vitest";
+import { app } from "../../src";
+import type { Document } from "@supermemory/db/schema";
+
+import { testClient } from "hono/testing";
+import { env, SELF } from "cloudflare:test";
+
+const API_KEY =
+ "sm_4y1M2QIpRtKJMMfXWCqAhD_NVXOqLqOzOOuIZ1qhL1Gj0BFWFPuRlng5TPvZ1OIu1Zn1G8_xuuz59M4o4l-sAkSieZgaW09COg";
+
+interface MemoryResponse {
+ items: Array<Document>;
+ total: number;
+}
+
+interface SuccessResponse {
+ success: boolean;
+}
+
+describe("Memories Routes", () => {
+ const client = testClient(app, env);
+
+ describe("GET /api/memories", () => {
+ it("should list memories with default pagination", async () => {
+ const res = await client.api.memories.$get(
+ { query: {} },
+ {
+ headers: {
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ }
+ );
+
+ expect(res.status).toBe(200);
+ const data = (await res.json()) as MemoryResponse;
+ expect(data).toHaveProperty("items");
+ expect(data).toHaveProperty("total");
+ expect(Array.isArray(data.items)).toBe(true);
+ });
+
+ it("should respect pagination parameters", async () => {
+ const res = await client.api.memories.$get(
+ {
+ query: {
+ start: "1",
+ count: "5",
+ },
+ },
+ {
+ headers: {
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ }
+ );
+ expect(res.status).toBe(200);
+ const data = (await res.json()) as MemoryResponse;
+ expect(data.items.length).toBeLessThanOrEqual(5);
+ });
+
+ it("should filter by space ID", async () => {
+ const res = await client.api.memories.$get(
+ {
+ query: {
+ spaceId: "test-space-uuid",
+ },
+ },
+ {
+ headers: {
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ }
+ );
+ expect(res.status).toBe(200);
+ const data = (await res.json()) as MemoryResponse;
+ expect(data).toHaveProperty("items");
+ expect(data).toHaveProperty("total");
+ });
+
+ it("should handle unauthorized space access", async () => {
+ const res = await client.api.memories.$get(
+ {
+ query: {
+ spaceId: "private-space-uuid",
+ },
+ },
+ {
+ headers: {
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ }
+ );
+ expect(res.status).toBe(401);
+ });
+
+ it("should reject requests without API key", async () => {
+ const res = await client.api.memories.$get(
+ { query: {} },
+ {
+ headers: {
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ }
+ );
+ expect(res.status).toBe(401);
+ });
+
+ it("should respect ETag caching", async () => {
+ // First request to get ETag
+ const res1 = await client.api.memories.$get(
+ { query: {} },
+ {
+ headers: {
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ }
+ );
+ const etag = res1.headers.get("ETag");
+ expect(etag).toBeDefined();
+
+ // Second request with ETag
+ const res2 = await client.api.memories.$get(
+ { query: {} },
+ {
+ headers: {
+ Authorization: `Bearer ${API_KEY}`,
+ "If-None-Match": etag!,
+ },
+ }
+ );
+ expect(res2.status).toBe(304);
+ });
+ });
+
+ describe("GET /api/memories/:id", () => {
+ let testMemoryId: string;
+
+ beforeAll(async () => {
+ const res = await client.api.memories.$get(
+ { query: {} },
+ {
+ headers: {
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ }
+ );
+ const data = (await res.json()) as MemoryResponse;
+ if (data.items.length > 0) {
+ testMemoryId = data.items[0].uuid;
+ }
+ });
+
+ it("should retrieve a specific memory", async () => {
+ if (!testMemoryId) {
+ console.warn("No test memory available, skipping test");
+ return;
+ }
+
+ const res = await client.api.memories[":id"].$get(
+ {
+ param: {
+ id: testMemoryId,
+ },
+ },
+ {
+ headers: {
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ }
+ );
+ expect(res.status).toBe(200);
+ const memory = await res.json();
+ expect(memory).toHaveProperty("uuid", testMemoryId);
+ });
+
+ it("should reject unauthorized access", async () => {
+ const res = await client.api.memories[":id"].$get(
+ {
+ param: {
+ id: testMemoryId,
+ },
+ },
+ {
+ headers: {
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ }
+ );
+ expect(res.status).toBe(401);
+ });
+ });
+
+ describe("DELETE /api/memories/:id", () => {
+ let memoryId: string;
+
+ beforeAll(async () => {
+ const res = await client.api.memories.$get(
+ { query: {} },
+ {
+ headers: {
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ }
+ );
+ const data = (await res.json()) as MemoryResponse;
+ if (data.items.length > 0) {
+ memoryId = data.items[0].uuid;
+ }
+ });
+
+ it("should delete a memory", async () => {
+ const res = await client.api.memories[":id"].$delete(
+ {
+ param: { id: memoryId },
+ },
+ {
+ headers: { Authorization: `Bearer ${API_KEY}` },
+ }
+ );
+
+ expect(res.status).toBe(200);
+ expect(await res.json()).toEqual({ success: true });
+
+ // Verify deletion
+ const getRes = await client.api.memories[":id"].$get(
+ {
+ param: { id: memoryId },
+ },
+ {
+ headers: { Authorization: `Bearer ${API_KEY}` },
+ }
+ );
+ expect(getRes.status).toBe(404);
+ });
+
+ it("should reject unauthorized deletion", async () => {
+ const res = await client.api.memories[":id"].$delete(
+ {
+ param: { id: memoryId },
+ },
+ {
+ headers: { Authorization: `Bearer ${API_KEY}` },
+ }
+ );
+ expect(res.status).toBe(401);
+ });
+ });
+});
diff --git a/apps/backend/test/setup.ts b/apps/backend/test/setup.ts
new file mode 100644
index 00000000..62c993c7
--- /dev/null
+++ b/apps/backend/test/setup.ts
@@ -0,0 +1,32 @@
+import { Hono } from "hono";
+import type { Env } from "../src/types";
+import { describe, it, expect, beforeAll, afterAll } from "vitest";
+
+// Helper to generate random test content
+export function generateTestContent(length: number = 1000): string {
+ return Array(length)
+ .fill(0)
+ .map(() => Math.random().toString(36).charAt(2))
+ .join("");
+}
+
+// Helper to measure response time
+export async function measureResponseTime(
+ fn: () => Promise<Response>
+): Promise<number> {
+ const start = performance.now();
+ await fn();
+ return performance.now() - start;
+}
+
+// Common test expectations
+export const expect200 = (response: Response) =>
+ expect(response.status).toBe(200);
+export const expect401 = (response: Response) =>
+ expect(response.status).toBe(401);
+export const expect403 = (response: Response) =>
+ expect(response.status).toBe(403);
+export const expect404 = (response: Response) =>
+ expect(response.status).toBe(404);
+export const expect429 = (response: Response) =>
+ expect(response.status).toBe(429);