-
Notifications
You must be signed in to change notification settings - Fork 431
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Migrated Scribe to a CARE App + Context #8469
base: develop
Are you sure you want to change the base?
Conversation
✅ Deploy Preview for care-ohc ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
👋 Hi, @shivankacker, This message is automatically generated by prince-chrismc/label-merge-conflicts-action so don't hesitate to report issues/improvements there. |
CARE Run #3834
Run Properties:
|
Project |
CARE
|
Branch Review |
scribe-context
|
Run status |
Passed #3834
|
Run duration | 04m 35s |
Commit |
2771ec63fc: Migrated Scribe to a CARE App + Context
|
Committer | Shivank Kacker |
View all properties for this run ↗︎ |
Test results | |
---|---|
Failures |
0
|
Flaky |
0
|
Pending |
0
|
Skipped |
0
|
Passing |
125
|
View all changes introduced in this branch ↗︎ |
👋 Hi, @shivankacker, This message is automatically generated by prince-chrismc/label-merge-conflicts-action so don't hesitate to report issues/improvements there. |
@shivankacker please close pending PR's before opening others. |
@bodhish working on this currently |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Outside diff range and nitpick comments (4)
cypress/pageobject/Patient/PatientLogupdate.ts (1)
54-54
: Consider adding value validation.Since this is now a direct integer input field, consider adding validation to ensure the input is within an acceptable range for pulse values.
Example implementation:
typePulse(pulse: string) { + const pulseNum = Number(pulse); + if (isNaN(pulseNum) || pulseNum < 0 || pulseNum > 300) { + throw new Error('Invalid pulse value. Must be between 0 and 300.'); + } cy.get("#pulse").click().type(pulse); + // Verify the value was entered correctly + cy.get("#pulse").should('have.value', pulse); }src/components/Form/FormFields/Autocomplete.tsx (2)
159-167
: Consider adding props.value to effect dependencies.While the value observation setup is good, there's a potential race condition if
props.value
changes while the effect is running. Consider addingprops.value
to the effect dependencies to ensure proper synchronization.useEffect(() => { if (props.value !== domValue && typeof domValue !== "undefined") props.onChange(domValue); - }, [domValue]); + }, [domValue, props.value]);
159-182
: Well-implemented value observation pattern.The integration of
useValueInjectionObserver
with ARIA attributes creates a robust pattern for form value synchronization. This aligns well with the PR objective of making forms aware of existing data. The implementation:
- Properly separates concerns between DOM observation and state management
- Follows accessibility best practices with ARIA attributes
- Uses modern React patterns effectively
This approach could be considered as a pattern for other form components that need similar value awareness capabilities.
src/components/Patient/DailyRounds.tsx (1)
852-855
: Simplify the onChange handler.The current onChange handler can be simplified since it's just passing through the nursing value.
-onChange={(log) => - handleFormFieldChange({ - name: "nursing", - value: log.nursing, - }) -} +onChange={(log) => handleFormFieldChange({ name: "nursing", value: log.nursing })}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (9)
cypress/pageobject/Patient/PatientLogupdate.ts
(1 hunks)src/Redux/api.tsx
(0 hunks)src/Utils/useVoiceRecorder.ts
(1 hunks)src/components/Common/DateInputV2.tsx
(4 hunks)src/components/Form/FormFields/Autocomplete.tsx
(3 hunks)src/components/Patient/DailyRounds.tsx
(10 hunks)src/components/Scribe/Scribe.tsx
(0 hunks)src/components/Scribe/formDetails.ts
(0 hunks)src/pluginTypes.ts
(1 hunks)
💤 Files with no reviewable changes (3)
- src/Redux/api.tsx
- src/components/Scribe/Scribe.tsx
- src/components/Scribe/formDetails.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- src/components/Common/DateInputV2.tsx
- src/pluginTypes.ts
🧰 Additional context used
🪛 Biome
src/Utils/useVoiceRecorder.ts
[error] 2-2: Do not shadow the global "Error" property.
Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.
(lint/suspicious/noShadowRestrictedNames)
src/components/Patient/DailyRounds.tsx
[error] 706-731: Avoid using unnecessary Fragment.
A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment
(lint/complexity/noUselessFragments)
🔇 Additional comments (9)
src/Utils/useVoiceRecorder.ts (3)
4-10
: LGTM: Clean state management implementation.
The hook's state management is well-organized with clear separation of concerns for audio URL, recording status, MediaRecorder instance, blob data, and waveform visualization.
96-119
: LGTM: Well-designed public API.
The public methods provide a clean and intuitive interface for controlling the recording functionality.
122-125
: 🛠️ Refactor suggestion
Improve error handling in requestRecorder function.
The requestRecorder
function should handle potential errors more gracefully and provide meaningful error messages for different failure scenarios.
Consider this improvement:
async function requestRecorder() {
- const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
- return new MediaRecorder(stream);
+ try {
+ if (!navigator.mediaDevices?.getUserMedia) {
+ throw new Error("Audio recording is not supported in this browser");
+ }
+ const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
+ return new MediaRecorder(stream);
+ } catch (error) {
+ if (error instanceof DOMException) {
+ switch (error.name) {
+ case "NotAllowedError":
+ throw new Error("Microphone permission denied");
+ case "NotFoundError":
+ throw new Error("No microphone found");
+ default:
+ throw new Error(`Failed to setup audio recording: ${error.message}`);
+ }
+ }
+ throw error;
+ }
}
Likely invalid or redundant comment.
cypress/pageobject/Patient/PatientLogupdate.ts (1)
54-54
: 🛠️ Refactor suggestion
Verify alignment with form field changes.
The change from typeAndSelectOption
to direct input aligns with Issue #8978's goal of replacing range auto-complete fields with integer fields. However, similar methods in this class (e.g., typeRespiratory
, typeSpo2
) still use typeAndSelectOption
.
Let's verify if other vital sign fields have been updated in the application code:
Consider updating similar vital sign methods for consistency:
typePulse(pulse: string) {
cy.get("#pulse").click().type(pulse);
}
typeRespiratory(respiratory: string) {
- cy.typeAndSelectOption("#resp", respiratory);
+ cy.get("#resp").click().type(respiratory);
}
typeSpo2(spo: string) {
- cy.typeAndSelectOption("#ventilator_spo2", spo);
+ cy.get("#ventilator_spo2").click().type(spo);
}
src/components/Form/FormFields/Autocomplete.tsx (2)
9-9
: LGTM: Import statements are properly organized.
The new imports for useRef
and useValueInjectionObserver
are correctly placed and support the enhanced value observation functionality.
Also applies to: 17-17
110-110
: LGTM: Ref initialization is properly typed.
The menuRef
is correctly initialized with proper typing for the dropdown menu container.
src/components/Patient/DailyRounds.tsx (3)
677-682
: LGTM! Well-structured form field improvements.
The replacement of range fields with numeric text fields is well implemented with appropriate:
- Input validation (min/max ranges)
- Medical thresholds for visual feedback
- Consistent labeling with units (bpm, mg/dL, %)
Also applies to: 706-711, 738-743, 763-768
863-866
: LGTM! Well-organized UI structure.
Good use of:
- Semantic class names for styling
- Proper placement of data-scribe-ignore attributes
🧰 Tools
🪛 Biome
[error] 863-945: Avoid using unnecessary Fragment.
A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment
(lint/complexity/noUselessFragments)
557-561
: Verify Scribe plugin initialization and form integration.
The Scribe plugin integration looks good, but let's verify that the form data attribute is properly recognized by the plugin.
✅ Verification successful
Let me gather more information about the Scribe plugin configuration and usage.
Let me check the plugin engine implementation and how it handles plugin components.
Let me check the plugin types and configuration to complete the verification.
Based on the verification results, I can now provide a final response:
Scribe plugin integration is properly configured and implemented.
The integration is correctly set up with:
- Proper plugin type definition in
pluginTypes.ts
withScribeComponentType
- Correct form data attribute usage with
data-scribe-form
- Proper plugin component initialization through
PluginEngine.tsx
- Consistent data attributes for form fields with
data-scribe-ignore
where needed
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check if Scribe plugin is properly imported and configured
# Test: Search for Scribe plugin configuration
rg -A 5 "PLUGIN_Component.*Scribe"
Length of output: 471
Script:
#!/bin/bash
# Check for PLUGIN_Component definition and imports
rg -l "PLUGIN_Component"
# Check for other Scribe-related configurations or utilities
rg -i "scribe" --type ts --type tsx
# Look for plugin-related type definitions or configurations
ast-grep --pattern 'type PLUGIN_Component = $_'
Length of output: 333
Script:
#!/bin/bash
# Check PluginEngine.tsx implementation
cat src/PluginEngine.tsx
# Check for data attribute usage in the codebase
rg "data-scribe" --type ts --type tsx --type js --type jsx
# Look for plugin component usage pattern
ast-grep --pattern 'const PLUGIN_Component = $_'
Length of output: 1554
Script:
#!/bin/bash
# Check plugin types definition
cat src/pluginTypes.ts
# Check for any Scribe-specific configurations
rg -g '!*.test.*' -g '!*.spec.*' -i "scribe"
# Look for form data attributes usage
rg "data-" -g '*.tsx' -g '*.ts' -A 2
Length of output: 106618
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Outside diff range and nitpick comments (5)
src/components/Common/TemperatureFormField.tsx (2)
27-27
: Add input validation before conversion.While the conversion chain ensures proper number formatting, it's recommended to validate the input value before conversion to handle potential invalid inputs gracefully.
- ? Number(fahrenheitToCelsius(parseFloat(value)).toFixed(1)).toString() + ? !isNaN(parseFloat(value)) + ? Number(fahrenheitToCelsius(parseFloat(value)).toFixed(1)).toString() + : ""
Line range hint
1-89
: Consider additional safety measures for medical application.As this component handles critical patient data in a medical context, consider implementing:
- Type definitions for medically valid temperature ranges
- Audit logging for temperature changes (important for medical records)
- Visual indicators for abnormal temperature ranges
- Internationalization support for temperature units based on locale
Example type definition:
type TemperatureRange = { min: number; max: number; unit: TemperatureUnit; }; const MEDICAL_TEMPERATURE_RANGES: Record<TemperatureUnit, TemperatureRange> = { celsius: { min: 35, max: 41.1, unit: "celsius" }, fahrenheit: { min: 95, max: 106, unit: "fahrenheit" } };src/components/Patient/DailyRounds.tsx (3)
844-855
: Consider memoizing the nursing care onChange handlerThe onChange handler for NursingCare is recreated on every render. Consider memoizing it with useCallback to optimize performance.
-onChange={(log) => - handleFormFieldChange({ - name: "nursing", - value: log.nursing, - }) -} +onChange={useCallback((log) => + handleFormFieldChange({ + name: "nursing", + value: log.nursing, + }), [handleFormFieldChange])}
863-866
: Remove unnecessary data-scribe-ignore attributeThe div with class "flex flex-col gap-10" has a data-scribe-ignore attribute, but it's already within a parent element that has the same attribute. This creates unnecessary attribute duplication.
<div className="flex flex-col gap-10 divide-y-2 divide-dashed divide-secondary-600 border-t-2 border-dashed border-secondary-600 pt-6 md:col-span-2" - data-scribe-ignore >
🧰 Tools
🪛 Biome
[error] 863-945: Avoid using unnecessary Fragment.
A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment(lint/complexity/noUselessFragments)
639-640
: Improve boolean field handlingThe is_experiencing_dysuria field uses string literals "true"/"false" for a boolean field. Consider using actual boolean values for better type safety.
-options={["true", "false"]} -optionLabel={(c) => t(c === "true" ? "yes" : "no")} +options={[true, false]} +optionLabel={(value) => t(value ? "yes" : "no")}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (5)
src/Locale/en.json
(12 hunks)src/components/Common/BloodPressureFormField.tsx
(1 hunks)src/components/Common/TemperatureFormField.tsx
(2 hunks)src/components/Form/FormFields/TextFormField.tsx
(3 hunks)src/components/Patient/DailyRounds.tsx
(11 hunks)
✅ Files skipped from review due to trivial changes (1)
- src/components/Common/BloodPressureFormField.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
- src/Locale/en.json
- src/components/Form/FormFields/TextFormField.tsx
🧰 Additional context used
🪛 Biome
src/components/Patient/DailyRounds.tsx
[error] 706-731: Avoid using unnecessary Fragment.
A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment
(lint/complexity/noUselessFragments)
🔇 Additional comments (2)
src/components/Patient/DailyRounds.tsx (2)
677-682
: Improved form field validation with TextFormField
The replacement of range fields with TextFormField components includes proper validation constraints and helpful thresholds for medical measurements. Good improvements for:
- Pulse (0-200 bpm)
- Blood sugar (0-700 mg/dL)
- Respiratory rate (0-150 bpm)
- SpO2 (0-100%)
Also applies to: 706-711, 738-743, 763-768
557-561
: Verify data-scribe-form attribute usage
The form has been marked with data-scribe-form
attribute, but there's no documentation about its purpose or requirements. This could affect maintainability.
✅ Verification successful
Based on the search results, I can now generate the final response:
The data-scribe-form
attribute is part of the Scribe plugin integration
The attribute is used in conjunction with the <PLUGIN_Component __name="Scribe" />
component, which appears to be a legitimate plugin integration. The attribute serves as a form marker for the Scribe plugin functionality.
- The attribute is properly scoped to the form element that contains the daily rounds data
- The implementation follows a plugin-based architecture pattern with clear component boundaries
- The feature can be toggled via the
REACT_ENABLE_SCRIBE
environment variable
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for other usages of data-scribe-form to understand the pattern
rg -l 'data-scribe-form'
# Search for any documentation about scribe form attributes
rg -l 'data-scribe.*form' '*.md'
Length of output: 143
Script:
#!/bin/bash
# Search for any Scribe-related code or documentation
rg -i "scribe" -A 5 -B 5
# Look for plugin component definitions or documentation
ast-grep --pattern 'const PLUGIN_Component = $_'
Length of output: 147402
Script:
#!/bin/bash
# Search for Scribe-related configuration and documentation
rg -l "REACT_ENABLE_SCRIBE|data-scribe" -g "*.md"
# Look for Scribe plugin component usage and configuration
rg "PLUGIN_Component.*Scribe" -A 5 -B 5
# Search for data-scribe-form attribute documentation or related code
rg "data-scribe-form" -A 5 -B 5 -g "!*.{json,map}"
Length of output: 1809
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Outside diff range and nitpick comments (3)
src/Utils/useVoiceRecorder.ts (3)
1-2
: Be more specific with the notification import.Instead of importing all exports from
Notifications
, import only the specific notification function needed. This improves code maintainability and bundle size optimization.-import * as Notify from "./Notifications"; +import { Error as NotifyError } from "./Notifications";
15-19
: Consider combining effects for better state management.The first effect's logic could be moved into the second effect where the recording state is managed. This would centralize the recorder lifecycle management and reduce the number of effect dependencies.
69-100
: Add TypeScript types for better type safety.The audio analyzer setup could benefit from explicit TypeScript types and error handling.
+ interface AudioAnalyzerConfig { + fftSize: number; + minDecibels: number; + maxDecibels: number; + } const setupAudioAnalyser = () => { let animationFrameId: number; + const config: AudioAnalyzerConfig = { + fftSize: 32, + minDecibels: -90, + maxDecibels: -10 + }; try { audioContext = new (window.AudioContext || (window as any).webkitAudioContext)(); analyser = audioContext.createAnalyser(); - analyser.fftSize = 32; + Object.assign(analyser, config);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (2)
cypress/pageobject/Patient/PatientLogupdate.ts
(1 hunks)src/Utils/useVoiceRecorder.ts
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- cypress/pageobject/Patient/PatientLogupdate.ts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Outside diff range and nitpick comments (5)
src/Utils/useSegmentedRecorder.ts (3)
10-10
: LGTM! Consider adding JSDoc documentation.The new state variable for tracking microphone access is well-placed and appropriately initialized.
Add JSDoc documentation to explain the purpose of this state:
+/** Tracks whether the user has granted microphone access permission */ const [microphoneAccess, setMicrophoneAccess] = useState(false);
Line range hint
28-38
: Enhance error handling for better user feedback.While the microphone access state management is correct, the error handling could be more specific to help users troubleshoot issues, especially on iOS devices (ref: Issue #8227).
Consider this improvement:
setRecorder(newRecorder); setMicrophoneAccess(true); if (restart) { setIsRecording(true); } }, - () => { + (error) => { + const errorMessage = error.name === 'NotAllowedError' + ? t("audio__permission_denied") + : error.name === 'NotFoundError' + ? t("audio__no_device_found") + : t("audio__permission_message"); Notify.Error({ - msg: t("audio__permission_message"), + msg: errorMessage, }); setIsRecording(false); setMicrophoneAccess(false); },
Line range hint
13-14
: Consider making audio configuration more flexible.The
bufferInterval
andsplitSizeLimit
are hardcoded. Consider making these configurable through hook parameters to support different use cases and device capabilities.Example implementation:
interface AudioConfig { bufferInterval?: number; // milliseconds splitSizeLimit?: number; // bytes audioBitsPerSecond?: number; } const useSegmentedRecording = (config?: AudioConfig) => { const bufferInterval = config?.bufferInterval ?? 1000; const splitSizeLimit = config?.splitSizeLimit ?? 20_000_000; // ... rest of the implementation }src/Utils/useVoiceRecorder.ts (2)
74-104
: Add error handling to audio analyzer setup.The
setupAudioAnalyser
function should handle potential errors when creating audio context and analyzer nodes.const setupAudioAnalyser = () => { let animationFrameId: number; - audioContext = new (window.AudioContext || - (window as any).webkitAudioContext)(); - analyser = audioContext.createAnalyser(); + try { + audioContext = new (window.AudioContext || + (window as any).webkitAudioContext)(); + analyser = audioContext.createAnalyser(); + } catch (error) { + Notify.Error({ + msg: `Failed to initialize audio analyzer: ${ + error instanceof Error ? error.message : "Unknown error" + }`, + }); + return; + }
132-156
: Add browser compatibility checks.While the code handles iOS Safari well, it should also check for MediaRecorder API support.
async function requestRecorder() { + if (!navigator.mediaDevices || !window.MediaRecorder) { + throw new Error( + "Audio recording is not supported in this browser. Please use a modern browser." + ); + } + const constraints: MediaStreamConstraints = {
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (2)
src/Utils/useSegmentedRecorder.ts
(5 hunks)src/Utils/useVoiceRecorder.ts
(1 hunks)
🔇 Additional comments (3)
src/Utils/useSegmentedRecorder.ts (1)
103-112
:
Address potential race conditions and improve error handling.
The async conversion is good, but there are a few concerns to address:
- Add protection against race conditions:
const startRecording = async () => {
+ if (isRecording) return;
try {
+ setIsRecording(true); // Set early to prevent multiple calls
const newRecorder = await requestRecorder();
setRecorder(newRecorder);
setMicrophoneAccess(true);
- setIsRecording(true);
} catch (error) {
+ setIsRecording(false);
setMicrophoneAccess(false);
- throw new Error("Microphone access denied");
+ throw error; // Preserve the original error for better debugging
}
};
- Consider adding cleanup on component unmount to prevent memory leaks:
src/Utils/useVoiceRecorder.ts (2)
121-130
: LGTM! Well-structured hook return value.
The hook exports a clean interface with all necessary controls and state variables.
133-141
: Verify iOS audio recording functionality.
The implementation includes iOS-specific constraints, but we should verify if this fully resolves the iPhone issues reported in #8227.
✅ Verification successful
Based on the search results from useVoiceRecorder.ts, I can now generate the final response:
iOS audio recording implementation appears complete and well-handled
The implementation includes all necessary iOS Safari-specific handling:
- Proper audio constraints (sampleRate: 44100, channelCount: 1)
- Fallback MIME type handling (webm → mp4) for Safari compatibility
- Essential audio quality settings (echoCancellation and noiseSuppression)
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for any remaining iOS-specific workarounds or issues in the codebase
# Search for iOS-related audio recording issues or workarounds
echo "Searching for iOS-specific audio handling..."
rg -i "ios|safari|iphone" --type ts --type tsx
# Search for MediaRecorder configurations that might affect iOS
echo "Checking MediaRecorder configurations..."
rg "MediaRecorder|getUserMedia|audio.*constraints" --type ts --type tsx
Length of output: 368
Script:
#!/bin/bash
# Let's try with correct file type flags and more focused search patterns
# Search for iOS/Safari related audio handling
echo "Searching for iOS-specific audio handling..."
rg -i "ios|safari|iphone" -t typescript
# Search for MediaRecorder and audio constraints
echo "Checking MediaRecorder and audio constraints..."
rg "MediaRecorder|getUserMedia|audio.*constraints" -t typescript
# Search specifically in useVoiceRecorder.ts
echo "Checking useVoiceRecorder.ts specifically..."
rg -A 5 "constraints|MediaRecorder" src/Utils/useVoiceRecorder.ts
# Look for any related test files
echo "Looking for related test files..."
fd -e test.ts -e spec.ts voice
Length of output: 1654
👋 Hi, @shivankacker, This message is automatically generated by prince-chrismc/label-merge-conflicts-action so don't hesitate to report issues/improvements there. |
Will merge conflicts once PR is tested and approved |
@shivankacker can you clear the merge conflict, to get it ready for review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (30)
cypress/e2e/patient_spec/PatientBedManagement.cy.ts (1)
Line range hint
6-54
: Consider enhancing test robustness and coverage.While the test implementation is solid, consider these improvements:
- Add data cleanup in afterEach to ensure test isolation
- Add error handling for failed bed assignments
- Add test cases for edge scenarios:
- Attempting to assign an already occupied bed
- Handling network errors during bed assignment
- Verifying bed status updates in real-time
Here's a suggested enhancement:
afterEach(() => { cy.saveLocalStorage(); + // Clean up assigned beds + cy.intercept('POST', '**/bed/clear/').as('clearBed'); + patientPage.visitPatient(switchPatientOne); + patientLogupdate.clickSwitchBed(); + cy.get('#clear-button').click(); + cy.wait('@clearBed'); + + patientPage.visitPatient(switchPatientTwo); + patientLogupdate.clickSwitchBed(); + cy.get('#clear-button').click(); + cy.wait('@clearBed'); }); +it("Should handle bed assignment failures gracefully", () => { + // Simulate network error + cy.intercept('POST', '**/bed/assign/', { + statusCode: 500, + body: { detail: 'Internal Server Error' } + }).as('failedAssignment'); + + patientPage.visitPatient(switchPatientOne); + patientLogupdate.clickSwitchBed(); + patientLogupdate.selectBed(switchBedOne); + + // Verify error handling + cy.wait('@failedAssignment'); + cy.verifyNotification("Failed to assign bed"); +});cypress/e2e/patient_spec/PatientDoctorConnect.cy.ts (2)
Line range hint
1-14
: Consider moving test data to fixtures.The test data (patient name, user roles) should be moved to a fixture file for better maintainability and reusability. This would make it easier to update test data and share it across different test files.
Example implementation:
// cypress/fixtures/doctor-connect.json { "patientName": "Dummy Patient 11", "users": { "doctor": "Dev Doctor", "nurse": "Dev Staff", "teleIcuDoctor": "Dev Doctor Two" } } // In test file let testData: any; before(() => { cy.fixture('doctor-connect').then((data) => { testData = data; }); loginPage.loginAsDistrictAdmin(); cy.saveLocalStorage(); });
Line range hint
29-54
: Split the test case into multiple focused scenarios.The current test case violates the single responsibility principle by testing multiple features (user visibility, copy functionality, icon presence, and sorting) in one test. This makes it harder to debug failures and maintain the test.
Consider splitting into these focused test cases:
it("should display users under correct sections", () => { patientPage.visitPatient(testData.patientName); doctorconnect.clickDoctorConnectButton(); cy.verifyContentPresence("#doctor-connect-home-doctor", [testData.users.doctor]); cy.verifyContentPresence("#doctor-connect-home-nurse", [testData.users.nurse]); cy.verifyContentPresence("#doctor-connect-remote-doctor", [testData.users.teleIcuDoctor]); }); it("should copy phone number correctly", () => { patientPage.visitPatient(testData.patientName); doctorconnect.clickDoctorConnectButton(); doctorconnect.CopyFunctionTrigger(); doctorconnect.clickCopyPhoneNumber("#doctor-connect-home-doctor", testData.users.doctor); doctorconnect.verifyCopiedContent(); }); it("should display communication icons", () => { patientPage.visitPatient(testData.patientName); doctorconnect.clickDoctorConnectButton(); doctorconnect.verifyIconVisible("#whatsapp-icon"); doctorconnect.verifyIconVisible("#phone-icon"); }); it("should filter users by role correctly", () => { patientPage.visitPatient(testData.patientName); doctorconnect.clickDoctorConnectButton(); doctorconnect.clickUsersSortBy("Doctor"); cy.verifyContentPresence("#doctor-connect-home-doctor", [testData.users.doctor]); doctorconnect.clickUsersSortBy("Nurse"); cy.verifyContentPresence("#doctor-connect-home-nurse", [testData.users.nurse]); doctorconnect.clickUsersSortBy("TeleICU Doctor"); cy.verifyContentPresence("#doctor-connect-remote-doctor", [testData.users.teleIcuDoctor]); });cypress/e2e/resource_spec/ResourcesHomepage.cy.ts (4)
Line range hint
5-11
: Consider moving test data to a separate constants file.The phone number constant could be moved to a shared test data file to maintain consistency across tests and make updates easier.
- const phone_number = "9999999999";
Create a new file
cypress/fixtures/testData.ts
:export const TEST_PHONE_NUMBER = "9999999999";
Line range hint
39-63
: Enhance resource request creation test reliability.The resource request creation test could be flaky due to the search dependency. Consider these improvements:
- Add retry ability for the search
- Add more specific assertions for the facility search results
- Include error scenarios
it("Create a resource request", () => { cy.visit("/facility"); - cy.get("#search").click().type("dummy facility 40"); + cy.get("#search") + .click() + .type("dummy facility 40") + .should("have.value", "dummy facility 40"); + cy.intercept("GET", "**/api/v1/facility/**").as("loadFacilities"); - cy.get("#facility-details").click(); + cy.get("#facility-details") + .should("be.visible") + .and("contain.text", "dummy facility 40") + .click(); + cy.wait("@loadFacilities").its("response.statusCode").should("eq", 200); + + // Verify facility details are loaded + cy.get("body").should("not.contain.text", "Loading...");
Line range hint
1-89
: Consider adding more comprehensive test coverage.The test suite could benefit from additional scenarios:
- Error handling cases (e.g., network errors, validation errors)
- Accessibility checks for the resource page
- Verification of UI elements and their states
Example additions:
it("Should handle network errors gracefully", () => { cy.intercept("GET", "**/api/v1/facility/**", { statusCode: 500, body: { message: "Internal Server Error" } }).as("failedRequest"); // Test error handling }); it("Should meet accessibility standards", () => { cy.visit("/resource"); cy.injectAxe(); cy.checkA11y(); });
Line range hint
65-77
: Verify resource status updates more thoroughly.The status update test should verify:
- Available status options
- Status change reflection in UI
- API payload correctness
it("Update the status of resource", () => { cy.visit(createdResource); + // Verify available status options + const expectedStatuses = ["APPROVED", "REJECTED", "PENDING"]; resourcePage.clickUpdateStatus(); + cy.get("[data-testid='status-options']") + .should("be.visible") + .find("option") + .should("have.length", expectedStatuses.length) + .each(($el, index) => { + expect($el.text()).to.equal(expectedStatuses[index]); + }); + + // Intercept status update request + cy.intercept("PATCH", "**/api/v1/resource/**").as("updateStatus"); resourcePage.updateStatus("APPROVED"); resourcePage.clickSubmitButton(); + + // Verify API request + cy.wait("@updateStatus").then((interception) => { + expect(interception.request.body.status).to.equal("APPROVED"); + }); + + // Verify UI update + cy.get("[data-testid='resource-status']") + .should("be.visible") + .and("contain.text", "APPROVED"); + resourcePage.verifySuccessNotification( "Resource request updated successfully", ); });cypress/e2e/facility_spec/FacilityInventory.cy.ts (2)
1-4
: Consider implementing a consistent import ordering pattern.While moving the
LoginPage
import is harmless, consider organizing imports consistently (e.g., alphabetically) to improve maintainability.-import FacilityPage from "../../pageobject/Facility/FacilityCreation"; -import FacilityHome from "../../pageobject/Facility/FacilityHome"; -import LoginPage from "../../pageobject/Login/LoginPage"; +import FacilityHome from "../../pageobject/Facility/FacilityHome"; +import FacilityPage from "../../pageobject/Facility/FacilityCreation"; +import LoginPage from "../../pageobject/Login/LoginPage";
Line range hint
28-94
: Improve test reliability by following Cypress best practices.Several improvements could make these tests more robust:
- Replace hard-coded
cy.wait(3000)
with proper Cypress commands:-cy.wait(3000); +cy.get('#element').should('be.visible');
- Standardize success message verification:
-facilityPage.verifySuccessNotification("Inventory created successfully"); -facilityPage.verifySuccessNotification("Minimum quantiy updated successfully"); +const successMessages = { + inventoryCreated: "Inventory created successfully", + minimumQuantityUpdated: "Minimum quantiy updated successfully" +}; +facilityPage.verifySuccessNotification(successMessages.inventoryCreated);
- Make element visibility checks more robust:
-if ($body.find("#update-minimum-quantity").is(":visible")) { +cy.get('body').then(($body) => { + const updateBtn = $body.find("#update-minimum-quantity"); + if (updateBtn.length && updateBtn.is(":visible")) {src/Utils/useSegmentedRecorder.ts (2)
11-11
: Remove redundant comment.The variable name
microphoneAccess
is self-explanatory, making the inline comment "New state" unnecessary.- const [microphoneAccess, setMicrophoneAccess] = useState(false); // New state + const [microphoneAccess, setMicrophoneAccess] = useState(false);
130-130
: Remove redundant comment.The inline comment "Return microphoneAccess" is unnecessary as the code is self-documenting.
- microphoneAccess, // Return microphoneAccess + microphoneAccess,cypress/e2e/patient_spec/PatientFileUpload.ts (5)
Line range hint
4-28
: Consider extracting test constants to a separate file.The test setup follows good practices with page objects and proper test isolation. However, the test constants (patient names, file names) could be moved to a separate configuration file for better maintainability and reuse across other test files.
+ // testData/patients.ts + export const TEST_PATIENTS = { + PATIENT_ONE: "Dummy Patient 3", + PATIENT_TWO: "Dummy Patient 4", + PATIENT_THREE: "Dummy Patient 5" + }; + + export const TEST_FILES = { + AUDIO_NAME: "cypress audio", + FILE_NAME: "cypress name", + MODIFIED_NAME: "cypress modified name" + };
Line range hint
30-46
: Add verification for audio file format and content.The audio recording test should verify the format and basic properties of the recorded audio file. Also consider adding error scenarios for when audio recording fails.
it("Record an Audio and download the file", () => { patientPage.visitPatient(patientNameOne); visitPatientFileUploadSection.call(patientFileUpload); patientFileUpload.recordAudio(); patientFileUpload.typeAudioName(cypressAudioName); patientFileUpload.clickUploadAudioFile(); cy.verifyNotification("File Uploaded Successfully"); patientFileUpload.verifyUploadFilePresence(cypressAudioName); cy.get("button").contains("Download").click(); cy.verifyNotification("Downloading file..."); + // Verify audio file properties + cy.get('[data-testid="audio-player"]').should('have.attr', 'src') + .and('match', /^blob:http/); + // Verify file download + cy.readFile('cypress/downloads/' + cypressAudioName) + .should('exist'); });
Line range hint
48-64
: Add error scenarios for file upload test.The file upload test should include scenarios for invalid file types, large files, and network failures. Also verify the archived file's accessibility state.
it("Upload a File and archive it", () => { patientPage.visitPatient(patientNameTwo); visitPatientFileUploadSection.call(patientFileUpload); + // Test invalid file type + patientFileUpload.uploadFile('invalid.exe'); + cy.verifyNotification("Invalid file type"); + + // Test file size limit + patientFileUpload.uploadFile('large.pdf'); + cy.verifyNotification("File size exceeds limit"); + patientFileUpload.uploadFile(); patientFileUpload.typeFileName(cypressFileName); patientFileUpload.clickUploadFile(); cy.verifyNotification("File Uploaded Successfully"); cy.closeNotification(); patientFileUpload.verifyUploadFilePresence(cypressFileName); patientFileUpload.archiveFile(); patientFileUpload.clickSaveArchiveFile(); cy.verifyNotification("File archived successfully"); patientFileUpload.verifyArchiveFile(cypressFileName); + // Verify archived file is not editable + patientFileUpload.verifyFileRenameOption(false); });
Line range hint
66-115
: Enhance user permission test coverage.The permission test should verify additional operations like file deletion and archival permissions. Also consider testing with more user roles and edge cases.
it("User-level Based Permission for File Modification", () => { loginPage.login("dummynurse1", "Coronasafe@123"); cy.reload(); patientPage.visitPatient(patientNameThree); visitPatientFileUploadSection.call(patientFileUpload); patientFileUpload.uploadFile(); patientFileUpload.typeFileName(cypressFileName); patientFileUpload.clickUploadFile(); cy.verifyNotification("File Uploaded Successfully"); cy.closeNotification(); patientFileUpload.verifyUploadFilePresence(cypressFileName); + // Verify additional permissions + patientFileUpload.verifyDeleteOption(false); + patientFileUpload.verifyArchiveOption(false); + // ... existing permission checks ... + + // Test with additional user roles + loginPage.login("doctor1", "Coronasafe@123"); + cy.reload(); + patientFileUpload.verifyUploadFilePresence(cypressFileName); + patientFileUpload.verifyFileRenameOption(true); + patientFileUpload.verifyDeleteOption(true); + patientFileUpload.verifyArchiveOption(true); });
Line range hint
123-131
: Add cross-browser testing configuration.The tests should be configured to run across different browsers to ensure consistent behavior. Also consider adding parallel test execution for better performance.
+ // cypress.config.ts + export default { + e2e: { + browsers: ['chrome', 'firefox', 'edge'], + // Enable parallel execution + parallel: true, + // Group similar tests + testIsolation: false + } + };cypress/e2e/assets_spec/AssetsManage.cy.ts (3)
Line range hint
1-120
: Consider enhancing test maintainability and reliability.While reviewing the entire test suite, I noticed some opportunities for improvement:
Test data management:
- Hard-coded values like "Dummy Facility 40" should be moved to test fixtures
- Date manipulation could be centralized in a helper
Test isolation:
- Consider using
cy.intercept()
to mock network requests- Add cleanup in
afterEach
to ensure consistent stateError handling:
- Add timeout configurations for slow operations
- Include error assertions for negative scenarios
Example implementation for test data management:
// fixtures/asset-data.json { "facility": { "name": "Dummy Facility 40" }, "asset": { "name": "Dummy Camera", "initialLocation": "Camera Location", "newLocation": "Dummy Location 1" } } // support/commands.ts Cypress.Commands.add('loadAssetTestData', () => { cy.fixture('asset-data.json').as('testData'); }); // Example usage in test beforeEach(() => { cy.loadAssetTestData(); // ... other setup }); it('Verify Asset Warranty Expiry Label', function() { const { asset } = this.testData; assetSearchPage.typeSearchKeyword(asset.name); // ... rest of the test });
Line range hint
8-13
: Move date utility to a dedicated helper file.The
addDaysToDate
function should be moved to a shared helper file for reusability across test files.// support/helpers/date.ts export const addDaysToDate = (numberOfDays: number): string => { const inputDate = new Date(); inputDate.setDate(inputDate.getDate() + numberOfDays); return inputDate.toISOString().split('T')[0]; }; // Import in test file import { addDaysToDate } from '../../support/helpers/date';
Line range hint
36-65
: Enhance warranty expiry test with data-driven approach.The warranty expiry test could be more maintainable using a data-driven approach.
const warrantyTestCases = [ { days: 100, expectedLabel: '' }, // > 3 months { days: 80, expectedLabel: '3 months' }, // < 3 months { days: 20, expectedLabel: '1 month' }, // < 1 month { days: 100, expectedLabel: '' } // Reset case ]; it('Verify Asset Warranty Expiry Label', () => { assetSearchPage.typeSearchKeyword(assetname); assetSearchPage.pressEnter(); assetSearchPage.verifyBadgeContent(assetname); assetSearchPage.clickAssetByName(assetname); warrantyTestCases.forEach(({ days, expectedLabel }) => { assetPage.clickupdatedetailbutton(); assetPage.scrollintoWarrantyDetails(); assetPage.enterWarrantyExpiryDate(addDaysToDate(days)); assetPage.clickassetupdatebutton(); assetPage.verifyWarrantyExpiryLabel(expectedLabel); }); });cypress/e2e/facility_spec/FacilityHomepage.cy.ts (1)
Line range hint
89-97
: Consider enhancing pagination test coverage.While the basic pagination tests are good, consider adding test cases for:
- Edge cases (first/last page)
- Items per page changes
- Total items count verification
- Page number validation
Example enhancement:
it("handles pagination edge cases", () => { assetPagination.navigateToLastPage(); assetPagination.verifyNextButtonDisabled(); assetPagination.navigateToFirstPage(); assetPagination.verifyPreviousButtonDisabled(); assetPagination.changeItemsPerPage(50); assetPagination.verifyItemsPerPageApplied(50); });cypress/e2e/users_spec/UsersCreation.cy.ts (4)
Line range hint
1-200
: Consider enhancing test coverage for iPhone-specific scenarios.Given that Issue #8227 mentions iPhone-specific malfunctions, it would be valuable to add test cases that specifically verify the application's behavior on iPhone viewports.
Consider adding:
it("should work correctly on iPhone viewport", () => { cy.viewport('iphone-x'); // Test user creation flow // Test profile updates // Verify any audio-related functionality });
Line range hint
19-31
: Consider extracting themakeid
utility function.The
makeid
function is a utility that could be reused across other test files. Consider moving it to a shared utilities file.Move this to
cypress/pageobject/utils/constants.ts
:export const makeid = (length: number) => { let result = ""; const characters = "abcdefghijklmnopqrstuvwxyz0123456789"; const charactersLength = characters.length; for (let i = 0; i < length; i++) { result += characters.charAt(Math.floor(Math.random() * charactersLength)); } return result; };
Line range hint
32-35
: Consider using test data management for user lists.The hardcoded array of users could be better managed through test data fixtures.
Consider creating a fixture file
cypress/fixtures/users.json
:{ "alreadyLinkedUsers": ["devdoctor", "devstaff2", "devdistrictadmin"] }Then import it in the test:
let users; before(() => { cy.fixture('users').then((data) => { users = data; }); });
Line range hint
36-50
: Consider using an enum for error messages.The error message arrays could be better managed using TypeScript enums or constants in a separate file.
Consider creating
cypress/constants/errorMessages.ts
:export enum UserCreationErrors { USER_TYPE = "Please select the User Type", PHONE_NUMBER = "Please enter valid phone number", // ... other messages } export enum ProfileErrors { REQUIRED = "This field is required", PHONE_NUMBER = "Please enter valid phone number" }cypress/e2e/patient_spec/PatientRegistration.cy.ts (4)
Line range hint
9-31
: Consider improving date handling and age calculation.The current implementation could be enhanced for better maintainability and robustness:
- The hardcoded year value could lead to maintenance issues
- Date calculations could benefit from a more robust approach
Consider this improvement:
-const yearOfBirth = "2001"; +const TEST_YEAR_OF_BIRTH = "2001"; // Make the constant name more descriptive const calculateAge = () => { - const currentYear = new Date().getFullYear(); - return currentYear - parseInt(yearOfBirth); + const today = new Date(); + const birthDate = new Date(`${TEST_YEAR_OF_BIRTH}-01-01`); + let age = today.getFullYear() - birthDate.getFullYear(); + const monthDiff = today.getMonth() - birthDate.getMonth(); + if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) { + age--; + } + return age; };
Line range hint
32-329
: Enhance test organization and error coverage.While the test cases are comprehensive, consider these improvements:
- Group test data setup into a separate fixture file
- Add negative test cases for form validation
- Add assertions for error states in the form fields
Create a new fixture file
cypress/fixtures/patient-registration.json
:{ "validPatient": { "name": "Patient With No Consultation", "gender": "Male", "updatedGender": "Female", "address": "Test Patient Address", // ... other test data }, "invalidPatient": { "name": "", // for validation testing "phone": "invalid", // ... invalid test data } }Then refactor the tests to use this fixture:
describe("Patient Creation with consultation", () => { let testData; before(() => { cy.fixture('patient-registration.json').then((data) => { testData = data; }); // ... existing setup }); // Add negative test case it("should show validation errors for invalid input", () => { patientPage.createPatient(); patientPage.selectFacility(testData.validPatient.facility); patientPage.typePatientName(testData.invalidPatient.name); patientPage.typePatientPhoneNumber(testData.invalidPatient.phone); patientPage.clickCreatePatient(); // Assert validation errors cy.get('[data-testid="name-error"]').should('be.visible'); cy.get('[data-testid="phone-error"]').should('be.visible'); }); // ... existing test cases using testData });
Line range hint
276-329
: Enhance transfer test error scenarios.The transfer test could be expanded to cover more error cases:
- Transfer with missing required fields
- Transfer with invalid patient data
- Network error handling
Add these test cases:
it("should handle transfer errors appropriately", () => { // Test missing required fields patientPage.createPatient(); patientPage.selectFacility(patientTransferFacility); patientTransfer.clickTransferSubmitButton(); cy.get('[data-testid="transfer-error"]').should('be.visible'); // Test network error cy.intercept('POST', '/api/transfer', { statusCode: 500, body: { message: 'Internal Server Error' } }); // ... complete the transfer flow cy.get('[data-testid="error-notification"]') .should('contain', 'Failed to transfer patient'); });
Line range hint
32-329
: Add tests for Scribe integration.Based on the PR objectives of migrating Scribe to CARE App, consider adding test cases for:
- Scribe interaction with existing form data
- Audio upload functionality (especially for iPhone)
- Integration between Scribe and patient registration
Would you like me to help create test cases for these scenarios? I can provide a detailed implementation that covers:
- Scribe awareness of pre-filled form data
- Audio upload validation
- Cross-browser compatibility tests
public/locale/en.json (2)
254-255
: Consider adding more voice-related localization keys for better UX.The voice-related translations are clear and user-friendly. However, consider adding these additional keys to enhance the user experience:
- Error states (e.g., "voice_recognition_failed", "network_error_during_recording")
- Accessibility labels (e.g., "voice_record_button_aria_label")
- Progress indicators (e.g., "processing_voice_input")
Also applies to: 490-491, 707-707, 1021-1021, 1078-1078, 1095-1096, 1160-1160, 1164-1164, 1191-1192, 1274-1274
334-334
: Make the autofilled fields message more descriptive.The "autofilled_fields" message could be more specific to provide better context to users.
Consider using a more descriptive message like:
- "autofilled_fields": "Autofilled Fields", + "autofilled_fields": "Fields automatically filled from your health records",
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
⛔ Files ignored due to path filters (1)
package-lock.json
is excluded by!**/package-lock.json
📒 Files selected for processing (25)
cypress/e2e/assets_spec/AssetHomepage.cy.ts
(1 hunks)cypress/e2e/assets_spec/AssetsCreation.cy.ts
(1 hunks)cypress/e2e/assets_spec/AssetsManage.cy.ts
(1 hunks)cypress/e2e/facility_spec/FacilityCreation.cy.ts
(1 hunks)cypress/e2e/facility_spec/FacilityHomepage.cy.ts
(1 hunks)cypress/e2e/facility_spec/FacilityInventory.cy.ts
(1 hunks)cypress/e2e/facility_spec/FacilityManage.cy.ts
(1 hunks)cypress/e2e/patient_spec/PatientBedManagement.cy.ts
(1 hunks)cypress/e2e/patient_spec/PatientConsultationCreation.cy.ts
(1 hunks)cypress/e2e/patient_spec/PatientDoctorConnect.cy.ts
(1 hunks)cypress/e2e/patient_spec/PatientFileUpload.ts
(1 hunks)cypress/e2e/patient_spec/PatientLogUpdate.cy.ts
(1 hunks)cypress/e2e/patient_spec/PatientPrescription.cy.ts
(1 hunks)cypress/e2e/patient_spec/PatientRegistration.cy.ts
(1 hunks)cypress/e2e/resource_spec/ResourcesHomepage.cy.ts
(1 hunks)cypress/e2e/users_spec/UsersCreation.cy.ts
(1 hunks)cypress/e2e/users_spec/UsersManage.cy.ts
(1 hunks)public/locale/en.json
(12 hunks)src/Routers/AppRouter.tsx
(1 hunks)src/Utils/request/api.tsx
(0 hunks)src/Utils/useSegmentedRecorder.ts
(5 hunks)src/components/Common/BloodPressureFormField.tsx
(1 hunks)src/components/Common/DateInputV2.tsx
(4 hunks)src/components/Common/TemperatureFormField.tsx
(2 hunks)src/components/Common/prescription-builder/PrescriptionDropdown.tsx
(1 hunks)
💤 Files with no reviewable changes (1)
- src/Utils/request/api.tsx
✅ Files skipped from review due to trivial changes (7)
- cypress/e2e/assets_spec/AssetHomepage.cy.ts
- cypress/e2e/assets_spec/AssetsCreation.cy.ts
- cypress/e2e/facility_spec/FacilityCreation.cy.ts
- cypress/e2e/facility_spec/FacilityManage.cy.ts
- cypress/e2e/patient_spec/PatientConsultationCreation.cy.ts
- cypress/e2e/patient_spec/PatientLogUpdate.cy.ts
- cypress/e2e/patient_spec/PatientPrescription.cy.ts
🚧 Files skipped from review as they are similar to previous changes (5)
- src/Routers/AppRouter.tsx
- src/components/Common/BloodPressureFormField.tsx
- src/components/Common/DateInputV2.tsx
- src/components/Common/TemperatureFormField.tsx
- src/components/Common/prescription-builder/PrescriptionDropdown.tsx
🔇 Additional comments (14)
cypress/e2e/patient_spec/PatientBedManagement.cy.ts (1)
1-4
: LGTM! Import changes align with the migration.
The addition of PatientConsultationPage
import is consistent with the PR's objective of migrating Scribe functionality.
cypress/e2e/patient_spec/PatientDoctorConnect.cy.ts (2)
Line range hint 16-28
: LGTM! Well-structured test setup.
The test lifecycle hooks are properly implemented with good practices:
- Login state persistence using localStorage
- Proper cleanup of filters before each test
- Clear URL verification
Line range hint 56-58
: LGTM! Proper test cleanup.
The afterEach hook correctly persists the localStorage state for subsequent tests.
cypress/e2e/resource_spec/ResourcesHomepage.cy.ts (1)
1-3
: LGTM! Import organization follows best practices.
The imports are now properly organized at the top of the file, improving code readability.
cypress/e2e/facility_spec/FacilityInventory.cy.ts (1)
Line range hint 5-27
: Verify test stability after Scribe migration.
Since this PR involves migrating Scribe to a CARE app, please ensure these inventory management tests remain stable after the migration. Consider:
- Running these tests against both old and new environments
- Verifying that the page objects and selectors remain valid
- Documenting any environment-specific setup required for these tests
src/Utils/useSegmentedRecorder.ts (2)
Line range hint 29-41
: Verify microphone access handling on iOS Safari.
Given the reported issues with iPhone (Issue #8227), please ensure this implementation works correctly on iOS Safari. Consider:
- iOS Safari requires user interaction before allowing media access
- Audio recording might need specific handling for iOS compatibility
#!/bin/bash
# Search for iOS-specific handling in the codebase
rg -i "ios|safari|useragent" --type ts --type tsx
104-113
:
Enhance error handling in startRecording.
The current implementation has several issues that need attention:
- The error message isn't internationalized
- The recorder state should be cleaned up on error
- The error handling at call sites might need to be documented
Apply these improvements:
const startRecording = async () => {
try {
const newRecorder = await requestRecorder();
setRecorder(newRecorder);
setMicrophoneAccess(true);
setIsRecording(true);
} catch (error) {
setMicrophoneAccess(false);
+ setRecorder(null);
+ setIsRecording(false);
- throw new Error("Microphone access denied");
+ throw new Error(t("audio__permission_denied"));
}
};
cypress/e2e/assets_spec/AssetsManage.cy.ts (1)
2-2
: LGTM! Import reordering looks good.
The reordering of imports maintains code organization without affecting functionality.
Also applies to: 5-5
cypress/e2e/facility_spec/FacilityHomepage.cy.ts (2)
2-5
: LGTM! Import changes are clean and purposeful.
The addition of AssetPagination and reorganization of imports align well with the test file's functionality.
Line range hint 9-168
: Test structure follows best practices, but consider adding Scribe-related tests.
The test suite is well-structured using the page object pattern and covers core facility homepage functionality comprehensively. However, given that this PR involves migrating Scribe functionality, consider adding test coverage for:
- Scribe integration with facility data
- Audio processing functionality (especially for iPhone devices, ref: Issue Scribe is malfunctioning in iphone #8227)
- Form data awareness (ref: Issue Make Scribe Aware of already present form data #8134)
Let's verify if there are any Scribe-related tests in the codebase:
cypress/e2e/users_spec/UsersManage.cy.ts (2)
4-4
: LGTM! Import change aligns with module organization.
The addition of UserPage
import from UserSearch
module follows good separation of concerns, keeping page object models organized by functionality.
Line range hint 1-168
: Verify test coverage for Scribe migration.
The test suite thoroughly covers user management operations but should be verified against the new Scribe CARE app integration.
Let's check for any Scribe-related test coverage:
Consider adding specific test cases to verify:
- User permissions interaction with the new Scribe CARE app
- Integration points between user management and Scribe functionality
- Data consistency when users interact with Scribe features
cypress/e2e/users_spec/UsersCreation.cy.ts (1)
3-3
: LGTM! Import statements are properly organized.
The imports are well-structured and the addition of generatePhoneNumber
aligns with its usage in the test cases.
Also applies to: 5-5, 8-8
cypress/e2e/patient_spec/PatientRegistration.cy.ts (1)
1-7
: LGTM! Well-organized imports.
The new imports for PatientTransfer
and generatePhoneNumber
are appropriately added and align with their usage in the test cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Outside diff range and nitpick comments (7)
src/CAREUI/interactive/KeyboardShortcut.tsx (1)
81-98
: Consider improving accessibility and error handling.While the implementation is solid, consider these enhancements:
- Add error handling for invalid shortcut keys
- Improve screen reader support
- Consider mobile visibility strategy
export function KeyboardShortcutKey(props: { shortcut: string[]; useShortKeys?: boolean; }) { const { shortcut, useShortKeys } = props; + // Validate shortcut keys + const validShortcuts = shortcut.every(key => + key in SHORTCUT_KEY_MAP || key.length > 0 + ); + + if (!validShortcuts) { + console.warn('Invalid shortcut keys provided:', shortcut); + return null; + } return ( - <div className="hidden shrink-0 items-center md:flex"> + <div + className="hidden shrink-0 items-center md:flex" + role="group" + aria-label="Keyboard shortcuts" + > {shortcut.map((key, idx, keys) => ( <Fragment key={idx}> <kbd + aria-label={`Press ${SHORTCUT_KEY_MAP[key] || key}`} className="relative z-10 flex h-6 min-w-6 shrink-0 items-center justify-center rounded-md border border-b-4 border-secondary-400 bg-secondary-100 px-2 text-xs text-black" >src/Utils/useVoiceRecorder.ts (6)
6-10
: Consider using a single state object for related states.The hook uses multiple independent state variables that are conceptually related. Consider combining them into a single state object to make state updates more atomic and prevent potential race conditions.
- const [audioURL, setAudioURL] = useState(""); - const [isRecording, setIsRecording] = useState(false); - const [recorder, setRecorder] = useState<MediaRecorder | null>(null); - const [blob, setBlob] = useState<Blob | null>(null); - const [waveform, setWaveform] = useState<number[]>([]); // Decibel waveform + const [state, setState] = useState({ + audioURL: "", + isRecording: false, + recorder: null as MediaRecorder | null, + blob: null as Blob | null, + waveform: [] as number[], + });
16-20
: Add explanatory comment for the recorder reset logic.The purpose of this effect is not immediately clear. Consider adding a comment explaining why the recorder needs to be reset when recording stops and an audio URL exists.
useEffect(() => { + // Reset recorder after successful recording to free up resources and prepare for next recording if (!isRecording && recorder && audioURL) { setRecorder(null); } }, [isRecording, recorder, audioURL]);
28-38
: Enhance error handling with specific error types.The error handling could be more specific to help users understand and resolve issues better. Consider categorizing errors based on their type (permission denied, device not found, etc.).
} catch (error) { + let errorMessage = "Please grant microphone permission to record audio."; + if (error instanceof DOMException) { + switch (error.name) { + case 'NotAllowedError': + errorMessage = "Microphone access was denied. Please allow access in your browser settings."; + break; + case 'NotFoundError': + errorMessage = "No microphone found. Please connect a microphone and try again."; + break; + case 'NotReadableError': + errorMessage = "Could not access your microphone. Please check if it's properly connected."; + break; + default: + errorMessage = `Microphone error: ${error.message}`; + } + } Notify.Error({ - msg: error instanceof Error - ? error.message - : "Please grant microphone permission to record audio.", + msg: errorMessage, });
107-120
: Add TypeScript return types to control functions.The control functions lack explicit return type annotations. Adding them would improve type safety and documentation.
- const startRecording = () => { + const startRecording = (): void => { setIsRecording(true); }; - const stopRecording = () => { + const stopRecording = (): void => { setIsRecording(false); setWaveform([]); }; - const resetRecording = () => { + const resetRecording = (): void => { setAudioURL(""); setBlob(null); setWaveform([]); };
122-131
: Add explicit return type interface.Define an interface for the hook's return value to improve type safety and documentation.
+interface VoiceRecorderHook { + audioURL: string; + isRecording: boolean; + startRecording: () => void; + stopRecording: () => void; + blob: Blob | null; + waveform: number[]; + resetRecording: () => void; +} -const useVoiceRecorder = (handleMicPermission: (allowed: boolean) => void) => { +const useVoiceRecorder = (handleMicPermission: (allowed: boolean) => void): VoiceRecorderHook => {
133-157
: Add comprehensive JSDoc documentation.The
requestRecorder
function would benefit from detailed JSDoc documentation explaining its purpose, parameters, return value, and possible errors.+/** + * Requests access to the user's microphone and creates a MediaRecorder instance. + * Includes special handling for iOS Safari compatibility. + * + * @throws {Error} When microphone access is denied or initialization fails + * @returns {Promise<MediaRecorder>} A configured MediaRecorder instance + */ async function requestRecorder() {
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (2)
src/CAREUI/interactive/KeyboardShortcut.tsx
(2 hunks)src/Utils/useVoiceRecorder.ts
(1 hunks)
🔇 Additional comments (2)
src/CAREUI/interactive/KeyboardShortcut.tsx (2)
1-1
: LGTM! Import changes are well-structured.
The import changes follow best practices:
- Using
Fragment
from 'react/jsx-runtime' is optimal for performance - Relative import path for utils improves maintainability
Also applies to: 4-4
75-78
: LGTM! Well-structured component with clear props interface.
The component has a clear single responsibility and good TypeScript typing.
@nihal467 resolved merge conflicts, deploy preview failing due to cache issue, nothing else. |
👋 Hi, @shivankacker, This message is automatically generated by prince-chrismc/label-merge-conflicts-action so don't hesitate to report issues/improvements there. |
Proposed Changes
Moves Scribe to https://github.com/ohcnetwork/care_scribe_fe
Screen.Recording.2024-11-06.at.12.34.23.PM.mov
Requires care_scribe backend plugin pointing to ohcnetwork/care_scribe#12
Requires the care_scribe_fe frontend appp. Add that by updating your env to include
REACT_ENABLED_APPS="ohcnetwork/care_livekit_fe,ohcnetwork/care_scribe_fe"
NOTE: Cannot update non arbitrary fields like symptoms, diagnoses for now.
@ohcnetwork/care-fe-code-reviewers
Merge Checklist
Summary by CodeRabbit
Release Notes
New Features
Bug Fixes
Chores