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
4 changes: 2 additions & 2 deletions fixture/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ export const users = [
},
{
uid: 'Uid2',
githubId: 'daadaadaah',
githubId: 'daadaadaah2',
githubProfile: 'https://avatars1.githubusercontent.com/u/60481383?s=460&v=4',
},
{
uid: 'Uid3',
githubId: 'daadaadaah',
githubId: 'daadaadaah3',
githubProfile: 'https://avatars1.githubusercontent.com/u/60481383?s=460&v=4',
},
]
Expand Down
6 changes: 6 additions & 0 deletions front-end/services/api/__mocks__/api.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { user } from '../../../../fixture/data';

export async function getDevLinks() {
return [];
}
Expand All @@ -7,3 +9,7 @@ export async function getUsers() {
}

export const addUser = jest.fn();

export async function getUser() {
return user;
}
6 changes: 6 additions & 0 deletions front-end/services/api/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,9 @@ export async function addUser({ uid, githubId, githubProfile }) {

return resaddUserInfo;
}

export async function getUser({ githubId }) {
const responses = await db.collection('user').where('githubId', '==', githubId).get();

return responses.docs.map((doc) => (doc.data()))[0];
}
12 changes: 11 additions & 1 deletion front-end/services/api/api.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { getDevLinks, getUsers, addUser } from './api';
import {
getDevLinks, getUsers, addUser, getUser,
} from './api';

import { devLinks, users, user } from '../../../fixture/data';

Expand Down Expand Up @@ -30,4 +32,12 @@ describe('api', () => {
expect(data).toEqual(user);
});
});

