Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 39 additions & 23 deletions src/components/auth/AuthForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ const FORM_TYPE = {
register: '회원가입',
};

const AuthForm = ({ type, onChange, fields }) => {
const AuthForm = ({
type, fields, onChange, onSubmit,
}) => {
const formType = FORM_TYPE[type];

const { userEmail, password } = fields;
Expand All @@ -22,35 +24,49 @@ const AuthForm = ({ type, onChange, fields }) => {
onChange({ name, value });
};

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

onSubmit();
};

return (
<AuthFormWrapper>
<h2>{formType}</h2>
<input
type="text"
value={userEmail}
name="userEmail"
placeholder="이메일"
autoComplete="email"
onChange={handleChange}
/>
<input
type="password"
value={password}
name="password"
placeholder="비밀번호"
autoComplete="password"
onChange={handleChange}
/>
{type === 'register' && (
<form onSubmit={handleSubmit}>
<input
type="text"
value={userEmail}
name="userEmail"
placeholder="이메일"
autoComplete="email"
onChange={handleChange}
/>
<input
type="password"
value={fields.passwordConfirm}
name="passwordConfirm"
placeholder="비밀번호 확인"
autoComplete="new-password"
value={password}
name="password"
placeholder="비밀번호"
autoComplete="password"
onChange={handleChange}
/>
)}
{type === 'register' && (
<input
type="password"
value={fields.passwordConfirm}
name="passwordConfirm"
placeholder="비밀번호 확인"
autoComplete="new-password"
onChange={handleChange}
/>
)}
<button
data-testid="auth-button"
type="submit"
>
{formType}
</button>
</form>
</AuthFormWrapper>
);
};
Expand Down
15 changes: 15 additions & 0 deletions src/components/auth/AuthForm.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,19 @@ import AuthForm from './AuthForm';

describe('AuthForm', () => {
const handleChange = jest.fn();
const handleSubmit = jest.fn();

beforeEach(() => {
handleChange.mockClear();
handleSubmit.mockClear();
});

const renderAuthForm = ({ type, fields }) => render((
<AuthForm
type={type}
fields={fields}
onChange={handleChange}
onSubmit={handleSubmit}
/>
));

Expand Down Expand Up @@ -94,5 +97,17 @@ describe('AuthForm', () => {
expect(handleChange).toBeCalled();
});
});

it('listens event call submit', () => {
const { getByTestId } = renderAuthForm(register);

const button = getByTestId('auth-button');

expect(button).not.toBeNull();

fireEvent.submit(button);

expect(handleSubmit).toBeCalled();
});
});
});
32 changes: 28 additions & 4 deletions src/containers/auth/RegisterFormContainer.jsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import React, { useCallback } from 'react';
import React, { useCallback, useEffect } from 'react';

import { useHistory } from 'react-router-dom';
import { useSelector, useDispatch } from 'react-redux';

import { get } from '../../util/utils';
import { changeAuthField } from '../../reducers/slice';
import { changeAuthField, clearAuth, requestRegister } from '../../reducers/slice';

import AuthForm from '../../components/auth/AuthForm';

const RegisterFormContainer = () => {
const dispatch = useDispatch();
const history = useHistory();

const register = useSelector(get('register'));
const auth = useSelector(get('auth'));
const authError = useSelector(get('authError'));

const onChangeRegisterField = useCallback(({ name, value }) => {
dispatch(
Expand All @@ -20,13 +24,33 @@ const RegisterFormContainer = () => {
value,
}),
);
});
}, [dispatch]);

const onSubmit = useCallback(() => {
dispatch(requestRegister());
}, [dispatch]);

useEffect(() => {
if (auth) {
history.push('/login');
}

if (authError) {
// TODO: 추 후 error 처리
console.error(authError);
}
Comment on lines +38 to +41
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

error 처리 해주자.


return () => {
dispatch(clearAuth());
};
}, [dispatch, auth, authError]);

return (
<AuthForm
type="register"
onChange={onChangeRegisterField}
fields={register}
onChange={onChangeRegisterField}
onSubmit={onSubmit}
/>
);
};
Expand Down
49 changes: 48 additions & 1 deletion src/containers/auth/RegisterFormContainer.test.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
import React from 'react';

import { MemoryRouter } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux';

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

import RegisterFormContainer from './RegisterFormContainer';

const mockPush = jest.fn();

jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useHistory() {
return { push: mockPush };
},
}));

describe('RegisterFormContainer', () => {
const dispatch = jest.fn();

Expand All @@ -19,11 +29,15 @@ describe('RegisterFormContainer', () => {
password: '',
passwordConfirm: '',
},
auth: given.auth,
authError: given.authError,
}));
});

const renderRegisterFormContainer = () => render((
<RegisterFormContainer />
<MemoryRouter>
<RegisterFormContainer />
</MemoryRouter>
));

it('renders register form text', () => {
Expand Down Expand Up @@ -62,5 +76,38 @@ describe('RegisterFormContainer', () => {
});
});
});

it('submit event calls dispatch', () => {
const { getByTestId } = renderRegisterFormContainer();

const button = getByTestId('auth-button');

expect(button).not.toBeNull();

fireEvent.submit(button);

expect(dispatch).toBeCalled();
});
});

describe('action after signing up', () => {
context('when success auth to register', () => {
given('auth', () => ({
auth: 'seungmin@naver.com',
}));

it('go to login page', () => {
renderRegisterFormContainer();

expect(mockPush).toBeCalledWith('/login');
});
});

// TODO: 현재 authError는 콘솔 출력
context('when failure auth to register', () => {
given('authError', () => ({
authError: 'error',
}));
});
});
});
53 changes: 53 additions & 0 deletions src/reducers/slice.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
getStudyGroup,
getStudyGroups,
postStudyGroup,
postUserRegister,
} from '../services/api';

const writeInitialState = {
Expand Down Expand Up @@ -39,6 +40,8 @@ const { actions, reducer } = createSlice({
writeField: writeInitialState,
register: authInitialState.register,
login: authInitialState.login,
auth: null,
authError: null,
},

reducers: {
Expand Down Expand Up @@ -95,6 +98,38 @@ const { actions, reducer } = createSlice({
draft[form][name] = value;
});
},

clearAuthFields(state) {
const { register, login } = authInitialState;

return {
...state,
register,
login,
};
},

setAuth(state, { payload: user }) {
return {
...state,
auth: user,
};
},

setAuthError(state, { payload: error }) {
return {
...state,
authError: error,
};
},

clearAuth(state) {
return {
...state,
auth: null,
authError: null,
};
},
},
});

Expand All @@ -105,6 +140,10 @@ export const {
clearWriteFields,
successWrite,
changeAuthField,
clearAuthFields,
setAuth,
setAuthError,
clearAuth,
} = actions;

export const loadStudyGroups = (tag) => async (dispatch) => {
Expand Down Expand Up @@ -135,4 +174,18 @@ export const writeStudyGroup = () => async (dispatch, getState) => {
dispatch(clearWriteFields());
};

export const requestRegister = () => async (dispatch, getState) => {
const { register: { userEmail, password } } = getState();

try {
const { user } = await postUserRegister({ userEmail, password });

dispatch(setAuth(user.email));

dispatch(clearAuthFields());
} catch (error) {
setAuthError(error);
}
};

export default reducer;
Loading