Skip to content

Commit

Permalink
useSelector implementation (#25)
Browse files Browse the repository at this point in the history
Co-authored-by: Antonio <a.pangallo85@gmail.com>
  • Loading branch information
iusehooks and Antonio authored Jan 7, 2021
1 parent e281bb8 commit 8970a22
Show file tree
Hide file tree
Showing 34 changed files with 820 additions and 147 deletions.
2 changes: 1 addition & 1 deletion .babelrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ if (process.env.NODE_ENV === "test") {
}

if (process.env.NODE_ENV === "development") {
presets = ["@babel/preset-react"];
presets = ["@babel/preset-env", "@babel/preset-react"];
}

module.exports = {
Expand Down
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
}
},
"rules": {
"no-unused-vars": ["error", { "varsIgnorePattern": "omit" }],
"prettier/prettier": ["error", {
"endOfLine":"auto",
"trailingComma": "none",
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,13 @@ export default function App() {
}
```

## Author

- Antonio Pangallo [@antonio_pangall](https://twitter.com/antonio_pangall)

## Code Sandboxes

- Twitter What's Happening Form Bar: [Sandbox](https://codesandbox.io/s/twitter-bar-form-czx3o)
- Shopping Cart: [Sandbox](https://codesandbox.io/s/shopping-cart-97y5k)
- Examples: Slider, Select, Collections etc..: [Sandbox](https://codesandbox.io/s/formexample2-mmcjs)
- Various Implementation: [Sandbox](https://codesandbox.io/s/035l4l75ln)
Expand Down
2 changes: 1 addition & 1 deletion __tests__/Collection.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ describe("Component => Collection", () => {
it("should reduce a Collection of type object value with the given reducer function", () => {
const initalValue = { name: "test" };
const props = { onInit };
const reducer = jest.fn((state, prevState) => {
const reducer = jest.fn(state => {
const newState = { ...state };
if (newState.name !== "mickey") newState.name = "foo";
return newState;
Expand Down
4 changes: 2 additions & 2 deletions __tests__/Form.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ describe("Component => Form", () => {
it("should reduce the Form state with the given reducer function", () => {
const initialState = { name: "test" };

const reducer = jest.fn((state, prevState) => {
const reducer = jest.fn(state => {
const newState = { ...state };
if (newState.name !== "mickey") newState.name = "foo";
return newState;
Expand Down Expand Up @@ -709,7 +709,7 @@ describe("Component => Form", () => {
});

it("should submitted, submitAttempts be equal for async func which does not explicitly resolve or reject", async () => {
async function test(mIndex) {
async function test() {
return 1;
}
async function onSubmit() {
Expand Down
64 changes: 61 additions & 3 deletions __tests__/Input.spec.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import React from "react";
import { act } from "react-dom/test-utils";
import { render, fireEvent, waitFor, cleanup } from "@testing-library/react";
import {
render,
fireEvent,
waitFor,
cleanup,
act
} from "@testing-library/react";
import userEvent from "@testing-library/user-event";

import Form, { Input } from "./../src";
import { Form, Input } from "./../src";

import InputAsync from "./helpers/components/InputAsync";
import InputSyncValidation from "./helpers/components/InputSyncValidation";
Expand Down Expand Up @@ -126,6 +132,58 @@ describe("Component => Input", () => {
expect(onSubmit).toHaveBeenCalledWith({ text: "text" }, true);
});

it("should render Input of type file single/multiple and upload files", () => {
const singeFile = "singeFile";
const multipleFile = "multipleFile";
const props = { onChange };
const fileValue = new File(["(⌐□_□)"], "file.xml", {
type: "application/xml"
});
const files = [
new File(["hello"], "hello.png", { type: "image/png" }),
new File(["there"], "there.png", { type: "image/png" })
];

const children = [
<Input key="1" data-testid={singeFile} type="file" name={singeFile} />,
<Input
key="2"
multiple
data-testid={multipleFile}
type="file"
name={multipleFile}
/>
];
const { getByTestId } = mountForm({ children, props });
const fileInput = getByTestId(singeFile);
const fileInputMultiple = getByTestId(multipleFile);

act(() => {
userEvent.upload(fileInput, fileValue);
});
expect(onChange).toHaveBeenCalledWith({ [singeFile]: fileValue }, true);

act(() => {
userEvent.upload(fileInputMultiple, files);
});

expect(onChange).toHaveBeenCalledWith(
{ [singeFile]: fileValue, [multipleFile]: files },
true
);

expect(fileInput.type).toBe("file");
expect(fileInput.files[0]).toStrictEqual(fileValue);
expect(fileInput.files.item(0)).toStrictEqual(fileValue);
expect(fileInput.files).toHaveLength(1);

expect(fileInputMultiple.type).toBe("file");
expect(fileInputMultiple.multiple).toBe(true);
expect(fileInputMultiple.files).toHaveLength(2);
expect(fileInputMultiple.files[0]).toStrictEqual(files[0]);
expect(fileInputMultiple.files[1]).toStrictEqual(files[1]);
});

it("should trigger onChange event when the Input value changes", () => {
const onChangeInput = jest.fn(value => value);
const children = [
Expand Down
2 changes: 1 addition & 1 deletion __tests__/helpers/components/AgeRange.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { Input, Collection } from "./../../../src";

const preventAge = (state, prevState, formState) => {
const preventAge = (state, prevState) => {
let newState = { ...state };
if (newState.end < prevState.start) newState.end = prevState.start;

Expand Down
35 changes: 35 additions & 0 deletions __tests__/helpers/components/CmpWithSelectorToggle.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React, { useState } from "react";
import { useSelector } from "./../../../src";

export const CmpWithSelectorToggle = ({ id = "", ...props }) => {
const [visible, toggle] = useState(() => true);

return (
<>
{visible && <CmpWithSelector id={id} {...props} />}
<button
type="button"
data-testid={`toggle${id}`}
onClick={() => toggle(prev => !prev)}
/>
</>
);
};

export const CmpWithSelector = ({ selector, setNewValue, id = "" }) => {
const [value = "", setValue] = useSelector(selector);

const valueToShow = typeof value === "object" ? JSON.stringify(value) : value;
return (
<>
<pre>
<code data-testid={`selector${id}`}>{valueToShow}</code>
</pre>
<button
type="button"
data-testid={`selectorBtn${id}`}
onClick={() => setValue(setNewValue)}
/>
</>
);
};
33 changes: 31 additions & 2 deletions __tests__/hooks/useField.spec.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
import React from "react";
import { render, fireEvent, cleanup } from "@testing-library/react";
import Form, { Collection, useField, withIndex } from "./../../src";
import { render, fireEvent, cleanup, act } from "@testing-library/react";
import { Form, Collection, useField, withIndex } from "./../../src";

const InputCustom = withIndex(({ type, name, value, index, ...restAttr }) => {
const props = useField({ type, name, value, index });
return <input {...restAttr} {...props}></input>;
});

const CustomField = withIndex(({ name, value, ...restAttr }) => {
const props = useField({ type: "custom", name, value });
const onChange = () => props.onChange({ target: { value: "5" } });
return (
<button type="button" onClick={onChange} {...restAttr}>
Change Value
</button>
);
});

const InputCustomNoAutoIndex = ({ type, name, value, index, ...restAttr }) => {
const props = useField({ type, name, value, index });
return <input {...restAttr} {...props}></input>;
Expand Down Expand Up @@ -59,6 +69,25 @@ describe("Hooks => useField", () => {
expect(onChange).toHaveBeenCalledWith({ number: "50", number2: "5" }, true);
});

it("should render a Field of type custom with an initial value", () => {
const name = "custom";
const props = { onInit, onChange };
const initial = { a: "test" };

const children = [
<CustomField key="1" data-testid={name} name={name} value={initial} />
];
const { getByTestId } = mountForm({ children, props });
expect(onInit).toHaveBeenCalledWith({ [name]: initial }, true);

const custom = getByTestId("custom");
act(() => {
fireEvent.click(custom);
});

expect(onChange).toHaveBeenCalledWith({ [name]: "5" }, true);
});

it("should change a Field value due to an action", () => {
const props = { onChange };
const children = [
Expand Down
Loading

0 comments on commit 8970a22

Please sign in to comment.