๐Ÿ‘จโ€๐Ÿ’ป Seungineer's GitHub Contribution

๐Ÿ› ๏ธ Tool/React

[ํ”„๋ฆฌ์ฝ”์Šค] ์ˆซ์ž ์•ผ๊ตฌ ๊ฒŒ์ž„ ver.javascript - Cypress All Pass

seungineer = seungwoo + engineer 2024. 6. 2. 03:21

๊ตฌํ˜„์„ ์œ„ํ•œ MEMO

index.html์— ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์Šคํฌ๋ฆฝํŠธ๋กœ ์ด๋ฏธ ํฌํ•จ๋˜์–ด ์žˆ๊ธฐ์— ์ „์—ญ ๊ฐ์ฒด๋กœ ์ถ”๊ฐ€๋˜์–ด ์žˆ์Œ

- ๋”ฐ๋กœ import ํ•˜์ง€ ์•Š์•„๋„ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

// ex)
const randomNumber = Random.pickNumberInRange(1, 9);

import

๋ชจ๋“ˆ์—์„œ ์—ฌ๋Ÿฌ ๋ฉค๋ฒ„๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค. ์•„๋ž˜์˜ import๋กœ ํ˜„์žฌ ๋ฒ”์œ„ ๋‚ด์— foo, bar ๋ฉค๋ฒ„๋ฅผ ํฌํ•จ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.

import { foo, bar } from "my-module.js";

commit message convention(Angular JS)

- ์ปค๋ฐ‹ ์ „์— ํ™•์ธํ•˜๊ธฐ!!

๋”๋ณด๊ธฐ

Subject line

Subject line contains succinct description of the change.

Allowed <type>

  • feat (feature)
  • fix (bug fix)
  • docs (documentation)
  • style (formatting, missing semi colons, …)
  • refactor
  • test (when adding missing tests)
  • chore (maintain)

Allowed <scope>

Scope could be anything specifying place of the commit change. For example $location, $browser, $compile, $rootScope, ngHref, ngClick, ngView, etc...

 

<subject> text

  • use imperative, present tense: “change” not “changed” nor “changes”
  • don't capitalize first letter
  • no dot (.) at the end

Message body

  • just as in use imperative, present tense: “change” not “changed” nor “changes”
  • includes motivation for the change and contrasts with previous behavior

๊ตฌํ˜„์‚ฌํ•ญ

  • index.html์—์„œ ์ˆซ์ž๋ฅผ ์ž…๋ ฅ๋ฐ›๊ณ , ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด xxx.js ํŒŒ์ผ์—์„œ ์ด ๊ฐ’์ด ์ฒ˜๋ฆฌ๋˜๋„๋ก ํ•ด์•ผ ํ•จ
  • id๊ฐ€ result์ธ div ํƒœ๊ทธ์— ํžŒํŠธ(1์ŠคํŠธ๋ผ์ดํฌ, 1๋ณผ 1์ŠคํŠธ๋ผ์ดํฌ, ๋‚ซ์‹ฑ)๋ฅผ ๋ฐ›์•„์„œ ํ‘œ์‹œํ•ด์•ผ ํ•จ

index.js

export default class BaseballGame {
  play(computerInputNumbers, userInputNumbers) {
    return "๊ฒฐ๊ณผ ๊ฐ’ String";
  }
}

// ์˜ˆ์‹œ
play(123, 456); // '๋‚ซ์‹ฑ'
play(123, 345); // '1๋ณผ'
play(123, 432); // '2๋ณผ'
play(123, 312); // '3๋ณผ'
play(123, 145); // '1์ŠคํŠธ๋ผ์ดํฌ'
play(123, 134); // '1๋ณผ 1์ŠคํŠธ๋ผ์ดํฌ'
play(123, 132); // '2๋ณผ 1์ŠคํŠธ๋ผ์ดํฌ'
play(123, 124); // '2์ŠคํŠธ๋ผ์ดํฌ'

BaseballGame ํด๋ž˜์Šค์˜ play ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด์„œ return ๊ฐ’์ด ์˜ˆ์‹œ์™€ ๊ฐ™์ด ๋‚˜์˜ฌ ์ˆ˜ ์žˆ๊ฒŒ ๋‚ด๋ถ€ ๋กœ์ง ์กฐ์ •

