From 61485cc73ca4e695cd61fdebd73377d6ab9fddf3 Mon Sep 17 00:00:00 2001 From: Steve Kinney Date: Tue, 24 Sep 2024 15:56:02 -0600 Subject: [PATCH] Add examples --- examples/guess-the-number/game.js | 33 ++++++++++++++++++++++ examples/guess-the-number/index.js | 38 ++++++++++++-------------- examples/guess-the-number/package.json | 3 ++ examples/yearbook/package.json | 24 ++++++++++++++++ examples/yearbook/person.js | 31 +++++++++++++++++++++ examples/yearbook/person.test.js | 9 ++++++ package-lock.json | 31 ++++++++++++++++++++- package.json | 5 ++-- 8 files changed, 150 insertions(+), 24 deletions(-) create mode 100644 examples/guess-the-number/game.js create mode 100644 examples/yearbook/package.json create mode 100644 examples/yearbook/person.js create mode 100644 examples/yearbook/person.test.js diff --git a/examples/guess-the-number/game.js b/examples/guess-the-number/game.js new file mode 100644 index 0000000..593d9c4 --- /dev/null +++ b/examples/guess-the-number/game.js @@ -0,0 +1,33 @@ +export class Game { + /** + * A number guessing game. + * @param {number} minimum - The minimum number to guess. + * @param {number} maximum - The maximum number to guess. + */ + constructor(minimum, maximum) { + this.secretNumber = Math.ceil(Math.random() * maximum - minimum) + minimum; + this.guesses = new Set(); + + console.log(`Guess the number between ${minimum} and ${maximum}.`); + } + + /** + * Make a guess for the secret number. + * @param {number} number - The number to guess. + */ + guess(number) { + if (this.guesses.has(number)) { + return 'You already guessed that number!'; + } + + this.guesses.add(number); + + if (number < this.secretNumber) { + return 'Too low!'; + } else if (number > this.secretNumber) { + return 'Too high!'; + } else if (number === this.secretNumber) { + return `Correct! You guessed the number in ${this.guesses.size} attempts.`; + } + } +} diff --git a/examples/guess-the-number/index.js b/examples/guess-the-number/index.js index e46c384..076057e 100644 --- a/examples/guess-the-number/index.js +++ b/examples/guess-the-number/index.js @@ -1,38 +1,34 @@ -// Import the readline module to handle user input +import { Game } from './game.js'; +import chalk from 'chalk'; import { createInterface } from 'readline'; -// Create an interface for reading from stdin (standard input) const rl = createInterface({ input: process.stdin, output: process.stdout, }); -// Generate a random number between 1 and 100 -const randomNumber = Math.floor(Math.random() * 100) + 1; -let attempts = 0; +let game = new Game(1, 100); -// Function to handle user's guess -function askQuestion() { - rl.question('Guess the number (between 1 and 100): ', (answer) => { +function startGame() { + rl.question(`Guess ${chalk.cyanBright('→')} `, (answer) => { const guess = parseInt(answer, 10); - attempts++; // Check if the user's guess is correct if (isNaN(guess)) { - console.log('Please enter a valid number.'); - askQuestion(); // Ask again if input is invalid - } else if (guess < randomNumber) { - console.log('Too low!'); - askQuestion(); // Ask again - } else if (guess > randomNumber) { - console.log('Too high!'); - askQuestion(); // Ask again + console.log(chalk.red('Please enter a valid number.')); + startGame(); + } + + const result = game.guess(guess); + + console.log(result); + + if (result.startsWith('Correct')) { + rl.close(); } else { - console.log(`Correct! You guessed the number in ${attempts} attempts.`); - rl.close(); // End the game + startGame(); } }); } -// Start the game by asking the first question -askQuestion(); +startGame(); diff --git a/examples/guess-the-number/package.json b/examples/guess-the-number/package.json index 315f30a..60c41d2 100644 --- a/examples/guess-the-number/package.json +++ b/examples/guess-the-number/package.json @@ -21,5 +21,8 @@ "@vitest/ui": "^2.1.1", "vite": "^5.4.5", "vitest": "^2.1.1" + }, + "dependencies": { + "chalk": "^5.3.0" } } diff --git a/examples/yearbook/package.json b/examples/yearbook/package.json new file mode 100644 index 0000000..dca4a4c --- /dev/null +++ b/examples/yearbook/package.json @@ -0,0 +1,24 @@ +{ + "name": "yearbook", + "version": "1.0.0", + "main": "index.js", + "type": "module", + "scripts": { + "test": "vitest" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/stevekinney/testing-javascript.git" + }, + "author": "Steve Kinney ", + "license": "MIT", + "bugs": { + "url": "https://github.com/stevekinney/testing-javascript/issues" + }, + "homepage": "https://github.com/stevekinney/testing-javascript#readme", + "devDependencies": { + "@vitest/ui": "^2.1.1", + "vite": "^5.4.5", + "vitest": "^2.1.1" + } +} diff --git a/examples/yearbook/person.js b/examples/yearbook/person.js new file mode 100644 index 0000000..6c7e00b --- /dev/null +++ b/examples/yearbook/person.js @@ -0,0 +1,31 @@ +export class Person { + /** + * A person in the yearbook. + * @param {string} firstName + * @param {string} lastName + * @param {string} dateOfBirth + */ + constructor(firstName, lastName, dateOfBirth) { + this.firstName = firstName; + this.lastName = lastName; + this.dateOfBirth = dateOfBirth; + } + + get fullName() { + return `${this.firstName} ${this.lastName}`; + } + + get age() { + const today = new Date(); + const birthDate = new Date(this.dateOfBirth); + + let age = today.getFullYear() - birthDate.getFullYear(); + const month = today.getMonth() - birthDate.getMonth(); + + if (month < 0 || (month === 0 && today.getDate() < birthDate.getDate())) { + age--; + } + + return age; + } +} diff --git a/examples/yearbook/person.test.js b/examples/yearbook/person.test.js new file mode 100644 index 0000000..5f31485 --- /dev/null +++ b/examples/yearbook/person.test.js @@ -0,0 +1,9 @@ +import { describe, expect, it } from 'vitest'; +import { Person } from './person'; + +describe('Person', () => { + it('should be an instance of a Person', () => { + const person = new Person('John', 'Doe', '2000-01-01'); + expect(person).toBeInstanceOf(Person); + }); +}); diff --git a/package-lock.json b/package-lock.json index 79dfaba..db8703f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,8 @@ "examples/characters", "examples/accident-counter", "packages/css-configuration", - "packages/utility-belt" + "packages/utility-belt", + "examples/yearbook" ], "devDependencies": { "prettier": "^3.3.3", @@ -102,12 +103,27 @@ "examples/guess-the-number": { "version": "1.0.0", "license": "MIT", + "dependencies": { + "chalk": "^5.3.0" + }, "devDependencies": { "@vitest/ui": "^2.1.1", "vite": "^5.4.5", "vitest": "^2.1.1" } }, + "examples/guess-the-number/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "examples/task-list": { "version": "1.0.0", "license": "MIT", @@ -153,6 +169,15 @@ "vitest": "^2.1.1" } }, + "examples/yearbook": { + "version": "1.0.0", + "license": "MIT", + "devDependencies": { + "@vitest/ui": "^2.1.1", + "vite": "^5.4.5", + "vitest": "^2.1.1" + } + }, "node_modules/@adobe/css-tools": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.0.tgz", @@ -6609,6 +6634,10 @@ "node": ">=8" } }, + "node_modules/yearbook": { + "resolved": "examples/yearbook", + "link": true + }, "packages/css-configuration": { "version": "1.0.0", "license": "MIT", diff --git a/package.json b/package.json index d55dc59..b0e3cf9 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "A set of examples and exercises for Steve Kinney's \"Introduction to Testing\" course for Frontend Masters.", "main": "index.js", "scripts": { - "test": "vitest", + "test": "echo \"Please run the tests from inside one of the examples!\" && exit 0", "format": "prettier --write ." }, "repository": { @@ -35,7 +35,8 @@ "examples/characters", "examples/accident-counter", "packages/css-configuration", - "packages/utility-belt" + "packages/utility-belt", + "examples/yearbook" ], "devDependencies": { "prettier": "^3.3.3",