fhir-react 0.3.7 → 0.3.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.
Files changed (138) hide show
  1. package/.circleci/config.yml +1 -1
  2. package/.eslintrc +10 -1
  3. package/.stylelintrc +6 -2
  4. package/README.md +19 -1
  5. package/build/index.js +15 -11
  6. package/build/style.css +7 -7
  7. package/package.json +55 -54
  8. package/src/assets/containers/AdverseEvent/adverse-event.svg +6 -0
  9. package/src/assets/containers/Generic/generic.svg +3 -0
  10. package/src/assets/containers/MedicationDispense/medication-dispense.svg +5 -0
  11. package/src/assets/containers/PractitionerRole/practitioner-role.svg +5 -0
  12. package/src/assets/containers/ReferralRequest/referral-request.svg +8 -0
  13. package/src/assets/containers/RelatedPerson/related-person.svg +6 -0
  14. package/src/components/containers/Accordion/Accordion.js +21 -13
  15. package/src/components/datatypes/CodeableConcept/CodeableConcept.js +6 -3
  16. package/src/components/datatypes/Coding/Coding.js +7 -3
  17. package/src/components/datatypes/Reference/Reference.js +7 -5
  18. package/src/components/datatypes/Telecom/Telecom.js +2 -3
  19. package/src/components/resources/AdverseEvent/AdverseEvent.js +81 -42
  20. package/src/components/resources/AdverseEvent/AdverseEvent.stories.js +12 -2
  21. package/src/components/resources/AdverseEvent/AdverseEvent.test.js +109 -2
  22. package/src/components/resources/AllergyIntolerance/AllergyIntolerance.js +7 -1
  23. package/src/components/resources/AllergyIntolerance/AllergyIntolerance.test.js +36 -1
  24. package/src/components/resources/Appointment/Appointment.js +2 -1
  25. package/src/components/resources/Appointment/Appointment.test.js +36 -1
  26. package/src/components/resources/Bundle/Bundle.css +7 -0
  27. package/src/components/resources/Bundle/Bundle.js +15 -11
  28. package/src/components/resources/Bundle/Bundle.stories.js +12 -78
  29. package/src/components/resources/Bundle/Bundle.test.js +0 -3
  30. package/src/components/resources/CarePlan/CarePlan.js +2 -1
  31. package/src/components/resources/CarePlan/CarePlan.test.js +42 -6
  32. package/src/components/resources/CareTeam/CareTeam.js +72 -50
  33. package/src/components/resources/CareTeam/CareTeam.stories.js +20 -3
  34. package/src/components/resources/CareTeam/CareTeam.test.js +109 -1
  35. package/src/components/resources/CareTeam/CareTeamParticipants.js +1 -1
  36. package/src/components/resources/Claim/Claim.js +2 -1
  37. package/src/components/resources/Claim/Claim.test.js +32 -1
  38. package/src/components/resources/ClaimResponse/AddedItem.js +61 -11
  39. package/src/components/resources/ClaimResponse/AddedItems.js +5 -9
  40. package/src/components/resources/ClaimResponse/ClaimResponse.js +137 -83
  41. package/src/components/resources/ClaimResponse/ClaimResponse.stories.js +15 -2
  42. package/src/components/resources/ClaimResponse/ClaimResponse.test.js +112 -1
  43. package/src/components/resources/ClaimResponse/Item.js +44 -9
  44. package/src/components/resources/ClaimResponse/Items.js +5 -4
  45. package/src/components/resources/Condition/Condition.js +3 -3
  46. package/src/components/resources/Condition/Condition.test.js +37 -4
  47. package/src/components/resources/Coverage/Coverage.js +2 -1
  48. package/src/components/resources/Coverage/Coverage.test.js +36 -1
  49. package/src/components/resources/Device/Device.js +2 -1
  50. package/src/components/resources/Device/Device.test.js +36 -1
  51. package/src/components/resources/DiagnosticReport/DiagnosticReport.js +7 -2
  52. package/src/components/resources/DiagnosticReport/DiagnosticReport.test.js +36 -1
  53. package/src/components/resources/DocumentReference/DocumentReference.js +7 -2
  54. package/src/components/resources/DocumentReference/DocumentReference.test.js +42 -1
  55. package/src/components/resources/Encounter/Encounter.js +2 -1
  56. package/src/components/resources/Encounter/Encounter.test.js +36 -1
  57. package/src/components/resources/ExplanationOfBenefit/ExplanationOfBenefit.js +2 -0
  58. package/src/components/resources/ExplanationOfBenefit/ExplanationOfBenefit.test.js +38 -1
  59. package/src/components/resources/FamilyMemberHistory/FamilyMemberHistory.js +7 -2
  60. package/src/components/resources/FamilyMemberHistory/FamilyMemberHistory.test.js +36 -1
  61. package/src/components/resources/Generic/Generic.js +20 -7
  62. package/src/components/resources/Generic/Generic.stories.js +2 -1
  63. package/src/components/resources/Generic/Generic.test.js +26 -7
  64. package/src/components/resources/Goal/Goal.js +2 -3
  65. package/src/components/resources/Goal/Goal.test.js +32 -1
  66. package/src/components/resources/Immunization/Immunization.js +2 -2
  67. package/src/components/resources/Immunization/Immunization.test.js +36 -1
  68. package/src/components/resources/List/DrugTierDefinitionExtension.js +79 -35
  69. package/src/components/resources/List/Entries.js +3 -3
  70. package/src/components/resources/List/List.js +135 -88
  71. package/src/components/resources/List/List.stories.js +38 -5
  72. package/src/components/resources/List/List.test.js +105 -1
  73. package/src/components/resources/Location/Location.js +65 -47
  74. package/src/components/resources/Location/Location.stories.js +11 -4
  75. package/src/components/resources/Location/Location.test.js +106 -4
  76. package/src/components/resources/Medication/Medication.js +2 -1
  77. package/src/components/resources/Medication/Medication.test.js +36 -1
  78. package/src/components/resources/MedicationAdministration/MedicationAdministration.js +86 -62
  79. package/src/components/resources/MedicationAdministration/MedicationAdministration.stories.js +7 -0
  80. package/src/components/resources/MedicationAdministration/MedicationAdministration.test.js +117 -1
  81. package/src/components/resources/MedicationDispense/DosageInstruction.js +25 -0
  82. package/src/components/resources/MedicationDispense/MedicationDispense.js +68 -68
  83. package/src/components/resources/MedicationDispense/MedicationDispense.stories.js +7 -0
  84. package/src/components/resources/MedicationDispense/MedicationDispense.test.js +108 -1
  85. package/src/components/resources/MedicationKnowledge/MedicationKnowledge.js +115 -66
  86. package/src/components/resources/MedicationKnowledge/MedicationKnowledge.stories.js +6 -0
  87. package/src/components/resources/MedicationKnowledge/MedicationKnowledge.test.js +110 -1
  88. package/src/components/resources/MedicationOrder/MedicationOrder.js +2 -3
  89. package/src/components/resources/MedicationOrder/MedicationOrder.test.js +35 -4
  90. package/src/components/resources/MedicationRequest/MedicationRequest.js +2 -1
  91. package/src/components/resources/MedicationRequest/MedicationRequest.test.js +33 -4
  92. package/src/components/resources/MedicationStatement/MedicationStatement.js +7 -2
  93. package/src/components/resources/MedicationStatement/MedicationStatement.test.js +36 -1
  94. package/src/components/resources/Observation/Observation.js +2 -1
  95. package/src/components/resources/Observation/Observation.test.js +30 -1
  96. package/src/components/resources/Organization/Organization.js +3 -2
  97. package/src/components/resources/Organization/Organization.test.js +36 -1
  98. package/src/components/resources/Patient/Patient.js +2 -0
  99. package/src/components/resources/Patient/Patient.test.js +31 -2
  100. package/src/components/resources/Practitioner/Practitioner.js +2 -1
  101. package/src/components/resources/Practitioner/Practitioner.test.js +36 -1
  102. package/src/components/resources/PractitionerRole/PractitionerRole.js +50 -29
  103. package/src/components/resources/PractitionerRole/PractitionerRole.stories.js +7 -0
  104. package/src/components/resources/PractitionerRole/PractitionerRole.test.js +108 -1
  105. package/src/components/resources/Procedure/Procedure.js +2 -2
  106. package/src/components/resources/Procedure/Procedure.test.js +30 -1
  107. package/src/components/resources/Questionnaire/Group.js +53 -0
  108. package/src/components/resources/Questionnaire/Items.js +45 -0
  109. package/src/components/resources/Questionnaire/Questionnaire.css +24 -5
  110. package/src/components/resources/Questionnaire/Questionnaire.js +31 -170
  111. package/src/components/resources/Questionnaire/Questionnaire.stories.js +8 -0
  112. package/src/components/resources/Questionnaire/Questionnaire.test.js +194 -15
  113. package/src/components/resources/Questionnaire/Questions.js +40 -0
  114. package/src/components/resources/Questionnaire/getQuestionText.js +20 -0
  115. package/src/components/resources/QuestionnaireResponse/Answers.js +59 -0
  116. package/src/components/resources/QuestionnaireResponse/Group.js +70 -0
  117. package/src/components/resources/QuestionnaireResponse/Items.js +45 -0
  118. package/src/components/resources/QuestionnaireResponse/QuestionnaireResponse.css +33 -8
  119. package/src/components/resources/QuestionnaireResponse/QuestionnaireResponse.js +52 -236
  120. package/src/components/resources/QuestionnaireResponse/QuestionnaireResponse.stories.js +8 -0
  121. package/src/components/resources/QuestionnaireResponse/QuestionnaireResponse.test.js +38 -3
  122. package/src/components/resources/QuestionnaireResponse/Questions.js +43 -0
  123. package/src/components/resources/QuestionnaireResponse/getQuestionText.js +22 -0
  124. package/src/components/resources/ReferralRequest/ReferralRequest.js +65 -40
  125. package/src/components/resources/ReferralRequest/ReferralRequest.test.js +111 -11
  126. package/src/components/resources/RelatedPerson/RelatedPerson.js +151 -0
  127. package/src/components/resources/RelatedPerson/RelatedPerson.stories.js +46 -0
  128. package/src/components/resources/RelatedPerson/RelatedPerson.test.js +156 -0
  129. package/src/components/resources/RelatedPerson/index.js +3 -0
  130. package/src/components/resources/ResearchStudy/ResearchStudy.js +160 -130
  131. package/src/components/resources/ResearchStudy/ResearchStudy.stories.js +2 -0
  132. package/src/components/resources/ResearchStudy/ResearchStudy.test.js +108 -1
  133. package/src/components/ui/index.js +22 -9
  134. package/src/fixtures/dstu2/resources/relatedPerson/example1.json +79 -0
  135. package/src/fixtures/example-icons.jsx +42 -0
  136. package/src/fixtures/r4/resources/relatedPerson/example1.json +64 -0
  137. package/src/fixtures/stu3/resources/relatedPerson/example1.json +43 -0
  138. package/src/style.scss +3 -1
