1// @vitest-environment jsdom
2
3import { scopeThreadRef } from "@t3tools/client-runtime/environment";
4import { EnvironmentId, ThreadId } from "@t3tools/contracts";
5import { afterEach, beforeEach, expect, it, vi } from "vite-plus/test";
6import {
7 COMPOSER_DRAFT_STORAGE_KEY,
8 prepareComposerDraftsForReload,
9 useComposerDraftStore,
10} from "./composerDraftStore";
11
12const target = scopeThreadRef(EnvironmentId.make("refresh-host"), ThreadId.make("refresh-thread"));
13
14beforeEach(() => {
15 vi.useFakeTimers();
16 useComposerDraftStore.setState({
17 draftsByThreadKey: {},
18 draftThreadsByThreadKey: {},
19 logicalProjectDraftThreadKeyByLogicalProjectKey: {},
20 });
21});
22afterEach(() => {
23 vi.restoreAllMocks();
24 vi.useRealTimers();
25});
26
27it("flushes current text synchronously and confirms it survives rehydration", async () => {
28 useComposerDraftStore.getState().setPrompt(target, "latest keystroke");
29 expect(prepareComposerDraftsForReload()).toBe(true);
30 expect(localStorage.getItem(COMPOSER_DRAFT_STORAGE_KEY)).toContain("latest keystroke");
31 useComposerDraftStore.setState({ draftsByThreadKey: {} });
32 await useComposerDraftStore.persist.rehydrate();
33 expect(useComposerDraftStore.getState().getComposerDraft(target)?.prompt).toBe(
34 "latest keystroke",
35 );
36});
37
38it("defers while file bytes exist only locally, then permits their uploaded reference", () => {
39 const file = new File(["private bytes"], "note.txt", { type: "text/plain" });
40 useComposerDraftStore
41 .getState()
42 .addFiles(target, [
43 {
44 type: "file",
45 id: "note",
46 name: file.name,
47 mimeType: file.type,
48 sizeBytes: file.size,
49 file,
50 },
51 ]);
52 expect(prepareComposerDraftsForReload()).toBe(false);
53 useComposerDraftStore
54 .getState()
55 .setFileUpload(target, "note", target.environmentId, "uploaded-note");
56 expect(prepareComposerDraftsForReload()).toBe(true);
57});
58
59it("defers when storage rejects or silently drops the flushed draft", () => {
60 useComposerDraftStore.getState().setPrompt(target, "must survive");
61 const write = vi.spyOn(Storage.prototype, "setItem").mockImplementation(() => {
62 throw new DOMException("full", "QuotaExceededError");
63 });
64 expect(prepareComposerDraftsForReload()).toBe(false);
65 write.mockImplementation(() => {});
66 expect(prepareComposerDraftsForReload()).toBe(false);
67});