-> ๊ฒฐ๊ณผ ๊ฐ’์„ ์ŠคํŠธ๋ง์œผ๋กœ ๋ฆฌํ„ดํ•˜๊ณ , alert๊ฐ€ ๋‚˜์˜ค๋„๋ก ํ•ด์•ผํ•จ.


๊ธฐ๋Šฅ ๊ตฌํ˜„

ํ•จ์ˆ˜์˜ ์—ฌ๋Ÿฌ ๊ฐ’ ๋ฐ˜ํ™˜ํ•˜๊ธฐ

์—ฌ๋Ÿฌ ๊ฐ’๋“ค์„ ๋ฐฐ์—ด ํ˜น์€ ๊ฐ์ฒด๋กœ ๋ฌถ์–ด์„œ ํ•˜๋‚˜์˜ ๊ฐ’์œผ๋กœ ๋งŒ๋“  ํ›„์— ๋ฐ˜ํ™˜ํ•˜๊ฑฐ๋‚˜, ๋ฐฐ์—ด, ๊ฐ์ฒด๋ฅผ ๋ถ„ํ•  ํ›„ ๋Œ€์ž…ํ•˜์—ฌ ๋ฐ˜ํ™˜์ด ํ•„์š”ํ•˜๋‹ค.

  • parseInputNumber() ํ•จ์ˆ˜์˜ return ๊ฐ’์„ ๊ฐ์ฒด๋กœ ๋ฌถ์–ด์„œ ๋ฐ˜ํ™˜
  • ๋ถ„ํ•  ๋Œ€์ž… ๋ฐฉ๋ฒ•์œผ๋กœ ๋ณ€์ˆ˜์— ํ• ๋‹น

input number parsing ๋ฐ play method์— ๊ฐ์ฒด๋กœ ๋ฐ˜ํ™˜

'ํ•จ์ˆ˜(๋˜๋Š” ๋ฉ”์†Œ๋“œ)๊ฐ€ ํ•œ ๊ฐ€์ง€ ์ผ๋งŒ ํ•˜๋„๋ก ์ตœ๋Œ€ํ•œ ์ž‘๊ฒŒ ๋งŒ๋“ค๋ฉฐ, indent depth๊ฐ€ 3์ด ๋„˜์ง€ ์•Š๋„๋ก ๊ตฌํ˜„ํ•œ๋‹ค'๋Š” ๊ณตํ†ต ์š”๊ตฌ ์‚ฌํ•ญ์— ๋”ฐ๋ผ parsing ํ•˜๋Š” ํ•จ์ˆ˜์™€ parsing๋œ ํ•จ์ˆ˜๋ฅผ ๊ฐ์ฒด๋กœ ๋งŒ๋“ค์–ด ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋กœ ๋‚˜๋ˆ„์–ด ๊ตฌํ˜„ํ•œ๋‹ค.

import {parseInputNumber} from './calLogic.js';
class BaseballGame {
  play(computerInputNumbers, userInputNumbers) {
    let [comIn, userIN] = parseInputNumber(computerInputNumbers, userInputNumbers)
    console.log(comIn, userIN);
    return "๊ฒฐ๊ณผ ๊ฐ’ String";
  }
}
function generateObj (CIN_first, CIN_second, CIN_third,UIN_first, UIN_second, UIN_third){
    const comIN = new Object();
    comIN['first'] = CIN_first;
    comIN['second'] = CIN_second;
    comIN['third'] = CIN_third;

    const userIN = new Object();
    userIN['first'] = UIN_first;
    userIN['second'] = UIN_second;
    userIN['third'] = UIN_third;
    return [comIN, userIN];
}


export function parseInputNumber (computerInputNumbers, userInputNumbers){
    let CIN_first, CIN_second, CIN_third;
    let UIN_first, UIN_second, UIN_third;
    CIN_first = Math.floor(computerInputNumbers/100);
    CIN_second = Math.floor(computerInputNumbers%100/10);
    CIN_third = Math.floor(computerInputNumbers%10);
    UIN_first = Math.floor(userInputNumbers/100);
    UIN_second = Math.floor(userInputNumbers%100/10);
    UIN_third = Math.floor(userInputNumbers%10);
    console.log(CIN_first, CIN_second, CIN_third);
    console.log(UIN_first, UIN_second, UIN_third);
    return generateObj(CIN_first, CIN_second, CIN_third,UIN_first, UIN_second, UIN_third);
}
  • parseInputNumber ํ•จ์ˆ˜: ์ปดํ“จํ„ฐ์—์„œ ์ƒ์„ฑํ•œ ๋žœ๋ค ์ˆซ์ž์™€ user๋กœ ๋ถ€ํ„ฐ ์ž…๋ ฅ ๋ฐ›์€ ์ˆ˜๋ฅผ ์ž๋ฆฟ์ˆ˜์— ๋”ฐ๋ผ ๋‚˜๋ˆ„์–ด ๊ฐ๊ฐ ๊ด€๋ฆฌํ•œ๋‹ค.
  • generateObj ํ•จ์ˆ˜: ์ด ํ•จ์ˆ˜์—์„œ ๊ฐ๊ฐ ๊ด€๋ฆฌ๋˜๋Š” ๋ณ€์ˆ˜๋ฅผ ๊ฐ์ฒดํ™”ํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

๋ณผ, ์ŠคํŠธ๋ผ์ดํฌ ๊ฐœ์ˆ˜ ์„ธ๊ธฐ

parsing ํ›„ ๊ฐ์ฒด ํ˜•ํƒœ๋กœ ๊ด€๋ฆฌ ํ•˜๊ณ  ์žˆ๋Š” input number๋ฅผ ๋น„๊ตํ•˜์—ฌ ๋ณผ์˜ ๊ฐœ์ˆ˜์™€ ์ŠคํŠธ๋ผ์ดํฌ ๊ฐœ์ˆ˜๋ฅผ ์„ธ์•ผํ•œ๋‹ค. ์ด ํ•จ์ˆ˜๋„ ๊ตฌํ˜„ ์š”๊ตฌ์‚ฌํ•ญ์— ๋”ฐ๋ผ ๋ณผ์˜ ๊ฐœ์ˆ˜๋ฅผ ์„ธ๋Š” ํ•จ์ˆ˜, ์ŠคํŠธ๋ผ์ดํฌ์˜ ๊ฐœ์ˆ˜๋ฅผ ์„ธ๋Š” ํ•จ์ˆ˜ ๋‚˜๋ˆ„์–ด ๊ตฌํ˜„ํ•œ๋‹ค.

// ๋‘ ๊ฐ์ฒด๋ฅผ ์ „๋‹ฌ ๋ฐ›์•„์„œ ๊ฒŒ์ž„ ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌํ„ดํ•˜๋Š” main ํ•จ์ˆ˜
export function gamestart (comIN, userIN){
    // i = ballCheck
    let strike_cnt = strikeCheck(comIN, userIN);
    let ball_cnt = ballCheck(comIN, userIN);
    return [ball_cnt, strike_cnt];
}
// ball ๊ฐœ์ˆ˜ ์„ธ๊ธฐ
function ballCheck(comIN, userIN){
    let com_arr = Object.values(comIN);
    let user_arr = Object.values(userIN);
    let temp_ball_cnt = 0;
    for (let i = 0; i<3; i++){
        if (user_arr.includes(com_arr[i])){
            console.log(com_arr[i]);
            console.log(user_arr);
            temp_ball_cnt += 1
        }
    }
    return temp_ball_cnt;
}
// strike ๊ฐœ์ˆ˜ ์„ธ๊ธฐ
function strikeCheck(comIN, userIN){
    let temp_strike_cnt = 0;
    if (comIN['first'] == userIN['first']){
        userIN['first'] = 10;
        temp_strike_cnt += 1;
    }
    if (comIN['second'] == userIN['second']){
        userIN['second'] = 10;
        temp_strike_cnt += 1;
    }
    if (comIN['third'] == userIN['third']){
        userIN['third'] = 10;
        temp_strike_cnt += 1;
    }
    return temp_strike_cnt;


}
  • export function () ~ : export๋ฅผ ํ†ตํ•ด index.js ํŒŒ์ผ์—์„œ ์ด ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.
  • gamestart : ๋ณธ๊ฒฉ์ ์œผ๋กœ game์ด ์‹œ์ž‘๋˜๋Š” ํ•จ์ˆ˜๋กœ game์˜ ๊ฒฐ๊ณผ๋กœ ๋ณผ์˜ ๊ฐœ์ˆ˜(ball_cnt), ์ŠคํŠธ๋ผ์ดํฌ์˜ ๊ฐœ์ˆ˜(strike_cnt)๋ฅผ returnํ•œ๋‹ค.
  • strikeCheck : ๋ฐ˜๋“œ์‹œ ballCheck ์ „์— strikeCheck๊ฐ€ ์ˆ˜ํ–‰๋˜์–ด์•ผ ํ•œ๋‹ค. ์™œ๋ƒํ•˜๋ฉด, strike๋Š” ball๋กœ ์นด์šดํŒ…๋˜์ง€ ์•Š๋„๋ก strike์— ํ•ด๋‹นํ•˜๋Š” value๋ฅผ ์ˆ˜์ •ํ•ด๋ฒ„๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์ปดํ“จํ„ฐ์˜ ๋žœ๋ค๊ฐ’ ์ƒ์„ฑ

