Skip to content

Commit

Permalink
Merge pull request #39 from saseungmin/apply-change-input
Browse files Browse the repository at this point in the history
[Feature] Auth input fields onChange action
  • Loading branch information
saseungmin authored Feb 26, 2021
2 parents bbc2e74 + 41a9b8c commit b51a249
Show file tree
Hide file tree
Showing 5 changed files with 181 additions and 23 deletions.
54 changes: 54 additions & 0 deletions src/components/auth/AuthInput.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React from 'react';

import { useRecoilState } from 'recoil';

import authFieldsAtom from '../../recoil/auth';

const authFieldsProperty = {
userId: {
inputType: 'text',
placeholder: '아이디',
autoComplete: 'username',
},
password: {
inputType: 'password',
placeholder: '비밀번호',
autoComplete: 'new-password',
},
passwordConfirm: {
inputType: 'password',
placeholder: '비밀번호 확인',
autoComplete: 'new-password',
},
};

const AuthInput = ({ formType, inputName }) => {
const [authFieldsState, setAuthFieldsState] = useRecoilState(authFieldsAtom);

const { inputType, placeholder, autoComplete } = authFieldsProperty[inputName];

const onChange = (e, type) => {
const { name, value } = e.target;

setAuthFieldsState({
...authFieldsState,
[type]: {
...authFieldsState[type],
[name]: value,
},
});
};

return (
<input
type={inputType}
name={inputName}
placeholder={placeholder}
autoComplete={autoComplete}
value={authFieldsState[formType][inputName]}
onChange={(e) => onChange(e, formType)}
/>
);
};

export default AuthInput;
69 changes: 69 additions & 0 deletions src/components/auth/AuthInput.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import React from 'react';

import { RecoilRoot } from 'recoil';

import { render, fireEvent } from '@testing-library/react';

import InjectTestingRecoilState from '../common/InjectTestingRecoilState';

import AuthInput from './AuthInput';

describe('AuthInput', () => {
const renderAuthInput = ({ type, name, fields }) => render((
<RecoilRoot>
<InjectTestingRecoilState
authFields={fields}
/>
<AuthInput
formType={type}
inputName={name}
/>
</RecoilRoot>

));

it('renders auth input', () => {
const props = {
type: 'login',
name: 'userId',
fields: {
login: {
userId: 'seungmin',
},
},
};

const { getByPlaceholderText } = renderAuthInput(props);

const input = getByPlaceholderText('아이디');

expect(input).not.toBeNull();
expect(input).toHaveValue('seungmin');
});

it('listens event change input value', () => {
const props = {
type: 'login',
name: 'userId',
fields: {
login: {
userId: '',
},
},
};

const { getByPlaceholderText } = renderAuthInput(props);

const input = getByPlaceholderText('아이디');

fireEvent.change(input, {
target: {
value: 'seungmin',
name: 'userId',
},
});

expect(input).not.toBeNull();
expect(input).toHaveValue('seungmin');
});
});
45 changes: 24 additions & 21 deletions src/components/auth/AuthModalForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import { useRecoilValue, useResetRecoilState } from 'recoil';
import styled from '@emotion/styled';
import { css } from '@emotion/react';

import { authStatusAtom } from '../../recoil/auth';
import authFieldsAtom, { authStatusAtom } from '../../recoil/auth';
import { FORM_TYPE } from '../../utils/constants/constants';

import AuthInput from './AuthInput';

const AuthModalFormWrapper = styled.div`
top: 0;
left: 0;
Expand Down Expand Up @@ -53,19 +55,26 @@ const AuthModalBoxWrapper = styled.div`
`;

const AuthFormWrapper = styled.form`
display: flex;
flex-direction: column;
justify-content: center;
`;

const AuthModalForm = () => {
const authStatusState = useRecoilValue(authStatusAtom);
const resetAuthStatusState = useResetRecoilState(authStatusAtom);
const { type, visible } = useRecoilValue(authStatusAtom);

const { type, visible } = authStatusState;
const resetAuthStatusState = useResetRecoilState(authStatusAtom);
const resetAuthFieldsState = useResetRecoilState(authFieldsAtom);

const handleSubmit = (e) => {
e.preventDefault();
};

const onCloseAuthModal = () => {
resetAuthStatusState();
resetAuthFieldsState();
};

if (!visible) {
return null;
}
Expand All @@ -77,24 +86,18 @@ const AuthModalForm = () => {
<AuthModalBoxWrapper>
<h2>{formType}</h2>
<AuthFormWrapper onSubmit={handleSubmit}>
<input
type="text"
name="userId"
placeholder="아이디"
autoComplete="username"
<AuthInput
formType={type}
inputName="userId"
/>
<input
type="password"
name="password"
placeholder="비밀번호"
autoComplete="new-password"
<AuthInput
formType={type}
inputName="password"
/>
{type === 'register' && (
<input
type="password"
name="passwordConfirm"
placeholder="비밀번호 확인"
autoComplete="new-password"
<AuthInput
formType={type}
inputName="passwordConfirm"
/>
)}
<button
Expand All @@ -105,7 +108,7 @@ const AuthModalForm = () => {
</button>
<button
type="button"
onClick={resetAuthStatusState}
onClick={onCloseAuthModal}
>
닫기
</button>
Expand Down
13 changes: 13 additions & 0 deletions src/components/auth/AuthModalForm.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,19 @@ describe('AuthModalForm', () => {

fireEvent.submit(getByTestId('auth-submit-button'));
});

it('When click Close button, the modal window is closed.', () => {
const props = {
type: 'register',
visible: true,
};

const { container, getByText } = renderAuthForm(props);

fireEvent.click(getByText('닫기'));

expect(container).toBeEmptyDOMElement();
});
});

context("Isn't visible", () => {
Expand Down
23 changes: 21 additions & 2 deletions src/components/common/InjectTestingRecoilState.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,41 @@ import { useEffect } from 'react';
import { useSetRecoilState } from 'recoil';

import todosAtom, { filterAtom } from '../../recoil/todos';
import { authStatusAtom } from '../../recoil/auth';
import authFieldsAtom, { authStatusAtom } from '../../recoil/auth';

const authState = {
type: '',
visible: false,
};

const InjectTestingRecoilState = ({ todos = [], filter = 'ALL', auth = authState }) => {
const authFieldsState = {
register: {
userId: '',
password: '',
passwordConfirm: '',
},
login: {
userId: '',
password: '',
},
};

const InjectTestingRecoilState = ({
todos = [],
filter = 'ALL',
auth = authState,
authFields = authFieldsState,
}) => {
const setTodosState = useSetRecoilState(todosAtom);
const setFilterState = useSetRecoilState(filterAtom);
const setAuthState = useSetRecoilState(authStatusAtom);
const setAuthFieldsState = useSetRecoilState(authFieldsAtom);

useEffect(() => {
setTodosState(todos);
setFilterState(filter);
setAuthState(auth);
setAuthFieldsState(authFields);
}, []);

return null;
Expand Down

0 comments on commit b51a249

Please sign in to comment.