ci / node (pull_request) Skipped
ci / version (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 3m3s
ci / docker-build (pull_request) Skipped
ci / publish (pull_request) Skipped
ci / announce (pull_request) Skipped
Second of three for background push across accounts (multi-account spec, MA-8 part 2). Turning on "Notify me even when inbuxa is closed" now registers this browser in every signed-in account, each through its own session (the route from the previous change), and renewal keeps them all current. GET /api/auth/accounts says which mail account each session is, so the subscription can name it. The remembered endpoint is kept per account, and survives the clean-up that follows switching accounts. The service worker is told who the other accounts are. A push for one of them is titled with that account's address, shown even while a tab is focused (the tab only shows the front account's mail), and its Mark read and Archive act through that account's session. Clicking it brings that account to the front and opens the message. While push is on, the tab's own polling of other accounts stops notifying, so nothing arrives twice. Signing out of one account removes this device's subscription there only; signing out of all, or turning push off, removes every one. Also fixes where every background notification opened: the worker linked to /mail/inbox/<thread>, and the route takes a mailbox id there, so a click landed on the inbox list with "That folder no longer exists". The worker now gets each account's inbox id and links to the message. Checked end to end in Chrome against a local server with two accounts: both registered and verified, a message to the account not in front showed a notification under its address, and clicking it switched accounts and opened the message. No new strings. typecheck, tests (web 1547, server 279) and build pass.
46 lines
2.2 KiB
TypeScript
46 lines
2.2 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
import { clearSignedInData, setDeviceTrusted } from "@/lib/storage";
|
|
import { deviceClientId, registeredEndpoint, rememberEndpoint, unsubscribeAccount, type JmapCall } from "@/lib/notify/webpush";
|
|
|
|
/** inbuxa MA-8 part 2: every signed-in account on this device has its own push subscription. */
|
|
|
|
beforeEach(() => localStorage.clear());
|
|
afterEach(() => localStorage.clear());
|
|
|
|
describe("push for every signed-in account", () => {
|
|
it("remembers each account's endpoint, and keeps them through a switch", () => {
|
|
rememberEndpoint("https://push.example/old");
|
|
// An account with nothing of its own yet reads the endpoint from before
|
|
expect(registeredEndpoint("acc-a")).toBe("https://push.example/old");
|
|
rememberEndpoint("https://push.example/a", "acc-a");
|
|
rememberEndpoint("https://push.example/b", "acc-b");
|
|
expect(registeredEndpoint("acc-a")).toBe("https://push.example/a");
|
|
expect(registeredEndpoint("acc-b")).toBe("https://push.example/b");
|
|
localStorage.setItem("ihasmail:cached-mail", "x");
|
|
clearSignedInData();
|
|
expect(registeredEndpoint("acc-a")).toBe("https://push.example/a");
|
|
expect(localStorage.getItem("ihasmail:cached-mail")).toBeNull();
|
|
rememberEndpoint(null, "acc-a");
|
|
expect(localStorage.getItem("ihasmail:pushEndpoint:acc-a")).toBeNull();
|
|
});
|
|
|
|
it("removes only this device's subscription from one account", async () => {
|
|
// A device id is kept only where the device is trusted
|
|
setDeviceTrusted(true);
|
|
const mine = deviceClientId();
|
|
const destroyed: string[] = [];
|
|
const call: JmapCall = async <T,>(method: string, args: Record<string, unknown>) => {
|
|
if (method === "PushSubscription/get") {
|
|
return { list: [{ id: "p1", deviceClientId: mine }, { id: "p2", deviceClientId: "ihasmail-other-phone" }] } as T;
|
|
}
|
|
destroyed.push(...((args.destroy as string[]) ?? []));
|
|
return {} as T;
|
|
};
|
|
rememberEndpoint("https://push.example/a", "acc-a");
|
|
await unsubscribeAccount(call, "acc-a");
|
|
expect(destroyed).toEqual(["p1"]);
|
|
expect(localStorage.getItem("ihasmail:pushEndpoint:acc-a")).toBeNull();
|
|
setDeviceTrusted(false);
|
|
});
|
|
});
|