import { describe, it, expect, mock, beforeEach } from "bun:test"; // Mock the OAuth client and session const mockOAuthSession = { getTokenInfo: mock(), }; const mockOAuthClient = { restore: mock(), }; const mockSession = { did: "did:plc:test123", updateConfig: mock(), save: mock(), destroy: mock(), }; // Mock environment void mock.module("../env", () => ({ env: { COOKIE_SECRET: "test-secret-key-for-testing-purposes-only", }, })); describe("Token Refresh Logic", () => { beforeEach(() => { mockOAuthClient.restore.mockClear(); mockOAuthSession.getTokenInfo.mockClear(); mockSession.updateConfig.mockClear(); mockOAuthClient.restore.mockResolvedValue(mockOAuthSession); }); it('should use "auto" mode for automatic token refresh', async () => { const mockTokenInfo = { expiresAt: new Date(Date.now() + 30 * 60 * 1000), }; mockOAuthSession.getTokenInfo.mockResolvedValueOnce(mockTokenInfo); const oauthSession = await mockOAuthClient.restore(mockSession.did, false); await oauthSession.getTokenInfo("auto"); expect(mockOAuthSession.getTokenInfo).toHaveBeenCalledWith("auto"); }); it("should handle token refresh in mobile endpoint", async () => { const mockTokenInfo = { expiresAt: new Date(Date.now() + 30 * 60 * 1000), }; mockOAuthSession.getTokenInfo.mockResolvedValueOnce(mockTokenInfo); const oauthSession = await mockOAuthClient.restore(mockSession.did); await oauthSession.getTokenInfo("auto"); mockSession.updateConfig({ cookieName: "sid", password: "test-secret-key-for-testing-purposes-only", ttl: 60 * 60 * 24, }); expect(mockSession.updateConfig).toHaveBeenCalledWith( expect.objectContaining({ ttl: 86400, }), ); }); it("should handle token refresh failure gracefully", async () => { mockOAuthSession.getTokenInfo.mockRejectedValueOnce(new Error("Token refresh failed")); try { const oauthSession = await mockOAuthClient.restore(mockSession.did); await oauthSession.getTokenInfo("auto"); } catch (error) { expect(error).toBeInstanceOf(Error); expect((error as Error).message).toBe("Token refresh failed"); } }); it("should prioritize automatic refresh over manual refresh", () => { const autoMode = "auto"; const manualMode = false; expect(autoMode).toBe("auto"); expect(autoMode).not.toBe(manualMode); }); it("should maintain consistent session TTL across refresh operations", () => { const sessionTTL = 60 * 60 * 24; expect(sessionTTL).toBe(86400); const firstRefreshTTL = sessionTTL; const secondRefreshTTL = sessionTTL; expect(firstRefreshTTL).toBe(secondRefreshTTL); }); });