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단계 - 자판기] 병민(윤병인) 미션 제출합니다. #66

Merged
merged 118 commits into from
Apr 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
118 commits
Select commit Hold shift + click to select a range
3d96d4c
:truck: chore(setup): 커밋 린트 설정
airman5573 Mar 23, 2022
9b4b681
:truck: chore(setup): webpack설정
airman5573 Mar 23, 2022
3271886
:truck: chore(setup): lint와 formatter설정
airman5573 Mar 23, 2022
c7f10de
:truck: chore(setup): dist폴더 추적 중단
airman5573 Mar 23, 2022
a17868c
:memo: docs(todo): 구현할 기능 정리
jhy979 Mar 23, 2022
a0a4316
:recycle: refactor(typo): typo scope 추가
jhy979 Mar 23, 2022
e6b3bd9
:recycle: refactor(typo): prettier 적용
jhy979 Mar 23, 2022
d7373e9
:truck: chore(setup): 함수 15줄 제한 해제
airman5573 Mar 23, 2022
8f52110
:sparkles: feat(ui): component 생성
airman5573 Mar 23, 2022
b4a0297
:truck: chore(setup): typescript target 설정
jhy979 Mar 23, 2022
f1be242
:truck: chore(setup): commit scope flux 추가
jhy979 Mar 23, 2022
bfc5093
:sparkles: feat(flux): store 생성
jhy979 Mar 23, 2022
0ca6b34
:sparkles: feat(flux): flux 패턴 생성
jhy979 Mar 24, 2022
02c5ede
:truck: chore(setup): 명시적 any 선언을 허용한다
airman5573 Mar 24, 2022
6a7fc05
:sparkles: feat(decorator): custom element decorator와 event bind deco…
airman5573 Mar 24, 2022
c289836
:sparkles: feat(template): 상품관리탭 template, style 추가
jhy979 Mar 25, 2022
df84428
:truck: chore(setup): 커밋 스코프 추가
airman5573 Mar 26, 2022
5e7798a
:recycle: refactor(component): 컴포넌트 분리
airman5573 Mar 26, 2022
29c336c
:truck: chore(setup): git에서 추적하지 않을 파일 추가
airman5573 Mar 26, 2022
68a57ef
:sparkles: feat(ui): 상품 관리 탭에서 상품을 추가한다
airman5573 Mar 26, 2022
d3cda8a
:sparkles: feat(component): 상품관리탭에서 상품 수정 기능 추가
jhy979 Mar 26, 2022
49923c6
:sparkles: feat(component): 상품 관리 탭에서 상품 삭제
airman5573 Mar 26, 2022
80b19e8
:recycle: refactor(component): 반복되는 코드 함수로 분리
airman5573 Mar 26, 2022
b0ad8c6
:recycle: refactor(cleanup): 불필요한 코드 삭제
airman5573 Mar 26, 2022
ab5221a
:sparkles: feat(component): 상품 수정 삭제 기능 추가
airman5573 Mar 27, 2022
1b2d9d9
:recycle: refactor(ui): 상품 추가 필드 초기화 및 포커싱
airman5573 Mar 27, 2022
52b590b
:sparkles: feat(component): 잔돈 충전 기능 추가
jhy979 Mar 27, 2022
3f3ed7d
:recycle: refactor(cleanup): 사용하지 않는 type 삭제
airman5573 Mar 27, 2022
146aefa
:recycle: refactor(cleanup): 불필요한 eslint disable comment 삭제
airman5573 Mar 27, 2022
62458e4
:sparkles: feat(routing): 라우팅 기능을 추가한다
airman5573 Mar 27, 2022
fbb3d15
:construction_worker: build: netlify 설정 파일 추가
airman5573 Mar 27, 2022
870263d
:recycle: refactor(cleanup): 더미 데이터 삭제
airman5573 Mar 27, 2022
f0ffe42
:bug: fix(component): 동적으로 컴포넌트 그릴시 event가 재등록 되지 않는 문제 해결
airman5573 Mar 27, 2022
99a449e
:sparkles: feat(component): 상품 구매 탭 임시 추가 및 라우팅 구현
airman5573 Mar 28, 2022
7380b27
:bug: fix(component): 페이지 이동 시 nav 배경색이 변경되지 않는 에러 수정
jhy979 Mar 28, 2022
7d5da7e
:recycle: refactor(routing): 라우팅 시 state값을 기준으로 각 컴포넌트 내 동적 렌더링
jhy979 Mar 28, 2022
26718e1
:sparkles: feat(util): 객체 deep copy 유틸 함수 추가
jhy979 Mar 28, 2022
6c371e5
:recycle: refactor(flux): state을 얕은 복사에서 깊은 복사로 변경
jhy979 Mar 28, 2022
f565230
:lipstick: style(ui): 1000이상 단위 콤마 추가
jhy979 Mar 28, 2022
dbb6fef
:recycle: refactor(cleanup): 사용하지 않는 모듈 import 제거
jhy979 Mar 28, 2022
eb3d0fe
:bug: fix(routing): 라우팅 발생 전 Component 삽입
jhy979 Mar 28, 2022
9824bc7
:recycle: refactor(typo): config 파일에 lint 적용
jhy979 Mar 28, 2022
bab412b
:white_check_mark: test(validation): validation test 추가
jhy979 Mar 28, 2022
6b14bb0
:recycle: refactor(cleanup): 불필요한 모듈 import 제거
jhy979 Mar 28, 2022
d7e0fdc
:recycle: refactor: 상수 처리
jhy979 Mar 28, 2022
84da723
:white_check_mark: test(validation): 충전 금액 테스트 추가
jhy979 Mar 28, 2022
7f6920c
:recycle: refactor: 에러 메세지에 들어간 숫자를 상수로 대체
jhy979 Mar 28, 2022
695df52
:bug: fix(ui): 엔터 클릭으로 form 제출 방지
jhy979 Mar 28, 2022
07cb5e0
:recycle: refactor(cleanup): 불필요한 코드 삭제
airman5573 Mar 30, 2022
93acdb2
:recycle: refactor(cleanup): 관련있는 상수들 그룹핑
airman5573 Mar 30, 2022
811abd6
:recycle: refactor(logic): 상품 필터링 로직 단순화
airman5573 Mar 30, 2022
9e413e9
:recycle: refactor(logic): 3항 연산자 사용시 불필요한 !(not) 제거
airman5573 Mar 30, 2022
44c33b1
:recycle: refactor: 가독성 향상
airman5573 Mar 30, 2022
fd29999
:bug: fix(component): navigation link 활성화 표시 중복 제거
airman5573 Mar 30, 2022
43fbac8
:recycle: refactor(component): template을 분리한다
airman5573 Mar 31, 2022
db72ee1
:lipstick: style(ui): 상품 수정시 나오는 input의 간격 조정
airman5573 Mar 31, 2022
e176b61
:recycle: refactor(readability): reducer 가독성 향상
airman5573 Mar 31, 2022
025f449
:lipstick: style(ui): 상품 입력 폼에 라벨 추가
airman5573 Mar 31, 2022
9b4da44
:sparkles: feat(component): 상품 구매시 필요한 금액을 입력하는 폼 추가
airman5573 Apr 2, 2022
4f18be5
:recycle: refactor(cleanup): 중복 코드 삭제
airman5573 Apr 2, 2022
97ca1ed
:recycle: refactor: 관련 있는 코드끼리 묶는다
airman5573 Apr 2, 2022
892be56
:bug: fix(flux): switch에 break을 추가한다
airman5573 Apr 2, 2022
b0e07ff
:sparkles: feat(component): 구매 가능 상품 리스트를 보여준다
airman5573 Apr 2, 2022
e860bbb
:bug: fix(flux): switch에 break를 추가한다
airman5573 Apr 2, 2022
6848537
:sparkles: feat(component): 잔돈 반환하는 컴포넌트를 추가한다
airman5573 Apr 2, 2022
a90d1b3
:bug: fix(ui): 500원 100원 50원 10원 순으로 보여준다
airman5573 Apr 3, 2022
40a929e
:memo: docs(todo): 할일 목록 추가
airman5573 Apr 3, 2022
302e398
:memo: docs(todo): 회원 기능 to do list를 추가한다
airman5573 Apr 3, 2022
a526475
:recycle: refactor: 관련있는 파일을 묶어놓는다
airman5573 Apr 3, 2022
ba79542
:bug: fix(ui): 버튼 문구를 수정한다
airman5573 Apr 3, 2022
b57a287
:recycle: refactor: router
airman5573 Apr 3, 2022
80b25be
:sparkles: feat(ui): 로그인 페이지를 추가한다
airman5573 Apr 3, 2022
a695d5b
:recycle: refactor(cleanup): 불필요한 margin을 삭제한다
airman5573 Apr 3, 2022
43f983b
:recycle: refactor(style): n번째가 아닌 마지막 요소를 찝는다
airman5573 Apr 3, 2022
c4d0597
:bug: fix(style): 좌우 패딩을 피그마에 맞게 수정한다
airman5573 Apr 3, 2022
52d5212
:bug: fix(ui): 라벨을 클릭하면 input에 포커스가 가도록 수정한다
airman5573 Apr 3, 2022
359bf71
:memo: docs(todo): 할일 목록을 삭제한다
airman5573 Apr 3, 2022
f23cfdf
:memo: docs(todo): 할일 목록을 삭제한다
airman5573 Apr 3, 2022
14be954
:sparkles: feat(page): 회원가입 페이지를 추가한다
airman5573 Apr 4, 2022
14421ca
:sparkles: feat: 회원가입 기능을 추가한다
airman5573 Apr 4, 2022
8d82e7c
:sparkles: feat: 로그인 기능을 추가한다
airman5573 Apr 4, 2022
10003c9
:sparkles: feat(ui): input에 선택적으로 disabled option을 준다
airman5573 Apr 5, 2022
859b44a
:sparkles: feat(ui): 로그인 여부에 따라 선택적으로 View를 보여준다
airman5573 Apr 5, 2022
58ad428
:bug: fix(validation): 비밀번호 길이를 체크하는 유효성 검사를 수정한다
airman5573 Apr 5, 2022
4212ae8
:sparkles: feat(page): 회원 정보 수정 페이지를 추가한다
airman5573 Apr 5, 2022
5e25d24
:recycle: refactor(router): 라우팅 방식을 변경한다
airman5573 Apr 5, 2022
89e27be
:sparkles: feat(ui): 다른 페이지로 되돌아가는 버튼을 생성한다
airman5573 Apr 5, 2022
ca42a68
:bug: fix(component): 피드백을 초기화 하는 방식을 변경한다
airman5573 Apr 5, 2022
0a9e6ea
:sparkles: feat(ui): 키보드 엔터키로도 form을 제출할 수 있도록 한다
airman5573 Apr 5, 2022
0b3e812
:sparkles: feat(ui): aPI 통신 할때 제출 버튼에 loading indicator를 보여준다
airman5573 Apr 5, 2022
db8548b
:bug: fix: 동기화 문제를 해결한다
airman5573 Apr 5, 2022
1eb6252
:sparkles: feat(component): 상품이 없을때 없다고 표시한다
airman5573 Apr 6, 2022
2c53f74
:sparkles: feat: store의 state를 localStorage에서 관리한다
airman5573 Apr 6, 2022
c3ed58d
:sparkles: feat(ui): alert대신 toast로 사용자에게 성공/실패 여부를 안내한다
airman5573 Apr 6, 2022
a00c19f
:recycle: refactor: async/await 방식으로 비동기 요청을 처리한다
airman5573 Apr 6, 2022
0483961
:recycle: refactor(component): loading중인지 판단하는 방식을 변경한다
airman5573 Apr 6, 2022
a444707
:sparkles: feat(ui): 상품을 수정할때도 enter키로 confirm한다
airman5573 Apr 6, 2022
88f2a43
:construction: wip: merge
airman5573 Apr 7, 2022
08692d4
:recycle: refactor(cleanup): merge후 생성된 옛날 파일들을 삭제한다
airman5573 Apr 7, 2022
01e92b8
:bug: fix(component): 라벨 이름을 변경한다
airman5573 Apr 7, 2022
f1c718e
:white_check_mark: test(ui): 상품 추가 테스트 케이스를 추가한다
airman5573 Apr 7, 2022
f84181a
:bug: fix: 반환 가능한 돈이 있으면 그거라도 반환한다
airman5573 Apr 7, 2022
3eb8730
:bug: fix(ui): 로그인시 상품관리 탭을 active상태로 변경한다
airman5573 Apr 10, 2022
05d212a
:memo: docs(todo): 완료한 항목에 표시한다
airman5573 Apr 10, 2022
f2436bb
:recycle: refactor: 가독성 향상을 위한 코드 개선
airman5573 Apr 10, 2022
68e9671
:recycle: refactor: 불필요한 옵션을 제거한다
airman5573 Apr 10, 2022
52e9045
:recycle: refactor: 컴포넌트를 폴더 안에 넣는다
airman5573 Apr 10, 2022
ba85bc5
:white_check_mark: test: test를 개선한다
airman5573 Apr 11, 2022
eabd187
:sparkles: feat(ui): helptip을 추가한다
airman5573 Apr 12, 2022
02105b2
:sparkles: feat(routing): 일치하는 페이지가 없는 경우 home으로 redirect한다
airman5573 Apr 14, 2022
0facfc2
:white_check_mark: test(domain): 상품을 구매하기 위해 투입한 돈에 대한 유효성 검사가 잘 이뤄지는…
airman5573 Apr 14, 2022
8520452
:recycle: refactor(logic): 함수 인자에 기본값을 지정한다
airman5573 Apr 14, 2022
4d0f6d1
:recycle: refactor(test): test코드를 파일로 분리한다
airman5573 Apr 14, 2022
45a0ff2
:recycle: refactor(cleanup): 불필요한 옵션을 제거한다
airman5573 Apr 14, 2022
5f50abf
:recycle: refactor: 리터럴 대신 상수를 사용한다
airman5573 Apr 14, 2022
d31ee67
:recycle: refactor(test): 테스트 코드를 실패/성공 케이스로 분리한다
airman5573 Apr 14, 2022
6826b70
:recycle: refactor(cleanup): 단일 컴포넌트들을 한곳에 모아놓는다
airman5573 Apr 14, 2022
67e4d8c
:recycle: refactor(cleanup): 로그인 프로세스를 담당하는 함수를 분리한다
airman5573 Apr 14, 2022
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
10 changes: 10 additions & 0 deletions cypress.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"testFiles": "**/*.spec.js",
"screenshotOnRunFailure": false,
"video": false,
"pluginsFile": false,
"supportFile": "./cypress/support",
"fixturesFolder": "./cypress/fixtures",
"defaultCommandTimeout": 30000,
"baseUrl": "http://localhost:9000"
}
6 changes: 6 additions & 0 deletions cypress/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
extends: ['plugin:cypress/recommended'],
rules: {
'no-unused-expressions': 0, // chai assertions trigger this rule
},
};
46 changes: 46 additions & 0 deletions cypress/integration/charge-money.fail.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { ERROR_MESSAGE, COIN, MONEY } from '../../src/constants';

