Skip to content

Update vitest to v4 and related dependencies in thunder frontend#1300

Open
DonOmalVindula wants to merge 1 commit intoasgardeo:mainfrom
DonOmalVindula:migrate-vitest-v4
Open

Update vitest to v4 and related dependencies in thunder frontend#1300
DonOmalVindula wants to merge 1 commit intoasgardeo:mainfrom
DonOmalVindula:migrate-vitest-v4

Conversation

@DonOmalVindula
Copy link
Contributor

@DonOmalVindula DonOmalVindula commented Feb 5, 2026

Purpose

This pull request significantly expands and improves the test coverage for several UI components in the Thunder Develop frontend, focusing on the Header, Navbar, Sidebar, and related subcomponents. The changes add detailed tests for rendering, structure, icons, interactivity, and memoization, as well as refining test utilities and mock setups for more robust and isolated testing.

Header and Subcomponent Test Enhancements:

  • Added comprehensive tests to Header for icon rendering, layout structure, mobile navigation, tooltips, and correct rendering of subcomponents such as LanguageSwitcher and ColorSchemeToggle. Tests also verify correct memoization and layout after re-render.
  • Expanded Search component tests to cover outlined variant rendering, adornments, input sizing, form control structure, and preservation of content after re-render.
  • Improved LanguageSwitcher tests with cases for selection logic, icon rendering, menu structure, secondary text display, empty language lists, and memoization. Also updated test utilities and mocks for more accurate simulation. [1] [2] [3] [4]

Navbar and Breadcrumbs Test Improvements:

  • Added tests for AppNavbar to verify rendering of SideMenuMobile, initial drawer state, app bar styling, and content preservation after re-render.
  • Enhanced CustomIcon tests to include gradient background styling.
  • Greatly expanded NavbarBreadcrumbs tests to cover different navigation contexts, breadcrumb segment rendering, typography, separator icons, alignment, and memoization.

Sidebar and Menu Test Isolation:

  • Updated MenuContent tests to reset and restore the useNavigation mock before each test, ensuring isolation and preventing state leakage between tests.

Related Issues

Related PRs

  • N/A

Checklist

  • Followed the contribution guidelines.
  • Manual test round performed and verified.
  • Documentation provided. (Add links if there are any)
  • Tests provided. (Add links if there are any)
    • Unit Tests
    • Integration Tests
  • Breaking changes. (Fill if applicable)
    • Breaking changes section filled.
    • breaking change label added.

Security checks

  • Followed secure coding standards in WSO2 Secure Coding Guidelines
  • Confirmed that this PR doesn't commit any keys, passwords, tokens, usernames, or other secrets.

Summary by CodeRabbit

  • Tests

    • Significantly expanded test coverage across applications, flows, organization units, and authentication features
    • Added comprehensive tests for component rendering, interactions, error handling, and edge cases
    • Enhanced test utilities and mock setups for improved reliability
  • Refactor

    • Improved type safety in test mocks with stricter generic signatures
    • Optimized mock initialization patterns across test suites
    • Updated environment detection mechanism
  • Chores

    • Updated testing framework and dependencies to latest versions
    • Added browser testing support with Playwright integration

Copilot AI review requested due to automatic review settings February 5, 2026 09:01
@DonOmalVindula DonOmalVindula added the skip-changelog Skip generating changelog for a particular PR label Feb 5, 2026
brionmario
brionmario previously approved these changes Feb 5, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request upgrades Vitest from v3 to v4 across the Thunder frontend monorepo, with a focus on improving type safety in test files. The upgrade includes updating the browser testing provider configuration and modernizing test mock implementations.

Changes:

  • Upgraded Vitest and related packages from v3.2.4 to v4.0.17, including adding the new @vitest/browser-playwright dependency for browser-based testing
  • Enhanced type safety in test files by adding explicit generic types to vi.fn() mock declarations and replacing TypeScript eslint-disable comments with explicit type casts
  • Improved test reliability by adding setup steps to reset hoisted mock implementations before each test in rich text plugin tests
  • Updated Vitest browser provider configuration from string-based 'playwright' to function-based playwright() API in vitest.config.ts files

Reviewed changes

