diff --git a/packages/workbox-cli/src/lib/questions/ask-root-of-web-app.ts b/packages/workbox-cli/src/lib/questions/ask-root-of-web-app.ts index 528818f9f..ecd0a6d22 100644 --- a/packages/workbox-cli/src/lib/questions/ask-root-of-web-app.ts +++ b/packages/workbox-cli/src/lib/questions/ask-root-of-web-app.ts @@ -17,8 +17,9 @@ import {constants} from '../constants'; const ROOT_PROMPT = 'Please enter the path to the root of your web app:'; -// The key used for the question/answer. -const name = 'globDirectory'; +// The keys used for the questions/answers. +const questionRootDirectory = 'globDirectory'; +const questionManualInput = 'manualDirectoryInput'; /** * @return {Promise>} The subdirectories of the current @@ -41,44 +42,44 @@ async function getSubdirectories(): Promise> { /** * @return {Promise} The answers from inquirer. */ -async function askQuestion() { - const subdirectories = await getSubdirectories(); +async function askQuestion(): Promise<{ globDirectory: string; manualDirectoryInput?: string }> { + const subdirectories: (string | InstanceType)[] = await getSubdirectories(); if (subdirectories.length > 0) { const manualEntryChoice = 'Manually enter path'; return prompt([{ - name, + name: questionRootDirectory, type: 'list', message: ol`What is the root of your web app (i.e. which directory do you deploy)?`, choices: subdirectories.concat([ - new Separator().toString(), + new Separator(), manualEntryChoice, ]), }, { - name, - when: (answers: { [x: string]: string }) => answers[name] === manualEntryChoice, + name: questionManualInput, + when: (answers: { globDirectory: string }) => answers.globDirectory === manualEntryChoice, message: ROOT_PROMPT, - }]); - } else { - return prompt([{ - name, - message: ROOT_PROMPT, - default: '.', - }]); + } + ]); } + + return prompt([{ + name: questionRootDirectory, + message: ROOT_PROMPT, + default: '.', + }]); } export async function askRootOfWebApp() { - const answers = await askQuestion(); - const globDirectory = answers[name]; + const { manualDirectoryInput, globDirectory } = await askQuestion(); try { - const stat = await fse.stat(globDirectory); + const stat = await fse.stat(manualDirectoryInput || globDirectory); assert(stat.isDirectory()); } catch (error) { throw new Error(errors['glob-directory-invalid']); } - return globDirectory; + return manualDirectoryInput || globDirectory; } diff --git a/test/workbox-cli/node/lib/questions/ask-root-of-web-app.js b/test/workbox-cli/node/lib/questions/ask-root-of-web-app.js index f37b4308f..f5391700c 100644 --- a/test/workbox-cli/node/lib/questions/ask-root-of-web-app.js +++ b/test/workbox-cli/node/lib/questions/ask-root-of-web-app.js @@ -14,8 +14,12 @@ const {errors} = require('../../../../../packages/workbox-cli/build/lib/errors') const MODULE_PATH = '../../../../../packages/workbox-cli/build/lib/questions/ask-root-of-web-app'; // This is the hardcoded name of the question that's passed to inquirer. // It's used as the key to read the response from the answer. -const QUESTION_NAME = 'globDirectory'; +const questionRootDirectory = 'globDirectory'; +const questionManualInput = 'manualDirectoryInput'; const DIRECTORY = '/path/to/directory'; +const CHILD_DIRECTORY = '/path/to/directory/child'; +const CHILD_DIRECTORY_WHITE_SPACE = '/path/to/directory/ child'; +const CHILD_DIRECTORY_BLANK = ' '; describe(`[workbox-cli] lib/questions/ask-root-of-web-app.js`, function() { it(`should reject with a 'glob-directory-invalid' error when the answer isn't a valid directory`, async function() { @@ -24,7 +28,7 @@ describe(`[workbox-cli] lib/questions/ask-root-of-web-app.js`, function() { callback(null, []); }, 'inquirer': { - prompt: () => Promise.resolve({[QUESTION_NAME]: DIRECTORY}), + prompt: () => Promise.resolve({[questionRootDirectory]: DIRECTORY}), }, 'fs-extra': { stat: (path) => { @@ -47,13 +51,43 @@ describe(`[workbox-cli] lib/questions/ask-root-of-web-app.js`, function() { } }); - it(`should resolve with a valid answer to the question`, async function() { + it(`should reject with a 'glob-directory-invalid' error when the manual input is provided (directory does not exist)`, async function() { const {askRootOfWebApp} = proxyquire(MODULE_PATH, { 'glob': (pattern, config, callback) => { callback(null, []); }, 'inquirer': { - prompt: () => Promise.resolve({[QUESTION_NAME]: DIRECTORY}), + prompt: () => Promise.resolve({ + [questionRootDirectory]: DIRECTORY, + [questionManualInput]: CHILD_DIRECTORY, + }), + }, + 'fs-extra': { + stat: (path) => { + return { + isDirectory: () => { + return path !== CHILD_DIRECTORY; + }, + }; + }, + }, + }); + + try { + await askRootOfWebApp(); + throw new Error('Unexpected success.'); + } catch (error) { + expect(error.message).to.eql(errors['glob-directory-invalid']); + } + }); + + it(`should resolve with a valid answer to the question when no child directories are present (default: use current directory)`, async function() { + const {askRootOfWebApp} = proxyquire(MODULE_PATH, { + 'glob': (pattern, config, callback) => { + callback(null, []); + }, + 'inquirer': { + prompt: () => Promise.resolve({[questionRootDirectory]: DIRECTORY}), }, 'fs-extra': { stat: (path) => { @@ -71,5 +105,83 @@ describe(`[workbox-cli] lib/questions/ask-root-of-web-app.js`, function() { const answer = await askRootOfWebApp(); expect(answer).to.eql(DIRECTORY); }); + + it(`should resolve with a valid answer to the question when manual input is provided (directory exists)`, async function() { + const {askRootOfWebApp} = proxyquire(MODULE_PATH, { + 'glob': (pattern, config, callback) => { + callback(null, []); + }, + 'inquirer': { + prompt: () => Promise.resolve({ + [questionRootDirectory]: DIRECTORY, + [questionManualInput]: CHILD_DIRECTORY, + }), + }, + 'fs-extra': { + stat: (path) => { + return { + isDirectory: () => { + return path === CHILD_DIRECTORY; + }, + }; + }, + }, + }); + + const answer = await askRootOfWebApp(); + expect(answer).to.eql(CHILD_DIRECTORY); + }); + + it(`should resolve with a valid answer to the question when manual input is provided (directory exists and name contains white space)`, async function() { + const {askRootOfWebApp} = proxyquire(MODULE_PATH, { + 'glob': (pattern, config, callback) => { + callback(null, []); + }, + 'inquirer': { + prompt: () => Promise.resolve({ + [questionRootDirectory]: DIRECTORY, + [questionManualInput]: CHILD_DIRECTORY_WHITE_SPACE, + }), + }, + 'fs-extra': { + stat: (path) => { + return { + isDirectory: () => { + return path === CHILD_DIRECTORY_WHITE_SPACE; + }, + }; + }, + }, + }); + + const answer = await askRootOfWebApp(); + expect(answer).to.eql(CHILD_DIRECTORY_WHITE_SPACE); + }); + + it(`should resolve with a valid answer to the question when manual input is provided (directory exists and name is composed of only white space)`, async function() { + const {askRootOfWebApp} = proxyquire(MODULE_PATH, { + 'glob': (pattern, config, callback) => { + callback(null, []); + }, + 'inquirer': { + prompt: () => Promise.resolve({ + [questionRootDirectory]: DIRECTORY, + [questionManualInput]: CHILD_DIRECTORY_BLANK, + }), + }, + 'fs-extra': { + stat: (path) => { + return { + isDirectory: () => { + return path === CHILD_DIRECTORY_BLANK; + }, + }; + }, + }, + }); + + const answer = await askRootOfWebApp(); + expect(answer).to.eql(CHILD_DIRECTORY_BLANK); + }); });