Session: agent-a12e11-subagent-a12e118e — 2026-04-29

workspace-doctolib · Claude · branch HEAD · claude-sonnet-4-6 · 2026-04-29 13:40 · 1 msgs · 26 tools · 16 min read · updated 8 days ago

Analyze test coverage for PR https://github.com/doctolib/doctolib/pull/241055 — \"feat(FHIR-2195): add...

tools: Bash, ToolSearch, Read
← workspace-doctolib Download .md .txt .json
Tool calls
Bash Bash: 24 calls (92.3%) 24 Read Read: 1 call (3.8%) 1 ToolSearch ToolSearch: 1 call (3.8%) 1
Token usage1.5M total
Input39
Cache creation105.5K
Cache read1.4M
Output3.8K
Cache hit ratio93%· healthy

Project: workspace-doctolib · Branch: HEAD · Mode: ` · **Model:**claude-sonnet-4-6`

Stats: 1 user messages, 26 tool calls, tools used: Bash, ToolSearch, Read.

Conversation

Turn 1 — User

Analyze test coverage for PR https://github.com/doctolib/doctolib/pull/241055 — "feat(FHIR-2195): add archive/unarchive actions to document list".

The PR adds archive/unarchive actions to the NHR document list UI. Here are the test files:


useNhrDocumentStatusActions.test.ts (191 lines, NEW)

import { act, renderHook } from '@testing-library/react'
import type { Patient } from 'monolith_DEPRECATED/types/doctor/api/Patient'
import type { NhrDocument } from '@doctolib/tpf-national-health-records'
import type { DropdownActionOption } from '@doctolib/tpf-national-health-records-ui'
import { useNhrDocumentStatusActions } from './useNhrDocumentStatusActions'
import { useNationalHealthRecords } from './useNationalHealthRecords'
import { useInvalidateNhrDocuments } from './useInvalidateNhrDocuments'

const findOption = (options: DropdownActionOption[], key: string): DropdownActionOption => {
  const opt = options.find((o) => o.key === key)
  if (!opt) throw new Error(`Option "${key}" not found`)
  return opt
}

jest.mock('./useNationalHealthRecords')
jest.mock('./useInvalidateNhrDocuments')
jest.mock('monolith_DEPRECATED/services/i18n', () => ({
  __esModule: true,
  default: { t: (key: string) => key },
}))

const mockUpdateDocumentMetadata = jest.fn()
const mockInvalidate = jest.fn()

const patient = { ins: 'INS-123' } as unknown as Patient
const activeDoc = { id: 'doc-1', status: '1' } as unknown as NhrDocument
const archivedDoc = { id: 'doc-2', status: '4' } as unknown as NhrDocument

describe('useNhrDocumentStatusActions', () => {
  beforeEach(() => {
    jest.clearAllMocks()
    jest.mocked(useNationalHealthRecords).mockReturnValue({
      searchDocuments: jest.fn(),
      getDocumentsContent: jest.fn(),
      updateDocumentMetadata: mockUpdateDocumentMetadata,
    })
    jest.mocked(useInvalidateNhrDocuments).mockReturnValue(mockInvalidate)
  })

  describe('options', () => {
    it('exposes archive and unarchive options', () => {
      const { result } = renderHook(() => useNhrDocumentStatusActions({ patient }))
      expect(result.current.options.map((o) => o.key)).toEqual(['archive', 'unarchive'])
    })

    it('archive option is only available for active documents', () => {
      const { result } = renderHook(() => useNhrDocumentStatusActions({ patient }))
      const archiveOption = findOption(result.current.options, 'archive')
      expect(archiveOption.isAvailable?.(activeDoc)).toBe(true)
      expect(archiveOption.isAvailable?.(archivedDoc)).toBe(false)
    })

    it('unarchive option is only available for archived documents', () => {
      const { result } = renderHook(() => useNhrDocumentStatusActions({ patient }))
      const unarchiveOption = findOption(result.current.options, 'unarchive')
      expect(unarchiveOption.isAvailable?.(archivedDoc)).toBe(true)
      expect(unarchiveOption.isAvailable?.(activeDoc)).toBe(false)
    })
  })
  // (remaining 150+ lines cut for brevity — covers handleConfirm success, handleConfirm error, handleDismiss)
})