Copilot reviewed 31 out of 32 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
frontend/pnpm-workspace.yaml Updated catalog versions for vitest (4.0.17), @vitest/coverage-istanbul (4.0.17), and added @vitest/browser-playwright
frontend/pnpm-lock.yaml Dependency lock file updates reflecting the Vitest v4 upgrade and new dependencies
frontend/packages/thunder-test-utils/src/mocks/i18n.ts Added explicit return types to mock functions for better type safety
frontend/packages/thunder-shared-hooks/vitest.config.ts Updated browser provider from string 'playwright' to function call playwright()
frontend/packages/thunder-shared-hooks/package.json Added @vitest/browser-playwright dependency
frontend/packages/thunder-shared-contexts/vitest.config.ts Updated browser provider configuration to use function call
frontend/packages/thunder-shared-contexts/package.json Added @vitest/browser-playwright dependency
frontend/packages/thunder-shared-branding/vitest.config.ts Updated browser provider configuration to use function call
frontend/packages/thunder-shared-branding/package.json Added @vitest/browser-playwright dependency
frontend/apps/thunder-gate/src/tests/main.test.tsx Changed QueryClient mock from returning empty object to empty function (potential issue)
frontend/apps/thunder-develop/src/hooks/useDataGridLocaleText.ts Replaced process.env.NODE_ENV with Vite-standard import.meta.env.DEV
frontend/apps/thunder-develop/src/features/login-flow/hooks/tests/*.test.ts Added explicit types to mock function declarations for improved type safety
frontend/apps/thunder-develop/src/features/flows/components/resources/steps/execution/tests/Execution.test.tsx Simplified mockUseNodeId typing using generic type parameter syntax
frontend/apps/thunder-develop/src/features/flows/components/resource-property-panel/rich-text/helper-plugins/tests/*.test.tsx Added beforeEach setup to reset hoisted mocks to default implementations
frontend/apps/thunder-develop/src/features/flows/api/tests/*.test.tsx Added explicit generic types to mockHttpRequest declarations
frontend/apps/thunder-develop/src/features/integrations/api/tests/useIdentityProviders.test.tsx Added explicit generic type to mockHttpRequest
frontend/apps/thunder-develop/src/features/applications/components/edit-application/token-settings/EditTokenSettings.tsx Changed ref type from NodeJS.Timeout to ReturnType<typeof setTimeout> for better portability
frontend/apps/thunder-develop/src/features/applications/components/tests/ApplicationsList.test.tsx Added type cast for navigate mock to match expected return type
frontend/apps/thunder-develop/src/features/applications/api/tests/*.test.tsx Added explicit generic types to mock functions and replaced eslint-disable comments with explicit type casts
Files not reviewed (1)
  • frontend/pnpm-lock.yaml: Language not supported

@codecov
Copy link

codecov bot commented Feb 5, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.74%. Comparing base (422d4b1) to head (bd39f2c).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1300      +/-   ##
==========================================
- Coverage   89.67%   87.74%   -1.94%     
==========================================
  Files         649      655       +6     
  Lines       42534    43432     +898     
  Branches     2454     4288    +1834     
==========================================
- Hits        38144    38111      -33     
+ Misses       2375     2373       -2     
- Partials     2015     2948     +933     
Flag Coverage Δ
backend-integration-postgres 53.09% <ø> (ø)
backend-integration-sqlite 53.07% <ø> (ø)
backend-unit 82.24% <ø> (-0.02%) ⬇️
frontend-apps-develop-unit 82.60% <100.00%> (-7.86%) ⬇️
frontend-apps-gate-unit 85.06% <ø> (+0.18%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai
Copy link

coderabbitai bot commented Feb 5, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR comprehensively refines TypeScript types in test files throughout the frontend codebase, transitions Vitest browser configuration from string-based to function-based provider instantiation, updates environment detection from Node.js to Vite semantics, and significantly expands test coverage for components, hooks, and pages across multiple features with hundreds of new test cases.

Changes

Cohort / File(s) Summary
API Hook Test Typing Refinements
frontend/apps/thunder-develop/src/features/applications/api/__tests__/useCreateApplication.test.tsx, ...useDeleteApplication.test.tsx, ...useGetApplication.test.tsx, ...useGetApplications.test.tsx, ...useUpdateApplication.test.tsx, frontend/apps/thunder-develop/src/features/flows/api/__tests__/useCreateFlow.test.tsx, ...useDeleteFlow.test.tsx, ...useGetFlowById.test.tsx, ...useGetFlows.test.tsx, ...useUpdateFlow.test.tsx, frontend/apps/thunder-develop/src/features/integrations/api/__tests__/useIdentityProviders.test.tsx
Narrowed mockHttpRequest types from generic ReturnType<typeof vi.fn> to precise promise-based signature ReturnType<typeof vi.fn<(...args: unknown[]) => Promise<unknown>>>, with corresponding initialization and call-site casting updates for type safety.
Component and Hook Test Typing Refinements
frontend/apps/thunder-develop/src/features/applications/components/__tests__/ApplicationsList.test.tsx, frontend/apps/thunder-develop/src/features/flows/components/resource-property-panel/rich-text/helper-plugins/__tests__/CustomLinkPlugin.test.tsx, ...CustomLinkPluginPredefinedUrls.test.tsx, frontend/apps/thunder-develop/src/features/flows/components/resources/steps/execution/__tests__/Execution.test.tsx, frontend/apps/thunder-develop/src/features/login-flow/hooks/__tests__/useElementAddition.test.ts, ...useFlowInitialization.test.ts, ...useFlowSave.test.ts, ...useNodeTypes.test.tsx, ...useTemplateAndWidgetLoading.test.ts
Enhanced mock function types with intersections (e.g., ReturnType<typeof vi.fn> & UpdateNodeInternals) to support callable function signatures and improved state-updater type accuracy.
Core Implementation Type Updates
frontend/apps/thunder-develop/src/features/applications/components/edit-application/token-settings/EditTokenSettings.tsx, frontend/apps/thunder-develop/src/hooks/useDataGridLocaleText.ts
Changed NodeJS.Timeout to ReturnType for DOM timeout consistency; updated environment detection from process.env.NODE_ENV to import.meta.env.DEV for Vite alignment.
Vitest Configuration Updates
frontend/packages/thunder-shared-contexts/vitest.config.ts, frontend/packages/thunder-shared-hooks/vitest.config.ts
Added playwright import and transitioned provider configuration from string 'playwright' to function call playwright() for proper browser-test integration.
Vitest Dependency Updates
frontend/packages/thunder-shared-contexts/package.json, frontend/packages/thunder-shared-hooks/package.json, frontend/pnpm-workspace.yaml
Added @vitest/browser-playwright as devDependency; bumped vitest and coverage packages to version 4.0.17 in catalog.
Test Utility Type Exports
frontend/packages/thunder-test-utils/src/mocks/i18n.ts
Added explicit return type annotations to mockUseTranslation and mockUseLanguage functions to improve type inference and IDE support.
Extensive Test Coverage Additions
frontend/apps/thunder-gate/src/__tests__/components/AcceptInviteBox.test.tsx, ...SignInBox.test.tsx, ...SignUpBox.test.tsx, ...main.test.tsx, frontend/apps/thunder-develop/src/components/Header/__tests__/Header.test.tsx, ...LanguageSwitcher.test.tsx, frontend/apps/thunder-develop/src/components/Navbar/__tests__/NavbarBreadcrumbs.test.tsx, ...AppNavbar.test.tsx, frontend/apps/thunder-develop/src/components/Sidebar/__tests__/MenuContent.test.tsx, ...SideMenu.test.tsx, ...SideMenuMobile.test.tsx, frontend/apps/thunder-develop/src/components/Header/__tests__/Search.test.tsx, frontend/apps/thunder-develop/src/hooks/__tests__/useDataGridLocaleText.test.tsx
Added comprehensive UI rendering, interaction, branding, and accessibility test cases for Header, Navigation, Sidebar, and utility hook components; covers edge cases, fallback rendering, user interactions, and memoization paths.
Organization Units Feature Test Coverage
frontend/apps/thunder-develop/src/features/organization-units/api/__tests__/useCreateOrganizationUnit.test.ts, ...useDeleteOrganizationUnit.test.ts, ...useGetChildOrganizationUnits.test.ts, ...useGetOrganizationUnit.test.ts, ...useGetOrganizationUnitGroups.test.ts, ...useGetOrganizationUnitUsers.test.ts, ...useGetOrganizationUnits.test.ts, ...useUpdateOrganizationUnit.test.ts, frontend/apps/thunder-develop/src/features/organization-units/components/__tests__/OrganizationUnitDeleteDialog.test.tsx, ...edit-organization-unit/__tests__/EditAdvancedSettings.test.tsx, ...EditChildOUs.test.tsx, ...EditGeneralSettings.test.tsx, ...EditGroups.test.tsx, ...EditUsers.test.tsx, frontend/apps/thunder-develop/src/features/organization-units/pages/__tests__/CreateOrganizationUnitPage.test.tsx, ...OrganizationUnitEditPage.test.tsx, ...OrganizationUnitsListPage.test.tsx
Added extensive API hook tests for fetch behavior (empty params, re-fetches, error handling, cache invalidation), component tests for UI rendering/interactions (deletion flow, edit dialogs, data loading), and page tests for navigation and form submission across organization unit management features.
Applications Feature Test Coverage
frontend/apps/thunder-develop/src/features/applications/components/create-application/__tests__/ConfigureExperience.test.tsx, ...edit-application/customization-settings/__tests__/ContactsSection.test.tsx, ...general-settings/__tests__/AccessSection.test.tsx, ...token-settings/__tests__/TokenUserAttributesSection.test.tsx, ...advanced-settings/__tests__/CertificateSection.test.tsx, ...OAuth2ConfigSection.test.tsx, ...customization-settings/__tests__/AppearanceSection.test.tsx, ...flows-settings/__tests__/AuthenticationFlowSection.test.tsx, ...RegistrationFlowSection.test.tsx, ...general-settings/__tests__/EditGeneralSettings.test.tsx, ...integration-guides/__tests__/TechnologyGuide.test.tsx, ...token-settings/__tests__/TokenIssuerSection.test.tsx, ...TokenValidationSection.test.tsx, frontend/apps/thunder-develop/src/features/applications/pages/__tests__/ApplicationCreatePage.test.tsx, ...ApplicationEditPage.test.tsx
Added comprehensive tests for application creation/editing workflows including styling validation, edge cases for undefined/missing fields, clipboard operations, autocomplete filtering, certificate/OAuth configuration handling, branding selection, flow selection, language mapping for code blocks, and multi-step navigation scenarios.
Internationalization Provider Test Coverage
frontend/apps/thunder-develop/src/i18n/__tests__/I18nProvider.test.tsx
Added tests for translation merging behavior, memoization/re-render stability, and handling of missing translation properties in API responses.
Configuration and Coverage Updates
frontend/apps/thunder-develop/vite.config.ts
Expanded test coverage exclusion patterns to ignore DS\_Store and JSON files for cleaner coverage reports.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

The diff spans ~20+ files with heterogeneous changes across typing refinements, configuration updates, and extensive test additions. While many individual changes follow repetitive patterns (especially type refinements and similar test structures), the breadth across features and components, combined with new test logic requiring individual reasoning, warrants moderate-to-high review effort.

Possibly related PRs

  • Implement Organization Unit Tree UI #1350 — Adds comprehensive test coverage and typing refinements for organization-units API hooks and components (useCreateOrganizationUnit, useDeleteOrganizationUnit, OrganizationUnitDeleteDialog), directly aligned with OU feature testing.
  • Add user info config view to application edit #1337 — Modifies EditTokenSettings.tsx for userinfo-related logic; this PR adjusts the same file's timeout type annotation, creating a code-level intersection.

Suggested labels

Type/Improvement, Type/Tests

Suggested reviewers

  • jeradrutnam
  • ThaminduDilshan
  • brionmario

Poem

🐰 A rabbit hops through test files with glee,
Types refined and coverage set free!
From applications to flows so grand,
Testing now spreads across the land. 🧪✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description provides a clear purpose but does not follow the required template structure and is missing or incomplete sections. Fill in all required template sections: ensure 'Approach' section is completed with implementation details; verify 'Related Issues' and 'Related PRs' are properly filled; check all checklist items including manual testing, documentation, tests, and security checks. For checklist items that don't apply, explicitly mark them as N/A or provide explanation.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main objective: updating vitest to v4 and managing related dependencies in the frontend.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a 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

🤖 Fix all issues with AI agents
In
`@frontend/apps/thunder-develop/src/features/login-flow/hooks/__tests__/useTemplateAndWidgetLoading.test.ts`:
- Line 174: The mock implementation for mockValidateEdges does not match its
declared signature; update the mock for validateEdges so it accepts both
parameters (edges: Edge[], nodes: Node[]) and returns the expected value (e.g.,
return edges) — replace the existing vi.fn((edges) => edges) with vi.fn((edges,
nodes) => edges) (or a minimal implementation that uses both args) to match the
declared type and prevent hidden bugs when validateEdges is called with two
arguments.
🧹 Nitpick comments (10)
frontend/apps/thunder-develop/src/features/flows/components/resource-property-panel/rich-text/helper-plugins/__tests__/CustomLinkPluginPredefinedUrls.test.tsx (1)

121-137: LGTM! Consistent with the other test file.

The mock reset pattern matches CustomLinkPlugin.test.tsx, ensuring both test files have identical isolation guarantees.

Consider extracting the shared mock setup (vi.hoisted definitions + beforeEach resets) to a common test utility file to reduce duplication across both CustomLinkPlugin test files. This would make future maintenance easier if mock signatures change.

frontend/apps/thunder-gate/src/__tests__/components/SignUp/SignUpBox.test.tsx (3)

1656-1660: Consider adding assertion for SELECT component.

The test includes a SELECT component with label 'Country' in the components array but only asserts on Phone, OTP, and Resend. Adding an assertion for the SELECT would improve test coverage.

💡 Suggested improvement
     render(<SignUpBox />);
     expect(screen.getByLabelText(/Phone/)).toBeInTheDocument();
     expect(screen.getByText('OTP')).toBeInTheDocument();
+    expect(screen.getByText('Country')).toBeInTheDocument();
     expect(screen.getByText('Resend')).toBeInTheDocument();
   });

1708-1722: Test assertion could be more specific.

This test is named "renders branded logo with alt fallback" but only asserts that the signup container exists. Consider adding an assertion that actually verifies the logo is rendered or that the fallback alt text is applied.


1756-1774: Test assertion could verify the button renders.

This test verifies handling of a social login trigger with missing label and image, but only asserts that the container exists. Consider adding an assertion to verify how the component handles the missing properties (e.g., button still renders, uses fallback text, or doesn't render at all).

frontend/apps/thunder-gate/src/__tests__/components/AcceptInvite/AcceptInviteBox.test.tsx (2)

1274-1368: Test names imply key assertions, but only rendering is checked.

These three tests don’t verify key behavior; they only verify that components render. Consider renaming to match intent or add an assertion (e.g., no React key warning).

💡 Suggested rename to match current assertions
-it('uses fallback index keys when components have undefined id', () => {
+it('renders components when ids are undefined', () => {
...
-it('uses fallback keys for EMAIL_INPUT with undefined id in form block', () => {
+it('renders EMAIL_INPUT when id is undefined', () => {
...
-it('uses fallback keys for SELECT with undefined id in form block', () => {
+it('renders SELECT when id is undefined', () => {

1370-1429: Branding test assertions don’t match their titles.

These tests mention centered alignment and logo alt/size, but only assert container presence. Either assert the expected styles/attributes or rename.

✅ Example assertions aligned with titles
 it('renders with branding enabled and centered text alignment', () => {
@@
-  render(<AcceptInviteBox />);
-  expect(screen.getByText('Accept Invitation')).toBeInTheDocument();
+  render(<AcceptInviteBox />);
+  const heading = screen.getByText('Accept Invitation');
+  expect(heading).toBeInTheDocument();
+  expect(heading).toHaveStyle({ textAlign: 'center' });
 });
@@
 it('renders branded logo with alt fallback', () => {
@@
-  render(<AcceptInviteBox />);
-  expect(screen.getByTestId('asgardeo-accept-invite')).toBeInTheDocument();
+  render(<AcceptInviteBox />);
+  const logo = screen.getByRole('img');
+  expect(logo).toHaveAttribute('src', 'https://example.com/logo.png');
+  expect(logo).toHaveAttribute('alt');
 });
@@
 it('renders branded logo with custom alt, height, and width', () => {
@@
-  render(<AcceptInviteBox />);
-  expect(screen.getByTestId('asgardeo-accept-invite')).toBeInTheDocument();
+  render(<AcceptInviteBox />);
+  const logo = screen.getByRole('img');
+  expect(logo).toHaveAttribute('src', 'https://example.com/logo.png');
+  expect(logo).toHaveAttribute('alt', 'Custom Alt');
+  expect(logo).toHaveAttribute('height', '50');
+  expect(logo).toHaveAttribute('width', '120');
 });
frontend/apps/thunder-develop/src/features/login-flow/hooks/__tests__/useNodeTypes.test.tsx (1)

95-101: Simplify mock typing using Vitest's generic vi.fn syntax.

The current intersection type pattern works but is verbose. Vitest's generic vi.fn accepts a function signature directly, which simplifies the typing:

let mockOnAddElementToView = vi.fn<(element: Element, viewId: string) => void>();
let mockOnAddElementToForm = vi.fn<(element: Element, formId: string) => void>();

Then in beforeEach, simply reassign with the same generic:

mockOnAddElementToView = vi.fn<(element: Element, viewId: string) => void>();
mockOnAddElementToForm = vi.fn<(element: Element, formId: string) => void>();

This eliminates the need for manual intersection types and casts, making the code more idiomatic and readable.

frontend/apps/thunder-gate/src/__tests__/components/SignIn/SignInBox.test.tsx (3)

1499-1536: Add an assertion that the fallback-key path avoids list-key warnings.
Right now the test only checks rendering; it would still pass if keys were missing and React logged warnings. Consider asserting that no key-related warning is emitted (or rename the test if you intend it as a smoke test).

💡 Example: guard against key warnings
 it('uses fallback index keys when components have undefined id', () => {
+  const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
   mockSignInRenderProps = createMockSignInRenderProps({
     components: [
       {
         type: 'TEXT',
         label: 'Welcome',
         variant: 'H1',
       },
       {
         type: 'BLOCK',
         components: [
           {
             type: 'TEXT_INPUT',
             ref: 'username',
             label: 'Username',
             required: false,
           },
           {
             type: 'PASSWORD_INPUT',
             ref: 'password',
             label: 'Password',
             required: false,
           },
           {
             type: 'ACTION',
             eventType: 'SUBMIT',
             label: 'Continue',
             variant: 'PRIMARY',
           },
         ],
       },
     ],
   });
   render(<SignInBox />);
   expect(screen.getByText('Welcome')).toBeInTheDocument();
   expect(screen.getByLabelText(/Username/)).toBeInTheDocument();
   expect(screen.getByLabelText(/Password/)).toBeInTheDocument();
+  expect(consoleErrorSpy).not.toHaveBeenCalledWith(
+    expect.stringContaining('unique "key"')
+  );
+  consoleErrorSpy.mockRestore();
 });

1688-1828: Fallback/branding tests should assert the fallback attributes.
These cases currently only assert that rendering succeeds; they won’t fail if alt/size/placeholder fallbacks regress. Consider asserting the expected alt, height/width, and placeholder values to make the tests meaningful (or rename them to “renders without crashing”).


1830-1889: “Field error” test doesn’t verify error UI state.
It only checks that onSubmit isn’t called. Consider asserting error indicators (e.g., aria-invalid, helper text, or error styling) so the test validates the stated behavior.

Copilot AI review requested due to automatic review settings February 5, 2026 10:14
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 34 out of 35 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • frontend/pnpm-lock.yaml: Language not supported

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Fix all issues with AI agents
In
`@frontend/apps/thunder-develop/src/features/login-flow/hooks/__tests__/useFlowInitialization.test.ts`:
- Line 181: The mockValidateEdges currently only accepts a single parameter and
ignores the nodes argument, which can hide bugs; update the mock declaration in
useFlowInitialization.test.ts so mockValidateEdges is typed and implemented to
accept both (edges: Edge[], nodes: Node[]) and return edges (e.g., vi.fn((edges:
Edge[], nodes: Node[]) => edges)) so the mocked function signature matches the
real validateEdges and the nodes parameter is available to tests; keep the
variable name mockValidateEdges and the Edge/Node types when updating the mock.

In
`@frontend/apps/thunder-gate/src/__tests__/components/SignUp/SignUpBox.test.tsx`:
- Around line 1724-1741: The test only asserts the container renders but must
validate the branded logo attributes; update the SignUpBox.test that uses
mockUseBranding so after render(<SignUpBox />) you query the image (e.g.,
screen.getByRole('img', { name: /Custom Alt/i }) or screen.getByAltText('Custom
Alt')) and add assertions that its alt equals 'Custom Alt' and its height/width
reflect 50 and 120 (or check the rendered img attributes/props/style), keeping
the existing mocked branding in place and replacing the weak container-only
expect with these image attribute checks.
- Around line 1682-1706: The test "renders with branding enabled and centered
text alignment" currently only verifies the text exists; either rename it to
"renders with branding enabled" or add an assertion that checks the rendered
text's alignment (e.g., inspect the DOM node returned by
screen.getByText('Create Account') or its container from SignUpBox for a
centered text style/class), updating the test that uses mockUseBranding and
mockSignUpRenderProps/createMockSignUpRenderProps so the assertion targets the
correct element returned by SignUpBox and verifies text-align:center (or the
expected CSS class) rather than only existence.
- Around line 1657-1660: The test currently only asserts Phone/OTP/Resend but
the test title references SELECT and TRIGGER with an undefined id; add
assertions that the SELECT combobox and TRIGGER button are rendered and have no
id. Locate where the SELECT and TRIGGER are created in the SignUpBox test and
add expectations using screen.getByRole('combobox') (or screen.getByLabelText
for the select) and screen.getByRole('button', { name: /trigger/i }) to assert
they are in the document and that their id attribute is null/undefined (e.g.,
element.getAttribute('id') === null).
- Around line 1708-1722: The test only checks the container; update it to locate
the actual logo image rendered by SignUpBox (e.g., use
within(screen.getByTestId('asgardeo-signup')).getByRole('img') or
getByTestId('branding-logo') if present) and assert the image's src includes the
mocked logo url ('https://example.com/logo.png') and that its alt attribute
matches the expected fallback text (or at minimum is non-empty) to verify both
rendering and alt fallback behavior while keeping mockUseBranding as currently
defined.

Copy link

@coderabbitai coderabbitai bot left a 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

🤖 Fix all issues with AI agents
In
`@frontend/apps/thunder-develop/src/components/Sidebar/__tests__/SideMenuMobile.test.tsx`:
- Around line 111-116: The test currently only checks button count and can miss
the notification bell; modify the MenuButton component used for the notification
bell (MenuButton in MenuButton.tsx) to include an accessible name such as
aria-label="notifications" on the notification MenuButton, then update the test
in SideMenuMobile.test.tsx (the 'renders notification bell button when open'
case) to explicitly assert the presence of that button by querying
getByRole('button', { name: /notifications/i }) or similar instead of relying on
buttons.length.

In `@frontend/pnpm-workspace.yaml`:
- Line 58: Update the Vitest integration to meet v4 requirements: ensure the
project Node.js runtime is bumped to >=20.0.0 and Vite to >=6.0.0, then audit
any Vitest config entries referencing removed options
(coverage.ignoreEmptyLines, coverage.experimentalAstAwareRemapping,
coverage.all, coverage.extensions) and replace them with the new semantics (use
coverage.include for file selection and remove the removed flags), and adjust
coverage hint usage for TypeScript+esbuild by preserving legal comments (e.g.,
/* `@preserve` */) where necessary; update the vitest version entry (the vitest:
4.0.17 line) only after confirming Node/Vite compatibility and then run the
test/coverage suite to validate coverage number changes due to the new AST-based
remapping.
- Around line 28-29: CI lacks Playwright browsers for Vitest's
`@vitest/browser-playwright` provider used by packages thunder-shared-hooks,
thunder-shared-contexts, thunder-shared-branding, and thunder-i18n; update the
CI workflow to run the Playwright browser installation (e.g., run npx playwright
install --with-deps or the equivalent playwright install command) before any
frontend test step that invokes pnpm test:coverage (notably in the
thunder-develop and thunder-gate test steps), ensuring the installation step
precedes pnpm test:coverage so Vitest can launch browsers during CI runs.
🧹 Nitpick comments (7)
frontend/apps/thunder-develop/src/components/Sidebar/__tests__/MenuContent.test.tsx (2)

