Skip to content

Fix/broken tests on develop#7548

Open
DMills27 wants to merge 13 commits intodevelopfrom
fix/broken-tests-on-develop
Open

Fix/broken tests on develop#7548
DMills27 wants to merge 13 commits intodevelopfrom
fix/broken-tests-on-develop

Conversation

@DMills27
Copy link
Copy Markdown
Member

@DMills27 DMills27 commented Apr 9, 2026

What kind of change does this PR introduce?

Bugfix — repairs pre-existing broken unit tests on the develop branch that were failing after the Toolbar/SearchFilterBar component refactoring.

Issue Number:

Fixes #7544
Fixes #7545
Fixes #7546

Snapshots/Videos:

N/A — test-only changes with no UI impact.

If relevant, did you update the documentation?

Not applicable — no user-facing or API changes.

Summary

After the unified Toolbar component replaced both Navbar/PageHeader and SearchFilterBar, several test files were left with stale mock targets, outdated CSS class assertions, and mismatched data-testid queries. This PR repairs all six affected test files:

  • SortingButton.spec.tsx — Added missing type prop to DropDownButton mock destructuring; updated a test that asserted a non-existent icon prop on SortingButton.
  • UserGlobalScreen.spec.tsx — Updated toHaveClass('pageContainer') assertions to 'expand'/'contract' matching the refactored component.
  • posts.spec.tsx — Retargeted mock from shared-components/Navbar/Navbar to shared-components/Toolbar/Toolbar with updated interface (sortingfilters).
  • Organizations.spec.tsx — Replaced getByTestId('searchBtn') with userEvent.keyboard('{Enter}') (Toolbar hides the search button); fixed initial data wait to use organizations-list; corrected post-search assertions to expect refetched data.
  • OrganizationPeople.spec.tsx — Retargeted mock from SearchFilterBar to Toolbar with correct InterfaceToolbarProps type.
  • Groups.spec.tsx — Replaced all userEvent.type(searchInput, ...) calls with an atomic setNativeInputValue helper to avoid per-character GraphQL queries in server-side search mode; added mock for name_contains: 'Group'; fixed assertion placement inside waitFor blocks.
  • config/vite.config.ts — Wrapped vite-plugin-istanbul in a CYPRESS_COVERAGE env check to prevent it from forcing sourcemaps on every module during dev; gated verbose proxy logging behind ALLOW_LOGS=true.

Does this PR introduce a breaking change?

No.

Checklist

CodeRabbit AI Review

  • I have reviewed and addressed all critical issues flagged by CodeRabbit AI
  • I have implemented or provided justification for each non-critical suggestion
  • I have documented my reasoning in the PR comments where CodeRabbit AI suggestions were not implemented

Test Coverage

  • I have written tests for all new changes/features
  • I have verified that test coverage meets or exceeds 95%
  • I have run the test suite locally and all tests pass

Other information

All 206 tests across the 6 affected spec files pass locally. The setNativeInputValue helper in Groups.spec.tsx uses the native HTMLInputElement.prototype.value setter + InputEvent dispatch to set controlled input values atomically, avoiding the per-character query issue that userEvent.type causes with serverSide: true in DataGridWrapper.

Have you read the contributing guide?

Yes

Summary by CodeRabbit

  • Tests

    • Improved reliability: switched many tests to atomic input updates, awaited async UI changes, standardized Enter-key search submission, updated mocks and icon expectations, and replaced clearAllMocks with restoreAllMocks.
  • Chores

    • Build/dev server tweaks: coverage tooling enabled only when requested; verbose proxy request/response logging gated behind a runtime toggle.

DMills27 and others added 9 commits April 4, 2026 20:25
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…, search bar layout

- DropDownButton: white bg + gray text default; blue bg + white text on hover/active
- UserGlobalScreen + UserScreen: replace placeholder fallback with buttonLabel='▼'
- Toolbar: wrap SearchBar in .searchBarWrapper for proper flex-item sizing
- Toolbar: change flex-wrap to nowrap so search, filters, actions stay on one row
- Rework sidebar toggle: hamburger when collapsed, branding + circle chevron when expanded
- Fix collapse button with full-height wrapper and flexbox centering for reliable click target
- Add sidebar right border to separate it visually from page content
- Sync ProfileCard visibility with sidebar animation via max-height/opacity CSS transitions
- Make ProfileCard fully clickable, navigating to profile settings
- Fix blue hover on ProfileCard and SidebarOrgSection by adding variant=link
- Fix icon sizes: forward width/height in IconComponent for My Organizations and Settings;
  add strokeWidth 1.5 to normalise thin-stroke SVGs (Plugins); add iconSize prop to
  SidebarNavItem to compensate for FaUsers wide viewBox (640x512)
- Fix Create Org button background and alignment
- Fix Switch to Portal icon spacing
- Fix Users table number alignment and text size
- Remove duplicate search icon in Toolbar
- Fix Create Post button default and hover styles
- Replace hardcoded CSS values with design tokens in LeftDrawer and UserSidebar
- Fix MUI barrel import in IconComponent to use deep path imports
- Remove duplicate search button (showSearchButton=false keeps leading icon only)
- Increase gap between search bar and controls from 2px to 12px
- Style Create Event button to match SortingButton: white bg, blue on hover
- Fix responsiveness: allow search bar to shrink so buttons stay on same row
  when sidebar is open (min-width reduced from 420px to 160px)
Fix 6 test files with failures caused by the Toolbar/SearchFilterBar
refactoring: update mock targets, fix CSS class assertions, replace
per-character userEvent.type with atomic setNativeInputValue for
server-side search, and correct post-search data assertions.
@DMills27 DMills27 requested a review from palisadoes April 9, 2026 18:16
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 9, 2026

Our Pull Request Approval Process

This PR will be reviewed according to our:

  1. Palisadoes Contributing Guidelines

  2. AI Usage Policy

Your PR may be automatically closed if:

  1. Our PR template isn't filled in correctly
  2. You haven't correctly linked your PR to an issue

👉 https://docs.github.com/en/issues/tracking-your-work-with-issues/using-issues/linking-a-pull-request-to-an-issue

Thanks for contributing!

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 9, 2026

Walkthrough

Vite config now conditionally includes Istanbul and gates proxy request/response logging behind env flags. Many test files were updated: mocks swapped to Toolbar/DropDownButton, search submission switched from button clicks to Enter or native input assignment, async assertions use waitFor/find*, mock teardown changed to vi.restoreAllMocks(), and data-testid/CSS-class expectations were updated.

Changes

Cohort / File(s) Summary
Vite config & proxy logging
config/vite.config.ts
Istanbul plugin added to plugins only when process.env.CYPRESS_COVERAGE === 'true'. Proxy request/response body logging and proxyReq/proxyRes handlers are registered only when env.ALLOW_LOGS === 'true'; proxy error handler remains unconditional.
Toolbar / DropDownButton mock updates
src/screens/AdminPortal/OrganizationPeople/OrganizationPeople.spec.tsx, src/shared-components/posts/posts.spec.tsx, src/shared-components/SortingButton/SortingButton.spec.tsx, src/shared-components/Navbar/Navbar.spec.tsx, src/shared-components/SearchFilterBar/SearchFilterBar.spec.tsx
Replaced/updated mocked components to newer contracts (Toolbar, DropDownButton); mocks now accept/handle optional props (search, filters, actions, type), render conditional inputs/icons, and adjust test element output (new data-testid patterns and icon rendering).
Search/input interaction changes
src/screens/UserPortal/Organizations/Organizations.spec.tsx, src/shared-components/posts/posts.spec.tsx, src/components/AdminPortal/Advertisements/Advertisements.spec.tsx, src/screens/AdminPortal/SubTags/SubTags.spec.tsx, src/screens/AdminPortal/Users/Users.spec.tsx, src/screens/UserPortal/Pledges/Pledges.spec.tsx
Switched search activation from clickable search buttons to Enter-key submission; tests updated to press Enter after typing and removed/relaxed assertions expecting searchBtn/searchButton.
Native input setter & GraphQL mock adjustments
src/screens/UserPortal/Volunteer/Groups/Groups.spec.tsx
Added setNativeInputValue() helper to set input value atomically (avoids per-keystroke debounce); updated GraphQL mock set (added EVENT_VOLUNTEER_GROUP_LIST) and adjusted related assertions/timeouts.
Async handling & mock teardown changes
src/screens/UserPortal/UserGlobalScreen/UserGlobalScreen.spec.tsx, src/screens/UserPortal/Volunteer/Groups/Groups.spec.tsx, src/screens/UserPortal/Organizations/Organizations.spec.tsx, src/shared-components/SidebarBase/SidebarBase.spec.tsx, multiple specs
Replaced vi.clearAllMocks() with vi.restoreAllMocks() in teardown; introduced waitFor/findBy* for async UI updates; updated CSS/class assertions to match renamed classes (e.g., contract / expand) and conditional rendering (e.g., talawa-logo).
Test assertions & test-id migrations
src/shared-components/posts/posts.spec.tsx, src/shared-components/SearchFilterBar/SearchFilterBar.spec.tsx, various specs
Updated test IDs and queries to align with refactored components (toggle/item testids, toolbar aria labels, container/testid prefixes), and adjusted several assertions to match new DOM structure and aria attributes.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • palisadoes

Caution

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

  • Ignore

❌ Failed checks (1 error, 2 inconclusive)

