2 changed files with 244 additions and 137 deletions
@ -1,145 +1,99 @@ |
|||||
import { filesystem, system } from 'gluegun'; |
|
||||
const stripANSI = require('strip-ansi'); |
|
||||
|
import { filesystem } from 'gluegun'; |
||||
import * as latestVersion from 'latest-version'; |
import * as latestVersion from 'latest-version'; |
||||
import Dep from '../../commands/add/dep'; |
import Dep from '../../commands/add/dep'; |
||||
|
import { |
||||
|
createDefaultNbxConfig, |
||||
|
expectFailCli, |
||||
|
expectGitCommits, |
||||
|
testCli, |
||||
|
} from '../test-helpers.spec'; |
||||
|
|
||||
jest.setTimeout(90000); |
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; |
|
||||
|
testCli({ |
||||
|
runCommand: (args: string[]) => Dep.run(args), |
||||
|
name: 'nbx add:dep', |
||||
|
defaultArgs: ['--no-spinner'], |
||||
|
tests: [ |
||||
|
{ |
||||
|
name: 'fail if no package.json found', |
||||
|
runner: expectFailCli({ |
||||
|
args: ['chalk'], |
||||
|
errorMessage: 'There is no package.json not found in the current folder', |
||||
|
before: async () => { |
||||
|
filesystem.remove('package.json'); |
||||
|
}, |
||||
|
}), |
||||
|
}, |
||||
|
{ |
||||
|
name: 'fail if dependancy is already in package.json', |
||||
|
runner: expectFailCli({ |
||||
|
args: ['chalk'], |
||||
|
errorMessage: 'chalk is already installed in this project', |
||||
|
before: async () => { |
||||
|
await createDefaultNbxConfig(); |
||||
|
filesystem.write('package.json', { dependencies: { chalk: '2.3.2' } }); |
||||
|
}, |
||||
|
}), |
||||
|
}, |
||||
|
{ |
||||
|
name: 'fail if dev dependancy is already in package.json', |
||||
|
runner: expectFailCli({ |
||||
|
args: ['chalk', '-D'], |
||||
|
errorMessage: 'chalk is already installed in this project', |
||||
|
before: async () => { |
||||
|
await createDefaultNbxConfig(); |
||||
|
filesystem.write('package.json', { devDependencies: { chalk: '2.3.2' } }); |
||||
|
}, |
||||
|
}), |
||||
|
}, |
||||
|
{ |
||||
|
name: 'work with dependency', |
||||
|
runner: expectGitCommits({ |
||||
|
args: ['chalk'], |
||||
|
expectGitLog: async () => { |
||||
|
const latestChalk = await latestVersion('chalk'); |
||||
|
return [ |
||||
|
`:heavy_plus_sign: add chalk@${latestChalk} as a dependency`, |
||||
|
'M\tpackage.json', |
||||
|
'M\tyarn.lock', |
||||
|
]; |
||||
|
}, |
||||
|
checks: async () => { |
||||
|
const latestChalk = await latestVersion('chalk'); |
||||
|
|
||||
beforeEach(async () => { |
|
||||
consoleLogOutput = []; |
|
||||
console.log = (x: any) => consoleLogOutput.push(stripANSI(x)); |
|
||||
|
const packageJson = filesystem.read('package.json', 'json'); |
||||
|
expect(packageJson).toStrictEqual({ |
||||
|
dependencies: { |
||||
|
chalk: latestChalk, |
||||
|
}, |
||||
|
}); |
||||
|
}, |
||||
|
}), |
||||
|
}, |
||||
|
{ |
||||
|
name: 'work with a dev dependency', |
||||
|
runner: expectGitCommits({ |
||||
|
args: ['chalk', '-D'], |
||||
|
expectGitLog: async () => { |
||||
|
const latestChalk = await latestVersion('chalk'); |
||||
|
return [ |
||||
|
`:heavy_plus_sign: add chalk@${latestChalk} as a dev dependency`, |
||||
|
'M\tpackage.json', |
||||
|
'M\tyarn.lock', |
||||
|
]; |
||||
|
}, |
||||
|
checks: async () => { |
||||
|
const latestChalk = await latestVersion('chalk'); |
||||
|
|
||||
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', |
|
||||
]); |
|
||||
}); |
|
||||
|
const packageJson = filesystem.read('package.json', 'json'); |
||||
|
expect(packageJson).toStrictEqual({ |
||||
|
devDependencies: { |
||||
|
chalk: latestChalk, |
||||
|
}, |
||||
|
}); |
||||
|
}, |
||||
|
}), |
||||
|
}, |
||||
|
], |
||||
}); |
}); |
||||
@ -0,0 +1,153 @@ |
|||||
|
import { Command } from '@oclif/command'; |
||||
|
const stripANSI = require('strip-ansi'); |
||||
|
import { filesystem, system } from 'gluegun'; |
||||
|
|
||||
|
export type TestRun = (args: { exec: Function; defaultArgs?: string[] }) => Promise<any>; |
||||
|
|
||||
|
export interface TestCase { |
||||
|
name: string; |
||||
|
runner: TestRun; |
||||
|
} |
||||
|
|
||||
|
export interface TestCliParams { |
||||
|
tests: TestCase[]; |
||||
|
runCommand: (args: string[]) => PromiseLike<any>; |
||||
|
name: string; |
||||
|
defaultArgs?: string[]; |
||||
|
} |
||||
|
|
||||
|
export const createDefaultNbxConfig = async () => { |
||||
|
filesystem.write('.nbxrc', { git: { user: 'aaa', email: 'bbb' } }); |
||||
|
}; |
||||
|
|
||||
|
export const initWithConfigAndCommit = async () => { |
||||
|
await system.run('git init'); |
||||
|
await createDefaultNbxConfig(); |
||||
|
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"'); |
||||
|
}; |
||||
|
|
||||
|
export const expectGitCommits = ({ |
||||
|
before, |
||||
|
args, |
||||
|
expectGitLog, |
||||
|
checks, |
||||
|
}: { |
||||
|
args: string[]; |
||||
|
expectGitLog: string[] | (() => Promise<any>); |
||||
|
before?: () => Promise<any>; |
||||
|
checks?: () => Promise<any>; |
||||
|
}): TestRun => async ({ exec, defaultArgs = [] }) => { |
||||
|
await initWithConfigAndCommit(); |
||||
|
await before?.(); |
||||
|
|
||||
|
try { |
||||
|
await exec([...args, ...defaultArgs]); |
||||
|
} catch { |
||||
|
fail('Cli errored'); |
||||
|
} |
||||
|
|
||||
|
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 !== ''); |
||||
|
|
||||
|
if (expectGitLog instanceof Function) { |
||||
|
expect(afterSlitted).toStrictEqual([ |
||||
|
...(await expectGitLog()), |
||||
|
'init state', |
||||
|
'A\t.gitignore', |
||||
|
'A\t.nbxrc', |
||||
|
'A\tpackage.json', |
||||
|
'A\tyarn.lock', |
||||
|
]); |
||||
|
} else { |
||||
|
expect(afterSlitted).toStrictEqual([ |
||||
|
...expectGitLog, |
||||
|
'init state', |
||||
|
'A\t.gitignore', |
||||
|
'A\t.nbxrc', |
||||
|
'A\tpackage.json', |
||||
|
'A\tyarn.lock', |
||||
|
]); |
||||
|
} |
||||
|
|
||||
|
await checks?.(); |
||||
|
}; |
||||
|
|
||||
|
export const expectFailCli = ({ |
||||
|
assertions = 4, |
||||
|
before, |
||||
|
args, |
||||
|
errorMessage, |
||||
|
}: { |
||||
|
assertions?: number; |
||||
|
before?: () => Promise<any>; |
||||
|
args: string[]; |
||||
|
errorMessage: string; |
||||
|
}): TestRun => async ({ exec, defaultArgs = [] }) => { |
||||
|
expect.assertions(assertions); |
||||
|
try { |
||||
|
await before?.(); |
||||
|
|
||||
|
await exec([...args, ...defaultArgs]); |
||||
|
// eslint-disable-next-line unicorn/catch-error-name
|
||||
|
} catch (e) { |
||||
|
expect(e).toBeDefined(); |
||||
|
expect(e.message).toBeDefined(); |
||||
|
expect(e.message).toBe(errorMessage); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
export const testCli = ({ tests, runCommand, name, defaultArgs }: TestCliParams) => { |
||||
|
/* 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); |
||||
|
}); |
||||
|
|
||||
|
describe(name, () => { |
||||
|
it('should print help correctly', async () => { |
||||
|
try { |
||||
|
await runCommand(['-h']); |
||||
|
} catch {} |
||||
|
expect(consoleLogOutput).toMatchSnapshot(); |
||||
|
}); |
||||
|
|
||||
|
tests.forEach(testCase => { |
||||
|
it(`should ${testCase.name}`, async () => { |
||||
|
await testCase.runner({ exec: runCommand, defaultArgs: defaultArgs }); |
||||
|
expect(consoleLogOutput).toMatchSnapshot(); |
||||
|
}); |
||||
|
}); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
const testHelp = (command: Command) => { |
||||
|
it(''); |
||||
|
}; |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue