@startsimpli/ui 0.4.7 → 0.4.8
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.
- package/package.json +1 -1
- package/src/__mocks__/next/link.js +11 -0
- package/src/components/account/__tests__/account.test.tsx +315 -0
- package/src/components/command-palette/CommandGroup.tsx +23 -0
- package/src/components/command-palette/CommandPalette.tsx +183 -200
- package/src/components/command-palette/CommandResultItem.tsx +59 -0
- package/src/components/command-palette/__tests__/CommandGroup.test.tsx +81 -0
- package/src/components/command-palette/__tests__/CommandResultItem.test.tsx +166 -0
- package/src/components/command-palette/__tests__/command-palette-context.test.tsx +166 -0
- package/src/components/command-palette/__tests__/useCommandPaletteSearch.test.ts +271 -0
- package/src/components/command-palette/index.ts +6 -0
- package/src/components/command-palette/useCommandPaletteSearch.ts +114 -0
- package/src/components/compose/__tests__/compose.test.tsx +656 -0
- package/src/components/dashboard/PipelineFunnel.tsx +126 -0
- package/src/components/dashboard/TopCampaigns.tsx +132 -0
- package/src/components/dashboard/__tests__/dashboard.test.tsx +785 -0
- package/src/components/dashboard/index.ts +6 -0
- package/src/components/dialog/ConfirmDialog.tsx +72 -0
- package/src/components/dialog/__tests__/ConfirmDialog.test.tsx +126 -0
- package/src/components/dialog/index.ts +3 -0
- package/src/components/email-dialogs/__tests__/email-dialogs.test.tsx +982 -0
- package/src/components/email-editor/BlockRenderer.tsx +120 -0
- package/src/components/email-editor/__tests__/BlockRenderer.test.tsx +332 -0
- package/src/components/email-editor/__tests__/block-renderers.test.ts +624 -0
- package/src/components/email-editor/__tests__/email-html-renderer.test.ts +376 -0
- package/src/components/email-editor/blocks/__tests__/blocks.test.tsx +818 -0
- package/src/components/email-editor/editor-sidebar.tsx +6 -731
- package/src/components/email-editor/email-editor.tsx +78 -467
- package/src/components/email-editor/hooks/__tests__/useDragDrop.test.ts +355 -0
- package/src/components/email-editor/hooks/__tests__/useEmailEditorState.test.ts +551 -0
- package/src/components/email-editor/hooks/useDragDrop.ts +181 -0
- package/src/components/email-editor/hooks/useEmailEditorState.ts +426 -0
- package/src/components/email-editor/index.ts +1 -0
- package/src/components/email-editor/panels/BlockPropertyPanel.tsx +637 -0
- package/src/components/email-editor/panels/GlobalStylesPanel.tsx +108 -0
- package/src/components/email-editor/panels/SectionSettingsPanel.tsx +80 -0
- package/src/components/email-editor/panels/__tests__/BlockPropertyPanel.test.tsx +707 -0
- package/src/components/email-editor/panels/__tests__/GlobalStylesPanel.test.tsx +226 -0
- package/src/components/email-editor/panels/index.ts +3 -0
- package/src/components/enrichment/__tests__/enrichment.test.tsx +184 -0
- package/src/components/gantt/GanttBoardView.tsx +71 -0
- package/src/components/gantt/GanttChart.tsx +134 -881
- package/src/components/gantt/GanttFilterBar.tsx +100 -0
- package/src/components/gantt/GanttListView.tsx +63 -0
- package/src/components/gantt/GanttTimelineView.tsx +215 -0
- package/src/components/gantt/__tests__/GanttBoardView.test.tsx +305 -0
- package/src/components/gantt/__tests__/GanttFilterBar.test.tsx +544 -0
- package/src/components/gantt/__tests__/GanttListView.test.tsx +337 -0
- package/src/components/gantt/__tests__/GanttTimelineView.test.tsx +375 -0
- package/src/components/gantt/__tests__/gantt-utils.test.ts +341 -0
- package/src/components/gantt/__tests__/useGanttState.test.ts +535 -0
- package/src/components/gantt/hooks/useGanttState.ts +644 -0
- package/src/components/gantt/index.ts +10 -0
- package/src/components/integrations/__tests__/integrations.test.tsx +191 -0
- package/src/components/kanban/__tests__/kanban.test.tsx +157 -0
- package/src/components/lists/__tests__/lists.test.tsx +263 -0
- package/src/components/loading/__tests__/loading.test.tsx +114 -0
- package/src/components/navigation/__tests__/navigation.test.tsx +194 -0
- package/src/components/pipeline/__tests__/pipeline.test.tsx +169 -0
- package/src/components/settings/__tests__/settings.test.tsx +181 -0
- package/src/components/wizard/__tests__/wizard.test.tsx +97 -0
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
import { render, screen, fireEvent } from '@testing-library/react'
|
|
2
|
+
import { GanttListView } from '../GanttListView'
|
|
3
|
+
import type { GanttListViewProps } from '../GanttListView'
|
|
4
|
+
import type { GanttTask, TimelineItem } from '../types'
|
|
5
|
+
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
// Helpers
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
|
|
10
|
+
function makeItem(overrides: Partial<TimelineItem> & { id: string; title: string; status: string }): TimelineItem {
|
|
11
|
+
return { startDate: '2025-01-01', endDate: '2025-03-31', ...overrides }
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function makeTask(item: TimelineItem, overrides: Partial<GanttTask> = {}): GanttTask {
|
|
15
|
+
return {
|
|
16
|
+
item,
|
|
17
|
+
start: new Date('2025-01-01'),
|
|
18
|
+
end: new Date('2025-03-31'),
|
|
19
|
+
progress: 50,
|
|
20
|
+
timeProgress: 30,
|
|
21
|
+
depth: 0,
|
|
22
|
+
hasChildren: false,
|
|
23
|
+
parentId: null,
|
|
24
|
+
healthStatus: 'on_track',
|
|
25
|
+
...overrides,
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const CATEGORY_COLORS: Record<string, string> = {
|
|
30
|
+
product: '#3b82f6',
|
|
31
|
+
team: '#a855f7',
|
|
32
|
+
other: '#6b7280',
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function defaultProps(overrides: Partial<GanttListViewProps> = {}): GanttListViewProps {
|
|
36
|
+
return {
|
|
37
|
+
listItems: [],
|
|
38
|
+
focusedRowIndex: -1,
|
|
39
|
+
categoryColors: CATEGORY_COLORS,
|
|
40
|
+
handleItemClick: jest.fn(),
|
|
41
|
+
...overrides,
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
// Header rendering
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
|
|
49
|
+
describe('GanttListView — header', () => {
|
|
50
|
+
it('renders the Title column header', () => {
|
|
51
|
+
render(<GanttListView {...defaultProps()} />)
|
|
52
|
+
expect(screen.getByText('Title')).toBeInTheDocument()
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
it('renders the Status column header', () => {
|
|
56
|
+
render(<GanttListView {...defaultProps()} />)
|
|
57
|
+
expect(screen.getByText('Status')).toBeInTheDocument()
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('renders the Category column header', () => {
|
|
61
|
+
render(<GanttListView {...defaultProps()} />)
|
|
62
|
+
expect(screen.getByText('Category')).toBeInTheDocument()
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
it('renders the Dates column header', () => {
|
|
66
|
+
render(<GanttListView {...defaultProps()} />)
|
|
67
|
+
expect(screen.getByText('Dates')).toBeInTheDocument()
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
it('renders the Progress column header', () => {
|
|
71
|
+
render(<GanttListView {...defaultProps()} />)
|
|
72
|
+
expect(screen.getByText('Progress')).toBeInTheDocument()
|
|
73
|
+
})
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
// Empty state
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
|
|
80
|
+
describe('GanttListView — empty state', () => {
|
|
81
|
+
it('renders only the header row when listItems is empty', () => {
|
|
82
|
+
const { container } = render(<GanttListView {...defaultProps()} />)
|
|
83
|
+
expect(container.querySelectorAll('.gantt-list-row')).toHaveLength(0)
|
|
84
|
+
})
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
// ---------------------------------------------------------------------------
|
|
88
|
+
// Row rendering
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
90
|
+
|
|
91
|
+
describe('GanttListView — row rendering', () => {
|
|
92
|
+
it('renders a row for each task', () => {
|
|
93
|
+
const listItems = [
|
|
94
|
+
makeTask(makeItem({ id: 'a', title: 'Alpha', status: 'in_progress' })),
|
|
95
|
+
makeTask(makeItem({ id: 'b', title: 'Beta', status: 'completed' })),
|
|
96
|
+
makeTask(makeItem({ id: 'c', title: 'Gamma', status: 'not_started' })),
|
|
97
|
+
]
|
|
98
|
+
const { container } = render(<GanttListView {...defaultProps({ listItems })} />)
|
|
99
|
+
expect(container.querySelectorAll('.gantt-list-row')).toHaveLength(3)
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
it('renders each task title in the list', () => {
|
|
103
|
+
const listItems = [
|
|
104
|
+
makeTask(makeItem({ id: 'a', title: 'Alpha Task', status: 'in_progress' })),
|
|
105
|
+
makeTask(makeItem({ id: 'b', title: 'Beta Task', status: 'completed' })),
|
|
106
|
+
]
|
|
107
|
+
render(<GanttListView {...defaultProps({ listItems })} />)
|
|
108
|
+
expect(screen.getByText('Alpha Task')).toBeInTheDocument()
|
|
109
|
+
expect(screen.getByText('Beta Task')).toBeInTheDocument()
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
it('renders a status badge with the task status (underscores replaced with spaces)', () => {
|
|
113
|
+
const listItems = [
|
|
114
|
+
makeTask(makeItem({ id: 'a', title: 'Task A', status: 'in_progress' })),
|
|
115
|
+
makeTask(makeItem({ id: 'b', title: 'Task B', status: 'not_started' })),
|
|
116
|
+
]
|
|
117
|
+
render(<GanttListView {...defaultProps({ listItems })} />)
|
|
118
|
+
expect(screen.getByText('in progress')).toBeInTheDocument()
|
|
119
|
+
expect(screen.getByText('not started')).toBeInTheDocument()
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
it('renders a category badge when the task item has a category', () => {
|
|
123
|
+
const listItems = [
|
|
124
|
+
makeTask(makeItem({ id: 'a', title: 'Task A', status: 'in_progress', category: 'product' })),
|
|
125
|
+
]
|
|
126
|
+
render(<GanttListView {...defaultProps({ listItems })} />)
|
|
127
|
+
expect(screen.getByText('product')).toBeInTheDocument()
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
it('does not render a category badge when item has no category', () => {
|
|
131
|
+
const listItems = [
|
|
132
|
+
makeTask(makeItem({ id: 'a', title: 'Task A', status: 'in_progress' })),
|
|
133
|
+
]
|
|
134
|
+
const { container } = render(<GanttListView {...defaultProps({ listItems })} />)
|
|
135
|
+
expect(container.querySelector('.gantt-category-badge')).not.toBeInTheDocument()
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
it('renders a progress percentage text', () => {
|
|
139
|
+
const listItems = [
|
|
140
|
+
makeTask(makeItem({ id: 'a', title: 'Task A', status: 'in_progress' }), { progress: 75 }),
|
|
141
|
+
]
|
|
142
|
+
render(<GanttListView {...defaultProps({ listItems })} />)
|
|
143
|
+
expect(screen.getByText('75%')).toBeInTheDocument()
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
it('renders 0% progress correctly', () => {
|
|
147
|
+
const listItems = [
|
|
148
|
+
makeTask(makeItem({ id: 'a', title: 'Task A', status: 'not_started' }), { progress: 0 }),
|
|
149
|
+
]
|
|
150
|
+
render(<GanttListView {...defaultProps({ listItems })} />)
|
|
151
|
+
expect(screen.getByText('0%')).toBeInTheDocument()
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
it('renders 100% progress correctly', () => {
|
|
155
|
+
const listItems = [
|
|
156
|
+
makeTask(makeItem({ id: 'a', title: 'Task A', status: 'completed' }), { progress: 100 }),
|
|
157
|
+
]
|
|
158
|
+
render(<GanttListView {...defaultProps({ listItems })} />)
|
|
159
|
+
expect(screen.getByText('100%')).toBeInTheDocument()
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
it('renders formatted date range in the Dates column', () => {
|
|
163
|
+
const listItems = [
|
|
164
|
+
makeTask(makeItem({ id: 'a', title: 'Task A', status: 'in_progress' }), {
|
|
165
|
+
// Use local-time constructor to avoid UTC→local timezone offset shifting the day
|
|
166
|
+
start: new Date(2025, 0, 15), // Jan 15 2025 local
|
|
167
|
+
end: new Date(2025, 3, 20), // Apr 20 2025 local
|
|
168
|
+
}),
|
|
169
|
+
]
|
|
170
|
+
const { container } = render(<GanttListView {...defaultProps({ listItems })} />)
|
|
171
|
+
// The dates cell contains the full range as its textContent
|
|
172
|
+
const datesCell = container.querySelector('.gantt-list-col-dates:not(.gantt-list-header span)')
|
|
173
|
+
// Find the data row's dates cell (second .gantt-list-col-dates element)
|
|
174
|
+
const datesCells = container.querySelectorAll('.gantt-list-col-dates')
|
|
175
|
+
// datesCells[0] is the header "Dates", datesCells[1] is the data row cell
|
|
176
|
+
const dataCell = datesCells[1] as HTMLElement
|
|
177
|
+
expect(dataCell.textContent).toMatch(/Jan 15/)
|
|
178
|
+
expect(dataCell.textContent).toMatch(/Apr 20/)
|
|
179
|
+
})
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
// ---------------------------------------------------------------------------
|
|
183
|
+
// Focus state
|
|
184
|
+
// ---------------------------------------------------------------------------
|
|
185
|
+
|
|
186
|
+
describe('GanttListView — focus state', () => {
|
|
187
|
+
it('applies gantt-row-focused class to the focused row index', () => {
|
|
188
|
+
const listItems = [
|
|
189
|
+
makeTask(makeItem({ id: 'a', title: 'Alpha', status: 'not_started' })),
|
|
190
|
+
makeTask(makeItem({ id: 'b', title: 'Beta', status: 'in_progress' })),
|
|
191
|
+
]
|
|
192
|
+
const { container } = render(
|
|
193
|
+
<GanttListView {...defaultProps({ listItems, focusedRowIndex: 1 })} />
|
|
194
|
+
)
|
|
195
|
+
const rows = container.querySelectorAll('.gantt-list-row')
|
|
196
|
+
expect(rows[0]).not.toHaveClass('gantt-row-focused')
|
|
197
|
+
expect(rows[1]).toHaveClass('gantt-row-focused')
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
it('does not apply gantt-row-focused when focusedRowIndex is -1', () => {
|
|
201
|
+
const listItems = [
|
|
202
|
+
makeTask(makeItem({ id: 'a', title: 'Alpha', status: 'not_started' })),
|
|
203
|
+
]
|
|
204
|
+
const { container } = render(
|
|
205
|
+
<GanttListView {...defaultProps({ listItems, focusedRowIndex: -1 })} />
|
|
206
|
+
)
|
|
207
|
+
expect(container.querySelector('.gantt-row-focused')).not.toBeInTheDocument()
|
|
208
|
+
})
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
// ---------------------------------------------------------------------------
|
|
212
|
+
// Item click
|
|
213
|
+
// ---------------------------------------------------------------------------
|
|
214
|
+
|
|
215
|
+
describe('GanttListView — item click', () => {
|
|
216
|
+
it('calls handleItemClick when a row is clicked', () => {
|
|
217
|
+
const handleItemClick = jest.fn()
|
|
218
|
+
const item = makeItem({ id: 'a', title: 'Clickable Task', status: 'in_progress' })
|
|
219
|
+
const listItems = [makeTask(item)]
|
|
220
|
+
render(<GanttListView {...defaultProps({ listItems, handleItemClick })} />)
|
|
221
|
+
fireEvent.click(screen.getByText('Clickable Task'))
|
|
222
|
+
expect(handleItemClick).toHaveBeenCalledWith(item)
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
it('calls handleItemClick with the correct item when multiple rows exist', () => {
|
|
226
|
+
const handleItemClick = jest.fn()
|
|
227
|
+
const itemA = makeItem({ id: 'a', title: 'Task A', status: 'in_progress' })
|
|
228
|
+
const itemB = makeItem({ id: 'b', title: 'Task B', status: 'completed' })
|
|
229
|
+
const listItems = [makeTask(itemA), makeTask(itemB)]
|
|
230
|
+
render(<GanttListView {...defaultProps({ listItems, handleItemClick })} />)
|
|
231
|
+
fireEvent.click(screen.getByText('Task B'))
|
|
232
|
+
expect(handleItemClick).toHaveBeenCalledWith(itemB)
|
|
233
|
+
expect(handleItemClick).toHaveBeenCalledTimes(1)
|
|
234
|
+
})
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
// ---------------------------------------------------------------------------
|
|
238
|
+
// Depth indentation
|
|
239
|
+
// ---------------------------------------------------------------------------
|
|
240
|
+
|
|
241
|
+
describe('GanttListView — depth indentation', () => {
|
|
242
|
+
it('renders an indent spacer for child tasks (depth > 0)', () => {
|
|
243
|
+
const listItems = [
|
|
244
|
+
makeTask(makeItem({ id: 'child', title: 'Child Task', status: 'in_progress' }), { depth: 1 }),
|
|
245
|
+
]
|
|
246
|
+
const { container } = render(<GanttListView {...defaultProps({ listItems })} />)
|
|
247
|
+
// The indent span has inline style with a calculated width
|
|
248
|
+
const row = container.querySelector('.gantt-list-row')
|
|
249
|
+
const indentSpan = row?.querySelector('span[style]')
|
|
250
|
+
expect(indentSpan).toBeInTheDocument()
|
|
251
|
+
})
|
|
252
|
+
|
|
253
|
+
it('does not render an indent spacer for root tasks (depth 0)', () => {
|
|
254
|
+
const listItems = [
|
|
255
|
+
makeTask(makeItem({ id: 'root', title: 'Root Task', status: 'in_progress' }), { depth: 0 }),
|
|
256
|
+
]
|
|
257
|
+
const { container } = render(<GanttListView {...defaultProps({ listItems })} />)
|
|
258
|
+
const row = container.querySelector('.gantt-list-row')
|
|
259
|
+
// At depth 0, no inline-block span is injected
|
|
260
|
+
const titleCell = row?.querySelector('.gantt-list-col-title')
|
|
261
|
+
// Check that no child span with display:inline-block exists
|
|
262
|
+
const indentSpans = titleCell?.querySelectorAll('span[style]') ?? []
|
|
263
|
+
expect(indentSpans).toHaveLength(0)
|
|
264
|
+
})
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
// ---------------------------------------------------------------------------
|
|
268
|
+
// Progress bar color
|
|
269
|
+
// ---------------------------------------------------------------------------
|
|
270
|
+
|
|
271
|
+
describe('GanttListView — progress bar', () => {
|
|
272
|
+
it('renders the progress fill bar', () => {
|
|
273
|
+
const listItems = [
|
|
274
|
+
makeTask(makeItem({ id: 'a', title: 'Task A', status: 'in_progress' }), { progress: 60 }),
|
|
275
|
+
]
|
|
276
|
+
const { container } = render(<GanttListView {...defaultProps({ listItems })} />)
|
|
277
|
+
const fill = container.querySelector('.gantt-list-progress-fill') as HTMLElement | null
|
|
278
|
+
expect(fill).toBeInTheDocument()
|
|
279
|
+
expect(fill?.style.width).toBe('60%')
|
|
280
|
+
})
|
|
281
|
+
|
|
282
|
+
it('uses the on_track health color for the progress fill when healthStatus is on_track', () => {
|
|
283
|
+
const listItems = [
|
|
284
|
+
makeTask(makeItem({ id: 'a', title: 'Task A', status: 'in_progress' }), {
|
|
285
|
+
progress: 50,
|
|
286
|
+
healthStatus: 'on_track',
|
|
287
|
+
}),
|
|
288
|
+
]
|
|
289
|
+
const { container } = render(<GanttListView {...defaultProps({ listItems })} />)
|
|
290
|
+
const fill = container.querySelector('.gantt-list-progress-fill') as HTMLElement | null
|
|
291
|
+
// on_track color is #22c55e
|
|
292
|
+
expect(fill?.style.backgroundColor).toBe('rgb(34, 197, 94)')
|
|
293
|
+
})
|
|
294
|
+
|
|
295
|
+
it('uses the at_risk health color when healthStatus is at_risk', () => {
|
|
296
|
+
const listItems = [
|
|
297
|
+
makeTask(makeItem({ id: 'a', title: 'Task A', status: 'in_progress' }), {
|
|
298
|
+
progress: 20,
|
|
299
|
+
healthStatus: 'at_risk',
|
|
300
|
+
}),
|
|
301
|
+
]
|
|
302
|
+
const { container } = render(<GanttListView {...defaultProps({ listItems })} />)
|
|
303
|
+
const fill = container.querySelector('.gantt-list-progress-fill') as HTMLElement | null
|
|
304
|
+
// at_risk color is #eab308
|
|
305
|
+
expect(fill?.style.backgroundColor).toBe('rgb(234, 179, 8)')
|
|
306
|
+
})
|
|
307
|
+
|
|
308
|
+
it('uses the blocked health color when healthStatus is blocked', () => {
|
|
309
|
+
const listItems = [
|
|
310
|
+
makeTask(makeItem({ id: 'a', title: 'Task A', status: 'blocked' }), {
|
|
311
|
+
progress: 10,
|
|
312
|
+
healthStatus: 'blocked',
|
|
313
|
+
}),
|
|
314
|
+
]
|
|
315
|
+
const { container } = render(<GanttListView {...defaultProps({ listItems })} />)
|
|
316
|
+
const fill = container.querySelector('.gantt-list-progress-fill') as HTMLElement | null
|
|
317
|
+
// blocked color is #ef4444
|
|
318
|
+
expect(fill?.style.backgroundColor).toBe('rgb(239, 68, 68)')
|
|
319
|
+
})
|
|
320
|
+
})
|
|
321
|
+
|
|
322
|
+
// ---------------------------------------------------------------------------
|
|
323
|
+
// Category color fallback
|
|
324
|
+
// ---------------------------------------------------------------------------
|
|
325
|
+
|
|
326
|
+
describe('GanttListView — category color fallback', () => {
|
|
327
|
+
it('uses the other fallback color for unknown categories', () => {
|
|
328
|
+
const listItems = [
|
|
329
|
+
makeTask(makeItem({ id: 'a', title: 'Task A', status: 'in_progress', category: 'unknown_cat' })),
|
|
330
|
+
]
|
|
331
|
+
const { container } = render(<GanttListView {...defaultProps({ listItems })} />)
|
|
332
|
+
const badge = container.querySelector('.gantt-category-badge') as HTMLElement | null
|
|
333
|
+
expect(badge).toBeInTheDocument()
|
|
334
|
+
// '#6b7280' in rgb
|
|
335
|
+
expect(badge?.style.backgroundColor).toBe('rgb(107, 114, 128)')
|
|
336
|
+
})
|
|
337
|
+
})
|