diff --git a/src/commands/add/dep.ts b/src/commands/add/dep.ts new file mode 100644 index 0000000..8bf6b7d --- /dev/null +++ b/src/commands/add/dep.ts @@ -0,0 +1,44 @@ +// import {flags} from '@oclif/command' +import { BaseCommand } from '../../utls/base-command'; +import { BaseAddCommand } from '../../utls/base-add-command'; +import { flags } from '@oclif/command'; + +export default class Dep extends BaseAddCommand { + static description = 'proxy to yarn add, plus gitmoji commit'; + + static examples = [ + `$ nbx add:dep -D eslint`, + `$ nbx add:dep --dev eslint`, + `$ nbx add:dep chalk`, + ]; + + static flags = { + ...BaseCommand.flags, + dev: flags.boolean({ default: false, char: 'D', description: 'install as a dev dependency' }), + }; + + static args = [{ name: 'dep', description: 'The dependency to install', required: true }]; + + async run() { + if (!this.hasDirPackageJson()) { + this.error('There is no package.json not found in the current folder'); + } + const { + args: { dep }, + flags: { dev }, + } = this.parse(Dep); + + if ((dev && this.hasDevDependencyInPackageJson(dep)) || this.hasDependencyInPackageJson(dep)) { + if (this.hasDevDependencyInPackageJson(dep)) { + this.error(`${dep} is already installed in this project.`); + } + } + + await this.initGit(); + if (dev) { + await this.addDevDependency(dep, true); + } else { + await this.addDependency(dep, true); + } + } +} diff --git a/src/tests/add/__snapshots__/dep.spec.ts.snap b/src/tests/add/__snapshots__/dep.spec.ts.snap new file mode 100644 index 0000000..86d4335 --- /dev/null +++ b/src/tests/add/__snapshots__/dep.spec.ts.snap @@ -0,0 +1,45 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`dep should fail if dependancy is already in package.json 1`] = `[Error: Config not found. Tried to look for a .nbxrc, .nbxrc.json, .nbxrc.yaml, .nbxrc.yml, .nbxrc.js]`; + +exports[`dep should fail if dev dependancy is already in package.json 1`] = `[Error: chalk is already installed in this project.]`; + +exports[`dep should fail if no package.json found 1`] = `[Error: There is no package.json not found in the current folder]`; + +exports[`dep should print help correctly 1`] = ` +Array [ + "proxy to yarn add, plus gitmoji commit +", + "USAGE + $ nbx add:dep DEP + +ARGUMENTS + DEP The dependency to install + +OPTIONS + -D, --dev install as a dev dependency + -h, --help show CLI help + -v, --verbose Verbose output + --[no-]spinner Enable spinner in cli output, true by default + +EXAMPLES + $ nbx add:dep -D eslint + $ nbx add:dep --dev eslint + $ nbx add:dep chalk", + "", +] +`; + +exports[`dep should work with a dev dependency 1`] = ` +Array [ + "Adding chalk as a dev dependency", + "The step was done without any error.", +] +`; + +exports[`dep should work with dependency 1`] = ` +Array [ + "Adding chalk as a dependency", + "The step was done without any error.", +] +`; diff --git a/src/tests/add/dep.spec.ts b/src/tests/add/dep.spec.ts new file mode 100644 index 0000000..d3b2244 --- /dev/null +++ b/src/tests/add/dep.spec.ts @@ -0,0 +1,145 @@ +import { filesystem, system } from 'gluegun'; +const stripANSI = require('strip-ansi'); +import * as latestVersion from 'latest-version'; +import Dep from '../../commands/add/dep'; + +jest.setTimeout(90000); + +/* eslint-disable no-console,max-nested-callbacks,@typescript-eslint/ban-ts-ignore */ +let consoleLogOutput: string[]; +let execPath: string; +const originalCwd = process.cwd(); +const originalLog = console.log; + +beforeEach(async () => { + consoleLogOutput = []; + console.log = (x: any) => consoleLogOutput.push(stripANSI(x)); + + const tmpDirName = `${new Date().getTime()}-${Math.random() * 100}-add-nbx-test`; + execPath = filesystem.path('/', 'tmp', tmpDirName); + filesystem.dir(execPath); + process.chdir(execPath); +}); +afterEach(() => { + console.log = originalLog; + process.chdir(originalCwd); + jest.restoreAllMocks(); + filesystem.remove(execPath); +}); + +const initWithConfigAndCommit = async () => { + await system.run('git init'); + filesystem.write('.nbxrc', { git: { user: 'aaa', email: 'bbb' } }); + filesystem.write('package.json', {}); + await system.run('touch yarn.lock'); + await system.run('echo node_modules > .gitignore'); + await system.run('git add * .nbxrc .gitignore'); + try { + await system.run('git config user.email "you@example.com"'); + await system.run('git config user.name "Your Name"'); + } catch {} + await system.run('git commit -m "init state"'); +}; + +describe('dep', () => { + it('should print help correctly', async () => { + try { + await Dep.run(['-h']); + } catch {} + expect(consoleLogOutput).toMatchSnapshot(); + }); + it('should fail if no package.json found', async () => { + expect.assertions(1); + try { + filesystem.remove('package.json'); + await Dep.run(['chalk', '--no-spinner']); + // eslint-disable-next-line unicorn/catch-error-name + } catch (e) { + expect(e).toMatchSnapshot(); + } + }); + it('should fail if dependancy is already in package.json', async () => { + expect.assertions(1); + try { + filesystem.write('package.json', { dependencies: { chalk: '2.3.2' } }); + await Dep.run(['chalk', '--no-spinner']); + // eslint-disable-next-line unicorn/catch-error-name + } catch (e) { + expect(e).toMatchSnapshot(); + } + }); + it('should fail if dev dependancy is already in package.json', async () => { + expect.assertions(1); + try { + filesystem.write('package.json', { devDependencies: { chalk: '2.3.2' } }); + await Dep.run(['chalk', '--dev', '--no-spinner']); + // eslint-disable-next-line unicorn/catch-error-name + } catch (e) { + expect(e).toMatchSnapshot(); + } + }); + + it('should work with dependency', async () => { + await initWithConfigAndCommit(); + const latestChalk = await latestVersion('chalk'); + + await Dep.run(['chalk', '--no-spinner']); + + const packageJson = filesystem.read('package.json', 'json'); + expect(consoleLogOutput).toMatchSnapshot(); + expect(packageJson).toStrictEqual({ + dependencies: { + chalk: latestChalk, + }, + }); + const after = await system.run('git log --name-status --format="%s"'); + const afterSlitted = after + .split('\n') + .map(val => val.trim()) + .map(val => stripANSI(val)) + .filter(val => val !== ''); + + expect(afterSlitted).toStrictEqual([ + `:heavy_plus_sign: add chalk@${latestChalk} as a dependency`, + 'M\tpackage.json', + 'M\tyarn.lock', + 'init state', + 'A\t.gitignore', + 'A\t.nbxrc', + 'A\tpackage.json', + 'A\tyarn.lock', + ]); + }); + + it('should work with a dev dependency', async () => { + await initWithConfigAndCommit(); + const latestChalk = await latestVersion('chalk'); + + await Dep.run(['chalk', '-D', '--no-spinner']); + + const packageJson = filesystem.read('package.json', 'json'); + expect(consoleLogOutput).toMatchSnapshot(); + expect(packageJson).toStrictEqual({ + devDependencies: { + chalk: latestChalk, + }, + }); + const after = await system.run('git log --name-status --format="%s"'); + const afterSlitted = after + .split('\n') + .map(val => val.trim()) + .map(val => stripANSI(val)) + .filter(val => val !== ''); + + expect(afterSlitted).toStrictEqual([ + `:heavy_plus_sign: add chalk@${latestChalk} as a dev dependency`, + 'M\tpackage.json', + 'M\tyarn.lock', + 'init state', + 'A\t.gitignore', + 'A\t.nbxrc', + 'A\tpackage.json', + 'A\tyarn.lock', + ]); + }); +});