Ask shared accounts together, and about files only when Files opens
At sign-in the files, contacts and calendar stores each asked every shared account a question, one account after another: a request apiece before the reader had opened any of those views. Files now only works out at sign-in whether it is available. Which shared accounts hold files is asked when the Files view or the file picker opens, which the Files view already did on every visit. Shared address books and calendars are asked for in one request, and the calendar store loads its calendars, identities and shared calendars side by side.
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { CAP, client } from "@/jmap/client";
|
||||
import type { JmapSession } from "@/jmap/types";
|
||||
import { useSession } from "@/store/session";
|
||||
import { useFiles } from "@/store/files";
|
||||
import { useContacts } from "@/store/contacts";
|
||||
import { useCalendar } from "@/store/calendar";
|
||||
|
||||
/**
|
||||
* What signing in costs for each account somebody has shared with the reader.
|
||||
*
|
||||
* The files, contacts and calendar stores each asked every shared account a
|
||||
* question at sign-in, one account after another -- a request apiece, before
|
||||
* the reader had opened any of those views. The questions now go out together,
|
||||
* and Files does not ask at all until it is opened.
|
||||
*/
|
||||
|
||||
const SHARED = ["s1", "s2", "s3"];
|
||||
|
||||
const session = {
|
||||
capabilities: { [CAP.core]: { maxCallsInRequest: 16, maxObjectsInGet: 500 }, [CAP.filenode]: {}, [CAP.contacts]: {}, [CAP.calendars]: {} },
|
||||
accounts: {
|
||||
own: { name: "[email protected]", isPersonal: true, accountCapabilities: { [CAP.filenode]: {}, [CAP.contacts]: {}, [CAP.calendars]: {} } },
|
||||
...Object.fromEntries(SHARED.map((id) => [id, { name: `${id}@example.com`, isPersonal: false, accountCapabilities: {} }])),
|
||||
},
|
||||
primaryAccounts: { [CAP.filenode]: "own", [CAP.contacts]: "own", [CAP.calendars]: "own" },
|
||||
state: "s",
|
||||
} as unknown as JmapSession;
|
||||
|
||||
type Call = [string, Record<string, unknown>, string];
|
||||
|
||||
let requests: Call[][];
|
||||
|
||||
beforeEach(() => {
|
||||
requests = [];
|
||||
vi.stubGlobal("fetch", vi.fn(async (_url: string, init: RequestInit) => {
|
||||
const { methodCalls } = JSON.parse(init.body as string) as { methodCalls: Call[] };
|
||||
requests.push(methodCalls);
|
||||
const methodResponses = methodCalls.map(([name, args, id]) => {
|
||||
const accountId = args.accountId as string;
|
||||
if (name === "FileNode/query") return [name, { accountId, ids: accountId === "s2" ? ["f1"] : [], total: 0, position: 0, queryState: "q" }, id];
|
||||
if (name === "Calendar/get") return [name, { accountId, state: "1", list: [{ id: `cal-${accountId}`, name: `Calendar of ${accountId}` }], notFound: [] }, id];
|
||||
return [name, { accountId, state: "1", list: [], notFound: [] }, id];
|
||||
});
|
||||
return { ok: true, status: 200, json: async () => ({ methodResponses, sessionState: "s" }) } as Response;
|
||||
}));
|
||||
client.session = session;
|
||||
useSession.setState({ status: "authenticated", session, accountId: "own" });
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
describe("shared accounts", () => {
|
||||
it("are not asked about files at sign-in", async () => {
|
||||
await useFiles.getState().init();
|
||||
expect(requests).toHaveLength(0);
|
||||
expect(useFiles.getState().available).toBe(true);
|
||||
expect(useFiles.getState().ownAccountId).toBe("own");
|
||||
});
|
||||
|
||||
it("are asked about files together when Files wants to know", async () => {
|
||||
await useFiles.getState().discoverShared();
|
||||
expect(requests).toHaveLength(1);
|
||||
expect(requests[0]!.map(([n, a]) => `${n} ${a.accountId}`)).toEqual(SHARED.map((id) => `FileNode/query ${id}`));
|
||||
expect(useFiles.getState().sharedAccounts).toEqual([{ id: "s2", name: "[email protected]" }]);
|
||||
});
|
||||
|
||||
it("are asked about address books in one request", async () => {
|
||||
await useContacts.getState().loadShared();
|
||||
expect(requests).toHaveLength(1);
|
||||
expect(requests[0]!.filter(([n]) => n === "AddressBook/get")).toHaveLength(3);
|
||||
});
|
||||
|
||||
it("are asked about calendars in one request, and listed in the session's order", async () => {
|
||||
await useCalendar.getState().loadSharedCalendars();
|
||||
expect(requests).toHaveLength(1);
|
||||
expect(useCalendar.getState().sharedCalendars.map((c) => c.accountId)).toEqual(SHARED);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user