mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
api.logout() (POST /auth/logout) existed but was never called, leaving the bearer token valid server-side after a client-local logout. Add a small logout() helper that fires the revocation best-effort — fire-and-forget with its rejection swallowed — then runs clearAuth() synchronously, so a slow, offline, or rejecting server can never block or delay the local logout. Wire it into the settings Log Out button. Tests pin both paths: logout is called, and local logout still completes when the request rejects or never settles. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
53 lines
1.7 KiB
TypeScript
53 lines
1.7 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
|
|
// clearAuth pulls in voice/livekit/notification teardown; stub it so this test
|
|
// stays a pure unit test of the best-effort revoke-then-teardown ordering.
|
|
const clearAuth = vi.fn();
|
|
vi.mock("@stores/auth.store", () => ({
|
|
clearAuth: () => clearAuth(),
|
|
}));
|
|
|
|
import { logout } from "../../src/lib/logout";
|
|
|
|
function makeApi(logoutImpl: () => Promise<void>): { logout: ReturnType<typeof vi.fn> } {
|
|
return { logout: vi.fn(logoutImpl) };
|
|
}
|
|
|
|
describe("logout", () => {
|
|
beforeEach(() => {
|
|
clearAuth.mockClear();
|
|
});
|
|
|
|
it("calls POST /auth/logout and then clears local auth", () => {
|
|
const api = makeApi(() => Promise.resolve());
|
|
|
|
logout(api);
|
|
|
|
expect(api.logout).toHaveBeenCalledTimes(1);
|
|
expect(clearAuth).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it("still logs out locally when the revocation request rejects", async () => {
|
|
const api = makeApi(() => Promise.reject(new Error("network down")));
|
|
|
|
// Must not throw despite the rejected request...
|
|
expect(() => logout(api)).not.toThrow();
|
|
// ...and the local teardown must have happened regardless of the outcome.
|
|
expect(clearAuth).toHaveBeenCalledTimes(1);
|
|
|
|
// Let the rejected promise settle: the swallowing .catch() must prevent an
|
|
// unhandled rejection and must not re-trigger teardown.
|
|
await Promise.resolve();
|
|
expect(clearAuth).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it("does not await the request before local logout (best-effort, non-blocking)", () => {
|
|
// A request that never settles must not delay or block clearAuth.
|
|
const api = makeApi(() => new Promise<void>(() => {}));
|
|
|
|
logout(api);
|
|
|
|
expect(clearAuth).toHaveBeenCalledTimes(1);
|
|
});
|
|
});
|