index.html์ด ์ตœ์ดˆ ๋กœ๋”ฉ๋  ๋•Œ, ๋žœ๋ค ๋„˜๋ฒ„๋ฅผ ์ƒ์„ฑํ•˜์—ฌ user๊ฐ€ ๋งž์ถœ ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„ํ•œ๋‹ค. ์œ ์˜ํ•  ์ ์€ form tag์˜ button์„ ํด๋ฆญํ•˜์—ฌ๋„ ์ด ๋žœ๋ค ๊ฐ’์€ ๋ณ€๊ฒฝ๋˜๋ฉด ์•ˆ ๋œ๋‹ค๋Š” ์ ์ด๋‹ค. ์ด๋ฅผ ๊ณ ๋ คํ•˜๋ฉด, ./index.js ํŒŒ์ผ์—์„œ script๊ฐ€ ํŒŒ์‹ฑ๋  ๋•Œ ์ตœ์ดˆ ํ˜ธ์ถœ๋˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์•„ ๋ณด์ธ๋‹ค.

// src/index.js

function generateRandom(){
  const randomNumber1 = MissionUtils.Random.pickNumberInRange(1, 9);
  const randomNumber2 = MissionUtils.Random.pickNumberInRange(1, 9);
  while (randomNumber1 == randomNumber2){
    randomNumber2 = MissionUtils.Random.pickNumberInRange(1, 9);
  }
  const randomNumber3 = MissionUtils.Random.pickNumberInRange(1, 9);
  while (randomNumber1 == randomNumber3 | randomNumber2 == randomNumber3){
    randomNumber3 = MissionUtils.Random.pickNumberInRange(1, 9);
  }
  return randomNumber1 * 100 + randomNumber2 * 10 + randomNumber3;
}
...
const randomNumber = generateRandom();
const form = document.querySelector("form");
form.addEventListener('submit', function(event) {
  ...
  let result_str = game.play(userInput, randomNumber);
  ...
});
  • generateRandom : ์ค‘๋ณต๋˜๋Š” ์ˆซ์ž๊ฐ€ ์ƒ์„ฑ๋˜๋ฉด ์•ˆ ๋˜๊ธฐ์— ์ƒ์„ฑ ์‹œ ํ™•์ธํ•˜์—ฌ ์ค‘๋ณต๋  ๊ฒฝ์šฐ ์žฌ์ƒ์„ฑ๋  ์ˆ˜ ์žˆ๋„๋ก while ๋ฌธ์„ ๊ตฌ์„ฑํ•œ๋‹ค.

๊ฒฐ๊ณผ ๋ฌธ์ž์—ด ์ถœ๋ ฅ ๋ฐ ํ‘œ์‹œ

