diff --git a/CHANGELOG.md b/CHANGELOG.md index d67263859..d860867f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed +- Fixed the public offers endpoint returning a JSON body with a `text/plain` content type. [#1670](https://github.com/sourcebot-dev/sourcebot/pull/1670) + ## [5.1.14] - 2026-09-17 ### Added diff --git a/packages/web/src/app/api/(server)/offers/route.test.ts b/packages/web/src/app/api/(server)/offers/route.test.ts new file mode 100644 index 000000000..118d6c2e0 --- /dev/null +++ b/packages/web/src/app/api/(server)/offers/route.test.ts @@ -0,0 +1,47 @@ +import { NextRequest } from "next/server"; +import { beforeEach, describe, expect, test, vi } from "vitest"; + +const mocks = vi.hoisted(() => ({ + offers: vi.fn(), +})); + +vi.mock("@/features/billing/client", () => ({ + client: { + offers: mocks.offers, + }, +})); + +vi.mock("@sourcebot/shared", () => ({ + env: { + SOURCEBOT_INSTALL_ID: "install-id", + }, +})); + +vi.mock("@/lib/posthog", () => ({ + captureEvent: vi.fn(), +})); + +const importRoute = async () => { + vi.resetModules(); + return import("./route"); +}; + +describe("GET /api/offers", () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + test("returns offers as JSON", async () => { + const offers = [{ id: "startup" }]; + mocks.offers.mockResolvedValue(offers); + const { GET } = await importRoute(); + + const response = await GET(new NextRequest("https://sourcebot.example.com/api/offers")); + + expect(mocks.offers).toHaveBeenCalledTimes(1); + expect(mocks.offers).toHaveBeenCalledWith({ installId: "install-id" }); + expect(response.headers.get("content-type")).toContain("application/json"); + expect(response.headers.get("cache-control")).toBe("public, max-age=300"); + await expect(response.json()).resolves.toEqual(offers); + }); +}); diff --git a/packages/web/src/app/api/(server)/offers/route.ts b/packages/web/src/app/api/(server)/offers/route.ts index aff748d5d..bae6e4911 100644 --- a/packages/web/src/app/api/(server)/offers/route.ts +++ b/packages/web/src/app/api/(server)/offers/route.ts @@ -8,9 +8,9 @@ export const GET = apiHandler(async () => { installId: env.SOURCEBOT_INSTALL_ID, }); - return new Response(JSON.stringify(offers), { + return Response.json(offers, { headers: { 'Cache-Control': 'public, max-age=300' } }); -}) \ No newline at end of file +})