diff --git a/src/components/ErrorMessages.tsx b/src/components/ErrorMessages.tsx new file mode 100644 index 00000000..04f6e252 --- /dev/null +++ b/src/components/ErrorMessages.tsx @@ -0,0 +1,9 @@ +interface ErrorMessagesProps { + messages: string[]; +} + +const ErrorMessages: React.FC = ({ messages }) => { + return
{messages.join(", ")}
; +}; + +export default ErrorMessages; diff --git a/src/components/NumberOfBeings.test.tsx b/src/components/NumberOfBeings.test.tsx new file mode 100644 index 00000000..8c0cf898 --- /dev/null +++ b/src/components/NumberOfBeings.test.tsx @@ -0,0 +1,58 @@ +import { render, screen, fireEvent } from "@testing-library/react"; +import NumberOfBeings from "./NumberOfBeings"; + +test("renders form element and displays numberOfBeing props", () => { + const mockOnChange = jest.fn(); + const mockValidateNumberOfBeings = jest.fn(); + mockValidateNumberOfBeings.mockReturnValue([]); + + render( + + ); + + const labelText = screen.getByLabelText(/Number Of Beings/i); + expect(labelText).toBeInTheDocument(); + const inputText = screen.getByDisplayValue("2"); + expect(inputText).toBeInTheDocument(); + const errorMessage = screen.queryByText("Error message on beings number"); + expect(errorMessage).toBe(null); +}); + +test("calls the onChange function in input with correct value", () => { + const mockOnChange = jest.fn(); + const mockValidateNumberOfBeings = jest.fn(); + mockValidateNumberOfBeings.mockReturnValue([]); + render( + + ); + + const input = screen.getByRole("textbox"); + fireEvent.change(input, { target: { value: "10" } }); + expect(mockOnChange).toHaveBeenCalledWith("10"); +}); + +test("error messages are displayed when invalid number of beings is used", () => { + const mockOnChange = jest.fn(); + const mockValidateNumberOfBeings = jest.fn(); + mockValidateNumberOfBeings.mockReturnValue(["Beings should be more than 3"]); + + render( + + ); + + const errorMessage = screen.getByText("Beings should be more than 3"); + + expect(errorMessage).toBeInTheDocument(); +}); diff --git a/src/components/NumberOfBeings.tsx b/src/components/NumberOfBeings.tsx new file mode 100644 index 00000000..f6edd7b5 --- /dev/null +++ b/src/components/NumberOfBeings.tsx @@ -0,0 +1,29 @@ +import ErrorMessages from "./ErrorMessages"; + +interface NumberOfBeingsProps { + numberOfBeings: string; + onChangeBeings: (value: string) => void; + validateField: (name: string) => string[]; +} + +const NumberOfBeings: React.FC = ({ + numberOfBeings, + onChangeBeings, + validateField, +}) => ( + <> +
+ + onChangeBeings(e.target.value)} + /> +
+ + +); + +export default NumberOfBeings; diff --git a/src/components/PlanetName.test.tsx b/src/components/PlanetName.test.tsx new file mode 100644 index 00000000..64c35b89 --- /dev/null +++ b/src/components/PlanetName.test.tsx @@ -0,0 +1,59 @@ +import { render, screen, fireEvent } from "@testing-library/react"; +import PlanetName from "./PlanetName"; + +test("renders form element and displays planetName props", () => { + const mockOnChange = jest.fn(); + const mockValidatePlanetName = jest.fn(); + mockValidatePlanetName.mockReturnValue([]); + + render( + + ); + + const labelText = screen.getByLabelText(/Planet Name/i); + expect(labelText).toBeInTheDocument(); + const inputText = screen.getByDisplayValue("mars"); + expect(inputText).toBeInTheDocument(); + + const errorMessage = screen.queryByText("Planet name: error!panic!"); + expect(errorMessage).toBe(null); +}); + +test("calls the onChange function in input with correct value", () => { + const mockOnChange = jest.fn(); + const mockValidatePlanetName = jest.fn(); + mockValidatePlanetName.mockReturnValue([]); + + render( + + ); + + const input = screen.getByRole("textbox"); + fireEvent.change(input, { target: { value: "Earth" } }); + expect(mockOnChange).toHaveBeenCalledWith("Earth"); +}); + +test("error messages are displayed when invalid planet name is used", () => { + const mockOnChange = jest.fn(); + const mockValidatePlanetName = jest.fn(); + mockValidatePlanetName.mockReturnValue(["panic!"]); + + render( + + ); + + const errorMessage = screen.getByText("panic!"); + expect(errorMessage).toBeInTheDocument(); +}); diff --git a/src/components/PlanetName.tsx b/src/components/PlanetName.tsx new file mode 100644 index 00000000..52f29d80 --- /dev/null +++ b/src/components/PlanetName.tsx @@ -0,0 +1,29 @@ +import ErrorMessages from "./ErrorMessages"; + +interface PlanetNameProps { + planetName: string; + onChangePlanetName: (value: string) => void; + validateField: (name: string) => string[]; +} + +const PlanetName: React.FC = ({ + planetName, + onChangePlanetName, + validateField, +}) => ( + <> +
+ + onChangePlanetName(e.target.value)} + /> +
+ + +); + +export default PlanetName; diff --git a/src/components/SparingReason.test.tsx b/src/components/SparingReason.test.tsx new file mode 100644 index 00000000..e80b3f2e --- /dev/null +++ b/src/components/SparingReason.test.tsx @@ -0,0 +1,63 @@ +import { render, screen, fireEvent } from "@testing-library/react"; +import SparingReason from "./SparingReason"; +test("renders form element and displays sparingReason props", () => { + const mockOnChange = jest.fn(); + const mockValidateSparingReason = jest.fn(); + mockValidateSparingReason.mockReturnValue([]); + + render( + + ); + + const labelText = screen.getByLabelText("Reason for Sparing"); + expect(labelText).toBeInTheDocument(); + const inputText = screen.getByDisplayValue("Life is good!"); + expect(inputText).toBeInTheDocument(); + const errorMessage = screen.queryByText( + "Reason for sparing: Must be between 17 and 153 characters" + ); + expect(errorMessage).toBe(null); +}); + +test("calls the onChange function in input with correct value", () => { + const mockOnChange = jest.fn(); + const mockValidateSparingReason = jest.fn(); + mockValidateSparingReason.mockReturnValue([]); + + render( + + ); + const input = screen.getByRole("textbox"); + fireEvent.change(input, { target: { value: "Yes it is" } }); + expect(mockOnChange).toHaveBeenCalledWith("Yes it is"); +}); + +test("error messages are displayed when invalid sparing reason is used", () => { + const mockOnChange = jest.fn(); + const mockValidateSparingReason = jest.fn(); + mockValidateSparingReason.mockReturnValue([ + "Reason for sparing: Must be between 17 and 153 characters", + ]); + + render( + + ); + + const errorMessage = screen.getByText( + "Reason for sparing: Must be between 17 and 153 characters" + ); + + expect(errorMessage).toBeInTheDocument(); +}); diff --git a/src/components/SparingReason.tsx b/src/components/SparingReason.tsx new file mode 100644 index 00000000..44a64100 --- /dev/null +++ b/src/components/SparingReason.tsx @@ -0,0 +1,28 @@ +import ErrorMessages from "./ErrorMessages"; + +interface SparingReasonProps { + sparingReason: string; + onChangeSparingReason: (value: string) => void; + validateField: (name: string) => string[]; +} + +const SparingReason: React.FC = ({ + sparingReason, + onChangeSparingReason, + validateField, +}) => ( + <> +
+ +