1import { describe, expect, it } from "vite-plus/test";
2
3import { pendingDraftWork } from "./pendingDraftWork";
4
5describe("PendingDraftWork", () => {
6 it("holds a draft until every transfer it started has finished", async () => {
7 const pending = pendingDraftWork;
8 const key = "concurrent-transfers";
9 // Two pasted attachments downloading at once, the second slower than the first.
10 const defer = () => {
11 let resolve!: () => void;
12 const promise = new Promise<void>((settle) => {
13 resolve = settle;
14 });
15 return { promise, resolve };
16 };
17 const fast = defer();
18 const slow = defer();
19 const transfer = async (done: Promise<void>) => {
20 pending.begin(key);
21 try {
22 await done;
23 } finally {
24 pending.end(key);
25 }
26 };
27 const both = Promise.all([transfer(fast.promise), transfer(slow.promise)]);
28
29 expect(pending.has(key)).toBe(true);
30 fast.resolve();
31 await fast.promise;
32 // The first finishing must not release the draft while the second is still downloading.
33 expect(pending.has(key)).toBe(true);
34 slow.resolve();
35 await both;
36 expect(pending.has(key)).toBe(false);
37 });
38
39 it("keeps one draft's work from blocking another", () => {
40 const pending = pendingDraftWork;
41 pending.begin("isolated-a");
42 expect(pending.has("isolated-b")).toBe(false);
43 pending.end("isolated-a");
44 expect(pending.has("isolated-a")).toBe(false);
45 });
46
47 it("keeps a claim on the draft across a remount of the composer", async () => {
48 // The composer unmounting mid-download must not release the draft: the transfer is still
49 // running, and a fresh per-instance counter would read empty and let the draft send.
50 const { pendingDraftWork: first } = await import("./pendingDraftWork");
51 first.begin("remounted");
52 const { pendingDraftWork: second } = await import("./pendingDraftWork");
53 expect(second.has("remounted")).toBe(true);
54 second.end("remounted");
55 expect(first.has("remounted")).toBe(false);
56 });
57
58 it("does not go negative when a transfer ends twice", () => {
59 const pending = pendingDraftWork;
60 pending.begin("double-end");
61 pending.end("double-end");
62 pending.end("double-end");
63 pending.begin("double-end");
64 // A stray extra `end` must not leave the counter below zero, or this begin would read false.
65 expect(pending.has("double-end")).toBe(true);
66 });
67});