[Customer Portal][FE][Web] Implement Error States for Project Hub and Refactor Test Suite - #130
Conversation
Add a new Vitest test file for ErrorStateIcon verifying the component renders an SVG, has the expected viewBox and aria-hidden attributes, and correctly forwards SVG props (e.g. data-testid). Uses @testing-library/react for DOM assertions.
Add a mock for ErrorStateIcon and rename the test to 'should render error state when isError is true'. Replace previous assertions for tooltip/No Projects Yet with checks for the error-state-icon and specific error messages, while retaining the logger error assertion.
Introduce ErrorStateIcon.tsx — a React component that renders a detailed SVG illustration for full-page error states (used when data fails to load, e.g. Project Hub). The component accepts SVGProps<SVGSVGElement>, sets accessibility attributes (aria-hidden, focusable={false}), and includes the project license header. Adds the asset to apps/customer-portal/webapp/src/components/common/error-state.
Replace the previous error indicator with a centered ErrorStateIcon and enhanced error layout for the ProjectHub page. Add TriangleAlert (styled with error color) alongside FolderOpen as a conditional icon, update header and subtitle copy when an error occurs, and adjust spacing/padding for the error state. Also update imports to reflect ErrorStateIcon and TriangleAlert and remove the old ErrorIndicator import.
📝 WalkthroughWalkthroughAdds two SVG React components (EmptyIcon, ErrorStateIcon), integrates them into ProjectHub for empty/error rendering, and updates tests and mocks to cover the new icons and loader behavior. Changes
Sequence Diagram(s)sequenceDiagram
participant User as "User"
participant ProjectHub as "ProjectHub\n(component)"
participant Loader as "LoaderContext\n(useLoader)"
participant API as "Projects API"
participant EmptyIcon as "EmptyIcon\n(component)"
participant ErrorIcon as "ErrorStateIcon\n(component)"
Note over ProjectHub: UI load sequence
User->>ProjectHub: navigate
ProjectHub->>Loader: showLoader()
ProjectHub->>API: fetchProjects()
alt API returns error
API-->>ProjectHub: error
ProjectHub->>Loader: hideLoader()
ProjectHub->>ErrorIcon: render ErrorStateIcon
ProjectHub->>User: display error header & message
else API returns empty list
API-->>ProjectHub: []
ProjectHub->>Loader: hideLoader()
ProjectHub->>EmptyIcon: render EmptyIcon
ProjectHub->>User: display "No Projects Yet" header & message
else API returns projects
API-->>ProjectHub: projects[]
ProjectHub->>Loader: hideLoader()
ProjectHub->>User: render project list and normal header
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In
`@apps/customer-portal/webapp/src/components/common/error-state/ErrorStateIcon.tsx`:
- Around line 27-34: The SVG in ErrorStateIcon.tsx has mismatched intrinsic size
vs viewBox (width="268" height="229" vs viewBox="0 0 592 421") causing
letterboxing; update the <svg> in the ErrorStateIcon component to use
width/height that match the viewBox aspect ratio (e.g., scale to 592x421 or a
proportional pair) or adjust the viewBox to 268x229 so the intrinsic size and
viewBox align, and make the aria attributes consistent with EmptyIcon by using
aria-hidden="true" and focusable="false" instead of the mixed boolean forms.
🧹 Nitpick comments (5)
apps/customer-portal/webapp/src/components/common/empty-state/EmptyIcon.tsx (1)
136-213: Static gradient IDs will clash if multipleEmptyIconinstances coexist in the DOM.IDs like
paint0_linear_1857_52are global to the document. If twoEmptyIconcomponents render simultaneously, the second instance's<path fill="url(#paint0_linear_1857_52)">will resolve to the first instance's gradient definition, which may produce incorrect rendering (especially if one is hidden or removed).This is unlikely given the current single-use in
ProjectHub, but worth noting for future reuse. A common fix is to useReact.useId()to namespace the IDs.apps/customer-portal/webapp/src/components/common/error-state/__tests__/ErrorStateIcon.test.tsx (1)
21-35: Tests look good — consider adding a matching test file forEmptyIcon.The two tests adequately cover SVG rendering and prop forwarding. However, there's no corresponding
EmptyIcon.test.tsxin this PR. For consistency, consider adding analogous tests for theEmptyIconcomponent.apps/customer-portal/webapp/src/pages/ProjectHub.tsx (1)
116-148: Duplicated containersxbetween error and empty states — consider extracting.The
Boxwrappers at lines 118–127 and 135–144 share identicalsxprops (display: "flex",flexDirection: "column",alignItems: "center",justifyContent: "center",gap: 2,py: 10). A small constant or shared wrapper would reduce duplication.♻️ Example extraction
+ const centeredContainerSx = { + display: "flex", + flexDirection: "column", + alignItems: "center", + justifyContent: "center", + gap: 2, + py: 10, + } as const; + // ... then in renderContent: if (isError) { return ( - <Box - sx={{ - display: "flex", - flexDirection: "column", - alignItems: "center", - justifyContent: "center", - gap: 2, - py: 10, - }} - > + <Box sx={centeredContainerSx}> <ErrorStateIcon /> </Box> ); } if (projects.length === 0) { return ( - <Box - sx={{ - display: "flex", - flexDirection: "column", - alignItems: "center", - justifyContent: "center", - gap: 2, - py: 10, - }} - > + <Box sx={centeredContainerSx}> <EmptyIcon /> </Box> ); }apps/customer-portal/webapp/src/pages/__tests__/ProjectHub.test.tsx (2)
197-222: Error state test is thorough — optionally verify theTriangleAlerticon is rendered.The test checks for
error-state-icon, error title, and error subtitle — good coverage. You could additionally assertscreen.getByTestId("triangle-alert-icon")to verify the header icon switches to the alert icon in error state.
125-141: Good test setup — consider adding a test for single-project auto-navigation.
ProjectHubnavigates to/${projects[0].id}/dashboardwhen exactly one project is returned (line 60-62 ofProjectHub.tsx). This behavior isn't covered by any test case. A test with a single project inmockUseGetProjectscould verify this redirect.
There was a problem hiding this comment.
Pull request overview
This pull request modernizes the error and empty state handling in the Project Hub page by introducing dedicated icon components (EmptyIcon and ErrorStateIcon) to replace basic text messages and the legacy ErrorIndicator component. The changes improve visual consistency and user experience with more descriptive messaging and better-structured UI layouts.
Changes:
- Added new
ErrorStateIconcomponent with unit tests for displaying full-page error states - Added new
EmptyIconcomponent for displaying empty state visuals - Updated
ProjectHubcomponent to use the new icon components with improved conditional rendering and enhanced error/empty state messages
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
apps/customer-portal/webapp/src/components/common/error-state/ErrorStateIcon.tsx |
New SVG icon component for error states with documentation |
apps/customer-portal/webapp/src/components/common/error-state/__tests__/ErrorStateIcon.test.tsx |
Unit tests for ErrorStateIcon component |
apps/customer-portal/webapp/src/components/common/empty-state/EmptyIcon.tsx |
New SVG icon component for empty states with documentation |
apps/customer-portal/webapp/src/pages/ProjectHub.tsx |
Updated error/empty state rendering logic with new icon components and improved messaging; removed ErrorIndicator dependency |
apps/customer-portal/webapp/src/pages/__tests__/ProjectHub.test.tsx |
Updated test mocks and assertions to reflect new UI components and messaging |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Update ErrorStateIcon: change SVG height from 229 to 191 to match layout/design, and normalize accessibility attributes by setting aria-hidden="true" and focusable="false" (instead of bare booleans). Other props are still forwarded to the SVG.
Update ErrorStateIcon.test to assert that the SVG's aria-hidden attribute has an explicit empty-string value (expect(svg).toHaveAttribute("aria-hidden", "")). This makes the test verify the exact attribute value rather than only its presence, preventing false positives and ensuring the component renders the expected accessibility attribute.
Change EmptyIcon's focusable attribute from the string "false" to the boolean false to match JSX/SVG prop typing. Add unit tests for EmptyIcon to verify the SVG renders, has the expected viewBox and aria-hidden attributes, and passes through arbitrary SVG props (data-testid).
Change ErrorStateIcon focusable prop to a boolean (focusable={false}) to match SVG/TypeScript expectations and ensure correct DOM rendering. Update the test to expect aria-hidden="true" on the rendered SVG element. Adjustments keep component attributes consistent and tests accurate.
Replace conditional title strings and icon logic in ProjectHub with explicit Typography blocks for error, empty and normal states. Removed the TriangleAlert import and always use FolderOpen for the header; added distinct h4 and subtitle2 texts for the error and empty states and simplified the header rendering/spacing logic. This clarifies the UI structure and consolidates subtitle content for the normal project selection view.
e83e1cb
into
wso2-open-operations:customer-portal-milestone-1
Description
This pull request introduces improved empty and error state handling in the Project Hub page, replacing basic text messages and legacy error indicators with dedicated icon components and more descriptive messaging. It also adds unit tests for the new error state icon and updates mocks in related tests to support these changes.
Enhancements to empty and error state UI:
ProjectHubwith new icon components (EmptyIconandErrorStateIcon) and updated messaging for both empty and error states. This includes improved layout and more user-friendly descriptions. (apps/customer-portal/webapp/src/pages/ProjectHub.tsx) [1] [2]EmptyIconcomponent for empty state visuals. (apps/customer-portal/webapp/src/components/common/empty-state/EmptyIcon.tsx)ErrorStateIconcomponent and its unit test to ensure correct rendering and prop handling. (apps/customer-portal/webapp/src/components/common/error-state/__tests__/ErrorStateIcon.test.tsx)Improvements to test coverage and mocking:
ProjectHubtests to use new icon components, revised mock data, and improved mocking for UI elements and hooks to reflect the new UI logic. (apps/customer-portal/webapp/src/pages/__tests__/ProjectHub.test.tsx) [1] [2] [3] [4]These changes collectively modernize the Project Hub's feedback for empty and error states, making the UI clearer and more visually consistent.
Summary by CodeRabbit
New Features
Tests