Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[2단계 - 자주 가는 음식점] 엽토(김건엽) 미션 제출합니다. #71

Merged
merged 51 commits into from
Mar 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
946eb69
refactor: add 메서드 실행시에 localStorage 갱신해줬던 것을 새로고침 시 갱신해주도록 변경하다
yeopto Mar 7, 2023
3f8bfd2
feat: 레스토랑 정보에 즐겨찾기 여부를 확인할 수 있는 key값을 추가하다
yeopto Mar 7, 2023
ad6b877
feat: 자주가는 음식점을 등록, 취소하는 기능을 구현하다
yeopto Mar 8, 2023
316de3d
test: 음식점이 즐겨찾기 되어있는지 확인하는 테스트 코드를 작성하다
yeopto Mar 8, 2023
c9bfa44
feat: 자주가는 음식점 리스트 가져오는 기능을 구현하다
yeopto Mar 8, 2023
96e7387
test: 즐겨찾기 된 음식점만 가져오는지 확인하는 테스트 코드를 작성하다
yeopto Mar 8, 2023
1782ce6
feat: 음식점을 삭제하는 기능을 구현하다
yeopto Mar 8, 2023
99e1565
test: 음식점을 삭제하는 테스트 코드를 작성하다
yeopto Mar 8, 2023
52f1c3f
feat: tabbar 컴포넌트를 만들다
yeopto Mar 8, 2023
d667ee1
style: tabbar style을 지정하다
yeopto Mar 8, 2023
39d6c26
refactor: 필터 템플릿 삽입 위치를 변경하다
yeopto Mar 8, 2023
75bd7c6
feat: 탭바 이벤트를 설정하다
yeopto Mar 9, 2023
9db32e7
feat: 필터를 열고 닫는 기능을 구현하다
yeopto Mar 9, 2023
49c77c8
feat: 즐겨찾기 목록을 렌더링하는 기능을 구현하다
yeopto Mar 9, 2023
05a6a30
style: 필터 스타일을 추가하다
yeopto Mar 9, 2023
237a8b2
feat: 레스토랑 리스트 스타일을 변경하다
yeopto Mar 9, 2023
0181c70
feat: 즐겨찾기 UI와 기능을 구현하다
yeopto Mar 9, 2023
b9a0e82
refactor: Modal 추상 클래스를 만들어서 상속하게 만들다
yeopto Mar 9, 2023
01af69d
test: 로직 변경에 따라 테스트 코드를 수정하다
yeopto Mar 9, 2023
4f3c661
refactor: 부모 클래스에 있는 메서드를 삭제하다
yeopto Mar 9, 2023
2cc4c12
feat: 음식점 정보에 id값을 추가하다
yeopto Mar 10, 2023
225c901
refactor: Header 이벤트를 수정하다
yeopto Mar 10, 2023
7ba378f
feat: RestaurantItem 이벤트를 추가하다
yeopto Mar 10, 2023
e12a5a2
refactor: AddModal 렌더링 로직을 변경하다
yeopto Mar 10, 2023
afd8105
refactor: Modal 추상컴포넌트를 수정하다
yeopto Mar 10, 2023
7ed61eb
feat: 음식점 정보 모달 컴포넌트를 생성하다
yeopto Mar 10, 2023
3b723fa
style: 음식점 정보 스타일을 입히다
yeopto Mar 10, 2023
be7722e
feat: 이벤트 핸들링 로직을 추가하다
yeopto Mar 10, 2023
cc74d74
refactor: item 이벤트를 list로 옮기다
yeopto Mar 10, 2023
6920ec8
refactor: 즐겨찾기 아이콘에 id를 추가하다
yeopto Mar 10, 2023
2a99cb2
refactor: item 이벤트를 삭제하다
yeopto Mar 10, 2023
6c78c6d
refactor: alt값을 id로 변경하다
yeopto Mar 10, 2023
d5c869d
refactor: itemEvent를 수정하다
yeopto Mar 10, 2023
6c2fc95
feat: infoModal에서 즐겨찾기 기능을 만들다
yeopto Mar 11, 2023
85d5125
refactor: 필요없는 모듈선언을 지우다
yeopto Mar 11, 2023
3c10bc8
feat: 삭제하기 기능을 만들다
yeopto Mar 11, 2023
7fa1d72
test: 테스트 코드를 수정하다
yeopto Mar 11, 2023
05d40ab
test: e2e 테스트 코드를 작성하다
yeopto Mar 11, 2023
4b60ab5
docs: 2단계 미션 정보를 작성하다
yeopto Mar 11, 2023
2511636
chore: Mock 데이터를 만들다
yeopto Mar 11, 2023
c8fbfa3
refactor: 전체 로직을 수정하다
yeopto Mar 13, 2023
50ea26a
style: 반복되는 선언 삭제하다
yeopto Mar 13, 2023
fb59a09
refactor: 필요없는 return문 삭제하다
yeopto Mar 13, 2023
a02e386
refactor: addModal로직을 수정하다
yeopto Mar 13, 2023
1622f1a
refactor: InfoModal 로직을 수정하다
yeopto Mar 13, 2023
120c9cd
refactor: RestaurantsList 로직을 수정하다
yeopto Mar 13, 2023
180dfb6
refactor: RestaurantItem 로직을 수정하다
yeopto Mar 13, 2023
cce27b1
refactor: index.js를 수정하다
yeopto Mar 13, 2023
68f4756
test: Test 코드를 수정하다
yeopto Mar 13, 2023
c68fd4e
refactor: alt값을 사용한 것을 id로 변경하다
yeopto Mar 15, 2023
5faf628
refactor: 메서드명을 수정하다
yeopto Mar 15, 2023
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
22 changes: 19 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,30 @@
- 입력값이 잘못되었을 때 사용자에게 알려주는 방식은 자유롭게 구현한다.
- 새로고침해도 추가한 음식점 정보들이 유지되어야 한다.

