1const t = require('tap')
2const { load: loadMockNpm } = require('../../fixtures/mock-npm')
3
4const MockRegistry = require('@npmcli/mock-registry')
5
6const user = 'test-user'
7const token = 'test-auth-token'
8const auth = { '//registry.npmjs.org/:_authToken': token }
9const versions = ['1.0.0', '1.0.1', '1.0.1-pre']
10
11// libnpmaccess maps these to read-write and read-only
12const packages = { foo: 'write', bar: 'write', baz: 'write', buzz: 'read' }
13
14t.test('completion', async t => {
15  const { npm, deprecate } = await loadMockNpm(t, {
16    command: 'deprecate',
17    config: {
18      ...auth,
19    },
20  })
21
22  const testComp = async (argv, expect) => {
23    const res =
24      await deprecate.completion({ conf: { argv: { remain: argv } } })
25    t.strictSame(res, expect, `completion: ${argv}`)
26  }
27
28  const registry = new MockRegistry({
29    tap: t,
30    registry: npm.config.get('registry'),
31    authorization: token,
32  })
33
34  registry.whoami({ username: user, times: 4 })
35  registry.getPackages({ team: user, packages, times: 4 })
36  await Promise.all([
37    testComp([], ['foo', 'bar', 'baz']),
38    testComp(['b'], ['bar', 'baz']),
39    testComp(['fo'], ['foo']),
40    testComp(['g'], []),
41  ])
42
43  await testComp(['foo', 'something'], [])
44
45  registry.whoami({ responseCode: 401, body: {} })
46
47  await t.rejects(
48    testComp([], []),
49    { code: 'E401' }
50  )
51})
52
53t.test('no args', async t => {
54  const { npm } = await loadMockNpm(t)
55  await t.rejects(
56    npm.exec('deprecate', []),
57    { code: 'EUSAGE' },
58    'logs usage'
59  )
60})
61
62t.test('only one arg', async t => {
63  const { npm } = await loadMockNpm(t)
64  await t.rejects(
65    npm.exec('deprecate', ['foo']),
66    { code: 'EUSAGE' },
67    'logs usage'
68  )
69})
70
71t.test('invalid semver range', async t => {
72  const { npm } = await loadMockNpm(t)
73  await t.rejects(
74    npm.exec('deprecate', ['foo@notaversion', 'this will fail']),
75    /invalid version range/,
76    'logs semver error'
77  )
78})
79
80t.test('undeprecate', async t => {
81  const { npm, joinedOutput } = await loadMockNpm(t, { config: { ...auth } })
82  const registry = new MockRegistry({
83    tap: t,
84    registry: npm.config.get('registry'),
85    authorization: token,
86  })
87  const manifest = registry.manifest({
88    name: 'foo',
89    versions,
90  })
91  await registry.package({ manifest, query: { write: true } })
92  registry.nock.put('/foo', body => {
93    for (const version of versions) {
94      if (body.versions[version].deprecated !== '') {
95        return false
96      }
97    }
98    return true
99  }).reply(200, {})
100
101  await npm.exec('deprecate', ['foo', ''])
102  t.match(joinedOutput(), '')
103})
104
105t.test('deprecates given range', async t => {
106  const { npm, joinedOutput } = await loadMockNpm(t, { config: { ...auth } })
107  const registry = new MockRegistry({
108    tap: t,
109    registry: npm.config.get('registry'),
110    authorization: token,
111  })
112  const manifest = registry.manifest({
113    name: 'foo',
114    versions,
115  })
116  await registry.package({ manifest, query: { write: true } })
117  const message = 'test deprecation message'
118  registry.nock.put('/foo', body => {
119    if (body.versions['1.0.1'].deprecated) {
120      return false
121    }
122    if (body.versions['1.0.1-pre'].deprecated) {
123      return false
124    }
125    return body.versions['1.0.0'].deprecated === message
126  }).reply(200, {})
127  await npm.exec('deprecate', ['foo@1.0.0', message])
128  t.match(joinedOutput(), '')
129})
130
131t.test('deprecates all versions when no range is specified', async t => {
132  const { npm, joinedOutput } = await loadMockNpm(t, { config: { ...auth } })
133  const registry = new MockRegistry({
134    tap: t,
135    registry: npm.config.get('registry'),
136    authorization: token,
137  })
138  const manifest = registry.manifest({
139    name: 'foo',
140    versions,
141  })
142  await registry.package({ manifest, query: { write: true } })
143  const message = 'test deprecation message'
144  registry.nock.put('/foo', body => {
145    for (const version of versions) {
146      if (body.versions[version].deprecated !== message) {
147        return false
148      }
149    }
150    return true
151  }).reply(200, {})
152
153  await npm.exec('deprecate', ['foo', message])
154  t.match(joinedOutput(), '')
155})
156
157t.test('does nothing if version does not actually exist', async t => {
158  const { npm, joinedOutput } = await loadMockNpm(t, { config: { ...auth } })
159  const registry = new MockRegistry({
160    tap: t,
161    registry: npm.config.get('registry'),
162    authorization: token,
163  })
164  const manifest = registry.manifest({
165    name: 'foo',
166    versions,
167  })
168  await registry.package({ manifest, query: { write: true } })
169  await npm.exec('deprecate', ['foo@1.0.99', 'this should be ignored'])
170  t.match(joinedOutput(), '')
171})
172