describe('getUser', () => {
it('returns user', async () => {
const data = await getUser({ githubId: user.githubId });

expect(data).toEqual(user);
});
});
});
37 changes: 29 additions & 8 deletions front-end/services/firebase/__mocks__/firebase.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,35 @@ const firebase = {
data: () => item,
})),
}),
where: jest.fn().mockImplementation(() => ({
get: jest.fn().mockResolvedValue({
docs: collections[name].map((item) => ({
id: item.uid,
data: () => item,
})),
}),
})),
where: jest.fn().mockImplementation((fieldName, operator, value) => {
let result = null;

if (operator === '==') {
result = ({
get: jest.fn().mockResolvedValue({
docs: collections[name]
.filter((doc) => doc[fieldName] === value)
.map((doc) => ({
id: doc.uid,
data: () => doc,
})),
}),
});
}

if (operator === 'in') {
result = ({
get: jest.fn().mockResolvedValue({
docs: collections[name].map((item) => ({
id: item.uid,
data: () => item,
})),
}),
});
}

return result;
}),
doc: jest.fn().mockImplementation((docName) => ({
get: jest.fn().mockResolvedValue({
id: docName,
Expand Down
2 changes: 2 additions & 0 deletions front-end/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Switch, Route } from 'react-router-dom';
import Header from './Header';

import HomePage from './HomePage';
import UserPage from './UserPage';
import NotFoundPage from './NotFoundPage';

const Wrapper = styled.div({
Expand All @@ -20,6 +21,7 @@ export default function App() {
<Header />
<Switch>
<Route exact path="/" component={HomePage} />
<Route exact path="/user/:devLinkerId" component={UserPage} />
<Route component={NotFoundPage} />
</Switch>
</Wrapper>
Expand Down
19 changes: 17 additions & 2 deletions front-end/src/App.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import { render } from '@testing-library/react';

import { MemoryRouter } from 'react-router-dom';

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

import App from './App';

import { user } from '../../fixture/data';

jest.mock('react-redux');
jest.mock('../services/firebase/firebase.js');

Expand All @@ -16,6 +18,10 @@ describe('App with router', () => {

beforeEach(() => {
useDispatch.mockImplementation(() => dispatch);

useSelector.mockImplementation((selector) => selector({
devLinkerInfo: user,
}));
});

function renderApp({ path }) {
Expand All @@ -36,13 +42,22 @@ describe('App with router', () => {
});

context('with path /', () => {
it('shows loading message', () => {
it('shows devlinks', () => {
const { container } = renderApp({ path: '/' });

expect(container).toHaveTextContent('로딩중');
});
});

context('with path /user/devlinker', () => {
it('shows devlinkerInfo', () => {
const { container, getByAltText } = renderApp({ path: '/user/devlinker' });

expect(getByAltText(`${user.githubId}`)).toHaveAttribute('src', user.githubProfile);
expect(container).toHaveTextContent(user.githubId);
});
});

context('with invalid path', () => {
it('renders the not found page', () => {
const { container } = renderApp({ path: '/xxx' });
Expand Down
4 changes: 3 additions & 1 deletion front-end/src/Header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ export default function Header() {
{userInfo ? (
<UserInfoWrapper>
<ImgWrapper>
<img id="first-devlinker-img" src={userInfo.githubProfile} alt={userInfo.githubId} />
<Link to={`/user/${userInfo.githubId}`}>
<img id="first-devlinker-img" src={userInfo.githubProfile} alt={userInfo.githubId} />
</Link>
</ImgWrapper>
<button type="button" onClick={handleClickLogout}>로 그 아 웃</button>
</UserInfoWrapper>
Expand Down
63 changes: 63 additions & 0 deletions front-end/src/UserInfo.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import React from 'react';

import styled from '@emotion/styled';

const Wrapper = styled.div({
height: '100%',
padding: '0px 50px',
display: 'flex',
flexDirection: 'column',
margin: '0 10em',
});
const TopWrapper = styled.div({
display: 'flex',
flexDirection: 'row',
borderBottom: '#dcdc 1px solid',

});

const TopLeftWrapper = styled.div({
padding: '0 4em 4em 4em',
});

const ImgWrapper = styled.div({
width: '12em',
height: '12em',
borderRadius: '100%',
overflow: 'hidden',
border: '#dcdc 1px solid',
'& img': {
width: '100%',
height: '100%',
objectFit: 'cover',
},
});

const TopRightWrapper = styled.div({
'& div': {
margin: '0 4em',
'& span': {
fontSize: '2em',
fontFamily: 'system-ui',
},
},
});

export default function UserInfo({ userInfo }) {
return (
<Wrapper>
<TopWrapper>
<TopLeftWrapper>
<ImgWrapper>
<img id="user-img" src={userInfo.githubProfile} alt={userInfo.githubId} />
</ImgWrapper>
</TopLeftWrapper>
<TopRightWrapper>
<div>
<span>{userInfo.githubId}</span>
</div>
</TopRightWrapper>
</TopWrapper>
</Wrapper>
);
}
14 changes: 14 additions & 0 deletions front-end/src/UserInfo.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react';

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

import UserInfo from './UserInfo';

import { user } from '../../fixture/data';

test('UserInfo ', () => {
const { container, getByAltText } = render(<UserInfo userInfo={user} />);

expect(getByAltText(`${user.githubId}`)).toHaveAttribute('src', user.githubProfile);
expect(container).toHaveTextContent(user.githubId);
});
19 changes: 19 additions & 0 deletions front-end/src/UserInfoContainer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';

import { useSelector } from 'react-redux';

import { get } from './common/utils';

import UserInfo from './UserInfo';

export default function UserInfoContainer() {
const devLinkerInfo = useSelector(get('devLinkerInfo'));

if (!devLinkerInfo) {
return <p>로딩중....</p>;
}

return (
<UserInfo userInfo={devLinkerInfo} />
);
}
45 changes: 45 additions & 0 deletions front-end/src/UserInfoContainer.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React from 'react';

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

import { useSelector } from 'react-redux';

import UserInfoContainer from './UserInfoContainer';

import { user } from '../../fixture/data';

jest.mock('react-redux');

describe('<UserInfoContainer />', () => {
context('with devLinkerInfo', () => {
beforeEach(() => {
useSelector.mockImplementation((selector) => selector({
devLinkerInfo: user,
}));
});

it('show devLinkerInfo', () => {
const { container, getByAltText } = render(
<UserInfoContainer />,
);

expect(getByAltText(`${user.githubId}`)).toHaveAttribute('src', user.githubProfile);
expect(container).toHaveTextContent(user.githubId);
});
});

context('without devLinkerInfo', () => {
beforeEach(() => {
useSelector.mockImplementation((selector) => selector({
devLinkerInfo: null,
}));
});

it('show loading..', () => {
const { container } = render(
<UserInfoContainer />,
);
expect(container).toHaveTextContent('로딩중....');
});
});
});
36 changes: 36 additions & 0 deletions front-end/src/UserPage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React, { useEffect } from 'react';

import styled from '@emotion/styled';

import { useParams } from 'react-router-dom';

import { useDispatch } from 'react-redux';

import {
loadDevLinkerInfo,
} from './common/slice';

import UserInfoContainer from './UserInfoContainer';

const Wrapper = styled.div({
height: '100vh',
padding: '0px 50px',
display: 'flex',
flexDirection: 'column',
});

export default function UserPage({ params }) {
const dispatch = useDispatch();

const { devLinkerId } = params || useParams();

useEffect(() => {
dispatch(loadDevLinkerInfo({ devLinkerGithubId: devLinkerId }));
}, []);

return (
<Wrapper>
<UserInfoContainer />
</Wrapper>
);
}
30 changes: 30 additions & 0 deletions front-end/src/UserPage.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react';

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

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

import UserPage from './UserPage';

import { user } from '../../fixture/data';

jest.mock('react-redux');
jest.mock('../services/firebase/firebase.js');

test('UserPage ', () => {
const dispatch = jest.fn();

useDispatch.mockImplementation(() => dispatch);

useSelector.mockImplementation((selector) => selector({
devLinkerInfo: user,
}));

expect(dispatch).not.toBeCalled();

render(
<UserPage params={{ devLinkerId: user.devLinkerId }} />,
);

expect(dispatch).toBeCalledTimes(1);
});
Loading