describe('잔돈을 충전한다 - 실패케이스', () => {
const email = `${Date.now()}@gmail.com`;
const name = '윤병인';
const password = 'Abcde123!';

before(() => {
cy.register(email, name, password);
cy.login(email, password);
});

beforeEach(() => {
cy.restoreLocalStorage();
});

it('빈 값을 허용하지 않는다', () => {
const money = '';
cy.chargeMoney(money);
cy.checkToastErrorMessage(ERROR_MESSAGE.EMPTY_CHARGE_MONEY);
});

it('숫자만 입력 가능하다.', () => {
const money = '1,000';
cy.chargeMoney(money);
cy.checkToastErrorMessage(ERROR_MESSAGE.NOT_NUMBER_CHARGE_MONEY);
});

it('양수만 입력 가능하다', () => {
const money = '-1000';
cy.chargeMoney(money);
cy.checkToastErrorMessage(ERROR_MESSAGE.NEGATIVE_CHARGE_MONEY);
});

it(`${COIN.MIN_UNIT.toLocaleString()}원으로 나누어 떨어지는 금액만 투입할 수 있다`, () => {
const money = '1001';
cy.chargeMoney(money);
cy.checkToastErrorMessage(ERROR_MESSAGE.NOT_DIVIDED_BY_TEN_CHARGE_MONEY);
});

it(`잔돈으로 보유할 수 있는 최대 금액은 ${MONEY.MAX.toLocaleString()}원이다`, () => {
const money = `${MONEY.MAX + 1000}`;
cy.chargeMoney(money);
cy.checkToastErrorMessage(ERROR_MESSAGE.OVER_MAX_CHARGE_MONEY);
});
});
30 changes: 30 additions & 0 deletions cypress/integration/charge-money.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { testid } from '../support/utils';
import { COIN } from '../../src/constants';
import { krLocaleStringToInt } from '../../src/utils';

describe('잔돈을 충전한다 - 성공케이스', () => {
const email = `${Date.now()}@gmail.com`;
const name = '윤병인';
const password = 'Abcde123!';
const chargedMoney = 3000;

before(() => {
cy.register(email, name, password);
cy.login(email, password);
});

it('잔돈을 충전한다', () => {
cy.restoreLocalStorage();
cy.chargeMoney(chargedMoney);
cy.get(testid`charged-money`).should('have.text', chargedMoney.toLocaleString());

cy.get(testid`changes-inventory`).then(($el) => {
console.log($el[0]);
const total = COIN.UNITS.reduce((acc, unit) => {
const count = krLocaleStringToInt($el.find(testid(`coin-unit-${unit}-quantity`)).text());
return acc + count * unit;
}, 0);
cy.get(testid`charged-money`).should('have.text', total.toLocaleString());
});
});
});
101 changes: 101 additions & 0 deletions cypress/integration/product-manage.fail.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { ERROR_MESSAGE } from '../../src/constants';

describe('상품을 관리 한다 - 실패케이스', () => {
const email = `${Date.now()}@gmail.com`;
const name = '윤병인';
const password = 'Abcde123!';
const _product = {
name: '콜라',
price: 1000,
quantity: 10,
};

before(() => {
cy.register(email, name, password);
cy.login(email, password);
});

beforeEach(() => {
cy.restoreLocalStorage();
cy.removeProducts();
});

it('상품명이 빈 경우', () => {
const product = { ..._product, name: '' };
cy.addProduct(product);
cy.checkToastErrorMessage(ERROR_MESSAGE.EMPTY_PRODUCT_NAME);
});

it('상품명이 너무 긴 경우', () => {
const product = { ..._product, name: '가나다라마바사123456' };
cy.addProduct(product);
cy.checkToastErrorMessage(ERROR_MESSAGE.OVER_MAX_LENGTH_PRODUCT_NAME);
});

it('상품명이 중복된 경우', () => {
cy.addProduct(_product);
cy.addProduct(_product);
cy.checkToastErrorMessage(ERROR_MESSAGE.DUPLICATE_PRDUCT_NAME);
});

it('상품가격이 빈 경우', () => {
const product = { ..._product, name: '환타', price: '' };
cy.addProduct(product);
cy.checkToastErrorMessage(ERROR_MESSAGE.EMPTY_PRODUCT_PRICE);
});

it('상품수량이 빈 경우', () => {
const product = { ..._product, name: '밀키스', quantity: '' };
cy.addProduct(product);
cy.checkToastErrorMessage(ERROR_MESSAGE.EMPTY_PRODUCT_QUANTITY);
});

// 상품 수정

it('상품 수정 - 상품명이 빈 경우', () => {
cy.addProduct(_product);
cy.findProduct(_product.name);
cy.get('@productIndex').then((index) => {
cy.editProduct(index, true, { ..._product, name: '' });
cy.checkToastErrorMessage(ERROR_MESSAGE.EMPTY_PRODUCT_NAME);
});
});

it('상품 수정 - 상품명이 너무 긴 경우', () => {
cy.addProduct(_product);
cy.findProduct(_product.name);
cy.get('@productIndex').then((index) => {
cy.editProduct(index, true, { ..._product, name: '가나다라마바사123456' });
cy.checkToastErrorMessage(ERROR_MESSAGE.OVER_MAX_LENGTH_PRODUCT_NAME);
});
});

it('상품 수정 - 상품명이 중복된 경우', () => {
cy.addProduct(_product);
const newProduct = { ..._product, name: '사이다' };
cy.addProduct(newProduct);
cy.findProduct(_product.name);
cy.get('@productIndex').then((index) => {
cy.editProduct(index, true, newProduct);
cy.checkToastErrorMessage(ERROR_MESSAGE.DUPLICATE_PRDUCT_NAME);
});
});

it('상품 수정 - 상품가격이 빈 경우', () => {
cy.addProduct(_product);
cy.findProduct(_product.name);
cy.get('@productIndex').then((index) => {
cy.editProduct(index, true, { ..._product, price: '' });
cy.checkToastErrorMessage(ERROR_MESSAGE.EMPTY_PRODUCT_PRICE);
});
});

it('상품 수정 - 상품수량이 빈 경우', () => {
cy.addProduct(_product);
cy.findProduct(_product.name);
cy.get('@productIndex').then((index) => {
cy.editProduct(index, true, { ..._product, quantity: '' });
cy.checkToastErrorMessage(ERROR_MESSAGE.EMPTY_PRODUCT_QUANTITY);
});
});
});
54 changes: 54 additions & 0 deletions cypress/integration/product-manage.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { testid } from '../support/utils';

describe('상품을 관리 한다 - 성공케이스', () => {
const email = `${Date.now()}@gmail.com`;
const name = '윤병인';
const password = 'Abcde123!';
const product = {
name: '콜라',
price: 1000,
quantity: 10,
};

before(() => {
cy.register(email, name, password);
cy.login(email, password);
});

beforeEach(() => {
cy.restoreLocalStorage();
cy.removeProducts();
});

it('상품을 추가한다', () => {
cy.addProduct(product);
cy.get(testid`product-inventory-table`)
.find('tbody tr td:first-of-type span')
.contains(product.name);
});

it('상품을 수정한다', () => {
const product = {
name: '사이다',
price: 1150,
quantity: 8,
};
cy.addProduct(product);
cy.editProduct(0, false, product);
cy.get(`product-inventory ${testid`product-name`}`).should('have.text', product.name);
cy.get(`product-inventory ${testid`product-price`}`).should(
'have.text',
product.price.toLocaleString()
);
cy.get(`product-inventory ${testid`product-quantity`}`).should(
'have.text',
product.quantity.toLocaleString()
);
});

it('상품을 삭제한다', () => {
cy.addProduct(product);
cy.get(testid`delete-btn`).click();
cy.get('product-inventory table').should('not.exist');
});
});
46 changes: 46 additions & 0 deletions cypress/integration/purchase-product.fail.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { ERROR_MESSAGE, COIN, INSERT_MONEY } from '../../src/constants';

