From 168246c56ce702afb548ea8bf1832b72e2deb147 Mon Sep 17 00:00:00 2001 From: Nicolas Olmos Date: Fri, 16 Jan 2026 15:23:43 -0300 Subject: [PATCH] fix: pagination on sponsor forms when rows per page change --- .../__tests__/sponsor-forms-actions.test.js | 160 ++++++++++++------ src/actions/sponsor-forms-actions.js | 8 +- 2 files changed, 115 insertions(+), 53 deletions(-) diff --git a/src/actions/__tests__/sponsor-forms-actions.test.js b/src/actions/__tests__/sponsor-forms-actions.test.js index 646f2483e..357b85506 100644 --- a/src/actions/__tests__/sponsor-forms-actions.test.js +++ b/src/actions/__tests__/sponsor-forms-actions.test.js @@ -1,66 +1,124 @@ -import * as OpenStackUiCoreActions from "openstack-uicore-foundation/lib/utils/actions"; -import { deleteSponsorFormItem } from "../sponsor-forms-actions"; -import * as UtilsMethods from "../../utils/methods"; -import * as BaseActions from "../base-actions"; +/** + * @jest-environment jsdom + */ +import { expect, jest, describe, it } from "@jest/globals"; +import configureStore from "redux-mock-store"; +import thunk from "redux-thunk"; +import flushPromises from "flush-promises"; +import { getRequest } from "openstack-uicore-foundation/lib/utils/actions"; +import { getSponsorForms } from "../sponsor-forms-actions"; +import * as methods from "../../utils/methods"; -jest.mock("openstack-uicore-foundation/lib/utils/actions", () => { - const originalModule = jest.requireActual( - "openstack-uicore-foundation/lib/utils/actions" - ); - - return { +jest.mock("openstack-uicore-foundation/lib/utils/actions", () => ({ __esModule: true, - ...originalModule, - deleteRequest: jest.fn(() => () => () => Promise.resolve()) - }; -}); + ...jest.requireActual("openstack-uicore-foundation/lib/utils/actions"), + postRequest: jest.fn(), + getRequest: jest.fn() + })); + +describe("Sponsor Forms Actions", () => { + describe("GetSponsorForms", () => { + const middlewares = [thunk]; + const mockStore = configureStore(middlewares); + + beforeEach(() => { + jest.spyOn(methods, "getAccessTokenSafely").mockReturnValue("TOKEN"); + + getRequest.mockImplementation( + ( + requestActionCreator, + receiveActionCreator, + endpoint, // eslint-disable-line no-unused-vars + payload, // eslint-disable-line no-unused-vars + errorHandler = null, // eslint-disable-line no-unused-vars + requestActionPayload = {} + ) => + ( + params = {} // eslint-disable-line no-unused-vars + ) => + (dispatch) => { + if ( + requestActionCreator && + typeof requestActionCreator === "function" + ) + dispatch(requestActionCreator(requestActionPayload)); + + return new Promise((resolve) => { + if (typeof receiveActionCreator === "function") { + dispatch(receiveActionCreator({ response: {} })); + resolve({ response: {} }); + } + dispatch(receiveActionCreator); + resolve({ response: {} }); + }); + } + ); + }); -describe("SponsorFormActions", () => { - describe("DeleteSponsorFormItem", () => { afterEach(() => { // restore the spy created with spyOn jest.restoreAllMocks(); }); + describe("On perPage change", () => { + it("should request first page if perPage is greater than the total items count", async () => { + const store = mockStore({ + currentSummitState: { + currentSummit: {} + }, + sponsorFormsListState: { + totalCount: 13 + } + }); - 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 - } - })); + store.dispatch(getSponsorForms("", 2, 50, "id", 1, false, [])); + await flushPromises(); - const params = { - formId: "AAA", - itemId: "III" - }; + expect(getRequest).toHaveBeenCalled(); + expect(getRequest).toHaveBeenCalledWith( + expect.anything(), + expect.anything(), + expect.anything(), + expect.anything(), + { + hideArchived: false, + order: "id", + orderDir: 1, + page: 1, + perPage: 50, + term: "" + } + ); + }); - const spyOnGetAccessTokenSafely = jest - .spyOn(UtilsMethods, "getAccessTokenSafely") - .mockImplementation(() => "access _token"); - const spyOnSnackbarSuccessHandler = jest.spyOn( - BaseActions, - "snackbarSuccessHandler" - ); + it("should request user selected page if perPage is lower than the total items count", async () => { + const store = mockStore({ + currentSummitState: { + currentSummit: {} + }, + sponsorFormsListState: { + totalCount: 50 + } + }); - await deleteSponsorFormItem(params.formId, params.itemId)( - mockedDispatch, - mockedGetState - ); + store.dispatch(getSponsorForms("", 2, 20, "id", 1, false, [])); + await flushPromises(); - // gets acces token safely - expect(spyOnGetAccessTokenSafely).toHaveBeenCalled(); - // calls delete request - expect(OpenStackUiCoreActions.deleteRequest).toHaveBeenCalled(); - // shows snackbar - expect(spyOnSnackbarSuccessHandler).toHaveBeenCalled(); + expect(getRequest).toHaveBeenCalled(); + expect(getRequest).toHaveBeenCalledWith( + expect.anything(), + expect.anything(), + expect.anything(), + expect.anything(), + { + hideArchived: false, + order: "id", + orderDir: 1, + page: 2, + perPage: 20, + term: "" + } + ); + }); }); }); }); diff --git a/src/actions/sponsor-forms-actions.js b/src/actions/sponsor-forms-actions.js index 085b09bfd..5437f0102 100644 --- a/src/actions/sponsor-forms-actions.js +++ b/src/actions/sponsor-forms-actions.js @@ -106,7 +106,7 @@ export const SPONSOR_FORM_ITEM_UNARCHIVED = "SPONSOR_FORM_ITEM_UNARCHIVED"; export const getSponsorForms = ( term = "", - page = DEFAULT_CURRENT_PAGE, + currentPage = DEFAULT_CURRENT_PAGE, perPage = DEFAULT_PER_PAGE, order = "id", orderDir = DEFAULT_ORDER_DIR, @@ -114,8 +114,9 @@ export const getSponsorForms = sponsorshipTypesId = [] ) => async (dispatch, getState) => { - const { currentSummitState } = getState(); + const { currentSummitState, sponsorFormsListState } = getState(); const { currentSummit } = currentSummitState; + const { totalCount } = sponsorFormsListState; const accessToken = await getAccessTokenSafely(); const filter = []; @@ -126,6 +127,9 @@ export const getSponsorForms = filter.push(`name=@${escapedTerm},code=@${escapedTerm}`); } + // Resets page to avoid backend error. + const page = perPage > totalCount ? 1 : currentPage; + const params = { page, fields: "id,code,name,level,expire_date,is_archived",