intelliwaketssveltekitv25 1.0.96 → 1.0.98
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/dist/Functions.d.ts +49 -0
- package/dist/Functions.js +54 -0
- package/dist/ListGroupItems.svelte +6 -8
- package/dist/app.css +1 -1
- package/docs/Home.md +2 -1
- package/docs/ListGroupItems.md +484 -0
- package/docs/MasterDetailLayout.md +557 -0
- package/docs/_Sidebar.md +4 -0
- package/package.json +1 -1
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
# ListGroupItems Testing Guide
|
|
2
|
+
|
|
3
|
+
A guide for testing ListGroupItems components in downstream applications using Playwright.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
ListGroupItems automatically adds data attributes to help you locate items in tests:
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
// Select a list item by its key
|
|
11
|
+
await page.locator('[data-listgroupitem-key="myValue:MyTitle:st:bv:rt:sect"]').click()
|
|
12
|
+
|
|
13
|
+
// Select a link within a list item
|
|
14
|
+
await page.locator('[data-listgroupitem-key-a="myValue:MyTitle:st:bv:rt:sect"]').click()
|
|
15
|
+
|
|
16
|
+
// Access a badge within an item
|
|
17
|
+
await page.locator('[data-listgroupitem-key="myValue:MyTitle:st:bv:rt:sect"] .listGroupBadgeValue')
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Pro Tip:** Use the exported `ListGroupItemKeyCalc` function to generate keys that match the component:
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import { ListGroupItemKeyCalc } from 'intelliwaketssveltekitv25'
|
|
24
|
+
|
|
25
|
+
const item = { value: 'myValue', title: 'MyTitle' }
|
|
26
|
+
const key = ListGroupItemKeyCalc(item)
|
|
27
|
+
await page.locator(`[data-listgroupitem-key="${key}"]`).click()
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Core Concepts
|
|
31
|
+
|
|
32
|
+
### Data Attributes
|
|
33
|
+
|
|
34
|
+
ListGroupItems provides two data attributes for targeting elements:
|
|
35
|
+
|
|
36
|
+
| Attribute | Location | Purpose |
|
|
37
|
+
|-----------|----------|---------|
|
|
38
|
+
| `data-listgroupitem-key` | `<li>` element (class `listGroupItem`) | Identifies the entire list item container |
|
|
39
|
+
| `data-listgroupitem-key-a` | `<a>` element (when item has href) | Identifies the clickable link within the item |
|
|
40
|
+
|
|
41
|
+
### Badge Selection
|
|
42
|
+
|
|
43
|
+
Badges within list items use the `listGroupBadgeValue` class and can be located relative to their parent item:
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
// Find badge value
|
|
47
|
+
const badge = page.locator('[data-listgroupitem-key="user:123:..."] .listGroupBadgeValue')
|
|
48
|
+
await expect(badge).toHaveText('5')
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Common Testing Patterns
|
|
54
|
+
|
|
55
|
+
### Clicking List Items
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
// Click an item with a link (href)
|
|
59
|
+
await page.locator('[data-listgroupitem-key-a="settings:Settings:st:bv:rt:sect"]').click()
|
|
60
|
+
|
|
61
|
+
// Click an item with a custom click handler (no href)
|
|
62
|
+
await page.locator('[data-listgroupitem-key="action:ActionItem:st:bv:rt:sect"]').click()
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Verifying Item State
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
// Check if item is selected
|
|
69
|
+
const item = page.locator('[data-listgroupitem-key="dashboard:Dashboard:st:bv:rt:sect"]')
|
|
70
|
+
await expect(item).toHaveClass(/selected/)
|
|
71
|
+
|
|
72
|
+
// Check if item is disabled
|
|
73
|
+
await expect(item).toHaveClass(/disabled/)
|
|
74
|
+
|
|
75
|
+
// Verify badge value
|
|
76
|
+
const badge = item.locator('.listGroupBadgeValue')
|
|
77
|
+
await expect(badge).toHaveText('12')
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Testing Hierarchical Items
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
// Parent item
|
|
84
|
+
const parent = page.locator('[data-listgroupitem-key="folder:Folder:st:bv:rt:sect"]')
|
|
85
|
+
|
|
86
|
+
// Expand/collapse toggle (when subsExist is true)
|
|
87
|
+
await parent.locator('div[role="button"]').first().click()
|
|
88
|
+
|
|
89
|
+
// Child items appear in nested ListGroupItems components
|
|
90
|
+
const child = page.locator('[data-listgroupitem-key="subfolder:SubFolder:st:bv:rt:sect"]')
|
|
91
|
+
await expect(child).toBeVisible()
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Testing Sections
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
// Section headers have class 'listGroupHeader'
|
|
98
|
+
const section = page.locator('.listGroupHeader').filter({ hasText: 'My Section' })
|
|
99
|
+
await section.click() // Collapses/expands the section
|
|
100
|
+
|
|
101
|
+
// Items within collapsed sections are hidden
|
|
102
|
+
const item = page.locator('[data-listgroupitem-key="item:SectionItem:st:bv:rt:sect"]')
|
|
103
|
+
await expect(item).toBeHidden()
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Understanding Key Generation
|
|
109
|
+
|
|
110
|
+
### Automatic Key Format
|
|
111
|
+
|
|
112
|
+
When a list item doesn't have a custom `key` property, ListGroupItems generates one from available properties:
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
{value}:{title}:{sub_title}:{badgeValue}:{rightText}:{section}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**Default values when properties are missing:**
|
|
119
|
+
- `value` → `'v'`
|
|
120
|
+
- `title` → `paneName` → `'t'`
|
|
121
|
+
- `sub_title` → `'st'`
|
|
122
|
+
- `badgeValue` → `'bv'`
|
|
123
|
+
- `rightText` → `'rt'`
|
|
124
|
+
- `section` → `'sect'`
|
|
125
|
+
|
|
126
|
+
**Example:**
|
|
127
|
+
```typescript
|
|
128
|
+
{
|
|
129
|
+
value: 'user123',
|
|
130
|
+
title: 'John Doe',
|
|
131
|
+
sub_title: 'Admin',
|
|
132
|
+
badgeValue: '5',
|
|
133
|
+
rightText: 'Active',
|
|
134
|
+
section: 'Users'
|
|
135
|
+
}
|
|
136
|
+
// Generates: "user123:John Doe:Admin:5:Active:Users"
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Custom Keys
|
|
140
|
+
|
|
141
|
+
For more predictable testing, provide a custom `key` property:
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
const items: TListGroupItem[] = [
|
|
145
|
+
{
|
|
146
|
+
key: 'user-john-doe', // Custom key for testing
|
|
147
|
+
title: 'John Doe',
|
|
148
|
+
value: 'user123',
|
|
149
|
+
// ... other properties
|
|
150
|
+
}
|
|
151
|
+
]
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Then in your test:
|
|
155
|
+
```typescript
|
|
156
|
+
await page.locator('[data-listgroupitem-key="user-john-doe"]').click()
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Using ListGroupItemKeyCalc in Tests
|
|
160
|
+
|
|
161
|
+
The library exports the `ListGroupItemKeyCalc` function so your tests can generate the exact same keys as the component. This ensures consistency and prevents key mismatches:
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
import { test, expect } from '@playwright/test'
|
|
165
|
+
import { ListGroupItemKeyCalc } from 'intelliwaketssveltekitv25'
|
|
166
|
+
import type { TListGroupItem } from 'intelliwaketssveltekitv25'
|
|
167
|
+
|
|
168
|
+
test('navigate to user settings', async ({ page }) => {
|
|
169
|
+
// Define your item (this could come from your app's data)
|
|
170
|
+
const settingsItem: TListGroupItem = {
|
|
171
|
+
value: 'settings',
|
|
172
|
+
title: 'User Settings',
|
|
173
|
+
section: 'Configuration'
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Generate the key using the same function the component uses
|
|
177
|
+
const key = ListGroupItemKeyCalc(settingsItem)
|
|
178
|
+
// key = "settings:User Settings:st:bv:rt:Configuration"
|
|
179
|
+
|
|
180
|
+
// Use the key to locate and click the item
|
|
181
|
+
await page.locator(`[data-listgroupitem-key="${key}"]`).click()
|
|
182
|
+
|
|
183
|
+
// Verify navigation
|
|
184
|
+
await expect(page).toHaveURL(/.*settings/)
|
|
185
|
+
})
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
**Benefits:**
|
|
189
|
+
- **No manual key construction** - Avoid errors from typos or format mismatches
|
|
190
|
+
- **Type safety** - TypeScript ensures your item has valid properties
|
|
191
|
+
- **Consistency** - Same function used by component and tests
|
|
192
|
+
- **Easy refactoring** - If key format changes, only update one function
|
|
193
|
+
|
|
194
|
+
**Advanced Pattern - Test Fixtures:**
|
|
195
|
+
|
|
196
|
+
Create reusable test fixtures with pre-calculated keys:
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
// test-fixtures.ts
|
|
200
|
+
import { ListGroupItemKeyCalc, type TListGroupItem } from 'intelliwaketssveltekitv25'
|
|
201
|
+
|
|
202
|
+
export const testItems = {
|
|
203
|
+
dashboard: {
|
|
204
|
+
value: 'dashboard',
|
|
205
|
+
title: 'Dashboard',
|
|
206
|
+
section: 'Main'
|
|
207
|
+
},
|
|
208
|
+
settings: {
|
|
209
|
+
value: 'settings',
|
|
210
|
+
title: 'Settings',
|
|
211
|
+
section: 'Configuration'
|
|
212
|
+
}
|
|
213
|
+
} as const satisfies Record<string, TListGroupItem>
|
|
214
|
+
|
|
215
|
+
// Pre-calculate keys
|
|
216
|
+
export const testKeys = Object.fromEntries(
|
|
217
|
+
Object.entries(testItems).map(([name, item]) => [name, ListGroupItemKeyCalc(item)])
|
|
218
|
+
) as Record<keyof typeof testItems, string>
|
|
219
|
+
|
|
220
|
+
// Usage in tests:
|
|
221
|
+
// await page.locator(`[data-listgroupitem-key="${testKeys.dashboard}"]`).click()
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Advanced Testing Scenarios
|
|
227
|
+
|
|
228
|
+
### Working with Dynamic Content
|
|
229
|
+
|
|
230
|
+
When titles contain HTML or special characters:
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
// ListGroupItems converts title to string for key generation
|
|
234
|
+
// HTML tags and entities are preserved in the key
|
|
235
|
+
const item = {
|
|
236
|
+
title: 'User <strong>Admin</strong>', // HTML in title
|
|
237
|
+
value: 'admin'
|
|
238
|
+
}
|
|
239
|
+
// Generated key: "admin:User <strong>Admin</strong>:st:bv:rt:sect"
|
|
240
|
+
|
|
241
|
+
// For reliable testing, use custom keys or match on value only
|
|
242
|
+
await page.locator('[data-listgroupitem-key^="admin:"]').click()
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
**Best Practices:**
|
|
246
|
+
1. **Preferred:** Use custom `key` property for items with dynamic or HTML content
|
|
247
|
+
2. **Recommended:** Use `ListGroupItemKeyCalc` function to generate keys programmatically
|
|
248
|
+
3. **Fallback:** Use partial matching with `^=` or `*=` selectors
|
|
249
|
+
|
|
250
|
+
### Testing Icons and Images
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
// Items with icons (via faProps or icon property)
|
|
254
|
+
const item = page.locator('[data-listgroupitem-key="settings:Settings:st:bv:rt:sect"]')
|
|
255
|
+
|
|
256
|
+
// Icon is inside the item
|
|
257
|
+
const icon = item.locator('svg') // FontAwesome icons render as SVG
|
|
258
|
+
await expect(icon).toBeVisible()
|
|
259
|
+
|
|
260
|
+
// Images
|
|
261
|
+
const img = item.locator('img')
|
|
262
|
+
await expect(img).toHaveAttribute('alt', 'Settings')
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Testing Right Text and Badges
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
const item = page.locator('[data-listgroupitem-key="task:MyTask:st:bv:rt:sect"]')
|
|
269
|
+
|
|
270
|
+
// Right text appears in a div with inline-block float-right
|
|
271
|
+
const rightText = item.locator('div.inline-block.float-right')
|
|
272
|
+
await expect(rightText).toHaveText('Due Soon')
|
|
273
|
+
|
|
274
|
+
// Badges have specific styling and data-color-dark attribute
|
|
275
|
+
const badge = item.locator('.listGroupBadgeValue')
|
|
276
|
+
await expect(badge).toHaveAttribute('data-color-dark', 'primary')
|
|
277
|
+
await expect(badge).toHaveText('3')
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Testing Ellipsis and Wrap Behavior
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
// When ellipses prop is true, title attribute contains full text
|
|
284
|
+
const item = page.locator('[data-listgroupitem-key="long:Very Long Title...:st:bv:rt:sect"]')
|
|
285
|
+
const titleDiv = item.locator('div.overflow-hidden').first()
|
|
286
|
+
await expect(titleDiv).toHaveAttribute('title', 'Very Long Title That Was Truncated')
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## Component Props Affecting Testing
|
|
292
|
+
|
|
293
|
+
### Key Props
|
|
294
|
+
|
|
295
|
+
| Prop | Type | Impact on Testing |
|
|
296
|
+
|------|------|-------------------|
|
|
297
|
+
| `listItems` | `TListGroupItem[]` | Source of all items and their keys |
|
|
298
|
+
| `subsExist` | `boolean` | Adds collapse/expand controls to items with children |
|
|
299
|
+
| `useValueInHref` | `boolean` | Appends `:value` to href paths, affecting navigation |
|
|
300
|
+
| `active` | `TFindIsActive` | Filters which items are visible (`true` shows non-hidden, `false` shows hidden, `null` shows all) |
|
|
301
|
+
| `collapsedValues` | `string[]` | Controls which parent items are collapsed (children hidden) |
|
|
302
|
+
| `collapsedSections` | `string[]` | Controls which sections are collapsed (items hidden) |
|
|
303
|
+
| `parentSection` | `string \| null` | Filters section headers (section won't show if it matches parent) |
|
|
304
|
+
|
|
305
|
+
### Testing with Different Props
|
|
306
|
+
|
|
307
|
+
```typescript
|
|
308
|
+
// Test item visibility based on 'active' prop
|
|
309
|
+
// When active={true}, only items with hidden !== true are shown
|
|
310
|
+
const hiddenItem = page.locator('[data-listgroupitem-key="archived:Archived:st:bv:rt:sect"]')
|
|
311
|
+
await expect(hiddenItem).toBeHidden()
|
|
312
|
+
|
|
313
|
+
// When active={null}, all items are shown
|
|
314
|
+
await expect(hiddenItem).toBeVisible()
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
## CSS Classes for Testing
|
|
320
|
+
|
|
321
|
+
ListGroupItems uses several CSS classes that can aid in test selection:
|
|
322
|
+
|
|
323
|
+
| Class | Element | Purpose |
|
|
324
|
+
|-------|---------|---------|
|
|
325
|
+
| `listGroup` | `<ul>` | Root container |
|
|
326
|
+
| `listGroupItem` | `<li>` | Individual list item |
|
|
327
|
+
| `listGroupHeader` | `<li>` | Section header (clickable to collapse) |
|
|
328
|
+
| `listGroupBadgeValue` | `<div>` | Badge value indicator |
|
|
329
|
+
| `listEmpty` | `<li>` | Shown when list is empty |
|
|
330
|
+
| `selected` | `<li>` | Item is currently selected/active |
|
|
331
|
+
| `disabled` | `<li>` | Item is disabled |
|
|
332
|
+
| `list_group_indicator` | `<li>` | Animated selection indicator |
|
|
333
|
+
|
|
334
|
+
### Example: Testing Selection States
|
|
335
|
+
|
|
336
|
+
```typescript
|
|
337
|
+
// Wait for selection indicator to appear
|
|
338
|
+
await page.locator('.list_group_indicator').waitFor({ state: 'visible' })
|
|
339
|
+
|
|
340
|
+
// Verify correct item is selected
|
|
341
|
+
const selectedItem = page.locator('.listGroupItem.selected')
|
|
342
|
+
await expect(selectedItem).toHaveAttribute('data-listgroupitem-key', 'expected:key:st:bv:rt:sect')
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
## Troubleshooting
|
|
348
|
+
|
|
349
|
+
### Key Not Found
|
|
350
|
+
|
|
351
|
+
**Problem:** `locator('[data-listgroupitem-key="..."]')` doesn't find the element.
|
|
352
|
+
|
|
353
|
+
**Solutions:**
|
|
354
|
+
1. Check if item is filtered by `active` prop
|
|
355
|
+
2. Check if item is in a collapsed section (`collapsedSections`)
|
|
356
|
+
3. Check if parent item is collapsed (`collapsedValues`)
|
|
357
|
+
4. Verify key format matches generated key (check console/inspector)
|
|
358
|
+
5. Use partial match: `locator('[data-listgroupitem-key^="value:"]')`
|
|
359
|
+
|
|
360
|
+
### Link Not Clickable
|
|
361
|
+
|
|
362
|
+
**Problem:** `data-listgroupitem-key-a` attribute not found.
|
|
363
|
+
|
|
364
|
+
**Explanation:** This attribute only exists when:
|
|
365
|
+
- Item has `pathFromItem` (generated from `href` or `title`)
|
|
366
|
+
- Item does NOT have `linkClick` handler
|
|
367
|
+
|
|
368
|
+
**Solution:** If item has `linkClick`, use `data-listgroupitem-key` on the `<li>` instead.
|
|
369
|
+
|
|
370
|
+
### Item Hidden But Should Be Visible
|
|
371
|
+
|
|
372
|
+
**Problem:** Item exists in DOM but is not visible.
|
|
373
|
+
|
|
374
|
+
**Check:**
|
|
375
|
+
1. Is parent item collapsed? Look for `collapsed` property in parent
|
|
376
|
+
2. Is section collapsed? Check `collapsedSections` array
|
|
377
|
+
3. Is item filtered by `active` prop? Check `hidden` property on item
|
|
378
|
+
4. Is item in a nested ListGroupItems? Parent's `topValue` determines which items show
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
## Complete Example
|
|
383
|
+
|
|
384
|
+
```typescript
|
|
385
|
+
import { test, expect } from '@playwright/test'
|
|
386
|
+
import { ListGroupItemKeyCalc, type TListGroupItem } from 'intelliwaketssveltekitv25'
|
|
387
|
+
|
|
388
|
+
test('navigate and interact with list group', async ({ page }) => {
|
|
389
|
+
await page.goto('/dashboard')
|
|
390
|
+
|
|
391
|
+
// Wait for list to load
|
|
392
|
+
await page.locator('.listGroup').waitFor()
|
|
393
|
+
|
|
394
|
+
// Click a section header to expand it
|
|
395
|
+
await page.locator('.listGroupHeader').filter({ hasText: 'Settings' }).click()
|
|
396
|
+
|
|
397
|
+
// Define the item we want to interact with
|
|
398
|
+
const profileItem: TListGroupItem = {
|
|
399
|
+
value: 'profile',
|
|
400
|
+
title: 'Profile Settings',
|
|
401
|
+
section: 'sect'
|
|
402
|
+
}
|
|
403
|
+
const profileKey = ListGroupItemKeyCalc(profileItem)
|
|
404
|
+
|
|
405
|
+
// Click a list item using generated key
|
|
406
|
+
await page.locator(`[data-listgroupitem-key-a="${profileKey}"]`).click()
|
|
407
|
+
|
|
408
|
+
// Verify navigation occurred
|
|
409
|
+
await expect(page).toHaveURL(/.*profile/)
|
|
410
|
+
|
|
411
|
+
// Verify item is selected
|
|
412
|
+
const selectedItem = page.locator(`[data-listgroupitem-key="${profileKey}"]`)
|
|
413
|
+
await expect(selectedItem).toHaveClass(/selected/)
|
|
414
|
+
|
|
415
|
+
// Check badge value
|
|
416
|
+
const badge = selectedItem.locator('.listGroupBadgeValue')
|
|
417
|
+
await expect(badge).toHaveText('3')
|
|
418
|
+
|
|
419
|
+
// Expand an item with children using generated key
|
|
420
|
+
const usersItem: TListGroupItem = {
|
|
421
|
+
value: 'users',
|
|
422
|
+
title: 'Users',
|
|
423
|
+
section: 'sect'
|
|
424
|
+
}
|
|
425
|
+
const usersKey = ListGroupItemKeyCalc(usersItem)
|
|
426
|
+
const parentItem = page.locator(`[data-listgroupitem-key="${usersKey}"]`)
|
|
427
|
+
await parentItem.locator('div[role="button"]').first().click()
|
|
428
|
+
|
|
429
|
+
// Child items now visible
|
|
430
|
+
const adminUsersItem: TListGroupItem = {
|
|
431
|
+
value: 'users-admin',
|
|
432
|
+
title: 'Admin Users',
|
|
433
|
+
section: 'sect'
|
|
434
|
+
}
|
|
435
|
+
const adminUsersKey = ListGroupItemKeyCalc(adminUsersItem)
|
|
436
|
+
const childItem = page.locator(`[data-listgroupitem-key="${adminUsersKey}"]`)
|
|
437
|
+
await expect(childItem).toBeVisible()
|
|
438
|
+
})
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
---
|
|
442
|
+
|
|
443
|
+
## Reference: TListGroupItem Properties
|
|
444
|
+
|
|
445
|
+
Key properties that affect testing:
|
|
446
|
+
|
|
447
|
+
```typescript
|
|
448
|
+
type TListGroupItem = {
|
|
449
|
+
key?: string // Custom key (recommended for testing)
|
|
450
|
+
value?: string // Used in auto-generated key and for hierarchy
|
|
451
|
+
title?: string | Snippet // Primary display text, used in key
|
|
452
|
+
sub_title?: string | Snippet // Secondary text, used in key
|
|
453
|
+
section?: string // Section header, used in key
|
|
454
|
+
badgeValue?: string | number // Badge content, used in key
|
|
455
|
+
rightText?: string // Right-aligned text, used in key
|
|
456
|
+
|
|
457
|
+
href?: string // Custom navigation path
|
|
458
|
+
linkClick?: () => void // Custom click handler (overrides href)
|
|
459
|
+
|
|
460
|
+
parent_value?: string // Parent item value (for hierarchy)
|
|
461
|
+
subs?: TListGroupItem[] // Child items
|
|
462
|
+
|
|
463
|
+
selected?: boolean // Item is selected
|
|
464
|
+
disabled?: boolean // Item is disabled
|
|
465
|
+
hidden?: boolean // Item is hidden (respects 'active' prop)
|
|
466
|
+
collapsed?: boolean // Item's children are collapsed
|
|
467
|
+
|
|
468
|
+
// Visual properties
|
|
469
|
+
faProps?: IFAProps // FontAwesome icon props
|
|
470
|
+
icon?: IconDefinition // FontAwesome icon
|
|
471
|
+
imageHref?: string // Image URL
|
|
472
|
+
bigIcon?: boolean // Larger icon size
|
|
473
|
+
badgeClass?: string // Additional badge CSS classes
|
|
474
|
+
badgeColor?: string // Badge color theme
|
|
475
|
+
itemClass?: string // Additional item CSS classes
|
|
476
|
+
|
|
477
|
+
// Other
|
|
478
|
+
paneName?: string // Fallback for title in key generation
|
|
479
|
+
hover_title?: string // Tooltip text
|
|
480
|
+
noLinkReplace?: boolean // Affects DisplayHTML link processing
|
|
481
|
+
strikeThrough?: boolean // Strike-through styling
|
|
482
|
+
dataSvelteKitPreloadData?: string // SvelteKit preload behavior
|
|
483
|
+
}
|
|
484
|
+
```
|