Create an application that will return a random color in the command line.
It should work like this:
When a user enters node index.js
in the command line, a block of 31x9 #
characters colored with a random color (using hex code, e.g. #ff0000
) should be generated.
It should look like this:
In addition to node index.js
, it should also be able to accept the request for a:
- hue (eg. green or red or blue)
- luminosity (eg. light or dark)
...and then generate random colors that match those choices.
For example:
When you believe you are done, set up a test:
- Create a directory called
.github
(there is a dot at the start) - Create a directory called
workflows
inside.github
- Create a file called
test.yml
insideworkflows
containing the following code
name: Test Project
on: push
jobs:
test:
name: Test Project
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
with:
version: 'latest'
- uses: actions/setup-node@v4
with:
node-version: 'lts/*'
cache: 'pnpm'
- name: Install project dependencies
run: pnpm install
- name: Install test dependencies
run: pnpm add --save-dev strip-ansi
- name: Create test file
# Create a test file that will run index.js from the project
# with Node.js and check that it roughly matches the
# following pattern (9 rows, 31 columns, with a space in the
# center and a hex code in the middle):
#
# ###############################
# ###############################
# ###############################
# ##### #####
# ##### #edff28 #####
# ##### #####
# ###############################
# ###############################
# ###############################
#
# The pattern will be matched in a forgiving way:
# - Unlimited number of spaces at the start of each line
# - Minimum 1 # character left and right border
# - Minimum 1 # character top and bottom border
# - Minimum 1 space surrounding the hex code
# - Minimum 11 columns
# - Minimum 5 rows
run: |
cat > test.js <<'END_SCRIPT'
import { exec } from 'node:child_process';
import { promisify } from 'node:util';
import stripAnsi from 'strip-ansi';
const execAsync = promisify(exec);
const { stdout: stdoutNoArgs1 } = await execAsync('node index.js');
const pattern =
/^( *#{11,}\n){1,} *#{1,} +#{1,}\n *#{1,} +(#[A-Fa-f0-9]{6}) +#{1,}\n *#{1,} +#{1,}\n( *#{11,}\n){1,}/m;
// Get hex color from the output
const matchNoArgs1 = stripAnsi(stdoutNoArgs1).match(pattern);
if (!matchNoArgs1) {
console.log('❌ `node index.js` (run 1): pattern did not match');
process.exit(1);
}
console.log('✔️ `node index.js` (run 1): pattern matched');
const [, , hexCodeNoArgs1] = matchNoArgs1;
const { stdout: stdoutNoArgs2 } = await execAsync('node index.js');
const match2 = stripAnsi(stdoutNoArgs2).match(pattern);
if (!match2) {
console.log('❌ `node index.js` (run 2): pattern did not match');
process.exit(1);
}
console.log('✔️ `node index.js` (run 2): pattern matched');
const [, , hexCodeNoArgs2] = match2;
const { stdout: stdoutNoArgs3 } = await execAsync('node index.js');
const match3 = stripAnsi(stdoutNoArgs3).match(pattern);
if (!match3) {
console.log('❌ `node index.js` (run 3): pattern did not match');
process.exit(1);
}
console.log('✔️ `node index.js` (run 3): pattern matched');
const [, , hexCodeNoArgs3] = match3;
if (hexCodeNoArgs1 === hexCodeNoArgs2 && hexCodeNoArgs2 === hexCodeNoArgs3) {
console.log(
`❌ \`node index.js\` (all 3 runs): the hex code was the same: ${hexCodeNoArgs1}`,
);
process.exit(1);
}
console.log(
`✔️ \`node index.js\` (all 3 runs): the hex code was different: ${hexCodeNoArgs1}, ${hexCodeNoArgs2}, ${hexCodeNoArgs3}`,
);
const { stdout: stdoutRed } = await execAsync('node index.js red');
const matchRed = stripAnsi(stdoutRed).match(pattern);
if (!matchRed) {
console.log('❌ `node index.js red`: pattern did not match');
process.exit(1);
}
console.log('✔️ `node index.js red`: pattern matched');
const [, , hexCodeRed] = matchRed;
function hexCodeLikeColor(hexCode, color) {
const r = parseInt(hexCode.slice(1, 3), 16);
const g = parseInt(hexCode.slice(3, 5), 16);
const b = parseInt(hexCode.slice(5, 7), 16);
if (color === 'red') return r >= Math.max(g, b);
const luminosity = 0.2126 * r + 0.7152 * g + 0.0722 * b; // #ffffff is 255
return (
b >=
Math.max(
r,
// Adjust green for turquoises
g - 10,
) && luminosity <= 128
); // blue dark
}
if (!hexCodeLikeColor(hexCodeRed, 'red')) {
console.log(
`❌ \`node index.js red\`: the hex code ${hexCodeRed} is not red`,
);
process.exit(1);
}
console.log(`✔️ \`node index.js red\`: the hex code ${hexCodeRed} is red`);
const { stdout: stdoutBlueDark } = await execAsync('node index.js blue dark');
const matchBlueDark = stripAnsi(stdoutBlueDark).match(pattern);
if (!matchBlueDark) {
console.log('❌ `node index.js blue dark`: pattern did not match');
process.exit(1);
}
console.log('✔️ `node index.js blue dark`: pattern matched');
const [, , hexCodeBlueDark] = matchBlueDark;
if (!hexCodeLikeColor(hexCodeBlueDark, 'blue')) {
console.log(
`❌ \`node index.js blue dark\`: the hex code ${hexCodeBlueDark} is not dark blue`,
);
process.exit(1);
}
console.log(
`✔️ \`node index.js blue dark\`: the hex code ${hexCodeBlueDark} is dark blue`,
);
console.log('✔️ All tests passed');
END_SCRIPT
- name: Run test file
run: node test.js
- If a user types "ask" instead of a color name, print questions to ask the user for the name of the color and the luminosity
- If a user types a size in the format of
WWxHH
(eg.31x9
) before the color and luminosity, it will use this as the size of the box
- Preflight runs through without errors in your project
- Link in your GitHub repo's About section: Replit demo
- Drone bot has been tagged and responded with a passing message
- Correct GitHub commit message format (see Writing Commit Messages)