• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1const { readFileSync, statSync } = require('fs')
2const { resolve } = require('path')
3const t = require('tap')
4const _mockNpm = require('../../fixtures/mock-npm')
5const mockGlobals = require('@npmcli/mock-globals')
6
7const mockNpm = async (t, opts = {}) => {
8  const res = await _mockNpm(t, {
9    ...opts,
10    command: 'version',
11    mocks: {
12      ...opts.mocks,
13      '{ROOT}/package.json': { version: '1.0.0' },
14    },
15  })
16  return {
17    ...res,
18    result: () => res.outputs[0],
19  }
20}
21
22t.test('node@1', async t => {
23  mockGlobals(t, { 'process.versions': { node: '1.0.0' } }, { replace: true })
24
25  t.test('no args', async t => {
26    const { version, result } = await mockNpm(t, {
27      prefixDir: {
28        'package.json': JSON.stringify({
29          name: 'test-version-no-args',
30          version: '3.2.1',
31        }),
32      },
33    })
34
35    await version.exec([])
36
37    t.strictSame(
38      result(),
39      [{
40        'test-version-no-args': '3.2.1',
41        node: '1.0.0',
42        npm: '1.0.0',
43      }],
44      'should output expected values for various versions in npm'
45    )
46  })
47
48  t.test('too many args', async t => {
49    const { version } = await mockNpm(t)
50    await t.rejects(
51      version.exec(['foo', 'bar']),
52      /npm version/,
53      'should throw usage instructions error'
54    )
55  })
56
57  t.test('completion', async t => {
58    const { version } = await mockNpm(t)
59    const testComp = async (argv, expect) => {
60      const res = await version.completion({ conf: { argv: { remain: argv } } })
61      t.strictSame(res, expect, argv.join(' '))
62    }
63
64    await testComp(
65      ['npm', 'version'],
66      ['major', 'minor', 'patch', 'premajor', 'preminor', 'prepatch', 'prerelease', 'from-git']
67    )
68    await testComp(['npm', 'version', 'major'], [])
69  })
70
71  t.test('failure reading package.json', async t => {
72    const { version, result } = await mockNpm(t)
73
74    await version.exec([])
75
76    t.strictSame(
77      result(),
78      [{
79        npm: '1.0.0',
80        node: '1.0.0',
81      }],
82      'should not have package name on returning object'
83    )
84  })
85})
86
87t.test('empty versions', async t => {
88  mockGlobals(t, { 'process.versions': {} }, { replace: true })
89
90  t.test('--json option', async t => {
91    const { version, result } = await mockNpm(t, {
92      config: { json: true },
93    })
94
95    await version.exec([])
96    t.same(result(), ['{\n  "npm": "1.0.0"\n}'], 'should return json stringified result')
97  })
98
99  t.test('with one arg', async t => {
100    const { version, result } = await mockNpm(t, {
101      mocks: {
102        libnpmversion: () => '4.0.0',
103      },
104    })
105
106    await version.exec(['major'])
107    t.same(result(), ['v4.0.0'], 'outputs the new version prefixed by the tagVersionPrefix')
108  })
109
110  t.test('workspaces', async t => {
111    t.test('no args, all workspaces', async t => {
112      const { version, result } = await mockNpm(t, {
113        prefixDir: {
114          'package.json': JSON.stringify(
115            {
116              name: 'workspaces-test',
117              version: '1.0.0',
118              workspaces: ['workspace-a', 'workspace-b'],
119            },
120            null,
121            2
122          ),
123          'workspace-a': {
124            'package.json': JSON.stringify({
125              name: 'workspace-a',
126              version: '1.0.0',
127            }),
128          },
129          'workspace-b': {
130            'package.json': JSON.stringify({
131              name: 'workspace-b',
132              version: '1.0.0',
133            }),
134          },
135        },
136        config: { workspaces: true },
137      })
138
139      await version.exec([])
140      t.same(
141        result(),
142        [
143          {
144            'workspaces-test': '1.0.0',
145            'workspace-a': '1.0.0',
146            'workspace-b': '1.0.0',
147            npm: '1.0.0',
148          },
149        ],
150        'outputs includes main package and workspace versions'
151      )
152    })
153
154    t.test('no args, single workspaces', async t => {
155      const { version, result } = await mockNpm(t, {
156        prefixDir: {
157          'package.json': JSON.stringify(
158            {
159              name: 'workspaces-test',
160              version: '1.0.0',
161              workspaces: ['workspace-a', 'workspace-b'],
162            },
163            null,
164            2
165          ),
166          'workspace-a': {
167            'package.json': JSON.stringify({
168              name: 'workspace-a',
169              version: '1.0.0',
170            }),
171          },
172          'workspace-b': {
173            'package.json': JSON.stringify({
174              name: 'workspace-b',
175              version: '1.0.0',
176            }),
177          },
178        },
179        config: {
180          workspace: 'workspace-a',
181        },
182      })
183
184      await version.exec([])
185      t.same(
186        result(),
187        [
188          {
189            'workspaces-test': '1.0.0',
190            'workspace-a': '1.0.0',
191            npm: '1.0.0',
192          },
193        ],
194        'outputs includes main package and requested workspace versions'
195      )
196    })
197
198    t.test('no args, all workspaces, workspace with missing name or version', async t => {
199      const { version, result } = await mockNpm(t, {
200        prefixDir: {
201          'package.json': JSON.stringify(
202            {
203              name: 'workspaces-test',
204              version: '1.0.0',
205              workspaces: ['workspace-a', 'workspace-b', 'workspace-c'],
206            },
207            null,
208            2
209          ),
210          'workspace-a': {
211            'package.json': JSON.stringify({
212              name: 'workspace-a',
213              version: '1.0.0',
214            }),
215          },
216          'workspace-b': {
217            'package.json': JSON.stringify({
218              name: 'workspace-b',
219            }),
220          },
221          'workspace-c': {
222            'package.json': JSON.stringify({
223              version: '1.0.0',
224            }),
225          },
226        },
227        config: { workspaces: true },
228      })
229
230      await version.exec([])
231      t.same(
232        result(),
233        [
234          {
235            'workspaces-test': '1.0.0',
236            'workspace-a': '1.0.0',
237            npm: '1.0.0',
238          },
239        ],
240        'outputs includes main package and valid workspace versions'
241      )
242    })
243
244    t.test('with one arg, all workspaces', async t => {
245      const { version, outputs, prefix } = await mockNpm(t, {
246        prefixDir: {
247          'package.json': JSON.stringify(
248            {
249              name: 'workspaces-test',
250              version: '1.0.0',
251              workspaces: ['workspace-a', 'workspace-b'],
252            },
253            null,
254            2
255          ),
256          'workspace-a': {
257            'package.json': JSON.stringify({
258              name: 'workspace-a',
259              version: '1.0.0',
260            }),
261          },
262          'workspace-b': {
263            'package.json': JSON.stringify({
264              name: 'workspace-b',
265              version: '1.0.0',
266            }),
267          },
268        },
269        config: { workspaces: true },
270      })
271
272      await version.exec(['major'])
273      t.same(
274        outputs.map(o => o[0]).slice(0, 4),
275        ['workspace-a', 'v2.0.0', 'workspace-b', 'v2.0.0'],
276        'outputs the new version for only the workspaces prefixed by the tagVersionPrefix'
277      )
278
279      t.matchSnapshot(readFileSync(resolve(prefix, 'package-lock.json'), 'utf8'))
280    })
281
282    t.test('with one arg, all workspaces, saves package.json', async t => {
283      const { version, outputs, prefix } = await mockNpm(t, {
284        prefixDir: {
285          'package.json': JSON.stringify(
286            {
287              name: 'workspaces-test',
288              version: '1.0.0',
289              workspaces: ['workspace-a', 'workspace-b'],
290              dependencies: {
291                'workspace-a': '^1.0.0',
292                'workspace-b': '^1.0.0',
293              },
294            },
295            null,
296            2
297          ),
298          'workspace-a': {
299            'package.json': JSON.stringify({
300              name: 'workspace-a',
301              version: '1.0.0',
302            }),
303          },
304          'workspace-b': {
305            'package.json': JSON.stringify({
306              name: 'workspace-b',
307              version: '1.0.0',
308            }),
309          },
310        },
311        config: {
312          save: true,
313          workspaces: true,
314        },
315      })
316
317      await version.exec(['major'])
318      t.same(
319        outputs.map(o => o[0]).slice(0, 4),
320        ['workspace-a', 'v2.0.0', 'workspace-b', 'v2.0.0'],
321        'outputs the new version for only the workspaces prefixed by the tagVersionPrefix'
322      )
323
324      t.matchSnapshot(readFileSync(resolve(prefix, 'package-lock.json'), 'utf8'))
325    })
326
327    t.test('too many args', async t => {
328      const { version } = await mockNpm(t, { config: { workspaces: true } })
329
330      await t.rejects(
331        version.exec(['foo', 'bar']),
332        /npm version/,
333        'should throw usage instructions error'
334      )
335    })
336
337    t.test('no workspaces-update', async t => {
338      const { version, outputs, prefix } = await mockNpm(t, {
339        prefixDir: {
340          'package.json': JSON.stringify(
341            {
342              name: 'workspaces-test',
343              version: '1.0.0',
344              workspaces: ['workspace-a', 'workspace-b'],
345            },
346            null,
347            2
348          ),
349          'workspace-a': {
350            'package.json': JSON.stringify({
351              name: 'workspace-a',
352              version: '1.0.0',
353            }),
354          },
355          'workspace-b': {
356            'package.json': JSON.stringify({
357              name: 'workspace-b',
358              version: '1.0.0',
359            }),
360          },
361        },
362        mocks: {
363          libnpmversion: (arg, opts) => {
364            return '2.0.0'
365          },
366        },
367        config: {
368          workspaces: true,
369          'workspaces-update': false,
370        },
371      })
372
373      await version.exec(['major'])
374      t.same(
375        outputs.map(o => o[0]).slice(0, 4),
376        ['workspace-a', 'v2.0.0', 'workspace-b', 'v2.0.0'],
377        'outputs the new version for only the workspaces prefixed by the tagVersionPrefix'
378      )
379
380      t.throws(
381        () => statSync(resolve(prefix, 'package-lock.json')),
382        'should not have a lockfile since have not reified'
383      )
384    })
385  })
386})
387