@startsimpli/integrations 0.1.6 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,250 @@
1
+ /**
2
+ * THE TRACKING SURFACE, rendered (bd startsim-768w.38.25).
3
+ *
4
+ * The screen makes one claim — "this is what is still owed" — and every case
5
+ * below is a way that claim could be false on screen while the data underneath
6
+ * is fine: a closed item shown as outstanding, an item with no owner rendered
7
+ * as though it had one, a filter that did nothing, a row with no traceable
8
+ * source, a run that closed something and did not say why.
9
+ */
10
+ import { render, screen, within } from '@testing-library/react';
11
+ import userEvent from '@testing-library/user-event';
12
+ import { describe, expect, it, vi } from 'vitest';
13
+
14
+ import { TrackerPage } from '../components/pages/TrackerPage';
15
+ import type {
16
+ Commitment,
17
+ CommitmentQuery,
18
+ CommitmentTrackerApi,
19
+ CorpusPage,
20
+ } from '../corpus/types';
21
+
22
+ const NOW = Date.parse('2026-08-10T12:00:00Z');
23
+ const SCOPE = { orgId: 'tandem' };
24
+
25
+ function commitment(overrides: Partial<Commitment> & { externalId: string; title: string }): Commitment {
26
+ return {
27
+ id: overrides.externalId,
28
+ dedupeKey: overrides.externalId.replace('commit:', ''),
29
+ subtype: 'action',
30
+ detail: '',
31
+ status: 'open',
32
+ subjectKey: '',
33
+ actionKey: '',
34
+ mentions: [
35
+ {
36
+ documentId: 'doc_1',
37
+ originKey: 'rules:x',
38
+ occurredAt: '2026-08-01T15:00:00Z',
39
+ quote: 'Status in the system reads "comments received", which is misleading.',
40
+ extractor: 'rules',
41
+ },
42
+ ],
43
+ firstSeenAt: '2026-08-01T15:00:00Z',
44
+ lastSeenAt: '2026-08-01T15:00:00Z',
45
+ extractorVersion: 'rules+model@1',
46
+ source: 'granola',
47
+ sourceLabel: 'Granola',
48
+ scope: SCOPE,
49
+ ...overrides,
50
+ };
51
+ }
52
+
53
+ const ROWS: Commitment[] = [
54
+ commitment({ externalId: 'commit:open1', title: 'Chase the inventor for comments on 2148', ownerName: 'Rae' }),
55
+ commitment({
56
+ externalId: 'commit:overdue1',
57
+ title: 'Send the equity sheet to Harry Holcomb',
58
+ dueAt: '2026-08-05T00:00:00Z',
59
+ }),
60
+ commitment({
61
+ externalId: 'commit:done1',
62
+ title: 'File the PCT for 2205',
63
+ status: 'done',
64
+ statusReason: '2205: filed as first PCT on June 25; already complete',
65
+ resolvedBy: 'doc_9',
66
+ resolvedAt: '2026-08-08T00:00:00Z',
67
+ lastSeenAt: '2026-08-08T00:00:00Z',
68
+ }),
69
+ ];
70
+
71
+ function makeApi(options: {
72
+ rows?: Commitment[];
73
+ appliedFilters?: string[];
74
+ onQuery?: (query: CommitmentQuery) => void;
75
+ extract?: CommitmentTrackerApi['extract'];
76
+ } = {}): CommitmentTrackerApi {
77
+ const rows = options.rows ?? ROWS;
78
+ return {
79
+ async listCommitments(query: CommitmentQuery = {}): Promise<CorpusPage<Commitment>> {
80
+ options.onQuery?.(query);
81
+ // Deliberately returns EVERYTHING, like the tenant API does today: the
82
+ // screen has to be correct against a server that ignores the filters.
83
+ return {
84
+ count: rows.length,
85
+ next: null,
86
+ previous: null,
87
+ results: rows,
88
+ appliedFilters: options.appliedFilters ?? [],
89
+ };
90
+ },
91
+ ...(options.extract ? { extract: options.extract } : {}),
92
+ };
93
+ }
94
+
95
+ describe('TrackerPage — what is outstanding', () => {
96
+ it('shows open items and hides closed ones', async () => {
97
+ render(<TrackerPage api={makeApi()} scope={SCOPE} now={NOW} />);
98
+
99
+ expect(await screen.findByText('Chase the inventor for comments on 2148')).toBeInTheDocument();
100
+ expect(screen.getByText('Send the equity sheet to Harry Holcomb')).toBeInTheDocument();
101
+ // The one thing this screen must never do: present finished work as owed.
102
+ expect(screen.queryByText('File the PCT for 2205')).not.toBeInTheDocument();
103
+ });
104
+
105
+ it('sends the status and window as SERVER parameters', async () => {
106
+ const queries: CommitmentQuery[] = [];
107
+ render(<TrackerPage api={makeApi({ onQuery: (query) => queries.push(query) })} scope={SCOPE} now={NOW} />);
108
+ await screen.findByText('Chase the inventor for comments on 2148');
109
+
110
+ expect(queries[0].status).toEqual(['open', 'blocked']);
111
+ expect(queries[0].pageSize).toBe(200);
112
+ });
113
+
114
+ it('says so when the data API does not honour the filters', async () => {
115
+ render(<TrackerPage api={makeApi()} scope={SCOPE} now={NOW} />);
116
+ // The Library's `appliedFilters` contract, owed here about status — a
117
+ // status filter that silently does nothing breaks the screen's only claim.
118
+ expect(
119
+ await screen.findByText(/does not filter by .*status/i),
120
+ ).toBeInTheDocument();
121
+ });
122
+
123
+ it('does NOT nag when the API reports it applied them', async () => {
124
+ render(
125
+ <TrackerPage
126
+ api={makeApi({ appliedFilters: ['status', 'owner', 'dueBefore', 'changedAfter'] })}
127
+ scope={SCOPE}
128
+ now={NOW}
129
+ />,
130
+ );
131
+ await screen.findByText('Chase the inventor for comments on 2148');
132
+ expect(screen.queryByText(/does not filter by/i)).not.toBeInTheDocument();
133
+ });
134
+
135
+ it('puts an overdue item above one with no due date', async () => {
136
+ render(<TrackerPage api={makeApi()} scope={SCOPE} now={NOW} />);
137
+ await screen.findByText('Chase the inventor for comments on 2148');
138
+ const titles = screen.getAllByRole('article').map((node) => within(node).getByRole('heading').textContent);
139
+ expect(titles[0]).toBe('Send the equity sheet to Harry Holcomb');
140
+ });
141
+
142
+ it('says an item is overdue, with the date', async () => {
143
+ render(<TrackerPage api={makeApi()} scope={SCOPE} now={NOW} />);
144
+ expect(await screen.findByText(/Overdue/)).toBeInTheDocument();
145
+ });
146
+
147
+ it('says how long something has been open, which is the point of the screen', async () => {
148
+ render(<TrackerPage api={makeApi()} scope={SCOPE} now={NOW} />);
149
+ // Raised 2026-08-01, read 2026-08-10 — nine calendar days, eight elapsed.
150
+ expect(await screen.findAllByText(/open for 8 days/)).not.toHaveLength(0);
151
+ });
152
+
153
+ it('states that nobody was named rather than rendering a blank', async () => {
154
+ render(<TrackerPage api={makeApi()} scope={SCOPE} now={NOW} />);
155
+ // "Nobody said who owns this" is a fact about the meeting, and it is the
156
+ // most actionable thing on the screen. A blank cell hides it.
157
+ expect(await screen.findByText('No owner named')).toBeInTheDocument();
158
+ expect(screen.getByText('Rae')).toBeInTheDocument();
159
+ });
160
+
161
+ it('renders every row with the meeting it came from and a verbatim quote', async () => {
162
+ render(<TrackerPage api={makeApi()} scope={SCOPE} now={NOW} />);
163
+ await screen.findByText('Chase the inventor for comments on 2148');
164
+ for (const article of screen.getAllByRole('article')) {
165
+ expect(within(article).getByText(/From 1 meeting/)).toBeInTheDocument();
166
+ expect(within(article).getByText(/Status in the system reads/)).toBeInTheDocument();
167
+ }
168
+ });
169
+
170
+ it('shows the closed tab with the sentence that closed it', async () => {
171
+ render(<TrackerPage api={makeApi()} scope={SCOPE} now={NOW} />);
172
+ await screen.findByText('Chase the inventor for comments on 2148');
173
+ await userEvent.click(screen.getByRole('tab', { name: 'Closed' }));
174
+
175
+ expect(await screen.findByText('File the PCT for 2205')).toBeInTheDocument();
176
+ // "Why does it say this is done" has to be answerable without opening the
177
+ // meeting, or nobody trusts a single closed row.
178
+ expect(screen.getByText(/Closed by: .*filed as first PCT/)).toBeInTheDocument();
179
+ });
180
+
181
+ it('filters by owner', async () => {
182
+ render(<TrackerPage api={makeApi()} scope={SCOPE} now={NOW} />);
183
+ await screen.findByText('Chase the inventor for comments on 2148');
184
+ await userEvent.type(screen.getByPlaceholderText('Owner'), 'Rae');
185
+
186
+ expect(screen.getByText('Chase the inventor for comments on 2148')).toBeInTheDocument();
187
+ expect(screen.queryByText('Send the equity sheet to Harry Holcomb')).not.toBeInTheDocument();
188
+ });
189
+
190
+ it('tells a fresh workspace what to do instead of showing an empty page', async () => {
191
+ render(<TrackerPage api={makeApi({ rows: [] })} scope={SCOPE} now={NOW} />);
192
+ expect(await screen.findByText(/Nothing has been pulled out of your meetings yet/)).toBeInTheDocument();
193
+ });
194
+ });
195
+
196
+ describe('TrackerPage — running the extraction', () => {
197
+ const RESULT = {
198
+ documentsProcessed: 16,
199
+ fromRules: 24,
200
+ fromModel: 11,
201
+ created: 30,
202
+ merged: 5,
203
+ resolved: 2,
204
+ needsReview: [{ commitmentId: 'commit:open1', documentId: 'doc_4', quote: '2148 came back from the inventor' }],
205
+ droppedOutOfScope: 0,
206
+ provider: { provider: 'anthropic', model: 'claude-sonnet-4-6', live: true },
207
+ };
208
+
209
+ it('reports what the run did, and what the MODEL added over the rules', async () => {
210
+ const extract = vi.fn(async () => RESULT);
211
+ render(<TrackerPage api={makeApi({ extract })} scope={SCOPE} now={NOW} />);
212
+ await screen.findByText('Chase the inventor for comments on 2148');
213
+ await userEvent.click(screen.getByRole('button', { name: 'Pull from meetings' }));
214
+
215
+ expect(extract).toHaveBeenCalledWith({ scope: SCOPE });
216
+ expect(await screen.findByText(/Read 16 meetings/)).toBeInTheDocument();
217
+ // The measurement of whether the model call is worth paying for, on screen.
218
+ expect(screen.getByText(/24 came from the meetings’ own next-step lists, 11 were read/)).toBeInTheDocument();
219
+ expect(screen.getByText(/anthropic · claude-sonnet-4-6/)).toBeInTheDocument();
220
+ });
221
+
222
+ it('surfaces weak resolution matches instead of quietly closing things', async () => {
223
+ render(<TrackerPage api={makeApi({ extract: async () => RESULT })} scope={SCOPE} now={NOW} />);
224
+ await screen.findByText('Chase the inventor for comments on 2148');
225
+ await userEvent.click(screen.getByRole('button', { name: 'Pull from meetings' }));
226
+
227
+ expect(await screen.findByText(/Nothing was closed automatically/)).toBeInTheDocument();
228
+ expect(screen.getByText(/2148 came back from the inventor/)).toBeInTheDocument();
229
+ });
230
+
231
+ it('reports a leaking data API rather than absorbing it', async () => {
232
+ render(
233
+ <TrackerPage
234
+ api={makeApi({ extract: async () => ({ ...RESULT, droppedOutOfScope: 3 }) })}
235
+ scope={SCOPE}
236
+ now={NOW}
237
+ />,
238
+ );
239
+ await screen.findByText('Chase the inventor for comments on 2148');
240
+ await userEvent.click(screen.getByRole('button', { name: 'Pull from meetings' }));
241
+
242
+ expect(await screen.findByText(/3 records from another\s+workspace were returned/)).toBeInTheDocument();
243
+ });
244
+
245
+ it('hides the control entirely on a read-only deployment', async () => {
246
+ render(<TrackerPage api={makeApi()} scope={SCOPE} now={NOW} />);
247
+ await screen.findByText('Chase the inventor for comments on 2148');
248
+ expect(screen.queryByRole('button', { name: 'Pull from meetings' })).not.toBeInTheDocument();
249
+ });
250
+ });
@@ -30,3 +30,4 @@ export type {
30
30
  // connections. Same rule as above — the page composers ship, not just the parts.
31
31
  export * from './pages/LibraryPage';
32
32
  export * from './pages/AskPage';
33
+ export * from './pages/TrackerPage';