useInvalidateNhrDocuments.test.ts (31 lines, NEW)

it('returns a function that invalidates dmp-documents queries for the patient INS', async () => {
  const { result } = renderHook(() => useInvalidateNhrDocuments(patient))
  await result.current()
  expect(mockInvalidateQueries).toHaveBeenCalledWith({ queryKey: ['dmp-documents', 'INS-123'] })
})

it('uses patient.ins as the prefix key, busting all filter variants', async () => {
  const otherPatient = { ins: 'INS-456' } as unknown as Patient
  const { result } = renderHook(() => useInvalidateNhrDocuments(otherPatient))
  await result.current()
  expect(mockInvalidateQueries).toHaveBeenCalledWith({ queryKey: ['dmp-documents', 'INS-456'] })
})

NhrDocumentActionDialog.test.tsx (124 lines, NEW)

Tests: renders nothing when config is null, renders nothing when isOpen=false, renders title/body, shows confirm button, shows/hides cancel button based on isLoading, shows er …(truncated, 1848 more chars)

Turn 1 — Assistant

I'll analyze the test coverage by examining the actual implementation files alongside the provided test excerpts.

Tools used:

  • Bash: find /Users/USER/workspace/doctolib/worktrees/doctolib -name "useNhrDocumentStatusActions*" -o -name "useInvalidateNhrDocuments*" -o -name "NhrDocumentActionDialog*" -o -name "DmpNhrAdapter*" 2>/ …(truncated, 19 more chars)

Tool results:

→ result (ok): /Users/USER/workspace/doctolib/worktrees/doctolib/fhir-2216_fix-nhr-date-columns-and-document-type/packages/@doctolib/national-health-records/src/business/adapters/DmpNhrAdapter.ts /Users/USER/workspace/doctolib/worktrees/doctolib/fhir-2216_fix-nhr-date-columns-and-document-type/packages/@doctolib/national-health-records/src/business/adapters/DmpNhrAdapter.test.ts /Users/USER/workspace/doctolib/worktrees/doctolib/fhir-2189_class-code-label-map/packages/@doctolib/national-health-records/src/busin …(truncated, 3768 more chars)

Tools used:

  • Bash: find /Users/USER/workspace/doctolib/worktrees/doctolib -path "*FHIR-2195*" -name "*.ts" -o -path "*FHIR-2195*" -name "*.tsx" 2>/dev/null | head -30

Tool results:

→ result (ok): (Bash completed with no output)

Tools used:

  • ToolSearch (inputs: query, max_results)

Tool results:

→ result (ok)

Let me fetch the PR and all relevant implementation files.

Tools used:

  • Bash: gh pr view 241055 --repo doctolib/doctolib --json title,body,files,additions,deletions,headRefName 2>/dev/null | head -100

Tool results:

