@genspectrum/dashboard-components 1.17.0 → 1.18.0

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/util.d.ts CHANGED
@@ -248,52 +248,212 @@ declare const mutationAnnotationSchema: default_2.ZodObject<{
248
248
  name: default_2.ZodString;
249
249
  description: default_2.ZodString;
250
250
  symbol: default_2.ZodString;
251
- nucleotideMutations: default_2.ZodOptional<default_2.ZodArray<default_2.ZodString, "many">>;
252
- nucleotidePositions: default_2.ZodOptional<default_2.ZodArray<default_2.ZodString, "many">>;
253
- aminoAcidMutations: default_2.ZodOptional<default_2.ZodArray<default_2.ZodString, "many">>;
254
- aminoAcidPositions: default_2.ZodOptional<default_2.ZodArray<default_2.ZodString, "many">>;
251
+ nucleotideMutations: default_2.ZodOptional<default_2.ZodArray<default_2.ZodUnion<[default_2.ZodString, default_2.ZodObject<{
252
+ mutation: default_2.ZodString;
253
+ name: default_2.ZodOptional<default_2.ZodString>;
254
+ description: default_2.ZodOptional<default_2.ZodString>;
255
+ }, "strip", default_2.ZodTypeAny, {
256
+ mutation: string;
257
+ name?: string | undefined;
258
+ description?: string | undefined;
259
+ }, {
260
+ mutation: string;
261
+ name?: string | undefined;
262
+ description?: string | undefined;
263
+ }>]>, "many">>;
264
+ nucleotidePositions: default_2.ZodOptional<default_2.ZodArray<default_2.ZodUnion<[default_2.ZodString, default_2.ZodObject<{
265
+ position: default_2.ZodString;
266
+ name: default_2.ZodOptional<default_2.ZodString>;
267
+ description: default_2.ZodOptional<default_2.ZodString>;
268
+ }, "strip", default_2.ZodTypeAny, {
269
+ position: string;
270
+ name?: string | undefined;
271
+ description?: string | undefined;
272
+ }, {
273
+ position: string;
274
+ name?: string | undefined;
275
+ description?: string | undefined;
276
+ }>]>, "many">>;
277
+ aminoAcidMutations: default_2.ZodOptional<default_2.ZodArray<default_2.ZodUnion<[default_2.ZodString, default_2.ZodObject<{
278
+ mutation: default_2.ZodString;
279
+ name: default_2.ZodOptional<default_2.ZodString>;
280
+ description: default_2.ZodOptional<default_2.ZodString>;
281
+ }, "strip", default_2.ZodTypeAny, {
282
+ mutation: string;
283
+ name?: string | undefined;
284
+ description?: string | undefined;
285
+ }, {
286
+ mutation: string;
287
+ name?: string | undefined;
288
+ description?: string | undefined;
289
+ }>]>, "many">>;
290
+ aminoAcidPositions: default_2.ZodOptional<default_2.ZodArray<default_2.ZodUnion<[default_2.ZodString, default_2.ZodObject<{
291
+ position: default_2.ZodString;
292
+ name: default_2.ZodOptional<default_2.ZodString>;
293
+ description: default_2.ZodOptional<default_2.ZodString>;
294
+ }, "strip", default_2.ZodTypeAny, {
295
+ position: string;
296
+ name?: string | undefined;
297
+ description?: string | undefined;
298
+ }, {
299
+ position: string;
300
+ name?: string | undefined;
301
+ description?: string | undefined;
302
+ }>]>, "many">>;
255
303
  }, "strip", default_2.ZodTypeAny, {
256
304
  symbol: string;
257
305
  name: string;
258
306
  description: string;
259
- nucleotideMutations?: string[] | undefined;
260
- nucleotidePositions?: string[] | undefined;
261
- aminoAcidMutations?: string[] | undefined;
262
- aminoAcidPositions?: string[] | undefined;
307
+ nucleotideMutations?: (string | {
308
+ mutation: string;
309
+ name?: string | undefined;
310
+ description?: string | undefined;
311
+ })[] | undefined;
312
+ nucleotidePositions?: (string | {
313
+ position: string;
314
+ name?: string | undefined;
315
+ description?: string | undefined;
316
+ })[] | undefined;
317
+ aminoAcidMutations?: (string | {
318
+ mutation: string;
319
+ name?: string | undefined;
320
+ description?: string | undefined;
321
+ })[] | undefined;
322
+ aminoAcidPositions?: (string | {
323
+ position: string;
324
+ name?: string | undefined;
325
+ description?: string | undefined;
326
+ })[] | undefined;
263
327
  }, {
264
328
  symbol: string;
265
329
  name: string;
266
330
  description: string;
267
- nucleotideMutations?: string[] | undefined;
268
- nucleotidePositions?: string[] | undefined;
269
- aminoAcidMutations?: string[] | undefined;
270
- aminoAcidPositions?: string[] | undefined;
331
+ nucleotideMutations?: (string | {
332
+ mutation: string;
333
+ name?: string | undefined;
334
+ description?: string | undefined;
335
+ })[] | undefined;
336
+ nucleotidePositions?: (string | {
337
+ position: string;
338
+ name?: string | undefined;
339
+ description?: string | undefined;
340
+ })[] | undefined;
341
+ aminoAcidMutations?: (string | {
342
+ mutation: string;
343
+ name?: string | undefined;
344
+ description?: string | undefined;
345
+ })[] | undefined;
346
+ aminoAcidPositions?: (string | {
347
+ position: string;
348
+ name?: string | undefined;
349
+ description?: string | undefined;
350
+ })[] | undefined;
271
351
  }>;
