Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
6c7a96d
initial commit
boramson Nov 25, 2024
30a006a
docs(README): 구현할 기능 목록 작성
boramson Nov 25, 2024
e3ec6a2
feat(constants): inputMessages 상수화
boramson Nov 25, 2024
6464421
feat(InputView): 입력받을 값 내용 정의
boramson Nov 25, 2024
4237548
feat(controller): [입력] 로또 구입 금액을 입력받는다.
boramson Nov 25, 2024
b6b7dd5
feat(module) : [입력] 로또 구입 금액을 입력받는다. with validation
boramson Nov 25, 2024
b59e2da
feat(constants): errorMessages 상수화
boramson Nov 25, 2024
6b2b920
feat(validation): 여러가지 상황에서 사용될 validtaion 클래스 생성
boramson Nov 25, 2024
b51406f
feat(constants): outputMessages 상수화
boramson Nov 25, 2024
b5e1cff
feat(OutputView): 출력될 내용 정의
boramson Nov 25, 2024
4a3c8db
fix(module): awiat 코드 추가
boramson Nov 25, 2024
328ea43
fix(module): InputPurchaseModule이 구매수량을 return할 수 있도록 만들었습니다.
boramson Nov 25, 2024
c1f4bf8
feat(contorller): [출력] 발행한 로또 수량 및 번호를 출력한다.
boramson Nov 25, 2024
6ae0035
feat(OutputView): 수정 및 일부 코드 추가
boramson Nov 25, 2024
d9cd286
feat(controller): [출력] 발행한 로또 수량 및 번호를 출력한다. 로또 번호는 오름차순으로 정렬하여 보여준다.
boramson Nov 25, 2024
03cb4f5
feat(module): 검증된 Lotto번호 최종 return 할 수 있도록 만듬
boramson Nov 25, 2024
25899e5
feat(module): 보너스넘버를 입력받고 validation 하는 클래스
boramson Nov 25, 2024
1bb4cd7
feat(controller): [입력] 보너스 번호를 입력 받는다.
boramson Nov 25, 2024
f4943c4
feat(constants): outputMessages 상수 추가
boramson Nov 25, 2024
a286cfc
feat(OutputView): 출력에 필요한 내용 추가
boramson Nov 25, 2024
bd8d4b9
============ 5시간 내 구현을 하지 못함 ================
boramson Nov 26, 2024
27a258f
chroe: LottoController 한줄로 만들었습니다.
boramson Nov 29, 2024
b771a16
feat(constants): errorMessage 중복제거, ERROR_MESSAGES 키값 상수명칭에서 카멜케이스로 변…
boramson Nov 29, 2024
26ef7b2
chore: errorMessages.js export 변경으로 인하여 import {} 추가
boramson Nov 29, 2024
6b3b3f9
chore(constants): outputMessages 키명칭 카멜케이스로 변경
boramson Nov 29, 2024
2e0ea5c
chore(constants): outputMessages 키명칭 카멜케이스로 변경에 따른 print 명칭 변경
boramson Nov 29, 2024
ad80c86
chore(constants): inputMessages 키명칭 카멜케이스로 변경
boramson Nov 29, 2024
14650ef
chore(OInputView): inputMessages 키명칭 카멜케이스로 변경에 따른 print 명칭 변경
boramson Nov 29, 2024
732e159
chore(constants): errorMessages 키명칭 카멜케이스로 변경
boramson Nov 30, 2024
0f79b81
feat(util): throw Error 중복 제거를 위한 util 함수 생성
boramson Nov 30, 2024
e247daa
feat(validation) : throw new Error를 createThrowError() 함수로 변경
boramson Nov 30, 2024
07b2974
chore: 알파벳 오타 수정
boramson Nov 30, 2024
9b66531
feat(validation): add method winningNumberSixDigit
boramson Nov 30, 2024
cd1d4ca
feat(module): add validation winningNumberSixDigit
boramson Nov 30, 2024
3d59a8c
feat(validation): add Mesaage winningNumberSixDigit
boramson Nov 30, 2024
bc20677
chore: ERROR_MESSAGE import 변경 및 키명칭 변경
boramson Nov 30, 2024
90c1edf
feat(module): ERROR_MESSAGE import 변경 및 키명칭 변경 / construct를 통해 winni…
boramson Nov 30, 2024
db0d3bb
feat(validation): add new method 'isDuplicatedInWinningNumber'
boramson Nov 30, 2024
a61eb34
feat(constants): add ERROR_MESSAGES 'isDuplicatedInWinningNumber'
boramson Nov 30, 2024
6c30c61
chore(module): console.log 제거
boramson Nov 30, 2024
c42cb60
chore: return 제거
boramson Nov 30, 2024
b0e07b8
feat(module): 구매수량을 리턴하는 클래스에서 구매금액을 리턴하는 클래스로 변경
boramson Nov 30, 2024
1ddce8f
chore: 단순 띄어쓰기 수정
boramson Nov 30, 2024
f05b992
chore: 단순 outputMessage 키값 수정
boramson Nov 30, 2024
2303ec1
chore: matchedFiveBonus: '5개 일치, 보너스 볼 일치 (30,000,000원) - ', 에서 보너스 볼…
boramson Nov 30, 2024
cae0e80
feat(module): 당첨내역과 총 수익률을 출력하는 기능목록 구현
boramson Nov 30, 2024
6642614
feat(controller): [출력] 당첨 내역을 출력한다. / [출력] 총 수익률을 출력한다.
boramson Nov 30, 2024
8276e3c
feat(module): printRandomNumber Module로 만들고, import로 가져와서 사용하기
boramson Nov 30, 2024
bcfc800
chore: 주석 제거
boramson Nov 30, 2024
ab5ebca
chore: console.log 제거하지 않는 실수를 지속적으로 반복함.
boramson Nov 30, 2024
37b5a4d
chore: prettier 적용
boramson Nov 30, 2024
273b81b
feat(constant): add errorMessage 'isDuplicatedInLottoNumbers'
boramson Nov 30, 2024
67c50ec
feat(Lotto.js): add validation 'isDuplicatedInLottoNumbers'
boramson Nov 30, 2024
a0c7481
feat(validation): add validation 'isDuplicatedInLottoNumbers'
boramson Nov 30, 2024
e4bb927
feat(module): add validation 'isDuplicatedInLottoNumbers' in InputWin…
boramson Nov 30, 2024
c726bcd
feat(util): const ERROR_PREFIX = '[ERROR]';를 출력 시켜 test 코드를 통과하려고 함.
boramson Nov 30, 2024
6b83281
feat(util): 문자열을 배열로 바꾸는 도구
boramson Dec 1, 2024
5cec1e2
fix(validation): new Set() 배열이 들어가지 않고 있는 점 수정 in isDuplicatedInLotto…
boramson Dec 1, 2024
e9d5752
test: 기능별 test code 만들기
boramson Dec 1, 2024
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
66 changes: 66 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,67 @@
# javascript-lotto-precourse

 

 

