diff options
Diffstat (limited to 'packages/create-astro/test')
-rw-r--r-- | packages/create-astro/test/directory-step.test.js | 23 | ||||
-rw-r--r-- | packages/create-astro/test/typescript-step.test.js | 117 | ||||
-rw-r--r-- | packages/create-astro/test/utils.js | 26 |
3 files changed, 153 insertions, 13 deletions
diff --git a/packages/create-astro/test/directory-step.test.js b/packages/create-astro/test/directory-step.test.js index 0031f97fd..26737ca94 100644 --- a/packages/create-astro/test/directory-step.test.js +++ b/packages/create-astro/test/directory-step.test.js @@ -1,6 +1,8 @@ import path from 'path'; import { promises, existsSync } from 'fs'; -import { PROMPT_MESSAGES, testDir, setup, promiseWithTimeout, timeout } from './utils.js'; +import { + PROMPT_MESSAGES, testDir, setup, promiseWithTimeout, timeout +} from './utils.js'; const inputs = { nonEmptyDir: './fixtures/select-directory/nonempty-dir', @@ -12,9 +14,10 @@ const inputs = { describe('[create-astro] select directory', function () { this.timeout(timeout); it('should prompt for directory when none is provided', function () { - return promiseWithTimeout((resolve) => { + return promiseWithTimeout((resolve, onStdout) => { const { stdout } = setup(); stdout.on('data', (chunk) => { + onStdout(chunk); if (chunk.includes(PROMPT_MESSAGES.directory)) { resolve(); } @@ -22,9 +25,10 @@ describe('[create-astro] select directory', function () { }); }); it('should NOT proceed on a non-empty directory', function () { - return promiseWithTimeout((resolve) => { + return promiseWithTimeout((resolve, onStdout) => { const { stdout } = setup([inputs.nonEmptyDir]); stdout.on('data', (chunk) => { + onStdout(chunk); if (chunk.includes(PROMPT_MESSAGES.directory)) { resolve(); } @@ -46,9 +50,10 @@ describe('[create-astro] select directory', function () { if (!existsSync(resolvedEmptyDirPath)) { await promises.mkdir(resolvedEmptyDirPath); } - return promiseWithTimeout((resolve) => { + return promiseWithTimeout((resolve, onStdout) => { const { stdout } = setup([inputs.emptyDir]); stdout.on('data', (chunk) => { + onStdout(chunk); if (chunk.includes(PROMPT_MESSAGES.template)) { resolve(); } @@ -56,9 +61,10 @@ describe('[create-astro] select directory', function () { }); }); it('should proceed when directory does not exist', function () { - return promiseWithTimeout((resolve) => { + return promiseWithTimeout((resolve, onStdout) => { const { stdout } = setup([inputs.nonexistentDir]); stdout.on('data', (chunk) => { + onStdout(chunk); if (chunk.includes(PROMPT_MESSAGES.template)) { resolve(); } @@ -66,14 +72,17 @@ describe('[create-astro] select directory', function () { }); }); it('should error on bad directory selection in prompt', function () { - return promiseWithTimeout((resolve) => { + return promiseWithTimeout((resolve, onStdout) => { + let wrote = false; const { stdout, stdin } = setup(); stdout.on('data', (chunk) => { + onStdout(chunk); if (chunk.includes('is not empty!')) { resolve(); } - if (chunk.includes(PROMPT_MESSAGES.directory)) { + if (!wrote && chunk.includes(PROMPT_MESSAGES.directory)) { stdin.write(`${inputs.nonEmptyDir}\x0D`); + wrote = true; } }); }); diff --git a/packages/create-astro/test/typescript-step.test.js b/packages/create-astro/test/typescript-step.test.js new file mode 100644 index 000000000..abec21646 --- /dev/null +++ b/packages/create-astro/test/typescript-step.test.js @@ -0,0 +1,117 @@ +import { expect } from 'chai'; +import { deleteSync } from 'del'; +import { existsSync, mkdirSync, readdirSync, readFileSync } from 'fs'; +import path from 'path'; +import { + PROMPT_MESSAGES, testDir, setup, promiseWithTimeout, timeout +} from './utils.js'; + +const inputs = { + emptyDir: './fixtures/select-typescript/empty-dir', +}; + +function isEmpty(dirPath) { + return !existsSync(dirPath) || readdirSync(dirPath).length === 0; +} + +function ensureEmptyDir() { + const dirPath = path.resolve(testDir, inputs.emptyDir); + if (!existsSync(dirPath)) { + mkdirSync(dirPath, { recursive: true }); + } else if (!isEmpty(dirPath)) { + const globPath = path.resolve(dirPath, '*'); + deleteSync(globPath, { dot: true }); + } +} + +function getTsConfig(installDir) { + const filePath = path.resolve(testDir, installDir, 'tsconfig.json'); + return JSON.parse(readFileSync(filePath, 'utf-8')); +} + +describe('[create-astro] select typescript', function () { + this.timeout(timeout); + + beforeEach(ensureEmptyDir); + + afterEach(ensureEmptyDir); + + it('should prompt for typescript when none is provided', async function () { + return promiseWithTimeout((resolve, onStdout) => { + const { stdout } = setup([ + inputs.emptyDir, + '--template', 'minimal', + '--install', '0', + '--git', '0' + ]); + stdout.on('data', (chunk) => { + onStdout(chunk); + if (chunk.includes(PROMPT_MESSAGES.typescript)) { + resolve(); + } + }); + }, () => lastStdout); + }); + + it('should not prompt for typescript when provided', async function () { + return promiseWithTimeout((resolve, onStdout) => { + const { stdout } = setup([ + inputs.emptyDir, + '--template', 'minimal', + '--install', '0', + '--git', '0', + '--typescript', 'base' + ]); + stdout.on('data', (chunk) => { + onStdout(chunk); + if (chunk.includes(PROMPT_MESSAGES.typescriptSucceed)) { + resolve(); + } + }); + }, () => lastStdout); + }); + + it('should use "strict" config when specified', async function () { + return promiseWithTimeout((resolve, onStdout) => { + let wrote = false; + const { stdout, stdin } = setup([ + inputs.emptyDir, + '--template', 'minimal', + '--install', '0', + '--git', '0' + ]); + stdout.on('data', (chunk) => { + onStdout(chunk); + if (!wrote && chunk.includes(PROMPT_MESSAGES.typescript)) { + stdin.write('\x1B\x5B\x42\x0D'); + wrote = true; + } + if (chunk.includes(PROMPT_MESSAGES.typescriptSucceed)) { + const tsConfigJson = getTsConfig(inputs.emptyDir); + expect(tsConfigJson).to.deep.equal({'extends': 'astro/tsconfigs/strict'}); + resolve(); + } + }); + }, () => lastStdout); + }); + + it('should create tsconfig.json when missing', async function () { + return promiseWithTimeout((resolve, onStdout) => { + const { stdout } = setup([ + inputs.emptyDir, + '--template', 'cassidoo/shopify-react-astro', + '--install', '0', + '--git', '0', + '--typescript', 'base' + ]); + stdout.on('data', (chunk) => { + onStdout(chunk); + if (chunk.includes(PROMPT_MESSAGES.typescriptSucceed)) { + const tsConfigJson = getTsConfig(inputs.emptyDir); + expect(tsConfigJson).to.deep.equal({'extends': 'astro/tsconfigs/base'}); + resolve(); + } + }); + }, () => lastStdout); + }); +}); diff --git a/packages/create-astro/test/utils.js b/packages/create-astro/test/utils.js index b085ef083..9be444b5b 100644 --- a/packages/create-astro/test/utils.js +++ b/packages/create-astro/test/utils.js @@ -1,31 +1,45 @@ import { execa } from 'execa'; -import { fileURLToPath } from 'url'; import { dirname } from 'path'; +import stripAnsi from 'strip-ansi'; +import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); export const testDir = dirname(__filename); export const timeout = 5000; -const createAstroError = new Error( - 'Timed out waiting for create-astro to respond with expected output.' -); +const timeoutError = function (details) { + let errorMsg = + 'Timed out waiting for create-astro to respond with expected output.'; + if (details) { + errorMsg += '\nLast output: "' + details + '"'; + } + return new Error(errorMsg); +} export function promiseWithTimeout(testFn) { return new Promise((resolve, reject) => { + let lastStdout; + function onStdout (chunk) { + lastStdout = stripAnsi(chunk.toString()).trim() || lastStdout; + } + const timeoutEvent = setTimeout(() => { - reject(createAstroError); + reject(timeoutError(lastStdout)); }, timeout); function resolver() { clearTimeout(timeoutEvent); resolve(); } - testFn(resolver); + + testFn(resolver, onStdout); }); } export const PROMPT_MESSAGES = { directory: 'Where would you like to create your new project?', template: 'Which template would you like to use?', + typescript: 'How would you like to setup TypeScript?', + typescriptSucceed: 'Next steps' }; export function setup(args = []) { |