import test from 'node:test' import assert from 'node:assert/strict' import { PassThrough } from 'node:stream' import path from 'node:path' import fs from 'node:fs' import sinon from 'sinon' import fsMock from 'mock-fs' import chalk from 'chalk' import getStream from 'get-stream' import date from 'date-and-time' import { cli } from '../../../cli.js' import { isExistingPath } from '../../../utils/isExistingPath.js' const input = ['generate', 'challenge'] const githubUser = 'theoludwig' const challenge = 'aaaa-test-jest' const inputChallenge = `--challenge=${challenge}` const inputGitHubUser = `--github-user=${githubUser}` await test('programming-challenges generate challenge', async (t) => { t.beforeEach(() => { fsMock( { [process.cwd()]: fsMock.load(process.cwd(), { recursive: true, lazy: true }) }, { createCwd: false } ) }) t.afterEach(() => { fsMock.restore() sinon.restore() }) await t.test('succeeds and generate the new challenge', async () => { sinon.stub(console, 'log').value(() => {}) const consoleLogSpy = sinon.spy(console, 'log') const dateString = date.format(new Date(), 'D MMMM Y', true) const stream = new PassThrough() const exitCode = await cli.run( [...input, inputChallenge, inputGitHubUser], { stdin: process.stdin, stdout: stream, stderr: stream } ) stream.end() assert.strictEqual(exitCode, 0) const challengePath = path.join(process.cwd(), 'challenges', challenge) const readmePath = path.join(challengePath, 'README.md') const readmeContent = await fs.promises.readFile(readmePath, { encoding: 'utf-8' }) const successMessage = `${chalk.bold.green( 'Success:' )} created the new challenge at ${challengePath}.` assert.strictEqual(consoleLogSpy.calledWith(successMessage), true) assert.strictEqual(await isExistingPath(challengePath), true) assert.strictEqual( readmeContent, `# ${challenge} Created by [@${githubUser}](https://github.com/${githubUser}) on ${dateString}. ## Instructions Description of the challenge... ## Examples See the \`test\` folder for examples of input/output. ` ) }) await t.test('fails without options', async () => { const stream = new PassThrough() const promise = getStream(stream) const exitCode = await cli.run(input, { stdin: process.stdin, stdout: stream, stderr: stream }) stream.end() assert.strictEqual(exitCode, 1) const output = await promise assert.match(output, /Unknown Syntax Error/) }) await t.test('fails with already existing challenge', async () => { sinon.stub(console, 'error').value(() => {}) const consoleErrorSpy = sinon.spy(console, 'error') const stream = new PassThrough() const exitCode = await cli.run( [...input, '--challenge=hello-world', inputGitHubUser], { stdin: process.stdin, stdout: stream, stderr: stream } ) stream.end() assert.strictEqual(exitCode, 1) assert.strictEqual( consoleErrorSpy.calledWith( `${chalk.bold.red('Error:')} The challenge already exists: hello-world.` ), true ) }) await t.test('fails with invalid challenge name', async () => { sinon.stub(console, 'error').value(() => {}) const consoleErrorSpy = sinon.spy(console, 'error') const stream = new PassThrough() const exitCode = await cli.run( [...input, '--challenge=hEllO-world', inputGitHubUser], { stdin: process.stdin, stdout: stream, stderr: stream } ) stream.end() assert.strictEqual(exitCode, 1) assert.strictEqual( consoleErrorSpy.calledWith( `${chalk.bold.red('Error:')} Invalid challenge name.` ), true ) }) })