Skip to content

Commit 7933d13

Browse files
committed
Test draft state
1 parent 2b9fb6a commit 7933d13

1 file changed

Lines changed: 134 additions & 0 deletions

File tree

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
import {applyConciergeDraftEvent} from '@pages/inbox/conciergeDraftState';
2+
import CONST from '@src/CONST';
3+
4+
const REPORT_ID = '123';
5+
const REPORT_ACTION_ID = '456';
6+
const CREATED = '2026-04-03 10:00:00.000';
7+
const STREAM_SESSION_ID = 'stream-session-1';
8+
9+
function createDraftEvent(overrides?: Partial<Parameters<typeof applyConciergeDraftEvent>[1]>) {
10+
return {
11+
reportID: REPORT_ID,
12+
reportActionID: REPORT_ACTION_ID,
13+
streamSessionID: STREAM_SESSION_ID,
14+
sequence: 1,
15+
status: 'started' as const,
16+
created: CREATED,
17+
bodyMarkdown: 'Hello, **world**!',
18+
...overrides,
19+
};
20+
}
21+
22+
function getFirstMessageHTML(draft: ReturnType<typeof applyConciergeDraftEvent>) {
23+
const message = draft?.reportAction.message;
24+
25+
if (!Array.isArray(message)) {
26+
return undefined;
27+
}
28+
29+
return message.at(0)?.html;
30+
}
31+
32+
function getFirstMessageText(draft: ReturnType<typeof applyConciergeDraftEvent>) {
33+
const message = draft?.reportAction.message;
34+
35+
if (!Array.isArray(message)) {
36+
return undefined;
37+
}
38+
39+
return message.at(0)?.text;
40+
}
41+
42+
describe('conciergeDraftState', () => {
43+
it('should create a synthetic Concierge draft action from the first streamed snapshot', () => {
44+
const draft = applyConciergeDraftEvent(null, createDraftEvent(), REPORT_ID);
45+
46+
expect(draft?.reportAction.reportActionID).toBe(REPORT_ACTION_ID);
47+
expect(draft?.reportAction.actorAccountID).toBe(CONST.ACCOUNT_ID.CONCIERGE);
48+
expect(draft?.reportAction.created).toBe(CREATED);
49+
expect(getFirstMessageHTML(draft)).toContain('<strong>world</strong>');
50+
expect(getFirstMessageText(draft)).toBe('Hello, *world*!');
51+
});
52+
53+
it('should update the same draft session when a newer sequence arrives', () => {
54+
const initialDraft = applyConciergeDraftEvent(null, createDraftEvent(), REPORT_ID);
55+
const updatedDraft = applyConciergeDraftEvent(
56+
initialDraft,
57+
createDraftEvent({
58+
sequence: 2,
59+
status: 'updated',
60+
bodyMarkdown: 'Hello, **streaming** world!',
61+
}),
62+
REPORT_ID,
63+
);
64+
65+
expect(updatedDraft?.sequence).toBe(2);
66+
expect(getFirstMessageHTML(updatedDraft)).toContain('<strong>streaming</strong>');
67+
});
68+
69+
it('should ignore stale events from the same stream session', () => {
70+
const initialDraft = applyConciergeDraftEvent(null, createDraftEvent({sequence: 3}), REPORT_ID);
71+
const staleDraft = applyConciergeDraftEvent(
72+
initialDraft,
73+
createDraftEvent({
74+
sequence: 2,
75+
status: 'updated',
76+
bodyMarkdown: 'This should be ignored',
77+
}),
78+
REPORT_ID,
79+
);
80+
81+
expect(staleDraft).toBe(initialDraft);
82+
expect(getFirstMessageText(staleDraft)).toBe('Hello, *world*!');
83+
});
84+
85+
it('should keep the draft visible through completion and prefer finalRenderedHTML when provided', () => {
86+
const initialDraft = applyConciergeDraftEvent(null, createDraftEvent(), REPORT_ID);
87+
const completedDraft = applyConciergeDraftEvent(
88+
initialDraft,
89+
createDraftEvent({
90+
sequence: 2,
91+
status: 'completed',
92+
finalRenderedHTML: '<comment><strong>Server rendered</strong></comment>',
93+
bodyMarkdown: undefined,
94+
}),
95+
REPORT_ID,
96+
);
97+
98+
expect(completedDraft?.status).toBe('completed');
99+
expect(getFirstMessageHTML(completedDraft)).toBe('<comment><strong>Server rendered</strong></comment>');
100+
expect(getFirstMessageText(completedDraft)).toBe('Server rendered');
101+
});
102+
103+
it('should clear the active draft when the same stream session fails', () => {
104+
const initialDraft = applyConciergeDraftEvent(null, createDraftEvent(), REPORT_ID);
105+
const failedDraft = applyConciergeDraftEvent(
106+
initialDraft,
107+
createDraftEvent({
108+
sequence: 2,
109+
status: 'failed',
110+
terminalReason: 'lostLease',
111+
bodyMarkdown: undefined,
112+
}),
113+
REPORT_ID,
114+
);
115+
116+
expect(failedDraft).toBeNull();
117+
});
118+
119+
it('should ignore events for a different report', () => {
120+
const initialDraft = applyConciergeDraftEvent(null, createDraftEvent(), REPORT_ID);
121+
const otherReportDraft = applyConciergeDraftEvent(
122+
initialDraft,
123+
createDraftEvent({
124+
reportID: '999',
125+
sequence: 2,
126+
status: 'updated',
127+
bodyMarkdown: 'Different report',
128+
}),
129+
REPORT_ID,
130+
);
131+
132+
expect(otherReportDraft).toBe(initialDraft);
133+
});
134+
});

0 commit comments

Comments
 (0)