Skip to content
Source
Sign inSign up
Open History to see the last commit

appShortcutsRuntime.test.ts

70 lines2.7 KB

1import { describe, expect, it, vi } from "vite-plus/test";
2​
3vi.mock("expo-quick-actions", () => ({}));
4vi.mock("react-native", () => ({ Platform: { OS: "android" } }));
5vi.mock("../../persistence/imperative", () => ({}));
6vi.mock("../../state/atom-registry", () => ({}));
7vi.mock("../../state/threads", () => ({ environmentThreadShells: {} }));
8vi.mock("./appShortcuts", async () => {
9 const { withRecentThreadShortcut } =
10 await vi.importActual<typeof import("./appShortcuts")>("./appShortcuts");
11 return { withRecentThreadShortcut };
12});
13​
14import type { RecentThreadShortcut } from "../../persistence/imperative";
15import { createRecentThreadShortcuts } from "./appShortcutsRuntime";
16​
17const thread = (threadId: string, title = threadId): RecentThreadShortcut => ({
18 environmentId: "env",
19 threadId,
20 title,
21});
22​
23function setup(load: () => Promise<ReadonlyArray<RecentThreadShortcut>>) {
24 const save = vi.fn<(list: ReadonlyArray<RecentThreadShortcut>) => Promise<void>>(() =>
25 Promise.resolve(),
26 );
27 const publish = vi.fn<(list: ReadonlyArray<RecentThreadShortcut>) => Promise<void>>(() =>
28 Promise.resolve(),
29 );
30 return { save, publish, recents: createRecentThreadShortcuts({ load, save, publish }) };
32​
33describe("createRecentThreadShortcuts", () => {
34 it("waits for the persisted list before recording the open thread", async () => {
35 const { save, publish, recents } = setup(() => Promise.resolve([thread("old")]));
36 recents.recordActiveThread(thread("new"));
37 expect(publish).not.toHaveBeenCalled();
38 await recents.loaded;
39 await recents.saved();
40 expect(publish).toHaveBeenLastCalledWith([thread("new"), thread("old")]);
41 expect(save).toHaveBeenLastCalledWith([thread("new"), thread("old")]);
42 });
43​
44 it("does not persist the empty fallback after a failed load", async () => {
45 using _warn = vi.spyOn(console, "warn").mockImplementation(() => undefined);
46 const { save, publish, recents } = setup(() => Promise.reject(new Error("read failed")));
47 await recents.loaded;
48 await recents.saved();
49 expect(publish).toHaveBeenLastCalledWith([]);
50 expect(save).not.toHaveBeenCalled();
51​
52 recents.recordActiveThread(thread("a"));
53 await recents.saved();
54 expect(save).toHaveBeenLastCalledWith([thread("a")]);
55 });
56​
57 it("records title changes of the open thread and ignores repeats", async () => {
58 const { publish, recents } = setup(() => Promise.resolve([]));
59 await recents.loaded;
60 recents.recordActiveThread(thread("a", ""));
61 recents.recordActiveThread(thread("a", "Named"));
62 recents.recordActiveThread(thread("a", "Named"));
63 recents.recordActiveThread(null);
64 expect(publish.mock.calls.map(([list]) => list)).toEqual([
65 [],
66 [thread("a", "")],
67 [thread("a", "Named")],
68 ]);
69 });
70});