@@ -21,11 +21,11 @@ import {
21
21
  Header,
22
22
  MissingValue,
23
23
  Root,
24
- Title,
25
- Value,
26
24
  ValueSection,
27
25
  BadgeSecondary,
26
+ ValueSectionItem,
28
27
  } from '../../ui';
28
+ import Accordion from '../../containers/Accordion';
29
29
 
30
30
  const commonDTO = fhirResource => {
31
31
  const id = _get(fhirResource, 'id');
@@ -285,8 +285,7 @@ const hasPaymentInfo = payment => {
285
285
  return Object.values(payment).filter(item => item).length > 0;
286
286
  };
287
287
 
288
- const ClaimResponse = props => {
289
- const { fhirVersion, fhirResource } = props;
288
+ const ClaimResponse = ({ fhirVersion, fhirResource, fhirIcons, onClick }) => {
290
289
  let fhirResourceData = {};
291
290
  try {
292
291
  fhirResourceData = resourceDTO(fhirVersion, fhirResource);
@@ -314,88 +313,143 @@ const ClaimResponse = props => {
314
313
  const hasAddedItems = addedItems.length > 0;
315
314
  const hasPayment = hasPaymentInfo(payment);
316
315
 
316
+ const tableData = [
317
+ {
318
+ label: 'Created At',
319
+ testId: 'created',
320
+ data: created && <DateType fhirData={created} isBlack />,
321
+ status: created,
322
+ },
323
+ {
324
+ label: 'Request claim',
325
+ testId: 'request',
326
+ data: requestReference && <Reference fhirData={requestReference} />,
327
+ status: requestReference,
328
+ },
329
+ {
330
+ label: 'Disposition',
331
+ testId: 'disposition',
332
+ data: disposition,
333
+ status: disposition,
334
+ },
335
+ {
336
+ label: 'Total cost',
337
+ testId: 'totalCost',
338
+ data: totalCost && <Money fhirData={totalCost} />,
339
+ status: totalCost,
340
+ },
341
+ {
342
+ label: 'Total benefit',
343
+ testId: 'totalBenefit',
344
+ data: totalBenefit && <Money fhirData={totalBenefit} />,
345
+ status: totalBenefit,
346
+ },
347
+ ];
348
+
349
+ const paymentData = [
350
+ {
351
+ label: 'Type',
352
+ testId: 'payment.type',
353
+ data: payment.typeCoding ? (
354
+ <Coding fhirData={payment.typeCoding} />
355
+ ) : (
356
+ <MissingValue />
357
+ ),
358
+ status: true,
359
+ },
360
+ {
361
+ label: 'Amount',
362
+ testId: 'payment.amount',
363
+ data: payment.amount ? (
364
+ <Money fhirData={payment.amount} />
365
+ ) : (
366
+ <MissingValue />
367
+ ),
368
+ status: payment.amount,
369
+ },
370
+ {
371
+ label: 'Date',
372
+ testId: 'payment.date',
373
+ data: payment.date ? (
374
+ <DateType fhirData={payment.date} isBlack />
375
+ ) : (
376
+ <MissingValue />
377
+ ),
378
+ status: payment.date,
379
+ },
380
+ {
381
+ label: 'Reference',
382
+ testId: 'payment.ref',
383
+ data: payment.ref ? (
384
+ <Identifier fhirData={payment.ref} />
385
+ ) : (
386
+ <MissingValue />
387
+ ),
388
+ status: payment.ref,
389
+ },
390
+ ];
391
+
317
392
  return (
318
393
  <Root name="ClaimResponse">
319
- <Header>
320
- <Title>Claim response #{id}</Title>
321
- {outcome && <Badge data-testid="outcome">{outcome}</Badge>}
322
- {status && (
323
- <BadgeSecondary data-testid="status">{status}</BadgeSecondary>
324
- )}
325
- </Header>
326
- <Body>
327
- {created && (
328
- <Value label="Created At" data-testid="created">
329
- <DateType fhirData={created} />
330
- </Value>
331
- )}
332
- {requestReference && (
333
- <Value label="Request claim" data-testid="request">
334
- <Reference fhirData={requestReference} />
335
- </Value>
336
- )}
337
- {disposition && (
338
- <Value label="Disposition" data-testid="disposition">
339
- {disposition}
340
- </Value>
341
- )}
342
- {totalCost && (
343
- <Value label="Total cost" data-testid="totalCost">
344
- <Money fhirData={totalCost} />
345
- </Value>
346
- )}
347
- {totalBenefit && (
348
- <Value label="Total benefit" data-testid="totalBenefit">
349
- <Money fhirData={totalBenefit} />
350
- </Value>
351
- )}
352
- {isNotEmptyArray(totalCostsArr) && (
353
- <ValueSection label="Total" data-testid="totalSection">
354
- {totalCostsArr.map(
355
- ({ category, amount }, i) =>
356
- category && (
357
- <Value label={category} key={`total-value-${i}`}>
358
- <Money fhirData={amount} />
359
- </Value>
360
- ),
394
+ <Accordion
395
+ headerContent={
396
+ <Header
397
+ resourceName="ClaimResponse"
398
+ title={`Claim response #${id}`}
399
+ badges={
400
+ <>
401
+ {outcome && <Badge data-testid="outcome">{outcome}</Badge>}
402
+ {status && (
403
+ <BadgeSecondary data-testid="status">{status}</BadgeSecondary>
404
+ )}
405
+ </>
406
+ }
407
+ icon={fhirIcons}
408
+ />
409
+ }
410
+ bodyContent={
411
+ <Body tableData={tableData}>
412
+ {isNotEmptyArray(totalCostsArr) && (
413
+ <ValueSection label="Total" data-testid="totalSection" marginTop>
414
+ {totalCostsArr.map(
415
+ ({ category, amount }, i) =>
416
+ category && (
417
+ <ValueSectionItem
418
+ label={category}
419
+ key={`total-value-${i}`}
420
+ >
421
+ <Money fhirData={amount} />
422
+ </ValueSectionItem>
423
+ ),
424
+ )}
425
+ </ValueSection>
426
+ )}
427
+ {hasPayment && (
428
+ <ValueSection
429
+ label="Payment"
430
+ data-testid="paymentSection"
431
+ marginTop
432
+ >
433
+ {paymentData.map(
434
+ (item, index) =>
435
+ item.status && (
436
+ <ValueSectionItem
437
+ key={`payment-item-${index}`}
438
+ label={item.label}
439
+ data-testid={item.testId}
440
+ >
441
+ {item.data}
442
+ </ValueSectionItem>
443
+ ),
444
+ )}
445
+ </ValueSection>
361
446
  )}
362
- </ValueSection>
363
- )}
364
- {hasPayment && (
365
- <ValueSection label="Payment" data-testid="paymentSection">
366
- <Value label="Type" data-testid="payment.type">
367
- {payment.typeCoding ? (
368
- <Coding fhirData={payment.typeCoding} />
369
- ) : (
370
- <MissingValue />
371
- )}
372
- </Value>
373
- <Value label="Amount" data-testid="payment.amount">
374
- {payment.amount ? (
375
- <Money fhirData={payment.amount} />
376
- ) : (
377
- <MissingValue />
378
- )}
379
- </Value>
380
- <Value label="Date" data-testid="payment.date">
381
- {payment.date ? (
382
- <DateType fhirData={payment.date} />
383
- ) : (
384
- <MissingValue />
385
- )}
386
- </Value>
387
- <Value label="Reference" data-testid="payment.ref">
388
- {payment.ref ? (
389
- <Identifier fhirData={payment.ref} />
390
- ) : (
391
- <MissingValue />
392
- )}
393
- </Value>
394
- </ValueSection>
395
- )}
396
- {hasAddedItems && <AddedItems addedItems={addedItems} />}
397
- {hasItems && <Items items={items} />}
398
- </Body>
447
+ {hasAddedItems && <AddedItems addedItems={addedItems} />}
448
+ {hasItems && <Items items={items} />}
449
+ </Body>
450
+ }
451
+ onClick={onClick}
452
+ />
399
453
  </Root>
400
454
  );
401
455
  };
@@ -10,6 +10,8 @@ import example2ClaimResponseSTU3 from '../../../fixtures/stu3/resources/claimRes
10
10
  import example1ClaimResponseR4 from '../../../fixtures/r4/resources/claimResponse/example1.json';
11
11
  import example2ClaimResponseR4 from '../../../fixtures/r4/resources/claimResponse/example2.json';
12
12
  import example3ClaimResponseR4 from '../../../fixtures/r4/resources/claimResponse/example3.json';
13
+ import fhirIcons from '../../../fixtures/example-icons';
14
+ import ClaimResponseIcon from '../../../assets/containers/ClaimResponse/claim-response.svg';
13
15
 
14
16
  export default { title: 'Claim Response' };
15
17
 
@@ -19,6 +21,7 @@ export const ExampleDSTU2 = () => {
19
21
  <ClaimResponse
20
22
  fhirResource={fhirResource}
21
23
  fhirVersion={fhirVersions.DSTU2}
24
+ fhirIcons={require('../../../assets/containers/ClaimResponse/claim-response.svg')}
22
25
  />
23
26
  );
24
27
  };
@@ -29,6 +32,7 @@ export const Example1OfSTU3 = () => {
29
32
  <ClaimResponse
30
33
  fhirResource={fhirResource}
31
34
  fhirVersion={fhirVersions.STU3}
35
+ fhirIcons={ClaimResponseIcon}
32
36
  />
33
37
  );
34
38
  };
@@ -38,6 +42,7 @@ export const Example2OfSTU3 = () => {
38
42
  <ClaimResponse
39
43
  fhirResource={fhirResource}
40
44
  fhirVersion={fhirVersions.STU3}
45
+ fhirIcons={fhirIcons}
41
46
  />
42
47
  );
43
48
  };
@@ -45,13 +50,21 @@ export const Example2OfSTU3 = () => {
45
50
  export const Example1OfR4 = () => {
46
51
  const fhirResource = object('Resource', example1ClaimResponseR4);
47
52
  return (
48
- <ClaimResponse fhirResource={fhirResource} fhirVersion={fhirVersions.R4} />
53
+ <ClaimResponse
54
+ fhirResource={fhirResource}
55
+ fhirVersion={fhirVersions.R4}
56
+ fhirIcons={false}
57
+ />
49
58
  );
50
59
  };
51
60
  export const Example2OfR4 = () => {
52
61
  const fhirResource = object('Resource', example2ClaimResponseR4);
53
62
  return (
54
- <ClaimResponse fhirResource={fhirResource} fhirVersion={fhirVersions.R4} />
63
+ <ClaimResponse
64
+ fhirResource={fhirResource}
65
+ fhirVersion={fhirVersions.R4}
66
+ fhirIcons={'random text'}
67
+ />
55
68
  );
56
69
  };
57
70
  export const Example3OfR4 = () => {
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { render } from '@testing-library/react';
2
+ import { fireEvent, render } from '@testing-library/react';
3
3
 
4
4
  import ClaimResponse from './ClaimResponse';
5
5
  import fhirVersions from '../fhirResourceVersions';
@@ -10,8 +10,84 @@ import stu3Example2 from '../../../fixtures/stu3/resources/claimResponse/example
10
10
  import r4Example1 from '../../../fixtures/r4/resources/claimResponse/example1.json';
11
11
  import r4Example2 from '../../../fixtures/r4/resources/claimResponse/example2.json';
12
12
  import r4Example3 from '../../../fixtures/r4/resources/claimResponse/example3.json';
13
+ import fhirIcons from '../../../fixtures/example-icons';
13
14
 
14
15
  describe('should render the ClaimResponse component properly', () => {
16
+ it('component without a fhirIcons props should render a default icon', () => {
17
+ const defaultProps = {
18
+ fhirVersion: fhirVersions.DSTU2,
19
+ fhirResource: dstu2Example1,
20
+ };
21
+
22
+ const { getByAltText } = render(<ClaimResponse {...defaultProps} />);
23
+ const headerIcon = getByAltText('claim response');
24
+
25
+ expect(headerIcon.getAttribute('src')).toContain('IMAGE_MOCK');
26
+ });
27
+
28
+ it('component with a false as a fhirIcons props should render a placeholder', () => {
29
+ const defaultProps = {
30
+ fhirVersion: fhirVersions.DSTU2,
31
+ fhirResource: dstu2Example1,
32
+ fhirIcons: false,
33
+ };
34
+
35
+ const { getByTestId } = render(<ClaimResponse {...defaultProps} />);
36
+ const headerIcon = getByTestId('placeholder');
37
+
38
+ expect(headerIcon).toBeTruthy();
39
+ });
40
+
41
+ it('component with the img as a fhirIcons props should render an img', () => {
42
+ const defaultProps = {
43
+ fhirVersion: fhirVersions.DSTU2,
44
+ fhirResource: dstu2Example1,
45
+ fhirIcons: (
46
+ <img
47
+ src={require('../assets/containers/ClaimResponse/claim-response.svg')}
48
+ alt="clipboard with a symmetrical cross and a return arrow"
49
+ />
50
+ ),
51
+ };
52
+
53
+ const { getByAltText } = render(<ClaimResponse {...defaultProps} />);
54
+ const headerIcon = getByAltText(
55
+ 'clipboard with a symmetrical cross and a return arrow',
56
+ );
57
+
58
+ expect(headerIcon.getAttribute('src')).toContain('IMAGE_MOCK');
59
+ });
60
+
61
+ it('component with the resources object as a fhirIcons props should render an img', () => {
62
+ const defaultProps = {
63
+ fhirVersion: fhirVersions.DSTU2,
64
+ fhirResource: dstu2Example1,
65
+ fhirIcons: fhirIcons,
66
+ };
67
+
68
+ const { getByAltText } = render(<ClaimResponse {...defaultProps} />);
69
+ const headerIcon = getByAltText(
70
+ 'clipboard with a symmetrical cross and a return arrow',
71
+ );
72
+
73
+ expect(headerIcon.getAttribute('src')).toContain('IMAGE_MOCK');
74
+ });
75
+
76
+ it('component with the url as a fhirIcons props should render an img', () => {
77
+ const avatarSrc =
78
+ 'https://www.gravatar.com/avatar/?s=50&r=any&default=identicon&forcedefault=1';
79
+ const defaultProps = {
80
+ fhirVersion: fhirVersions.DSTU2,
81
+ fhirResource: dstu2Example1,
82
+ fhirIcons: avatarSrc,
83
+ };
84
+
85
+ const { getByAltText } = render(<ClaimResponse {...defaultProps} />);
86
+ const headerIcon = getByAltText('header icon');
87
+
88
+ expect(headerIcon.getAttribute('src')).toContain(avatarSrc);
89
+ });
90
+
15
91
  it('with DSTU2 source data', () => {
16
92
  const defaultProps = {
17
93
  fhirResource: dstu2Example1,
@@ -262,4 +338,39 @@ describe('should render the ClaimResponse component properly', () => {
262
338
  ' (expense)',
263
339
  ]);
264
340
  });
341
+
342
+ it('should fire custom onClick function', () => {
343
+ const defaultProps = {
344
+ fhirResource: r4Example3,
345
+ fhirVersion: fhirVersions.R4,
346
+ };
347
+
348
+ const onClick = jest.fn();
349
+ const { getAllByRole } = render(
350
+ <ClaimResponse {...defaultProps} onClick={onClick} />,
351
+ );
352
+ const accordion = getAllByRole('button')[0];
353
+ fireEvent.click(accordion);
354
+
355
+ const attribute = accordion.getAttribute('data-bs-toggle');
356
+ expect(attribute).not.toEqual('collapse');
357
+ expect(onClick).toHaveBeenCalled();
358
+ });
359
+
360
+ it('should not fire custom onClick function', () => {
361
+ const defaultProps = {
362
+ fhirResource: r4Example3,
363
+ fhirVersion: fhirVersions.R4,
364
+ };
365
+
366
+ const onClick = 'test';
367
+ const { getAllByRole } = render(
368
+ <ClaimResponse {...defaultProps} onClick={onClick} />,
369
+ );
370
+ const accordion = getAllByRole('button')[0];
371
+ fireEvent.click(accordion);
372
+
373
+ const attribute = accordion.getAttribute('data-bs-toggle');
374
+ expect(attribute).toEqual('collapse');
375
+ });
265
376
  });
@@ -1,20 +1,40 @@
1
- import React from 'react';
1
+ import React, { useState } from 'react';
2
2
 
3
- import { TableCell, TableRow } from '../../ui';
3
+ import { Chevron, TableCell, TableRow } from '../../ui';
4
4
  import Coding from '../../datatypes/Coding';
5
5
  import Money from '../../datatypes/Money';
6
6
 
7
- const Item = props => {
8
- const { item, parentSequences, level } = props;
9
-
7
+ const Item = ({ item, parentSequences, parentId, isCollapse = false }) => {
10
8
  const itemSequences = [...parentSequences, item.sequenceLinkId];
11
9
  const id = itemSequences.join('.');
10
+ const collapseId = parentSequences.length ? parentId : item.sequence;
11
+
12
+ const [rotate, setRotate] = useState(false);
13
+ const handleTableExpand = () => setRotate(!rotate);
14
+
15
+ const isExpandable =
16
+ parentSequences.length === 0 && item.subItems.length !== 0;
12
17
 
13
18
  return (
14
19
  <>
15
- <TableRow>
16
- <TableCell data-testid="items.sequence">{id}</TableCell>
17
- <TableCell data-testid="items.adjudication">
20
+ <TableRow
21
+ className={`${isCollapse ? `collapse item-${parentId}` : ''} ${
22
+ isExpandable ? 'fw-bold table-expandable-row border-top' : ''
23
+ }`}
24
+ data-bs-target={`.item-${collapseId}`}
25
+ data-bs-toggle={'collapse'}
26
+ aria-controls={id}
27
+ aria-expanded="false"
28
+ onClick={handleTableExpand}
29
+ >
30
+ <TableCell
31
+ data-testid="items.sequence"
32
+ className="col-md-2 align-self-start"
33
+ isAlignTop
34
+ >
35
+ {id}
36
+ </TableCell>
37
+ <TableCell data-testid="items.adjudication" className="col-md-8">
18
38
  {item.adjudication.map((adjudication, idx) => (
19
39
  <div
20
40
  key={idx}
@@ -29,13 +49,28 @@ const Item = props => {
29
49
  </div>
30
50
  ))}
31
51
  </TableCell>
52
+ {isExpandable ? (
53
+ <TableCell className="col-md-2" isAlignTop>
54
+ <button
55
+ className="fhir-container__Accordion__header-button w-100 p-0 border-0 rounded-1 collapsed text-dark bg-transparent shadow-none "
56
+ type="button"
57
+ >
58
+ <div className={` ${rotate ? ' header-rotate' : ''}`}>
59
+ <Chevron strokeColor={rotate ? '#2a6fd7' : '#6f83a9'} />
60
+ </div>
61
+ </button>
62
+ </TableCell>
63
+ ) : (
64
+ <TableCell style={{ width: '64px' }} className="col-md-2" />
65
+ )}
32
66
  </TableRow>
33
67
  {item.subItems.map((subItem, idx) => (
34
68
  <Item
35
69
  key={idx}
36
70
  item={subItem}
37
- level={level + 1}
38
71
  parentSequences={itemSequences}
72
+ parentId={collapseId}
73
+ isCollapse
39
74
  />
40
75
  ))}
41
76
  </>
@@ -7,17 +7,18 @@ const Items = props => {
7
7
  const { items } = props;
8
8
 
9
9
  return (
10
- <ValueSection label="Items" data-testid="items">
10
+ <ValueSection label="Items" data-testid="items" marginTop>
11
11
  <Table>
12
12
  <thead>
13
13
  <TableRow>
14
14
  <TableHeader>ID</TableHeader>
15
- <TableHeader expand>Adjudication</TableHeader>
15
+ <TableHeader>Adjudication</TableHeader>
16
+ <TableHeader></TableHeader>
16
17
  </TableRow>
17
18
  </thead>
18
- <tbody>
19
+ <tbody className="border-top-0">
19
20
  {items.map((item, idx) => (
20
- <Item key={idx} item={item} level={0} parentSequences={[]} />
21
+ <Item key={idx} item={item} parentSequences={[]} />
21
22
  ))}
22
23
  </tbody>
23
24
  </Table>
@@ -86,9 +86,8 @@ const resourceDTO = (fhirVersion, fhirResource) => {
86
86
  throw Error('Unrecognized the fhir version property type.');
87
87
  }
88
88
  };
89
- function Condition(props) {
90
- const { fhirResource, fhirVersion, fhirIcons } = props;
91
89
 
90
+ const Condition = ({ fhirResource, fhirVersion, fhirIcons, onClick }) => {
92
91
  const {
93
92
  codeText,
94
93
  severityText,
@@ -157,10 +156,11 @@ function Condition(props) {
157
156
  />
158
157
  }
159
158
  bodyContent={<Body tableData={tableData} />}
159
+ onClick={onClick}
160
160
  />
161
161
  </Root>
162
162
  );
163
- }
163
+ };
164
164
 
165
165
  Condition.propTypes = {
166
166
  fhirResource: PropTypes.shape({}).isRequired,
@@ -8,7 +8,7 @@ import exampleConditionSTU3 from '../../../fixtures/stu3/resources/condition/exa
8
8
  import exampleConditionSeverity from '../../../fixtures/dstu2/resources/condition/example-severity.json';
9
9
  import exampleConditionSeveritySTU3 from '../../../fixtures/stu3/resources/condition/example-severity.json';
10
10
  import fhirVersions from '../fhirResourceVersions';
11
- import { render } from '@testing-library/react';
11
+ import { fireEvent, render } from '@testing-library/react';
12
12
  import fhirIcons from '../../../fixtures/example-icons';
13
13
 
14
14
  describe('should render component correctly', () => {
@@ -108,9 +108,7 @@ describe('should render component correctly', () => {
108
108
  expect(getByTestId('clinicalStatus').textContent).toEqual('active');
109
109
  expect(getByTestId('severity').textContent).toEqual('Medium severity');
110
110
  expect(getByTestId('onsetDate').textContent).toEqual('8/24/2015');
111
- expect(getByTestId('asserter').textContent).toEqual(
112
- 'MOORE, NICKPractitioner/f8fedcd9e6e565a21f457909',
113
- );
111
+ expect(getByTestId('asserter').textContent).toEqual('MOORE, NICK');
114
112
  });
115
113
 
116
114
  it('STU3 - without severity field', () => {
@@ -191,4 +189,39 @@ describe('should render component correctly', () => {
191
189
  expect(getByTestId('asserter').textContent).toEqual('Practitioner/f201');
192
190
  expect(getByTestId('dateRecorded').textContent).toEqual('4/4/2013');
193
191
  });
192
+
193
+ it('should fire custom onClick function', () => {
194
+ const defaultProps = {
195
+ fhirResource: example3ConditionSeverityR4,
196
+ fhirVersion: fhirVersions.R4,
197
+ };
198
+
199
+ const onClick = jest.fn();
200
+ const { getByRole } = render(
201
+ <Condition {...defaultProps} onClick={onClick} />,
202
+ );
203
+ const accordion = getByRole('button');
204
+ fireEvent.click(accordion);
205
+
206
+ const attribute = accordion.getAttribute('data-bs-toggle');
207
+ expect(attribute).not.toEqual('collapse');
208
+ expect(onClick).toHaveBeenCalled();
209
+ });
210
+
211
+ it('should not fire custom onClick function', () => {
212
+ const defaultProps = {
213
+ fhirResource: example3ConditionSeverityR4,
214
+ fhirVersion: fhirVersions.R4,
215
+ };
216
+
217
+ const onClick = 'test';
218
+ const { getByRole } = render(
219
+ <Condition {...defaultProps} onClick={onClick} />,
220
+ );
221
+ const accordion = getByRole('button');
222
+ fireEvent.click(accordion);
223
+
224
+ const attribute = accordion.getAttribute('data-bs-toggle');
225
+ expect(attribute).toEqual('collapse');
226
+ });
194
227
  });
@@ -114,7 +114,7 @@ const resourceDTO = (fhirVersion, fhirResource) => {
114
114
  }
115
115
  };
116
116
 
117
- const Coverage = ({ fhirResource, fhirVersion, fhirIcons }) => {
117
+ const Coverage = ({ fhirResource, fhirVersion, fhirIcons, onClick }) => {
118
118
  let fhirResourceData = {};
119
119
  try {
120
120
  fhirResourceData = resourceDTO(fhirVersion, fhirResource);
@@ -232,6 +232,7 @@ const Coverage = ({ fhirResource, fhirVersion, fhirIcons }) => {
232
232
  />
233
233
  }
234
234
  bodyContent={<Body tableData={tableData} />}
235
+ onClick={onClick}
235
236
  />
236
237
  </Root>
237
238
  );
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { render } from '@testing-library/react';
2
+ import { fireEvent, render } from '@testing-library/react';
3
3
  import Coverage from './Coverage';
4
4
  import fhirVersions from '../fhirResourceVersions';
5
5
 
@@ -151,4 +151,39 @@ describe('should render component correctly', () => {
151
151
  expect(getByTestId('type').textContent).toContain('extended healthcare');
152
152
  expect(queryAllByTestId('details').length).toEqual(0);
153
153
  });
154
+
155
+ it('should fire custom onClick function', () => {
156
+ const defaultProps = {
157
+ fhirResource: exampleCoverageR4,
158
+ fhirVersion: fhirVersions.R4,
159
+ };
160
+
161
+ const onClick = jest.fn();
162
+ const { getByRole } = render(
163
+ <Coverage {...defaultProps} onClick={onClick} />,
164
+ );
165
+ const accordion = getByRole('button');
166
+ fireEvent.click(accordion);
167
+
168
+ const attribute = accordion.getAttribute('data-bs-toggle');
169
+ expect(attribute).not.toEqual('collapse');
170
+ expect(onClick).toHaveBeenCalled();
171
+ });
172
+
173
+ it('should not fire custom onClick function', () => {
174
+ const defaultProps = {
175
+ fhirResource: exampleCoverageR4,
176
+ fhirVersion: fhirVersions.R4,
177
+ };
178
+
179
+ const onClick = 'test';
180
+ const { getByRole } = render(
181
+ <Coverage {...defaultProps} onClick={onClick} />,
182
+ );
183
+ const accordion = getByRole('button');
184
+ fireEvent.click(accordion);
185
+
186
+ const attribute = accordion.getAttribute('data-bs-toggle');
187
+ expect(attribute).toEqual('collapse');
188
+ });
154
189
  });