From 60c192698c899f5807d24f4c96ba855bd479d8a1 Mon Sep 17 00:00:00 2001 From: Anshuman Verma Date: Tue, 22 Sep 2020 20:49:02 +0530 Subject: [PATCH] refactor: cleanup package-utils --- packages/utils/__tests__/index.test.ts | 80 +++++++++++++++++++++++ packages/utils/src/index.ts | 1 + packages/utils/src/prompt-installation.ts | 6 +- yarn.lock | 39 +++++------ 4 files changed, 101 insertions(+), 25 deletions(-) create mode 100644 packages/utils/__tests__/index.test.ts diff --git a/packages/utils/__tests__/index.test.ts b/packages/utils/__tests__/index.test.ts new file mode 100644 index 00000000000..2cfcaeab359 --- /dev/null +++ b/packages/utils/__tests__/index.test.ts @@ -0,0 +1,80 @@ +'use strict'; + +import { packageExists, promptInstallation, runCommand } from '../'; +import ExternalCommand from '../../webpack-cli/lib/commands/ExternalCommand'; + +describe('@webpack-cli/utils', () => { + it('should check existence of package', () => { + // use an actual path relative to the packageUtils file + expect(packageExists('../lib/package-exists')).toBeTruthy(); + expect(packageExists('./nonexistent-package')).toBeFalsy(); + }); + + it('should not throw if the user interrupts', async () => { + (promptInstallation as jest.Mock).mockImplementation(() => { + throw new Error(); + }); + await expect(ExternalCommand.run('info')).resolves.not.toThrow(); + }); +}); + +describe('promptInstallation', () => { + let packageUtils; + beforeAll(() => { + packageUtils = require('../lib/'); + packageUtils.getPackageManager = jest.fn(); + packageUtils.packageExists = jest.fn(() => true); + }); + + beforeEach(() => { + (runCommand as jest.Mock).mockClear(); + (prompt as jest.Mock).mockClear(); + }); + + it('should prompt to install using npm if npm is package manager', async () => { + packageUtils.getPackageManager.mockReturnValue('npm'); + (prompt as jest.Mock).mockReturnValue({ + installConfirm: true, + }); + + const preMessage = jest.fn(); + const promptResult = await packageUtils.promptInstallation('test-package', preMessage); + expect(promptResult).toBeTruthy(); + expect(preMessage.mock.calls.length).toEqual(1); + expect((prompt as jest.Mock).mock.calls.length).toEqual(1); + expect((runCommand as jest.Mock).mock.calls.length).toEqual(1); + expect((prompt as jest.Mock).mock.calls[0][0][0].message).toMatch(/Would you like to install test-package\?/); + // install the package using npm + expect((runCommand as jest.Mock).mock.calls[0][0]).toEqual('npm install -D test-package'); + }); + + it('should prompt to install using yarn if yarn is package manager', async () => { + packageUtils.getPackageManager.mockReturnValue('yarn'); + (prompt as jest.Mock).mockReturnValue({ + installConfirm: true, + }); + + const promptResult = await packageUtils.promptInstallation('test-package'); + expect(promptResult).toBeTruthy(); + expect((prompt as jest.Mock).mock.calls.length).toEqual(1); + expect((runCommand as jest.Mock).mock.calls.length).toEqual(1); + expect((prompt as jest.Mock).mock.calls[0][0][0].message).toMatch(/Would you like to install test-package\?/); + // install the package using yarn + expect((runCommand as jest.Mock).mock.calls[0][0]).toEqual('yarn add -D test-package'); + }); + + it('should not install if install is not confirmed', async () => { + packageUtils.getPackageManager.mockReturnValue('npm'); + (prompt as jest.Mock).mockReturnValue({ + installConfirm: false, + }); + + const promptResult = await packageUtils.promptInstallation('test-package'); + expect(promptResult).toBeUndefined(); + expect((prompt as jest.Mock).mock.calls.length).toEqual(1); + // runCommand should not be called, because the installation is not confirmed + expect((runCommand as jest.Mock).mock.calls.length).toEqual(0); + expect((prompt as jest.Mock).mock.calls[0][0][0].message).toMatch(/Would you like to install test-package\?/); + expect(process.exitCode).toEqual(2); + }); +}); diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 46145db13f5..5a29dc28ac6 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -13,3 +13,4 @@ export * from './global-packages-path'; export * from './get-package-manager'; export * from './package-exists'; export * from './run-command'; +export * from './prompt-installation'; diff --git a/packages/utils/src/prompt-installation.ts b/packages/utils/src/prompt-installation.ts index 601f3f74e66..c8ee4075b97 100644 --- a/packages/utils/src/prompt-installation.ts +++ b/packages/utils/src/prompt-installation.ts @@ -1,6 +1,8 @@ import { prompt } from 'enquirer'; import { green } from 'colorette'; import { runCommand } from './run-command'; +import { getPackageManager } from './get-package-manager'; +import { packageExists } from './package-exists'; /** * @@ -9,7 +11,7 @@ import { runCommand } from './run-command'; */ // eslint-disable-next-line @typescript-eslint/explicit-function-return-type export async function promptInstallation(packageName: string, preMessage?: Function) { - const packageManager = exports.getPackageManager(); + const packageManager = getPackageManager(); const options = [packageManager === 'yarn' ? 'add' : 'install', '-D', packageName]; const commandToBeRun = `${packageManager} ${options.join(' ')}`; @@ -27,7 +29,7 @@ export async function promptInstallation(packageName: string, preMessage?: Funct ]); if (installConfirm) { await runCommand(commandToBeRun); - return exports.packageExists(packageName); + return packageExists(packageName); } // eslint-disable-next-line require-atomic-updates process.exitCode = 2; diff --git a/yarn.lock b/yarn.lock index 9b5a6dda444..87e41ff51b4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2467,13 +2467,6 @@ resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== -"@types/cross-spawn@6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/@types/cross-spawn/-/cross-spawn-6.0.1.tgz#60fa0c87046347c17d9735e5289e72b804ca9b63" - integrity sha512-MtN1pDYdI6D6QFDzy39Q+6c9rl2o/xN7aWGe6oZuzqq5N6+YuwFsWiEAv3dNzvzN9YzU+itpN8lBzFpphQKLAw== - dependencies: - "@types/node" "*" - "@types/cross-spawn@^6.0.2": version "6.0.2" resolved "https://registry.yarnpkg.com/@types/cross-spawn/-/cross-spawn-6.0.2.tgz#168309de311cd30a2b8ae720de6475c2fbf33ac7" @@ -4688,15 +4681,6 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: safe-buffer "^5.0.1" sha.js "^2.4.8" -cross-spawn@7.0.1, cross-spawn@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.1.tgz#0ab56286e0f7c24e153d04cc2aa027e43a9a5d14" - integrity sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -4708,6 +4692,15 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" +cross-spawn@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.1.tgz#0ab56286e0f7c24e153d04cc2aa027e43a9a5d14" + integrity sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -6362,13 +6355,6 @@ global-dirs@^0.1.1: dependencies: ini "^1.3.4" -global-modules@2.0.0, global-modules@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" - integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== - dependencies: - global-prefix "^3.0.0" - global-modules@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" @@ -6378,6 +6364,13 @@ global-modules@^1.0.0: is-windows "^1.0.1" resolve-dir "^1.0.0" +global-modules@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" + integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== + dependencies: + global-prefix "^3.0.0" + global-prefix@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe"