Skip to content

Commit

Permalink
test: add lib/uninstall.js tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ruyadorno committed Dec 1, 2020
1 parent e9a440b commit a3511c5
Show file tree
Hide file tree
Showing 2 changed files with 275 additions and 15 deletions.
37 changes: 22 additions & 15 deletions lib/uninstall.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
// remove a package.
'use strict'

const { resolve } = require('path')
const Arborist = require('@npmcli/arborist')
const npm = require('./npm.js')
const rpj = require('read-package-json-fast')
const { resolve } = require('path')

const npm = require('./npm.js')
const usageUtil = require('./utils/usage.js')
const reifyFinish = require('./utils/reify-finish.js')
const completion = require('./utils/completion/installed-shallow.js')

const usage = usageUtil(
'uninstall',
'npm uninstall [<@scope>/]<pkg>[@<version>]... [--save-prod|--save-dev|--save-optional] [--no-save]'
)

const cmd = (args, cb) => rm(args).then(() => cb()).catch(cb)

Expand All @@ -16,12 +23,19 @@ const rm = async args => {

if (!args.length) {
if (!global)
throw new Error('must provide a package name to remove')
throw new Error('Must provide a package name to remove')
else {
const pkg = await rpj(resolve(npm.localPrefix, 'package.json'))
.catch(er => {
throw er.code !== 'ENOENT' && er.code !== 'ENOTDIR' ? er : usage()
})
let pkg

try {
pkg = await rpj(resolve(npm.localPrefix, 'package.json'))
} catch (er) {
if (er.code !== 'ENOENT' && er.code !== 'ENOTDIR')
throw er
else
throw usage
}

args.push(pkg.name)
}
}
Expand All @@ -35,11 +49,4 @@ const rm = async args => {
await reifyFinish(arb)
}

const usage = usageUtil(
'uninstall',
'npm uninstall [<@scope>/]<pkg>[@<version>]... [--save-prod|--save-dev|--save-optional] [--no-save]'
)

const completion = require('./utils/completion/installed-shallow.js')

module.exports = Object.assign(cmd, { usage, completion })
253 changes: 253 additions & 0 deletions test/lib/uninstall.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
const fs = require('fs')
const { resolve } = require('path')
const t = require('tap')
const requireInject = require('require-inject')

const npm = {
globalDir: '',
flatOptions: {
global: false,
prefix: '',
},
localPrefix: '',
}
const mocks = {
'../../lib/npm.js': npm,
'../../lib/utils/reify-finish.js': () => Promise.resolve(),
'../../lib/utils/usage.js': () => 'usage instructions',
}

const uninstall = requireInject('../../lib/uninstall.js', mocks)

t.afterEach(cb => {
npm.globalDir = ''
npm.prefix = ''
npm.flatOptions.global = false
npm.flatOptions.prefix = ''
cb()
})

t.test('remove single installed lib', t => {
const path = t.testdir({
'package.json': JSON.stringify({
name: 'test-rm-single-lib',
version: '1.0.0',
dependencies: {
a: '*',
b: '*',
},
}),
node_modules: {
a: {
'package.json': JSON.stringify({
name: 'a',
version: '1.0.0',
}),
},
b: {
'package.json': JSON.stringify({
name: 'b',
version: '1.0.0',
}),
},
},
'package-lock.json': JSON.stringify({
name: 'test-rm-single-lib',
version: '1.0.0',
lockfileVersion: 2,
requires: true,
packages: {
'': {
name: 'test-rm-single-lib',
version: '1.0.0',
dependencies: {
a: '*',
},
},
'node_modules/a': {
version: '1.0.0',
},
'node_modules/b': {
version: '1.0.0',
},
},
dependencies: {
a: {
version: '1.0.0',
},
b: {
version: '1.0.0',
},
},
}),
})

const b = resolve(path, 'node_modules/b')
t.ok(() => fs.statSync(b))

npm.flatOptions.prefix = path

uninstall(['b'], err => {
if (err)
throw err

t.throws(() => fs.statSync(b), 'should have removed package from nm')
t.end()
})
})

t.test('remove multiple installed libs', t => {
const path = t.testdir({
node_modules: {
a: {
'package.json': JSON.stringify({
name: 'a',
version: '1.0.0',
}),
},
b: {
'package.json': JSON.stringify({
name: 'b',
version: '1.0.0',
}),
},
},
'package-lock.json': JSON.stringify({
name: 'test-rm-single-lib',
version: '1.0.0',
lockfileVersion: 2,
requires: true,
packages: {
'': {
name: 'test-rm-single-lib',
version: '1.0.0',
dependencies: {
a: '*',
},
},
'node_modules/a': {
version: '1.0.0',
},
'node_modules/b': {
version: '1.0.0',
},
},
dependencies: {
a: {
version: '1.0.0',
},
b: {
version: '1.0.0',
},
},
}),
})

const a = resolve(path, 'node_modules/a')
const b = resolve(path, 'node_modules/b')
t.ok(() => fs.statSync(a))
t.ok(() => fs.statSync(b))

npm.flatOptions.prefix = path

uninstall(['b'], err => {
if (err)
throw err

t.throws(() => fs.statSync(a), 'should have removed a package from nm')
t.throws(() => fs.statSync(b), 'should have removed b package from nm')
t.end()
})
})

t.test('no args local', t => {
const path = t.testdir()

npm.flatOptions.prefix = path

uninstall([], err => {
t.match(
err,
/Must provide a package name to remove/,
'should throw package name required error'
)

t.end()
})
})

t.test('no args global', t => {
const path = t.testdir({
lib: {
node_modules: {
a: t.fixture('symlink', '../../projects/a'),
},
},
projects: {
a: {
'package.json': JSON.stringify({
name: 'a',
version: '1.0.0',
}),
},
},
})

npm.localPrefix = resolve(path, 'projects', 'a')
npm.globalDir = resolve(path, 'lib', 'node_modules')
npm.flatOptions.global = true
npm.flatOptions.prefix = path

const a = resolve(path, 'lib/node_modules/a')
t.ok(() => fs.statSync(a))

uninstall([], err => {
if (err)
throw err

t.throws(() => fs.statSync(a), 'should have removed global nm symlink')

t.end()
})
})

t.test('no args global but no package.json', t => {
const path = t.testdir({})

npm.prefix = path
npm.localPrefix = path
npm.flatOptions.global = true

uninstall([], err => {
t.match(
err,
'usage instructions',
'should throw usage instructions'
)

t.end()
})
})

t.test('unknown error reading from localPrefix package.json', t => {
const path = t.testdir({})

const uninstall = requireInject('../../lib/uninstall.js', {
...mocks,
'read-package-json-fast': () => Promise.reject(new Error('ERR')),
})

npm.prefix = path
npm.localPrefix = path
npm.flatOptions.global = true

uninstall([], err => {
t.match(
err,
/ERR/,
'should throw unknown error'
)

t.end()
})
})

0 comments on commit a3511c5

Please sign in to comment.