Check name Status Explanation Resolution
I18n Key Completeness ❌ Error The i18n key 'errorOccured' used in SubTags.tsx line 153 does not exist in any of the 5 supported locale files (en, es, fr, hi, zh). Replace tCommon('errorOccured') with an existing key like tCommon('error') or tErrors('errorLoading', { entity: t('tags') }) and verify it exists in all locale files.
Test Coverage Gate ❓ Inconclusive Unable to verify test coverage ≥95% threshold for modified files without accessing repository structure, package.json, test configuration, and actual coverage reports. Execute the provided bash scripts to inspect repository configuration, modified files, and run coverage tests to determine if threshold is met.
Typescript Compilation ❓ Inconclusive TypeScript compilation check cannot be fully evaluated in sandbox due to missing type definition dependencies (@types/node, @types/react, @types/react-dom), though 206 tests pass locally. Run pnpm install to install dependencies and execute pnpm run typecheck in a complete environment, or rely on CI system validation with properly installed dependencies.
✅ Passed checks (6 passed)
Check name Status Explanation
Title check ✅ Passed The title "Fix/broken tests on develop" is concise and accurately summarizes the main change—repairing pre-existing broken unit tests after a component refactoring.
Description check ✅ Passed The PR description is comprehensive and addresses all template sections: change type (bugfix), related issues, motivation, breaking changes, and checklist verification. It details fixes for six affected spec files and a Vite config change.
Linked Issues check ✅ Passed The PR directly addresses all three linked issues (#7544, #7545, #7546) by fixing data-testid misalignments, updating CSS class assertions, and repairing GraphQL mocks in affected spec files.
Out of Scope Changes check ✅ Passed All changes are directly aligned with the linked issues: test-only fixes for SortingButton, UserGlobalScreen, posts, Organizations, OrganizationPeople, and Groups spec files, plus a necessary Vite config adjustment for coverage gating—no unrelated changes detected.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Component Architecture Compliance ✅ Passed PR contains only test and config changes with no component source modifications. Existing components fully comply with architecture policy: interfaces in separate files, correct placement in src/shared-components/, proper export naming, and valid wrapper patterns.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/broken-tests-on-develop

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ast-grep (0.42.1)
src/components/AdminPortal/Advertisements/Advertisements.spec.tsx

Error: Cannot parse rule /ast-grep-rules/../git/.coderabbit/ast-grep-rules/no-dynamic-timestamps-in-tests.yml
Help: The file is not a valid ast-grep rule. Please refer to doc and fix the error.
See also: https://ast-grep.github.io/guide/rule-config.html

✖ Caused by
╰▻ Fail to parse yaml as RuleConfig
╰▻ files: invalid type: string "**/*.{spec,test}.{ts,tsx}", expected a sequence at line 3 column 8

src/screens/AdminPortal/SubTags/SubTags.spec.tsx

Error: Cannot parse rule /ast-grep-rules/../git/.coderabbit/ast-grep-rules/no-dynamic-timestamps-in-tests.yml
Help: The file is not a valid ast-grep rule. Please refer to doc and fix the error.
See also: https://ast-grep.github.io/guide/rule-config.html

✖ Caused by
╰▻ Fail to parse yaml as RuleConfig
╰▻ files: invalid type: string "**/*.{spec,test}.{ts,tsx}", expected a sequence at line 3 column 8

src/screens/AdminPortal/Users/Users.spec.tsx

Error: Cannot parse rule /ast-grep-rules/../git/.coderabbit/ast-grep-rules/no-dynamic-timestamps-in-tests.yml
Help: The file is not a valid ast-grep rule. Please refer to doc and fix the error.
See also: https://ast-grep.github.io/guide/rule-config.html

✖ Caused by
╰▻ Fail to parse yaml as RuleConfig
╰▻ files: invalid type: string "**/*.{spec,test}.{ts,tsx}", expected a sequence at line 3 column 8

  • 4 others

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 9, 2026

The linked issue must be assigned to the PR author.

@github-actions github-actions Bot closed this Apr 9, 2026
@DMills27 DMills27 reopened this Apr 9, 2026
Copy link
Copy Markdown
Contributor

@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: 6

Caution

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

⚠️ Outside diff range comments (2)
src/screens/UserPortal/UserGlobalScreen/UserGlobalScreen.spec.tsx (1)

78-91: ⚠️ Potential issue | 🔴 Critical

Replace vi.clearAllMocks() with vi.restoreAllMocks() in lifecycle hooks; move async assertions into waitFor blocks

Three blocking test-stability issues:

  1. Lines 125 & 135vi.clearAllMocks() is forbidden. Use vi.restoreAllMocks() in both beforeEach and afterEach.

  2. Line 135-136afterEach missing vi.restoreAllMocks(). Must include both cleanup() AND vi.restoreAllMocks() for sharded CI.

  3. Lines 494 & 510 — Assertions follow awaited user interactions without waitFor. Move into waitFor blocks:

    • Line 494: expect(mainContainer).toHaveClass('expand') follows await user.click(closeButton)
    • Line 510: expect(mainContainer).toHaveClass('contract') follows await user.click(openButton)
Suggested patch
   beforeEach(() => {
-    vi.clearAllMocks();
+    vi.restoreAllMocks();
   });

   afterEach(() => {
-    vi.clearAllMocks();
+    vi.restoreAllMocks();
     cleanup();
     Object.defineProperty(window, 'innerWidth', {
       writable: true,
       configurable: true,
       value: originalInnerWidth,
     });
   });

   it('should apply expand class when drawer is hidden', async () => {
     const user = userEvent.setup();
     renderComponent();

     const closeButton = screen.getByTestId('closeMenu');
     await user.click(closeButton);

     const mainContainer = screen.getByTestId('mainpageright');
-    expect(mainContainer).toHaveClass('expand');
+    await waitFor(() => expect(mainContainer).toHaveClass('expand'));
   });

   it('should apply contract class when drawer is shown', async () => {
     const user = userEvent.setup();
     renderComponent();

     const closeButton = screen.getByTestId('closeMenu');
     await user.click(closeButton);

     const openButton = screen.getByTestId('openMenu');
     await user.click(openButton);

     const mainContainer = screen.getByTestId('mainpageright');
-    expect(mainContainer).toHaveClass('contract');
+    await waitFor(() => expect(mainContainer).toHaveClass('contract'));
   });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/screens/UserPortal/UserGlobalScreen/UserGlobalScreen.spec.tsx` around
lines 78 - 91, Replace vi.clearAllMocks() calls with vi.restoreAllMocks() in the
test lifecycle hooks: update the beforeEach to use vi.restoreAllMocks() instead
of vi.clearAllMocks(), and ensure afterEach calls both cleanup() and
vi.restoreAllMocks() (add vi.restoreAllMocks() if missing). Also make the two
post-interaction assertions stable by moving them into waitFor blocks: after
awaiting user.click(closeButton) wrap
expect(mainContainer).toHaveClass('expand') inside await waitFor(() =>
expect(mainContainer).toHaveClass('expand')), and after awaiting
user.click(openButton) wrap expect(mainContainer).toHaveClass('contract') inside
await waitFor(() => expect(mainContainer).toHaveClass('contract')).
src/screens/UserPortal/Organizations/Organizations.spec.tsx (1)

539-560: ⚠️ Potential issue | 🟡 Minor

Update test name to match Enter-key behavior

Issue Goals:

  • #7544 intent is addressed by moving search submission away from searchBtn to Enter-key flow.
  • Gap: test description is stale: Line 539 says “clicking search button” while Line 560 now submits via keyboard.

Tests (incl. Flakiness):

  • ✅ Awaited user interactions and post-action assertions are properly synchronized.
  • ✅ No hardcoded delays introduced in changed segments.

Components/Policy:

  • afterEach includes both cleanup() and vi.restoreAllMocks().

GraphQL:

  • ✅ No blocking request-shape issue in changed lines.

i18n & a11y:

  • I18nextProvider remains present.

Security:

  • ✅ No security concerns in this changed segment.

Action Items:

  1. Rename the test at Line 539 to reflect keyboard submission (Enter key), e.g. “should search organizations when pressing Enter key”.
Suggested diff
-test('should search organizations when clicking search button', async () => {
+test('should search organizations when pressing Enter key', async () => {

As per coding guidelines, “Issue goals (Priority #1): … list gaps with file:line” and flakiness checks require clear, deterministic async test intent.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/screens/UserPortal/Organizations/Organizations.spec.tsx` around lines 539
- 560, Update the Jest test title string for the test that currently reads
"should search organizations when clicking search button" to reflect the new
Enter-key submission flow (e.g., "should search organizations when pressing
Enter key") so the description matches behavior in the test that types into
searchInput and triggers await userEvent.keyboard('{Enter}'); ensure you update
the test() call surrounding the render and userEvent steps in
Organizations.spec.tsx.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/screens/AdminPortal/OrganizationPeople/OrganizationPeople.spec.tsx`:
- Around line 58-60: The test currently uses optional chaining in the click
handler (props.filters?.[0]?.onChange?.('invalid')), allowing the click to
silently no-op if filters[0].onChange is missing; change this to fail loudly by
ensuring the handler exists and is callable: either remove the final optional
chain to call props.filters![0]!.onChange('invalid') so test fails if missing,
or add an explicit guard that throws (e.g., if (typeof
props.filters?.[0]?.onChange !== 'function') throw new
Error('filters[0].onChange is required in this test');
props.filters[0].onChange('invalid')). Target the onClick block that references
props.filters and onChange in OrganizationPeople.spec.tsx.

In `@src/screens/UserPortal/Volunteer/Groups/Groups.spec.tsx`:
- Around line 483-495: The test claims to verify input trimming but currently
types a plain 'Teresa', so it won't catch regressions in trim(); update the test
around the search input (searchInput retrieved via getByTestId('searchByInput')
and set via setNativeInputValue) to supply a value with surrounding whitespace
(e.g., leading/trailing spaces) instead of 'Teresa', keep the debounce/waitFor
assertions (expect Group 1 present, Group 2 absent) and ensure you still call
userEvent.clear(searchInput) before setNativeInputValue so the test explicitly
covers the trim() path.
- Around line 1434-1444: The test currently only asserts the input value after
calling setNativeInputValue(searchInput, 'Group 1') and can falsely pass if the
debounced search handler never runs; update the test (the block using
setNativeInputValue, searchInput, and waitFor) to also assert observable
filtered results from the UI—e.g., inside the waitFor after confirming the input
value, add an assertion using screen.queryByText('Group 2') or
screen.getByText('Group 1') to verify that Group 2 is not rendered and Group 1
is present (which confirms the GraphQL mock for name_contains: 'Group 1' ran);
make the same change in the other test block referenced around lines 1467–1473
that uses the same helpers so both tests validate UI results rather than only
the input value.
- Around line 678-683: Change the flaky search assertion to actually wait for
the refetch by typing a unique term (use setNativeInputValue(searchInput, 'Group
1')) so only one result is returned, then wrap the expect(viewButtons.length ===
1) inside a waitFor to ensure the grid reloads before clicking; locate the test
block that queries findAllByTestId('viewGroupBtn') and replace the unconditional
find/assert/click sequence with a waitFor-based assert followed by
userEvent.click(viewButtons[0]). Also fix the afterEach cleanup by replacing
vi.clearAllMocks() with vi.restoreAllMocks() in the test teardown so mocks are
properly restored between sharded tests.

In `@src/shared-components/posts/posts.spec.tsx`:
- Around line 155-160: The test triggers search.onSearch twice because the mock
wired to the input calls search.onSearch on every onChange and again on Enter;
update the test to match the Toolbar contract by removing the onChange
invocation and only invoking search.onSearch from the onKeyDown Enter handler
(i.e., keep the onKeyDown block that calls search.onSearch((e.target as
HTMLInputElement).value) and stop calling search.onSearch in onChange), ensuring
the mocked component uses the same single- invocation behavior as Toolbar and
prevents duplicate query triggers.

In `@src/shared-components/SortingButton/SortingButton.spec.tsx`:
- Around line 287-293: The test "should render type-based icon when type prop is
provided" in SortingButton.spec.tsx duplicates assertions already covered by the
existing "Icon Types" sort-path test; remove the redundant expectation(s) —
specifically drop either the whole test or at least the duplicated lines
checking data-icon-type='sort' (the getByTestId('sorting-icon') and
expect(...).toHaveAttribute('data-icon-type', 'sort')) so only the unique
coverage from the "Icon Types" assertions remains; locate this in the
SortingButton.spec.tsx test block and delete the redundant assertion(s) to keep
the spec lean.

---

Outside diff comments:
In `@src/screens/UserPortal/Organizations/Organizations.spec.tsx`:
- Around line 539-560: Update the Jest test title string for the test that
currently reads "should search organizations when clicking search button" to
reflect the new Enter-key submission flow (e.g., "should search organizations
when pressing Enter key") so the description matches behavior in the test that
types into searchInput and triggers await userEvent.keyboard('{Enter}'); ensure
you update the test() call surrounding the render and userEvent steps in
Organizations.spec.tsx.

In `@src/screens/UserPortal/UserGlobalScreen/UserGlobalScreen.spec.tsx`:
- Around line 78-91: Replace vi.clearAllMocks() calls with vi.restoreAllMocks()
in the test lifecycle hooks: update the beforeEach to use vi.restoreAllMocks()
instead of vi.clearAllMocks(), and ensure afterEach calls both cleanup() and
vi.restoreAllMocks() (add vi.restoreAllMocks() if missing). Also make the two
post-interaction assertions stable by moving them into waitFor blocks: after
awaiting user.click(closeButton) wrap
expect(mainContainer).toHaveClass('expand') inside await waitFor(() =>
expect(mainContainer).toHaveClass('expand')), and after awaiting
user.click(openButton) wrap expect(mainContainer).toHaveClass('contract') inside
await waitFor(() => expect(mainContainer).toHaveClass('contract')).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 85a8e4cc-5e56-4544-a8cd-76865bcb7c9a

📥 Commits

Reviewing files that changed from the base of the PR and between b87aaed and ef38d4e.

📒 Files selected for processing (7)
  • config/vite.config.ts
  • src/screens/AdminPortal/OrganizationPeople/OrganizationPeople.spec.tsx
  • src/screens/UserPortal/Organizations/Organizations.spec.tsx
  • src/screens/UserPortal/UserGlobalScreen/UserGlobalScreen.spec.tsx
  • src/screens/UserPortal/Volunteer/Groups/Groups.spec.tsx
  • src/shared-components/SortingButton/SortingButton.spec.tsx
  • src/shared-components/posts/posts.spec.tsx

Comment thread src/screens/UserPortal/Volunteer/Groups/Groups.spec.tsx Outdated
Comment thread src/screens/UserPortal/Volunteer/Groups/Groups.spec.tsx
Comment thread src/shared-components/posts/posts.spec.tsx Outdated
Comment thread src/shared-components/SortingButton/SortingButton.spec.tsx Outdated
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 9, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

Let me fetch the details of all the failing GitHub Actions jobs.


🏁 Script executed:

#!/bin/bash
# Fetch job details for all failing jobs
JOBS=(70664095325 70664095364 70664095326 70664095322 70664095353 70664095338 70664095324 70664095404 70664095333 70664095360)

for JOB_ID in "${JOBS[@]}"; do
  echo "===== JOB: $JOB_ID ====="
  gh api "repos/PalisadoesFoundation/talawa-admin/actions/jobs/$JOB_ID" --jq '{name: .name, status: .status, conclusion: .conclusion, started_at: .started_at, completed_at: .completed_at}' 2>/dev/null
  echo ""
done

Length of output: 1860


All shards failed. Now let me pull the step-level details and logs to find the actual error messages.


🏁 Script executed:

#!/bin/bash
JOBS=(70664095325 70664095364 70664095326 70664095322 70664095353 70664095338 70664095324 70664095404 70664095333 70664095360)

for JOB_ID in "${JOBS[@]}"; do
  echo "===== JOB: $JOB_ID ====="
  gh api "repos/PalisadoesFoundation/talawa-admin/actions/jobs/$JOB_ID" --jq '.steps[] | select(.conclusion == "failure") | {name: .name, conclusion: .conclusion, number: .number}' 2>/dev/null
  echo ""
done

Length of output: 1050


All shards fail at the Vitest step. Let me download the logs to see exactly which tests are failing.


🏁 Script executed:

#!/bin/bash
JOBS=(70664095325 70664095364 70664095326 70664095322 70664095353 70664095338 70664095324 70664095404 70664095333 70664095360)

for JOB_ID in "${JOBS[@]}"; do
  echo "===== JOB: $JOB_ID ====="
  gh api "repos/PalisadoesFoundation/talawa-admin/actions/jobs/$JOB_ID/logs" 2>/dev/null | \
    grep -E "(FAIL|PASS|Error:|✓|×|●|Cannot find module|TypeError|AssertionError|Expected|Received|✗|FAILED|failed)" | \
    head -60
  echo ""
done

Length of output: 89722


Good. I can clearly see two spec files with confirmed test failures. Let me get their actual assertion errors now.


🏁 Script executed:

#!/bin/bash

# Get detailed failure output for Shard 4 (Pledges)
echo "===== SHARD 4 - PLEDGES FAILURES ====="
gh api "repos/PalisadoesFoundation/talawa-admin/actions/jobs/70664095322/logs" 2>/dev/null | \
  grep -A 30 "should keep all rows when search query is empty\|should filter rows by campaign name" | head -80

echo ""
echo "===== SHARD 11 - ADVERTISEMENTS FAILURES ====="
gh api "repos/PalisadoesFoundation/talawa-admin/actions/jobs/70664095360/logs" 2>/dev/null | \
  grep -A 30 "search button renders correctly\|filters active advertisement by name\|filters active advertisement by description\|filter completed advertisement by name\|filter completed advertisement by description\|search for not existing" | head -120

Length of output: 19917


Now let me read the actual failing spec files to understand exactly what needs to change.


🏁 Script executed:

#!/bin/bash
echo "===== Pledges.spec.tsx - search-related tests ====="
fd "Pledges.spec.tsx" --exec grep -n "searchBtn\|searchInput\|keyboard\|Enter\|search\|onSearchChange\|filter rows\|keep all rows" {} | head -60

echo ""
echo "===== Advertisements.spec.tsx - failing tests ====="
fd "Advertisements.spec.tsx" src/components --exec grep -n "searchBtn\|searchInput\|keyboard\|Enter\|where\|name_contains\|search button renders\|filters active\|filter completed\|search for not existing\|OrganizationAdvertisements\|MOCK\|mock" {} | head -80

echo ""
echo "===== Advertisements.spec.tsx - full failing test bodies ====="
fd "Advertisements.spec.tsx" src/components --exec sed -n '/search button renders correctly/,/^  \}\)/p' {} | head -100

Length of output: 5127


🏁 Script executed:

#!/bin/bash
echo "===== Pledges.spec.tsx full failing tests ====="
fd "Pledges.spec.tsx" --exec sed -n '710,770p' {}

echo ""
echo "===== Advertisements.spec.tsx mock definitions ====="
fd "Advertisements.spec.tsx" src/components --exec sed -n '1,60p' {}

echo ""
echo "===== Advertisements.spec.tsx filterActive/filterCompleted mock imports ====="
fd "Advertisements.spec.tsx" src/components --exec grep -n "filterActive\|filterCompleted\|getCompleted\|getActive\|import.*mock\|from.*mock\|from.*fixtures\|from.*Advertisements.mock" {}

echo ""
echo "===== Advertisements mock file ====="
fd "Advertisements.mock*\|advertisements.mock*\|AdvertisementsMock*" --exec cat {}

Length of output: 5588


🏁 Script executed:

#!/bin/bash
echo "===== Find Advertisements mock file ====="
fd "AdvertisementsMocks" --exec echo {}

echo ""
echo "===== Read AdvertisementsMocks file ====="
fd "AdvertisementsMocks" --exec cat {}

echo ""
echo "===== Advertisements.spec.tsx failing test bodies (search button + filter tests) ====="
fd "Advertisements.spec.tsx" src/components --exec sed -n '335,530p' {}

Length of output: 21798


Now let me check the Advertisements component source to understand the current data-testid structure.


🏁 Script executed:

#!/bin/bash
echo "===== Advertisements.tsx - testids and search logic ====="
fd "Advertisements.tsx" src/components/AdminPortal/Advertisements --exec grep -n "data-testid\|searchButton\|searchname\|handleSearch\|onSearch\|Toolbar\|SearchBar\|setSearch\|refetch\|where\|name_contains" {}

echo ""
echo "===== Advertisements.tsx - full component ====="
fd "Advertisements.tsx" src/components/AdminPortal/Advertisements --exec cat {}

Length of output: 11587


🏁 Script executed:

#!/bin/bash
echo "===== Toolbar component ====="
fd "Toolbar.tsx" src/shared-components/Toolbar --exec cat {}

echo ""
echo "===== InterfaceToolbarProps type ====="
fd "Toolbar.tsx" src/shared-components/Toolbar --exec grep -n "interface\|type\|buttonTestId\|inputTestId\|search\|button\|hidden\|display" {}

Length of output: 7241


🏁 Script executed:

#!/bin/bash
echo "===== SearchBar component - button rendering ====="
fd "SearchBar.tsx" src/shared-components/SearchBar --exec grep -n "showSearchButton\|buttonTestId\|data-testid\|display\|hidden\|button" {}

echo ""
echo "===== SearchBar full component ====="
fd "SearchBar.tsx" src/shared-components/SearchBar --exec cat {}

Length of output: 9442


Now let me get the complete test failure summary for each shard from the end of their logs.


🏁 Script executed:

#!/bin/bash
JOBS=(70664095325 70664095364 70664095326 70664095322 70664095353 70664095338 70664095324 70664095404 70664095333 70664095360)
SHARDS=(1 2 3 4 5 6 7 8 9 11)

for i in "${!JOBS[@]}"; do
  JOB_ID="${JOBS[$i]}"
  SHARD="${SHARDS[$i]}"
  echo "===== SHARD $SHARD (Job $JOB_ID) - SUMMARY ====="
  gh api "repos/PalisadoesFoundation/talawa-admin/actions/jobs/$JOB_ID/logs" 2>/dev/null | \
    tail -100 | \
    grep -E "(Tests|FAIL|failed|×|❯|duration|Files|Test Files|passed|skipped)" | head -30
  echo ""
done

Length of output: 2618


Excellent! Now I have 3 more failing files. Let me get the remaining shard failure locations and check the identified spec files.


🏁 Script executed:

#!/bin/bash
# Get failure file locations for shards 5,6,7,8,9
for JOB_ID in 70664095353 70664095338 70664095324 70664095404 70664095333; do
  echo "===== JOB $JOB_ID ====="
  gh api "repos/PalisadoesFoundation/talawa-admin/actions/jobs/$JOB_ID/logs" 2>/dev/null | \
    grep -E "\.spec\.(tsx|ts|js):[0-9]+" | tail -20
  echo ""
done

Length of output: 5059


Now let me read the relevant lines from each failing spec file.


🏁 Script executed:

#!/bin/bash

# AddMember.spec.tsx line 1862
echo "===== AddMember.spec.tsx around line 1862 ====="
fd "AddMember.spec.tsx" --exec sed -n '1850,1875p' {}

echo ""
echo "===== SearchFilterBar.spec.tsx around line 760 ====="
fd "SearchFilterBar.spec.tsx" --exec sed -n '745,780p' {}

echo ""
echo "===== SubTags.spec.tsx around line 245 ====="
fd "SubTags.spec.tsx" --exec sed -n '230,260p' {}

echo ""
echo "===== Navbar.spec.tsx around line 179 ====="
fd "Navbar.spec.tsx" src/shared-components --exec sed -n '165,195p' {}

echo ""
echo "===== SidebarBase.spec.tsx around lines 120-135 and 295-310 ====="
fd "SidebarBase.spec.tsx" --exec sed -n '110,140p' {}
echo "..."
fd "SidebarBase.spec.tsx" --exec sed -n '288,315p' {}

Length of output: 6755


🏁 Script executed:

#!/bin/bash
echo "===== ChatRoom.spec.tsx around line 1027, 1141, 1226 ====="
fd "ChatRoom.spec.tsx" --exec sed -n '1020,1035p' {}
echo "..."
fd "ChatRoom.spec.tsx" --exec sed -n '1135,1145p' {}
echo "..."
fd "ChatRoom.spec.tsx" --exec sed -n '1220,1230p' {}

echo ""
echo "===== EventManager.spec.ts around line 204-228 ====="
fd "EventManager.spec.ts" --exec sed -n '195,235p' {}

echo ""
echo "===== InternalFileWriter.spec.ts around line 191, 225, 321 ====="
fd "InternalFileWriter.spec.ts" --exec sed -n '185,200p' {}
echo "..."
fd "InternalFileWriter.spec.ts" --exec sed -n '218,245p' {}
echo "..."
fd "InternalFileWriter.spec.ts" --exec sed -n '315,325p' {}

echo ""
echo "===== Donate.spec.tsx around line 875 ====="
fd "Donate.spec.tsx" --exec sed -n '865,885p' {}

echo ""
echo "===== OrganizationModal.spec.tsx around line 668 ====="
fd "OrganizationModal.spec.tsx" --exec sed -n '658,680p' {}

echo ""
echo "===== Users.spec.tsx around line 630 ====="
fd "Users.spec.tsx" src/screens/AdminPortal --exec sed -n '620,640p' {}

echo ""
echo "===== AdvertisementRegister.spec.tsx around line 172 ====="
fd "AdvertisementRegister.spec.tsx" --exec sed -n '162,185p' {}

echo ""
echo "===== getRefreshToken.spec.ts around line 187 ====="
fd "getRefreshToken.spec.ts" --exec sed -n '177,197p' {}

Length of output: 8158


🏁 Script executed:

#!/bin/bash
echo "===== SidebarBase - relevant testids and class names ====="
fd "SidebarBase.tsx" src/shared-components/SidebarBase --exec grep -n "data-testid\|expandedDrawer\|collapsedDrawer\|hamburgerIcon\|talawa-logo\|className" {} | head -40

echo ""
echo "===== Navbar - check for PageHeader, sorting, filters ====="
fd "Navbar.tsx" src/shared-components/Navbar --exec grep -n "PageHeader\|sorting\|filters\|export\|data-testid\|icon\|type" {} | head -40

echo ""
echo "===== SearchFilterBar.spec.tsx line 760 context and what testid it expects ====="
fd "SearchFilterBar.spec.tsx" --exec sed -n '700,785p' {}

echo ""
echo "===== Users.spec.tsx - look at Users component to understand where:undefined issue ====="
fd "Users.spec.tsx" src/screens/AdminPortal --exec sed -n '600,650p' {}

Length of output: 5706


Now I have a complete picture. Let me compile the full analysis and solutions.


@palisadoes — Here is a comprehensive breakdown of all 10 failing shards, grouped by root cause with starter fix code.


Root Causes & Solutions

All failures stem from the Toolbar/SearchBar/Sidebar refactor that changed component APIs, CSS class names, and data-testid values, but not all test files were updated. This PR (#7548) fixed 6 spec files; the following are the remaining broken files.


🔴 Category 1: searchBtn / searchButton removed by Toolbar (showSearchButton={false})

Affects: Shard 4 (Pledges.spec.tsx), Shard 3 (SubTags.spec.tsx), Shard 11 (Advertisements.spec.tsx)

Root cause: Toolbar passes showSearchButton={false} to SearchBar. Per SearchBar.tsx line 248, the button is conditionally not rendered when this prop is false. Any test calling getByTestId('searchBtn') or getByTestId('searchButton') throws "Unable to find element".

Fix for Pledges.spec.tsx (lines 723 and 746):

// BEFORE (fails – searchBtn no longer rendered):
await user.click(screen.getByTestId('searchBtn'));

// AFTER (trigger search via Enter key on the input):
await user.keyboard('{Enter}');

Full patched test blocks:

it('should keep all rows when search query is empty or whitespace', async () => {
  const user = userEvent.setup({ delay: null });
  renderMyPledges(link1);

  await waitFor(() => {
    expect(screen.getByText('Hospital Campaign')).toBeInTheDocument();
    expect(screen.getByText('School Campaign')).toBeInTheDocument();
  });

  const initialRows = screen.getAllByTestId(/^datatable-row-/);
  const searchInput = screen.getByTestId('searchByInput');
  await user.clear(searchInput);
  await user.type(searchInput, '   ');
  await user.keyboard('{Enter}'); // ← replaces getByTestId('searchBtn') click

  await waitFor(() => {
    expect(screen.getByText('Hospital Campaign')).toBeInTheDocument();
    expect(screen.getByText('School Campaign')).toBeInTheDocument();
    expect(screen.getAllByTestId(/^datatable-row-/)).toHaveLength(initialRows.length);
  });
});

it('should filter rows by campaign name when query is provided', async () => {
  const user = userEvent.setup({ delay: null });
  renderMyPledges(link1);

  await waitFor(() => {
    expect(screen.getByText('Hospital Campaign')).toBeInTheDocument();
    expect(screen.getByText('School Campaign')).toBeInTheDocument();
  });

  const searchInput = screen.getByTestId('searchByInput');
  await user.clear(searchInput);
  await user.type(searchInput, 'school');
  await user.keyboard('{Enter}'); // ← replaces getByTestId('searchBtn') click

  await waitFor(() => {
    expect(screen.getByText('School Campaign')).toBeInTheDocument();
    expect(screen.queryByText('Hospital Campaign')).not.toBeInTheDocument();
  });
});

Fix for SubTags.spec.tsx (line 245) — same pattern:

// BEFORE:
await user.click(screen.getByTestId('searchBtn'));

// AFTER:
await user.keyboard('{Enter}');

Fix for Advertisements.spec.tsxsearchButton is hidden; the Advertisements.tsx component also uses Toolbar with showSearchButton={false}. The search is client-side (filters in-memory state), triggered via Enter.

// "search button renders correctly" test – remove searchButton assertion:
it('search button renders correctly with placeholder', async () => {
  // ... render ...
  await wait();
  expect(screen.getByTestId('searchname')).toBeInTheDocument();
  // REMOVE: expect(screen.getByTestId('searchButton')).toBeInTheDocument();
  expect(screen.getByTestId('searchname')).toHaveAttribute(
    'placeholder',
    translations.searchAdvertisements,
  );
});

// Filter tests – replace button click with Enter:
await userEvent.clear(screen.getByTestId('searchname'));
await userEvent.type(screen.getByTestId('searchname'), 'Cookie shop 6');
// BEFORE: await userEvent.click(screen.getByTestId('searchButton'));
await userEvent.keyboard('{Enter}'); // ← replacement

// "search for not existing advertisement" test:
await userEvent.type(screen.getByTestId('searchname'), 'BandhanSearchedIt');
await userEvent.keyboard('{Enter}'); // ← replacement

🔴 Category 2: SidebarBase — missing data-testid on logo & renamed hamburger CSS classes

Affects: Shard 6 (SidebarBase.spec.tsx lines 123, 130, 299, 306)

Root cause: The SidebarBase.tsx component:

  • Renders <TalawaLogo> without a data-testid="talawa-logo" attribute → getByTestId('talawa-logo') fails
  • Uses a single styles.hamburgerIcon class (not hamburgerIconExpanded / hamburgerIconCollapsed) → class-name assertions fail

Fix — Component (SidebarBase.tsx): Add the testid to the logo and add conditional hamburger icon classes:

// Add data-testid to TalawaLogo wrapper:
<TalawaLogo data-testid="talawa-logo" className={styles.talawaLogo} />

// Or wrap it:
<span data-testid="talawa-logo">
  <TalawaLogo className={styles.talawaLogo} />
</span>

// Add conditional hamburger class:
<FaBars
  className={`${styles.hamburgerIcon} ${
    hideDrawer ? styles.hamburgerIconCollapsed : styles.hamburgerIconExpanded
  }`}
  size={22}
/>

Fix — Spec (if changing the component is not preferred, update tests to match current class names):

// BEFORE:
expect(brandingDiv?.className).toMatch(/sidebarBrandingContainerHidden/);
// AFTER – match what the component actually renders, e.g. the collapsed drawer:
expect(brandingDiv?.className).toMatch(/collapsedDrawer/); // adjust to actual class

// For hamburger icon:
// BEFORE:
expect(icon?.className.baseVal).toMatch(/hamburgerIconExpanded/);
// AFTER – match actual class name:
expect(icon?.className.baseVal).toMatch(/hamburgerIcon/);

🔴 Category 3: Navbar.spec.tsxPageHeader now wraps Toolbar but sorting[].icon prop removed

Affects: Shard 5 (Navbar.spec.tsx line 179)

Root cause: PageHeader now maps sorting → Toolbar filters, passing icon: s.icon through. However, from the PR's SortingButton.spec.tsx fix, the icon prop was removed in favour of type. So when the test asserts iconContainer.querySelector('img') on a sort-custom-icon container, no <img> is rendered.

Fix for Navbar.spec.tsx:

// BEFORE – expects icon from deprecated `icon` prop:
render(
  <PeopleTabNavbar
    sorting={[{
      title: 'Sort Custom',
      options: [{ label: 'A', value: 'a' }],
      selected: 'a',
      onChange: onSortChange,
      testIdPrefix: 'sort-custom',
      icon: 'custom-icon.png', // ← no longer rendered as <img>
    }]}
  />,
);
const iconContainer = screen.getByTestId('sort-custom-icon');
const img = iconContainer.querySelector('img');
// expect(img).toBeTruthy(); // ← remove or update

// AFTER – use `type` prop instead, assert the span with data-icon-type:
render(
  <PeopleTabNavbar
    sorting={[{
      title: 'Sort Custom',
      options: [{ label: 'A', value: 'a' }],
      selected: 'a',
      onChange: onSortChange,
      testIdPrefix: 'sort-custom',
      type: 'sort', // ← replaces icon
    }]}
  />,
);
const iconContainer = screen.getByTestId('sort-custom-icon');
expect(iconContainer).toHaveAttribute('data-icon-type', 'sort');

🔴 Category 4: SearchFilterBar.spec.tsxfilterPlugins-select testid / userEvent.selectOptions mismatch

Affects: Shard 2 (SearchFilterBar.spec.tsx line 760)

Root cause: The test uses userEvent.selectOptions(filterDropdown, 'installed') which requires a native <select> element. But DropDownButton renders a Bootstrap custom dropdown (a <button> toggle, not a <select>), whose testid is ${prefix}-select on the toggle <button>. The selectOptions API does not work on non-native selects.

Fix:

// BEFORE:
const filterDropdown = screen.getByTestId('filterPlugins-select');
await user.selectOptions(filterDropdown, 'installed');
expect(onFilterChange).toHaveBeenCalledWith('installed');

// AFTER – click the toggle, then click the option:
const filterToggle = screen.getByTestId('filterPlugins-select');
await user.click(filterToggle);
const installedOption = await screen.findByText('Installed Plugins');
await user.click(installedOption);
expect(onFilterChange).toHaveBeenCalledWith('installed');

🔴 Category 5: Users.spec.tsx — mock variable mismatch (where: undefined vs. where: null)

Affects: Shard 8 (Users.spec.tsx line 630)

Root cause: The mock has where: undefined but Apollo's MockedProvider performs a deep equality check on variables. If the component sends where: null (or omits the field), the mock won't match, triggering the "No more mocked responses" error.

Fix:

// In errorMock, change undefined → null (or match what the component sends):
{
  request: {
    query: USER_LIST_FOR_ADMIN,
    variables: {
      first: 12,
      after: null,
      orgFirst: 32,
      where: null, // ← was undefined; match the actual query variable
    },
  },
  error: new Error('Network error occurred'),
},

🟡 Category 6: Pre-existing failures that need deeper investigation

These failures appear to be pre-existing issues on the develop branch unrelated to the Toolbar refactor. They need separate fixes:

File Line Likely Issue
AddMember.spec.tsx 1862 Mock timing / missing data table rows after async query
ChatRoom.spec.tsx 1027, 1141, 1226 Mock exhaustion for DELETE_CHAT_MESSAGE / MARK_CHAT_MESSAGES_AS_READ mutations
EventManager.spec.ts 204–228 EventManager.emit() silently swallowing errors instead of passing them through
InternalFileWriter.spec.ts 191, 225, 321 window object setup mismatch with jsdom environment
Donate.spec.tsx 875 variableMatcher mock not matching in MockedProvider
OrganizationModal.spec.tsx 668 Toast error message text mismatch ('Failed to upload image' vs. actual string)
AdvertisementRegister.spec.tsx 172 Same toast text mismatch on upload failure
getRefreshToken.spec.ts 187 localStorageMock.key not behaving correctly in handleTokenRefresh

Summary

Shard Failing File Root Cause Fix
1 AddMember.spec.tsx Pre-existing (needs investigation)
2 SearchFilterBar.spec.tsx selectOptions on non-native select Use click toggle + click option
3 SubTags.spec.tsx searchBtn removed by Toolbar Replace with keyboard('{Enter}')
4 Pledges.spec.tsx searchBtn removed by Toolbar Replace with keyboard('{Enter}')
5 Navbar.spec.tsx icon prop removed, use type Replace icon with type, update assertion
6 SidebarBase.spec.tsx Missing talawa-logo testid; renamed hamburger CSS Add testid to logo; add conditional hamburger class
7 ChatRoom.spec.tsx, EventManager.spec.ts Pre-existing mock exhaustion / error propagation
8 InternalFileWriter.spec.ts, Donate.spec.tsx, OrganizationModal.spec.tsx, Users.spec.tsx Mock where: undefined, toast text, window mismatch Match actual query variables; fix toast strings
9 AdvertisementRegister.spec.tsx, getRefreshToken.spec.ts Pre-existing (toast text / localStorage mock)
11 Advertisements.spec.tsx searchButton hidden by Toolbar Remove button assertion; use keyboard('{Enter}')

The clearest wins (Categories 1–5) are directly caused by the Toolbar/component refactor and can be fixed by updating ~8 test files following the same pattern this PR already applied to Organizations.spec.tsx.

- Replace vi.clearAllMocks() with vi.restoreAllMocks() across all specs
- Wrap post-interaction assertions in waitFor() for async stability
- Remove duplicate type-based icon test in SortingButton
- Fix Toolbar mock in posts.spec to only fire onSearch on Enter
- Add explicit guard for missing filter handler in OrganizationPeople
- Restore whitespace padding in Groups trim test
- Rename misleading test names in Organizations spec
Copy link
Copy Markdown
Contributor

@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 (6)
src/screens/UserPortal/UserGlobalScreen/UserGlobalScreen.spec.tsx (1)

305-320: ⚠️ Potential issue | 🔴 Critical

🔴 Remaining race window in toggle-back flow despite added waitFor

Issue Goals

  • ✅ Refactor-aligned class/assertion updates are covered in this file (e.g., contract/expand).
  • ⚠️ One acceptance-risk remains for flakiness: the test still interacts with the reopen control before explicitly waiting for it.

Tests (incl. Flakiness)

  • Line 314–315: getByTestId('openMenu') + immediate click can race after the previous async click on close.
  • This can still fail intermittently in shard CI even though final assertions are in waitFor (Lines 317–320).
Suggested fix
-      const openButton = screen.getByTestId('openMenu');
-      await user.click(openButton);
+      const openButton = await screen.findByTestId('openMenu');
+      await user.click(openButton);

Components/Policy

  • ✅ No component-policy violations identified in changed lines.

GraphQL

  • ✅ Not applicable in this spec segment.

i18n & a11y

  • ✅ No new i18n/a11y regressions introduced by changed lines.

Security

  • ✅ No security concerns in changed lines.

Action Items

  1. Update Line 314 to use an async query (findByTestId) before clicking.
  2. Keep final assertions in waitFor as currently done.

As per coding guidelines, “After clicking elements that open UI (dropdowns, modals, dialogs, tooltips): MUST waitFor the container/menu itself to be visible BEFORE checking child elements.”

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/screens/UserPortal/UserGlobalScreen/UserGlobalScreen.spec.tsx` around
lines 305 - 320, The test races because it calls getByTestId('openMenu') and
immediately user.click after the prior async click; change the second lookup to
await screen.findByTestId('openMenu') and then await user.click(openButton) so
the reopen control is present before interaction, and keep the existing
waitFor(...) assertions that verify closeMenu/openMenu states; reference the
existing getByTestId('closeMenu'), findByTestId('openMenu'), user.click and
waitFor calls when making the change.
src/screens/UserPortal/Volunteer/Groups/Groups.spec.tsx (2)

116-116: ⚠️ Potential issue | 🔴 Critical

❌ NON-DETERMINISTIC TIMESTAMP — Use fixed UTC string.

dayjs() without arguments captures the current time, causing test flakiness in sharded CI environments where tests run at different times.

 const group1 = {
   __typename: 'EventVolunteerGroup',
   id: 'groupId1',
   name: 'Group 1',
   description: 'Volunteer Group Description',
   volunteersRequired: null,
-  createdAt: dayjs().toISOString(),
+  createdAt: '2025-01-01T10:00:00.000Z',
   leader: {
 const group2 = {
   __typename: 'EventVolunteerGroup',
   id: 'groupId2',
   name: 'Group 2',
   description: 'Volunteer Group Description',
   volunteersRequired: null,
-  createdAt: dayjs().toISOString(),
+  createdAt: '2025-01-01T10:00:00.000Z',
   leader: {

As per coding guidelines: "❌ FORBIDDEN PATTERNS: dayjs() without arguments (use dayjs('2025-01-01T10:00:00Z'))"

Also applies to: 157-157

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/screens/UserPortal/Volunteer/Groups/Groups.spec.tsx` at line 116, Replace
the non-deterministic dayjs().toISOString() used for test timestamps with a
fixed UTC string (e.g. '2025-01-01T10:00:00Z'); update the createdAt fields in
the test fixture/mock objects referenced in Groups.spec.tsx (the createdAt
property in the test data and the other occurrence noted at line 157) so tests
use a deterministic timestamp instead of dayjs() without arguments.

1467-1476: 🧹 Nitpick | 🔵 Trivial

Consider adding observable result assertion after Enter submit.

This test verifies the Enter key submit path but only asserts the input value. Adding an observable result check (similar to line 1444) would confirm the submit actually triggered the search.

Suggested enhancement
     setNativeInputValue(searchInput, 'Group 1');
     await userEvent.keyboard('{Enter}');
 
     // Verify search is handled
-    expect(searchInput).toHaveValue('Group 1');
+    await waitFor(() => {
+      expect(searchInput).toHaveValue('Group 1');
+      expect(screen.queryByText('Group 2')).not.toBeInTheDocument();
+    }, { timeout: 1500 });
   });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/screens/UserPortal/Volunteer/Groups/Groups.spec.tsx` around lines 1467 -
1476, The test currently simulates typing into searchByInput via
setNativeInputValue and pressing Enter (userEvent.keyboard) but only asserts the
input value; add an observable result assertion after the Enter press to confirm
the search ran (for example, assert the expected group appears in the DOM using
screen.getByText('Group 1') or a relevant results test id), placing this check
immediately after the existing expect(searchInput).toHaveValue('Group 1') so the
Enter-submit path verifies visible search results.
src/shared-components/SortingButton/SortingButton.spec.tsx (1)

178-221: ⚠️ Potential issue | 🔴 Critical

❌ BLOCKING - Missing cleanup() call in afterEach hook and assertions not awaited after user interactions.

Line 85-87: afterEach only calls vi.restoreAllMocks(). Add cleanup() from @testing-library/react for proper DOM teardown in sharded test execution.

Lines 183-186, 196-197, 207-208, 217-220, 333-336: Assertions after await user.click() must be wrapped in waitFor blocks. Although the mocked DropDownButton renders synchronously, the real component uses React-Bootstrap's async dropdown behavior. Wrap all assertions in waitFor for robustness and to match actual component behavior:

+import { render, screen, cleanup, waitFor } from '@testing-library/react';
...
     await user.click(screen.getByTestId('sort-toggle'));
+    await waitFor(() => {
       expect(screen.getByTestId('latest')).toBeInTheDocument();
       expect(screen.getByTestId('oldest')).toBeInTheDocument();
       expect(screen.getByTestId('1')).toBeInTheDocument();
       expect(screen.getByTestId('2')).toBeInTheDocument();
+    });

Also add to afterEach:

   afterEach(() => {
+    cleanup();
     vi.restoreAllMocks();
   });

Also applies to: 189-209, 314-337

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/shared-components/SortingButton/SortingButton.spec.tsx` around lines 178
- 221, Add cleanup() to the afterEach hook and ensure assertions following async
user interactions are awaited inside waitFor: import cleanup and waitFor from
`@testing-library/react`, update the afterEach to call vi.restoreAllMocks() and
cleanup(), and wrap the post-click expects in waitFor in the SortingButton tests
(references: afterEach, user.click calls targeting testIds 'sort-toggle',
'latest', 'oldest', '1', '2', and the vi.fn() onSortChange assertions) so DOM
teardown and the asynchronous dropdown behavior are handled reliably.
src/screens/UserPortal/Organizations/Organizations.spec.tsx (2)

592-609: ⚠️ Potential issue | 🟠 Major

Assert mode-specific output after each mode switch.

Re-checking organizations-list here does not prove the toggle worked, because that container is already rendered before switching modes. This test can still pass if the joined/created queries never run. Assert a mode-unique card or other mode-specific result after each selection so the regression coverage remains meaningful.

Based on learnings: screen tests should verify integration behavior in different scenarios rather than only asserting a shared container remains mounted.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/screens/UserPortal/Organizations/Organizations.spec.tsx` around lines 592
- 609, The test currently only re-checks the shared container
('organizations-list') after toggling modes, which doesn't verify the mode
switch; update the assertions after clicking modeChangeBtn-item-1 and
modeChangeBtn-item-2 to assert a mode-specific outcome (e.g., a unique test id
or text for the Joined vs Created view) instead of just 'organizations-list' —
for example assert a Joined-specific card/testid (like
'joined-organization-card' or a known organization name returned by the joined
query) after clicking modeChangeBtn-item-1 and assert a Created-specific
card/testid (like 'created-organization-card' or expected created org name)
after clicking modeChangeBtn-item-2 (you can also assert that the relevant
API/mocked query for the mode was invoked); update the checks around
userEvent.click(modeButton), modeChangeBtn-item-1, and modeChangeBtn-item-2 to
use those mode-unique assertions so the test actually validates mode-specific
rendering.

556-560: ⚠️ Potential issue | 🟠 Major

Replace global keyboard dispatch with input-targeted Enter key in all search test cases.

userEvent.keyboard('{Enter}') is focus-dependent and flaky in sharded CI when the input rerenders during async operations. The file already demonstrates the correct pattern at line 531: use await userEvent.type(searchInput, '{Enter}') instead to ensure the keypress targets the specific input element.

Instances to fix: lines 560, 734, 1703, 1791, 2032, 2136.

🔧 Correct pattern
  const searchInput = screen.getByTestId('searchInput');
  await userEvent.clear(searchInput);
  await userEvent.type(searchInput, 'Search Term');
-
-  await userEvent.keyboard('{Enter}');
+  await userEvent.type(searchInput, '{Enter}');

Human: For context, the learning from suhaib-ilahi on PR #7187 confirmed that user.keyboard() targeting wrong input due to focus issues caused shard failures; the fix was using input-targeted typing instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/screens/UserPortal/Organizations/Organizations.spec.tsx` around lines 556
- 560, The test uses a global Enter dispatch via userEvent.keyboard('{Enter}')
which is focus-dependent and flaky; update each failing case to target the
specific input element by replacing calls to userEvent.keyboard('{Enter}') with
await userEvent.type(searchInput, '{Enter}') (e.g., where searchInput is
obtained via screen.getByTestId('searchInput') in the Organizations.spec.tsx
tests at the noted instances) so the Enter keypress is sent directly to that
input and not reliant on document focus.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/screens/UserPortal/Volunteer/Groups/Groups.spec.tsx`:
- Around line 678-685: The test currently calls findAllByTestId('viewGroupBtn')
which can resolve against the initial pre-search state and makes the following
waitFor ineffective; after calling setNativeInputValue(searchInput, 'Group') you
should instead wait for a search-specific update (e.g., wait for the grid to
reflect the filtered results) before capturing the view buttons—use waitFor with
getAllByTestId('viewGroupBtn') (or await screen.findByText / another unique
result indicator) to assert the expected post-search count/state, then call
userEvent.click on the resolved button; update references around
setNativeInputValue, searchInput, viewGroupBtn, waitFor, and userEvent.click
accordingly.

In `@src/shared-components/SortingButton/SortingButton.spec.tsx`:
- Around line 85-87: The test suite is missing DOM cleanup between tests; import
cleanup from `@testing-library/react` and call cleanup() inside the existing
afterEach (e.g., in the same block that currently calls vi.restoreAllMocks()) so
the rendered DOM from render() in SortingButton tests is cleared between tests;
ensure cleanup() runs before vi.restoreAllMocks() in the afterEach that
currently surrounds the tests.

---

Outside diff comments:
In `@src/screens/UserPortal/Organizations/Organizations.spec.tsx`:
- Around line 592-609: The test currently only re-checks the shared container
('organizations-list') after toggling modes, which doesn't verify the mode
switch; update the assertions after clicking modeChangeBtn-item-1 and
modeChangeBtn-item-2 to assert a mode-specific outcome (e.g., a unique test id
or text for the Joined vs Created view) instead of just 'organizations-list' —
for example assert a Joined-specific card/testid (like
'joined-organization-card' or a known organization name returned by the joined
query) after clicking modeChangeBtn-item-1 and assert a Created-specific
card/testid (like 'created-organization-card' or expected created org name)
after clicking modeChangeBtn-item-2 (you can also assert that the relevant
API/mocked query for the mode was invoked); update the checks around
userEvent.click(modeButton), modeChangeBtn-item-1, and modeChangeBtn-item-2 to
use those mode-unique assertions so the test actually validates mode-specific
rendering.
- Around line 556-560: The test uses a global Enter dispatch via
userEvent.keyboard('{Enter}') which is focus-dependent and flaky; update each
failing case to target the specific input element by replacing calls to
userEvent.keyboard('{Enter}') with await userEvent.type(searchInput, '{Enter}')
(e.g., where searchInput is obtained via screen.getByTestId('searchInput') in
the Organizations.spec.tsx tests at the noted instances) so the Enter keypress
is sent directly to that input and not reliant on document focus.

In `@src/screens/UserPortal/UserGlobalScreen/UserGlobalScreen.spec.tsx`:
- Around line 305-320: The test races because it calls getByTestId('openMenu')
and immediately user.click after the prior async click; change the second lookup
to await screen.findByTestId('openMenu') and then await user.click(openButton)
so the reopen control is present before interaction, and keep the existing
waitFor(...) assertions that verify closeMenu/openMenu states; reference the
existing getByTestId('closeMenu'), findByTestId('openMenu'), user.click and
waitFor calls when making the change.

In `@src/screens/UserPortal/Volunteer/Groups/Groups.spec.tsx`:
- Line 116: Replace the non-deterministic dayjs().toISOString() used for test
timestamps with a fixed UTC string (e.g. '2025-01-01T10:00:00Z'); update the
createdAt fields in the test fixture/mock objects referenced in Groups.spec.tsx
(the createdAt property in the test data and the other occurrence noted at line
157) so tests use a deterministic timestamp instead of dayjs() without
arguments.
- Around line 1467-1476: The test currently simulates typing into searchByInput
via setNativeInputValue and pressing Enter (userEvent.keyboard) but only asserts
the input value; add an observable result assertion after the Enter press to
confirm the search ran (for example, assert the expected group appears in the
DOM using screen.getByText('Group 1') or a relevant results test id), placing
this check immediately after the existing expect(searchInput).toHaveValue('Group
1') so the Enter-submit path verifies visible search results.

In `@src/shared-components/SortingButton/SortingButton.spec.tsx`:
- Around line 178-221: Add cleanup() to the afterEach hook and ensure assertions
following async user interactions are awaited inside waitFor: import cleanup and
waitFor from `@testing-library/react`, update the afterEach to call
vi.restoreAllMocks() and cleanup(), and wrap the post-click expects in waitFor
in the SortingButton tests (references: afterEach, user.click calls targeting
testIds 'sort-toggle', 'latest', 'oldest', '1', '2', and the vi.fn()
onSortChange assertions) so DOM teardown and the asynchronous dropdown behavior
are handled reliably.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: f819217c-00b3-4138-ac0b-76aeaa231e4d

📥 Commits

Reviewing files that changed from the base of the PR and between ef38d4e and 6ec899b.

📒 Files selected for processing (6)
  • src/screens/AdminPortal/OrganizationPeople/OrganizationPeople.spec.tsx
  • src/screens/UserPortal/Organizations/Organizations.spec.tsx
  • src/screens/UserPortal/UserGlobalScreen/UserGlobalScreen.spec.tsx
  • src/screens/UserPortal/Volunteer/Groups/Groups.spec.tsx
  • src/shared-components/SortingButton/SortingButton.spec.tsx
  • src/shared-components/posts/posts.spec.tsx

Comment on lines +678 to 685
setNativeInputValue(searchInput, 'Group');

// Open modal
const viewButtons = screen.getAllByTestId('viewGroupBtn');
expect(viewButtons.length).toBeGreaterThan(0);
// Wait for grid to reload after search change, then open modal
const viewButtons = await screen.findAllByTestId('viewGroupBtn');
await waitFor(() => {
expect(viewButtons.length).toBeGreaterThan(0);
});
await userEvent.click(viewButtons[0]);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Potential race condition: findAllByTestId resolves from initial state.

The findAllByTestId('viewGroupBtn') at line 681 resolves immediately against the pre-search state (2 buttons). The subsequent waitFor on lines 682-684 checks an already-resolved array, so the test may pass even if the search refetch never completes.

Since this test verifies search state persistence across modal open/close, consider waiting for a search-specific indicator before proceeding:

Suggested fix
    const searchInput = screen.getByTestId('searchByInput') as HTMLInputElement;
    setNativeInputValue(searchInput, 'Group');

-   // Wait for grid to reload after search change, then open modal
-   const viewButtons = await screen.findAllByTestId('viewGroupBtn');
-   await waitFor(() => {
-     expect(viewButtons.length).toBeGreaterThan(0);
-   });
+   // Wait for search to complete - verify data grid reflects search
+   await waitFor(() => {
+     expect(screen.getAllByTestId('viewGroupBtn').length).toBeGreaterThan(0);
+   });
+   const viewButtons = screen.getAllByTestId('viewGroupBtn');
    await userEvent.click(viewButtons[0]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/screens/UserPortal/Volunteer/Groups/Groups.spec.tsx` around lines 678 -
685, The test currently calls findAllByTestId('viewGroupBtn') which can resolve
against the initial pre-search state and makes the following waitFor
ineffective; after calling setNativeInputValue(searchInput, 'Group') you should
instead wait for a search-specific update (e.g., wait for the grid to reflect
the filtered results) before capturing the view buttons—use waitFor with
getAllByTestId('viewGroupBtn') (or await screen.findByText / another unique
result indicator) to assert the expected post-search count/state, then call
userEvent.click on the resolved button; update references around
setNativeInputValue, searchInput, viewGroupBtn, waitFor, and userEvent.click
accordingly.

Comment thread src/shared-components/SortingButton/SortingButton.spec.tsx
- Fix race condition in UserGlobalScreen toggle-back flow (findByTestId)
- Add cleanup() and waitFor wrappers in SortingButton spec
- Add observable grid assertion in Groups search submit test
- Verify mode-specific output in Organizations mode-switch test
Copy link
Copy Markdown
Contributor

@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

♻️ Duplicate comments (1)
src/screens/UserPortal/Volunteer/Groups/Groups.spec.tsx (1)

680-684: ⚠️ Potential issue | 🟠 Major

Flaky search assertions still allow false positives in two updated paths

Issue Goals

  • For #7546, the test should prove async search state has settled.
  • Line 681 currently can resolve from pre-search UI, and Line 1475/Line 1478 asserts immediately after an async key event.

Tests (incl. Flakiness)

  • Line 680–684: findAllByTestId + asserting cached viewButtons.length does not verify post-search refetch state.
  • Line 1475–1478: assertions after await userEvent.keyboard('{Enter}') are outside waitFor, so they are race-prone in sharded CI.

Components/Policy

  • No component-policy issues in this diff.

GraphQL

  • Current checks can pass even if Enter-submit/search refetch regresses, because observable filtered results are not awaited.

i18n & a11y

  • No i18n/a11y issue in these changed lines.

Security

  • No security issue in these changed lines.

Action Items

Suggested stabilization patch
@@
-   // Wait for grid to reload after search change, then open modal
-   const viewButtons = await screen.findAllByTestId('viewGroupBtn');
-   await waitFor(() => {
-     expect(viewButtons.length).toBeGreaterThan(0);
-   });
+   // Wait for post-search grid state, then open modal
+   await waitFor(() => {
+     expect(screen.getAllByTestId('viewGroupBtn').length).toBeGreaterThan(0);
+   });
+   const viewButtons = screen.getAllByTestId('viewGroupBtn');
    await userEvent.click(viewButtons[0]);
@@
    setNativeInputValue(searchInput, 'Group 1');
    await userEvent.keyboard('{Enter}');
-
-   // Verify search is handled
-   expect(searchInput).toHaveValue('Group 1');
-
-   // Verify the grid is still rendered after search submit
-   expect(screen.getByRole('grid')).toBeInTheDocument();
+   await waitFor(() => {
+     expect(searchInput).toHaveValue('Group 1');
+     expect(screen.getByRole('grid')).toBeInTheDocument();
+     expect(screen.getByText('Group 1')).toBeInTheDocument();
+     expect(screen.queryByText('Group 2')).not.toBeInTheDocument();
+   });

As per coding guidelines, “expect(...) after await userEvent… not inside waitFor” is a blocking race pattern, and async UI transitions must be validated with condition-based waits.

Also applies to: 1472-1478

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/screens/UserPortal/Volunteer/Groups/Groups.spec.tsx` around lines 680 -
684, The current test uses screen.findAllByTestId('viewGroupBtn') and then
asserts on the cached viewButtons.length and also performs assertions
immediately after userEvent.keyboard('{Enter}'), which can observe pre-search
state and cause flakes; change both checks to wait for the post-search DOM state
instead: replace the cached-length assertion with a waitFor(() =>
expect(screen.queryAllByTestId('viewGroupBtn').length).toBeGreaterThan(0)) to
ensure the refetched grid has rendered, and wrap any assertions that follow
userEvent.keyboard('{Enter}') inside waitFor conditions that verify the expected
DOM change (e.g., presence/absence or count of 'viewGroupBtn' or the specific
result node) rather than asserting immediately after userEvent.keyboard.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/screens/UserPortal/Organizations/Organizations.spec.tsx`:
- Line 568: The test currently named "should search organizations when pressing
Enter key with keyboard helper" does not assert Enter-key submission but instead
verifies mode switching and selected-mode styling; rename the test declaration
(the test(...) call in Organizations.spec.tsx) to something like "should switch
search mode and apply selected-mode styling" so the title matches the assertions
(references: the test(...) invocation around the modal/mode switching assertions
and any assertions checking selected-mode class/styling).
- Line 560: Replace the focus-dependent calls to userEvent.keyboard('{Enter}')
with explicit input-targeted submissions using userEvent.type(searchInput,
'{Enter}') to match the pattern used at line 531; locate each occurrence of
userEvent.keyboard('{Enter}') (six instances referenced around lines 560, 755,
1724, 1812, 2053, 2157) and change them to call userEvent.type with the same
searchInput element used elsewhere in the test suite so the Enter key is sent
directly to the input rather than relying on focus.

---

Duplicate comments:
In `@src/screens/UserPortal/Volunteer/Groups/Groups.spec.tsx`:
- Around line 680-684: The current test uses
screen.findAllByTestId('viewGroupBtn') and then asserts on the cached
viewButtons.length and also performs assertions immediately after
userEvent.keyboard('{Enter}'), which can observe pre-search state and cause
flakes; change both checks to wait for the post-search DOM state instead:
replace the cached-length assertion with a waitFor(() =>
expect(screen.queryAllByTestId('viewGroupBtn').length).toBeGreaterThan(0)) to
ensure the refetched grid has rendered, and wrap any assertions that follow
userEvent.keyboard('{Enter}') inside waitFor conditions that verify the expected
DOM change (e.g., presence/absence or count of 'viewGroupBtn' or the specific
result node) rather than asserting immediately after userEvent.keyboard.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: ab896245-e3d8-4c92-ab1d-7663b099f188

📥 Commits

Reviewing files that changed from the base of the PR and between 6ec899b and f0ad58b.

📒 Files selected for processing (4)
  • src/screens/UserPortal/Organizations/Organizations.spec.tsx
  • src/screens/UserPortal/UserGlobalScreen/UserGlobalScreen.spec.tsx
  • src/screens/UserPortal/Volunteer/Groups/Groups.spec.tsx
  • src/shared-components/SortingButton/SortingButton.spec.tsx


const searchButton = screen.getByTestId('searchBtn');
await userEvent.click(searchButton);
await userEvent.keyboard('{Enter}');
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

head -n 50 src/screens/UserPortal/Organizations/Organizations.spec.tsx | tail -n 30

Repository: PalisadoesFoundation/talawa-admin

Length of output: 949


🏁 Script executed:

# First, check if the file exists and get size
wc -l src/screens/UserPortal/Organizations/Organizations.spec.tsx

Repository: PalisadoesFoundation/talawa-admin

Length of output: 141


🏁 Script executed:

# Get context around line 560 - check searchInput definition and usage
sed -n '540,580p' src/screens/UserPortal/Organizations/Organizations.spec.tsx

Repository: PalisadoesFoundation/talawa-admin

Length of output: 1198


🏁 Script executed:

# Check around line 755
sed -n '740,770p' src/screens/UserPortal/Organizations/Organizations.spec.tsx

Repository: PalisadoesFoundation/talawa-admin

Length of output: 980


🏁 Script executed:

# Search for searchInput definition in the file
rg -n 'searchInput\s*=' src/screens/UserPortal/Organizations/Organizations.spec.tsx | head -20

Repository: PalisadoesFoundation/talawa-admin

Length of output: 527


🏁 Script executed:

# Check how searchInput is initially queried and what type it is
rg -n 'searchInput' src/screens/UserPortal/Organizations/Organizations.spec.tsx | head -30

Repository: PalisadoesFoundation/talawa-admin

Length of output: 1573


🏁 Script executed:

# Get exact lines 560, 755, 1724, 1812, 2053, 2157 to confirm the current code
sed -n '560p;755p;1724p;1812p;2053p;2157p' src/screens/UserPortal/Organizations/Organizations.spec.tsx

Repository: PalisadoesFoundation/talawa-admin

Length of output: 310


🏁 Script executed:

# Get broader context for line 560 to see the test structure
sed -n '555,565p' src/screens/UserPortal/Organizations/Organizations.spec.tsx

Repository: PalisadoesFoundation/talawa-admin

Length of output: 408


🏁 Script executed:

# Check for all instances of userEvent.keyboard in the file
rg -n 'userEvent\.keyboard' src/screens/UserPortal/Organizations/Organizations.spec.tsx

Repository: PalisadoesFoundation/talawa-admin

Length of output: 338


🏁 Script executed:

# Check for all instances of userEvent.type with Enter key
rg -n "userEvent\.type.*Enter" src/screens/UserPortal/Organizations/Organizations.spec.tsx

Repository: PalisadoesFoundation/talawa-admin

Length of output: 128


🏁 Script executed:

# Get full context around line 531 to compare with line 560
sed -n '525,535p' src/screens/UserPortal/Organizations/Organizations.spec.tsx

Repository: PalisadoesFoundation/talawa-admin

Length of output: 493


🏁 Script executed:

# Verify the pattern at all 6 locations to confirm searchInput is defined before each keyboard call
sed -n '555,562p' src/screens/UserPortal/Organizations/Organizations.spec.tsx && echo "---" && \
sed -n '750,757p' src/screens/UserPortal/Organizations/Organizations.spec.tsx && echo "---" && \
sed -n '1720,1727p' src/screens/UserPortal/Organizations/Organizations.spec.tsx && echo "---" && \
sed -n '1808,1815p' src/screens/UserPortal/Organizations/Organizations.spec.tsx && echo "---" && \
sed -n '2049,2056p' src/screens/UserPortal/Organizations/Organizations.spec.tsx && echo "---" && \
sed -n '2153,2160p' src/screens/UserPortal/Organizations/Organizations.spec.tsx

Repository: PalisadoesFoundation/talawa-admin

Length of output: 1782


🏁 Script executed:

# Check test names around these lines to understand test intent
rg -B2 "userEvent\.keyboard\(\'{Enter}\'\)" src/screens/UserPortal/Organizations/Organizations.spec.tsx

Repository: PalisadoesFoundation/talawa-admin

Length of output: 198


🏁 Script executed:

# Check test names around these lines
rg -B2 "userEvent.keyboard" src/screens/UserPortal/Organizations/Organizations.spec.tsx

Repository: PalisadoesFoundation/talawa-admin

Length of output: 772


🏁 Script executed:

# Check test names/descriptions for the 6 keyboard calls
sed -n '520,562p' src/screens/UserPortal/Organizations/Organizations.spec.tsx | grep -A1 "test("

Repository: PalisadoesFoundation/talawa-admin

Length of output: 172


🏁 Script executed:

# Get test names for all 6 keyboard locations
sed -n '520,530p' src/screens/UserPortal/Organizations/Organizations.spec.tsx && echo "---560---" && \
sed -n '746,758p' src/screens/UserPortal/Organizations/Organizations.spec.tsx && echo "---755---" && \
sed -n '1716,1728p' src/screens/UserPortal/Organizations/Organizations.spec.tsx && echo "---1724---" && \
sed -n '1804,1816p' src/screens/UserPortal/Organizations/Organizations.spec.tsx && echo "---1812---" && \
sed -n '2045,2060p' src/screens/UserPortal/Organizations/Organizations.spec.tsx && echo "---2053---" && \
sed -n '2149,2165p' src/screens/UserPortal/Organizations/Organizations.spec.tsx

Repository: PalisadoesFoundation/talawa-admin

Length of output: 3066


🏁 Script executed:

# Verify that line 531 exists and uses the suggested pattern
sed -n '530,532p' src/screens/UserPortal/Organizations/Organizations.spec.tsx

Repository: PalisadoesFoundation/talawa-admin

Length of output: 177


🏁 Script executed:

# Check if there are any comments or context around why line 531 uses type() instead of keyboard()
sed -n '520,535p' src/screens/UserPortal/Organizations/Organizations.spec.tsx

Repository: PalisadoesFoundation/talawa-admin

Length of output: 569


Align Enter key submission with line 531 pattern for consistency and stability.

userEvent.keyboard('{Enter}') relies on focus state and is inconsistent with line 531, which correctly uses userEvent.type(searchInput, '{Enter}'). Replace all 6 instances to explicitly target the input element, preventing focus-dependency flakiness.

Affected lines

Line 560, 755, 1724, 1812, 2053, 2157

Fix: Change await userEvent.keyboard('{Enter}') to await userEvent.type(searchInput, '{Enter}') at each location.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/screens/UserPortal/Organizations/Organizations.spec.tsx` at line 560,
Replace the focus-dependent calls to userEvent.keyboard('{Enter}') with explicit
input-targeted submissions using userEvent.type(searchInput, '{Enter}') to match
the pattern used at line 531; locate each occurrence of
userEvent.keyboard('{Enter}') (six instances referenced around lines 560, 755,
1724, 1812, 2053, 2157) and change them to call userEvent.type with the same
searchInput element used elsewhere in the test suite so the Enter key is sent
directly to the input rather than relying on focus.

});

test('Mode dropdown switches list correctly', async () => {
test('should search organizations when pressing Enter key with keyboard helper', async () => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Rename the test to match what it actually validates.

Line 568 says this test is about “pressing Enter key with keyboard helper,” but the body verifies mode switching and selected-mode styling (no Enter submission path). Please rename to reflect its true purpose.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/screens/UserPortal/Organizations/Organizations.spec.tsx` at line 568, The
test currently named "should search organizations when pressing Enter key with
keyboard helper" does not assert Enter-key submission but instead verifies mode
switching and selected-mode styling; rename the test declaration (the test(...)
call in Organizations.spec.tsx) to something like "should switch search mode and
apply selected-mode styling" so the title matches the assertions (references:
the test(...) invocation around the modal/mode switching assertions and any
assertions checking selected-mode class/styling).

@DMills27
Copy link
Copy Markdown
Member Author

DMills27 commented Apr 10, 2026

@coderabbitai Examine the failing Github actions and give insights on what changes need to be made to make them succeed.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 10, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Get latest CI runs for PR `#7548`
gh api "repos/PalisadoesFoundation/talawa-admin/pulls/7548/checks" --jq '.check_runs[] | select(.conclusion == "failure" or .conclusion == null) | {name: .name, status: .status, conclusion: .conclusion, id: .id, url: .html_url}' 2>/dev/null | head -100

echo ""
echo "===== Latest workflow runs for PR `#7548` ====="
gh api "repos/PalisadoesFoundation/talawa-admin/actions/runs?head_sha=$(gh api repos/PalisadoesFoundation/talawa-admin/pulls/7548 --jq '.head.sha')" --jq '.workflow_runs[] | {id: .id, name: .name, status: .status, conclusion: .conclusion, created_at: .created_at}' 2>/dev/null | head -60

Length of output: 1058


🏁 Script executed:

#!/bin/bash
RUNS=(24221393775 24221393757 24221221121 24221220140)

for RUN_ID in "${RUNS[@]}"; do
  echo "===== RUN $RUN_ID ====="
  gh api "repos/PalisadoesFoundation/talawa-admin/actions/runs/$RUN_ID/jobs" \
    --jq '.jobs[] | select(.conclusion == "failure") | {name: .name, id: .id, conclusion: .conclusion}' 2>/dev/null
  echo ""
done

Length of output: 1314


🏁 Script executed:

#!/bin/bash
# Get failing test names for all test shards
JOBS=(70713354843 70713354845 70713354846 70713354848 70713354856 70713354857 70713354865 70713354866 70713354867 70713354956)

for JOB_ID in "${JOBS[@]}"; do
  echo "===== JOB $JOB_ID ====="
  gh api "repos/PalisadoesFoundation/talawa-admin/actions/jobs/$JOB_ID/logs" 2>/dev/null | \
    grep -E "(FAIL |× |✗ |●  |\.spec\.(tsx|ts|js) >|AssertionError|Expected|Cannot find module|TypeError|Unable to find)" | \
    grep -v "^$" | head -50
  echo ""
done

echo "===== SENSITIVE FILES CHECK (70712934343) ====="
gh api "repos/PalisadoesFoundation/talawa-admin/actions/jobs/70712934343/logs" 2>/dev/null | tail -40

echo ""
echo "===== PUSH WORKFLOW CODE COVERAGE (70712993597) ====="
gh api "repos/PalisadoesFoundation/talawa-admin/actions/jobs/70712993597/logs" 2>/dev/null | \
  grep -E "(FAIL |× |✗ |\.spec\.(tsx|ts|js) >|Error:|failed)" | head -40

Length of output: 53994


🏁 Script executed:

#!/bin/bash
echo "===== FundCampaignPledge.spec.tsx - searchBtn usage ====="
fd "FundCampaignPledge.spec.tsx" --exec grep -n "searchBtn\|searchInput\|keyboard\|Enter\|Search" {}

echo ""
echo "===== Invitations.spec.tsx - searchBtn usage ====="
fd "Invitations.spec.tsx" --exec grep -n "searchBtn\|searchInput\|keyboard\|Enter\|Search" {}

echo ""
echo "===== SidebarOrgSection.spec.tsx - failing tests ====="
fd "SidebarOrgSection.spec.tsx" --exec grep -n "button type\|disabled\|angle right\|type.*button\|toHaveAttribute\|Loading State\|Error State\|Success State" {}

echo ""
echo "===== SidebarOrgSection.tsx - what it actually renders ====="
fd "SidebarOrgSection.tsx" --exec grep -n "data-testid\|type=\|disabled\|angle\|className\|button" {} | head -40

echo ""
echo "===== VolunteerGroups.spec.tsx - failing search tests ====="
fd "VolunteerGroups.spec.tsx" src/screens/AdminPortal --exec grep -n "searchBtn\|debouncedSearch\|group name search\|via search button" {}

echo ""
echo "===== OrganizationDashboard.spec.tsx - failing test ====="
fd "OrganizationDashboard.spec.tsx" --exec grep -n "pending membership\|non-pending\|membership request" {} | head -20

echo ""
echo "===== AddMember.spec.tsx - addMembers and page-header testids ====="
fd "AddMember.spec.tsx" --exec grep -n "addMembers\|page-header\|getByTestId" {} | head -40

echo ""
echo "===== What testids AddMember component actually has ====="
fd "AddMember.tsx" --exec grep -n "data-testid" {} | head -30

echo ""
echo "===== SearchFilterBar.spec.tsx - sort-select and debounce tests ====="
fd "SearchFilterBar.spec.tsx" --exec sed -n '1,50p' {}
echo "..."
fd "SearchFilterBar.spec.tsx" --exec grep -n "sort-select\|debounce\|mock-sorting-button\|filterPlugins" {} | head -30

echo ""
echo "===== SearchFilterBar component - what testids it actually uses ====="
fd "SearchFilterBar.tsx" --exec grep -n "data-testid\|testIdPrefix\|select\|sort" {} | head -30

Length of output: 12084


🏁 Script executed:

#!/bin/bash
echo "===== SidebarOrgSection.spec.tsx - loading/error state tests ====="
fd "SidebarOrgSection.spec.tsx" --exec sed -n '200,345p' {}

echo ""
echo "===== AddMember.tsx - look for addMembers, page-header, Toolbar usage ====="
fd "AddMember.tsx" --exec grep -n "Toolbar\|PageHeader\|SearchFilterBar\|addMembers\|page-header\|toolbar\|data-testid" {} | head -30

echo ""
echo "===== OrganizationDashboard.spec.tsx - failing test body ====="
fd "OrganizationDashboard.spec.tsx" --exec sed -n '388,450p' {}

echo ""
echo "===== SearchFilterBar.tsx - full component to understand prop names ====="
fd "SearchFilterBar.tsx" --exec cat {} | head -80

echo ""
echo "===== SearchFilterBar types/interface ====="
fd "interface.ts" src --exec grep -n "dataTestIdPrefix\|testIdPrefix\|SearchFilterBar\|SortingButton" {} | head -30

echo ""
echo "===== SortingButton props interface ====="
fd "interface.ts" src/shared-components/SortingButton --exec cat {}
fd "SortingButton.tsx" --exec grep -n "testIdPrefix\|dataTestIdPrefix\|interface\|type\|props" {} | head -20

Length of output: 12577


@DMills27 — Here is a full breakdown of every currently failing test in the latest CI run, grouped by root cause with concrete fixes.


🔴 Critical Blocker: Sensitive File Check

Job: Checks if sensitive files have been changed without authorization

The CI policy flags config/vite.config.ts as a protected file. The log says:

"Unauthorized changes detected in sensitive files: config/vite.config.ts"

This must be authorized by a maintainer before the run can pass. The Vite config changes in this PR (CYPRESS_COVERAGE gate, ALLOW_LOGS verbose proxy gate) are functionally correct but will need explicit maintainer approval.


🔴 Category 1: searchBtn / searchButton Hidden by Toolbar (5 files)

Same root cause as the files already fixed in this PR — Toolbar sets showSearchButton={false}, removing the search button from the DOM.

FundCampaignPledge.spec.tsx — Line 762

// BEFORE
await userEvent.click(screen.getByTestId('searchBtn'));

// AFTER
await userEvent.keyboard('{Enter}');

Invitations.spec.tsx — Line 673

// BEFORE
await user.click(screen.getByTestId('searchBtn'));

// AFTER
await user.keyboard('{Enter}');

VolunteerGroups.spec.tsx (AdminPortal) — Lines 509–510, 580–581, 651–655

// BEFORE (lines 509-510)
const searchBtn = screen.getByTestId('searchBtn');
await userEvent.click(searchBtn);

// AFTER
await userEvent.keyboard('{Enter}');

Repeat for lines 580–581 and 651–655 (three separate test blocks).

SubTags.spec.tsx — (already identified in previous analysis)

await userEvent.keyboard('{Enter}'); // replaces getByTestId('searchBtn') click

Advertisements.spec.tsx — (already identified)

Remove the expect(screen.getByTestId('searchButton')).toBeInTheDocument() assertion; replace all userEvent.click(screen.getByTestId('searchButton')) with await userEvent.keyboard('{Enter}').


🔴 Category 2: SidebarBase.spec.tsx — Missing testid & renamed CSS classes

Tests fail on:

  • data-testid="talawa-logo" — not present in component
  • class /sidebarBrandingContainer/ — actual class is _toggleBtn_d1a4a8 _toggleBtnExpanded_...
  • class /hamburgerIconExpanded/ — actual class is just _hamburgerIcon_d1a4a8 (no variant suffix)
  • class /hamburgerIconCollapsed/ — same, no suffix

Fix in SidebarBase.tsx — add the testid and conditional classes:

// 1. Add data-testid to the TalawaLogo wrapper:
<span data-testid="talawa-logo">
  <TalawaLogo className={styles.talawaLogo} />
</span>

// 2. Add conditional hamburger icon class:
<FaBars
  className={`${styles.hamburgerIcon} ${
    hideDrawer
      ? styles.hamburgerIconCollapsed
      : styles.hamburgerIconExpanded
  }`}
  size={22}
/>

And add the corresponding CSS module entries hamburgerIconExpanded / hamburgerIconCollapsed in SidebarBase.module.css.


🔴 Category 3: SidebarOrgSection.spec.tsx — Three Separate Issues

Issue A: Loading state — <div> has no type attribute

The loading state renders a <div data-testid="orgBtn">, not a <button>. Test asserts toHaveAttribute('type', 'button').

Fix in SidebarOrgSection.tsx — change the loading div to a button:

// Loading branch — change div to button:
<button
  type="button"
  className={`${styles.profileContainer} shimmer`}
  data-testid="orgBtn"
  disabled
/>

Issue B: Error state — not a <button>

Test does .closest('button') from "Error loading Organization" text, but the element is a <div>.

Fix in SidebarOrgSection.tsx — change error container to a disabled button:

<button
  type="button"
  disabled
  className={`${styles.profileContainer} ${styles.bgDanger} text-white`}
  data-testid="sidebar-org-error"
>
  ...
</button>

Issue C: AngleRightIcon — no data-testid

Test looks for data-testid="angle-right-icon" but the component renders the SVG without a testid.

Fix in SidebarOrgSection.tsx:

<AngleRightIcon
  data-testid="angle-right-icon"
  fill="var(--bs-secondary)"
  data-fill="var(--bs-secondary)"
/>

🔴 Category 4: AddMember.spec.tsxaddMembers testid missing from DOM

AddMember.tsx uses Toolbar with testIdPrefix: 'addMembers'. DropDownButton renders the toggle with data-testid="addMembers-select", not data-testid="addMembers". The old page-header testid was from the pre-refactor Navbar/PageHeader.

Fix in AddMember.spec.tsx — mock the Toolbar to expose the expected testids:

vi.mock('shared-components/Toolbar/Toolbar', () => ({
  default: vi.fn(({ actions, filters }) => (
    <div data-testid="page-header">
      {actions?.map((action) => (
        <button
          key={action.label}
          data-testid={`${filters?.[0]?.testIdPrefix ?? 'addMembers'}`}
          onClick={action.onClick}
          type="button"
        >
          {action.label}
        </button>
      ))}
    </div>
  )),
}));

Or, update the assertions to use addMembers-select instead of addMembers — whichever matches the actual DropDownButton testid rendered by Toolbar.


🔴 Category 5: SearchFilterBar.spec.tsx — Prop name mismatch in SortingButton mock

The mock destructures dataTestIdPrefix, but Toolbar (which SearchFilterBar delegates to) passes the prop as testIdPrefix to SortingButton. So dataTestIdPrefix is undefined in the mock, and data-testid="mock-sorting-button-undefined" is rendered instead of "mock-sorting-button-sort".

Additionally, some tests still use the old sort-select testid (lines 270, 279, 708, 760) which the new mock no longer renders.

Fix — Update the SortingButton mock in SearchFilterBar.spec.tsx:

vi.mock('shared-components/SortingButton/SortingButton', () => ({
  default: vi.fn(
    ({ sortingOptions, selectedOption, onSortChange, testIdPrefix, dataTestIdPrefix }) => {
      const prefix = testIdPrefix ?? dataTestIdPrefix;
      return (
        <div data-testid={`mock-sorting-button-${prefix}`}>
          <select
            data-testid={`${prefix}-select`}
            value={selectedOption}
            onChange={(e) => onSortChange?.(e.target.value)}
          >
            {sortingOptions?.map((opt: { value: string; label: string }) => (
              <option key={opt.value} value={opt.value}>
                {opt.label}
              </option>
            ))}
          </select>
        </div>
      );
    },
  ),
}));

This restores the sort-select testid (for old test assertions) and correctly handles both testIdPrefix and dataTestIdPrefix.


🔴 Category 6: Users.spec.tsxwhere: <undefined> mock mismatch

The error mock specifies where: undefined but MockedProvider performs strict equality on variables. The component sends where: null.

// In errorMock / all mocks in Users.spec.tsx:
variables: {
  first: 12,
  after: null,
  orgFirst: 32,
  where: null, // ← was undefined
},

🟡 Category 7: Pre-existing failures (not caused by Toolbar refactor)

File Symptom Likely Root Cause
OrganizationDashboard.spec.tsx "correctly displays pending membership requests" MockedProvider timing / query variable mismatch
ChatRoom.spec.tsx Mock exhaustion for UpdateChatMessage/Chat Pre-existing mock count issue
EventManager.spec.ts uninstallPlugin is not a function Plugin manager API changed

These should be addressed in a separate PR/issue.


Summary Table

Shard File(s) Fix needed
6 SidebarBase.spec.tsx, FundCampaignPledge.spec.tsx, Invitations.spec.tsx Add testids/CSS in component; Enter key for search
4 Pledges.spec.tsx, SidebarOrgSection.spec.tsx Enter key; fix loading/error/icon in component
1 AddMember.spec.tsx Mock Toolbar or update testid references
5 EventManager.spec.ts (pre-existing) Separate fix needed
8 Users.spec.tsx where: undefinednull
2 SearchFilterBar.spec.tsx Fix SortingButton mock prop name + restore sort-select testid
3 SubTags.spec.tsx, OrganizationDashboard.spec.tsx Enter key; separate fix
11 Advertisements.spec.tsx, VolunteerGroups.spec.tsx Enter key for search
9 ChatRoom.spec.tsx (pre-existing) Separate fix needed
7 ChatRoom.spec.tsx (pre-existing) Separate fix needed
config/vite.config.ts Needs maintainer authorization

Fix 7 more test files broken by the Toolbar/SearchFilterBar refactoring:
- SubTags, Pledges, Advertisements, Users: replace searchBtn clicks with Enter key
- SearchFilterBar: replace selectOptions with click-based dropdown interaction
- Navbar: update icon prop to type prop in sorting config
- SidebarBase: fix logo testid and hamburger CSS class assertions
Copy link
Copy Markdown
Contributor

@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

Caution

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

⚠️ Outside diff range comments (2)
src/shared-components/SidebarBase/SidebarBase.spec.tsx (1)

63-69: ⚠️ Potential issue | 🔴 Critical

❌ BLOCKING test-stability violations must be fixed before merge

Test Cleanup (Critical for Sharded CI)

  • Line 64: Remove vi.clearAllMocks() from beforeEach. This pattern causes incomplete cleanup between tests in parallel shards.
  • Lines 67-69: Add cleanup() call to afterEach. Current implementation is missing required cleanup from @testing-library/react. Must contain both cleanup() AND vi.restoreAllMocks().

Async Assertion Race Conditions (Critical)

Lines 139–197: Assertions placed immediately after await userEvent.click() instead of inside waitFor() blocks. This causes flakiness in sharded CI when state changes are not fully propagated before assertions run.

Affected test cases:

  • Line 139–140: setHideDrawer toggle test
  • Line 146–147: setHideDrawer toggle test
  • Line 164–165: localStorage check test
  • Line 180–181: localStorage check test
  • Line 196–197: localStorage check test

Move each expect() call into waitFor() after corresponding await userEvent.click().

Suggested Pattern

afterEach(() => {
  cleanup();
  vi.restoreAllMocks();
});

// For each test:
await userEvent.click(toggleBtn);
await waitFor(() => {
  expect(mockSetHideDrawer).toHaveBeenCalledWith(true);
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/shared-components/SidebarBase/SidebarBase.spec.tsx` around lines 63 - 69,
Remove the vi.clearAllMocks() call from beforeEach, update afterEach to call
cleanup() followed by vi.restoreAllMocks(), and update the tests that assert
immediately after await userEvent.click(...) (the tests that use
mockSetHideDrawer and the localStorage assertions) so each expect(...) is placed
inside a waitFor(...) callback after the click (e.g., await
userEvent.click(toggleBtn); await waitFor(() => {
expect(mockSetHideDrawer).toHaveBeenCalledWith(true); });), ensuring all
assertions that depend on async state updates use waitFor.
src/components/AdminPortal/Advertisements/Advertisements.spec.tsx (1)

379-388: ⚠️ Potential issue | 🔴 Critical

❌ Blocking race condition after Enter-based search submissions.

After async search submission, assertions are not consistently condition-waited (fixed wait() or immediate expect). This is flaky in shard CI.

Proposed fix pattern (apply to all updated search tests)
-    await userEvent.keyboard('{Enter}');
-
-    await wait();
-    expect(screen.getByText('Cookie shop 6')).toBeInTheDocument();
-    expect(screen.queryByText('Cookie shop 5')).not.toBeInTheDocument();
+    await userEvent.keyboard('{Enter}');
+    await waitFor(() => {
+      expect(screen.getByText('Cookie shop 6')).toBeInTheDocument();
+      expect(screen.queryByText('Cookie shop 5')).not.toBeInTheDocument();
+    });
-    await userEvent.keyboard('{Enter}');
-    expect(
-      screen.getAllByText('Ads not present for this campaign.'),
-    ).toHaveLength(2);
+    await userEvent.keyboard('{Enter}');
+    await waitFor(() => {
+      expect(
+        screen.getAllByText('Ads not present for this campaign.'),
+      ).toHaveLength(2);
+    });

As per coding guidelines: “ALL assertions after async operations MUST be inside waitFor blocks” and “NEVER use fixed time delays in tests.”

Also applies to: 415-424, 447-456, 482-491, 514-518

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/AdminPortal/Advertisements/Advertisements.spec.tsx` around
lines 379 - 388, The test performs an Enter-based search by calling
userEvent.keyboard('{Enter}') then uses a bare wait() and immediate expects,
which causes a race; replace the fixed wait() and immediate assertions with a
proper asynchronous waitFor block (from `@testing-library/react`) that contains
the expects so the DOM assertions (screen.getByText('Cookie shop 6'),
screen.queryByText('Cookie shop 5'..'Cookie shop 1')) only run after the async
search completes; apply the same pattern to the other similar tests that call
userEvent.keyboard('{Enter}') (the groups around the current expect lines and
the ranges noted in the comment).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/screens/AdminPortal/SubTags/SubTags.spec.tsx`:
- Around line 4-11: The test uses a fragile hardcoded helper wait() and mixes
fireEvent.change() with user.keyboard(), causing flaky timing; remove the wait
helper (symbol: wait) and replace all await wait() usages with deterministic
async queries or waitFor() (e.g., screen.findByPlaceholderText,
screen.findByText) so assertions await the actual DOM conditions, and replace
fireEvent.change(...) usages with userEvent APIs (e.g., await user.type(...) or
await user.clear(...) + user.type(...)) to keep interactions consistent with
user.keyboard(); finally, remove fireEvent from the imports list to avoid
accidental usage and update tests referencing fireEvent.change to use the
userEvent equivalents (look for occurrences around the user.keyboard() call and
tests that previously awaited wait()).

In `@src/shared-components/Navbar/Navbar.spec.tsx`:
- Around line 77-82: Fix the JSX formatting and the inaccurate test: collapse
the JSX attributes for the icon node so the element uses inline attributes on a
single line (the div with data-testid={`${dataTestIdPrefix}-icon`} and
data-icon-type={type}) to satisfy Prettier, and update the test that claims
“type provided” (the spec block around lines 152-161) to actually pass an
explicit type prop into the rendered component (or else rename the test to state
it checks default behavior) so the provided-type path is exercised; search for
dataTestIdPrefix, data-testid `${dataTestIdPrefix}-icon`, and the spec block
referencing “type provided” to locate and change the code.

In `@src/shared-components/SearchFilterBar/SearchFilterBar.spec.tsx`:
- Around line 72-77: The spec has several race and policy issues: update the
afterEach block to call cleanup() and vi.restoreAllMocks(); ensure every
assertion that follows an async user action (e.g., after userEvent.click in
tests around the blocks referencing the dropdown/menu interactions) is wrapped
in waitFor; before querying/clicking option item testids (tests that toggle the
menu and then select options) await the menu visibility (e.g., await findByRole
or waitFor(() => expect(menu).toBeVisible())) so selection isn’t raced; replace
raw renders with the project helper that wraps components in I18nextProvider
(use the test render helper or renderWithI18next used elsewhere) instead of the
bare react-i18next mock; and fix the formatting violation noted near the
prettier warning by reformatting the affected code in the spec.

---

Outside diff comments:
In `@src/components/AdminPortal/Advertisements/Advertisements.spec.tsx`:
- Around line 379-388: The test performs an Enter-based search by calling
userEvent.keyboard('{Enter}') then uses a bare wait() and immediate expects,
which causes a race; replace the fixed wait() and immediate assertions with a
proper asynchronous waitFor block (from `@testing-library/react`) that contains
the expects so the DOM assertions (screen.getByText('Cookie shop 6'),
screen.queryByText('Cookie shop 5'..'Cookie shop 1')) only run after the async
search completes; apply the same pattern to the other similar tests that call
userEvent.keyboard('{Enter}') (the groups around the current expect lines and
the ranges noted in the comment).

In `@src/shared-components/SidebarBase/SidebarBase.spec.tsx`:
- Around line 63-69: Remove the vi.clearAllMocks() call from beforeEach, update
afterEach to call cleanup() followed by vi.restoreAllMocks(), and update the
tests that assert immediately after await userEvent.click(...) (the tests that
use mockSetHideDrawer and the localStorage assertions) so each expect(...) is
placed inside a waitFor(...) callback after the click (e.g., await
userEvent.click(toggleBtn); await waitFor(() => {
expect(mockSetHideDrawer).toHaveBeenCalledWith(true); });), ensuring all
assertions that depend on async state updates use waitFor.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: d6bd3201-a05e-4ec3-a27a-2ece19da71de

📥 Commits

Reviewing files that changed from the base of the PR and between f0ad58b and 6e1714c.

📒 Files selected for processing (7)
  • src/components/AdminPortal/Advertisements/Advertisements.spec.tsx
  • src/screens/AdminPortal/SubTags/SubTags.spec.tsx
  • src/screens/AdminPortal/Users/Users.spec.tsx
  • src/screens/UserPortal/Pledges/Pledges.spec.tsx
  • src/shared-components/Navbar/Navbar.spec.tsx
  • src/shared-components/SearchFilterBar/SearchFilterBar.spec.tsx
  • src/shared-components/SidebarBase/SidebarBase.spec.tsx

Comment on lines +4 to +11
import {
act,
cleanup,
fireEvent,
render,
screen,
waitFor,
} from '@testing-library/react';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify restricted fireEvent usage in spec files and inspect Enter-triggered search sites
rg -n --type tsx '\bfireEvent\b|keyboard\(\s*[`'\'']\{Enter\}[`'\'']\s*\)'

Repository: PalisadoesFoundation/talawa-admin

Length of output: 104


🏁 Script executed:

fd SubTags.spec.tsx --type f

Repository: PalisadoesFoundation/talawa-admin

Length of output: 125


🏁 Script executed:

cat -n src/screens/AdminPortal/SubTags/SubTags.spec.tsx | head -50

Repository: PalisadoesFoundation/talawa-admin

Length of output: 1963


🏁 Script executed:

sed -n '240,260p' src/screens/AdminPortal/SubTags/SubTags.spec.tsx

Repository: PalisadoesFoundation/talawa-admin

Length of output: 826


🏁 Script executed:

sed -n '235,265p' src/screens/AdminPortal/SubTags/SubTags.spec.tsx

Repository: PalisadoesFoundation/talawa-admin

Length of output: 1184


🏁 Script executed:

rg -n 'fireEvent' src/screens/AdminPortal/SubTags/SubTags.spec.tsx

Repository: PalisadoesFoundation/talawa-admin

Length of output: 167


🏁 Script executed:

sed -n '1,30p' src/screens/AdminPortal/SubTags/SubTags.spec.tsx | grep -E 'import.*user|fireEvent'

Repository: PalisadoesFoundation/talawa-admin

Length of output: 142


🏁 Script executed:

rg -n 'afterEach|cleanup\(\)|vi.restoreAllMocks|vi.clearAllMocks' src/screens/AdminPortal/SubTags/SubTags.spec.tsx | head -20

Repository: PalisadoesFoundation/talawa-admin

Length of output: 299


🏁 Script executed:

sed -n '135,150p' src/screens/AdminPortal/SubTags/SubTags.spec.tsx

Repository: PalisadoesFoundation/talawa-admin

Length of output: 466


🏁 Script executed:

sed -n '235,275p' src/screens/AdminPortal/SubTags/SubTags.spec.tsx

Repository: PalisadoesFoundation/talawa-admin

Length of output: 1602


🏁 Script executed:

grep -n 'wait()' src/screens/AdminPortal/SubTags/SubTags.spec.tsx | head -5

Repository: PalisadoesFoundation/talawa-admin

Length of output: 186


🏁 Script executed:

sed -n '80,100p' src/screens/AdminPortal/SubTags/SubTags.spec.tsx

Repository: PalisadoesFoundation/talawa-admin

Length of output: 583


🏁 Script executed:

sed -n '139,145p' src/screens/AdminPortal/SubTags/SubTags.spec.tsx

Repository: PalisadoesFoundation/talawa-admin

Length of output: 261


🏁 Script executed:

grep -n "^const wait\|^function wait\|^export.*wait" src/screens/AdminPortal/SubTags/SubTags.spec.tsx

Repository: PalisadoesFoundation/talawa-admin

Length of output: 59


🏁 Script executed:

rg -n "import.*wait|const wait|function wait" src/screens/AdminPortal/SubTags/SubTags.spec.tsx

Repository: PalisadoesFoundation/talawa-admin

Length of output: 126


🏁 Script executed:

sed -n '61,65p' src/screens/AdminPortal/SubTags/SubTags.spec.tsx

Repository: PalisadoesFoundation/talawa-admin

Length of output: 220


🏁 Script executed:

sed -n '245,260p' src/screens/AdminPortal/SubTags/SubTags.spec.tsx

Repository: PalisadoesFoundation/talawa-admin

Length of output: 707


❌ Critical: Replace hardcoded wait() function and fireEvent.change() with deterministic async patterns.

Two issues compound test flakiness in CI sharding:

  1. Hardcoded delay (line 61): The wait(ms = 500) helper uses setTimeout, creating race conditions in variable-latency CI. The multiple await wait() calls throughout this file (e.g., lines 147, 155, 163) prevent deterministic test execution.

  2. Mixed userEvent + fireEvent (line 250): Using fireEvent.change() with await user.keyboard() is inconsistent and can fail if focus is lost between operations.

Proposed fixes

Fix 1 (line 61-66): Replace hardcoded wait helper:

-async function wait(ms = 500): Promise<void> {
-  await act(() => {
-    return new Promise((resolve) => {
-      setTimeout(resolve, ms);
-    });
-  });
-}
+// Removed: Use waitFor/findBy queries instead for deterministic waits

Then replace all await wait() calls with waitFor() or async queries (e.g., screen.findByPlaceholderText()).

Fix 2 (lines 249-251): Replace fireEvent with userEvent:

-    const input = screen.getByPlaceholderText(translations.searchByName);
-    fireEvent.change(input, { target: { value: '  searchSubTag  ' } });
+    const input = await screen.findByPlaceholderText(translations.searchByName);
+    await user.click(input);
+    await user.clear(input);
+    await user.paste('  searchSubTag  ');
     await user.keyboard('{Enter}');

Also remove fireEvent from imports (line 7).

Also applies to: All await wait() calls (lines 147, 155, 163, 181, 193, and others). Replace with conditional async queries per guidelines.

🧰 Tools
🪛 ESLint

[error] 7-7: 'fireEvent' import from '@testing-library/react' is restricted. Tests in this file use fireEvent for user interactions; use userEvent from @testing-library/user-event instead.

(no-restricted-imports)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/screens/AdminPortal/SubTags/SubTags.spec.tsx` around lines 4 - 11, The
test uses a fragile hardcoded helper wait() and mixes fireEvent.change() with
user.keyboard(), causing flaky timing; remove the wait helper (symbol: wait) and
replace all await wait() usages with deterministic async queries or waitFor()
(e.g., screen.findByPlaceholderText, screen.findByText) so assertions await the
actual DOM conditions, and replace fireEvent.change(...) usages with userEvent
APIs (e.g., await user.type(...) or await user.clear(...) + user.type(...)) to
keep interactions consistent with user.keyboard(); finally, remove fireEvent
from the imports list to avoid accidental usage and update tests referencing
fireEvent.change to use the userEvent equivalents (look for occurrences around
the user.keyboard() call and tests that previously awaited wait()).

Comment on lines +77 to +82
<div
data-testid={`${dataTestIdPrefix}-icon`}
data-icon-type={type}
>
{icon}
</div>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Structured review: one CI blocker and one test-intent gap in the updated sort-icon checks

Issue Goals

  • The refactor objective to validate sort icon behavior is mostly covered, but the “provided type” path is not actually exercised: Line 152 says type is provided, while Lines 155-161 omit type.

Tests (incl. Flakiness)

  • ✅ No shard-flakiness anti-patterns in changed segments (cleanup + restore present; no fixed waits/silent catches).

Components/Policy

  • CI-blocking lint issue at Lines 77-80: Prettier requires inline attributes for this JSX node.

GraphQL

  • No issues in this segment.

i18n & a11y

  • No issues in this segment.

Security

  • No issues in this segment.

Action Items

  1. Fix JSX formatting at Lines 77-80.
  2. Make the “type provided” test truthful by adding explicit type in Lines 155-161, or rename the test to reflect default behavior.
Suggested patch
-        <div
-          data-testid={`${dataTestIdPrefix}-icon`}
-          data-icon-type={type}
-        >
+        <div data-testid={`${dataTestIdPrefix}-icon`} data-icon-type={type}>
           {icon}
         </div>
     const sortingProps = [
       {
         title: 'Sort Custom',
         options: [{ label: 'A', value: 'a' }],
         selected: 'a',
         onChange: mockSort,
         testIdPrefix: 'sort-custom',
+        type: 'sort',
       },
     ];

Also applies to: 152-167, 169-184

🧰 Tools
🪛 ESLint

[error] 77-80: Replace ⏎··········data-testid={${dataTestIdPrefix}-icon}⏎··········data-icon-type={type}⏎········ with ·data-testid={${dataTestIdPrefix}-icon}·data-icon-type={type}

(prettier/prettier)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/shared-components/Navbar/Navbar.spec.tsx` around lines 77 - 82, Fix the
JSX formatting and the inaccurate test: collapse the JSX attributes for the icon
node so the element uses inline attributes on a single line (the div with
data-testid={`${dataTestIdPrefix}-icon`} and data-icon-type={type}) to satisfy
Prettier, and update the test that claims “type provided” (the spec block around
lines 152-161) to actually pass an explicit type prop into the rendered
component (or else rename the test to state it checks default behavior) so the
provided-type path is exercised; search for dataTestIdPrefix, data-testid
`${dataTestIdPrefix}-icon`, and the spec block referencing “type provided” to
locate and change the code.

Comment on lines +72 to +77
vi.mock('react-i18next', () => ({
useTranslation: () => ({
t: (key: string) => key,
i18n: { language: 'en' },
}),
}));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🚫 Blocking: this spec still has shard-flakiness and policy violations despite the refactor fixes

Issue Goals

  • The PR’s CI-stability intent is partially met, but there’s a remaining gap: async interaction assertions are still race-prone in this file (src/shared-components/SearchFilterBar/SearchFilterBar.spec.tsx:295-301, 740-751, 796-801).

Tests (incl. Flakiness)

  • INCOMPLETE CLEANUP at src/shared-components/SearchFilterBar/SearchFilterBar.spec.tsx:107-109afterEach is missing cleanup().
  • RACE CONDITION at src/shared-components/SearchFilterBar/SearchFilterBar.spec.tsx:301, 744, 751, 800 — assertions run after async user actions but outside waitFor.
  • RACE CONDITION at src/shared-components/SearchFilterBar/SearchFilterBar.spec.tsx:298-299, 742-743, 798-799 — option items are queried/clicked immediately after toggle click without waiting for menu open state.

Components/Policy

  • src/shared-components/SearchFilterBar/SearchFilterBar.spec.tsx:560-562 has a prettier violation already flagged by static analysis.

GraphQL

  • No GraphQL-specific issue in this file.

i18n & a11y

  • src/shared-components/SearchFilterBar/SearchFilterBar.spec.tsx:72-77 mocks react-i18next, but renders are not wrapped in I18nextProvider. This violates the repository testing policy and can hide translation integration regressions.

Security

  • No security findings in this file.

Action Items

  1. Add cleanup() to afterEach.
  2. Wrap post-interaction assertions in waitFor.
  3. Wait for dropdown/menu visibility before selecting item testids.
  4. Use an I18nextProvider render helper for this spec.
  5. Apply the formatter fix at Line 560-562.
Suggested patch pattern
-import { render, screen } from '@testing-library/react';
+import { cleanup, render, screen, waitFor } from '@testing-library/react';

 afterEach(() => {
+  cleanup();
   vi.restoreAllMocks();
 });

 // Example pattern for dropdown interaction
 const toggleButton = screen.getByTestId('sort-toggle');
 await user.click(toggleButton);
-const option = screen.getByTestId('sort-item-ASCENDING');
+await waitFor(() =>
+  expect(screen.getByTestId('sort-item-ASCENDING')).toBeInTheDocument(),
+);
+const option = screen.getByTestId('sort-item-ASCENDING');
 await user.click(option);
-expect(onOptionChange).toHaveBeenCalledWith('ASCENDING');
+await waitFor(() =>
+  expect(onOptionChange).toHaveBeenCalledWith('ASCENDING'),
+);

 // Prettier
-expect(
-  screen.getByTestId('filter-container'),
-).toBeInTheDocument();
+expect(screen.getByTestId('filter-container')).toBeInTheDocument();

As per coding guidelines: afterEach in spec files must include both cleanup() and vi.restoreAllMocks(), all assertions after async user operations must be inside waitFor, and component tests must be wrapped with I18nextProvider.

Also applies to: 107-109, 295-301, 560-562, 740-751, 796-801

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/shared-components/SearchFilterBar/SearchFilterBar.spec.tsx` around lines
72 - 77, The spec has several race and policy issues: update the afterEach block
to call cleanup() and vi.restoreAllMocks(); ensure every assertion that follows
an async user action (e.g., after userEvent.click in tests around the blocks
referencing the dropdown/menu interactions) is wrapped in waitFor; before
querying/clicking option item testids (tests that toggle the menu and then
select options) await the menu visibility (e.g., await findByRole or waitFor(()
=> expect(menu).toBeVisible())) so selection isn’t raced; replace raw renders
with the project helper that wraps components in I18nextProvider (use the test
render helper or renderWithI18next used elsewhere) instead of the bare
react-i18next mock; and fix the formatting violation noted near the prettier
warning by reformatting the affected code in the spec.

@palisadoes palisadoes added the ignore-sensitive-files-pr The contributor has a legitimate reason for editiing protected files label Apr 11, 2026
@palisadoes palisadoes mentioned this pull request Apr 11, 2026
6 tasks
@github-actions
Copy link
Copy Markdown

This pull request did not get any activity in the past 10 days and will be closed in 360 days if no update occurs. Please verify it has no conflicts with the develop branch and rebase if needed.

@github-actions github-actions Bot added the no-pr-activity No pull request activity label Apr 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ignore-sensitive-files-pr The contributor has a legitimate reason for editiing protected files no-pr-activity No pull request activity

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants