• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict'
2
3const BB = require('bluebird')
4
5const common = require('../common-tap.js')
6const fs = require('graceful-fs')
7const mockTar = require('../util/mock-tarball.js')
8const mr = common.fakeRegistry.compat
9const path = require('path')
10const rimraf = BB.promisify(require('rimraf'))
11const Tacks = require('tacks')
12const { test } = require('tap')
13
14const { Dir, File } = Tacks
15const readdirAsync = BB.promisify(fs.readdir)
16const readFileAsync = BB.promisify(fs.readFile)
17
18const testDir = common.pkg
19
20let server
21test('setup', t => {
22  mr({}, (err, s) => {
23    t.ifError(err, 'registry mocked successfully')
24    server = s
25    t.end()
26  })
27})
28
29test('installs an npm: protocol alias package', t => {
30  const fixture = new Tacks(Dir({
31    'package.json': File({})
32  }))
33  fixture.create(testDir)
34  const packument = {
35    name: 'foo',
36    'dist-tags': { latest: '1.2.4' },
37    versions: {
38      '1.2.3': {
39        name: 'foo',
40        version: '1.2.3',
41        dist: {
42          tarball: `${server.registry}/foo/-/foo-1.2.3.tgz`
43        }
44      },
45      '1.2.4': {
46        name: 'foo',
47        version: '1.2.4',
48        dist: {
49          tarball: `${server.registry}/foo/-/foo-1.2.4.tgz`
50        }
51      }
52    }
53  }
54  server.get('/foo').reply(200, packument)
55  return mockTar({
56    'package.json': JSON.stringify({
57      name: 'foo',
58      version: '1.2.3'
59    })
60  }).then(tarball => {
61    server.get('/foo/-/foo-1.2.3.tgz').reply(200, tarball)
62    server.get('/foo/-/foo-1.2.4.tgz').reply(200, tarball)
63    return common.npm([
64      'install', 'foo@1.2.3',
65      '--cache', path.join(testDir, 'npmcache'),
66      '--registry', server.registry
67    ], { cwd: testDir })
68  }).then(([code, stdout, stderr]) => {
69    t.equal(code, 0)
70    t.comment(stdout)
71    t.comment(stderr)
72    return common.npm([
73      'install', 'bar@npm:foo@1.2.3',
74      '--cache', path.join(testDir, 'npmcache'),
75      '--registry', server.registry
76    ], { cwd: testDir })
77  }).then(([code, stdout, stderr]) => {
78    t.equal(code, 0)
79    t.comment(stdout)
80    t.comment(stderr)
81    t.match(stdout, /\+ foo@1\.2\.3 \(as bar\)/, 'useful message')
82    return readFileAsync(
83      path.join(testDir, 'node_modules', 'bar', 'package.json'),
84      'utf8'
85    )
86  }).then(JSON.parse).then(pkg => {
87    t.similar(pkg, {
88      name: 'foo',
89      version: '1.2.3'
90    }, 'successfully installed foo as bar in node_modules')
91    return common.npm(['ls', '--json'], { cwd: testDir })
92  }).then(([code, stdout, stderr]) => {
93    t.comment(stdout)
94    t.comment(stderr)
95    t.equal(code, 0, 'ls is clean')
96    t.deepEqual(JSON.parse(stdout), {
97      dependencies: {
98        bar: {
99          version: '1.2.3',
100          from: 'bar@npm:foo@1.2.3',
101          resolved: 'http://localhost:' + common.port + '/foo/-/foo-1.2.3.tgz'
102        },
103        foo: {
104          version: '1.2.3',
105          from: 'foo@1.2.3',
106          resolved: 'http://localhost:' + common.port + '/foo/-/foo-1.2.3.tgz'
107        }
108      }
109    }, 'both dependencies listed correctly')
110    return common.npm([
111      'outdated', '--json',
112      '--registry', server.registry
113    ], { cwd: testDir })
114  }).then(([code, stdout, stderr]) => {
115    t.equal(code, 1, 'non-zero because some packages outdated')
116    t.comment(stdout)
117    t.comment(stderr)
118    const parsed = JSON.parse(stdout)
119    t.match(parsed, {
120      foo: {
121        current: '1.2.3',
122        wanted: '1.2.4',
123        latest: '1.2.4',
124        location: /node_modules[/\\]foo/
125      },
126      bar: {
127        current: 'npm:foo@1.2.3',
128        wanted: 'npm:foo@1.2.4',
129        latest: 'npm:foo@1.2.4',
130        location: /node_modules[/\\]bar/
131      }
132    }, 'both regular and aliased dependency reported')
133    return common.npm([
134      'update',
135      '--registry', server.registry
136    ], { cwd: testDir })
137  }).then(([code, stdout, stderr]) => {
138    t.equal(code, 0, 'update succeeded')
139    t.comment(stdout)
140    t.comment(stderr)
141    return common.npm(['ls', '--json'], { cwd: testDir })
142  }).then(([code, stdout, stderr]) => {
143    t.equal(code, 0, 'ls succeeded')
144    t.comment(stdout)
145    t.comment(stderr)
146    const parsed = JSON.parse(stdout)
147    t.deepEqual(parsed, {
148      dependencies: {
149        bar: {
150          version: '1.2.4',
151          from: 'bar@npm:foo@1.2.4',
152          resolved: 'http://localhost:' + common.port + '/foo/-/foo-1.2.4.tgz'
153        },
154        foo: {
155          version: '1.2.4',
156          from: 'foo@1.2.4',
157          resolved: 'http://localhost:' + common.port + '/foo/-/foo-1.2.4.tgz'
158        }
159      }
160    }, 'ls shows updated packages')
161    return common.npm([
162      'rm', 'bar',
163      '--registry', server.registry
164    ], { cwd: testDir })
165  }).then(([code, stdout, stderr]) => {
166    t.equal(code, 0, 'rm succeeded')
167    t.comment(stdout)
168    t.comment(stderr)
169    t.match(stdout, 'removed 1 package', 'notified of removed package')
170    return readdirAsync(path.join(testDir, 'node_modules'))
171  }).then(dir => {
172    t.deepEqual(dir, ['foo'], 'regular foo left in place')
173  }).then(() => rimraf(testDir))
174})
175
176test('installs a tarball dep as a different name than package.json', t => {
177  return mockTar({
178    'package.json': JSON.stringify({
179      name: 'foo',
180      version: '1.2.3'
181    })
182  }).then(tarball => {
183    const fixture = new Tacks(Dir({
184      'package.json': File({}),
185      'foo.tgz': File(tarball)
186    }))
187    fixture.create(testDir)
188    return common.npm([
189      'install', 'file:foo.tgz',
190      '--cache', path.join(testDir, 'npmcache'),
191      '--registry', server.registry
192    ], { cwd: testDir })
193  }).then(([code, stdout, stderr]) => {
194    return common.npm([
195      'install', 'bar@file:foo.tgz',
196      '--cache', path.join(testDir, 'npmcache'),
197      '--registry', server.registry
198    ], { cwd: testDir })
199  }).then(([code, stdout, stderr]) => {
200    t.comment(stdout)
201    t.comment(stderr)
202    t.match(stdout, /^\+ foo@1\.2\.3 \(as bar\)/, 'useful message')
203    return readFileAsync(
204      path.join(testDir, 'node_modules', 'bar', 'package.json'),
205      'utf8'
206    )
207  }).then(JSON.parse).then(pkg => {
208    t.similar(pkg, {
209      name: 'foo',
210      version: '1.2.3'
211    }, 'successfully installed foo as bar in node_modules')
212    return common.npm(['ls', '--json'], { cwd: testDir })
213  }).then(([code, stdout, stderr]) => {
214    t.comment(stdout)
215    t.comment(stderr)
216    t.similar(JSON.parse(stdout), {
217      dependencies: {
218        bar: {
219          version: '1.2.3',
220          from: 'file:foo.tgz'
221        },
222        foo: {
223          version: '1.2.3',
224          from: 'file:foo.tgz'
225        }
226      }
227    }, 'both dependencies present')
228  }).then(() => rimraf(testDir))
229})
230
231test('installs a symlink dep as a different name than package.json', t => {
232  const fixture = new Tacks(Dir({
233    'package.json': File({}),
234    'foo': Dir({
235      'package.json': File({
236        name: 'foo',
237        version: '1.2.3'
238      })
239    })
240  }))
241  fixture.create(testDir)
242  return common.npm([
243    'install', 'bar@file:foo',
244    '--cache', path.join(testDir, 'npmcache'),
245    '--registry', server.registry
246  ], { cwd: testDir }).then(([code, stdout, stderr]) => {
247    t.comment(stdout)
248    t.comment(stderr)
249    t.match(stdout, /^\+ foo@1\.2\.3 \(as bar\)/, 'useful message')
250    return readFileAsync(
251      path.join(testDir, 'node_modules', 'bar', 'package.json'),
252      'utf8'
253    )
254  }).then(JSON.parse).then(pkg => {
255    t.similar(pkg, {
256      name: 'foo',
257      version: '1.2.3'
258    }, 'successfully installed foo as bar in node_modules')
259  }).then(() => rimraf(testDir))
260})
261
262test('cleanup', t => {
263  server.close()
264  return rimraf(testDir)
265})
266
267test('npm audit supports aliases')
268test('npm audit fix supports aliases')
269