272
352
 
273
353
  declare const mutationAnnotationsSchema: default_2.ZodArray<default_2.ZodObject<{
274
354
  name: default_2.ZodString;
275
355
  description: default_2.ZodString;
276
356
  symbol: default_2.ZodString;
277
- nucleotideMutations: default_2.ZodOptional<default_2.ZodArray<default_2.ZodString, "many">>;
278
- nucleotidePositions: default_2.ZodOptional<default_2.ZodArray<default_2.ZodString, "many">>;
279
- aminoAcidMutations: default_2.ZodOptional<default_2.ZodArray<default_2.ZodString, "many">>;
280
- aminoAcidPositions: default_2.ZodOptional<default_2.ZodArray<default_2.ZodString, "many">>;
357
+ nucleotideMutations: default_2.ZodOptional<default_2.ZodArray<default_2.ZodUnion<[default_2.ZodString, default_2.ZodObject<{
358
+ mutation: default_2.ZodString;
359
+ name: default_2.ZodOptional<default_2.ZodString>;
360
+ description: default_2.ZodOptional<default_2.ZodString>;
361
+ }, "strip", default_2.ZodTypeAny, {
362
+ mutation: string;
363
+ name?: string | undefined;
364
+ description?: string | undefined;
365
+ }, {
366
+ mutation: string;
367
+ name?: string | undefined;
368
+ description?: string | undefined;
369
+ }>]>, "many">>;
370
+ nucleotidePositions: default_2.ZodOptional<default_2.ZodArray<default_2.ZodUnion<[default_2.ZodString, default_2.ZodObject<{
371
+ position: default_2.ZodString;
372
+ name: default_2.ZodOptional<default_2.ZodString>;
373
+ description: default_2.ZodOptional<default_2.ZodString>;
374
+ }, "strip", default_2.ZodTypeAny, {
375
+ position: string;
376
+ name?: string | undefined;
377
+ description?: string | undefined;
378
+ }, {
379
+ position: string;
380
+ name?: string | undefined;
381
+ description?: string | undefined;
382
+ }>]>, "many">>;
383
+ aminoAcidMutations: default_2.ZodOptional<default_2.ZodArray<default_2.ZodUnion<[default_2.ZodString, default_2.ZodObject<{
384
+ mutation: default_2.ZodString;
385
+ name: default_2.ZodOptional<default_2.ZodString>;
386
+ description: default_2.ZodOptional<default_2.ZodString>;
387
+ }, "strip", default_2.ZodTypeAny, {
388
+ mutation: string;
389
+ name?: string | undefined;
390
+ description?: string | undefined;
391
+ }, {
392
+ mutation: string;
393
+ name?: string | undefined;
394
+ description?: string | undefined;
395
+ }>]>, "many">>;
396
+ aminoAcidPositions: default_2.ZodOptional<default_2.ZodArray<default_2.ZodUnion<[default_2.ZodString, default_2.ZodObject<{
397
+ position: default_2.ZodString;
398
+ name: default_2.ZodOptional<default_2.ZodString>;
399
+ description: default_2.ZodOptional<default_2.ZodString>;
400
+ }, "strip", default_2.ZodTypeAny, {
401
+ position: string;
402
+ name?: string | undefined;
403
+ description?: string | undefined;
404
+ }, {
405
+ position: string;
406
+ name?: string | undefined;
407
+ description?: string | undefined;
408
+ }>]>, "many">>;
281
409
  }, "strip", default_2.ZodTypeAny, {
282
410
  symbol: string;
283
411
  name: string;
284
412
  description: string;
285
- nucleotideMutations?: string[] | undefined;
286
- nucleotidePositions?: string[] | undefined;
287
- aminoAcidMutations?: string[] | undefined;
288
- aminoAcidPositions?: string[] | undefined;
413
+ nucleotideMutations?: (string | {
414
+ mutation: string;
415
+ name?: string | undefined;
416
+ description?: string | undefined;
417
+ })[] | undefined;
418
+ nucleotidePositions?: (string | {
419
+ position: string;
420
+ name?: string | undefined;
421
+ description?: string | undefined;
422
+ })[] | undefined;
423
+ aminoAcidMutations?: (string | {
424
+ mutation: string;
425
+ name?: string | undefined;
426
+ description?: string | undefined;
427
+ })[] | undefined;
428
+ aminoAcidPositions?: (string | {
429
+ position: string;
430
+ name?: string | undefined;
431
+ description?: string | undefined;
432
+ })[] | undefined;
289
433
  }, {
290
434
  symbol: string;
291
435
  name: string;
292
436
  description: string;
293
- nucleotideMutations?: string[] | undefined;
294
- nucleotidePositions?: string[] | undefined;
295
- aminoAcidMutations?: string[] | undefined;
296
- aminoAcidPositions?: string[] | undefined;
437
+ nucleotideMutations?: (string | {
438
+ mutation: string;
439
+ name?: string | undefined;
440
+ description?: string | undefined;
441
+ })[] | undefined;
442
+ nucleotidePositions?: (string | {
443
+ position: string;
444
+ name?: string | undefined;
445
+ description?: string | undefined;
446
+ })[] | undefined;
447
+ aminoAcidMutations?: (string | {
448
+ mutation: string;
449
+ name?: string | undefined;
450
+ description?: string | undefined;
451
+ })[] | undefined;
452
+ aminoAcidPositions?: (string | {
453
+ position: string;
454
+ name?: string | undefined;
455
+ description?: string | undefined;
456
+ })[] | undefined;
297
457
  }>, "many">;