197-212: Test name doesn't match what's being tested.

The test is named "shows tooltips with item text in mini mode" but only verifies icon centering (justifyContent: 'center'), not tooltip content. Consider renaming to "centers list item icons in mini mode" or actually testing tooltip behavior (e.g., by hovering and checking tooltip text appears).


214-228: Test name doesn't match what's being tested.

The test is named "does not show tooltips in expanded mode" but verifies text visibility (opacity, display) instead. Consider renaming to "shows text labels with full opacity in expanded mode" to accurately describe the assertion.

frontend/apps/thunder-develop/src/components/Header/__tests__/LanguageSwitcher.test.tsx (1)

116-117: Consider addressing the type casting pattern for language codes.

The repeated as unknown as 'en-US' casts suggest that SupportedLanguage type may be too restrictive for test scenarios. While this works, it could be cleaner to either:

  1. Extend the mock's type to accept broader language code strings
  2. Add test-specific language codes to the SupportedLanguage union type if the component is designed to support arbitrary languages

This is a minor maintenance concern and doesn't affect test correctness.

Also applies to: 137-137, 185-185, 211-214, 260-261, 285-286, 314-314

frontend/apps/thunder-develop/src/components/Header/__tests__/Header.test.tsx (2)

76-81: Fragile test relying on MUI internal class names.

Asserting stacks.length >= 1 based on .MuiStack-root class selectors is fragile because:

  1. MUI internal class names may change between versions
  2. The assertion >= 1 is too permissive to catch layout regressions

Consider testing layout behavior through more stable means like role queries or data-testid attributes.


83-88: Redundant test case.

This test duplicates the assertion on line 58 which already verifies screen.getByRole('button', {name: /open notifications/i}) is present.

Consider removing or differentiating this test

Either remove this test entirely since it's covered in "renders all header components", or enhance it to test additional notification-specific behavior (e.g., tooltip content, interaction).

frontend/apps/thunder-develop/src/components/Navbar/__tests__/NavbarBreadcrumbs.test.tsx (1)

211-225: Avoid brittle class-based assertions and redundant coverage.
This test overlaps with existing “Develop + Users” checks and relies on .MuiTypography-root, which is an implementation detail. Consider removing it or asserting via semantic structure/text instead.

frontend/apps/thunder-develop/src/components/Sidebar/__tests__/SideMenuMobile.test.tsx (1)

103-109: Avoid brittle MUI class selectors; prefer accessible queries.

.MuiAvatar-root and .MuiDivider-root are implementation details and can break on MUI upgrades. Prefer RTL queries that reflect user-visible semantics (e.g., alt text and separator role).

♻️ Suggested test adjustments
-    // Drawer renders in a portal, so use document instead of container
-    const avatar = document.querySelector('.MuiAvatar-root');
-    expect(avatar).toBeInTheDocument();
+    const avatar = screen.getByAltText('Riley Carter');
+    expect(avatar).toBeInTheDocument();
-    // Drawer renders in a portal, so use document instead of container
-    const dividers = document.querySelectorAll('.MuiDivider-root');
-    expect(dividers.length).toBeGreaterThan(0);
+    const dividers = screen.getAllByRole('separator');
+    expect(dividers.length).toBeGreaterThan(0);

Also applies to: 119-124

Copilot AI review requested due to automatic review settings February 5, 2026 12:37
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 43 out of 44 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • frontend/pnpm-lock.yaml: Language not supported

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/apps/thunder-develop/src/features/login-flow/hooks/__tests__/useFlowSave.test.ts (1)

325-342: ⚠️ Potential issue | 🟡 Minor

Test doesn't effectively verify pending state.

The test uses vi.doMock and vi.resetModules() but doesn't reimport the hook, so renderUseFlowSave() still uses the original mock. The comment on line 336 acknowledges this. The assertion only checks the type, not the actual value.

Consider removing or rewriting this test to avoid misleading coverage. One approach is to expose the pending state through props or use a different testing strategy.

🤖 Fix all issues with AI agents
In
`@frontend/apps/thunder-develop/src/components/Header/__tests__/Search.test.tsx`:
- Around line 112-119: The test "preserves content after re-render" currently
only checks static attributes; update it to type into the Search input before
calling rerender and then assert the typed content still exists after rerender.
Specifically, in the test for the Search component use userEvent.type (or
fireEvent.change) on the element returned by
screen.getByPlaceholderText('Search...') (or screen.getByLabelText('Search')),
call rerender(<Search />), then assert the input's value (via
expect(...).toHaveValue(...) or checking element.value) equals the typed string
to verify content preservation.