describe('상품을 구매한다 - 실패케이스', () => {
const email = `${Date.now()}@gmail.com`;
const name = '윤병인';
const password = 'Abcde123!';

before(() => {
cy.register(email, name, password);
cy.login(email, password);
});

beforeEach(() => {
cy.restoreLocalStorage();
});

it('돈 투입시 빈 값을 허용하지 않는다', () => {
const money = '';
cy.insertMoney(money);
cy.checkToastErrorMessage(ERROR_MESSAGE.EMPTY_INSERT_MONEY);
});

it('숫자만 입력 가능하다.', () => {
const money = '1,000';
cy.insertMoney(money);
cy.checkToastErrorMessage(ERROR_MESSAGE.NOT_NUMBER_INSERT_MONEY);
});

it('양수만 입력 가능하다', () => {
const money = '-1000';
cy.insertMoney(money);
cy.checkToastErrorMessage(ERROR_MESSAGE.NEGATIVE_INSERT_MONEY);
});

it(`${COIN.MIN_UNIT.toLocaleString()}원으로 나누어 떨어지는 금액만 투입할 수 있다`, () => {
const money = '1001';
cy.insertMoney(money);
cy.checkToastErrorMessage(ERROR_MESSAGE.NOT_DIVIDED_BY_TEN_INSERT_MONEY);
});

it(`충전할 수 있는 최대 금액은 ${INSERT_MONEY.MAX.toLocaleString()}원이다`, () => {
const money = `${INSERT_MONEY.MAX + 1000}`;
cy.insertMoney(money);
cy.checkToastErrorMessage(ERROR_MESSAGE.OVER_MAX_INSERT_MONEY);
});
});
72 changes: 72 additions & 0 deletions cypress/integration/purchase-product.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { coinToMoney, krLocaleStringToInt } from '../../src/utils';
import { testid } from '../support/utils';

