ci / node (pull_request) Skipped
ci / version (pull_request) Skipped
ci / docker-build (pull_request) Skipped
ci / publish (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 2m24s
ci / announce (pull_request) Skipped
With more than one account signed in (#49), mail arriving in one that isn't in front went unseen until someone switched to it (multi-account spec, MA-8). - GET /api/auth/accounts/unread answers the Inbox unread count of each account not in front, asked through that account's own session (its OAuth token renewed first if due), kept a minute per account. - The web app asks every two minutes while another account is signed in. The account menu shows each one's count beside its name, and the avatar carries a dot when any of them has unread mail. - When a count rises while the app is open and desktop notifications are on, a notification names the account ("New mail for [email protected]"); clicking it switches to that account. An account seen for the first time doesn't notify: its mail was already there. Not in this change: notifications with the app closed, which need each added account's own Web Push subscription. New strings (3, English only in the other ten catalogs): "New mail for {name}", "Unread in the Inbox: {count}", "Account: new mail in another account". Tests: the server answers the other account's count and nothing when alone; the client keeps the counts, notifies only on a rise and only with notifications on. Checked in Chrome against the mock. typecheck, tests (web 1541, server 277) and build pass.
69 lines
2.4 KiB
TypeScript
69 lines
2.4 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
|
/** inbuxa MA-8: new mail in the accounts not in front. */
|
|
|
|
const shown: { title: string; opts: Record<string, unknown> }[] = [];
|
|
vi.mock("@/lib/notify/notify", () => ({
|
|
showNotification: (title: string, opts: Record<string, unknown>) => shown.push({ title, opts }),
|
|
}));
|
|
|
|
const { risen, pollOtherUnread, useOtherUnread } = await import("@/lib/otherAccounts");
|
|
const { useSession } = await import("@/store/session");
|
|
const { useSettings } = await import("@/store/settings");
|
|
|
|
let counts: Record<string, number>;
|
|
|
|
beforeEach(() => {
|
|
shown.length = 0;
|
|
counts = { b: 3 };
|
|
vi.stubGlobal(
|
|
"fetch",
|
|
vi.fn(async () => {
|
|
const body = { accounts: Object.entries(counts).map(([id, unread]) => ({ id, unread })) };
|
|
return { ok: true, status: 200, json: async () => body, text: async () => JSON.stringify(body) } as Response;
|
|
}),
|
|
);
|
|
useOtherUnread.getState().set({});
|
|
useSession.setState({
|
|
signedIn: [
|
|
{ id: "a", username: "[email protected]", front: true },
|
|
{ id: "b", username: "[email protected]", front: false },
|
|
],
|
|
});
|
|
useSettings.setState((s) => ({ settings: { ...s.settings, desktopNotifications: true } }));
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.unstubAllGlobals();
|
|
});
|
|
|
|
describe("other accounts' unread mail", () => {
|
|
it("counts only a rise, and never an account seen for the first time", () => {
|
|
expect(risen({}, { b: 4 })).toEqual([]);
|
|
expect(risen({ b: 4 }, { b: 4 })).toEqual([]);
|
|
expect(risen({ b: 4 }, { b: 2 })).toEqual([]);
|
|
expect(risen({ b: 4, c: 1 }, { b: 5, c: 1 })).toEqual(["b"]);
|
|
});
|
|
|
|
it("keeps the counts, and names the account when new mail arrives", async () => {
|
|
await pollOtherUnread();
|
|
expect(useOtherUnread.getState().unread).toEqual({ b: 3 });
|
|
expect(shown).toEqual([]);
|
|
|
|
counts = { b: 5 };
|
|
await pollOtherUnread();
|
|
expect(shown).toHaveLength(1);
|
|
expect(shown[0]!.title).toContain("[email protected]");
|
|
expect(shown[0]!.opts.tag).toBe("other-account-b");
|
|
});
|
|
|
|
it("stays quiet when desktop notifications are off", async () => {
|
|
useSettings.setState((s) => ({ settings: { ...s.settings, desktopNotifications: false } }));
|
|
await pollOtherUnread();
|
|
counts = { b: 9 };
|
|
await pollOtherUnread();
|
|
expect(shown).toEqual([]);
|
|
expect(useOtherUnread.getState().unread).toEqual({ b: 9 });
|
|
});
|
|
});
|