Skip to content

Commit

Permalink
[장바구니 미션 Step 1] 코난(윤정민) 미션 제출합니다. (#170)
Browse files Browse the repository at this point in the history
* chore: 개발 환경 설정

* docs: 기능 요구사항 작성

* chore: styled-component, ts-jest 환경 설치

* chore: 목데이터 추가

* feat: Global Style 추가

* chore: 타입스크립트 module 선언

* feat: Router, RecoilRoot 적용

* feat: GlobalStyle 적용

* chore: 카트 이미지 추가

* feat: cart, product 타입 선언

* feat: cartState, totalAmountState 선언

* feat: Header 컴포넌트 구현

* feat: array 유틸함수, useCart 커스텀 훅 구현

* test: useCart 훅 테스트

* feat: ProductItem 컴포넌트 구현

* feat: ProductList 컴포넌트 구현

* feat: ProductPage 구현

* refactor: console.log 삭제

* feat: NotFoundPage 구현

* feat: product fetch 구현

* feat: LoadingPage 구현

* feat: ErrorBoundary 구현

* feat: Suspense, Errorboundary 적용

* test: cypress e2e 테스트 작성

* feat: LocalStorage 기능 추가

* chore: 배포 환경 설정

* refactor: 불필요한 기본값 및 localStorage 유틸 삭제

* feat: Header에 카트 이미지 및 링크 추가

* feat: 장바구니에 들어간 상품 종류로 수정

* style: Pretendard 폰트 추가

* refactor: products를 목데이터로 교체

* feat: cart에서 quantity를 가져오는 selectorFamily 구현

* refactor: toSpliced 활용

* style: Header및 ProductList 스타일 수정

* refactor: LocalStorageKey 상수 추출

* feat: Counter 컴포넌트 구현

* chore: mock data 수정

* style: Header, ProductList, ProductItem 스타일 수정
  • Loading branch information
cruelladevil committed May 18, 2023
1 parent 0191f7c commit 168c2ee
Show file tree
Hide file tree
Showing 40 changed files with 23,826 additions and 0 deletions.
23 changes: 23 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# production
/build

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*
40 changes: 40 additions & 0 deletions REQUIREMENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
## 기능 목록

- Header 구현

- 장바구니에 담긴 상품 전체의 갯수 구현

- 상품 목록 구현

- 상품 목록 레이아웃 구현 (grid)
- mock 데이터를 기반으로 정렬하기

- 상품 아이템 구현

- img 파일 import 하기

- 장바구니 버튼
- 장바구니 버튼을 클릭하면 상품이 1개가 담긴다.
- 장바구니 버튼이 숫자 인풋으로 바뀐다.
- 장바구니에 담을 상품의 갯수를 조절할 수 있다.

## mock 데이터

- Products

```json
[
{
"id": 1,
"name": "치킨",
"price": 10000,
"imageUrl": "<http://example.com/chicken.jpg>"
},
{
"id": 2,
"name": "피자",
"price": 20000,
"imageUrl": "<http://example.com/pizza.jpg>"
}
]
```
16 changes: 16 additions & 0 deletions cypress.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { defineConfig } from "cypress";

export default defineConfig({
component: {
devServer: {
framework: "create-react-app",
bundler: "webpack",
},
},

e2e: {
setupNodeEvents(on, config) {
// implement node event listeners here
},
},
});
30 changes: 30 additions & 0 deletions cypress/e2e/fetchProduct.cy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
describe('장바구니 e2e 테스트', () => {
beforeEach(() => {
cy.intercept(
{
method: 'GET',
url: /^https:\/\/json-server-4140.onrender.com\/cart-itmes\/?.*/,
},
{
fixture: 'mockProducts.json',
},
).as('fetchProduct');

cy.visit('http://localhost:3000/');
});

it('페이지에 접속하면 상품 목록(목 데이터) 8개를 렌더링한다.', () => {
cy.get('[data-cy=product-item]').should('have.length', 8);
});

it('장바구니 버튼을 클릭하면 상품을 장바구니에 1개 추가한다.', () => {
cy.get('[data-cy=add-cart').first().click();
cy.get('[data-cy=cart-amount').should('contain', 1);
});

it('장바구니 버튼에 상품 개수를 12개로 수정 시 헤더의 장바구니에 개수가 반영된다.', () => {
cy.get('[data-cy=add-cart').first().click();
cy.get('input').type('2');
cy.get('[data-cy=cart-amount').should('contain', 12);
});
});
50 changes: 50 additions & 0 deletions cypress/fixtures/mockProducts.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
[
{
"id": 1,
"name": "정사각(420ml)",
"price": 43400,
"imageUrl": "https://item.kakaocdn.net/do/d0abc6fe74e616536cf07626699bbc707154249a3890514a43687a85e6b6cc82"
},
{
"id": 2,
"name": "밀크티(370ml)",
"price": 73400,
"imageUrl": "https://item.kakaocdn.net/do/d0abc6fe74e616536cf07626699bbc707154249a3890514a43687a85e6b6cc82"
},
{
"id": 3,
"name": "정사각(370ml)",
"price": 41000,
"imageUrl": "https://item.kakaocdn.net/do/d0abc6fe74e616536cf07626699bbc707154249a3890514a43687a85e6b6cc82"
},
{
"id": 4,
"name": "납작(450ml)",
"price": 39900,
"imageUrl": "https://item.kakaocdn.net/do/d0abc6fe74e616536cf07626699bbc707154249a3890514a43687a85e6b6cc82"
},
{
"id": 5,
"name": "단지(480ml)",
"price": 38000,
"imageUrl": "https://item.kakaocdn.net/do/d0abc6fe74e616536cf07626699bbc707154249a3890514a43687a85e6b6cc82"
},
{
"id": 6,
"name": "납작(260ml)",
"price": 40200,
"imageUrl": "https://item.kakaocdn.net/do/d0abc6fe74e616536cf07626699bbc707154249a3890514a43687a85e6b6cc82"
},
{
"id": 7,
"name": "원형(500ml)",
"price": 50200,
"imageUrl": "https://item.kakaocdn.net/do/d0abc6fe74e616536cf07626699bbc707154249a3890514a43687a85e6b6cc82"
},
{
"id": 8,
"name": "원형(600ml)",
"price": 62400,
"imageUrl": "https://item.kakaocdn.net/do/d0abc6fe74e616536cf07626699bbc707154249a3890514a43687a85e6b6cc82"
}
]
25 changes: 25 additions & 0 deletions cypress/support/commands.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// ***********************************************
// This example commands.js 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) => { ... })
20 changes: 20 additions & 0 deletions cypress/support/e2e.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// ***********************************************************
// This example support/e2e.js 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')
13 changes: 13 additions & 0 deletions cypress/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"extends": "../tsconfig.json",
"include": ["**/*.ts", "../cypress.d.ts", "e2e/fetchProduct.cy.tsx"],
"compilerOptions": {
"lib": ["es5", "dom"],
"types": ["cypress", "node"],
"target": "es5",
"jsx": "preserve",
"isolatedModules": false,
"allowJs": true,
"noEmit": true
}
}
5 changes: 5 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'jsdom',
};

0 comments on commit 168c2ee

Please sign in to comment.