describe('상품을 구매한다 - 성공케이스', () => {
const email = `${Date.now()}@gmail.com`;
const name = '윤병인';
const password = 'Abcde123!';
const product = {
name: '콜라',
price: 1000,
quantity: 10,
};
const chargedMoney = 3000;
const insertedMoney = 3000;

before(() => {
cy.register(email, name, password);
cy.login(email, password);
});

beforeEach(() => {
cy.restoreLocalStorage();
});

it('돈을 투입한다', () => {
cy.insertMoney(insertedMoney);
cy.get(testid`inserted-money`)
.invoke('text')
.should('eq', insertedMoney.toLocaleString());
});

it('상품을 구매한다', () => {
cy.addProduct(product); // 상품 추가
cy.chargeMoney(chargedMoney); // 잔돈 충전
cy.purchaseProduct(product);
cy.get(testid`purchase-btn`).click();
cy.get(`${testid`product-price`} span`)
.invoke('text')
.then((_price) => {
const price = krLocaleStringToInt(_price);
cy.get(testid`inserted-money`)
.invoke('text')
.then((_insertedMoney) => {
const isPurchased = insertedMoney - price === krLocaleStringToInt(_insertedMoney);
expect(isPurchased).to.be.true;
});
});
});

it('잔돈을 반환한다', () => {
cy.releaseCoin();
cy.get(testid`release-coin-table`).then(($table) => {
const $trs = $table.find('tbody tr');
const coins = {};
$trs.each((_, $tr) => {
const $tds = $tr.querySelectorAll('td');
const [$unit, $count] = $tds;
const unit = krLocaleStringToInt($unit.querySelector('span').textContent);
const count = krLocaleStringToInt($count.querySelector('span').textContent);
coins[unit] = count;
});
const changes = coinToMoney(coins);
cy.get(testid`inserted-money`)
.invoke('text')
.then((_insertedMoney) => {
const isChangesCorrect =
insertedMoney === krLocaleStringToInt(_insertedMoney) + product.price + changes;
expect(isChangesCorrect).to.be.true;
});
});
});
});
Loading