2020-12-09 10:33:11 -05:00
|
|
|
const t = require('tap')
|
2022-03-31 22:43:17 +00:00
|
|
|
const { load: loadMockNpm } = require('../../fixtures/mock-npm')
|
2022-01-14 19:42:48 +02:00
|
|
|
|
2022-12-06 22:18:33 -05:00
|
|
|
const MockRegistry = require('@npmcli/mock-registry')
|
2022-03-31 22:43:17 +00:00
|
|
|
const user = 'test-user'
|
|
|
|
const pkg = 'test-package'
|
|
|
|
const auth = { '//registry.npmjs.org/:_authToken': 'test-auth-token' }
|
2020-12-09 10:33:11 -05:00
|
|
|
|
2022-03-31 22:43:17 +00:00
|
|
|
t.test('no args --force success', async t => {
|
|
|
|
const { joinedOutput, npm } = await loadMockNpm(t, {
|
|
|
|
config: {
|
|
|
|
force: true,
|
|
|
|
...auth,
|
2020-12-09 10:33:11 -05:00
|
|
|
},
|
2022-03-31 22:43:17 +00:00
|
|
|
prefixDir: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: pkg,
|
|
|
|
version: '1.0.0',
|
|
|
|
}, null, 2),
|
2020-12-09 10:33:11 -05:00
|
|
|
},
|
|
|
|
})
|
2021-05-20 15:54:50 -04:00
|
|
|
|
2022-04-14 21:57:02 +00:00
|
|
|
const registry = new MockRegistry({
|
|
|
|
tap: t,
|
|
|
|
registry: npm.config.get('registry'),
|
|
|
|
authorization: 'test-auth-token',
|
|
|
|
})
|
|
|
|
const manifest = registry.manifest({ name: pkg })
|
2024-01-11 06:28:56 -08:00
|
|
|
await registry.package({ manifest, query: { write: true }, times: 2 })
|
2023-02-18 17:09:39 -05:00
|
|
|
registry.unpublish({ manifest })
|
2022-03-31 22:43:17 +00:00
|
|
|
await npm.exec('unpublish', [])
|
2024-01-11 06:28:56 -08:00
|
|
|
t.equal(joinedOutput(), '- test-package')
|
2020-12-09 10:33:11 -05:00
|
|
|
})
|
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
t.test('no args --force missing package.json', async t => {
|
2022-03-31 22:43:17 +00:00
|
|
|
const { npm } = await loadMockNpm(t, {
|
|
|
|
config: {
|
|
|
|
force: true,
|
|
|
|
},
|
2020-12-09 10:33:11 -05:00
|
|
|
})
|
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
await t.rejects(
|
2022-03-31 22:43:17 +00:00
|
|
|
npm.exec('unpublish', []),
|
|
|
|
{ code: 'EUSAGE' },
|
2021-11-04 20:42:47 +00:00
|
|
|
'should throw usage instructions on missing package.json'
|
|
|
|
)
|
2020-12-09 10:33:11 -05:00
|
|
|
})
|
|
|
|
|
2022-03-31 22:43:17 +00:00
|
|
|
t.test('no args --force error reading package.json', async t => {
|
|
|
|
const { npm } = await loadMockNpm(t, {
|
|
|
|
config: {
|
|
|
|
force: true,
|
|
|
|
},
|
|
|
|
prefixDir: {
|
|
|
|
'package.json': '{ not valid json ]',
|
|
|
|
},
|
2020-12-09 10:33:11 -05:00
|
|
|
})
|
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
await t.rejects(
|
2022-03-31 22:43:17 +00:00
|
|
|
npm.exec('unpublish', []),
|
2023-06-08 05:24:49 -07:00
|
|
|
/Invalid package.json/,
|
2022-03-31 22:43:17 +00:00
|
|
|
'should throw error from reading package.json'
|
2021-11-04 20:42:47 +00:00
|
|
|
)
|
2020-12-09 10:33:11 -05:00
|
|
|
})
|
|
|
|
|
2024-01-11 06:28:56 -08:00
|
|
|
t.test('with args --force error reading package.json', async t => {
|
|
|
|
const { npm } = await loadMockNpm(t, {
|
|
|
|
config: {
|
|
|
|
force: true,
|
|
|
|
},
|
|
|
|
prefixDir: {
|
|
|
|
'package.json': '{ not valid json ]',
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
await t.rejects(
|
|
|
|
npm.exec('unpublish', [pkg]),
|
|
|
|
/Invalid package.json/,
|
|
|
|
'should throw error from reading package.json'
|
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.test('no force entire project', async t => {
|
2022-03-31 22:43:17 +00:00
|
|
|
const { npm } = await loadMockNpm(t)
|
2020-12-09 10:33:11 -05:00
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
await t.rejects(
|
2024-01-11 06:28:56 -08:00
|
|
|
npm.exec('unpublish', ['@npmcli/unpublish-test']),
|
2022-03-31 22:43:17 +00:00
|
|
|
/Refusing to delete entire project/
|
2021-11-04 20:42:47 +00:00
|
|
|
)
|
2020-12-09 10:33:11 -05:00
|
|
|
})
|
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
t.test('too many args', async t => {
|
2022-03-31 22:43:17 +00:00
|
|
|
const { npm } = await loadMockNpm(t)
|
2020-12-09 10:33:11 -05:00
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
await t.rejects(
|
2022-03-31 22:43:17 +00:00
|
|
|
npm.exec('unpublish', ['a', 'b']),
|
|
|
|
{ code: 'EUSAGE' },
|
2021-11-04 20:42:47 +00:00
|
|
|
'should throw usage instructions if too many args'
|
|
|
|
)
|
2020-12-09 10:33:11 -05:00
|
|
|
})
|
|
|
|
|
2024-01-11 06:28:56 -08:00
|
|
|
t.test('range', async t => {
|
|
|
|
const { npm } = await loadMockNpm(t)
|
|
|
|
|
|
|
|
await t.rejects(
|
|
|
|
npm.exec('unpublish', ['a@>1.0.0']),
|
|
|
|
{ code: 'EUSAGE' },
|
|
|
|
/single version/
|
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.test('tag', async t => {
|
|
|
|
const { npm } = await loadMockNpm(t)
|
|
|
|
|
|
|
|
await t.rejects(
|
|
|
|
npm.exec('unpublish', ['a@>1.0.0']),
|
|
|
|
{ code: 'EUSAGE' },
|
|
|
|
/single version/
|
|
|
|
)
|
|
|
|
})
|
|
|
|
|
2022-03-31 22:43:17 +00:00
|
|
|
t.test('unpublish <pkg>@version not the last version', async t => {
|
|
|
|
const { joinedOutput, npm } = await loadMockNpm(t, {
|
|
|
|
config: {
|
|
|
|
force: true,
|
|
|
|
...auth,
|
2020-12-09 10:33:11 -05:00
|
|
|
},
|
2022-03-31 22:43:17 +00:00
|
|
|
})
|
2022-04-14 21:57:02 +00:00
|
|
|
const registry = new MockRegistry({
|
|
|
|
tap: t,
|
|
|
|
registry: npm.config.get('registry'),
|
|
|
|
authorization: 'test-auth-token',
|
|
|
|
})
|
|
|
|
const manifest = registry.manifest({
|
|
|
|
name: pkg,
|
|
|
|
packuments: ['1.0.0', '1.0.1'],
|
|
|
|
})
|
|
|
|
await registry.package({ manifest, query: { write: true }, times: 3 })
|
|
|
|
registry.nock.put(`/${pkg}/-rev/${manifest._rev}`, body => {
|
|
|
|
// sets latest and deletes version 1.0.1
|
|
|
|
return body['dist-tags'].latest === '1.0.0' && body.versions['1.0.1'] === undefined
|
|
|
|
}).reply(201)
|
2022-03-31 22:43:17 +00:00
|
|
|
.intercept(`/${pkg}/-/${pkg}-1.0.1.tgz/-rev/${manifest._rev}`, 'DELETE').reply(201)
|
|
|
|
|
|
|
|
await npm.exec('unpublish', ['test-package@1.0.1'])
|
|
|
|
t.equal(joinedOutput(), '- test-package@1.0.1')
|
|
|
|
})
|
2020-12-09 10:33:11 -05:00
|
|
|
|
2022-03-31 22:43:17 +00:00
|
|
|
t.test('unpublish <pkg>@version last version', async t => {
|
|
|
|
const { npm } = await loadMockNpm(t, {
|
|
|
|
config: {
|
|
|
|
...auth,
|
2020-12-09 10:33:11 -05:00
|
|
|
},
|
|
|
|
})
|
2022-04-14 21:57:02 +00:00
|
|
|
const registry = new MockRegistry({
|
|
|
|
tap: t,
|
|
|
|
registry: npm.config.get('registry'),
|
|
|
|
authorization: 'test-auth-token',
|
|
|
|
})
|
|
|
|
const manifest = registry.manifest({ name: pkg })
|
|
|
|
await registry.package({ manifest, query: { write: true } })
|
2020-12-09 10:33:11 -05:00
|
|
|
|
2022-03-31 22:43:17 +00:00
|
|
|
await t.rejects(
|
|
|
|
npm.exec('unpublish', ['test-package@1.0.0']),
|
|
|
|
/Refusing to delete the last version of the package/
|
2021-11-04 20:42:47 +00:00
|
|
|
)
|
2020-12-09 10:33:11 -05:00
|
|
|
})
|
|
|
|
|
2024-01-11 06:28:56 -08:00
|
|
|
t.test('no version found in package.json no force', async t => {
|
|
|
|
const { npm } = await loadMockNpm(t, {
|
|
|
|
config: {
|
|
|
|
...auth,
|
|
|
|
},
|
|
|
|
prefixDir: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: pkg,
|
|
|
|
}, null, 2),
|
|
|
|
},
|
|
|
|
})
|
|
|
|
await t.rejects(
|
|
|
|
npm.exec('unpublish', []),
|
|
|
|
/Refusing to delete entire project/
|
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.test('no version found in package.json with force', async t => {
|
2022-03-31 22:43:17 +00:00
|
|
|
const { joinedOutput, npm } = await loadMockNpm(t, {
|
|
|
|
config: {
|
|
|
|
force: true,
|
|
|
|
...auth,
|
|
|
|
},
|
|
|
|
prefixDir: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: pkg,
|
|
|
|
}, null, 2),
|
|
|
|
},
|
2020-12-09 10:33:11 -05:00
|
|
|
})
|
2022-04-14 21:57:02 +00:00
|
|
|
const registry = new MockRegistry({
|
|
|
|
tap: t,
|
|
|
|
registry: npm.config.get('registry'),
|
|
|
|
authorization: 'test-auth-token',
|
|
|
|
})
|
|
|
|
const manifest = registry.manifest({ name: pkg })
|
2024-01-11 06:28:56 -08:00
|
|
|
await registry.package({ manifest, query: { write: true }, times: 2 })
|
2023-02-18 17:09:39 -05:00
|
|
|
registry.unpublish({ manifest })
|
2022-03-31 22:43:17 +00:00
|
|
|
|
|
|
|
await npm.exec('unpublish', [])
|
|
|
|
t.equal(joinedOutput(), '- test-package')
|
2020-12-09 10:33:11 -05:00
|
|
|
})
|
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
t.test('unpublish <pkg> --force no version set', async t => {
|
2022-03-31 22:43:17 +00:00
|
|
|
const { joinedOutput, npm } = await loadMockNpm(t, {
|
|
|
|
config: {
|
|
|
|
force: true,
|
|
|
|
...auth,
|
|
|
|
},
|
2020-12-09 10:33:11 -05:00
|
|
|
})
|
2022-04-14 21:57:02 +00:00
|
|
|
const registry = new MockRegistry({
|
|
|
|
tap: t,
|
|
|
|
registry: npm.config.get('registry'),
|
|
|
|
authorization: 'test-auth-token',
|
|
|
|
})
|
|
|
|
const manifest = registry.manifest({ name: pkg })
|
|
|
|
await registry.package({ manifest, query: { write: true }, times: 2 })
|
2023-02-18 17:09:39 -05:00
|
|
|
registry.unpublish({ manifest })
|
2022-03-31 22:43:17 +00:00
|
|
|
|
|
|
|
await npm.exec('unpublish', ['test-package'])
|
|
|
|
t.equal(joinedOutput(), '- test-package')
|
2020-12-09 10:33:11 -05:00
|
|
|
})
|
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
t.test('silent', async t => {
|
2022-03-31 22:43:17 +00:00
|
|
|
const { joinedOutput, npm } = await loadMockNpm(t, {
|
|
|
|
config: {
|
|
|
|
force: true,
|
|
|
|
loglevel: 'silent',
|
|
|
|
...auth,
|
|
|
|
},
|
2020-12-09 10:33:11 -05:00
|
|
|
})
|
2022-04-14 21:57:02 +00:00
|
|
|
const registry = new MockRegistry({
|
|
|
|
tap: t,
|
|
|
|
registry: npm.config.get('registry'),
|
|
|
|
authorization: 'test-auth-token',
|
|
|
|
})
|
|
|
|
const manifest = registry.manifest({
|
|
|
|
name: pkg,
|
|
|
|
packuments: ['1.0.0', '1.0.1'],
|
|
|
|
})
|
|
|
|
await registry.package({ manifest, query: { write: true }, times: 3 })
|
|
|
|
registry.nock.put(`/${pkg}/-rev/${manifest._rev}`, body => {
|
|
|
|
// sets latest and deletes version 1.0.1
|
|
|
|
return body['dist-tags'].latest === '1.0.0' && body.versions['1.0.1'] === undefined
|
|
|
|
}).reply(201)
|
2022-03-31 22:43:17 +00:00
|
|
|
.delete(`/${pkg}/-/${pkg}-1.0.1.tgz/-rev/${manifest._rev}`).reply(201)
|
|
|
|
|
|
|
|
await npm.exec('unpublish', ['test-package@1.0.1'])
|
|
|
|
t.equal(joinedOutput(), '')
|
2021-05-20 15:54:50 -04:00
|
|
|
})
|
2020-12-09 10:33:11 -05:00
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
t.test('workspaces', async t => {
|
2022-03-31 22:43:17 +00:00
|
|
|
const prefixDir = {
|
2021-05-20 15:54:50 -04:00
|
|
|
'package.json': JSON.stringify({
|
2022-03-31 22:43:17 +00:00
|
|
|
name: pkg,
|
2021-05-20 15:54:50 -04:00
|
|
|
version: '1.0.0',
|
|
|
|
workspaces: ['workspace-a', 'workspace-b', 'workspace-c'],
|
|
|
|
}, null, 2),
|
|
|
|
'workspace-a': {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'workspace-a',
|
|
|
|
version: '1.2.3-a',
|
|
|
|
repository: 'http://repo.workspace-a/',
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
'workspace-b': {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'workspace-b',
|
2024-01-11 06:28:56 -08:00
|
|
|
version: '1.2.3-b',
|
2021-05-20 15:54:50 -04:00
|
|
|
repository: 'https://github.com/npm/workspace-b',
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
'workspace-c': {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: 'workspace-n',
|
|
|
|
version: '1.2.3-n',
|
|
|
|
}),
|
|
|
|
},
|
2022-03-31 22:43:17 +00:00
|
|
|
}
|
2020-12-09 10:33:11 -05:00
|
|
|
|
2024-01-11 06:28:56 -08:00
|
|
|
t.test('with package name no force', async t => {
|
2022-03-31 22:43:17 +00:00
|
|
|
const { npm } = await loadMockNpm(t, {
|
|
|
|
config: {
|
2024-01-11 06:28:56 -08:00
|
|
|
workspace: ['workspace-a'],
|
2022-03-31 22:43:17 +00:00
|
|
|
},
|
|
|
|
prefixDir,
|
|
|
|
})
|
2021-11-04 20:42:47 +00:00
|
|
|
await t.rejects(
|
2024-01-11 06:28:56 -08:00
|
|
|
npm.exec('unpublish', ['workspace-a']),
|
2022-03-31 22:43:17 +00:00
|
|
|
/Refusing to delete entire project/
|
2021-11-04 20:42:47 +00:00
|
|
|
)
|
2021-05-20 15:54:50 -04:00
|
|
|
})
|
|
|
|
|
2024-01-11 06:28:56 -08:00
|
|
|
t.test('all workspaces last version --force', async t => {
|
2022-03-31 22:43:17 +00:00
|
|
|
const { joinedOutput, npm } = await loadMockNpm(t, {
|
|
|
|
config: {
|
|
|
|
workspaces: true,
|
|
|
|
force: true,
|
|
|
|
...auth,
|
|
|
|
},
|
|
|
|
prefixDir,
|
|
|
|
})
|
2022-04-14 21:57:02 +00:00
|
|
|
const registry = new MockRegistry({
|
|
|
|
tap: t,
|
|
|
|
registry: npm.config.get('registry'),
|
|
|
|
authorization: 'test-auth-token',
|
|
|
|
})
|
2024-01-11 06:28:56 -08:00
|
|
|
const manifestA = registry.manifest({ name: 'workspace-a', versions: ['1.2.3-a'] })
|
|
|
|
const manifestB = registry.manifest({ name: 'workspace-b', versions: ['1.2.3-b'] })
|
|
|
|
const manifestN = registry.manifest({ name: 'workspace-n', versions: ['1.2.3-n'] })
|
2022-04-14 21:57:02 +00:00
|
|
|
await registry.package({ manifest: manifestA, query: { write: true }, times: 2 })
|
|
|
|
await registry.package({ manifest: manifestB, query: { write: true }, times: 2 })
|
|
|
|
await registry.package({ manifest: manifestN, query: { write: true }, times: 2 })
|
|
|
|
registry.nock.delete(`/workspace-a/-rev/${manifestA._rev}`).reply(201)
|
2022-03-31 22:43:17 +00:00
|
|
|
.delete(`/workspace-b/-rev/${manifestB._rev}`).reply(201)
|
|
|
|
.delete(`/workspace-n/-rev/${manifestN._rev}`).reply(201)
|
|
|
|
|
|
|
|
await npm.exec('unpublish', [])
|
|
|
|
t.equal(joinedOutput(), '- workspace-a\n- workspace-b\n- workspace-n')
|
2021-05-20 15:54:50 -04:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2021-11-04 20:42:47 +00:00
|
|
|
t.test('dryRun with spec', async t => {
|
2022-03-31 22:43:17 +00:00
|
|
|
const { joinedOutput, npm } = await loadMockNpm(t, {
|
|
|
|
config: {
|
|
|
|
'dry-run': true,
|
|
|
|
...auth,
|
|
|
|
},
|
2021-05-20 15:54:50 -04:00
|
|
|
})
|
2022-04-14 21:57:02 +00:00
|
|
|
const registry = new MockRegistry({
|
|
|
|
tap: t,
|
|
|
|
registry: npm.config.get('registry'),
|
|
|
|
authorization: 'test-auth-token',
|
|
|
|
})
|
|
|
|
const manifest = registry.manifest({
|
|
|
|
name: pkg,
|
|
|
|
packuments: ['1.0.0', '1.0.1'],
|
|
|
|
})
|
|
|
|
await registry.package({ manifest, query: { write: true } })
|
2022-03-31 22:43:17 +00:00
|
|
|
|
|
|
|
await npm.exec('unpublish', ['test-package@1.0.1'])
|
|
|
|
t.equal(joinedOutput(), '- test-package@1.0.1')
|
2021-05-20 15:54:50 -04:00
|
|
|
})
|
|
|
|
|
2022-03-31 22:43:17 +00:00
|
|
|
t.test('dryRun with no args', async t => {
|
|
|
|
const { joinedOutput, npm } = await loadMockNpm(t, {
|
|
|
|
config: {
|
|
|
|
force: true,
|
|
|
|
'dry-run': true,
|
|
|
|
...auth,
|
|
|
|
},
|
|
|
|
prefixDir: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: pkg,
|
|
|
|
version: '1.0.0',
|
|
|
|
}, null, 2),
|
|
|
|
},
|
2021-05-20 15:54:50 -04:00
|
|
|
})
|
2024-01-11 06:28:56 -08:00
|
|
|
const registry = new MockRegistry({
|
|
|
|
tap: t,
|
|
|
|
registry: npm.config.get('registry'),
|
|
|
|
authorization: 'test-auth-token',
|
|
|
|
})
|
|
|
|
const manifest = registry.manifest({
|
|
|
|
name: pkg,
|
|
|
|
packuments: ['1.0.0', '1.0.1'],
|
|
|
|
})
|
|
|
|
await registry.package({ manifest, query: { write: true } })
|
2022-03-31 22:43:17 +00:00
|
|
|
|
|
|
|
await npm.exec('unpublish', [])
|
|
|
|
t.equal(joinedOutput(), '- test-package@1.0.0')
|
|
|
|
})
|
|
|
|
|
|
|
|
t.test('publishConfig no spec', async t => {
|
|
|
|
const alternateRegistry = 'https://other.registry.npmjs.org'
|
2025-03-13 05:31:42 -07:00
|
|
|
const { logs, joinedOutput, npm } = await loadMockNpm(t, {
|
2022-03-31 22:43:17 +00:00
|
|
|
config: {
|
|
|
|
force: true,
|
|
|
|
'//other.registry.npmjs.org/:_authToken': 'test-other-token',
|
|
|
|
},
|
|
|
|
prefixDir: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: pkg,
|
|
|
|
version: '1.0.0',
|
|
|
|
publishConfig: {
|
2025-03-13 05:31:42 -07:00
|
|
|
other: 'not defined',
|
2022-03-31 22:43:17 +00:00
|
|
|
registry: alternateRegistry,
|
|
|
|
},
|
|
|
|
}, null, 2),
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
2022-04-14 21:57:02 +00:00
|
|
|
const registry = new MockRegistry({
|
|
|
|
tap: t,
|
|
|
|
registry: alternateRegistry,
|
|
|
|
authorization: 'test-other-token',
|
|
|
|
})
|
|
|
|
const manifest = registry.manifest({ name: pkg })
|
2024-01-11 06:28:56 -08:00
|
|
|
await registry.package({ manifest, query: { write: true }, times: 2 })
|
2023-02-18 17:09:39 -05:00
|
|
|
registry.unpublish({ manifest })
|
2022-03-31 22:43:17 +00:00
|
|
|
await npm.exec('unpublish', [])
|
2024-01-11 06:28:56 -08:00
|
|
|
t.equal(joinedOutput(), '- test-package')
|
2025-03-13 05:31:42 -07:00
|
|
|
t.same(logs.warn, [
|
|
|
|
'using --force Recommended protections disabled.',
|
|
|
|
'Unknown publishConfig config "other". This will stop working in the next major version of npm.',
|
|
|
|
])
|
2022-03-31 22:43:17 +00:00
|
|
|
})
|
|
|
|
|
2024-04-11 18:24:57 -07:00
|
|
|
t.test('prioritize CLI flags over publishConfig no spec', async t => {
|
|
|
|
const alternateRegistry = 'https://other.registry.npmjs.org'
|
|
|
|
const publishConfig = { registry: 'http://publishconfig' }
|
|
|
|
const { joinedOutput, npm } = await loadMockNpm(t, {
|
|
|
|
config: {
|
|
|
|
force: true,
|
|
|
|
'//other.registry.npmjs.org/:_authToken': 'test-other-token',
|
|
|
|
},
|
|
|
|
prefixDir: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: pkg,
|
|
|
|
version: '1.0.0',
|
|
|
|
publishConfig,
|
|
|
|
}, null, 2),
|
|
|
|
},
|
|
|
|
argv: ['--registry', alternateRegistry],
|
|
|
|
})
|
|
|
|
|
|
|
|
const registry = new MockRegistry({
|
|
|
|
tap: t,
|
|
|
|
registry: alternateRegistry,
|
|
|
|
authorization: 'test-other-token',
|
|
|
|
})
|
|
|
|
const manifest = registry.manifest({ name: pkg })
|
|
|
|
await registry.package({ manifest, query: { write: true }, times: 2 })
|
|
|
|
registry.unpublish({ manifest })
|
|
|
|
await npm.exec('unpublish', [])
|
|
|
|
t.equal(joinedOutput(), '- test-package')
|
|
|
|
})
|
|
|
|
|
2022-03-31 22:43:17 +00:00
|
|
|
t.test('publishConfig with spec', async t => {
|
|
|
|
const alternateRegistry = 'https://other.registry.npmjs.org'
|
|
|
|
const { joinedOutput, npm } = await loadMockNpm(t, {
|
|
|
|
config: {
|
|
|
|
force: true,
|
|
|
|
'//other.registry.npmjs.org/:_authToken': 'test-other-token',
|
|
|
|
},
|
|
|
|
prefixDir: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: pkg,
|
|
|
|
version: '1.0.0',
|
|
|
|
publishConfig: {
|
|
|
|
registry: alternateRegistry,
|
|
|
|
},
|
|
|
|
}, null, 2),
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
2022-04-14 21:57:02 +00:00
|
|
|
const registry = new MockRegistry({
|
|
|
|
tap: t,
|
|
|
|
registry: alternateRegistry,
|
|
|
|
authorization: 'test-other-token',
|
|
|
|
})
|
|
|
|
const manifest = registry.manifest({ name: pkg })
|
|
|
|
await registry.package({ manifest, query: { write: true }, times: 2 })
|
2023-02-18 17:09:39 -05:00
|
|
|
registry.unpublish({ manifest })
|
2022-03-31 22:43:17 +00:00
|
|
|
await npm.exec('unpublish', ['test-package'])
|
|
|
|
t.equal(joinedOutput(), '- test-package')
|
2020-12-09 10:33:11 -05:00
|
|
|
})
|
|
|
|
|
2023-02-18 17:09:39 -05:00
|
|
|
t.test('scoped registry config', async t => {
|
|
|
|
const scopedPkg = `@npm/test-package`
|
|
|
|
const alternateRegistry = 'https://other.registry.npmjs.org'
|
|
|
|
const { npm } = await loadMockNpm(t, {
|
|
|
|
config: {
|
|
|
|
force: true,
|
|
|
|
'@npm:registry': alternateRegistry,
|
|
|
|
'//other.registry.npmjs.org/:_authToken': 'test-other-token',
|
|
|
|
},
|
|
|
|
prefixDir: {
|
|
|
|
'package.json': JSON.stringify({
|
|
|
|
name: pkg,
|
|
|
|
version: '1.0.0',
|
|
|
|
publishConfig: {
|
|
|
|
registry: alternateRegistry,
|
|
|
|
},
|
|
|
|
}, null, 2),
|
|
|
|
},
|
|
|
|
})
|
|
|
|
const registry = new MockRegistry({
|
|
|
|
tap: t,
|
|
|
|
registry: alternateRegistry,
|
|
|
|
authorization: 'test-other-token',
|
|
|
|
})
|
|
|
|
const manifest = registry.manifest({ name: scopedPkg })
|
2024-01-11 06:28:56 -08:00
|
|
|
await registry.package({ manifest, query: { write: true }, times: 2 })
|
2023-02-18 17:09:39 -05:00
|
|
|
registry.unpublish({ manifest })
|
|
|
|
await npm.exec('unpublish', [scopedPkg])
|
|
|
|
})
|
|
|
|
|
2021-03-01 11:38:43 -05:00
|
|
|
t.test('completion', async t => {
|
2023-06-08 05:24:49 -07:00
|
|
|
const { npm, unpublish } = await loadMockNpm(t, {
|
|
|
|
command: 'unpublish',
|
2022-03-31 22:43:17 +00:00
|
|
|
config: {
|
|
|
|
...auth,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
2021-03-01 11:38:43 -05:00
|
|
|
const testComp =
|
2022-03-31 22:43:17 +00:00
|
|
|
async (t, { argv, partialWord, expect, title }) => {
|
2021-03-04 17:40:28 -05:00
|
|
|
const res = await unpublish.completion(
|
2021-11-18 20:58:02 +00:00
|
|
|
{ conf: { argv: { remain: argv } }, partialWord }
|
2021-03-04 17:40:28 -05:00
|
|
|
)
|
2021-03-01 11:38:43 -05:00
|
|
|
t.strictSame(res, expect, title || argv.join(' '))
|
|
|
|
}
|
2020-12-09 10:33:11 -05:00
|
|
|
|
|
|
|
t.test('completing with multiple versions from the registry', async t => {
|
2022-04-14 21:57:02 +00:00
|
|
|
const registry = new MockRegistry({
|
|
|
|
tap: t,
|
|
|
|
registry: npm.config.get('registry'),
|
|
|
|
authorization: 'test-auth-token',
|
|
|
|
})
|
|
|
|
const manifest = registry.manifest({
|
|
|
|
name: pkg,
|
|
|
|
packuments: ['1.0.0', '1.0.1'],
|
|
|
|
})
|
|
|
|
await registry.package({ manifest, query: { write: true } })
|
2022-04-28 18:41:15 +05:30
|
|
|
registry.whoami({ username: user })
|
2022-12-06 22:18:33 -05:00
|
|
|
registry.getPackages({ team: user, packages: { [pkg]: 'write' } })
|
2020-12-09 10:33:11 -05:00
|
|
|
|
|
|
|
await testComp(t, {
|
|
|
|
argv: ['npm', 'unpublish'],
|
2022-03-31 22:43:17 +00:00
|
|
|
partialWord: 'test-package',
|
2020-12-09 10:33:11 -05:00
|
|
|
expect: [
|
2022-03-31 22:43:17 +00:00
|
|
|
'test-package@1.0.0',
|
|
|
|
'test-package@1.0.1',
|
2020-12-09 10:33:11 -05:00
|
|
|
],
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
t.test('no versions retrieved', async t => {
|
2022-04-14 21:57:02 +00:00
|
|
|
const registry = new MockRegistry({
|
|
|
|
tap: t,
|
|
|
|
registry: npm.config.get('registry'),
|
|
|
|
authorization: 'test-auth-token',
|
|
|
|
})
|
|
|
|
const manifest = registry.manifest({ name: pkg })
|
2022-03-31 22:43:17 +00:00
|
|
|
manifest.versions = {}
|
2022-04-14 21:57:02 +00:00
|
|
|
await registry.package({ manifest, query: { write: true } })
|
2022-04-28 18:41:15 +05:30
|
|
|
registry.whoami({ username: user })
|
2022-12-06 22:18:33 -05:00
|
|
|
registry.getPackages({ team: user, packages: { [pkg]: 'write' } })
|
2020-12-09 10:33:11 -05:00
|
|
|
|
|
|
|
await testComp(t, {
|
|
|
|
argv: ['npm', 'unpublish'],
|
2022-03-31 22:43:17 +00:00
|
|
|
partialWord: pkg,
|
2020-12-09 10:33:11 -05:00
|
|
|
expect: [
|
2022-03-31 22:43:17 +00:00
|
|
|
pkg,
|
2020-12-09 10:33:11 -05:00
|
|
|
],
|
|
|
|
title: 'should autocomplete package name only',
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
t.test('packages starting with same letters', async t => {
|
2022-04-14 21:57:02 +00:00
|
|
|
const registry = new MockRegistry({
|
|
|
|
tap: t,
|
|
|
|
registry: npm.config.get('registry'),
|
|
|
|
authorization: 'test-auth-token',
|
|
|
|
})
|
2022-04-28 18:41:15 +05:30
|
|
|
registry.whoami({ username: user })
|
2022-12-06 22:18:33 -05:00
|
|
|
registry.getPackages({ team: user,
|
|
|
|
packages: {
|
|
|
|
[pkg]: 'write',
|
|
|
|
[`${pkg}a`]: 'write',
|
|
|
|
[`${pkg}b`]: 'write',
|
|
|
|
} })
|
2020-12-09 10:33:11 -05:00
|
|
|
|
|
|
|
await testComp(t, {
|
|
|
|
argv: ['npm', 'unpublish'],
|
2022-03-31 22:43:17 +00:00
|
|
|
partialWord: pkg,
|
2020-12-09 10:33:11 -05:00
|
|
|
expect: [
|
2022-03-31 22:43:17 +00:00
|
|
|
pkg,
|
|
|
|
`${pkg}a`,
|
|
|
|
`${pkg}b`,
|
2020-12-09 10:33:11 -05:00
|
|
|
],
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
t.test('no packages retrieved', async t => {
|
2022-04-14 21:57:02 +00:00
|
|
|
const registry = new MockRegistry({
|
|
|
|
tap: t,
|
|
|
|
registry: npm.config.get('registry'),
|
|
|
|
authorization: 'test-auth-token',
|
|
|
|
})
|
2022-04-28 18:41:15 +05:30
|
|
|
registry.whoami({ username: user })
|
2022-12-06 22:18:33 -05:00
|
|
|
registry.getPackages({ team: user, packages: {} })
|
2020-12-09 10:33:11 -05:00
|
|
|
|
|
|
|
await testComp(t, {
|
|
|
|
argv: ['npm', 'unpublish'],
|
|
|
|
partialWord: 'pkg',
|
|
|
|
expect: [],
|
|
|
|
title: 'should have no autocompletion',
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
t.test('no pkg name to complete', async t => {
|
2022-04-14 21:57:02 +00:00
|
|
|
const registry = new MockRegistry({
|
|
|
|
tap: t,
|
|
|
|
registry: npm.config.get('registry'),
|
|
|
|
authorization: 'test-auth-token',
|
|
|
|
})
|
2022-04-28 18:41:15 +05:30
|
|
|
registry.whoami({ username: user })
|
2022-12-06 22:18:33 -05:00
|
|
|
registry.getPackages({ team: user,
|
|
|
|
packages: {
|
|
|
|
[pkg]: 'write',
|
|
|
|
[`${pkg}a`]: 'write',
|
|
|
|
} })
|
2020-12-09 10:33:11 -05:00
|
|
|
|
|
|
|
await testComp(t, {
|
|
|
|
argv: ['npm', 'unpublish'],
|
|
|
|
partialWord: undefined,
|
2022-03-31 22:43:17 +00:00
|
|
|
expect: [pkg, `${pkg}a`],
|
2020-12-09 10:33:11 -05:00
|
|
|
title: 'should autocomplete with available package names from user',
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
t.test('logged out user', async t => {
|
2022-04-14 21:57:02 +00:00
|
|
|
const registry = new MockRegistry({
|
|
|
|
tap: t,
|
|
|
|
registry: npm.config.get('registry'),
|
|
|
|
authorization: 'test-auth-token',
|
|
|
|
})
|
2022-04-28 18:41:15 +05:30
|
|
|
registry.whoami({ responseCode: 404 })
|
2020-12-09 10:33:11 -05:00
|
|
|
|
|
|
|
await testComp(t, {
|
|
|
|
argv: ['npm', 'unpublish'],
|
2022-03-31 22:43:17 +00:00
|
|
|
partialWord: pkg,
|
2020-12-09 10:33:11 -05:00
|
|
|
expect: [],
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
t.test('too many args', async t => {
|
|
|
|
await testComp(t, {
|
|
|
|
argv: ['npm', 'unpublish', 'foo'],
|
|
|
|
partialWord: undefined,
|
|
|
|
expect: [],
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|