-
Notifications
You must be signed in to change notification settings - Fork 3
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
[jwon] typescript-calculator #4
base: main
Are you sure you want to change the base?
Changes from all commits
5425534
7673c54
e56bd92
a09a533
3245492
b195677
7f18a8e
4db10e4
af1f010
739f4fd
6b9c861
5bbaf46
a4cbfe0
2fb6738
9f12852
0ac38ab
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"env": { | ||
"browser": true, | ||
"es2021": true, | ||
"cypress/globals": true | ||
}, | ||
"extends": ["airbnb-base", "plugin:cypress/recommended"], | ||
"parser": "@typescript-eslint/parser", | ||
"parserOptions": { | ||
"ecmaVersion": 12, | ||
"sourceType": "module" | ||
}, | ||
"plugins": ["@typescript-eslint", "cypress"], | ||
"ignorePatterns": ["dist/", "node_modules/"], | ||
"rules": { | ||
"cypress/no-assigning-return-values": "error", | ||
"cypress/no-unnecessary-waiting": "error", | ||
"cypress/assertion-before-screenshot": "warn", | ||
"cypress/no-force": "warn", | ||
"cypress/no-async-tests": "error", | ||
"import/extensions": "always" | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. EOL 관련 아티클 읽어보시면 좋을것 같아요 :) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,9 @@ | ||
package-lock.json | ||
yarn.lock | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. transcendence42/javascript-archive#16 (comment) 현재는 복잡도가 낮은 프로그램이여서 문제가 안될것같지만 후에 복잡도가 높아지면 같이 저장하는게 좋다고 생각합니다.! 또 |
||
cypress/fixtures/ | ||
cypress/intergration/examples/ | ||
index.html | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. gitignore에 index.html 파일이 있는 이유가 궁금합니다 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 헉 |
||
|
||
|
||
# Created by https://www.toptal.com/developers/gitignore/api/vscode,node,intellij | ||
# Edit at https://www.toptal.com/developers/gitignore?templates=vscode,node,intellij | ||
|
@@ -249,7 +255,7 @@ typings/ | |
|
||
# Nuxt.js build / generate output | ||
.nuxt | ||
dist | ||
# dist | ||
|
||
# Gatsby files | ||
.cache/ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"parser": "typescript", | ||
"singleQuote": true, | ||
"trailingComma": "all" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,79 @@ | ||||||
const calculate = (number1, operator, number2, expectedResult) => { | ||||||
cy.get('.modifiers').click(); | ||||||
for (let index = 0 ; index < number1.length ; index += 1) { | ||||||
cy.get('.digit').contains(number1[index]).click(); | ||||||
} | ||||||
cy.get('.operations').contains(operator).click(); | ||||||
for (let index = 0 ; index < number2.length ; index += 1) { | ||||||
cy.get('.digit').contains(number2[index]).click(); | ||||||
} | ||||||
cy.get('.operations').contains('=').click(); | ||||||
cy.get('#total').should('have.text', expectedResult) | ||||||
} | ||||||
Comment on lines
+1
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 깔끔하고 좋네요. |
||||||
|
||||||
describe('계산기 테스트', () => { | ||||||
beforeEach(() => { | ||||||
cy.visit('/'); | ||||||
}); | ||||||
|
||||||
it('1. 숫자 입력 시 3자리까지만 결과창에 표시', () => { | ||||||
cy.get('.digit').contains('1').click(); | ||||||
cy.get('#total').should('have.text', '1'); | ||||||
cy.get('.digit').contains('2').click(); | ||||||
cy.get('#total').should('have.text', '12'); | ||||||
cy.get('.digit').contains('3').click(); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 위에 calculate 만들어 준 것처럼 따로 함수로 빼주면 더 깔끔해 보일 것 같아요! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 맞아요. 다음 과제에선 cypress 코드 작성에 조금 더 신경을 써봐야겠어요~! |
||||||
cy.get('#total').should('have.text', '123'); | ||||||
cy.get('.digit').contains('4').click(); | ||||||
cy.get('#total').should('have.text', '123'); | ||||||
cy.get('.digit').contains('5').click(); | ||||||
cy.get('#total').should('have.text', '123'); | ||||||
}); | ||||||
|
||||||
it('2. [AC] 입력 시 0으로 초기화', () => { | ||||||
cy.get('.digit').contains('4').click(); | ||||||
cy.get('.digit').contains('2').click(); | ||||||
cy.get('.modifiers').click(); | ||||||
cy.get('#total').should('have.text', '0'); | ||||||
}) | ||||||
|
||||||
it('3. 연산자는 1개만 입력 가능', () => { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
작성한 it의 설명은 함수 단위 테스트 설명이라고 생각합니다. BDD인 만큼 조금 더 세부적으로 행동을 중심으로 작성하면 좋을것 같아요! 아래는 Given, When, Then 에 대한 간략 설명입니댜! Given : 시나리오 진행에 필요한 값을 설정합니다. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 맞아요! 제가 코멘트를 단 이유는 Given, When, Then의 느낌보다는 다음 it 설명이 유닛테스트 느낌이 더 강해서 였습니다. 조금 더 자세히 적어서 it 설명만 보아도 동작을 알 수 있어야 한다고 생각합니다.
연산자 2개 이상(Given) 으로 나누어서 적었습니다! |
||||||
cy.get('.digit').contains('4').click(); | ||||||
cy.get('.digit').contains('2').click(); | ||||||
cy.get('.operations').contains('+').click(); | ||||||
cy.get('.operations').contains('-').click(); | ||||||
cy.get('#total').should('have.text', '42+'); | ||||||
cy.get('.modifiers').click(); | ||||||
}) | ||||||
|
||||||
it('4. [숫자][연산자][숫자] 포맷 이후 연산자가 올 수 없음', () => { | ||||||
cy.get('.digit').contains('4').click(); | ||||||
cy.get('.digit').contains('2').click(); | ||||||
cy.get('.operations').contains('+').click(); | ||||||
cy.get('.digit').contains('4').click(); | ||||||
cy.get('.digit').contains('2').click(); | ||||||
cy.get('.operations').contains('-').click(); | ||||||
cy.get('#total').should('have.text', '42+42'); | ||||||
cy.get('.modifiers').click(); | ||||||
}) | ||||||
|
||||||
it('5. 한 자릿수 사칙연산', () => { | ||||||
calculate([4], '+', [2], '6'); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. LGTM 👍 👍 |
||||||
calculate([4], '-', [2], '2'); | ||||||
calculate([4], 'X', [2], '8'); | ||||||
calculate([4], '/', [2], '2'); | ||||||
}) | ||||||
|
||||||
it('6. 두 자릿수 사칙연산', () => { | ||||||
calculate([4, 2], '+', [2, 4], '66'); | ||||||
calculate([4, 2], '-', [2, 4], '18'); | ||||||
calculate([4, 2], 'X', [2, 4], '1008'); | ||||||
calculate([4, 2], '/', [2, 4], '1'); | ||||||
}) | ||||||
|
||||||
it('7. 세 자릿수 사칙연산', () => { | ||||||
calculate([1, 2, 3], '+', [3, 2, 1], '444'); | ||||||
calculate([1, 2, 3], '-', [3, 2, 1], '-198'); | ||||||
calculate([1, 2, 3], 'X', [3, 2, 1], '39483'); | ||||||
calculate([1, 2, 3], '/', [3, 2, 1], '0'); | ||||||
}) | ||||||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/// <reference types="cypress" /> | ||
// *********************************************************** | ||
// 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 | ||
} |
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) => { ... }) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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') |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
html, | ||
body { | ||
margin: 0; | ||
padding: 0; | ||
font-family: sans-serif; | ||
} | ||
|
||
#app { | ||
height: 100vh; | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
} | ||
|
||
.calculator { | ||
width: 300px; | ||
display: grid; | ||
grid-template-areas: | ||
'total total total total' | ||
'modif modif modif oper' | ||
'digit digit digit oper' | ||
'digit digit digit oper' | ||
'digit digit digit oper' | ||
'digit digit digit oper'; | ||
grid-auto-columns: 1fr; | ||
grid-auto-rows: 1fr; | ||
height: 500px; | ||
} | ||
|
||
button { | ||
font-size: 2rem; | ||
border: 0.5px solid #98999b; | ||
} | ||
|
||
.modifiers button { | ||
background-color: #ccc; | ||
} | ||
|
||
.operations button { | ||
background-color: orange; | ||
} | ||
|
||
.digits button { | ||
background-color: #efefef; | ||
} | ||
|
||
#total { | ||
grid-area: total; | ||
background-color: #333; | ||
color: white; | ||
margin: 0; | ||
padding: 1rem; | ||
display: flex; | ||
justify-content: flex-end; | ||
align-items: flex-end; | ||
font-size: 4rem; | ||
} | ||
|
||
.digits { | ||
grid-area: digit; | ||
display: flex; | ||
flex-wrap: wrap; | ||
flex-direction: row-reverse; | ||
} | ||
|
||
.digits button { | ||
flex: 1 0 30%; | ||
} | ||
|
||
.digit.wide { | ||
flex: 2 0 60%; | ||
order: 1; | ||
} | ||
|
||
.modifiers { | ||
grid-area: modif; | ||
grid-auto-flow: column; | ||
grid-auto-columns: 1fr; | ||
} | ||
|
||
.operations { | ||
grid-area: oper; | ||
} | ||
|
||
.subgrid { | ||
display: grid; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
export const OPERATOR = { | ||
ADD: "+", | ||
SUBSTRACT: "-", | ||
MULTIPLY: "X", | ||
DIVIDE: "/", | ||
EQUAL: "=", | ||
}; | ||
export const EQUAL = '='; | ||
export const REGEXP = { | ||
// SIGN: '\\-{1}', | ||
NUMBERS: '\\-?\\d{1,3}', | ||
OPERATORS: 'X|\\-|\\+|\\/{1}' | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { pushTotalValue, clearTotalValue } from "../view/index.js"; | ||
export const setEventListener = () => { | ||
document | ||
.getElementsByClassName("digits")[0] | ||
.addEventListener("click", (e) => { | ||
pushTotalValue(e); | ||
}); | ||
document | ||
.getElementsByClassName("operations")[0] | ||
.addEventListener("click", (e) => { | ||
pushTotalValue(e); | ||
}); | ||
document | ||
.getElementsByClassName("modifier")[0] | ||
.addEventListener("click", () => { | ||
clearTotalValue(); | ||
}); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import { setEventListener } from "./event.js"; | ||
export const controller = () => { | ||
setEventListener(); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
export const parseTotalValue = (totalValue) => { | ||
let isFirstNumberMinus = false; | ||
if (totalValue[0] === "-") { | ||
totalValue = totalValue.slice(1, totalValue.length); | ||
isFirstNumberMinus = true; | ||
} | ||
const operator = totalValue.replace(/\d/g, ""); | ||
const numbers = totalValue.split(operator); | ||
if (isFirstNumberMinus) { | ||
return ["-" + numbers[0], operator, numbers[1]]; | ||
} | ||
return [numbers[0], operator, numbers[1]]; | ||
}; | ||
Comment on lines
+1
to
+13
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 로직 변경 후 사용하지 않는 파일입니다. git rm을 누락했네요. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { REGEXP, EQUAL } from "../constants/index.js"; | ||
export const isNumber = (str) => { | ||
return /^[\d.]+(?:e-?\d+)?$/.test(str); | ||
}; | ||
export const checkFirstTotalValue = (totalValue, clickValue) => { | ||
return totalValue === "0" && (isNumber(clickValue) || clickValue === "-"); | ||
}; | ||
export const checkPreventClickValue = (totalValue, clickValue) => { | ||
const tmpValue = totalValue + clickValue; | ||
const tmpValueArray = tmpValue.match("(" + | ||
REGEXP.NUMBERS + | ||
")?(" + | ||
REGEXP.OPERATORS + | ||
")?(" + | ||
REGEXP.NUMBERS + | ||
")?"); | ||
if (tmpValueArray) { | ||
if (!tmpValueArray[2] && tmpValueArray[3]) { | ||
return true; | ||
} | ||
if (tmpValueArray[2] && | ||
!isNumber(totalValue.charAt(totalValue.length - 1)) && | ||
!isNumber(clickValue)) { | ||
return true; | ||
} | ||
if (tmpValueArray[3] && !isNumber(clickValue) && clickValue !== EQUAL) { | ||
return true; | ||
} | ||
if (tmpValueArray[3] && | ||
tmpValue.length !== tmpValueArray[0].length && | ||
clickValue !== EQUAL) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { controller } from "./controller/index.js"; | ||
const app = () => { | ||
controller(); | ||
}; | ||
app(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
파일명이 .exlintrc.json으로 되어 있는데 상관 없는건가요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아뇨.. 어쩐지 적용이 안되더라구요. 하하하하..