Skip to content

Conversation

@niko-exo
Copy link

@niko-exo niko-exo commented Dec 30, 2025

ref: https://app.clickup.com/t/86b7kbjcf

86b7kbjcf - Fix: item counter when deleting form item on second page

Changelog

  • Update reducer test
  • Dont update total count on delete item reducer
  • Test delete sponsor form item
  • Request sponsor form items to update total value correctly

Links

86b7kbjcf - Item counter does not refresh after deleting item until page refresh

Evidence

2025-12-30_13-34-24.mp4

Summary by CodeRabbit

  • Bug Fixes

    • Sponsor form item list now automatically refreshes after deletion, displaying the most current state without requiring a manual refresh.
  • Tests

    • Added comprehensive test coverage for the sponsor form item deletion workflow to verify proper functionality.

✏️ Tip: You can customize this high-level summary in your review settings.

snackbarErrorHandler
)(params)(dispatch)
.then(() => {
const { currentPage, perPage, order, orderDir, hideArchived } =
Copy link

@smarcet smarcet Jan 5, 2026

Choose a reason for hiding this comment

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

@niko-exo this is not necessary. please take the same approach as we did here
9319963
** note
this approach introduce a new bug that happens with current page is not longer valid ( user deletes the last item of current page )

Copy link

@smarcet smarcet left a comment

Choose a reason for hiding this comment

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

@niko-exo please review comments

@niko-exo niko-exo added the COMMENTS This PR has comments to solve label Jan 6, 2026
@niko-exo niko-exo force-pushed the fix/refresh-item-counter branch from 1a81b2a to 156ba5b Compare January 9, 2026 13:23
@coderabbitai
Copy link

coderabbitai bot commented Jan 9, 2026

📝 Walkthrough

Walkthrough

The pull request adds test coverage for sponsor form item deletion, updates the list refresh logic to refetch items after deletion, and modifies the reducer to stop tracking totalCount when items are deleted.

Changes

Cohort / File(s) Summary
Test Addition
src/actions/__tests__/sponsor-forms-actions.test.js
New test file covering DeleteSponsorFormItem flow, mocking deleteRequest, utilities, and base actions; verifies token retrieval, deleteRequest invocation, and snackbar handler execution.
Reducer Updates
src/reducers/sponsors/sponsor-form-items-list-reducer.js, src/reducers/sponsors/__tests__/sponsor-form-items-list-reducer.test.js
Removes totalCount recalculation and updates in SPONSOR_FORM_ITEM_DELETED handler; reducer now returns only updated items array without totalCount modification. Test expectations adjusted accordingly.
Page & Action Logic
src/pages/sponsors/sponsor-form-item-list-page/index.js, src/actions/sponsor-forms-actions.js
Page component now calls getSponsorFormItems to refresh list after deletion with current pagination and filter parameters. Minor whitespace adjustment in actions file.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 A list refreshes, deleted items flee,
No more counting totals in the spree,
Tests now guard the deletion way,
With mocked requests that save the day!
Hop, hop, delete—and all's pristine!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title references a specific issue (86b7kbjcf) and describes a concrete fix: refreshing the item counter when deleting a form item on the second page.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing touches
  • 📝 Generate docstrings

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

@niko-exo
Copy link
Author

niko-exo commented Jan 9, 2026

Branch rebased on master.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @src/actions/__tests__/sponsor-forms-actions.test.js:
- Around line 25-64: Test has a typo in the expectation message and is missing
stronger assertions: fix the typo "acces" -> "access" in the comment/assertion,
remove the unused sponsorFormItemsListState from the mockedGetState return, and
add assertions inside the "execute" test to verify deleteRequest was called with
the correct URL and handlers and that the SPONSOR_FORM_ITEM_DELETED action (or
the action creator used by deleteSponsorFormItem) was dispatched with the
expected itemId; use the existing spies/mocks (spyOnGetAccessTokenSafely,
spyOnSnackbarSuccessHandler, OpenStackUiCoreActions.deleteRequest) and the
deleteSponsorFormItem invocation to assert the exact parameters and dispatched
action.
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c119116 and 156ba5b.

📒 Files selected for processing (5)
  • src/actions/__tests__/sponsor-forms-actions.test.js
  • src/actions/sponsor-forms-actions.js
  • src/pages/sponsors/sponsor-form-item-list-page/index.js
  • src/reducers/sponsors/__tests__/sponsor-form-items-list-reducer.test.js
  • src/reducers/sponsors/sponsor-form-items-list-reducer.js
💤 Files with no reviewable changes (2)
  • src/actions/sponsor-forms-actions.js
  • src/reducers/sponsors/tests/sponsor-form-items-list-reducer.test.js
🧰 Additional context used
🧬 Code graph analysis (1)
src/pages/sponsors/sponsor-form-item-list-page/index.js (1)
src/actions/sponsor-forms-actions.js (4)
  • deleteSponsorFormItem (933-959)
  • deleteSponsorFormItem (933-959)
  • getSponsorFormItems (862-909)
  • getSponsorFormItems (862-909)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: build
  • GitHub Check: build
  • GitHub Check: build
  • GitHub Check: build
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (5)
src/actions/__tests__/sponsor-forms-actions.test.js (3)

1-5: LGTM!

The imports are well-organized and include all necessary dependencies for testing the DeleteSponsorFormItem action flow.


6-16: LGTM!

The mock correctly preserves the original module while stubbing deleteRequest with a triple-nested function that matches the thunk pattern used in the codebase: deleteRequest(...args)(params)(dispatch).


18-24: LGTM!

The test suite structure is clean, with proper cleanup using jest.restoreAllMocks() in afterEach to prevent test interference.

src/pages/sponsors/sponsor-form-item-list-page/index.js (1)

104-115: LGTM! This correctly fixes the item counter refresh issue.

The change properly addresses the root cause by refetching the list after deletion, ensuring totalCount and the items array are synchronized with the backend state. This approach is more reliable than attempting to calculate totalCount locally in the reducer.

The refresh preserves all current filters, sorting, and pagination parameters, maintaining the user's view state.

src/reducers/sponsors/sponsor-form-items-list-reducer.js (1)

131-136: LGTM! Simplifying the reducer is the right approach.

Removing the local totalCount recalculation eliminates the source of the bug. The subsequent refetch (added in the page component) ensures totalCount is updated accurately from the backend.

This change follows the single-source-of-truth principle: instead of attempting to maintain synchronization locally, rely on the server response via RECEIVE_SPONSOR_FORM_ITEMS to update both items and totalCount correctly.

Comment on lines +25 to +64
it("execute", async () => {
const mockedDispatch = jest.fn();
const mockedGetState = jest.fn(() => ({
currentSummitState: {
currentSummit: "SSS"
},
sponsorFormItemsListState: {
currentPage: 1,
perPage: 10,
order: "asc",
orderDir: 1,
hideArchived: false
}
}));

const params = {
formId: "AAA",
itemId: "III"
};

const spyOnGetAccessTokenSafely = jest
.spyOn(UtilsMethods, "getAccessTokenSafely")
.mockImplementation(() => "access _token");
const spyOnSnackbarSuccessHandler = jest.spyOn(
BaseActions,
"snackbarSuccessHandler"
);

await deleteSponsorFormItem(params.formId, params.itemId)(
mockedDispatch,
mockedGetState
);

// gets acces token safely
expect(spyOnGetAccessTokenSafely).toHaveBeenCalled();
// calls delete request
expect(OpenStackUiCoreActions.deleteRequest).toHaveBeenCalled();
// shows snackbar
expect(spyOnSnackbarSuccessHandler).toHaveBeenCalled();
});
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix typo and consider more comprehensive assertions.

Minor typo on line 58: "acces" should be "access".

The test validates the observable side effects but could be more thorough. Consider adding assertions to verify:

  • The correct parameters are passed to deleteRequest (URL, action creator, error handler)
  • The SPONSOR_FORM_ITEM_DELETED action is dispatched with the correct itemId

Additionally, sponsorFormItemsListState in the mocked state (lines 31-37) is not used by deleteSponsorFormItem and can be removed for clarity.

📝 Proposed fix for typo
-      // gets acces token safely
+      // gets access token safely
       expect(spyOnGetAccessTokenSafely).toHaveBeenCalled();
♻️ Optional: More comprehensive assertions
       const mockedGetState = jest.fn(() => ({
         currentSummitState: {
           currentSummit: "SSS"
-        },
-        sponsorFormItemsListState: {
-          currentPage: 1,
-          perPage: 10,
-          order: "asc",
-          orderDir: 1,
-          hideArchived: false
         }
       }));

And add more specific assertions:

       // gets access token safely
       expect(spyOnGetAccessTokenSafely).toHaveBeenCalled();
       // calls delete request
       expect(OpenStackUiCoreActions.deleteRequest).toHaveBeenCalled();
+      // verify deleteRequest was called with correct action creator
+      const deleteRequestCall = OpenStackUiCoreActions.deleteRequest.mock.calls[0];
+      expect(deleteRequestCall[1]).toBeDefined(); // action creator
+      expect(deleteRequestCall[2]).toContain('/show-forms/AAA/items/III'); // URL
       // shows snackbar
       expect(spyOnSnackbarSuccessHandler).toHaveBeenCalled();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it("execute", async () => {
const mockedDispatch = jest.fn();
const mockedGetState = jest.fn(() => ({
currentSummitState: {
currentSummit: "SSS"
},
sponsorFormItemsListState: {
currentPage: 1,
perPage: 10,
order: "asc",
orderDir: 1,
hideArchived: false
}
}));
const params = {
formId: "AAA",
itemId: "III"
};
const spyOnGetAccessTokenSafely = jest
.spyOn(UtilsMethods, "getAccessTokenSafely")
.mockImplementation(() => "access _token");
const spyOnSnackbarSuccessHandler = jest.spyOn(
BaseActions,
"snackbarSuccessHandler"
);
await deleteSponsorFormItem(params.formId, params.itemId)(
mockedDispatch,
mockedGetState
);
// gets acces token safely
expect(spyOnGetAccessTokenSafely).toHaveBeenCalled();
// calls delete request
expect(OpenStackUiCoreActions.deleteRequest).toHaveBeenCalled();
// shows snackbar
expect(spyOnSnackbarSuccessHandler).toHaveBeenCalled();
});
it("execute", async () => {
const mockedDispatch = jest.fn();
const mockedGetState = jest.fn(() => ({
currentSummitState: {
currentSummit: "SSS"
}
}));
const params = {
formId: "AAA",
itemId: "III"
};
const spyOnGetAccessTokenSafely = jest
.spyOn(UtilsMethods, "getAccessTokenSafely")
.mockImplementation(() => "access _token");
const spyOnSnackbarSuccessHandler = jest.spyOn(
BaseActions,
"snackbarSuccessHandler"
);
await deleteSponsorFormItem(params.formId, params.itemId)(
mockedDispatch,
mockedGetState
);
// gets access token safely
expect(spyOnGetAccessTokenSafely).toHaveBeenCalled();
// calls delete request
expect(OpenStackUiCoreActions.deleteRequest).toHaveBeenCalled();
// verify deleteRequest was called with correct action creator
const deleteRequestCall = OpenStackUiCoreActions.deleteRequest.mock.calls[0];
expect(deleteRequestCall[1]).toBeDefined(); // action creator
expect(deleteRequestCall[2]).toContain('/show-forms/AAA/items/III'); // URL
// shows snackbar
expect(spyOnSnackbarSuccessHandler).toHaveBeenCalled();
});
🤖 Prompt for AI Agents
In @src/actions/__tests__/sponsor-forms-actions.test.js around lines 25 - 64,
Test has a typo in the expectation message and is missing stronger assertions:
fix the typo "acces" -> "access" in the comment/assertion, remove the unused
sponsorFormItemsListState from the mockedGetState return, and add assertions
inside the "execute" test to verify deleteRequest was called with the correct
URL and handlers and that the SPONSOR_FORM_ITEM_DELETED action (or the action
creator used by deleteSponsorFormItem) was dispatched with the expected itemId;
use the existing spies/mocks (spyOnGetAccessTokenSafely,
spyOnSnackbarSuccessHandler, OpenStackUiCoreActions.deleteRequest) and the
deleteSponsorFormItem invocation to assert the exact parameters and dispatched
action.

@niko-exo
Copy link
Author

niko-exo commented Jan 9, 2026

Ready for review

@niko-exo niko-exo removed the COMMENTS This PR has comments to solve label Jan 9, 2026
@niko-exo niko-exo requested a review from smarcet January 9, 2026 13:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants