Skip to content

Commit

Permalink
[2단계 - 자주 가는 음식점] 센트(김영우) 미션 제출합니다 (#79)
Browse files Browse the repository at this point in the history
* refactor: form 초기화 방식 변경

* feat: 자주 가는 음식점 식별용 데이터 구조 추가

* fix: 음식점 카드 렌더링 오류 수정

* feat: 자주 가는 음식점 필터링 기능 추가

* feat: 디테일 모달 기능 추가

* feat: 레스토랑 삭제 기능 추가

* feat: 디테일 모달 닫기 기능 추가

* test: e2e 테스트 추가

* feat: 디테일 모달에서 즐겨찾기 변경 기능 추가

* fix: import 경로 오류 수정

* test: e2e 테스트 localstorage 더미 데이터에 id 추가

* refactor: string 반환 메서드의 반환 값 타입 단언부 수정

as string => ?? ''

* test: 반복되는 초기 설정 부분 beforeEach로 병합

* test: 정렬 기능 테스트시 두 가지 정렬 기준 모두 테스트 하도록 수정

* test: submit 메서드 사용 및 필수 입력 값 미 입력시 리스트에 추가되지 않는 것 확인부 추가

* test: 마크업 구조에 의존하는 쿼리 수정

* test: 필수값 미입력 테스트시 모달의 닫힘 여부를 판단하는 대상 변경

'.modal-container' => 'form'

* fix: 사용하지 않는 메서드 삭제

* refactor: id를 통해 restaurant를 찾을 때 Array.prototype.find 메서드 사용하도록 수정

* test: 더미데이터 수정에도 렌더링 테스트가 안정적으로 수행되도록 수정

즐겨찾기 필터링 테스트: like attribute가 true인지 여부 판별로 테스트
카테고리 필터링 테스트: category attribute가 선택한 카테고리와 일치하는지 여부 판별로 테스트

* refactor: 불필요한 타입 단언 최소화
  • Loading branch information
kyw0716 authored Mar 14, 2023
1 parent 42c7c87 commit dbcf155
Show file tree
Hide file tree
Showing 21 changed files with 675 additions and 32 deletions.
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
},
},
});
175 changes: 175 additions & 0 deletions cypress/e2e/spec.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
const restaurants = [
{
category: "한식",
name: "한식집1",
distance: "5",
like: "true",
description:
"한식집1 더미 설명입니다. 한식집1 더미 설명입니다. 한식집1 더미 설명입니다.",
link: "",
id: "1",
},
{
category: "한식",
name: "한식집2",
distance: "10",
like: "true",
description:
"한식집2 더미 설명입니다. 한식집2 더미 설명입니다. 한식집2 더미 설명입니다.",
link: "",
id: "2",
},
{
category: "중식",
name: "중식집1",
distance: "15",
like: "false",
description:
"중식집1 더미 설명입니다. 중식집1 더미 설명입니다. 중식집1 더미 설명입니다.",
link: "",
id: "3",
},
{
category: "양식",
name: "양식집1",
distance: "20",
like: "true",
description:
"양식집1 더미 설명입니다. 양식집1 더미 설명입니다. 양식집1 더미 설명입니다.",
link: "",
id: "4",
},
{
category: "일식",
name: "일식집1",
distance: "30",
like: "false",
description:
"일식집1 더미 설명입니다. 일식집1 더미 설명입니다. 일식집1 더미 설명입니다.",
link: "",
id: "5",
},
];

beforeEach(() => {
cy.visit("http://localhost:8080/", {
onBeforeLoad(win) {
win.localStorage.setItem("restaurants", JSON.stringify(restaurants));
},
});
});

describe("음식점 추가 모달 기능 테스트", () => {
it("값 입력 후 제출시 화면에 추가된 음식점이 렌더링 된다.", () => {
cy.contains("한식집3").should("not.exist");

cy.get(".gnb__button").click();

cy.get("#category").select("한식");
cy.get("#name").type("한식집3");
cy.get("#distance").select("5");
cy.get("#description").type(
"한식집3 더미 설명입니다. 한식집3 더미 설명입니다. 한식집3 더미 설명입니다."
);

cy.get("form").submit();

cy.contains("한식집3").should("be.visible");
});

it("필수 값을 입력하지 않고 제출시 모달이 열린채로 유지되며, 제출되지 않는다.", () => {
cy.get(".gnb__button").click();

cy.get("#name").type("한식집3");
cy.get("#distance").select("5");
cy.get("#description").type(
"한식집3 더미 설명입니다. 한식집3 더미 설명입니다. 한식집3 더미 설명입니다."
);

cy.get(".submit-button").click();

cy.get("form").should("be.visible");
cy.contains("한식집3").should("not.exist");
});
});

describe("음식점 리스트 렌더링 테스트", () => {
it("카테고리 필터 선택시 해당하는 카테고리를 가진 음식점만 렌더링 된다.", () => {
cy.get("#category-filter").select("한식");

cy.get(".restaurant-list").should((elem) =>
elem.children().each((_, li) => {
expect(li.getAttribute("category")).to.equal("한식");
})
);
});

it("정렬 필터 선택시 해당 정렬 기준에 의해 렌더링 된다.", () => {
const sortedTitleByDistance = [
"한식집1",
"한식집2",
"중식집1",
"양식집1",
"일식집1",
];
const sortedTitleByName = [
"양식집1",
"일식집1",
"중식집1",
"한식집1",
"한식집2",
];

cy.get("#sorting-filter").select("distance");

cy.get(".restaurant-list").should((elem) => {
elem.children().each((index, li) => {
expect(li.querySelector(".restaurant__name").innerText).to.equal(
sortedTitleByDistance[index]
);
});
});

cy.get("#sorting-filter").select("name");

cy.get(".restaurant-list").should((elem) => {
elem.children().each((index, li) => {
expect(li.querySelector(".restaurant__name").innerText).to.equal(
sortedTitleByName[index]
);
});
});
});

it("즐겨찾기 탭 클릭시 즐겨찾기한 음식점만 렌더링 된다.", () => {
cy.get("#like-button").click();

cy.get(".restaurant-list").should((elem) =>
elem.children().each((_, li) => {
expect(li.getAttribute("like")).to.equal("true");
})
);
});
});

describe("음식점 상세 모달 기능 테스트", () => {
it("음식점 카드 클릭시 해당 음식점의 상세 모달이 렌더링 된다.", () => {
cy.contains("일식집1").click();

cy.get("form").should("not.be.visible");
cy.get(".modal-detail").should("be.visible");
cy.get(".modal-detail").contains("일식집1").should("be.visible");
});

it("삭제하기 버튼 클릭시 음식점 리스트에서 해당 항목이 삭제된다.", () => {
cy.contains("일식집1").click();

cy.contains("삭제하기").click();

cy.get(".restaurant-list").contains("한식집1").should("be.visible");
cy.get(".restaurant-list").contains("한식집2").should("be.visible");
cy.get(".restaurant-list").contains("양식집1").should("be.visible");
cy.get(".restaurant-list").contains("중식집1").should("be.visible");
cy.get(".restaurant-list").contains("일식집1").should("not.exist");
});
});
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')
Loading

0 comments on commit dbcf155

Please sign in to comment.