In
`@frontend/apps/thunder-develop/src/components/Navbar/__tests__/AppNavbar.test.tsx`:
- Around line 145-152: The test in AppNavbar.test.tsx currently only checks for
the base class 'MuiAppBar-root' which doesn't confirm the box shadow is removed;
update the 'renders app bar with no box shadow' test to assert the actual style
on the rendered AppNavbar (render(<AppNavbar />)) by selecting the element
(container.querySelector('.MuiAppBar-root') or getByRole) and expecting the
computed style to show no shadow (e.g., expect(appBar).toHaveStyle('box-shadow:
none') or assert absence of elevation classes/styles), or alternatively check
that elevation-related classes are not present; modify the test assertions
accordingly to verify the boxShadow: 0 behavior.
🧹 Nitpick comments (17)
frontend/packages/thunder-test-utils/src/mocks/i18n.ts (1)

44-48: Consider adding an explicit return type for consistency.

The other mock functions now have explicit return type annotations. For consistency, you could add one here as well:

export const mockUseDataGridLocaleText = (): {
  noRowsLabel: string;
  noResultsOverlayLabel: string;
  paginationRowsPerPage: string;
} => ({
  // ...
});
frontend/apps/thunder-develop/src/components/Sidebar/__tests__/MenuContent.test.tsx (4)

197-212: Test name does not match assertions.

The test is named "shows tooltips with item text in mini mode" but only verifies that icons have justifyContent: 'center'. It doesn't actually verify tooltip content or behavior. Consider either:

  1. Renaming to reflect what's actually being tested (e.g., "centers list item icons in mini mode")
  2. Adding assertions for actual tooltip behavior

Note: This duplicates the assertion in the "centers list item buttons in mini mode" test (lines 265-278) which also checks centering in mini mode.


214-228: Test name misleading and overlaps with existing test.

This test is named "does not show tooltips in expanded mode" but actually verifies text visibility (opacity: '1', display: 'block'). This logic is already covered by the existing test "shows text labels in expanded mode" (lines 124-143). Consider removing this test or renaming it to clarify its distinct purpose if it tests something different.


326-339: Test name does not match assertion.

The test is named "sets icon margin to spacing in expanded mode" but only asserts minWidth: 0. To match the name, it should verify marginRight equals the spacing value (e.g., 24px for MUI's mr: 3). Consider either renaming the test or updating the assertion.

💡 Suggested fix to match the test name
   it('sets icon margin to spacing in expanded mode', async () => {
     const {default: SidebarContext} = await import('../context/SidebarContext');

     const {container} = render(
       <SidebarContext.Provider value={{mini: false, fullyExpanded: true, fullyCollapsed: false, hasDrawerTransitions: true}}>
         <MenuContent />
       </SidebarContext.Provider>
     );

     const listItemIcons = container.querySelectorAll('.MuiListItemIcon-root');
     listItemIcons.forEach((icon) => {
-      expect(icon).toHaveStyle({minWidth: 0});
+      expect(icon).toHaveStyle({minWidth: 0, marginRight: '24px'});
     });
   });

341-354: Partial overlap with existing test.

This test overlaps with "hides text labels in mini mode" (lines 103-122) which already verifies display: 'none'. The additional opacity: 0 assertion provides incremental value. Consider consolidating these into a single comprehensive test.

frontend/apps/thunder-develop/src/components/Header/__tests__/LanguageSwitcher.test.tsx (2)

116-117: Consider defining test language types for better type safety.

The as unknown as 'en-US' double cast pattern bypasses type checking. While acceptable in tests, consider creating a test helper or type for mock language data to avoid scattering these casts throughout.

♻️ Suggested approach

Define a helper at the top of the file or in test-utils:

// Helper to create mock language for testing
const createMockLanguage = (
  code: string,
  name: string,
  nativeName: string,
  direction: 'ltr' | 'rtl' = 'ltr'
) => ({
  code,
  name,
  nativeName,
  direction,
} as const);

// Usage in tests:
availableLanguages: [
  createMockLanguage('en-US', 'English (United States)', 'English (US)'),
  createMockLanguage('es-ES', 'Spanish (Spain)', 'Español (España)'),
],

332-337: Consider using a more resilient selector for the icon.

The CSS class selector svg.lucide-languages is coupled to the icon library's implementation. If Lucide changes its class naming convention, this test would break.

♻️ Alternative approach

Consider adding a data-testid to the icon in the component, or accept that this is a reasonable trade-off for testing icon presence:

-    const languagesIcon = container.querySelector('svg.lucide-languages');
+    // Verify SVG icon is present within the button
+    const button = screen.getByRole('button', {name: /change language/i});
+    const languagesIcon = button.querySelector('svg');
     expect(languagesIcon).toBeInTheDocument();
frontend/apps/thunder-develop/src/components/Header/__tests__/Header.test.tsx (4)

62-67: Same concern as LanguageSwitcher: CSS class selector for icon.

Using svg.lucide-bell is implementation-specific. Consider the same refactor suggestion as noted for the LanguageSwitcher tests.


76-81: Layout assertions are tightly coupled to MUI implementation.

These tests rely on MUI's internal CSS class names (.MuiStack-root) and computed styles. Such tests can break with MUI version updates without any functional change to your component.

Consider whether these layout tests provide sufficient value, or if the functional tests (checking that expected elements render) already provide adequate coverage.

♻️ Alternative approach

If layout verification is critical, consider:

  1. Adding data-testid attributes to key layout containers
  2. Using snapshot testing for structural verification
  3. Relying on visual regression testing for layout concerns
-  it('renders with correct layout structure', () => {
-    const {container} = render(<Header />);
-
-    const stacks = container.querySelectorAll('.MuiStack-root');
-    expect(stacks.length).toBeGreaterThanOrEqual(1);
-  });
+  it('renders with correct layout structure', () => {
+    const {container} = render(<Header />);
+
+    // Verify the header renders as a flex container
+    const header = container.firstChild;
+    expect(header).toBeInTheDocument();
+  });

Also applies to: 90-97


83-88: Duplicate test assertion.

This test ("renders notifications tooltip") checks the same assertion as the existing test on line 58 in "renders all header components". Consider removing this test to avoid redundancy, or expand it to verify tooltip-specific behavior.

♻️ Suggested fix

Either remove this test, or enhance it to test actual tooltip behavior:

-  it('renders notifications tooltip', () => {
-    render(<Header />);
-
-    const notificationsButton = screen.getByRole('button', {name: /open notifications/i});
-    expect(notificationsButton).toBeInTheDocument();
-  });
+  it('shows tooltip on notifications button hover', async () => {
+    render(<Header />);
+
+    const notificationsButton = screen.getByRole('button', {name: /open notifications/i});
+    fireEvent.mouseEnter(notificationsButton);
+
+    await waitFor(() => {
+      expect(screen.getByRole('tooltip')).toBeInTheDocument();
+    });
+  });

99-104: Duplicate assertions already covered in "renders all header components".

Lines 59 and 57 in the existing test already verify the language button and theme toggle presence. These separate tests don't add new coverage.

♻️ Consider consolidating or removing

If component isolation testing is the goal, the tests are acceptable. Otherwise, consider removing to reduce test maintenance burden:

-  it('renders LanguageSwitcher component', () => {
-    render(<Header />);
-
-    const languageButton = screen.getByRole('button', {name: /change language/i});
-    expect(languageButton).toBeInTheDocument();
-  });
-
-  it('renders ColorSchemeToggle component', () => {
-    render(<Header />);
-
-    expect(screen.getByTestId('theme-toggle')).toBeInTheDocument();
-  });

Also applies to: 106-110

frontend/apps/thunder-develop/src/components/Header/__tests__/Search.test.tsx (1)

81-100: Consider using semantic queries instead of MUI class selectors.

These tests rely on MUI-specific CSS classes (.MuiOutlinedInput-root, .MuiInputAdornment-positionStart, .MuiInputBase-sizeSmall) which are implementation details that could break if MUI changes its internal naming conventions. The existing tests in this file appropriately use semantic queries like getByPlaceholderText and getByLabelText.

For the start adornment test (lines 88-93), you could verify the icon exists within the input's structure using role queries or the existing svg.lucide-search selector from line 41.

frontend/apps/thunder-develop/src/components/Navbar/__tests__/AppNavbar.test.tsx (1)

180-186: Test name and assertion are mismatched.

The test claims to verify a gradient background but only checks borderRadius. Either rename the test or assert the gradient-related style to match intent.

frontend/apps/thunder-gate/src/__tests__/components/SignUp/SignUpBox.test.tsx (1)

1562-1607: Test name claims fallback keys but only asserts rendering.

Consider asserting the absence of React key warnings (or rename the test to match current coverage).

💡 Optional assertion to validate key handling
   it('uses fallback index keys when components have undefined id', () => {
+    const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
     mockSignUpRenderProps = createMockSignUpRenderProps({
       components: [
         {
           type: 'TEXT',
           label: 'Create Account',
           variant: 'H1',
         },
         {
           type: 'BLOCK',
           components: [
             {
               type: 'TEXT_INPUT',
               ref: 'firstName',
               label: 'First Name',
               placeholder: 'Enter first name',
               required: false,
             },
             {
               type: 'PASSWORD_INPUT',
               ref: 'password',
               label: 'Password',
               placeholder: 'Enter password',
               required: false,
             },
             {
               type: 'EMAIL_INPUT',
               ref: 'email',
               label: 'Email',
               placeholder: 'Enter email',
               required: false,
             },
             {
               type: 'ACTION',
               eventType: 'SUBMIT',
               label: 'Register',
               variant: 'SECONDARY',
             },
           ],
         },
       ],
     });
     render(<SignUpBox />);
     expect(screen.getByText('Create Account')).toBeInTheDocument();
     expect(screen.getByLabelText(/First Name/)).toBeInTheDocument();
+    expect(consoleErrorSpy).not.toHaveBeenCalledWith(
+      expect.stringMatching(/unique "key"/i),
+    );
+    consoleErrorSpy.mockRestore();
   });
frontend/apps/thunder-gate/src/__tests__/components/AcceptInvite/AcceptInviteBox.test.tsx (2)

1274-1368: Fallback‑key tests don’t actually validate key behavior.

React keys aren’t visible in the DOM, so these assertions can pass even if the fallback keys are broken. Consider asserting that no “unique key” warning is emitted to make the tests match their intent.

🔍 Possible tweak (apply similarly to the other fallback‑key tests)
   it('uses fallback index keys when components have undefined id', () => {
+    const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
     mockAcceptInviteRenderProps = createMockAcceptInviteRenderProps({
       components: [
         {
           type: 'TEXT',
@@
     });
     render(<AcceptInviteBox />);
+    const warnings = consoleSpy.mock.calls.flat().join(' ');
+    expect(warnings).not.toMatch(/unique "key"/i);
+    consoleSpy.mockRestore();
     expect(screen.getByText('Accept Invite')).toBeInTheDocument();
     expect(screen.getByLabelText(/Full Name/)).toBeInTheDocument();
   });

1396-1429: Branding logo tests only assert container presence.

The test names mention alt/size behavior, but they don’t assert the logo element itself. Consider asserting the rendered logo’s attributes (alt/src/height/width) so the tests exercise the intended behavior.

frontend/apps/thunder-develop/src/hooks/__tests__/useDataGridLocaleText.test.tsx (1)

323-351: Prefer restoring local spies instead of vi.restoreAllMocks().
vi.restoreAllMocks() can reset unrelated spies created elsewhere in the file or shared test setup. It’s safer to restore only the spies you create here.

♻️ Targeted restoration
-    const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
-
-    vi.spyOn(i18nModule.default, 'getResourceBundle').mockImplementation((lng: string, ns: string) => {
+    const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
+    const getResourceBundleSpy = vi
+      .spyOn(i18nModule.default, 'getResourceBundle')
+      .mockImplementation((lng: string, ns: string) => {
       const bundle = originalGetResourceBundle(lng, ns) as Record<string, unknown>;
       return {
         ...bundle,
         // Override a function key with a string value to trigger the DEV warning
         'dataTable.toolbarFiltersTooltipActive': 'not-a-function',
       };
     });
...
-    consoleSpy.mockRestore();
-    vi.restoreAllMocks();
+    consoleSpy.mockRestore();
+    getResourceBundleSpy.mockRestore();
-    vi.spyOn(i18nModule.default, 'getResourceBundle').mockImplementation(() => ({}));
+    const getResourceBundleSpy = vi
+      .spyOn(i18nModule.default, 'getResourceBundle')
+      .mockImplementation(() => ({}));
...
-    vi.restoreAllMocks();
+    getResourceBundleSpy.mockRestore();

Also applies to: 353-371

@DonOmalVindula DonOmalVindula force-pushed the migrate-vitest-v4 branch 2 times, most recently from 25565b6 to a267c29 Compare February 5, 2026 17:09
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
frontend/apps/thunder-develop/src/features/organization-units/components/edit-organization-unit/__tests__/EditGroups.test.tsx (1)

24-28: ⚠️ Potential issue | 🟡 Minor

Mock doesn't accept the organizationUnitId parameter that the component passes, so the test can't verify it's being propagated correctly.

The hook is called with organizationUnitId (line 53 of EditGroups.tsx), but the mock's default export doesn't accept any parameters. The test named "should pass organizationUnitId to the API hook" (lines 193-197) only checks for text rendering, not parameter passing. Update the mock to capture the parameter and assert it's called with the expected ID.

✅ Proposed fix
 const mockUseGetOrganizationUnitGroups = vi.fn();
 vi.mock('../../../api/useGetOrganizationUnitGroups', () => ({
-  default: () => mockUseGetOrganizationUnitGroups() as {data: GroupListResponse | undefined; isLoading: boolean},
+  default: (organizationUnitId: string) =>
+    mockUseGetOrganizationUnitGroups(organizationUnitId) as {data: GroupListResponse | undefined; isLoading: boolean},
 }));
   it('should pass organizationUnitId to the API hook', () => {
     renderWithProviders(<EditGroups organizationUnitId="different-ou" />);
 
     expect(screen.getByText('Groups')).toBeInTheDocument();
+    expect(mockUseGetOrganizationUnitGroups).toHaveBeenCalledWith('different-ou');
   });
frontend/apps/thunder-develop/src/features/organization-units/components/edit-organization-unit/__tests__/EditUsers.test.tsx (1)

24-28: ⚠️ Potential issue | 🟡 Minor

Mock hook should accept and forward the organizationUnitId parameter for proper testing.

The mocked hook currently ignores parameters passed to it. The test at lines 193-197 is named "should pass organizationUnitId to the API hook" but only checks rendering—it doesn't verify the parameter is actually passed. Update the mock to accept organizationUnitId and add an assertion to confirm the hook receives the correct value:

Proposed fix
 const mockUseGetOrganizationUnitUsers = vi.fn();
 vi.mock('../../../api/useGetOrganizationUnitUsers', () => ({
-  default: () => mockUseGetOrganizationUnitUsers() as {data: UserListResponse | undefined; isLoading: boolean},
+  default: (organizationUnitId: string) =>
+    mockUseGetOrganizationUnitUsers(organizationUnitId) as {data: UserListResponse | undefined; isLoading: boolean},
 }));
   it('should pass organizationUnitId to the API hook', () => {
     renderWithProviders(<EditUsers organizationUnitId="different-ou" />);
 
     expect(screen.getByText('Users')).toBeInTheDocument();
+    expect(mockUseGetOrganizationUnitUsers).toHaveBeenCalledWith('different-ou');
   });

Also applies to: 193-197

🤖 Fix all issues with AI agents
In
`@frontend/apps/thunder-develop/src/features/organization-units/api/__tests__/useCreateOrganizationUnit.test.ts`:
- Around line 241-257: The test doesn't assert that
queryClient.invalidateQueries was actually invoked, so store the spy returned by
vi.spyOn(queryClient, 'invalidateQueries') in a const (e.g., const invalidateSpy
= ...) before stubbing it, call result.current.mutate(createRequest) as before,
then add an assertion like expect(invalidateSpy).toHaveBeenCalled() after the
waitFor to confirm the rejection path is exercised; reference
useCreateOrganizationUnit, queryClient.invalidateQueries, and
result.current.mutate when adding the assertion.

In
`@frontend/apps/thunder-develop/src/features/organization-units/components/edit-organization-unit/__tests__/EditChildOUs.test.tsx`:
- Around line 307-311: The test name claims to verify that organizationUnitId is
passed to the API hook but only checks the rendered title; update the test to
either (A) actually assert the hook received the prop by mocking the API hook
used by EditChildOUs (e.g., jest.mock the module and assert the mocked
hook/function was called with "test-ou-id"), referencing the component
EditChildOUs and the API hook name used inside it, or (B) if you don't want to
mock the hook here, rename the test to reflect the current assertion (e.g.,
"should render with custom organizationUnitId") so the test name matches what is
validated.

In
`@frontend/apps/thunder-gate/src/__tests__/components/SignUp/SignUpBox.test.tsx`:
- Around line 1756-1774: The test currently only asserts that the container
('asgardeo-signup') exists but intends to verify the social login trigger;
update the assertion to check for the trigger element associated with the
provider button (e.g., query for an element tied to the component id
'provider-btn' or the rendered trigger text/role) after rendering SignUpBox with
mockSignUpRenderProps created via createMockSignUpRenderProps, or alternatively
rename the test to "does not crash when label/image missing" if the intent is
only to ensure no crash rather than presence of a trigger.

In `@frontend/packages/thunder-shared-branding/vitest.config.ts`:
- Around line 19-28: The vitest config uses the provider function playwright()
from `@vitest/browser-playwright` but the Playwright runtime is not declared in
devDependencies; add either "playwright" or "playwright-core" to devDependencies
(matching the Playwright version required by Vitest v4's browser-playwright peer
dependency) and install it (e.g., npm/yarn/pnpm add -D playwright or
playwright-core) so the provider playwright() can resolve at runtime; update
package.json devDependencies and reinstall to update lockfile.

In `@frontend/packages/thunder-shared-contexts/vitest.config.ts`:
- Around line 19-28: The package is importing and using playwright() from
`@vitest/browser-playwright` (see the import of playwright and the call to
playwright() in vitest.config), but playwright is missing from devDependencies;
add "playwright": "catalog:" to this package's devDependencies (matching the
workspace catalog version) so the peerDependency requirement for
`@vitest/browser-playwright` is satisfied.
🧹 Nitpick comments (18)
frontend/apps/thunder-develop/src/components/Sidebar/__tests__/MenuContent.test.tsx (3)

197-212: Test name is misleading — it verifies icon styling, not tooltip content.

The test is named "shows tooltips with item text in mini mode" but only verifies that ListItemIcon elements have justifyContent: 'center'. It doesn't actually assert anything about tooltip titles or their presence.

Consider either renaming the test to accurately describe what it verifies (e.g., "centers list item icons in mini mode") or actually testing the tooltip behavior.

♻️ Option 1: Rename to match actual behavior
-  it('shows tooltips with item text in mini mode', async () => {
+  it('centers list item icons in mini mode', async () => {
     const {default: SidebarContext} = await import('../context/SidebarContext');
 
     render(

326-339: Test name doesn't match assertion.

The test is named "sets icon margin to spacing in expanded mode" but asserts minWidth: 0 instead of any margin-related property. According to the relevant code snippet from MenuContent.tsx, in expanded mode the icon's marginRight should not be 'auto' (unlike mini mode).

Consider updating the test name or the assertion to match the intended behavior.

♻️ Suggested fix: Rename test to match assertion
-  it('sets icon margin to spacing in expanded mode', async () => {
+  it('sets icon minWidth to 0 in expanded mode', async () => {
     const {default: SidebarContext} = await import('../context/SidebarContext');

214-228: Test name doesn't match the assertions.

The test is named "does not show tooltips in expanded mode" but verifies that ListItemText elements have opacity: '1' and display: 'block'. The assertions don't verify tooltip absence.

Consider renaming to accurately reflect what's being tested.

♻️ Suggested fix
-  it('does not show tooltips in expanded mode', async () => {
+  it('shows text labels with full opacity in expanded mode', async () => {
     const {default: SidebarContext} = await import('../context/SidebarContext');
frontend/apps/thunder-develop/src/components/Header/__tests__/LanguageSwitcher.test.tsx (1)

339-349: Consider using screen.getByRole for consistency.

The test correctly verifies the menu ID, but using document.getElementById is slightly inconsistent with the screen query patterns used elsewhere in this file.

♻️ Optional: Use screen query with attribute check
     await waitFor(() => {
-      const menu = document.getElementById('language-menu');
-      expect(menu).toBeInTheDocument();
+      const menu = screen.getByRole('menu');
+      expect(menu).toHaveAttribute('id', 'language-menu');
     });
frontend/apps/thunder-develop/src/features/organization-units/api/__tests__/useGetOrganizationUnitGroups.test.ts (1)

217-227: Minor inconsistency: isFetching vs isLoading.

This test uses isFetching on line 224, while the similar existing test "should not fetch when organizationUnitId is undefined" (line 92) uses isLoading. Consider aligning these for consistency across similar test cases.

♻️ Suggested fix for consistency
-    expect(result.current.isFetching).toBe(false);
+    expect(result.current.isLoading).toBe(false);
frontend/apps/thunder-develop/src/components/Navbar/__tests__/NavbarBreadcrumbs.test.tsx (1)

266-282: Consider the brittleness of testing MUI internal styles.

Line 281 asserts on alignItems: 'center' which appears to be MUI's default internal styling for the breadcrumbs ol element rather than an explicit style set by the component. This test could become flaky if MUI updates their internal styles in a future version.

If the intent is to verify custom styling applied by StyledBreadcrumbs, consider testing only the styles explicitly defined in that styled component. If verifying the general visual structure, the existence of the element (line 280) may be sufficient.

frontend/apps/thunder-develop/src/features/organization-units/api/__tests__/useGetOrganizationUnitUsers.test.ts (2)

217-227: Minor inconsistency: uses isFetching instead of isLoading.

The similar test for undefined on line 92 uses isLoading, while this test uses isFetching. Both assertions are valid for disabled queries, but using isLoading would maintain consistency with the existing test pattern in this file.

♻️ Optional: align with existing test pattern
-    expect(result.current.isFetching).toBe(false);
+    expect(result.current.isLoading).toBe(false);

229-249: Consider using explicit initialProps pattern for clearer re-render tests.

The current closure-based approach works, but React Testing Library's explicit initialProps pattern is more readable and makes the prop change explicit. This avoids relying on closure capture semantics.

♻️ Optional: use explicit initialProps pattern
   it('should re-fetch when organizationUnitId changes', async () => {
     mockHttpRequest.mockResolvedValue({data: mockUserList});
 
-    let ouId = 'ou-123';
-    const {result, rerender} = renderHook(() => useGetOrganizationUnitUsers(ouId));
+    const {result, rerender} = renderHook(
+      ({id}: {id: string}) => useGetOrganizationUnitUsers(id),
+      {initialProps: {id: 'ou-123'}},
+    );
 
     await waitFor(() => {
       expect(result.current.data).toEqual(mockUserList);
     });
 
-    ouId = 'ou-456';
-    rerender();
+    rerender({id: 'ou-456'});
 
     await waitFor(() => {
       expect(mockHttpRequest).toHaveBeenCalledWith(
         expect.objectContaining({
           url: expect.stringContaining('/organization-units/ou-456/users') as unknown,
         }),
       );
     });
   });
frontend/apps/thunder-develop/src/features/organization-units/api/__tests__/useGetOrganizationUnit.test.ts (2)

187-198: Combine this with the existing “enabled is false” test to avoid duplication.

You already have a test at Lines 94-105 covering enabled === false with a valid id. Consider extending that test to assert isFetching === false instead of adding a near-duplicate case.


190-206: Avoid real timers; use waitFor (or fake timers) for deterministic tests.

The 100ms setTimeout introduces avoidable latency/flakiness. Prefer waitFor assertions so the test resolves as soon as the state settles.

♻️ Proposed change (use waitFor instead of setTimeout)
-    // Wait a bit to ensure query doesn't execute
-    await new Promise((resolve) => {
-      setTimeout(resolve, 100);
-    });
-
-    expect(result.current.isFetching).toBe(false);
-    expect(result.current.data).toBeUndefined();
-    expect(mockHttpRequest).not.toHaveBeenCalled();
+    await waitFor(() => {
+      expect(result.current.isFetching).toBe(false);
+      expect(result.current.data).toBeUndefined();
+      expect(mockHttpRequest).not.toHaveBeenCalled();
+    });
-    // Wait a bit to ensure query doesn't execute
-    await new Promise((resolve) => {
-      setTimeout(resolve, 100);
-    });
-
-    expect(result.current.isFetching).toBe(false);
-    expect(result.current.data).toBeUndefined();
-    expect(mockHttpRequest).not.toHaveBeenCalled();
+    await waitFor(() => {
+      expect(result.current.isFetching).toBe(false);
+      expect(result.current.data).toBeUndefined();
+      expect(mockHttpRequest).not.toHaveBeenCalled();
+    });
frontend/apps/thunder-develop/src/hooks/__tests__/useDataGridLocaleText.test.tsx (1)

27-464: Consider adding afterEach for consistent mock cleanup.

While each test properly calls vi.restoreAllMocks(), adding a shared cleanup at the describe level would provide a safety net if future tests forget cleanup or if a test fails before reaching the cleanup code:

 describe('useDataGridLocaleText', () => {
+  afterEach(() => {
+    vi.restoreAllMocks();
+  });
+
   it('should return localized text object for DataGrid', () => {

This is optional but improves test resilience.

frontend/apps/thunder-develop/src/features/organization-units/pages/__tests__/OrganizationUnitEditPage.test.tsx (1)

925-953: Test relies on conditional execution that may silently pass if button not found.

The if (nameEditButton) pattern means this test will pass without executing assertions if the button isn't found. Consider failing explicitly if the button is missing.

💡 Suggested improvement
     const nameEditButton = editButtons.find(
       (btn) => btn.querySelector('svg') && btn.closest('div')?.textContent?.includes('Test Organization Unit'),
     );

-    if (nameEditButton) {
+    expect(nameEditButton).toBeDefined();
+    if (nameEditButton) {
       fireEvent.click(nameEditButton);

Alternatively, use expect(nameEditButton).toBeDefined() before the conditional to ensure the test fails properly if the button isn't found.

frontend/apps/thunder-develop/src/features/organization-units/components/__tests__/OrganizationUnitsList.test.tsx (1)

572-591: Test data intentionally omits description property.

The test at line 579 creates an organization unit without a description property to test undefined handling. This is valid but could benefit from an inline comment for clarity.

📝 Consider adding a clarifying comment
         organizationUnits: [
+          // Intentionally omit description to test undefined handling
           {id: 'ou-1', handle: 'test', name: 'Test OU', parent: null},
         ],
frontend/apps/thunder-gate/src/__tests__/components/SignUp/SignUpBox.test.tsx (1)

1562-1607: Consider asserting no React key warnings for fallback-key coverage.

This test’s intent is about fallback keys, but it only checks rendering. You can make the intent concrete by asserting no key warning is logged.

Proposed test enhancement
   it('uses fallback index keys when components have undefined id', () => {
+    const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
     mockSignUpRenderProps = createMockSignUpRenderProps({
       components: [
         {
           type: 'TEXT',
           label: 'Create Account',
@@
     render(<SignUpBox />);
     expect(screen.getByText('Create Account')).toBeInTheDocument();
     expect(screen.getByLabelText(/First Name/)).toBeInTheDocument();
+    expect(consoleErrorSpy).not.toHaveBeenCalledWith(
+      expect.stringContaining('Each child in a list should have a unique "key"')
+    );
+    consoleErrorSpy.mockRestore();
   });
frontend/apps/thunder-develop/src/features/organization-units/api/__tests__/useGetChildOrganizationUnits.test.ts (1)

229-250: Consider using initialProps pattern for clearer re-render testing.

The mutable closure variable approach works but is less explicit. Using renderHook with initialProps makes the test intent clearer and is the recommended pattern from Testing Library.

♻️ Suggested refactor using initialProps pattern
 it('should re-fetch when parentId changes', async () => {
   mockHttpRequest.mockResolvedValue({data: mockChildOUList});

-  let parentId = 'parent-1';
-  const {result, rerender} = renderHook(() => useGetChildOrganizationUnits(parentId));
+  const {result, rerender} = renderHook(
+    ({parentId}) => useGetChildOrganizationUnits(parentId),
+    {initialProps: {parentId: 'parent-1'}},
+  );

   await waitFor(() => {
     expect(result.current.data).toEqual(mockChildOUList);
   });

   // Change parentId and re-render
-  parentId = 'parent-2';
-  rerender();
+  rerender({parentId: 'parent-2'});

   await waitFor(() => {
     expect(mockHttpRequest).toHaveBeenCalledWith(
       expect.objectContaining({
         url: expect.stringContaining('/organization-units/parent-2/ous') as unknown,
       }),
     );
   });
 });
frontend/apps/thunder-develop/src/features/organization-units/components/edit-organization-unit/__tests__/EditChildOUs.test.tsx (1)

286-297: Consider consolidating with existing avatar test.

This test is similar to the existing test at lines 207-216 ("should render avatars for each child OU"). The only difference is the assertion >= 2 vs > 0. Consider whether both tests are needed or if the existing test should be updated with the more specific assertion.

frontend/apps/thunder-develop/src/features/organization-units/components/edit-organization-unit/__tests__/EditGroups.test.tsx (1)

173-184: Consider consolidating duplicate avatar assertions.

This overlaps with the earlier “should render avatars for each group” test. You could merge to keep one strong assertion (e.g., count ≥ expected rows).

frontend/apps/thunder-develop/src/features/organization-units/components/edit-organization-unit/__tests__/EditUsers.test.tsx (1)

173-184: Consider consolidating duplicate avatar assertions.

This overlaps with the earlier avatar test; merging can reduce redundancy.

Copilot AI review requested due to automatic review settings February 5, 2026 17:47
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 68 out of 69 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • frontend/pnpm-lock.yaml: Language not supported

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Fix all issues with AI agents
In
`@frontend/apps/thunder-develop/src/components/Header/__tests__/LanguageSwitcher.test.tsx`:
- Around line 254-402: The test suite uses vi.clearAllMocks() which only clears
call history; change the beforeEach to call vi.resetAllMocks() (or explicitly
reset mockUseLanguage's implementation) so mockReturnValue overrides in tests do
not leak between cases; update the file's beforeEach that currently calls
vi.clearAllMocks() to use vi.resetAllMocks() or add a helper that calls
mockUseLanguage.mockReset() and re-establishes a default implementation,
ensuring references to mockUseLanguage, mockSetLanguage, and other mocks are
fully reset before each test.

In
`@frontend/apps/thunder-develop/src/features/applications/components/edit-application/token-settings/__tests__/TokenUserAttributesSection.test.tsx`:
- Around line 411-435: The test TokenUserAttributesSection.test.tsx claims
newAttribute should NOT appear when activeTokenType ("id") doesn't match
tokenType ("access") but only asserts 'email' is present; update the test for
TokenUserAttributesSection to also assert that the pending addition value (e.g.,
'newAttribute') is NOT present in container.textContent when passing
pendingAdditions and activeTokenType !== tokenType, ensuring the negative case
for pendingAdditions is verified alongside the existing positive assertion for
'email'.

In
`@frontend/apps/thunder-develop/src/features/applications/pages/__tests__/ApplicationCreatePage.test.tsx`:
- Around line 1102-1153: The test’s vi.doMock call has no effect because
ApplicationCreatePage/ApplicationCreateProvider already imported useGetUserTypes
earlier; replace the dynamic per-test doMock by using a hoisted mutable mock
(e.g., define mockUserTypesData via vi.hoisted and have the vi.mock for
'../../../user-types/api/useGetUserTypes' return that object) and in this test
mutate mockUserTypesData.schemas = [{name: 'customer', displayName: 'Customer'}]
before calling renderWithProviders(); alternatively, if you prefer isolating
imports per-test, call vi.resetModules() then dynamically import
ApplicationCreatePage/ApplicationCreateProvider after registering vi.doMock for
useGetUserTypes so the new mock is used.

In
`@frontend/apps/thunder-develop/src/features/applications/pages/__tests__/ApplicationEditPage.test.tsx`:
- Around line 1060-1122: The tests overwrite navigator.clipboard but never
restore it, risking global test leakage; save the original clipboard reference
before mutating (e.g., const originalClipboard = navigator.clipboard) and
restore it in an afterEach/afterAll teardown inside the same "Copy to Clipboard"
describe block; for each test where you call Object.defineProperty(navigator,
'clipboard', { value: { writeText: mockWriteText }, ... }), restore by
re-defining navigator.clipboard back to originalClipboard (or delete the
property if originalClipboard is undefined) so functions like mockWriteText and
renderComponent/EditGeneralSettingsMock do not leak state to other tests.

In
`@frontend/apps/thunder-develop/src/features/organization-units/components/edit-organization-unit/__tests__/EditGroups.test.tsx`:
- Around line 193-197: The test "should pass organizationUnitId to the API hook"
doesn't assert the hook was called with the expected ID; update the test for
EditGroups to verify mockUseGetOrganizationUnitGroups received "different-ou"
(or adjust the mock to capture its argument) when rendering via
renderWithProviders(<EditGroups organizationUnitId="different-ou" />), by spying
on or implementing the mock for mockUseGetOrganizationUnitGroups to record its
call and asserting
expect(mockUseGetOrganizationUnitGroups).toHaveBeenCalledWith(expect.objectContaining({
organizationUnitId: 'different-ou' })) or remove the test if capturing the
argument is not feasible with the current mock structure.

In `@frontend/packages/thunder-shared-branding/package.json`:
- Around line 67-68: The package.json currently lists
"@vitest/browser-playwright" and "vitest" but is missing the required peer
dependency for Playwright; add "playwright": "catalog:" to the devDependencies
section of this package.json so `@vitest/browser-playwright` has its peer
satisfied (update the devDependencies object alongside the existing
"@vitest/browser-playwright" and "vitest" entries).

In `@frontend/pnpm-workspace.yaml`:
- Around line 28-29: Add a pinned playwright entry to the pnpm workspace catalog
so `@vitest/browser-playwright` can consume it as a peer dependency; update the
catalog block that contains '@vitest/browser-playwright' and
'@vitest/coverage-istanbul' by adding a new key "playwright" with a fixed
version (for example "1.36.1") so packages can reference it via "playwright":
"catalog:".
🧹 Nitpick comments (15)
frontend/apps/thunder-develop/src/features/login-flow/hooks/__tests__/useFlowSave.test.ts (1)

84-86: Type casts correctly match declarations.

The explicit casts ensure type consistency between declaration and initialization.

Consider extracting a type alias if this pattern expands to more mocks, though current usage is reasonable.

♻️ Optional: Type alias to reduce repetition
+type MockFn<T extends (...args: unknown[]) => unknown> = ReturnType<typeof vi.fn> & T;
+
 describe('useFlowSave', () => {
-  let mockShowError: ReturnType<typeof vi.fn> & ((message: string) => void);
-  let mockShowSuccess: ReturnType<typeof vi.fn> & ((message: string) => void);
-  let mockSetOpenValidationPanel: ReturnType<typeof vi.fn> & ((open: boolean) => void);
+  let mockShowError: MockFn<(message: string) => void>;
+  let mockShowSuccess: MockFn<(message: string) => void>;
+  let mockSetOpenValidationPanel: MockFn<(open: boolean) => void>;

   beforeEach(() => {
     vi.clearAllMocks();
     vi.useFakeTimers();
-    mockShowError = vi.fn() as ReturnType<typeof vi.fn> & ((message: string) => void);
-    mockShowSuccess = vi.fn() as ReturnType<typeof vi.fn> & ((message: string) => void);
-    mockSetOpenValidationPanel = vi.fn() as ReturnType<typeof vi.fn> & ((open: boolean) => void);
+    mockShowError = vi.fn() as MockFn<(message: string) => void>;
+    mockShowSuccess = vi.fn() as MockFn<(message: string) => void>;
+    mockSetOpenValidationPanel = vi.fn() as MockFn<(open: boolean) => void>;
   });
frontend/apps/thunder-develop/src/features/applications/components/edit-application/general-settings/__tests__/AccessSection.test.tsx (1)

289-323: Consider making the assertion more specific about the value passed.

The test correctly validates that onFieldChange is called for the URL field after rerender, but the assertion at lines 320-321 only verifies that at least one call was made. Asserting the exact value would strengthen the test's coverage and align with the more specific assertion pattern used in ContactsSection.test.tsx.

✨ Proposed refinement for stronger assertion
       // The useEffect sees that the form's watched url !== currentUrl (which is now 'https://changed.com')
       // so it calls onFieldChange with the form's current value
       await waitFor(() => {
-        const urlCalls = mockOnFieldChange.mock.calls.filter((call) => call[0] === 'url');
-        expect(urlCalls.length).toBeGreaterThan(0);
+        expect(mockOnFieldChange).toHaveBeenCalledWith('url', 'https://example.com');
       });
frontend/apps/thunder-develop/src/i18n/__tests__/I18nProvider.test.tsx (2)

423-465: Consider asserting call count to verify memoization behavior.

The test comments indicate the intent is to "exercise the React Compiler memoization skip paths," but the assertions only verify the arguments passed to mockAddResourceBundle, not how many times it was called. To confirm memoization is preventing redundant calls across re-renders, consider adding a call count assertion:

    // Translations should still be merged correctly after re-renders
+   // Verify memoization prevents duplicate calls on re-render
+   expect(mockAddResourceBundle).toHaveBeenCalledTimes(1);
    expect(mockAddResourceBundle).toHaveBeenCalledWith(
      'en-US',
      'common',
      expect.objectContaining({greeting: 'Hello'}),
      true,
      true,
    );

Without this, the test verifies the component handles re-renders gracefully but doesn't prove the memoization is working as intended.


467-502: Assertions don't verify cached memoization behavior.

The test description and comments state the goal is to "exercise cached paths" for the React Compiler's internal cache, but the only assertions check that the text remains in the document—which would pass regardless of whether memoization is working.

To meaningfully verify caching behavior, consider asserting that mockAddResourceBundle is called only once despite multiple rerenders:

    expect(getByText('Test')).toBeInTheDocument();
+
+   // Verify memoization: addResourceBundle should not be called again on rerender
+   expect(mockAddResourceBundle).toHaveBeenCalledTimes(1);
  });

Alternatively, if the intent is simply to ensure the component doesn't break on rerender (smoke test), consider updating the test name and comments to reflect that purpose rather than referencing memoization.

frontend/apps/thunder-develop/src/features/applications/components/edit-application/token-settings/__tests__/TokenUserAttributesSection.test.tsx (1)

446-465: Test lacks meaningful assertions for toggle behavior.

The test clicks the accordion button twice but doesn't verify that the accordion actually toggles. It only asserts that the button exists. Consider adding assertions to verify the expanded/collapsed state or content visibility changes.

Suggested improvement with state verification
     it('should toggle default attributes accordion when clicked', async () => {
       const user = userEvent.setup();

       render(<TestWrapper />);

       // Find the Default Attributes accordion header
       const defaultAttributesHeader = screen.getByText('Default Attributes');
       const accordionButton = defaultAttributesHeader.closest('button');

       expect(accordionButton).toBeDefined();

       if (accordionButton) {
+        // Verify accordion is initially in expected state (expanded by component default)
+        expect(accordionButton).toHaveAttribute('aria-expanded', 'true');
+
         // Click to collapse
         await user.click(accordionButton);
+        expect(accordionButton).toHaveAttribute('aria-expanded', 'false');
+
         // Click to expand again
         await user.click(accordionButton);
+        expect(accordionButton).toHaveAttribute('aria-expanded', 'true');
       }
     });
frontend/apps/thunder-develop/src/features/organization-units/pages/__tests__/OrganizationUnitEditPage.test.tsx (2)

937-952: Consider using an assertion instead of conditional block to avoid silent test passes.

The if (nameEditButton) pattern will cause the test to pass silently without executing any assertions if the button is not found. This pattern exists in other tests in this file, but for new tests, consider failing explicitly if the required element is missing.

♻️ Proposed refactor to fail explicitly
-    if (nameEditButton) {
-      fireEvent.click(nameEditButton);
+    expect(nameEditButton).toBeDefined();
+    fireEvent.click(nameEditButton!);
 
-      await waitFor(() => {
-        expect(screen.getByDisplayValue('Test Organization Unit')).toBeInTheDocument();
-      });
+    await waitFor(() => {
+      expect(screen.getByDisplayValue('Test Organization Unit')).toBeInTheDocument();
+    });
 
-      const textbox = screen.getByDisplayValue('Test Organization Unit');
-      fireEvent.change(textbox, {target: {value: '  '}});
-      fireEvent.keyDown(textbox, {key: 'Enter'});
+    const textbox = screen.getByDisplayValue('Test Organization Unit');
+    fireEvent.change(textbox, {target: {value: '  '}});
+    fireEvent.keyDown(textbox, {key: 'Enter'});
 
-      // Should not show unsaved changes since empty names are not saved
-      await waitFor(() => {
-        expect(screen.getByText('Test Organization Unit')).toBeInTheDocument();
-      });
-    }
+    // Should not show unsaved changes since empty names are not saved
+    await waitFor(() => {
+      expect(screen.getByText('Test Organization Unit')).toBeInTheDocument();
+    });

1067-1072: Prefer Testing Library queries over direct DOM access.

Using document.querySelector('textarea') bypasses Testing Library's accessibility-focused queries. Consider using screen.getByRole('textbox') or a similar query for consistency with the rest of the test file.

♻️ Proposed refactor
       await waitFor(() => {
-        const textbox = document.querySelector('textarea');
-        expect(textbox).toBeInTheDocument();
+        expect(screen.getByRole('textbox')).toBeInTheDocument();
       });

-      const textbox = document.querySelector('textarea')!;
+      const textbox = screen.getByRole('textbox');
       fireEvent.change(textbox, {target: {value: 'New description'}});
frontend/apps/thunder-develop/src/features/organization-units/api/__tests__/useGetOrganizationUnits.test.ts (2)

238-246: Consider using initialProps pattern for cleaner re-render testing.

The current approach using let params reassignment relies on closure behavior. While this works, the idiomatic pattern using initialProps makes the test's intent more explicit:

♻️ Suggested refactor using initialProps pattern
-    let params = {limit: 10, offset: 0};
-    const {result, rerender} = renderHook(() => useGetOrganizationUnits(params));
+    const {result, rerender} = renderHook(
+      (props: {limit: number; offset: number}) => useGetOrganizationUnits(props),
+      {initialProps: {limit: 10, offset: 0}},
+    );

     await waitFor(() => {
       expect(result.current.data).toEqual(mockOrganizationUnitList);
     });

-    params = {limit: 10, offset: 10};
-    rerender();
+    rerender({limit: 10, offset: 10});

248-253: as unknown cast appears inconsistent with other assertions in this file.

The as unknown cast on line 251 is not used in similar expect.objectContaining assertions elsewhere in this file (e.g., lines 78-82, 91-96, 106-111). If this cast is required for Vitest v4 type compatibility, consider applying it consistently across all similar assertions, or removing it if unnecessary.

frontend/apps/thunder-develop/src/features/organization-units/components/edit-organization-unit/__tests__/EditGroups.test.tsx (2)

173-184: Duplicate test coverage with existing test.

This test is nearly identical to the test at lines 145-154 (should render avatars for each group). Both render the component, wait for group names, then query .MuiAvatar-root and assert the count. Consider removing one of them to avoid redundant coverage.


220-231: Test doesn't meaningfully verify re-render behavior.

The comment says "exercise memoization update paths" but the only assertion after rerender checks for static text ("Groups") that doesn't change between renders. Consider asserting that the component reflects the new prop or that the hook is called with the updated ID.

frontend/apps/thunder-develop/src/features/organization-units/api/__tests__/useDeleteOrganizationUnit.test.ts (1)

195-204: Consider restoring the spy after the test.

The spy on queryClient.invalidateQueries is not explicitly restored. While vi.clearAllMocks() in afterEach resets mock call history, it does not restore the original implementation of spied methods. For better test isolation, consider restoring the spy.

♻️ Suggested improvement
     // Spy on invalidateQueries to make it reject
     const invalidateSpy = vi.spyOn(queryClient, 'invalidateQueries').mockRejectedValue(new Error('Invalidation failed'));
 
     result.current.mutate('ou-123');
 
     await waitFor(() => {
       expect(result.current.isSuccess).toBe(true);
     });
 
     // Mutation should still succeed despite invalidation failure
     expect(invalidateSpy).toHaveBeenCalled();
+
+    // Restore the original implementation
+    invalidateSpy.mockRestore();
   });

Alternatively, you can add vi.restoreAllMocks() to the afterEach block to restore all spies globally.

frontend/apps/thunder-develop/src/components/Navbar/__tests__/NavbarBreadcrumbs.test.tsx (2)

179-209: Consolidate the repeated page cases with a parameterized test.

This trims duplication while keeping coverage identical.

♻️ Suggested refactor
-  it('renders breadcrumbs for organization-units page', async () => {
-    const mockUseNavigation = await import('@/layouts/contexts/useNavigation');
-    vi.mocked(mockUseNavigation.default).mockReturnValue({
-      currentPage: 'organization-units',
-      setCurrentPage: vi.fn(),
-      sidebarOpen: false,
-      setSidebarOpen: vi.fn(),
-      toggleSidebar: vi.fn(),
-    });
-
-    render(<NavbarBreadcrumbs />);
-
-    expect(screen.getByText('Develop')).toBeInTheDocument();
-    expect(screen.getByText('Organization Units')).toBeInTheDocument();
-  });
-
-  it('renders breadcrumbs for flows page', async () => {
-    const mockUseNavigation = await import('@/layouts/contexts/useNavigation');
-    vi.mocked(mockUseNavigation.default).mockReturnValue({
-      currentPage: 'flows',
-      setCurrentPage: vi.fn(),
-      sidebarOpen: false,
-      setSidebarOpen: vi.fn(),
-      toggleSidebar: vi.fn(),
-    });
-
-    render(<NavbarBreadcrumbs />);
-
-    expect(screen.getByText('Develop')).toBeInTheDocument();
-    expect(screen.getByText('Flows')).toBeInTheDocument();
-  });
+  it.each([
+    {currentPage: 'organization-units', label: 'Organization Units'},
+    {currentPage: 'flows', label: 'Flows'},
+  ])('renders breadcrumbs for $currentPage page', async ({currentPage, label}) => {
+    const mockUseNavigation = await import('@/layouts/contexts/useNavigation');
+    vi.mocked(mockUseNavigation.default).mockReturnValue({
+      currentPage,
+      setCurrentPage: vi.fn(),
+      sidebarOpen: false,
+      setSidebarOpen: vi.fn(),
+      toggleSidebar: vi.fn(),
+    });
+
+    render(<NavbarBreadcrumbs />);
+
+    expect(screen.getByText('Develop')).toBeInTheDocument();
+    expect(screen.getByText(label)).toBeInTheDocument();
+  });

223-282: Avoid relying on MUI-generated class names in assertions.

Selectors like .MuiTypography-body1, .MuiBreadcrumbs-ol, .MuiBox-root, and .MuiBreadcrumbs-separator are implementation details and may change with MUI upgrades or class name generator tweaks. Prefer semantic queries (role/label/text) or add stable test IDs for structure-specific assertions.

frontend/packages/thunder-shared-hooks/package.json (1)

63-64: Explicitly declare playwright for clarity and robustness.

While @vitest/browser-playwright declares playwright as a peer dependency (v1.58.1), it is currently being auto-resolved by pnpm. For clarity and to avoid potential issues with stricter peer dependency configurations, add "playwright": "catalog:" to devDependencies. Note: playwright is already available in the lock file and the build currently works.

🔧 Proposed addition
     "@vitest/browser-playwright": "catalog:",
+    "playwright": "catalog:",
     "vitest": "catalog:"

Also add playwright to the workspace catalog in frontend/pnpm-workspace.yaml if not already present for version consistency.

@DonOmalVindula DonOmalVindula force-pushed the migrate-vitest-v4 branch 2 times, most recently from 86069b3 to ca82712 Compare February 6, 2026 06:06
Copy link

@coderabbitai coderabbitai bot left a 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

🤖 Fix all issues with AI agents
In
`@frontend/apps/thunder-develop/src/features/applications/components/edit-application/integration-guides/__tests__/TechnologyGuide.test.tsx`:
- Around line 344-347: The test uses an ineffective regex (/\ .js$/) to assert
no filename is rendered; update the assertion to directly check for the specific
filename text that would appear (e.g.,
expect(screen.queryByText('index.js')).not.toBeInTheDocument()) or assert the
filename container is absent (e.g.,
expect(screen.queryByTestId('filename')).not.toBeInTheDocument()). Replace the
current screen.queryByText(/\.js$/) check and keep the existing codeBlocks
assertion unchanged.

In
`@frontend/apps/thunder-develop/src/features/applications/pages/__tests__/ApplicationEditPage.test.tsx`:
- Around line 556-583: The test "should open logo modal when edit button on
avatar is clicked" currently falls back to clicking the avatar if the avatar
edit button isn't found; change it to assert the edit button exists so the
edit-button path is always exercised: locate the avatar container (using
getByRole('img') and avatarSection?.querySelectorAll('button')), add an explicit
assertion that buttonsInAvatarSection exists and has length > 0 (fail the test
if not), then perform await user.click(buttonsInAvatarSection[0]) and waitFor
the 'logo-update-modal' to be visible; remove the fallback branch that clicks
the avatar directly.

In
`@frontend/apps/thunder-develop/src/hooks/__tests__/useDataGridLocaleText.test.tsx`:
- Around line 323-351: The test fails because import.meta.env.DEV is false
during Vitest runs so the DEV-only console.warn in useDataGridLocaleText never
runs; fix by either (A) making the test run in DEV by mocking the env before
rendering the hook (e.g., in the test for useDataGridLocaleText, set
import.meta.env.DEV to true via a test-time mock/stub so the console.warn path
in useDataGridLocaleText executes and your consoleSpy assertion passes) or (B)
avoid relying on DEV-only behavior by removing the console warning assertion
from the test (or instead assert the non-function result only). Locate the
failing test in useDataGridLocaleText.test.tsx and adjust the setup around
renderHook/useDataGridLocaleText accordingly or update vite.test define config
to set import.meta.env.DEV to 'true' if you prefer a global change.
🧹 Nitpick comments (19)
frontend/apps/thunder-develop/src/features/applications/components/edit-application/token-settings/__tests__/TokenValidationSection.test.tsx (1)

316-324: Duplicate test case.

This test duplicates the existing test at lines 113-121 ("should render helper text when no error"), which already verifies that the default hint text is displayed when there's no error for the shared token type.

Consider removing this duplicate or, if the intent is to group all hint/error-related assertions together, removing the original test from the "Rendering" block instead.

♻️ Suggested removal
   describe('Error States', () => {
     // ... error tests ...

-    it('should display default hint when no error', () => {
-      render(
-        <TestWrapper>
-          {({control, errors}) => <TokenValidationSection control={control} errors={errors} tokenType="shared" />}
-        </TestWrapper>,
-      );
-
-      expect(screen.getByText('Token validity period in seconds (e.g., 3600 for 1 hour)')).toBeInTheDocument();
-    });
   });
frontend/apps/thunder-develop/src/features/applications/components/edit-application/advanced-settings/__tests__/OAuth2ConfigSection.test.tsx (1)

303-327: Consider adding explicit assertions for the absence of chips.

The comments on lines 313 and 326 indicate that no chips should be rendered, but there are no explicit assertions to verify this. Adding assertions would make the tests more robust.

💡 Suggested assertions
       render(<OAuth2ConfigSection oauth2Config={oauth2Config} />);

       expect(screen.getByText('applications:edit.advanced.labels.grantTypes')).toBeInTheDocument();
-      // No chips should be rendered for grant types
+      // Verify no grant type chips are rendered
+      expect(screen.queryByText('authorization_code')).not.toBeInTheDocument();
     });

     it('should handle undefined response_types gracefully', () => {
       const oauth2Config = {
         grant_types: ['authorization_code'],
         pkce_required: false,
         public_client: false,
       } as OAuth2Config;

       render(<OAuth2ConfigSection oauth2Config={oauth2Config} />);

       expect(screen.getByText('applications:edit.advanced.labels.responseTypes')).toBeInTheDocument();
-      // No chips should be rendered for response types
+      // Verify no response type chips are rendered (only the grant type chip should exist)
+      expect(screen.queryByText('code')).not.toBeInTheDocument();
+      expect(screen.queryByText('token')).not.toBeInTheDocument();
     });
frontend/apps/thunder-gate/src/__tests__/components/AcceptInvite/AcceptInviteBox.test.tsx (2)

1370-1394: Test name is misleading - consider renaming or adding alignment assertion.

The test is named "renders with branding enabled and centered text alignment" but doesn't verify text alignment. It only checks that the text is rendered. Consider either:

  1. Renaming to "renders TEXT component with branding enabled"
  2. Adding an assertion that verifies the alignment (e.g., checking the style or class)

1396-1429: Consider adding assertions for logo attributes to match test names.

These tests verify that the component renders with various branding configurations, but don't assert on the specific attributes mentioned in the test names (alt fallback, custom alt/height/width). While they're valuable as smoke tests, consider adding assertions like:

const logo = screen.getByRole('img');
expect(logo).toHaveAttribute('alt', 'Custom Alt');
expect(logo).toHaveAttribute('height', '50');

This would make the tests more specific and aligned with their names.

frontend/apps/thunder-develop/src/components/Header/__tests__/LanguageSwitcher.test.tsx (1)

395-402: Test may be affected by mock state from previous test.

This test relies on the default mock implementation, but the previous test (line 377) sets availableLanguages: []. Since vi.clearAllMocks() doesn't reset implementations, this test may run with an empty languages array.

However, this test only checks that the button exists (not the menu content), so it would still pass. Consider adding an explicit mock reset or explicit mock setup here for test isolation and clarity.

♻️ Suggested improvement for test isolation
   it('should preserve button after re-render', () => {
+    mockUseLanguage.mockReturnValue({
+      currentLanguage: 'en-US' as const,
+      availableLanguages: [
+        {code: 'en-US' as const, name: 'English (United States)', nativeName: 'English (US)', direction: 'ltr' as const},
+      ],
+      setLanguage: vi.fn(),
+    });
+
     const {rerender} = render(<LanguageSwitcher />);

     rerender(<LanguageSwitcher />);

     const button = screen.getByRole('button', {name: /change language/i});
     expect(button).toBeInTheDocument();
   });
frontend/apps/thunder-develop/src/components/Header/__tests__/Search.test.tsx (1)

81-110: Tests rely on MUI internal class names which may change.

These tests use selectors like .MuiOutlinedInput-root, .MuiInputAdornment-positionStart, .MuiInputBase-sizeSmall, and .MuiFormControl-root. While functional, these are implementation details that could break if MUI changes its class naming convention.

Consider whether these structural tests add value beyond the existing behavioral tests (lines 24-79) that already verify the component renders correctly with the expected functionality.

frontend/apps/thunder-develop/src/components/Navbar/__tests__/AppNavbar.test.tsx (2)

180-186: Test name and assertion mismatch.

The test is named "renders with gradient background styling" but only asserts the borderRadius property. While borderRadius: '999px' is part of the component's styling, it doesn't verify the gradient background. Consider either:

  1. Renaming the test to match what it actually verifies (e.g., "renders with circular border radius")
  2. Adding an assertion for the gradient background if that's the intended behavior to test
✏️ Suggested rename for accuracy
-  it('renders with gradient background styling', () => {
+  it('renders with circular border radius styling', () => {
     const {container} = render(<CustomIcon />);

     const box = container.querySelector('.MuiBox-root');
     expect(box).toBeInTheDocument();
     expect(box).toHaveStyle({borderRadius: '999px'});
   });

132-136: Consider consolidating redundant test.

This test for rendering SideMenuMobile is redundant since the same assertion (screen.getByTestId('side-menu-mobile')) is already made in the "opens mobile menu when menu button is clicked" test (line 91) and "closes mobile menu when toggleDrawer is called with false" test (line 107).

frontend/apps/thunder-develop/src/features/applications/components/__tests__/ApplicationsList.test.tsx (3)

495-525: Test may not validate what it claims.

The mockRejectedValueOnce setup is semantically incorrect for useNavigate. React Router's navigate function is synchronous and doesn't return a Promise, so setting up a rejected Promise doesn't actually test error handling in a meaningful way. The test passes because the component never awaits the result.

If the intent is to test component resilience, consider either:

  1. Removing this test if navigation errors aren't a realistic scenario
  2. Testing a scenario where the navigate function throws synchronously instead
♻️ Suggested alternative if testing synchronous throw
 it('should handle navigation error gracefully', async () => {
   const user = userEvent.setup();
-  const navigationError = new Error('Navigation failed');
-  mockNavigate.mockRejectedValueOnce(navigationError);
+  mockNavigate.mockImplementationOnce(() => {
+    throw new Error('Navigation failed');
+  });

527-543: Assertion doesn't verify the claimed behavior.

The comment states "The onError handler should set src to empty string," but the assertion only checks that the element remains in the document. This would pass regardless of whether the error handling actually works.

♻️ Suggested fix for stronger assertion
   if (avatars[0]) {
     avatars[0].dispatchEvent(new Event('error'));
-    // The onError handler should set src to empty string
-    expect(avatars[0]).toBeInTheDocument();
+    // Verify the onError handler sets src to empty string
+    expect(avatars[0]).toHaveAttribute('src', '');
   }

359-368: Conditional guards may silently skip assertions.

The if (rows[1]) check means if the row doesn't exist (due to a bug or mock change), the test passes without validating navigation behavior. Consider asserting the row exists before clicking.

♻️ Suggested fix
   const rows = screen.getAllByRole('row');
-  // Click on first data row (index 1, as 0 is the header)
-  if (rows[1]) {
-    await user.click(rows[1]);
-
-    await waitFor(() => {
-      expect(mockNavigate).toHaveBeenCalledWith('/applications/app-1');
-    });
-  }
+  // Click on first data row (index 0 since mock DataGrid has no header row)
+  expect(rows[0]).toBeDefined();
+  await user.click(rows[0]);
+
+  await waitFor(() => {
+    expect(mockNavigate).toHaveBeenCalledWith('/applications/app-1');
+  });
frontend/apps/thunder-develop/src/features/applications/components/edit-application/token-settings/__tests__/TokenUserAttributesSection.test.tsx (1)

446-465: Consider adding assertions for accordion state changes.

The test clicks the accordion button twice but doesn't verify any state changes. Currently, it only confirms the button exists and can be clicked without throwing errors.

If testing MUI accordion expanded/collapsed state is challenging (as noted in line 300-302 comments), consider at minimum asserting that the default attributes (e.g., 'aud', 'exp') are visible/hidden after toggling, or add a comment explaining the test's limited scope.

frontend/apps/thunder-develop/src/features/applications/components/edit-application/integration-guides/__tests__/TechnologyGuide.test.tsx (3)

228-347: Duplicate tests with the "Code Block Language Mapping" describe block.

The tests added in the "Code Blocks" describe block (lines 229-347) duplicate tests already present in the "Code Block Language Mapping" describe block (lines 661-783):

| Lines 229-251 | duplicates | Lines 662-684 |
| Lines 253-276 | duplicates | Lines 686-709 |
| Lines 278-299 | duplicates | Lines 711-733 |
| Lines 301-322 | duplicates | Lines 735-757 |
| Lines 324-347 | duplicates | Lines 759-782 |

Consider removing one set of these duplicate tests to reduce maintenance overhead and test execution time.


229-251: Assertion does not verify the actual language mapping.

The test claims to verify that terminal maps to bash, but the assertion only checks that a <pre> element exists. It doesn't verify the language prop passed to SyntaxHighlighter.

To properly test the mapping, you could either:

  1. Mock SyntaxHighlighter and assert the language prop
  2. Check for a class or attribute set by the highlighter that indicates the language

638-657: Near-duplicate of the preceding test.

This test is nearly identical to "should handle fallback failure gracefully for code" (lines 623-637). Both tests:

  • Reject the clipboard API
  • Make execCommand throw
  • Click the copy button

The only difference is the use of waitFor and the assertion target. The comment says it tests "the catch handler in onClick" but doesn't actually verify the catch handler behavior (e.g., that logger.error was called).

If the intent is to verify the logger error path, consider:

Proposed improvement to verify actual catch behavior
       it('should trigger the catch handler in onClick when handleCopyCode rejects', async () => {
+        const loggerErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
         // Make both clipboard API and fallback fail to ensure the promise rejects
         mockWriteText.mockRejectedValue(new Error('Clipboard API failed'));
 
         const mockExecCommand = vi.fn().mockImplementation(() => {
           throw new Error('execCommand failed');
         });
         document.execCommand = mockExecCommand;
 
         renderWithProviders(<TechnologyGuide guides={mockIntegrationGuides} templateId="react" />);
 
         const copyCodeButton = screen.getByTestId('copy-code-button-1');
         fireEvent.click(copyCodeButton);
 
-        // Wait for the async operation to complete - the catch handler should log error
         await waitFor(() => {
-          expect(mockExecCommand).toHaveBeenCalledWith('copy');
+          // Verify the error was logged (actual catch handler behavior)
+          expect(loggerErrorSpy).toHaveBeenCalled();
         });
+        
+        loggerErrorSpy.mockRestore();
       });

If logger.error from @thunder/logger is used (per the relevant code snippet), spy on that instead.

frontend/apps/thunder-develop/src/features/organization-units/components/edit-organization-unit/__tests__/EditGeneralSettings.test.tsx (1)

262-290: Strengthen assertions to actually validate the cleared-timeout behavior.

Right now this test passes even if the earlier timeout is not cleared, because it only checks copy calls and total count. Add a mid-interval assertion so the “Copied” state doesn’t reset early.

Suggested test strengthening
     await act(async () => {
       fireEvent.click(idCopyButton);
     });

     expect(mockClipboard.writeText).toHaveBeenCalledWith('ou-123');
+    expect(idCopyButton).toHaveAttribute('aria-label', 'Copied');

-    // Advance timers to trigger the reset
+    // Ensure previous timeout doesn't reset state early
+    await act(async () => {
+      vi.advanceTimersByTime(1999);
+    });
+    expect(idCopyButton).toHaveAttribute('aria-label', 'Copied');
+
+    // Advance timers to trigger the reset
     await act(async () => {
-      vi.advanceTimersByTime(2000);
+      vi.advanceTimersByTime(1);
     });

+    expect(idCopyButton).toHaveAttribute('aria-label', 'Copy');
     // Both copies should have been triggered
     expect(mockClipboard.writeText).toHaveBeenCalledTimes(2);
frontend/apps/thunder-develop/src/features/organization-units/components/edit-organization-unit/__tests__/EditUsers.test.tsx (1)

193-197: Test doesn't verify the assertion claimed in its title.

The test claims to verify that organizationUnitId is passed to the API hook, but it only checks that the UI renders. To properly verify the prop is passed, you should assert that the mock was called with the expected ID.

💡 Suggested improvement
 it('should pass organizationUnitId to the API hook', () => {
   renderWithProviders(<EditUsers organizationUnitId="different-ou" />);

-  expect(screen.getByText('Users')).toBeInTheDocument();
+  expect(mockUseGetOrganizationUnitUsers).toHaveBeenCalled();
+  expect(screen.getByText('Users')).toBeInTheDocument();
 });

Note: This requires the mock to track calls. Alternatively, rename the test to better reflect what it actually verifies.

frontend/apps/thunder-develop/src/features/organization-units/components/__tests__/OrganizationUnitDeleteDialog.test.tsx (1)

222-239: Potential duplicate test.

This test (should call onSuccess when provided on successful deletion) appears to duplicate the existing test at lines 106-121 (should call onClose and onSuccess on successful deletion). Both tests verify that onSuccess and onClose are called after successful deletion.

Consider removing one of these tests or differentiating their purposes more clearly.

frontend/apps/thunder-develop/src/features/organization-units/pages/__tests__/OrganizationUnitEditPage.test.tsx (1)

1068-1074: Non-null assertion on querySelector result.

Using the non-null assertion (!) on document.querySelector('textarea') could cause test failures with unclear error messages if the element isn't found. Consider adding an explicit null check or assertion.

💡 Suggested improvement
       await waitFor(() => {
         const textbox = document.querySelector('textarea');
         expect(textbox).toBeInTheDocument();
       });

-      const textbox = document.querySelector('textarea')!;
+      const textbox = document.querySelector('textarea');
+      expect(textbox).not.toBeNull();
       fireEvent.change(textbox, {target: {value: 'New description'}});

Copy link

@coderabbitai coderabbitai bot left a 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

🤖 Fix all issues with AI agents
In
`@frontend/apps/thunder-develop/src/components/Sidebar/__tests__/MenuContent.test.tsx`:
- Around line 178-309: The tests currently call
vi.mocked(mockUseNavigation.default).mockReturnValue(...) which persists across
tests and can leak state; change those calls in the tests that override
useNavigation (the blocks setting currentPage: 'users' and currentPage: 'flows')
to use mockReturnValueOnce(...) instead, or add a beforeEach that calls
vi.clearAllMocks()/vi.resetAllMocks() to reset the mocked useNavigation between
tests so each test remains isolated (refer to mockUseNavigation.default and
mockReturnValue/mockReturnValueOnce in the test file).
🧹 Nitpick comments (5)
frontend/apps/thunder-develop/src/features/applications/components/edit-application/advanced-settings/__tests__/CertificateSection.test.tsx (1)

305-321: Duplicate test case.

This test duplicates the behavior already covered by the existing test 'should prioritize editedApp certificate value over application' (lines 188-204). Both tests verify that when both application and editedApp have certificate values, the editedApp value is displayed.

Consider removing this test to avoid redundancy in the test suite.

frontend/apps/thunder-develop/src/features/applications/components/create-application/__tests__/ConfigureExperience.test.tsx (2)

375-400: Duplicate tests: These are identical to tests in the "Rendering" block.

The tests at lines 376-387 and 389-400 perform the exact same setup and assertions as tests at lines 53-63 and 65-75. Both only verify that a radio button is checked, which doesn't actually test "styling" as the test names suggest.

Consider removing these duplicates or, if the intent is to actually verify visual styling, add assertions that check for specific CSS classes or computed styles on the card elements.


402-442: Test names claim to verify styling but assertions only check text presence.

Both tests (should apply selected styles for user type cards and should apply non-selected styles for user type cards) only assert that text is in the document. They don't verify any actual styling differences between selected and non-selected states.

To properly test styling, consider asserting on the card's border color or CSS classes that differ based on selection state:

💡 Suggested approach for testing selection styling
-    it('should apply selected styles for user type cards', () => {
+    it('should apply selected styles for user type cards', () => {
       const mockUserTypes = [
         {id: '1', name: 'Internal', ouId: 'INTERNAL', allowSelfRegistration: true},
         {id: '2', name: 'External', ouId: 'EXTERNAL', allowSelfRegistration: false},
       ];

       render(
         <ConfigureExperience
           selectedApproach={ApplicationCreateFlowSignInApproach.INBUILT}
           onApproachChange={mockOnApproachChange}
           userTypes={mockUserTypes}
           selectedUserTypes={['Internal']}
           onUserTypesChange={vi.fn()}
         />,
       );

-      // User type cards should be rendered with Internal showing as selected
-      expect(screen.getByText('Internal')).toBeInTheDocument();
-      expect(screen.getByText('External')).toBeInTheDocument();
+      // Verify Internal card has selected styling (e.g., primary border)
+      const internalCard = screen.getByText('Internal').closest('[class*="MuiCard"]');
+      expect(internalCard).toHaveStyle({ borderColor: expect.stringMatching(/primary/) });
+      // Or check for a specific class indicating selection
     });
frontend/apps/thunder-develop/src/features/applications/components/edit-application/token-settings/__tests__/TokenUserAttributesSection.test.tsx (1)

459-478: Consider adding assertions for accordion state changes.

The test clicks the accordion button but doesn't verify any observable behavior changes. While Material-UI controls the collapse mechanism, you could assert on aria-expanded attribute changes or content visibility to make this test more meaningful.

Suggested improvement
       if (accordionButton) {
+        // Verify initial expanded state
+        expect(accordionButton).toHaveAttribute('aria-expanded', 'true');
+
         // Click to collapse
         await user.click(accordionButton);
+        expect(accordionButton).toHaveAttribute('aria-expanded', 'false');
+
         // Click to expand again
         await user.click(accordionButton);
+        expect(accordionButton).toHaveAttribute('aria-expanded', 'true');
       }
frontend/apps/thunder-develop/src/components/Navbar/__tests__/NavbarBreadcrumbs.test.tsx (1)

211-282: Avoid asserting on MUI internal class names in tests.

At lines 211–282, the tests rely on .MuiTypography-*, .MuiBreadcrumbs-*, and .MuiBox-root class selectors. While these are documented API classes stable for theming, they are still implementation details in the context of testing. MUI's official testing guide recommends writing tests using semantic queries (role, aria-label, text) or data-testid instead, to avoid brittleness when internal DOM structures shift.

Prefer:

  • getByRole() with accessible names
  • getByLabelText() for labeled elements
  • getByText() for text content
  • getByTestId() as a last resort for decorative/complex elements
♻️ Example refactor for "renders both breadcrumb segments" test
-    const typographyElements = container.querySelectorAll('.MuiTypography-root');
-    expect(typographyElements.length).toBeGreaterThanOrEqual(2);
+    const breadcrumb = screen.getByRole('navigation');
+    const items = breadcrumb.querySelectorAll('li');
+    expect(items.length).toBeGreaterThanOrEqual(2);

@DonOmalVindula DonOmalVindula force-pushed the migrate-vitest-v4 branch 3 times, most recently from 6b82041 to 215f3d3 Compare February 12, 2026 12:02
brionmario
brionmario previously approved these changes Feb 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-changelog Skip generating changelog for a particular PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants