diff --git a/src/app/base/components/ActionForm/ActionForm.test.tsx b/src/app/base/components/ActionForm/ActionForm.test.tsx index 6b8656f228..c817442b0b 100644 --- a/src/app/base/components/ActionForm/ActionForm.test.tsx +++ b/src/app/base/components/ActionForm/ActionForm.test.tsx @@ -1,41 +1,21 @@ -import { Provider } from "react-redux"; -import { MemoryRouter } from "react-router-dom"; -import { CompatRouter } from "react-router-dom-v5-compat"; -import configureStore from "redux-mock-store"; - +import type { ActionFormProps } from "./ActionForm"; import ActionForm, { Labels } from "./ActionForm"; import { TestIds } from "app/base/components/FormikFormButtons"; -import type { RootState } from "app/store/root/types"; -import { rootState as rootStateFactory } from "testing/factories"; -import { userEvent, render, screen } from "testing/utils"; - -let state: RootState; -const mockStore = configureStore(); +import { userEvent, screen, renderWithBrowserRouter } from "testing/utils"; describe("ActionForm", () => { - beforeEach(() => { - state = rootStateFactory(); - }); - it("shows a spinner if form has not fully loaded", () => { - const store = mockStore(state); - render( - - - - - - - + renderWithBrowserRouter( + ); expect( @@ -44,22 +24,15 @@ describe("ActionForm", () => { }); it("can show the default submit label", () => { - const store = mockStore(state); - render( - - - - - - - + renderWithBrowserRouter( + ); expect( @@ -68,23 +41,16 @@ describe("ActionForm", () => { }); it("can override the submit label", () => { - const store = mockStore(state); - render( - - - - - - - + renderWithBrowserRouter( + ); expect( @@ -93,22 +59,15 @@ describe("ActionForm", () => { }); it("can show the correct saving state", async () => { - const store = mockStore(state); - render( - - - - - - - + renderWithBrowserRouter( + ); await userEvent.click(screen.getByRole("button")); @@ -120,45 +79,31 @@ describe("ActionForm", () => { }); it("disables the submit button when selectedCount equals 0", async () => { - const store = mockStore(state); - render( - - - - - - - + renderWithBrowserRouter( + ); expect(screen.getByRole("button")).toBeDisabled(); }); it("shows correct saving label if selectedCount changes after submit", async () => { - const store = mockStore(state); - const Proxy = ({ selectedCount }: { selectedCount: number }) => ( - - - - - - - + const Proxy = ({ selectedCount }: Partial>) => ( + ); - const { rerender } = render(); + const { rerender } = renderWithBrowserRouter(); // Submit the form to start processing. await userEvent.click(screen.getByRole("button")); @@ -175,27 +120,65 @@ describe("ActionForm", () => { }); it("can override showing the processing count", async () => { - const store = mockStore(state); - render( - - - - - - - + renderWithBrowserRouter( + ); await userEvent.click(screen.getByRole("button")); expect(screen.queryByTestId(TestIds.SavingLabel)).not.toBeInTheDocument(); }); + + it("displays a correct action status", () => { + const Proxy = ({ actionStatus, errors }: Partial>) => ( + + ); + + const { rerender } = renderWithBrowserRouter( + + ); + expect(screen.getByTestId(TestIds.SavingLabel)).toBeInTheDocument(); + + rerender(); + expect(screen.queryByTestId(TestIds.SavingLabel)).not.toBeInTheDocument(); + + const errors = { field: "Error message" }; + rerender(); + expect(screen.getByText("Error message")).toBeInTheDocument(); + }); + + it("sets saved status when processingCount drops to 0", () => { + const onSubmit = jest.fn(); + const Proxy = ({ processingCount }: Partial>) => ( + + ); + + const { rerender } = renderWithBrowserRouter(); + expect(screen.getByTestId(TestIds.SavingLabel)).toBeInTheDocument(); + + rerender(); + expect(screen.queryByTestId(TestIds.SavingLabel)).not.toBeInTheDocument(); + }); }); diff --git a/src/app/base/components/ActionForm/ActionForm.tsx b/src/app/base/components/ActionForm/ActionForm.tsx index 7705e98013..5cada0709b 100644 --- a/src/app/base/components/ActionForm/ActionForm.tsx +++ b/src/app/base/components/ActionForm/ActionForm.tsx @@ -31,7 +31,7 @@ const getLabel = ( return getNodeActionLabel(modelString, actionName, processing); }; -export type Props = Omit< +export type ActionFormProps = Omit< FormikFormProps, "buttonsAlign" | "saved" | "saving" | "savingLabel" | "submitLabel" > & { @@ -65,7 +65,7 @@ const ActionForm = ({ submitLabel, actionStatus, ...formikFormProps -}: Props): JSX.Element | null => { +}: ActionFormProps): JSX.Element | null => { const [selectedOnSubmit, setSelectedOnSubmit] = useState(selectedCount); const processingComplete = useProcessing({ hasErrors: !!errors, @@ -80,18 +80,13 @@ const ActionForm = ({ ); } // TODO: remove processingComplete once actionStatus has been implemented across all forms - // github.com/canonical/app-tribe/issues/1289 - const statusProps = actionStatus - ? { - saving: actionStatus === "loading", - saved: actionStatus === "success", - errors: errors || actionErrors, - } - : { - saved: processingComplete, - saving: !!processingCount && processingCount > 0, - errors: errors || actionErrors, - }; + // https://warthogs.atlassian.net/browse/MAASENG-2312 + const statusProps = { + saving: + actionStatus === "loading" || (!!processingCount && processingCount > 0), + saved: actionStatus === "success" || processingComplete, + errors: errors || actionErrors, + }; return ( diff --git a/src/app/base/components/ActionForm/index.ts b/src/app/base/components/ActionForm/index.ts index 11a00502c4..0c2f321b89 100644 --- a/src/app/base/components/ActionForm/index.ts +++ b/src/app/base/components/ActionForm/index.ts @@ -1,2 +1,2 @@ export { default } from "./ActionForm"; -export type { Props } from "./ActionForm"; +export type { ActionFormProps } from "./ActionForm";