Skip to content

Commit

Permalink
fix(frontend): intempestive re-render of form (#1019)
Browse files Browse the repository at this point in the history
* fix(frontend): intempestive re-render of form

* fix(frontend): wrong proptypes

* fix(frontend): bad practice in reducer
  • Loading branch information
UnbearableBear authored Jul 10, 2019
1 parent 7a559a9 commit 35e4da5
Show file tree
Hide file tree
Showing 6 changed files with 696 additions and 189 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from "react";
import React, { useState, useReducer } from "react";
import PropTypes from "prop-types";
import styled from "styled-components";
import { Form } from "react-final-form";
Expand All @@ -9,14 +9,14 @@ import { StepItems } from "./StepItems";
import { PrevNextBar } from "./PrevNextBar";

function Wizard({
initialValues = {},
initialSteps,
initialStepIndex = 0,
steps,
onSubmit,
onUpdate,
rules = null
initialValues = {},
Rules = null,
stepReducer
}) {
const [stepIndex, setStepIndex] = useState(initialStepIndex);
const [steps, dispatch] = useReducer(stepReducer, initialSteps);

const prevStep = () => {
setStepIndex(Math.max(0, stepIndex - 1));
Expand All @@ -36,12 +36,13 @@ function Wizard({
const handlePageSubmit = (values, form) => {
// This means the user clicked on a "restart a new simulation" button
if (stepIndex === steps.length - 1) {
onSubmit(values);
form.reset();
dispatch({
type: "reset"
});
setStepIndex(0);
} else {
nextStep();
onUpdate && onUpdate(values);
}
};
const stepItems = steps.map(({ name, label }) => ({
Expand Down Expand Up @@ -71,7 +72,9 @@ function Wizard({
return (
<>
<form onSubmit={handleSubmit}>
{rules}
{Rules && (
<Rules values={form.getState().values} dispatch={dispatch} />
)}
<StepItems activeIndex={stepIndex} items={stepItems} />
<StepWrapper narrow noPadding>
<Step form={form} />
Expand All @@ -92,10 +95,17 @@ function Wizard({
}

Wizard.propTypes = {
steps: PropTypes.array.isRequired,
initialValues: PropTypes.object,
stepReducer: PropTypes.func.isRequired,
initialSteps: PropTypes.arrayOf(
PropTypes.shape({
component: PropTypes.func.isRequired,
name: PropTypes.string.isRequired,
label: PropTypes.string.isRequired
})
).isRequired,
initialStepIndex: PropTypes.number,
onSubmit: PropTypes.func.isRequired
initialValues: PropTypes.object,
Rules: PropTypes.func
};

export { Wizard };
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from "react";
import { render } from "react-testing-library";
import { Wizard } from "../Wizard";
import { stepReducer } from "../stepReducer";
import { Field } from "react-final-form";

const FirstStep = () => <p>Premiere Etape</p>;
Expand All @@ -11,13 +12,6 @@ const SecondStep = () => (
Deuxieme Etape <button>Submit</button>
</p>
);
const FormStep = () => <Field name="firstName" component="input" />;

const FinalFormStep = {
label: "final form",
name: "final-form",
component: FormStep
};
const steps = [
{
name: "firstStep",
Expand All @@ -30,68 +24,76 @@ const steps = [
component: SecondStep
}
];

const AdditionalStep = () => <Field name="firstName" component="input" />;
const additionalStep = {
label: "Name",
name: "additional step",
component: AdditionalStep
};

describe("<Wizard />", () => {
it("should render a step", () => {
const onSubmit = jest.fn();
const { container } = render(<Wizard steps={steps} onSubmit={onSubmit} />);
expect(container).toMatchSnapshot();
});
it("should call onSubmit once finish", () => {
const onSubmit = jest.fn();
const { getByText } = render(
<Wizard steps={steps} onSubmit={onSubmit} initialStepIndex={1} />
const { container } = render(
<Wizard stepReducer={stepReducer} initialSteps={steps} />
);
const button = getByText(/submit/i);
button.click();
expect(onSubmit).toHaveBeenCalled();
expect(container).toMatchSnapshot();
});
it("should call navigate to the second step when click on Suivant", () => {
const onSubmit = jest.fn();
const onUpdate = jest.fn();
it("should navigate to the second step when click on Suivant", () => {
const { container, getByText } = render(
<Wizard steps={steps} onSubmit={onSubmit} onUpdate={onUpdate} />
<Wizard stepReducer={stepReducer} initialSteps={steps} />
);
const button = getByText(/suivant/i);
button.click();
expect(onUpdate).toHaveBeenCalled();
expect(container).toMatchSnapshot();
});
it("should call Step.validate when click on Suivant", () => {
const onSubmit = jest.fn();
const { getByText } = render(<Wizard steps={steps} onSubmit={onSubmit} />);
const { getByText } = render(
<Wizard stepReducer={stepReducer} initialSteps={steps} />
);
const button = getByText(/suivant/i);
button.click();
expect(FirstStep.validate).toHaveBeenCalled();
});
it("should handle initialStepIndex", () => {
const { container } = render(
<Wizard
stepReducer={stepReducer}
initialSteps={steps}
initialStepIndex={1}
/>
);
expect(container).toMatchSnapshot();
});
it("should call navigate the previous step when click on précédent", () => {
const onSubmit = jest.fn();
const { container, getByText } = render(
<Wizard steps={steps} onSubmit={onSubmit} initialStepIndex={1} />
<Wizard
stepReducer={stepReducer}
initialSteps={steps}
initialStepIndex={1}
/>
);
const button = getByText(/précédent/i);
button.click();
expect(container).toMatchSnapshot();
});
it("should handle initialValues", () => {
const onSubmit = jest.fn();
const { container } = render(
<Wizard
steps={[FinalFormStep]}
onSubmit={onSubmit}
stepReducer={stepReducer}
initialSteps={[...steps, additionalStep]}
initialValues={{ firstName: "lionel" }}
/>
);
expect(container).toMatchSnapshot();
});
it("should inject rules component", () => {
const onSubmit = jest.fn();
const Rule = () => <p>Rule</p>;
const { container } = render(
<Wizard
steps={[FinalFormStep]}
onSubmit={onSubmit}
initialValues={{ firstName: "lionel" }}
rules={[<Rule key="key" />]}
stepReducer={stepReducer}
initialSteps={steps}
Rules={() => <Rule key="key" />}
/>
);
expect(container).toMatchSnapshot();
Expand Down
Loading

0 comments on commit 35e4da5

Please sign in to comment.