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 Dep from '../../commands/add/dep'; |
|||
import { |
|||
createDefaultNbxConfig, |
|||
expectFailCli, |
|||
expectGitCommits, |
|||
testCli, |
|||
} from '../test-helpers.spec'; |
|||
|
|||
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