๋ณผ, ์ŠคํŠธ๋ผ์ดํฌ์˜ ๊ฐœ์ˆ˜๋ฅผ ๋ฐ›์•˜์œผ๋ฏ€๋กœ ์ด์— ๋”ฐ๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„ํ•œ๋‹ค. ์ด๋Š” ๊ธฐ๋Šฅ ์š”๊ตฌ์‚ฌํ•ญ์— ๋”ฐ๋ผ ์ถœ๋ ฅ๋˜๋„๋ก ํ•œ๋‹ค.

export function resultStr (ball_cnt, strike_cnt){
    let result;
    if (ball_cnt == 0 & strike_cnt == 0){
        result = '๋‚ซ์‹ฑ';
        return result;
    }
    if (ball_cnt == 0){
        result = strike_cnt + "์ŠคํŠธ๋ผ์ดํฌ"
        return result;
    }
    if (strike_cnt == 0){
        result = ball_cnt + "๋ณผ"
        return result;
    }
    result = ball_cnt + "๋ณผ" + " " + strike_cnt + "์ŠคํŠธ๋ผ์ดํฌ";
    return result;
}

export function displayResult(str){
    document.getElementById("result").innerText=str;
}
  • resultStr : ๋ณผ, ์ŠคํŠธ๋ผ์ดํฌ ๊ฐœ์ˆ˜์— ๋”ฐ๋ผ์„œ result์— ์•Œ๋งž๋Š” ๋ฌธ์ž์—ด์„ ํ• ๋‹นํ•˜์—ฌ return ํ•œ๋‹ค.
  • displayResult : ๋ฐ˜ํ™˜ ๋ฐ›์€ ๋ฌธ์ž์—ด์„ Element ID๊ฐ€ "result"์ธ ํƒœ๊ทธ์˜ ๋‚ด๋ถ€ text ๊ฐ’์œผ๋กœ ํ• ๋‹นํ•œ๋‹ค. text ๊ฐ’์—๋Š” ์•ž์„œ ์ƒ์„ฑํ•œ ๋ฌธ์ž์—ด์ด ํ• ๋‹น๋œ๋‹ค.

์œ ํšจํ•˜์ง€ ์•Š์€ ์ž…๋ ฅ์ฐฝ alert ์ฒ˜๋ฆฌ

//src/util.js
export function isInputValid(input_str){
    if (122 < input_str & input_str < 977){
        return true;
    }
    return false;
}

//src/index.js
form.addEventListener('submit', function(event) {
  ...
  if (isInputValid(userInput)){
    let game = new BaseballGame;
    let result_str = game.play(userInput, randomNumber);
    displayResult(result_str);
  }
  else{
    window.alert("invalid input");
  }
  • isInputValid : input ๊ฐ’์ด 123๋ถ€ํ„ฐ 987๊นŒ์ง€ ์ž…๋ ฅ๋˜๋ฏ€๋กœ ์œ„์™€ ๊ฐ™์ด ๋ฒ”์œ„๋ฅผ ์ฃผ์—ˆ๋‹ค. ์ค‘๋ณต๊ฐ’์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ๊ฐ€ ๋ฏธํกํ•˜์—ฌ ๋ณด์™„ ์˜ˆ์ •์ด๋‹ค.
  • ์œ ํšจ ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ window.alert() ํ•จ์ˆ˜๋กœ ์•ˆ๋‚ด ์ฐฝ์„ pop-up ํ•œ๋‹ค.

npm run test๋ฅผ ํ†ตํ•ด cypress๋ฅผ ์‹คํ–‰์‹œ์ผœ test๊ฐ€ ํ†ต๊ณผํ•˜๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ๋‹ค๋งŒ, ์ด๋Š” app.spec.js ๋‚ด์˜ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค๋ฅผ ํ†ต๊ณผํ•˜๋Š”์ง€ ์—ฌ๋ถ€๋งŒ ํ™•์ธ ๊ฐ€๋Šฅํ•˜์—ฌ ์„ธ๋ถ€ ๊ธฐ๋Šฅ ๊ตฌํ˜„์ด ์™„๋ฃŒ๋˜์—ˆ๋‹ค๋Š” ๋ณด์žฅ์„ ํ•  ์ˆ˜ ์—†๋‹ค.

์–ธ์ œ ๋ณด์•„๋„ ๋ณด๊ธฐ ์ข‹์€ ์ดˆ๋ก ๊ธ€์”จ PASS