## 실행 방법

# 2단계 - 자주 가는 음식점

## 🎯 기능 요구 사항

음식점의 상세 정보를 확인하고, 자주 가는 음식점으로 지정할 수 있는 기능을 추가한다.

- 음식점 상세 정보를 확인할 수 있다.
- 카테고리, 이름, 거리, 설명, 참고 링크를 확인할 수 있다.
- 음식점을 삭제할 수 있다.
- 자주 가는 음식점을 추가하고 목록으로 확인할 수 있다.
- 음식점 목록에서 자주 가는 음식점을 추가할 수 있다.
- 음식점 상세 정보에서 자주 가는 음식점으로 추가할 수 있다.
- 자주 가는 음식점 탭에서 추가한 음식점 목록을 확인할 수 있다.
- 새로고침해도 추가한 정보들이 유지되어야 한다.

# 실행 방법

```

npm run start

```

## 배포 링크
# 배포 링크

[링크](https://yeopto.github.io/javascript-lunch/dist/)
[링크](https://yeopto.github.io/javascript-lunch)
33 changes: 23 additions & 10 deletions __tests__/render.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@
* @jest-environment jsdom
*/
import Header from '../src/components/Header';
import Modal from '../src/components/Modal';
import AddModal from '../src/components/modal/AddModal';
import RestaurantFilter from '../src/components/RestaurantFilter';
import RestaurantsList from '../src/components/RestaurantsList';
import Restaurants from '../src/domain/Restaurants';
import InfoModal from '../src/components/modal/InfoModal';
import Tabbar from '../src/components/Tabbar';
import { $ } from '../src/utils/common';

import { screen, fireEvent } from '@testing-library/dom';
import '@testing-library/jest-dom';
Expand All @@ -17,6 +20,7 @@ describe('컴포넌트 단위 테스트', () => {
distance: 5,
description: 'undefined',
link: 'undefined',
id: 'a1234',
};

const doriRestaurant = {
Expand All @@ -25,6 +29,7 @@ describe('컴포넌트 단위 테스트', () => {
distance: 15,
description: 'undefined',
link: 'undefined',
id: 'a1235',
};

const restaurants = new Restaurants([yeoptoRestaurant, doriRestaurant]);
Expand All @@ -34,18 +39,26 @@ describe('컴포넌트 단위 테스트', () => {
<main></main>
`;

const $header = document.querySelector('.gnb');
const $main = document.querySelector('main');
const $header = $('.gnb');
const $main = $('main');

const header = new Header($header);
const modal = new Modal($main);
const tabbar = new Tabbar($main);
const restaurantFilter = new RestaurantFilter($main);
const restaurantsList = new RestaurantsList($main, restaurants);
const infoModal = new InfoModal(restaurants);
const restaurantsList = new RestaurantsList($main, restaurants, infoModal);
const addModal = new AddModal($main, restaurants, restaurantsList);

header.setEvent(modal.toggleModalOpen.bind(modal));
modal.setSubmitEvent(restaurantsList.setState.bind(restaurantsList), restaurants.add.bind(restaurants));
modal.setModalCloseEvent();
restaurantFilter.setEvent(restaurantsList.render.bind(restaurantsList));
header.setEvent(addModal.render.bind(addModal));

tabbar.setEvent(
restaurantsList.renderSortedList.bind(restaurantsList),
restaurantsList.renderFavoriteItem.bind(restaurantsList),
restaurantFilter.openFilter.bind(restaurantFilter),
restaurantFilter.closeFilter.bind(restaurantFilter)
);

restaurantFilter.setEvent(restaurantsList.renderSortedList.bind(restaurantsList));

test('음식점 리스트에 음식점들이 렌더링이 됐는지 확인한다.', () => {
const yeopto = screen.getByText('엽토네 떡볶이');
Expand All @@ -57,7 +70,7 @@ restaurantFilter.setEvent(restaurantsList.render.bind(restaurantsList));

test('모달 창이 정상적으로 팝업되는 지 확인한다.', () => {
fireEvent.click(screen.getByAltText('음식점 추가'));

expect(screen.getByText('새로운 음식점')).toBeInTheDocument();
});
});
24 changes: 24 additions & 0 deletions __tests__/restaurants.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,35 @@ import { Restaurant } from '../src/types/Types';

describe('Restaurants 도메인 테스트', () => {
const yeoptoRestaurant: Restaurant = {
id: '1123124',
category: '기타',
name: '엽토네 떡볶이',
distance: 5,
description: 'undefined',
link: 'undefined',
favorites: false,
};

const doriRestaurant: Restaurant = {
id: '1123125',
category: '한식',
name: '도리네 집밥',
distance: 15,
description: 'undefined',
link: 'undefined',
favorites: false,
};

const restaurants = new Restaurants([yeoptoRestaurant, doriRestaurant]);

const gongwonRestaurant: Restaurant = {
id: '1123126',
category: '일식',
name: '공원네 초밥집',
distance: 10,
description: 'undefined',
link: 'undefined',
favorites: false,
};

test('음식점 목록을 추가하는 기능 테스트', () => {
Expand Down Expand Up @@ -59,4 +65,22 @@ describe('Restaurants 도메인 테스트', () => {
test('음식점을 분류 카테고리에 따라 필터링 하는 기능 테스트', () => {
expect(restaurants.filterByCategory('한식', restaurants.restaurantsList)[0].name).toBe('도리네 집밥');
});

test('음식점이 즐겨찾기 되어있는지 확인한다', () => {
restaurants.setFavoriteState(yeoptoRestaurant.id);

expect(yeoptoRestaurant.favorites).toBe(true);
});

test('즐겨찾기 된 음식점만 가져오는지 확인한다', () => {
const favoriteRestaurantList = restaurants.getFavoriteRestaurantList();

expect(favoriteRestaurantList[0].name).toBe('엽토네 떡볶이');
});

test('음식점을 삭제하는지 확인한다', () => {
restaurants.remove(doriRestaurant.id);

expect(restaurants.restaurantsList.length).toBe(2);
});
});
9 changes: 9 additions & 0 deletions cypress.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { defineConfig } from "cypress";

export default defineConfig({
e2e: {
setupNodeEvents(on, config) {
// implement node event listeners here
},
},
});
45 changes: 45 additions & 0 deletions cypress/e2e/lunch.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
describe('점심 뭐 먹지 e2e 테스트', () => {
it('음식점 추가, 삭제, 필터링, 즐겨찾기 테스트', () => {
cy.visit('http://localhost:8080');
cy.viewport(500, 1000);

// 음식점 추가
cy.get('.gnb__button').click();
cy.get('#category').select('한식');
cy.get('#name').type('공원네 밥집');
cy.get('#distance').select('10분 내');
cy.get('#description').type('집 앞 분식점');
cy.get('form .button--primary').click();
Comment on lines +7 to +12

Choose a reason for hiding this comment

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

이 형식이 계속해서 반복으로 나타나는데 공통함수로 빼보는건 어떨까요?

Copy link
Author

Choose a reason for hiding this comment

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

이 부분은 다음 미션때 적용해보겠습니다!


cy.get('.gnb__button').click();
cy.get('#category').select('양식');
cy.get('#name').type('제레미 스파게티');
cy.get('#distance').select('20분 내');
cy.get('#description').type('야무짐');
cy.get('form .button--primary').click();

cy.get('.gnb__button').click();
cy.get('#category').select('중식');
cy.get('#name').type('사천성');
cy.get('#distance').select('15분 내');
cy.get('#description').type('얼큰함');
cy.get('form .button--primary').click();

// 음식점 삭제
cy.contains('공원네 밥집').click();
cy.contains('삭제하기').click();

// 음식점 필터링
cy.get('#sorting-filter').select('거리순');

// 리스트 확인
cy.get('.restaurant-list').first().should('contain.text', '사천성');

// 즐겨찾기 추가
cy.contains('사천성').parentsUntil('.restaurant-list').children('.favorite-icon').click();
cy.contains('자주 가는 음식점').click();

// 자주가는 음식점 리스트 확인
cy.get('.restaurant-list').first().should('contain.text', '사천성');
});
});
5 changes: 5 additions & 0 deletions cypress/fixtures/example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
}
37 changes: 37 additions & 0 deletions cypress/support/commands.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/// <reference types="cypress" />
// ***********************************************
// This example commands.ts shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add('login', (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
//
// declare global {
// namespace Cypress {
// interface Chainable {
// login(email: string, password: string): Chainable<void>
// drag(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
// dismiss(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
// visit(originalFn: CommandOriginalFn, url: string, options: Partial<VisitOptions>): Chainable<Element>
// }
// }
// }
20 changes: 20 additions & 0 deletions cypress/support/e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// ***********************************************************
// This example support/e2e.ts is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************

// Import commands.js using ES2015 syntax:
import './commands'

// Alternatively you can use CommonJS syntax:
// require('./commands')
10 changes: 9 additions & 1 deletion docs/REQUIREMENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,16 @@

## Domain

- [x] 음식점 목록을 확인 할 수 있는 기능
### 1단계

- [x] 음식점 목록을 확인할 수 있는 기능
- [x] 카테고리 별로 필터링 하는 기능
- [x] 이름 순으로 정렬할 수 있는 기능
- [x] 거리 순으로 정렬할 수 있는 기능
- [x] 음식점 목록에 새로운 음식점을 추가하는 기능 (카테고리, 이름, 거리는 입력 필수)

### 2단계

- [x] 자주가는 음식점을 등록, 취소하는 기능
- [x] 자주가는 음식점 리스트 가져오는 기능
- [x] 음식점을 삭제할 수 있는 기능
6 changes: 4 additions & 2 deletions src/components/Header.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ class Header {
this.$target.insertAdjacentHTML('afterbegin', this.template());
}

setEvent(callback) {
setEvent(addModalRender) {
const addButton = $('.gnb__button');
addButton.addEventListener('click', callback);
addButton.addEventListener('click', () => {
addModalRender();
});
}
}

Expand Down
Loading