diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000000..a5f06fd8b9 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,24 @@ +{ + "env": { + "browser": true, + "es2021": true, + "node" : true, + "jest": true + }, + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": 2021, + "sourceType": "module" + }, + "plugins": ["@typescript-eslint"], + "extends": [ + "airbnb-base", + "plugin:cypress/recommended" + ], + "rules": { + "import/extensions": ["error", "always"], + "import/no-unresolved": "off", + "@typescript-eslint/no-unused-vars": [2, { "args": "none" }], + "linebreak-style": "off" + } +} diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000000..b58b603fea --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,5 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000000..476be9003d --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000000..79ee123c2b --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000000..03d9549ea8 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/javascript-lotto.iml b/.idea/javascript-lotto.iml new file mode 100644 index 0000000000..0c8867d7e1 --- /dev/null +++ b/.idea/javascript-lotto.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/jsLinters/eslint.xml b/.idea/jsLinters/eslint.xml new file mode 100644 index 0000000000..541945bb08 --- /dev/null +++ b/.idea/jsLinters/eslint.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000000..6e2db72b3c --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000000..94a25f7f4c --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/architecture.md b/architecture.md new file mode 100644 index 0000000000..e65bf4c84c --- /dev/null +++ b/architecture.md @@ -0,0 +1,18 @@ +# 컴포넌트 구조 +## 최상위 App Component +앱의 전체 상태를 보유 +- 입력 받은 구입 금액 +- 구매 후 남은 금액 +- 자동/수동 구매 +- 번호 보기 상태 +- 저난 주 당첨번호 + +## lottoInput component +입력받은 값을 App Component로 올려주어야 함 +## lottoBoard component +구매한 로또를 보여줌 +- 번호보기 클릭 시 구매한 로또의 번호를 보여줌 +## lottoWin component +지난 주 당첨 번호를 입력받아 App Component로 올려주어야 함 +## lottoStatistic component +당첨 통계를 보여줘야 함 \ No newline at end of file diff --git a/cypress.json b/cypress.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/cypress.json @@ -0,0 +1 @@ +{} diff --git a/cypress/fixtures/example.json b/cypress/fixtures/example.json new file mode 100644 index 0000000000..02e4254378 --- /dev/null +++ b/cypress/fixtures/example.json @@ -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" +} diff --git a/cypress/integration/test2_spec.ts b/cypress/integration/test2_spec.ts new file mode 100644 index 0000000000..80c8939c92 --- /dev/null +++ b/cypress/integration/test2_spec.ts @@ -0,0 +1,82 @@ +/// +/* eslint-disable no-undef */ +import { + ERROR_DUPLICATED_NUMBER, ERROR_MISSING_NUMBER, ERROR_NUMBER_RANGE, +} from '../support/constant'; + +describe('lottoMachine', () => { + const go = (arr: number[]): Cypress.Chainable> => { + cy.get('.winning-number') + .each((input, idx) => { + if (arr[idx] !== 0) { + cy.wrap(input) + .clear() + .type(String(arr[idx])); + } + }); + if (arr[6] !== 0) { + cy.get('.bonus-number') + .clear() + .type(String(arr[6])); + } else { + cy.get('.bonus-number') + .clear(); + } + return cy.get('.open-result-modal-button') + .click(); + }; + + it('do not miss number', () => { + // const alertMessage: string = '번호를 모두 입력해주십시오.'; + cy.visit('./index.html'); + + const stub = cy.stub(); + cy.on('window:alert', stub); + + cy.get('.open-result-modal-button') + .click() + .then(() => { + expect(stub.getCall(0)).to.be.calledWith(ERROR_MISSING_NUMBER); + }); + + go([1, 0, 3, 4, 5, 6, 7]) + .then(() => { + expect(stub.getCall(0)).to.be.calledWith(ERROR_MISSING_NUMBER); + }); + + go([1, 20, 3, 4, 5, 6, 0]) + .then(() => { + expect(stub.getCall(0)).to.be.calledWith(ERROR_MISSING_NUMBER); + }); + }); + + it('has number in range 1 ~ 45', () => { + const stub = cy.stub(); + cy.on('window:alert', stub); + + go([1, 20, 3, 4, 5, 90, 15]) + .then(() => { + expect(stub.getCall(0)).to.be.calledWith(ERROR_NUMBER_RANGE); + }); + + go([1, 20, 3, 4, -50, 9, 18]) + .then(() => { + expect(stub.getCall(0)).to.be.calledWith(ERROR_NUMBER_RANGE); + }); + }); + + it('do not have duplicated number', () => { + const stub = cy.stub(); + cy.on('window:alert', stub); + + go([1, 20, 3, 4, 1, 9, 15]) + .then(() => { + expect(stub.getCall(0)).to.be.calledWith(ERROR_DUPLICATED_NUMBER); + }); + + go([1, 20, 3, 4, 8, 6, 20]) + .then(() => { + expect(stub.getCall(0)).to.be.calledWith(ERROR_DUPLICATED_NUMBER); + }); + }); +}); diff --git a/cypress/integration/test_spec.ts b/cypress/integration/test_spec.ts new file mode 100644 index 0000000000..b86218839a --- /dev/null +++ b/cypress/integration/test_spec.ts @@ -0,0 +1,24 @@ +/// +describe('lotto', () => { + it('basic cost input', () => { + cy.visit('./index.html'); + cy.get('.lotto-input') + .type('1111'); + cy.get('.lotto-input button') + .click(); + cy.get('.total') + .should('have.text', '총 1 개를 구매하였습니다.'); + cy.get('.tickets') + .find('span') + .should('have.length', 1); + cy.get('.balls') + .should('be.hidden'); + cy.get('.lotto-purchase') + .find('.toggle-button') + .click(); + cy.get('.balls') + .should('not.be.hidden'); + cy.get('.tickets') + .should('be.hidden'); + }); +}); diff --git a/cypress/plugins/index.js b/cypress/plugins/index.js new file mode 100644 index 0000000000..59b2bab6e4 --- /dev/null +++ b/cypress/plugins/index.js @@ -0,0 +1,22 @@ +/// +// *********************************************************** +// This example plugins/index.js can be used to load plugins +// +// You can change the location of this file or turn off loading +// the plugins file with the 'pluginsFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/plugins-guide +// *********************************************************** + +// This function is called when a project is opened or re-opened (e.g. due to +// the project's config changing) + +/** + * @type {Cypress.PluginConfig} + */ +// eslint-disable-next-line no-unused-vars +module.exports = (on, config) => { + // `on` is used to hook into various events Cypress emits + // `config` is the resolved Cypress config +} diff --git a/cypress/support/commands.js b/cypress/support/commands.js new file mode 100644 index 0000000000..119ab03f7c --- /dev/null +++ b/cypress/support/commands.js @@ -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) => { ... }) diff --git a/cypress/support/constant.ts b/cypress/support/constant.ts new file mode 100644 index 0000000000..a5ba8f6d8a --- /dev/null +++ b/cypress/support/constant.ts @@ -0,0 +1,8 @@ +const ERROR_NUMBER_RANGE = '1 ~ 45사이의 숫자를 입력해주십시오.'; +const ERROR_COST_RANGE = '1000원 ~ 100000원 이내로 구매가 가능합니다.'; +const ERROR_MISSING_NUMBER = '번호를 모두 입력해주십시오.'; +const ERROR_DUPLICATED_NUMBER = '번호는 중복될 수 없습니다.'; + +export { + ERROR_DUPLICATED_NUMBER, ERROR_MISSING_NUMBER, ERROR_NUMBER_RANGE, ERROR_COST_RANGE, +}; diff --git a/cypress/support/index.js b/cypress/support/index.js new file mode 100644 index 0000000000..d68db96df2 --- /dev/null +++ b/cypress/support/index.js @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.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') diff --git a/cypress/tsconfig.json b/cypress/tsconfig.json new file mode 100644 index 0000000000..61eaa2c984 --- /dev/null +++ b/cypress/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + }, + "rules": { + "import/extensions": "off" + }, + "include": ["**/*.ts"], +} \ No newline at end of file diff --git a/index.html b/index.html index 2b6f30628e..42c61d6077 100644 --- a/index.html +++ b/index.html @@ -9,13 +9,19 @@ - + 🎱 행운의 로또 + + + + 자동/수동 + + 구입할 금액을 입력해주세요. - + 🎱 행운의 로또 확인 - + - 총 5개를 구매하였습니다. + 총 5개를 구매하였습니다. - 번호보기 + 번호보기 - + 🎟️ 🎟️ 🎟️ 🎟️ 🎟️ + + + + 1 + 2 + 3 + 4 + 5 + 6 + + + - + 지난 주 당첨번호 6개와 보너스 넘버 1개를 입력해주세요. 당첨 번호 - + 🏆 당첨 통계 🏆 일치 갯수 당첨금 - 당첨 갯수 + 당첨 갯수 - + 3개 5,000 - n개 + n개 - + 4개 50,000 - n개 + n개 - + 5개 1,500,000 - n개 + n개 - + 5개 + 보너스볼 30,000,000 - n개 + n개 - + 6개 2,000,000,000 - n개 + n개 - 당신의 총 수익률은 %입니다. + 당신의 총 수익률은 %입니다. 다시 시작하기 - +
당신의 총 수익률은 %입니다.