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
6 changes: 4 additions & 2 deletions src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
ProfilePage,
NewProfilePage,
ApartmentPage,
ResultPage,
NotFoundPage,
} from './pages';

Expand All @@ -38,8 +39,9 @@ export default function App() {
<Route exact path="/" component={HomePage} />
<Route exact path="/profile" component={ProfilePage} />
<Route path="/profile/new" component={NewProfilePage} />
<Route exact path="/apartment" component={ApartmentPage} />
<Route path="/apartment/:id" component={ApartmentPage} />
<Route exact path="/apartments" component={ApartmentPage} />
<Route path="/apartments/:id" component={ApartmentPage} />
<Route exact path="/result" component={ResultPage} />
<Route component={NotFoundPage} />
</Switch>
</main>
Expand Down
39 changes: 29 additions & 10 deletions src/App.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ describe('App', () => {
const dispatch = jest.fn();

const profile = {
isNew: false,
name: '신형탁',
age: 29,
salary: 5000,
Expand All @@ -41,7 +42,18 @@ describe('App', () => {
},
];

const apartment = {
name: '아크로리버파크',
date: '2021-03',
district: '반포동',
area: '129.92',
price: '470,000',
lotNumber: 1,
};

given('userFields', () => (profile));
given('apartments', () => apartments);
given('apartment', () => apartment);

beforeEach(() => {
jest.clearAllMocks();
Expand All @@ -51,6 +63,7 @@ describe('App', () => {
useSelector.mockImplementation((selector) => selector({
userFields: given.userFields,
apartments: given.apartments,
apartment: given.apartment,
}));

loadItem.mockImplementation(() => null);
Expand All @@ -65,8 +78,6 @@ describe('App', () => {
}

context('with path /', () => {
given('userFields', () => (profile));

beforeEach(() => {
loadItem.mockImplementation(() => (JSON.stringify(profile)));
});
Expand All @@ -79,8 +90,6 @@ describe('App', () => {
});

context('with path /profile/new', () => {
given('userFields', () => (profile));

it('renders new profile page', () => {
renderApp({ path: '/profile/new' });

Expand All @@ -95,8 +104,6 @@ describe('App', () => {
});

context('with path /profile', () => {
given('userFields', () => (profile));

it('renders profile page', () => {
renderApp({ path: '/profile' });

Expand All @@ -107,19 +114,31 @@ describe('App', () => {
});
});

context('with path /aparment', () => {
context('with path /aparments', () => {
it('renders apartment page', () => {
renderApp({ path: '/apartment' });
renderApp({ path: '/apartments' });

expect(screen.getByText('거주하고 싶은신 아파트를 선택해주세요')).toBeInTheDocument();
});
});

context('with path /apartment/:id', () => {
context('with path /apartments/:id', () => {
it('redners the apartment page', () => {
renderApp({ path: '/apartment/riverside' });
renderApp({ path: '/apartments/riverside' });

expect(screen.getByText('아크로리버파크')).toBeInTheDocument();
});
});

context('with path /result', () => {
it('renders the apartment result page', () => {
renderApp({ path: '/result' });

expect(screen.getByText('결과')).toBeInTheDocument();

expect(screen.getByText('아크로리버파크')).toBeInTheDocument();
expect(screen.getByText('129.92')).toBeInTheDocument();
expect(screen.getByText('470,000')).toBeInTheDocument();
});
});

Expand Down
7 changes: 6 additions & 1 deletion src/components/LinkField.jsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import React, { useCallback } from 'react';

export default function LinkField({ url, title, onClick }) {
export default function LinkField({
url, title, onClick, apartment, changeApartment,
}) {
const handleClick = useCallback((event) => {
event.preventDefault();
if (title === '보기') {
changeApartment(apartment);
}
Comment on lines +8 to +10
Copy link

Choose a reason for hiding this comment

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

특정 경우에만 changeApartment()가 실행되는건가요?
그럼 title이 보기인 경우에만 사용하는 곳에서 changeApartment를 주입해주고
이 핸들러 함수에서는 changeApartment가 있는 경우에만 호출하도록 처리할 수도 있을 것 같아요.
changeApartment?.(apartment);

아니면 props로 onClick을 넘겨주고 있으니 onClick에 title이 보기인 경우에만 핸들링하는 로직을 넣어서 넘기는 방법도 있을 것 같아요.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

#42 반영 완료!

onClick({ url });
}, [onClick]);

Expand Down
62 changes: 46 additions & 16 deletions src/components/LinkField.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,68 @@ import LinkField from './LinkField';

describe('LinkField', () => {
const handleClick = jest.fn();
const changeApartment = jest.fn();

beforeEach(() => {
jest.clearAllMocks();
});

it('renders Link', () => {
render((
<LinkField
url="/profile/new"
title="내 정보 입력하러가기"
onClick={handleClick}
/>
));
context("with '내 정보 입력하러가기' title", () => {
it('renders Link', () => {
render((
<LinkField
url="/profile/new"
title="내 정보 입력하러가기"
onClick={handleClick}
/>
));

expect(screen.getByRole('link', {
name: '내 정보 입력하러가기',
})).toBeInTheDocument();
});
});

context("with '거주하고 싶은 아파트 둘러보기' title", () => {
it('calls handleClick upon clicking link', () => {
render((
<LinkField
url="/apartments"
title="거주하고 싶은 아파트 둘러보기"
onClick={handleClick}
/>
));

fireEvent.click(screen.getByRole('link', {
name: '거주하고 싶은 아파트 둘러보기',
}));

expect(screen.getByRole('link', {
name: '내 정보 입력하러가기',
})).toBeInTheDocument();
expect(handleClick).toBeCalledWith({ url: '/apartments' });
});
});

it('calls handleClick upon clicking link', () => {
context("with '보기' title", () => {
render((
<LinkField
url="/apartment"
title="거주하고 싶은 아파트 둘러보기"
url="/apartments"
title="보기"
onClick={handleClick}
apartment={{
name: '아크로리버파크',
date: '2021-03',
area: '129.92',
price: '470,000',
lotNumber: 1,
}}
changeApartment={changeApartment}
/>
));

fireEvent.click(screen.getByRole('link', {
name: '거주하고 싶은 아파트 둘러보기',
name: '보기',
}));

expect(handleClick).toBeCalledWith({ url: '/apartment' });
expect(handleClick).toBeCalled();
expect(changeApartment).toBeCalled();
});
});
34 changes: 14 additions & 20 deletions src/pages/Apartment/Apartment.jsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,20 @@
import React from 'react';

export default function Apartment({ apartments }) {
if (!apartments.length) {
return (
<p>loading</p>
);
}
export default function Apartment({ apartment }) {
const {
name,
district,
area,
} = apartment;

return (
<>
{apartments?.map((apartment) => (
<div key={apartment.name}>
<dl>
<dd>아파트명:</dd>
<dt>{apartment.name}</dt>
<dd>법정동:</dd>
<dt>{apartment.district}</dt>
<dd>전용면적:</dd>
<dt>{apartment.area}</dt>
</dl>
</div>
))}
</>
<dl>
<dd>아파트명:</dd>
<dt>{name}</dt>
<dd>법정동:</dd>
<dt>{district}</dt>
<dd>전용면적:</dd>
<dt>{area}</dt>
</dl>
);
}
43 changes: 13 additions & 30 deletions src/pages/Apartment/Apartment.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,20 @@ import { render, screen } from '@testing-library/react';
import Apartment from './Apartment';

describe('Apartment', () => {
const apartments = [
{
name: '아크로리버파크',
date: '2021-03',
area: '129.92',
price: '470,000',
lotNumber: 1,
},
{
name: '서울',
date: '2021-02',
area: '200.27',
price: '420,000',
lotNumber: 2,
},
];
const apartment = {
name: '아크로리버파크',
date: '2021-03',
district: '반포동',
area: '129.92',
price: '470,000',
lotNumber: 1,
};

context('without apartments', () => {
it('renders loading', () => {
render(<Apartment apartments={[]} />);
it('renders apartment', () => {
render(<Apartment apartment={apartment} />);

expect(screen.getByText('loading')).toBeInTheDocument();
});
});

context('with apartments', () => {
it('renders Apartment Page', () => {
render(<Apartment apartments={apartments} />);

expect(screen.getByText('아크로리버파크')).toBeInTheDocument();
expect(screen.getByText('서울')).toBeInTheDocument();
});
expect(screen.getByText('아크로리버파크')).toBeInTheDocument();
expect(screen.getByText('반포동')).toBeInTheDocument();
expect(screen.getByText('129.92')).toBeInTheDocument();
});
});
4 changes: 2 additions & 2 deletions src/pages/Apartment/ApartmentNavigation.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ export default function ApartmentNavigation({ onClick }) {
<ul>
<li>
<LinkField
url="/apartment/riverside"
url="/apartments/riverside"
title="한강 뷰"
onClick={onClick}
/>
</li>
<li>
<LinkField
url="/apartment/businessdistrict"
url="/apartments/businessdistrict"
title="우수 상권"
onClick={onClick}
/>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/Apartment/ApartmentNavigation.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,6 @@ describe('ApartmentNavigation', () => {
name: '한강 뷰',
}));

expect(handleClick).toBeCalledWith({ url: '/apartment/riverside' });
expect(handleClick).toBeCalledWith({ url: '/apartments/riverside' });
});
});
11 changes: 7 additions & 4 deletions src/pages/Apartment/ApartmentPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@ export default function ApartmentPage({ params }) {
}, [history]);

return (
<div>
<h2>거주하고 싶은신 아파트를 선택해주세요</h2>
<section>
<header>거주하고 싶은신 아파트를 선택해주세요</header>
<ApartmentNavigation onClick={handleClick} />
<ApartmentContainer apartmentCategory={id} />
</div>
<ApartmentContainer
apartmentCategory={id}
onClick={handleClick}
/>
</section>
);
}
30 changes: 30 additions & 0 deletions src/pages/Apartment/Apartments.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react';

import LinkField from '../../components/LinkField';

import Apartment from './Apartment';

export default function Apartments({ apartments, onClick, changeApartment }) {
if (!apartments.length) {
return (
<p>loading</p>
);
}

return (
<>
{apartments?.map((apartment) => (
<article key={apartment.name}>
Copy link

Choose a reason for hiding this comment

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

아파트 name이 key가 되는건가요? 아파트 이름이 겹치는 케이스는 없을까요?

아니라면 id 프로퍼티를 추가해서 사용해도 좋을 것 같네요 ㅎㅎ

Copy link
Contributor Author

Choose a reason for hiding this comment

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

아파트 이름이 중복될 가능성은 희박하다.

절대란 없으니, 추후에 백엔드에서 data를 가공할떄, id를 넣어주도록 수정 예정.

<Apartment apartment={apartment} />
<LinkField
url="/result"
title="보기"
onClick={onClick}
apartment={apartment}
changeApartment={changeApartment}
/>
</article>
))}
</>
);
}
Loading