Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/components/mui/RefundForm/__tests__/refund-form.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ describe("RefundForm", () => {
).toBeInTheDocument();
});

it("shows the refund info note and keeps submit enabled on first render", () => {
render(<RefundForm onSubmit={jest.fn()} />);
expect(screen.getByText("refund_form.info")).toBeInTheDocument();
expect(
screen.getByRole("button", { name: /refund_form\.queue_refund/i })
).toBeEnabled();
});

it("calls onSubmit with reason and amount in cents", async () => {
const onSubmit = jest.fn();
render(<RefundForm onSubmit={onSubmit} />);
Expand Down
14 changes: 3 additions & 11 deletions src/components/mui/RefundForm/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@ import { Box, Button, Grid2 } from "@mui/material";
import MuiFormikTextField from "openstack-uicore-foundation/lib/components/mui/formik-inputs/textfield";
import MuiFormikPriceField from "openstack-uicore-foundation/lib/components/mui/formik-inputs/price-field";
import InfoNote from "openstack-uicore-foundation/lib/components/mui/info-note";
import CustomAlert from "openstack-uicore-foundation/lib/components/mui/custom-alert";

const RefundForm = ({ onSubmit, disabled = false }) => {
const RefundForm = ({ onSubmit }) => {
// Formik does not block concurrent submits, so repeated Enter presses would
// each queue a refund. The ref guards the gap before isSubmitting re-renders.
const submittingRef = useRef(false);
Expand Down Expand Up @@ -60,7 +59,7 @@ const RefundForm = ({ onSubmit, disabled = false }) => {
enableReinitialize: true
});

const isDisabled = disabled || formik.isSubmitting;
const isDisabled = formik.isSubmitting;

return (
<FormikProvider value={formik}>
Expand Down Expand Up @@ -105,14 +104,7 @@ const RefundForm = ({ onSubmit, disabled = false }) => {
</Grid2>
</Box>
<Box sx={{ mt: 2 }}>
{disabled ? (
<CustomAlert
message={T.translate("refund_form.only_online_payments")}
severity="warning"
/>
) : (
<InfoNote message={T.translate("refund_form.info")} />
)}
<InfoNote message={T.translate("refund_form.info")} />
</Box>
</FormikProvider>
);
Expand Down
3 changes: 1 addition & 2 deletions src/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -4370,8 +4370,7 @@
"reason": "Reason for Refund",
"amount": "Amount",
"queue_refund": "Queue refund",
"info": "If the original payment was made via Stripe, the refund will be automatically queued and processed.",
"only_online_payments": "Only online payments are eligible for refunds"
"info": "Stripe payments are queued and refunded through Stripe automatically. Offline payments are recorded as refunded immediately; return the funds to the sponsor outside the platform."
},
"client_card": {
"title": "Client & Address Details",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import React from "react";
import { act, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import "@testing-library/jest-dom";
import { renderWithRedux } from "../../../../../../utils/test-utils";
import SponsorOrderDetails from "../sponsor-order-details";
import { refundSponsorOrder } from "../../../../../../actions/sponsor-purchases-actions";

jest.mock("i18n-react/dist/i18n-react", () => ({
__esModule: true,
default: { translate: (key) => key }
}));

jest.mock("../../../../../../routes/restrict", () => ({
__esModule: true,
default: (Component) => Component
}));

jest.mock("../../../../../../actions/sponsor-purchases-actions", () => ({
__esModule: true,
getSponsorOrder: jest.fn(() => () => {}),
clearSponsorOrder: jest.fn(() => () => {}),
refundSponsorOrder: jest.fn(() => () => Promise.resolve()),
cancelSponsorForm: jest.fn(() => () => {}),
undoCancelSponsorForm: jest.fn(() => () => {}),
updateClientAddress: jest.fn(() => () => {}),
updateClientInfo: jest.fn(() => () => {})
}));

jest.mock("openstack-uicore-foundation/lib/components/mui/cards", () => ({
__esModule: true,
ListCard: () => null
}));

jest.mock(
"openstack-uicore-foundation/lib/components/mui/sponsor-order-grid",
() => ({ __esModule: true, default: () => null })
);

jest.mock("../../../../../../components/mui/ClientCard", () => ({
__esModule: true,
default: () => null
}));

const renderPage = (type) => {
const order = {
id: 135,
number: "ORD-135",
type,
payment_method: type,
status: "Paid",
created: 1700000000,
purchased_by_full_name: "Jane Doe",
purchased_by_email: "jane@example.com",
client: {},
address: {}
};

return renderWithRedux(
<SponsorOrderDetails match={{ params: { order_id: "135" } }} />,
{
initialState: {
sponsorPagePurchaseListState: { currentOrder: order },
currentSummitState: { currentSummit: { id: 73, name: "Summit" } },
currentSponsorState: {
entity: { id: 680, company: { name: "Acme" }, sponsorships: [] }
}
}
}
);
};

describe("SponsorOrderDetails refund form", () => {
beforeEach(() => {
refundSponsorOrder.mockClear();
});

it.each(["Offline", "Online"])(
"renders an enabled refund form for %s orders",
(type) => {
renderPage(type);

expect(
screen.getByRole("button", { name: /refund_form\.queue_refund/i })
).toBeEnabled();
expect(
screen.queryByText("refund_form.only_online_payments")
).not.toBeInTheDocument();
}
);

it("submits a refund for an offline order with the amount in cents", async () => {
renderPage("Offline");

await act(async () => {
await userEvent.type(
screen.getByLabelText(/refund_form\.reason/i),
"Duplicate invoice"
);
await userEvent.type(screen.getByLabelText(/refund_form\.amount/i), "10");
await userEvent.click(
screen.getByRole("button", { name: /refund_form\.queue_refund/i })
);
});

expect(refundSponsorOrder).toHaveBeenCalledWith(
135,
1000,
"Duplicate invoice"
);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,7 @@ import {
updateClientAddress,
updateClientInfo
} from "../../../../../actions/sponsor-purchases-actions";
import {
ACCESS_ROUTES,
DATE_FORMAT,
PURCHASE_TYPES
} from "../../../../../utils/constants";
import { ACCESS_ROUTES, DATE_FORMAT } from "../../../../../utils/constants";
import Restrict from "../../../../../routes/restrict";
import { formatDate } from "../../../../../utils/methods";
import RefundForm from "../../../../../components/mui/RefundForm";
Expand Down Expand Up @@ -189,10 +185,7 @@ const SponsorOrderDetails = ({
"edit_sponsor.purchase_tab.order_details.issue_refund"
)}
</Typography>
<RefundForm
onSubmit={handleOrderRefund}
disabled={currentOrder.type === PURCHASE_TYPES.OFFLINE}
/>
<RefundForm onSubmit={handleOrderRefund} />
</CardContent>
</Card>
</Grid2>
Expand Down
Loading