# ✅ 구현할 기능 목록

간단한 로또 발매기를 구현한다.

 

### 🟢 [입력] 로또 구입 금액을 입력받는다.

#### ㄴ validation

- 예외 상황 시 에러 문구를 출력해야 한다. 단, 에러 문구는 "[ERROR]"로 시작해야 한다.
- 구입 금액은 1,000원 단위로 입력 받으며 1,000원으로 나우어 떨어지지 않는 경우 예외 처리한다.

 

 

### 🟢 [출력] 발행한 로또 수량 및 번호를 출력한다. 로또 번호는 오름차순으로 정렬하여 보여준다.

 

 

### 🟢 [입력] 당첨번호를 입력 받는다. 번호는 쉼표(,)를 기준으로 구분한다.

#### ㄴ validation

- 예외 상황 시 에러 문구를 출력해야 한다. 단, 에러 문구는 "[ERROR]"로 시작해야 한다.

 

 

### 🟢 [입력] 보너스 번호를 입력 받는다.

#### ㄴ validation

- 예외 상황 시 에러 문구를 출력해야 한다. 단, 에러 문구는 "[ERROR]"로 시작해야 한다.

 

 

### 🟢 [출력] 당첨 내역을 출력한다.

<출력 예시>
당첨 통계

\---

3개 일치 (5,000원) - 1개