→ result (ok): {"additions":1106,"body":"## Why\n\nFHIR-2195 — Wires the Archive/Unarchive actions into the Document List UI by providing the action configuration the dropdown consumes.\n\n⚠️ Depends on #241005 (DMP API change) — do not merge until that PR lands first. GitHub will automatically retarget this PR to master once #241005 merges.\n\n## How\n\nNew hook — useNhrDocumentStatusActions\nManages the full state machine: which options are visib …(truncated, 5944 more chars)

Tools used:

  • Bash: gh pr diff 241055 --repo doctolib/doctolib 2>/dev/null | head -800

Tool results:

→ result (ok): <persisted-output> Output too large (35.8KB). Full output saved to: /Users/USER/.claude/projects/-Users-clertonra-workspace-doctolib/d54757cf-182c-4820-b814-d35168883058/tool-results/bf7dgpqun.txt

Preview (first 2KB): diff --git a/config/locales/en_tmp.yml b/config/locales/en_tmp.yml index c48646744821d..3dcab23f9765f 100644 --- a/config/locales/en_tmp.yml +++ b/config/locales/en_tmp.yml @@ -56111,3 +56111,26 @@ en: urgent: Urgent request unknown: Other ge …(truncated, 1732 more chars)

Tools used:

  • Read: /Users/USER/.claude/projects/-Users-clertonra-workspace-doctolib/d54757cf-182c-4820-b814-d35168883058/tool-results/bf7dgpqun.txt

Tool results:

→ result (ok): 1 diff --git a/config/locales/en_tmp.yml b/config/locales/en_tmp.yml 2 index c48646744821d..3dcab23f9765f 100644 3 --- a/config/locales/en_tmp.yml 4 +++ b/config/locales/en_tmp.yml 5 @@ -56111,3 +56111,26 @@ en: 6 urgent: Urgent request 7 unknown: Other 8 general_request_from_professional_caller: Healthcare professionals 9 + national_health_records: 10 + patient: 11 + errors: 12 + missing_qualified_ins: Patient needs a Qualified INS to proce …(truncated, 39212 more chars)

Let me look at the actual implementation files, not the lock file.

Tools used:

  • Bash: gh api repos/doctolib/doctolib/contents/packages/@doctolib/national-health-records/src/hooks/useNhrDocumentStatusActions.ts?ref=FHIR-2195-monolith-nhr-document-status-actions 2>/dev/null | python3 -c …(truncated, 96 more chars)

Tool results:

→ result (ERROR): Exit code 1 (eval):1: no matches found: repos/doctolib/doctolib/contents/packages/@doctolib/national-health-records/src/hooks/useNhrDocumentStatusActions.ts?ref=FHIR-2195-monolith-nhr-document-status-actions Traceback (most recent call last): File "<string>", line 1, in <module> import sys,json,base64; d=json.load(sys.stdin); print(base64.b64decode(d['content']).decode()) ~~~~~~~~~^^^^^^^^^^^ File "/opt/homebrew/Cellar/<REDACTED>/3.14.4/Frameworks/Python.fra ~~~ …(truncated, 1033 more chars)

Tools used:

  • Bash: gh api "repos/doctolib/doctolib/contents/packages/%40doctolib/national-health-records/src/hooks/useNhrDocumentStatusActions.ts" --field "ref=FHIR-2195-monolith-nhr-document-status-actions" 2>/dev/null …(truncated, 110 more chars)

Tool results:

→ result (ERROR): Exit code 1 Traceback (most recent call last): File "<string>", line 1, in <module> import sys,json,base64; d=json.load(sys.stdin); print(base64.b64decode(d['content']).decode()) ~^^^^^^^^^^^ KeyError: 'content'

Tools used:

  • Bash: gh pr view 241055 --repo doctolib/doctolib --json headRefName,headRepository 2>/dev/null

Tool results:

→ result (ok): {"headRefName":"FHIR-2195-monolith-nhr-document-status-actions","headRepository":{"id":"MDEwOlJlcG9zaXRvcnkxNDAyMjQyMQ==","name":"doctolib","nameWithOwner":"doctolib/doctolib"}}

Tools used:

  • Bash: BRANCH="FHIR-2195-monolith-nhr-document-status-actions" …

Tool results:

→ result (ok): === FILE: packages/%40doctolib/national-health-records/src/hooks/useNhrDocumentStatusActions.ts === === FILE: packages/%40doctolib/national-health-records/src/hooks/useNhrDocumentStatusActions.test.ts === === FILE: packages/%40doctolib/national-health-records/src/hooks/useInvalidateNhrDocuments.ts === === FILE: packages/%40doctolib/national-health-records/src/hooks/useInvalidateNhrDocuments.test.ts === === FILE: packages/%40doctolib/national-health-records/src/components/NhrDocumentActionDialog/ …(truncated, 162 more chars)

Tools used:

  • Bash: gh pr diff 241055 --repo doctolib/doctolib -- "packages/@doctolib/national-health-records/src/hooks/useNhrDocumentStatusActions.ts" "packages/@doctolib/national-health-records/src/hooks/useNhrDocument …(truncated, 207 more chars)

Tool results:

→ result (ERROR): Exit code 1

Tools used:

  • Bash: gh pr diff 241055 --repo doctolib/doctolib 2>/dev/null | grep -A 200 "useNhrDocumentStatusActions.ts$" | head -220

Tool results:

→ result (ok): diff --git a/packages/@doctolib/national-health-records/src/hooks/useNhrDocumentStatusActions.ts b/packages/@doctolib/national-health-records/src/hooks/useNhrDocumentStatusActions.ts new file mode 100644 index 0000000000000..318806a23a573 --- /dev/null +++ b/packages/@doctolib/national-health-records/src/hooks/useNhrDocumentStatusActions.ts @@ -0,0 +1,101 @@ +import { useCallback, useMemo, useState } from 'react' +import type { NhrDocument } from '@doctolib/tpf-national-health-records' +import t …(truncated, 8156 more chars)

Tools used:

  • Bash: gh pr diff 241055 --repo doctolib/doctolib 2>/dev/null | grep -A 220 "useNhrDocumentStatusActions.test.ts$" | head -240

Tool results:

→ result (ok): diff --git a/packages/@doctolib/national-health-records/src/hooks/useNhrDocumentStatusActions.test.ts b/packages/@doctolib/national-health-records/src/hooks/useNhrDocumentStatusActions.test.ts new file mode 100644 index 0000000000000..ffc2a3a3b3ce4 --- /dev/null +++ b/packages/@doctolib/national-health-records/src/hooks/useNhrDocumentStatusActions.test.ts @@ -0,0 +1,191 @@ +import { act, renderHook } from '@testing-library/react' +import type { Patient } from 'monolith_DEPRECATED/types/doctor/ap …(truncated, 9322 more chars)

Tools used:

  • Bash: gh pr diff 241055 --repo doctolib/doctolib 2>/dev/null | grep -A 120 "useInvalidateNhrDocuments.test.ts$" | head -130

Tool results:

→ result (ok): diff --git a/packages/@doctolib/national-health-records/src/hooks/useInvalidateNhrDocuments.test.ts b/packages/@doctolib/national-health-records/src/hooks/useInvalidateNhrDocuments.test.ts new file mode 100644 index 0000000000000..99ae8a77126f0 --- /dev/null +++ b/packages/@doctolib/national-health-records/src/hooks/useInvalidateNhrDocuments.test.ts @@ -0,0 +1,31 @@ +import { renderHook } from '@testing-library/react' +import { useQueryClient } from '@tanstack/react-query-v5' +import type { Pati …(truncated, 5415 more chars)

Tools used:

  • Bash: gh pr diff 241055 --repo doctolib/doctolib 2>/dev/null | grep -A 200 "NhrDocumentActionDialog.tsx$" | head -230

Tool results:

→ result (ok): diff --git a/packages/@doctolib/national-health-records/src/components/NhrDocumentActionDialog/NhrDocumentActionDialog.tsx b/packages/@doctolib/national-health-records/src/components/NhrDocumentActionDialog/NhrDocumentActionDialog.tsx new file mode 100644 index 0000000000000..55e06847bc397 --- /dev/null +++ b/packages/@doctolib/national-health-records/src/components/NhrDocumentActionDialog/NhrDocumentActionDialog.tsx @@ -0,0 +1,32 @@ +import { Alert } from '@doctolib/design-system/Alert' +import …(truncated, 8419 more chars)

Tools used:

  • Bash: gh pr diff 241055 --repo doctolib/doctolib 2>/dev/null | grep -A 200 "NhrDocumentActionDialog.test.tsx$" | head -230

Tool results:

→ result (ok): diff --git a/packages/@doctolib/national-health-records/src/components/NhrDocumentActionDialog/NhrDocumentActionDialog.test.tsx b/packages/@doctolib/national-health-records/src/components/NhrDocumentActionDialog/NhrDocumentActionDialog.test.tsx new file mode 100644 index 0000000000000..4b17883f3bfc8 --- /dev/null +++ b/packages/@doctolib/national-health-records/src/components/NhrDocumentActionDialog/NhrDocumentActionDialog.test.tsx @@ -0,0 +1,124 @@ +import '@testing-library/jest-dom' +import Re …(truncated, 7273 more chars)

Tools used:

  • Bash: gh pr diff 241055 --repo doctolib/doctolib 2>/dev/null | grep -A 200 "DmpNhrAdapter.test.ts$" | head -230

Tool results:

→ result (ok): diff --git a/packages/@doctolib/national-health-records/src/business/adapters/DmpNhrAdapter.test.ts b/packages/@doctolib/national-health-records/src/business/adapters/DmpNhrAdapter.test.ts index 98306d4b594ae..022d4697ef1b8 100644 --- a/packages/@doctolib/national-health-records/src/business/adapters/DmpNhrAdapter.test.ts +++ b/packages/@doctolib/national-health-records/src/business/adapters/DmpNhrAdapter.test.ts @@ -20,6 +20,7 @@ jest.mock('@doctolib/dmp', () => ({ sharedOnlyWithPractition …(truncated, 8127 more chars)

Tools used:

  • Bash: gh pr diff 241055 --repo doctolib/doctolib 2>/dev/null | grep -A 100 "dmpDocumentHelpers.test.ts$" | head -110

Tool results:

→ result (ok): diff --git a/packages/@doctolib/national-health-records/src/variants/dmp/mappers/dmpDocumentHelpers.test.ts b/packages/@doctolib/national-health-records/src/variants/dmp/mappers/dmpDocumentHelpers.test.ts index 93331b55b08c0..dc5afca0cf32b 100644 --- a/packages/@doctolib/national-health-records/src/variants/dmp/mappers/dmpDocumentHelpers.test.ts +++ b/packages/@doctolib/national-health-records/src/variants/dmp/mappers/dmpDocumentHelpers.test.ts @@ -1,10 +1,13 @@ import type { NhrDocument } from …(truncated, 4929 more chars)

Tools used:

  • Bash: gh pr diff 241055 --repo doctolib/doctolib 2>/dev/null | grep -A 80 "PatientCard.tsx$" | head -100

Tool results:

→ result (ok): diff --git a/packages/@doctolib/shared_patient_file_and_appointment_page_components/src/desktop/PatientCard/PatientCard.tsx b/packages/@doctolib/shared_patient_file_and_appointment_page_components/src/desktop/PatientCard/PatientCard.tsx index 5a93957032bb8..2737d7ea40ca8 100644 --- a/packages/@doctolib/shared_patient_file_and_appointment_page_components/src/desktop/PatientCard/PatientCard.tsx +++ b/packages/@doctolib/shared_patient_file_and_appointment_page_components/src/desktop/PatientCard/Pat …(truncated, 3007 more chars)

Tools used:

  • Bash: gh pr diff 241055 --repo doctolib/doctolib 2>/dev/null | grep -A 60 "DmpApi.test.ts$" | head -70

Tool results:

→ result (ok): diff --git a/packages/@doctolib/dmp/src/business/DmpApi.test.ts b/packages/@doctolib/dmp/src/business/DmpApi.test.ts index 781a616f50228..2b146a28faf65 100644 --- a/packages/@doctolib/dmp/src/business/DmpApi.test.ts +++ b/packages/@doctolib/dmp/src/business/DmpApi.test.ts @@ -1590,13 +1590,13 @@ describe('DmpApi', () => { it('should call updateDocumentStatusCommand with session and props', async () => { getCachedDmpSessionMocked.mockResolvedValue({ sessionId: 'session-abc', healthcar …(truncated, 2401 more chars)

Tools used:

  • Bash: gh pr diff 241055 --repo doctolib/doctolib 2>/dev/null | grep -A 60 "DmpApi.ts$" | head -70

Tool results:

→ result (ok): diff --git a/packages/@doctolib/dmp/src/business/DmpApi.ts b/packages/@doctolib/dmp/src/business/DmpApi.ts index b84e8653cb2b0..c272c11b501ca 100644 --- a/packages/@doctolib/dmp/src/business/DmpApi.ts +++ b/packages/@doctolib/dmp/src/business/DmpApi.ts @@ -342,7 +342,9 @@ export class DmpApiImpl implements DmpApi { }

async updateDocumentStatus(props: DocumentStatusUpdateProps): Promise<void> { - const { ins, documentUniqueId: uniqueId, uuid, healthCareSettings, getTransactionFrames } …(truncated, 2908 more chars)

Now I have a comprehensive picture of all the implementation and test code. Let me do a final check on a few remaining questions.

Tools used:

  • Bash: gh pr diff 241055 --repo doctolib/doctolib 2>/dev/null | grep -B2 -A 40 "updateDocumentMetadata" | grep -A 30 "handleConfirm\|result\.status\|success.*false\|status.*error" | head -60

Tool results:

→ result (ok): + success: false, + error: { status: 'ERROR_42' }, + }) + const adapter = new DmpNhrAdapter(mockDmpApi, undefined) + + const result = await adapter.updateDocumentMetadata(updateProps) + + expect(result.result.payloads[0]).toEqual(expect.objectContaining({ status: 'error', message: 'DMP API error' })) + }) + + it('should combine apiErrorDescription and apiErrorExtendedInformations in message', async () => { + const mockDmpApi = createMockDmpApi() +
…(truncated, 2319 more chars)

Tools used:

  • Bash: # Check the full handleConfirm implementation — specifically whether it checks result.status for silent errors …

Tool results:

→ result (ok): + const handleConfirm = async () => { + if (!modalState || !nhrOperations || !patient.ins) return + + setIsLoading(true) + setError(null) + + try { + await nhrOperations.updateDocumentMetadata({ + patient: toNhrPatientInformation(patient.ins), + params: { payloads: [{ id: modalState.doc.id, propertyName: 'status' }] }, + }) + setModalState(null) + await invalidateNhrDocuments() + } catch { + setError(i18n.t('national_health_records.document_ …(truncated, 890 more chars)

Tools used:

  • Bash: # Check DmpNhrAdapter.ts updateDocumentMetadata return type and result.status behavior …

Tool results:

→ result (ok): (Bash completed with no output)

Tools used:

  • Bash: gh pr diff 241055 --repo doctolib/doctolib 2>/dev/null | grep -n "updateDocumentMetadata\|result\.status\|payloads.*status" | head -30

Tool results:

→ result (ok): 14236: params: { payloads: [{ id: 'doc-1', uuid: 'uuid-1', propertyName: 'status' }] }, 14250: expect(result.result.payloads[0]).toEqual(expect.objectContaining({ id: 'doc-1', status: 'success' })) 14263: const result = await adapter.updateDocumentMetadata(updateProps) 14276:+ const result = await adapter.updateDocumentMetadata(updateProps) 14278:+ expect(result.result.payloads[0]).toEqual(expect.objectContaining({ status: 'error', message: 'DMP API error' })) 14293:+ …(truncated, 722 more chars)

Tools used:

  • Bash: # Look at the full DmpNhrAdapter updateDocumentMetadata return value and check if there is a result.status overall …

Tool results:

→ result (ok): 14229:+ status: 'success', 14250: expect(result.result.payloads[0]).toEqual(expect.objectContaining({ id: 'doc-1', status: 'success' })) 14332:+ status: 'success', 14354:- return { id, uuid, propertyName, status: 'success' } 14388:+ return { id, uuid, propertyName, status: 'success' } 14750:+ mockUpdateDocumentMetadata.mockResolvedValue({ status: 'success', result: { payloads: [] } }) 14767:+ mockUpdateDocumentMetadata.mockResolvedValue({ status: 'su …(truncated, 844 more chars)

Now I have everything I need for a thorough analysis. Let me compile the findings.


Test Coverage Analysis: PR #241055 — feat(FHIR-2195): add archive/unarchive actions to document list

Summary

The test suite is broadly well-structured and covers the happy path thoroughly. The NhrDocumentActionDialog component tests are the strongest — they use a realistic Dialog mock and cover all meaningful render states. The useInvalidateNhrDocuments tests are complete for a thin hook. The DmpNhrAdapter additions are good but contain one significant contract drift. The central weakness is in useNhrDocumentStatusActions: the hook contains a critical silent-failure path that is completely untested, and two other behavioral gaps around patient.ins guard and invalidation failure are also missing.


Critical Gaps

1. Silent failure from adapter payload status is never surfaced to the user Criticality: 9/10

The PR description explicitly states "Checks result.status to surface silent failures from the adapter," but the actual handleConfirm implementation in useNhrDocumentStatusActions.ts does not check result.status at all:

// useNhrDocumentStatusActions.ts lines ~72-85
try {
  await nhrOperations.updateDocumentMetadata({ ... })
  setModalState(null)         // dialog closes on any resolve
  await invalidateNhrDocuments()
} catch {
  setError(...)
}

The adapter's updateDocumentMetadata resolves (does not throw) even when the DMP returns success: false. The mock in the test at line 14750 sets mockUpdateDocumentMetadata.mockResolvedValue({ status: 'success', result: { payloads: [] } }) — but the real adapter returns { status: 'success', result: { payloads: [{ status: 'error', ... }] } } for payload-level failures. Because handleConfirm never reads that return value, a DMP-level error silently dismisses the dialog and runs a cache invalidation as if the action succeeded.

A test exposing this would be:

it('shows error and keeps dialog open when adapter returns payload-level error', async () => {
  mockUpdateDocumentMetadata.mockResolvedValue({
    status: 'success',
    result: { payloads: [{ id: 'doc-1', status: 'error', message: 'Access denied' }] },
  })
  // ... click archive, call handleConfirm
  expect(result.current.modalState).not.toBeNull()   // this would FAIL today
  expect(result.current.error).not.toBeNull()         // this would FAIL today
  expect(mockInvalidate).not.toHaveBeenCalled()       // this would FAIL today
})

This is both a missing test and a real implementation bug. The PR description claims the result status check is there, but it is absent from the code.

File: /packages/@doctolib/national-health-records/src/hooks/useNhrDocumentStatusActions.ts lines 72–85 File: /packages/@doctolib/national-health-records/src/hooks/useNhrDocumentStatusActions.test.ts — no test covers this path


2. patient.ins null guard silently swallows in-flight dialogs Criticality: 7/10

The guard if (!modalState || !nhrOperations || !patient.ins) return exits without any user feedback. If patient.ins is null or empty string (a real scenario for patients without a qualified INS), the user clicks "Archive", sees the loading state skip entirely, and the dialog stays open frozen without explanation. There is no test for the patient.ins missing case:

// useNhrDocumentStatusActions.test.ts — this case does not exist:
it('does nothing and shows no error when patient.ins is missing', async () => {
  const patientWithoutIns = { ins: null } as unknown as Patient
  const { result } = renderHook(() => useNhrDocumentStatusActions({ patient: patientWithoutIns }))
  // ... click archive, call handleConfirm
  expect(mockUpdateDocumentMetadata).not.toHaveBeenCalled()
  // And what does the dialog show? Nothing changes — no error, no dismissal
})

The missing-INS scenario has a dedicated i18n key (national_health_records.patient.errors.missing_qualified_ins) added in this PR, but it is only used in useSearchDocuments. The hook does not emit it.

File: /packages/@doctolib/national-health-records/src/hooks/useNhrDocumentStatusActions.ts line ~71


3. DmpNhrAdapter mock return shape does not match the real updateDocumentMetadata contract Criticality: 7/10

In useNhrDocumentStatusActions.test.ts, the mock is:

mockUpdateDocumentMetadata.mockResolvedValue({ status: 'success', result: { payloads: [] } })

But the real NhrDocumentMetadataUpdateResult (as exercised in DmpNhrAdapter.test.ts line 14250) has the shape:

{ status: 'success', result: { payloads: [{ id, uuid, propertyName, status }] } }

The payloads array in the mock is always empty. This means the hook tests can never catch a regression where handleConfirm starts reading result.result.payloads[0].status. Any future fix for finding #1 above will need accurate mocks. The tests currently pass regardless of what the hook does with the resolved value, making them immune to regressions in that direction.

File: /packages/@doctolib/national-health-records/src/hooks/useNhrDocumentStatusActions.test.ts lines 14750, 14767, 14784, 14815


Important Improvements

4. handleDismiss during loading is silently ignored — no test verifies this contract Criticality: 6/10

The implementation has if (isLoading) return in handleDismiss. The cancel button is hidden in the dialog while loading (tested in NhrDocumentActionDialog), but nothing prevents a caller from invoking handleDismiss directly while isLoading is true (e.g. an ESC keydown handler, or a future refactor of the dialog's dismiss prop). There is no test that confirms the modal stays open when dismiss is called mid-flight:

it('does not dismiss the dialog while loading is in progress', async () => {
  let resolveUpdate: () => void
  mockUpdateDocumentMetadata.mockImplementation(
    () => new Promise((resolve) => { resolveUpdate = resolve })
  )
  // ... open dialog, start confirm
  act(() => result.current.handleDismiss())
  expect(result.current.modalState).not.toBeNull() // still open
  expect(result.current.isLoading).toBe(true)
})

File: /packages/@doctolib/national-health-records/src/hooks/useNhrDocumentStatusActions.ts lines ~89-91 File: /packages/@doctolib/national-health-records/src/hooks/useNhrDocumentStatusActions.test.ts — absent


5. invalidateNhrDocuments failure after a successful API call is not tested Criticality: 6/10

invalidateNhrDocuments() is awaited after updateDocumentMetadata succeeds. If the React Query client throws during invalidation (a legitimate failure mode — the queryClient can throw if the provider is unmounted), the outer catch will fire and show the generic error message even though the DMP operation actually succeeded. No test covers this:

it('shows error if invalidation throws even though update succeeded', async () => {
  mockUpdateDocumentMetadata.mockResolvedValue({ status: 'success', result: { payloads: [{ status: 'success' }] } })
  mockInvalidate.mockRejectedValue(new Error('Query client gone'))
  // ... open, confirm
  expect(result.current.error).not.toBeNull()
  expect(result.current.modalState).not.toBeNull() // the dialog is re-opened by the catch block
})

The bug here is actually a design issue: setModalState(null) runs before invalidateNhrDocuments(), so if invalidation throws, the error is shown but the modal is already closed (modalState is null). This is a confusing state for the user — an error with no context. The test would surface this.

File: /packages/@doctolib/national-health-records/src/hooks/useNhrDocumentStatusActions.ts lines 83-84


6. useInvalidateNhrDocuments does not test the patient.ins null path Criticality: 5/10

useInvalidateNhrDocuments passes patient.ins directly as part of the query key. When patient.ins is null or undefined, `invali …(truncated, 4202 more chars)

Keyboard shortcuts

⌘K / Ctrl+KOpen command palette
/Focus search
g hGo to home
g pGo to projects
g sGo to sessions
j / kNext / prev row (tables)
?Show this help
EscClose dialogs

Structured queries

Mix key:value filters with free text in the palette:

type:sessionOnly session pages
project:llm-wikiFilter by project name (substring)
model:claudeFilter by model name (substring)
date:>2026-03-01Sessions after a date
date:<2026-04-01Sessions before a date
tags:rustPages mentioning a tag/topic
sort:dateSort results by date (newest first)

Example: type:session project:llm-wiki date:>2026-04 sort:date