diff --git a/client/.env.sample b/client/.env.sample new file mode 100644 index 0000000..70a73f3 --- /dev/null +++ b/client/.env.sample @@ -0,0 +1 @@ +SERVER_URL= \ No newline at end of file diff --git a/client/jest.config.js b/client/jest.config.js index 4931934..1473472 100644 --- a/client/jest.config.js +++ b/client/jest.config.js @@ -1,3 +1,6 @@ module.exports = { testEnvironment: 'jsdom', + moduleNameMapper: { + '.+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2|svg)$': 'jest-transform-stub', + }, }; diff --git a/client/package-lock.json b/client/package-lock.json index 99b1bea..10e451f 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -34,6 +34,7 @@ "fork-ts-checker-webpack-plugin": "^6.3.2", "html-webpack-plugin": "^5.3.2", "jest": "^27.0.6", + "jest-transform-stub": "^2.0.0", "prettier": "^2.3.2", "typescript": "^4.3.5", "webpack": "^5.50.0", @@ -8765,6 +8766,12 @@ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, + "node_modules/jest-transform-stub": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jest-transform-stub/-/jest-transform-stub-2.0.0.tgz", + "integrity": "sha512-lspHaCRx/mBbnm3h4uMMS3R5aZzMwyNpNIJLXj4cEsV0mIUtS4IjYJLSoyjRCtnxb6RIGJ4NL2quZzfIeNhbkg==", + "dev": true + }, "node_modules/jest-util": { "version": "27.0.6", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.0.6.tgz", @@ -20369,6 +20376,12 @@ "semver": "^7.3.2" } }, + "jest-transform-stub": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jest-transform-stub/-/jest-transform-stub-2.0.0.tgz", + "integrity": "sha512-lspHaCRx/mBbnm3h4uMMS3R5aZzMwyNpNIJLXj4cEsV0mIUtS4IjYJLSoyjRCtnxb6RIGJ4NL2quZzfIeNhbkg==", + "dev": true + }, "jest-util": { "version": "27.0.6", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.0.6.tgz", diff --git a/client/package.json b/client/package.json index 71806dc..3122072 100644 --- a/client/package.json +++ b/client/package.json @@ -34,6 +34,7 @@ "fork-ts-checker-webpack-plugin": "^6.3.2", "html-webpack-plugin": "^5.3.2", "jest": "^27.0.6", + "jest-transform-stub": "^2.0.0", "prettier": "^2.3.2", "typescript": "^4.3.5", "webpack": "^5.50.0", diff --git a/client/src/components/login/Login.test.tsx b/client/src/components/login/Login.test.tsx new file mode 100644 index 0000000..6c096e1 --- /dev/null +++ b/client/src/components/login/Login.test.tsx @@ -0,0 +1,17 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import Login from './Login'; + +describe('Login 컴포넌트', () => { + test('facebook 버튼 UI', () => { + const login = render(); + + login.getByText('페이스북으로 로그인'); + }); + + test('google 버튼 UI', () => { + const login = render(); + + login.getByText('구글로 로그인'); + }); +}); diff --git a/client/src/components/login/Login.tsx b/client/src/components/login/Login.tsx new file mode 100644 index 0000000..ed3f1e7 --- /dev/null +++ b/client/src/components/login/Login.tsx @@ -0,0 +1,69 @@ +import React, { useCallback, useMemo } from 'react'; +import styled from 'styled-components'; +import OAuthButton from './OAuthButton'; +import FACEBOOK from './facebook.svg'; +import GOOGLE from './google.svg'; + +enum OAuthType { + Facebook, + Google, +} + +const Header = styled.h1` + font-size: 24px; + font-weight: normal; +`; + +const LoginContainer = styled.div` + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +`; + +const OAuthButtonWrapper = styled.div` + margin-top: 20px; + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + gap: 10px; +`; + +const Login = (): JSX.Element => { + const handleOAuthButtonClick = useCallback((redirectURL: string) => { + return () => (location.href = redirectURL); + }, []); + + const BUTTON_PROPS = useMemo( + () => ({ + [OAuthType.Facebook]: { + backgroundColor: '#4267b2', + fontColor: '#ffffff', + icon: FACEBOOK, + content: '페이스북으로 로그인', + onClick: handleOAuthButtonClick(`${process.env.SERVER_URL}/auth/facebook-login`), + }, + [OAuthType.Google]: { + backgroundColor: '#EA4335', + fontColor: '#ffffff', + icon: GOOGLE, + content: '구글로 로그인', + onClick: handleOAuthButtonClick(`${process.env.SERVER_URL}/auth/google-login`), + }, + }), + [handleOAuthButtonClick] + ); + + return ( + +
회원 로그인
+ + + + +
+ ); +}; + +export default Login; diff --git a/client/src/components/login/OAuthButton.tsx b/client/src/components/login/OAuthButton.tsx new file mode 100644 index 0000000..2a2e63f --- /dev/null +++ b/client/src/components/login/OAuthButton.tsx @@ -0,0 +1,55 @@ +import React, { MouseEventHandler } from 'react'; +import styled from 'styled-components'; + +type ContainerProps = { + backgroundColor: string; + fontColor: string; +}; + +const OAuthButtonContainer = styled.button` + background-color: ${(props) => props.backgroundColor}; + color: ${(props) => props.fontColor}; + display: flex; + align-items: center; + justify-content: center; + gap: 15px; + height: 50px; + width: 300px; + padding: 15px; + border: none; + cursor: pointer; +`; + +const OAuthIcon = styled.img` + max-width: 18px; + max-height: 100%; +`; + +const OAuthButtonContent = styled.span` + font-size: 16px; +`; + +type Props = { + backgroundColor: string; + fontColor: string; + icon: string; + content: string; + onClick: MouseEventHandler; +}; + +const OAuthButton = ({ + icon, + fontColor, + backgroundColor, + content, + onClick, +}: Props): JSX.Element => { + return ( + + + {content} + + ); +}; + +export default OAuthButton; diff --git a/client/src/components/login/facebook.svg b/client/src/components/login/facebook.svg new file mode 100644 index 0000000..b60b3e1 --- /dev/null +++ b/client/src/components/login/facebook.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/components/login/google.svg b/client/src/components/login/google.svg new file mode 100644 index 0000000..7dbb495 --- /dev/null +++ b/client/src/components/login/google.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/client/src/components/login/kakao.svg b/client/src/components/login/kakao.svg new file mode 100644 index 0000000..1e23afc --- /dev/null +++ b/client/src/components/login/kakao.svg @@ -0,0 +1 @@ + diff --git a/client/webpack.dev.js b/client/webpack.dev.js index e774c20..42d44a8 100644 --- a/client/webpack.dev.js +++ b/client/webpack.dev.js @@ -19,6 +19,6 @@ module.exports = merge(common, { mode: 'DEV', }, }), - new EnvironmentPlugin([]), + new EnvironmentPlugin(['SERVER_URL']), ], });