&nbsp;

&nbsp;

### 🟢 [출력] 총 수익률을 출력한다.

수익률은 소수점 둘쨰 자리에서 반올림 한다. (ex. 100.0%, 51.5%, 1,000,000.0%)

-
50 changes: 25 additions & 25 deletions __tests__/ApplicationTest.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import App from "../src/App.js";
import { MissionUtils } from "@woowacourse/mission-utils";
import App from '../src/App.js';
import { MissionUtils } from '@woowacourse/mission-utils';

const mockQuestions = (inputs) => {
MissionUtils.Console.readLineAsync = jest.fn();
Expand All @@ -19,7 +19,7 @@ const mockRandoms = (numbers) => {
};

const getLogSpy = () => {
const logSpy = jest.spyOn(MissionUtils.Console, "print");
const logSpy = jest.spyOn(MissionUtils.Console, 'print');
logSpy.mockClear();
return logSpy;
};
Expand All @@ -29,7 +29,7 @@ const runException = async (input) => {
const logSpy = getLogSpy();

const RANDOM_NUMBERS_TO_END = [1, 2, 3, 4, 5, 6];
const INPUT_NUMBERS_TO_END = ["1000", "1,2,3,4,5,6", "7"];
const INPUT_NUMBERS_TO_END = ['1000', '1,2,3,4,5,6', '7'];

mockRandoms([RANDOM_NUMBERS_TO_END]);
mockQuestions([input, ...INPUT_NUMBERS_TO_END]);
Expand All @@ -39,15 +39,15 @@ const runException = async (input) => {
await app.run();

// then
expect(logSpy).toHaveBeenCalledWith(expect.stringContaining("[ERROR]"));
expect(logSpy).toHaveBeenCalledWith(expect.stringContaining('[ERROR]'));
};

describe("로또 테스트", () => {
describe('로또 테스트', () => {
beforeEach(() => {
jest.restoreAllMocks();
});

test("기능 테스트", async () => {
test('기능 테스트', async () => {
// given
const logSpy = getLogSpy();

Expand All @@ -61,37 +61,37 @@ describe("로또 테스트", () => {
[2, 13, 22, 32, 38, 45],
[1, 3, 5, 14, 22, 45],
]);
mockQuestions(["8000", "1,2,3,4,5,6", "7"]);
mockQuestions(['8000', '1,2,3,4,5,6', '7']);

// when
const app = new App();
await app.run();

// then
const logs = [
"8개를 구매했습니다.",
"[8, 21, 23, 41, 42, 43]",
"[3, 5, 11, 16, 32, 38]",
"[7, 11, 16, 35, 36, 44]",
"[1, 8, 11, 31, 41, 42]",
"[13, 14, 16, 38, 42, 45]",
"[7, 11, 30, 40, 42, 43]",
"[2, 13, 22, 32, 38, 45]",
"[1, 3, 5, 14, 22, 45]",
"3개 일치 (5,000원) - 1개",
"4개 일치 (50,000원) - 0개",
"5개 일치 (1,500,000원) - 0개",
"5개 일치, 보너스 볼 일치 (30,000,000원) - 0개",
"6개 일치 (2,000,000,000원) - 0개",
"총 수익률은 62.5%입니다.",
'8개를 구매했습니다.',
'[8, 21, 23, 41, 42, 43]',
'[3, 5, 11, 16, 32, 38]',
'[7, 11, 16, 35, 36, 44]',
'[1, 8, 11, 31, 41, 42]',
'[13, 14, 16, 38, 42, 45]',
'[7, 11, 30, 40, 42, 43]',
'[2, 13, 22, 32, 38, 45]',
'[1, 3, 5, 14, 22, 45]',
'3개 일치 (5,000원) - 1개',
'4개 일치 (50,000원) - 0개',
'5개 일치 (1,500,000원) - 0개',
'5개 일치, 보너스 볼 일치 (30,000,000원) - 0개',
'6개 일치 (2,000,000,000원) - 0개',
'총 수익률은 62.5%입니다.',
];

logs.forEach((log) => {
expect(logSpy).toHaveBeenCalledWith(expect.stringContaining(log));
});
});

test("예외 테스트", async () => {
await runException("1000j");
test('예외 테스트', async () => {
await runException('1000j');
});
});
41 changes: 41 additions & 0 deletions __tests__/InputBonusModule.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import InputBonusModule from '../src/modules/InputBonusModule';

describe('로또 구입 금액 검증', () => {
// given
const bonusNumber = new InputBonusModule();

// 실패하는 코드
test('당첨번호에 있는 값이 보너스번호로 입력되면 ERROR가 발생한다.', () => {
// when
const testBonusNumber = '1';
const winningNumber = [1, 2, 3, 4, 5, 6];

// then
expect(() => {
bonusNumber.validateBonusNumber(testBonusNumber, winningNumber);
}).toThrow('[ERROR]');
});

// 성공하는 코드
test('당첨번호에 있는 값이 보너스번호로 입력될 수 없다.', () => {
// when
const testBonusNumber = '7';
const winningNumber = [1, 2, 3, 4, 5, 6];

// then
expect(() => {
bonusNumber.validateBonusNumber(testBonusNumber, winningNumber);
}).toBeTruthy();
});

// (추가적인 테스트 코드)
test('입력값이 빈값이면 ERROR가 발생한다.', () => {
// when
const testBonusNumber = '';

// then
expect(() => {
bonusNumber.validateBonusNumber(testBonusNumber);
}).toThrow('[ERROR]');
});
});
39 changes: 39 additions & 0 deletions __tests__/InputPurchaseModule.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import InputPurchaseModule from '../src/modules/InputPurchaseModule';

describe('로또 구입 금액 검증', () => {
// given
const purchaseAmount = new InputPurchaseModule();

// 실패하는 코드
test('1,000원으로 나누어 떨어지지 않으면 에러', () => {
// when
const testInput = '1500';

// then
expect(() => {
purchaseAmount.validatatePrice(testInput);
}).toThrow('[ERROR]');
});

// 성공하는 코드
test('1,000원 단위로 입력 가능해야 한다', () => {
// when
const testInput = '10000';

// then
expect(() => {
purchaseAmount.validatatePrice(testInput);
}).toBeTruthy();
});

// (추가적인 테스트 코드)
test('입력값이 빈값이면 ERROR가 발생한다.', () => {
// when
const testInput = '';

// then
expect(() => {
purchaseAmount.validatatePrice(testInput);
}).toThrow('[ERROR]');
});
});
61 changes: 61 additions & 0 deletions __tests__/InputWinningModule.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import InputWinningModule from '../src/modules/InputWinningModule';

describe('로또 구입 금액 검증', () => {
// given
const winningNumber = new InputWinningModule();

// 실패하는 코드
test('당첨번호는 6자리를 입력해야한다.', () => {
// when
const testInput = '1,2,3,4,5,6,7';

// then
expect(() => {
winningNumber.validateWinningNumber(testInput);
}).toThrow('[ERROR]');
});

// 성공하는 코드
test('당첨번호는 6자리를 입력해야한다.', () => {
// when
const testInput = '1,2,3,4,5,6';

// then
expect(() => {
winningNumber.validateWinningNumber(testInput);
}).toBeTruthy();
});

// 실패하는 코드
test('6자리 중 중복값은 없어야 한다.', () => {
// when
const testInput = '1,2,3,4,5,5';

// then
expect(() => {
winningNumber.validateWinningNumber(testInput);
}).toThrow('[ERROR]');
});

// 성공하는 코드
test('6자리 중 중복값은 없어야 한다.', () => {
// when
const testInput = '1,2,3,4,5,6';

// then
expect(() => {
winningNumber.validateWinningNumber(testInput);
}).toBeTruthy();
});

// (추가적인 테스트 코드)
test('입력값이 빈값이면 ERROR가 발생한다.', () => {
// when
const testInput = '';

// then
expect(() => {
winningNumber.validateWinningNumber(testInput);
}).toThrow('[ERROR]');
});
});
12 changes: 6 additions & 6 deletions __tests__/LottoTest.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import Lotto from "../src/Lotto";
import Lotto from '../src/Lotto';

describe("로또 클래스 테스트", () => {
test("로또 번호의 개수가 6개가 넘어가면 예외가 발생한다.", () => {
describe('로또 클래스 테스트', () => {
test('로또 번호의 개수가 6개가 넘어가면 예외가 발생한다.', () => {
expect(() => {
new Lotto([1, 2, 3, 4, 5, 6, 7]);
}).toThrow("[ERROR]");
}).toThrow('[ERROR]');
});

// TODO: 테스트가 통과하도록 프로덕션 코드 구현
test("로또 번호에 중복된 숫자가 있으면 예외가 발생한다.", () => {
test('로또 번호에 중복된 숫자가 있으면 예외가 발생한다.', () => {
expect(() => {
new Lotto([1, 2, 3, 4, 5, 5]);
}).toThrow("[ERROR]");
}).toThrow('[ERROR]');
});

// TODO: 추가 기능 구현에 따른 테스트 코드 작성
Expand Down
54 changes: 54 additions & 0 deletions __tests__/PrintRandomNumber.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { MissionUtils } from '@woowacourse/mission-utils';
import PrintRandomNumber from '../src/modules/PrintRandomNumber';
import OutputView from '../src/view/OutputView';

jest.mock('../src/view/OutputView');
jest.mock('@woowacourse/mission-utils', () => ({
MissionUtils: {
Random: {
pickUniqueNumbersInRange: jest.fn(),
},
},
}));

describe('PrintRandomNumber', () => {
// given
beforeEach(() => {
OutputView.printPurchaseNumber.mockClear();
OutputView.printLottoNumber.mockClear();
OutputView.printSpace.mockClear();
MissionUtils.Random.pickUniqueNumbersInRange.mockClear();
});

const printRandomNumber = new PrintRandomNumber();
const mockPurchaseQuantity = 3;
const mockLottoNumbers = [
[1, 2, 3, 4, 5, 6],
[7, 8, 9, 10, 11, 12],
[13, 14, 15, 16, 17, 18],
];

test('로또 번호 생성 및 출력 검증', () => {
// when
MissionUtils.Random.pickUniqueNumbersInRange
.mockReturnValueOnce(mockLottoNumbers[0])
.mockReturnValueOnce(mockLottoNumbers[1])
.mockReturnValueOnce(mockLottoNumbers[2]);

// then
expect(printRandomNumber.printRandomNumber(mockPurchaseQuantity)).toEqual([
[1, 2, 3, 4, 5, 6],
[7, 8, 9, 10, 11, 12],
[13, 14, 15, 16, 17, 18],
]);

expect(OutputView.printPurchaseNumber).toHaveBeenCalledWith(mockPurchaseQuantity);
expect(OutputView.printLottoNumber).toHaveBeenCalledTimes(mockPurchaseQuantity);
expect(OutputView.printSpace).toHaveBeenCalledTimes(1);

expect(MissionUtils.Random.pickUniqueNumbersInRange).toHaveBeenCalledTimes(
mockPurchaseQuantity
);
expect(MissionUtils.Random.pickUniqueNumbersInRange).toHaveBeenCalledWith(1, 45, 6);
});
});
Loading