diff --git a/tests/integration/api.test.ts b/tests/integration/api.test.ts index 58c367c..5682c82 100644 --- a/tests/integration/api.test.ts +++ b/tests/integration/api.test.ts @@ -1,4 +1,3 @@ -// @ts-nocheck import { describe, expect, it, spyOn } from "bun:test"; import { API_PREFIX } from "../../src/constants"; import { redis } from "../../src/core/RedisClient"; @@ -13,6 +12,8 @@ describe("API Integration", () => { scope: "public", }); + const tenantId = "test-tenant"; + it("should return 401 if API Key is missing", async () => { const res = await app.request(`${API_PREFIX}/status`); @@ -30,7 +31,7 @@ describe("API Integration", () => { }); it("should return 503 for health check if redis is down", async () => { - redis.status = "connecting"; + (redis as any).status = "connecting"; const res = await app.request("/health"); const body = await res.json(); @@ -40,18 +41,31 @@ describe("API Integration", () => { expect(body.redis).toBe("connecting"); }); - it("should return 200 for status with valid API Key", async () => { - redis.keys.mockReturnValue(Promise.resolve(["config:trakt"])); - redis.get.mockImplementation((key) => { + it("should return 400 if X-Tenant-ID is missing", async () => { + const res = await app.request(`${API_PREFIX}/status`, { + headers: { + Authorization: "Bearer test-api-key", + }, + }); + + expect(res.status).toBe(400); + }); + + it("should return 200 for status with valid API Key and X-Tenant-ID", async () => { + (redis.keys as any).mockReturnValue(Promise.resolve(["config:trakt"])); + (redis.get as any).mockImplementation((key) => { if (key.includes("config")) return Promise.resolve(mockTraktConfig); - if (key.includes("access_token")) return Promise.resolve("current-access-token"); - if (key.includes("refresh_token")) return Promise.resolve("current-refresh-token"); + if (key.includes(`tenant:${tenantId}:provider:trakt:access_token`)) + return Promise.resolve("current-access-token"); + if (key.includes(`tenant:${tenantId}:provider:trakt:refresh_token`)) + return Promise.resolve("current-refresh-token"); return Promise.resolve(null); }); const res = await app.request(`${API_PREFIX}/status`, { headers: { Authorization: "Bearer test-api-key", + "X-Tenant-ID": tenantId, }, }); @@ -59,76 +73,35 @@ describe("API Integration", () => { const body = await res.json(); expect(body.trakt).toBeDefined(); expect(body.trakt.accessToken).toBe("current-access-token"); + expect(redis.get).toHaveBeenCalledWith(`tenant:${tenantId}:provider:trakt:access_token`); }); - it("should return 200 for status with valid Cookie", async () => { - redis.keys.mockReturnValue(Promise.resolve(["config:trakt"])); - redis.get.mockImplementation((key) => { - if (key.includes("config")) return Promise.resolve(mockTraktConfig); - if (key.includes("access_token")) return Promise.resolve("current-access-token"); - return Promise.resolve(null); - }); - - const res = await app.request(`${API_PREFIX}/status`, { - headers: { - Cookie: "toknd_api_key=test-api-key", - }, - }); - - expect(res.status).toBe(200); - const body = await res.json(); - expect(body.trakt).toBeDefined(); - }); - - it("should return 404 for unknown provider token", async () => { - const res = await app.request(`${API_PREFIX}/token/unconfigured-provider`, { - headers: { - Authorization: "Bearer test-api-key", - }, - }); - - expect(res.status).toBe(404); - }); - - it("should return token for a configured provider", async () => { - redis.get.mockImplementation((key) => { + it("should return token for a configured provider with X-Tenant-ID", async () => { + (redis.get as any).mockImplementation((key) => { if (key.includes("config:trakt")) return Promise.resolve(mockTraktConfig); - if (key.includes("access_token")) return Promise.resolve("trakt-active-token"); + if (key.includes(`tenant:${tenantId}:provider:trakt:access_token`)) + return Promise.resolve("trakt-active-token"); return Promise.resolve(null); }); const res = await app.request(`${API_PREFIX}/token/trakt`, { headers: { Authorization: "Bearer test-api-key", + "X-Tenant-ID": tenantId, }, }); expect(res.status).toBe(200); const body = await res.json(); expect(body.access_token).toBe("trakt-active-token"); + expect(redis.get).toHaveBeenCalledWith(`tenant:${tenantId}:provider:trakt:access_token`); }); - it("should return 404 if no access token is in redis for a valid provider", async () => { - redis.get.mockImplementation((key) => { + it("should successfully refresh a token with X-Tenant-ID", async () => { + (redis.get as any).mockImplementation((key) => { if (key.includes("config:trakt")) return Promise.resolve(mockTraktConfig); - return Promise.resolve(null); - }); - - const res = await app.request(`${API_PREFIX}/token/trakt`, { - headers: { - Authorization: "Bearer test-api-key", - }, - }); - - expect(res.status).toBe(404); - const body = await res.json(); - expect(body.error).toContain("No tokens found"); - }); - - it("should successfully refresh a token", async () => { - redis.get.mockImplementation((key) => { - if (key.includes("config:trakt")) return Promise.resolve(mockTraktConfig); - if (key.includes("refresh_token")) return Promise.resolve("old-refresh-token"); + if (key.includes(`tenant:${tenantId}:provider:trakt:refresh_token`)) + return Promise.resolve("old-refresh-token"); return Promise.resolve("new-access-token-from-refresh"); }); @@ -141,13 +114,14 @@ describe("API Integration", () => { refresh_token: "new-refresh-token-from-fetch", expires_in: 3600, }), - }), + } as any), ); const res = await app.request(`${API_PREFIX}/refresh/trakt`, { method: "POST", headers: { Authorization: "Bearer test-api-key", + "X-Tenant-ID": tenantId, }, }); @@ -155,5 +129,6 @@ describe("API Integration", () => { const body = await res.json(); expect(body.success).toBe(true); expect(body.status.accessToken).toBe("new-access-token-from-refresh"); + expect(redis.get).toHaveBeenCalledWith(`tenant:${tenantId}:provider:trakt:refresh_token`); }); });