fix(files): the token list is fresh after the sessions end, a copy again reads Copied again, the Copied button says so
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
// @vitest-environment jsdom
|
||||
//
|
||||
// Ending every other session, or changing the password, revokes every API token on the server — so
|
||||
// the Tokens tab must not then show them from its cache as if they still worked.
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { cleanup, fireEvent, render, screen, waitFor } from "@testing-library/react";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
|
||||
import type { Me } from "../lib/api";
|
||||
import { qk } from "../lib/queryKeys";
|
||||
|
||||
const h = vi.hoisted(() => ({
|
||||
logoutOthers: vi.fn(async () => ({ ok: true })),
|
||||
setPassword: vi.fn(async (_p: string, _c?: string) => ({ ok: true })),
|
||||
}));
|
||||
|
||||
vi.mock("react-i18next", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("react-i18next")>();
|
||||
return {
|
||||
...actual,
|
||||
useTranslation: () => ({ t: (key: string) => key, i18n: { language: "en" } }),
|
||||
};
|
||||
});
|
||||
vi.mock("../lib/api", async (importOriginal) => ({
|
||||
...(await importOriginal<typeof import("../lib/api")>()),
|
||||
api: h,
|
||||
}));
|
||||
vi.mock("../lib/notifications", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../lib/notifications")>();
|
||||
return { ...actual, notify: vi.fn() };
|
||||
});
|
||||
vi.mock("./confirmContext", () => ({ useConfirm: () => vi.fn(async () => true) }));
|
||||
|
||||
import { SignInMethods } from "./SettingsPanel";
|
||||
|
||||
afterEach(cleanup);
|
||||
|
||||
const me = { email: "a@example.com", has_password: true, google_enabled: false } as Me;
|
||||
|
||||
function renderIt() {
|
||||
const qc = new QueryClient({ defaultOptions: { queries: { retry: false } } });
|
||||
qc.setQueryData(qk.apiTokens(), [{ id: 1 }]);
|
||||
render(
|
||||
<QueryClientProvider client={qc}>
|
||||
<SignInMethods me={me} />
|
||||
</QueryClientProvider>,
|
||||
);
|
||||
return qc;
|
||||
}
|
||||
|
||||
const tokensStale = (qc: QueryClient) => qc.getQueryState(qk.apiTokens())?.isInvalidated;
|
||||
|
||||
describe("SignInMethods", () => {
|
||||
it("signing the other sessions out marks the token list stale", async () => {
|
||||
const qc = renderIt();
|
||||
fireEvent.click(screen.getByText("settings.account.sessions.action"));
|
||||
await waitFor(() => expect(h.logoutOthers).toHaveBeenCalled());
|
||||
await waitFor(() => expect(tokensStale(qc)).toBe(true));
|
||||
});
|
||||
|
||||
it("a password changed marks the token list stale", async () => {
|
||||
const qc = renderIt();
|
||||
fireEvent.click(screen.getByText("settings.account.password.change"));
|
||||
fireEvent.change(screen.getByPlaceholderText("settings.account.password.current"), {
|
||||
target: { value: "old one" },
|
||||
});
|
||||
fireEvent.change(screen.getByPlaceholderText("settings.account.password.new"), {
|
||||
target: { value: "a brand new one" },
|
||||
});
|
||||
fireEvent.click(screen.getByText("settings.account.password.save"));
|
||||
await waitFor(() => expect(h.setPassword).toHaveBeenCalled());
|
||||
await waitFor(() => expect(tokensStale(qc)).toBe(true));
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user