298
458
 
299
459
  export declare type MutationComparisonProps = default_2.infer<typeof mutationComparisonPropsSchema>;
@@ -1252,7 +1412,7 @@ declare global {
1252
1412
 
1253
1413
  declare global {
1254
1414
  interface HTMLElementTagNameMap {
1255
- 'gs-statistics': StatisticsComponent;
1415
+ 'gs-sequences-by-location': SequencesByLocationComponent;
1256
1416
  }
1257
1417
  }
1258
1418
 
@@ -1260,7 +1420,7 @@ declare global {
1260
1420
  declare global {
1261
1421
  namespace React.JSX {
1262
1422
  interface IntrinsicElements {
1263
- 'gs-statistics': StatisticsComponent;
1423
+ 'gs-sequences-by-location': SequencesByLocationComponent;
1264
1424
  }
1265
1425
  }
1266
1426
  }
@@ -1268,7 +1428,7 @@ declare global {
1268
1428
 
1269
1429
  declare global {
1270
1430
  interface HTMLElementTagNameMap {
1271
- 'gs-sequences-by-location': SequencesByLocationComponent;
1431
+ 'gs-statistics': StatisticsComponent;
1272
1432
  }
1273
1433
  }
1274
1434
 
@@ -1276,7 +1436,7 @@ declare global {
1276
1436
  declare global {
1277
1437
  namespace React.JSX {
1278
1438
  interface IntrinsicElements {
1279
- 'gs-sequences-by-location': SequencesByLocationComponent;
1439
+ 'gs-statistics': StatisticsComponent;
1280
1440
  }
1281
1441
  }
1282
1442
  }
@@ -1284,7 +1444,10 @@ declare global {
1284
1444
 
1285
1445
  declare global {
1286
1446
  interface HTMLElementTagNameMap {
1287
- 'gs-wastewater-mutations-over-time': WastewaterMutationsOverTimeComponent;
1447
+ 'gs-location-filter': LocationFilterComponent;
1448
+ }
1449
+ interface HTMLElementEventMap {
1450
+ [gsEventNames.locationChanged]: LocationChangedEvent;
1288
1451
  }
1289
1452
  }
1290
1453
 
@@ -1292,7 +1455,7 @@ declare global {
1292
1455
  declare global {
1293
1456
  namespace React.JSX {
1294
1457
  interface IntrinsicElements {
1295
- 'gs-wastewater-mutations-over-time': WastewaterMutationsOverTimeComponent;
1458
+ 'gs-location-filter': LocationFilterComponent;
1296
1459
  }
1297
1460
  }
1298
1461
  }
@@ -1300,11 +1463,10 @@ declare global {
1300
1463
 
1301
1464
  declare global {
1302
1465
  interface HTMLElementTagNameMap {
1303
- 'gs-date-range-filter': DateRangeFilterComponent;
1466
+ 'gs-text-filter': TextFilterComponent;
1304
1467
  }
1305
1468
  interface HTMLElementEventMap {
1306
- [gsEventNames.dateRangeFilterChanged]: CustomEvent<Record<string, string>>;
1307
- [gsEventNames.dateRangeOptionChanged]: DateRangeOptionChangedEvent;
1469
+ [gsEventNames.textFilterChanged]: TextFilterChangedEvent;
1308
1470
  }
1309
1471
  }
1310
1472
 
@@ -1312,7 +1474,7 @@ declare global {
1312
1474
  declare global {
1313
1475
  namespace React.JSX {
1314
1476
  interface IntrinsicElements {
1315
- 'gs-date-range-filter': DateRangeFilterComponent;
1477
+ 'gs-text-filter': TextFilterComponent;
1316
1478
  }
1317
1479
  }
1318
1480
  }
@@ -1320,10 +1482,11 @@ declare global {
1320
1482
 
1321
1483
  declare global {
1322
1484
  interface HTMLElementTagNameMap {
1323
- 'gs-location-filter': LocationFilterComponent;
1485
+ 'gs-date-range-filter': DateRangeFilterComponent;
1324
1486
  }
1325
1487
  interface HTMLElementEventMap {
1326
- [gsEventNames.locationChanged]: LocationChangedEvent;
1488
+ [gsEventNames.dateRangeFilterChanged]: CustomEvent<Record<string, string>>;
1489
+ [gsEventNames.dateRangeOptionChanged]: DateRangeOptionChangedEvent;
1327
1490
  }
1328
1491
  }
1329
1492
 
@@ -1331,7 +1494,7 @@ declare global {
1331
1494
  declare global {
1332
1495
  namespace React.JSX {
1333
1496
  interface IntrinsicElements {
1334
- 'gs-location-filter': LocationFilterComponent;
1497
+ 'gs-date-range-filter': DateRangeFilterComponent;
1335
1498
  }
1336
1499
  }
1337
1500
  }
@@ -1339,10 +1502,10 @@ declare global {
1339
1502
 
1340
1503
  declare global {
1341
1504
  interface HTMLElementTagNameMap {
1342
- 'gs-text-filter': TextFilterComponent;
1505
+ 'gs-mutation-filter': MutationFilterComponent;
1343
1506
  }
1344
1507
  interface HTMLElementEventMap {
1345
- [gsEventNames.textFilterChanged]: TextFilterChangedEvent;
1508
+ [gsEventNames.mutationFilterChanged]: CustomEvent<MutationsFilter>;
1346
1509
  }
1347
1510
  }
1348
1511
 
@@ -1350,7 +1513,7 @@ declare global {
1350
1513
  declare global {
1351
1514
  namespace React.JSX {
1352
1515
  interface IntrinsicElements {
1353
- 'gs-text-filter': TextFilterComponent;
1516
+ 'gs-mutation-filter': MutationFilterComponent;
1354
1517
  }
1355
1518
  }
1356
1519
  }
@@ -1358,10 +1521,11 @@ declare global {
1358
1521
 
1359
1522
  declare global {
1360
1523
  interface HTMLElementTagNameMap {
1361
- 'gs-mutation-filter': MutationFilterComponent;
1524
+ 'gs-number-range-filter': NumberRangeFilterComponent;
1362
1525
  }
1363
1526
  interface HTMLElementEventMap {
1364
- [gsEventNames.mutationFilterChanged]: CustomEvent<MutationsFilter>;
1527
+ [gsEventNames.numberRangeFilterChanged]: NumberRangeFilterChangedEvent;
1528
+ [gsEventNames.numberRangeValueChanged]: NumberRangeValueChangedEvent;
1365
1529
  }
1366
1530
  }
1367
1531
 
@@ -1369,7 +1533,7 @@ declare global {
1369
1533
  declare global {
1370
1534
  namespace React.JSX {
1371
1535
  interface IntrinsicElements {
1372
- 'gs-mutation-filter': MutationFilterComponent;
1536
+ 'gs-number-range-filter': NumberRangeFilterComponent;
1373
1537
  }
1374
1538
  }
1375
1539
  }
@@ -1397,11 +1561,7 @@ declare global {
1397
1561
 
1398
1562
  declare global {
1399
1563
  interface HTMLElementTagNameMap {
1400
- 'gs-number-range-filter': NumberRangeFilterComponent;
1401
- }
1402
- interface HTMLElementEventMap {
1403
- [gsEventNames.numberRangeFilterChanged]: NumberRangeFilterChangedEvent;
1404
- [gsEventNames.numberRangeValueChanged]: NumberRangeValueChangedEvent;
1564
+ 'gs-wastewater-mutations-over-time': WastewaterMutationsOverTimeComponent;
1405
1565
  }
1406
1566
  }
1407
1567
 
@@ -1409,7 +1569,7 @@ declare global {
1409
1569
  declare global {
1410
1570
  namespace React.JSX {
1411
1571
  interface IntrinsicElements {
1412
- 'gs-number-range-filter': NumberRangeFilterComponent;
1572
+ 'gs-wastewater-mutations-over-time': WastewaterMutationsOverTimeComponent;
1413
1573
  }
1414
1574
  }
1415
1575
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@genspectrum/dashboard-components",
3
- "version": "1.17.0",
3
+ "version": "1.18.0",
4
4
  "description": "GenSpectrum web components for building dashboards",
5
5
  "type": "module",
6
6
  "license": "AGPL-3.0-only",
@@ -2,9 +2,17 @@ import { renderHook } from '@testing-library/preact';
2
2
  import { type FunctionalComponent } from 'preact';
3
3
  import { describe, expect, it } from 'vitest';
4
4
 
5
- import { MutationAnnotationsContextProvider, useMutationAnnotationsProvider } from './MutationAnnotationsContext';
5
+ import {
6
+ MutationAnnotationsContextProvider,
7
+ type ResolvedMutationAnnotation,
8
+ useMutationAnnotationsProvider,
9
+ } from './MutationAnnotationsContext';
6
10
  import { SubstitutionClass } from '../utils/mutations';
7
- import { type MutationAnnotations } from '../web-components/mutation-annotations-context';
11
+ import { type MutationAnnotation, type MutationAnnotations } from '../web-components/mutation-annotations-context';
12
+
13
+ function resolved(annotation: MutationAnnotation): ResolvedMutationAnnotation {
14
+ return { annotation, name: annotation.name, description: annotation.description };
15
+ }
8
16
 
9
17
  describe('useMutationAnnotation', () => {
10
18
  function renderAnnotationsHook(mockAnnotations: MutationAnnotations) {
@@ -35,13 +43,13 @@ describe('useMutationAnnotation', () => {
35
43
  it('should return the correct annotation for a given mutation', () => {
36
44
  const result = renderAnnotationsHook(mockAnnotations)(SubstitutionClass.parse('A123')!, 'nucleotide');
37
45
 
38
- expect(result).toEqual([mockAnnotations[0]]);
46
+ expect(result).toEqual([resolved(mockAnnotations[0])]);
39
47
  });
40
48
 
41
49
  it('should return the correct annotations if multiple contain a mutation', () => {
42
50
  const result = renderAnnotationsHook(mockAnnotations)(SubstitutionClass.parse('A456')!, 'nucleotide');
43
51
 
44
- expect(result).toEqual([mockAnnotations[0], mockAnnotations[1]]);
52
+ expect(result).toEqual([resolved(mockAnnotations[0]), resolved(mockAnnotations[1])]);
45
53
  });
46
54
  });
47
55
 
@@ -58,7 +66,7 @@ describe('useMutationAnnotation', () => {
58
66
  it('should return the correct mutation annotation for a given mutations', () => {
59
67
  const result = renderAnnotationsHook(mockAnnotations)(SubstitutionClass.parse('B456')!, 'amino acid');
60
68
 
61
- expect(result).toEqual([mockAnnotations[0]]);
69
+ expect(result).toEqual([resolved(mockAnnotations[0])]);
62
70
  });
63
71
  });
64
72
 
@@ -81,17 +89,17 @@ describe('useMutationAnnotation', () => {
81
89
 
82
90
  it('should return the correct mutation annotation covered by position only', () => {
83
91
  const result = renderAnnotationsHook(mockAnnotations)(SubstitutionClass.parse('A543T')!, 'nucleotide');
84
- expect(result).toEqual([mockAnnotations[0]]);
92
+ expect(result).toEqual([resolved(mockAnnotations[0])]);
85
93
  });
86
94
 
87
95
  it('should return the correct mutation annotation covered both by position and mutation', () => {
88
96
  const result = renderAnnotationsHook(mockAnnotations)(SubstitutionClass.parse('A321T')!, 'nucleotide');
89
- expect(result).toEqual([mockAnnotations[0]]);
97
+ expect(result).toEqual([resolved(mockAnnotations[0])]);
90
98
  });
91
99
 
92
100
  it('should return both annotations if one matches the mutations and the other the position', () => {
93
101
  const result = renderAnnotationsHook(mockAnnotations)(SubstitutionClass.parse('A432T')!, 'nucleotide');
94
- expect(result).toEqual([mockAnnotations[1], mockAnnotations[0]]);
102
+ expect(result).toEqual([resolved(mockAnnotations[0]), resolved(mockAnnotations[1])]);
95
103
  });
96
104
  });
97
105
 
@@ -108,12 +116,12 @@ describe('useMutationAnnotation', () => {
108
116
 
109
117
  it('should return the correct mutation annotation covered both by position and mutation', () => {
110
118
  const result = renderAnnotationsHook(mockAnnotations)(SubstitutionClass.parse('Gene:B432G')!, 'amino acid');
111
- expect(result).toEqual([mockAnnotations[0]]);
119
+ expect(result).toEqual([resolved(mockAnnotations[0])]);
112
120
  });
113
121
 
114
122
  it('should return the correct mutation annotation covered both by position only', () => {
115
123
  const result = renderAnnotationsHook(mockAnnotations)(SubstitutionClass.parse('Gene:B543G')!, 'amino acid');
116
- expect(result).toEqual([mockAnnotations[0]]);
124
+ expect(result).toEqual([resolved(mockAnnotations[0])]);
117
125
  });
118
126
 
119
127
  it('should return no mutation annotation for an amino acid position of wrong gene', () => {
@@ -124,4 +132,68 @@ describe('useMutationAnnotation', () => {
124
132
  expect(result).toBeUndefined();
125
133
  });
126
134
  });
135
+
136
+ describe('per-mutation name and description overrides', () => {
137
+ it('should use overridden name and description when both are provided on a mutation entry', () => {
138
+ const mockAnnotations: MutationAnnotations = [
139
+ {
140
+ name: 'Group name',
141
+ description: 'Group description',
142
+ symbol: 'X',
143
+ nucleotideMutations: [
144
+ { mutation: 'A123T', name: 'Override name', description: 'Override description' },
145
+ ],
146
+ },
147
+ ];
148
+ const result = renderAnnotationsHook(mockAnnotations)(SubstitutionClass.parse('A123T')!, 'nucleotide');
149
+ expect(result).toEqual([
150
+ { annotation: mockAnnotations[0], name: 'Override name', description: 'Override description' },
151
+ ]);
152
+ });
153
+
154
+ it('should fall back to group name when only description is overridden', () => {
155
+ const mockAnnotations: MutationAnnotations = [
156
+ {
157
+ name: 'Group name',
158
+ description: 'Group description',
159
+ symbol: 'X',
160
+ nucleotideMutations: [{ mutation: 'A123T', description: 'Override description' }],
161
+ },
162
+ ];
163
+ const result = renderAnnotationsHook(mockAnnotations)(SubstitutionClass.parse('A123T')!, 'nucleotide');
164
+ expect(result).toEqual([
165
+ { annotation: mockAnnotations[0], name: 'Group name', description: 'Override description' },
166
+ ]);
167
+ });
168
+
169
+ it('should fall back to group description when only name is overridden', () => {
170
+ const mockAnnotations: MutationAnnotations = [
171
+ {
172
+ name: 'Group name',
173
+ description: 'Group description',
174
+ symbol: 'X',
175
+ nucleotideMutations: [{ mutation: 'A123T', name: 'Override name' }],
176
+ },
177
+ ];
178
+ const result = renderAnnotationsHook(mockAnnotations)(SubstitutionClass.parse('A123T')!, 'nucleotide');
179
+ expect(result).toEqual([
180
+ { annotation: mockAnnotations[0], name: 'Override name', description: 'Group description' },
181
+ ]);
182
+ });
183
+
184
+ it('should use position-level override for position entries', () => {
185
+ const mockAnnotations: MutationAnnotations = [
186
+ {
187
+ name: 'Group name',
188
+ description: 'Group description',
189
+ symbol: 'X',
190
+ nucleotidePositions: [{ position: '123', name: 'Position override name' }],
191
+ },
192
+ ];
193
+ const result = renderAnnotationsHook(mockAnnotations)(SubstitutionClass.parse('A123T')!, 'nucleotide');
194
+ expect(result).toEqual([
195
+ { annotation: mockAnnotations[0], name: 'Position override name', description: 'Group description' },
196
+ ]);
197
+ });
198
+ });
127
199
  });