PR-URL: https://github.com/nodejs/node/pull/63463 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Jordan Harband <ljharb@gmail.com>
943 lines
25 KiB
JavaScript
943 lines
25 KiB
JavaScript
const t = require('tap')
|
|
const { load: loadMockNpm } = require('../fixtures/mock-npm.js')
|
|
const MockRegistry = require('@npmcli/mock-registry')
|
|
const realProcLog = require('proc-log')
|
|
const TrustCommand = require('../../lib/trust-cmd.js')
|
|
|
|
const packageName = '@npmcli/test-package'
|
|
|
|
t.test('trust-cmd via trust github with read function called', async t => {
|
|
const { npm } = await loadMockNpm(t, {
|
|
prefixDir: {
|
|
'package.json': JSON.stringify({
|
|
name: packageName,
|
|
version: '1.0.0',
|
|
}),
|
|
},
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
},
|
|
mocks: {
|
|
read: {
|
|
read: async () => 'y',
|
|
},
|
|
},
|
|
})
|
|
|
|
const registry = new MockRegistry({
|
|
tap: t,
|
|
registry: npm.config.get('registry'),
|
|
authorization: 'test-auth-token',
|
|
})
|
|
|
|
registry.trustCreate({ packageName })
|
|
|
|
await npm.exec('trust', ['github', '--allow-publish', packageName, '--file', 'workflow.yml', '--repository', 'npm/cli'])
|
|
})
|
|
|
|
t.test('trust-cmd via trust github with all options', async t => {
|
|
const { npm } = await loadMockNpm(t, {
|
|
prefixDir: {
|
|
'package.json': JSON.stringify({
|
|
name: packageName,
|
|
version: '1.0.0',
|
|
}),
|
|
},
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
yes: true,
|
|
},
|
|
})
|
|
|
|
const registry = new MockRegistry({
|
|
tap: t,
|
|
registry: npm.config.get('registry'),
|
|
authorization: 'test-auth-token',
|
|
})
|
|
|
|
registry.trustCreate({ packageName })
|
|
|
|
await npm.exec('trust', ['github', '--allow-publish', packageName, '--file', 'workflow.yml', '--repository', 'npm/cli', '--environment', 'production'])
|
|
})
|
|
|
|
t.test('trust-cmd via trust github with --allow-stage-publish', async t => {
|
|
const { npm } = await loadMockNpm(t, {
|
|
prefixDir: {
|
|
'package.json': JSON.stringify({
|
|
name: packageName,
|
|
version: '1.0.0',
|
|
}),
|
|
},
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
yes: true,
|
|
},
|
|
})
|
|
|
|
const registry = new MockRegistry({
|
|
tap: t,
|
|
registry: npm.config.get('registry'),
|
|
authorization: 'test-auth-token',
|
|
})
|
|
|
|
registry.trustCreate({ packageName })
|
|
|
|
await npm.exec('trust', ['github', '--allow-stage-publish', packageName, '--file', 'workflow.yml', '--repository', 'npm/cli'])
|
|
})
|
|
|
|
t.test('trust-cmd via trust github with --allow-staged-publish alias', async t => {
|
|
const { npm } = await loadMockNpm(t, {
|
|
prefixDir: {
|
|
'package.json': JSON.stringify({
|
|
name: packageName,
|
|
version: '1.0.0',
|
|
}),
|
|
},
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
yes: true,
|
|
},
|
|
})
|
|
|
|
const registry = new MockRegistry({
|
|
tap: t,
|
|
registry: npm.config.get('registry'),
|
|
authorization: 'test-auth-token',
|
|
})
|
|
|
|
registry.trustCreate({ packageName })
|
|
|
|
await npm.exec('trust', ['github', '--allow-staged-publish', packageName, '--file', 'workflow.yml', '--repository', 'npm/cli'])
|
|
})
|
|
|
|
t.test('trust-cmd via trust github missing permissions', async t => {
|
|
const { npm } = await loadMockNpm(t, {
|
|
prefixDir: {
|
|
'package.json': JSON.stringify({
|
|
name: packageName,
|
|
version: '1.0.0',
|
|
}),
|
|
},
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
yes: true,
|
|
},
|
|
})
|
|
|
|
await t.rejects(
|
|
npm.exec('trust', ['github', packageName, '--file', 'workflow.yml', '--repository', 'npm/cli']),
|
|
{ message: /At least one permission flag is required/ }
|
|
)
|
|
})
|
|
|
|
t.test('trust-cmd via trust github infers from package.json', async t => {
|
|
const { npm } = await loadMockNpm(t, {
|
|
prefixDir: {
|
|
'package.json': JSON.stringify({
|
|
name: packageName,
|
|
version: '1.0.0',
|
|
repository: 'https://github.com/npm/cli',
|
|
}),
|
|
},
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
},
|
|
mocks: {
|
|
'proc-log': {
|
|
...realProcLog,
|
|
input: {
|
|
...realProcLog.input,
|
|
read: async () => 'y',
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
const registry = new MockRegistry({
|
|
tap: t,
|
|
registry: npm.config.get('registry'),
|
|
authorization: 'test-auth-token',
|
|
})
|
|
|
|
registry.trustCreate({ packageName })
|
|
|
|
await npm.exec('trust', ['github', '--allow-publish', '--yes', '--file', 'workflow.yml'])
|
|
})
|
|
|
|
t.test('trust-cmd via trust github with dry-run', async t => {
|
|
const { npm, joinedOutput } = await loadMockNpm(t, {
|
|
prefixDir: {
|
|
'package.json': JSON.stringify({
|
|
name: packageName,
|
|
version: '1.0.0',
|
|
}),
|
|
},
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
'dry-run': true,
|
|
},
|
|
})
|
|
|
|
await npm.exec('trust', ['github', '--allow-publish', packageName, '--file', 'workflow.yml', '--repository', 'npm/cli'])
|
|
|
|
t.ok(joinedOutput().includes('Establishing trust'), 'shows notice about establishing trust')
|
|
})
|
|
|
|
t.test('trust-cmd via trust github missing package name', async t => {
|
|
const { npm } = await loadMockNpm(t, {
|
|
prefixDir: {},
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
},
|
|
})
|
|
|
|
await t.rejects(
|
|
npm.exec('trust', ['github', '--allow-publish', '--file', 'workflow.yml', '--repository', 'npm/cli']),
|
|
{ message: /Package name must be specified/ },
|
|
'throws when no package name'
|
|
)
|
|
})
|
|
|
|
t.test('trust-cmd via trust github missing file', async t => {
|
|
const { npm } = await loadMockNpm(t, {
|
|
prefixDir: {
|
|
'package.json': JSON.stringify({
|
|
name: packageName,
|
|
}),
|
|
},
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
},
|
|
})
|
|
|
|
await t.rejects(
|
|
npm.exec('trust', ['github', '--allow-publish', packageName, '--repository', 'npm/cli']),
|
|
{ message: /must be specified with the file option/ },
|
|
'throws when no file'
|
|
)
|
|
})
|
|
|
|
t.test('trust-cmd via trust github invalid file extension', async t => {
|
|
const { npm } = await loadMockNpm(t, {
|
|
prefixDir: {
|
|
'package.json': JSON.stringify({
|
|
name: packageName,
|
|
}),
|
|
},
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
},
|
|
})
|
|
|
|
await t.rejects(
|
|
npm.exec('trust', ['github', '--allow-publish', packageName, '--file', 'workflow.txt', '--repository', 'npm/cli']),
|
|
{ message: /must end in \.yml or \.yaml/ },
|
|
'throws when file has wrong extension'
|
|
)
|
|
})
|
|
|
|
t.test('trust-cmd via trust github missing repository', async t => {
|
|
const { npm } = await loadMockNpm(t, {
|
|
prefixDir: {
|
|
'package.json': JSON.stringify({
|
|
name: packageName,
|
|
}),
|
|
},
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
},
|
|
})
|
|
|
|
await t.rejects(
|
|
npm.exec('trust', ['github', '--allow-publish', packageName, '--file', 'workflow.yml']),
|
|
{ message: /must be specified with repository option/ },
|
|
'throws when no repository'
|
|
)
|
|
})
|
|
|
|
t.test('trust-cmd via trust github with custom registry warning', async t => {
|
|
const { npm, logs } = await loadMockNpm(t, {
|
|
prefixDir: {
|
|
'package.json': JSON.stringify({
|
|
name: packageName,
|
|
version: '1.0.0',
|
|
}),
|
|
},
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
registry: 'https://custom.registry.com/',
|
|
'dry-run': true,
|
|
},
|
|
})
|
|
|
|
await npm.exec('trust', ['github', '--allow-publish', packageName, '--file', 'workflow.yml', '--repository', 'npm/cli'])
|
|
|
|
t.ok(logs.warn.some(l => l.includes('may not support trusted publishing')), 'warns about custom registry')
|
|
})
|
|
|
|
t.test('trust-cmd via trust github with --json', async t => {
|
|
const { npm, joinedOutput } = await loadMockNpm(t, {
|
|
prefixDir: {
|
|
'package.json': JSON.stringify({
|
|
name: packageName,
|
|
version: '1.0.0',
|
|
}),
|
|
},
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
json: true,
|
|
'dry-run': true,
|
|
},
|
|
})
|
|
|
|
await npm.exec('trust', ['github', '--allow-publish', packageName, '--file', 'workflow.yml', '--repository', 'npm/cli'])
|
|
|
|
const output = joinedOutput()
|
|
t.ok(output.includes(packageName), 'JSON output includes package name')
|
|
t.ok(output.includes('workflow.yml'), 'JSON output includes file')
|
|
})
|
|
|
|
t.test('trust-cmd via trust github with user confirmation no', async t => {
|
|
const { npm } = await loadMockNpm(t, {
|
|
prefixDir: {
|
|
'package.json': JSON.stringify({
|
|
name: packageName,
|
|
version: '1.0.0',
|
|
}),
|
|
},
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
},
|
|
mocks: {
|
|
'proc-log': {
|
|
...realProcLog,
|
|
input: {
|
|
...realProcLog.input,
|
|
read: async () => 'n',
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
await t.rejects(
|
|
npm.exec('trust', ['github', '--allow-publish', packageName, '--file', 'workflow.yml', '--repository', 'npm/cli']),
|
|
{ message: 'User cancelled operation' },
|
|
'throws when user declines'
|
|
)
|
|
})
|
|
|
|
t.test('trust-cmd via trust github with --no-yes', async t => {
|
|
const { npm } = await loadMockNpm(t, {
|
|
prefixDir: {
|
|
'package.json': JSON.stringify({
|
|
name: packageName,
|
|
version: '1.0.0',
|
|
}),
|
|
},
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
yes: false,
|
|
},
|
|
})
|
|
|
|
await t.rejects(
|
|
npm.exec('trust', ['github', '--allow-publish', packageName, '--file', 'workflow.yml', '--repository', 'npm/cli']),
|
|
{ message: 'User cancelled operation' },
|
|
'throws when --no-yes flag is set'
|
|
)
|
|
})
|
|
|
|
t.test('trust-cmd via trust github with invalid answer', async t => {
|
|
const { npm } = await loadMockNpm(t, {
|
|
prefixDir: {
|
|
'package.json': JSON.stringify({
|
|
name: packageName,
|
|
version: '1.0.0',
|
|
}),
|
|
},
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
},
|
|
mocks: {
|
|
'proc-log': {
|
|
...realProcLog,
|
|
input: {
|
|
...realProcLog.input,
|
|
read: async () => 'maybe',
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
await t.rejects(
|
|
npm.exec('trust', ['github', '--allow-publish', packageName, '--file', 'workflow.yml', '--repository', 'npm/cli']),
|
|
{ message: 'User cancelled operation' },
|
|
'throws when user gives invalid answer'
|
|
)
|
|
})
|
|
|
|
t.test('trust-cmd via trust github with user confirmation Y uppercase', async t => {
|
|
const { npm } = await loadMockNpm(t, {
|
|
prefixDir: {
|
|
'package.json': JSON.stringify({
|
|
name: packageName,
|
|
version: '1.0.0',
|
|
}),
|
|
},
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
},
|
|
mocks: {
|
|
'proc-log': {
|
|
...realProcLog,
|
|
input: {
|
|
...realProcLog.input,
|
|
read: async () => 'Y',
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
const registry = new MockRegistry({
|
|
tap: t,
|
|
registry: npm.config.get('registry'),
|
|
authorization: 'test-auth-token',
|
|
})
|
|
|
|
registry.trustCreate({ packageName })
|
|
|
|
await npm.exec('trust', ['github', '--allow-publish', packageName, '--file', 'workflow.yml', '--repository', 'npm/cli'])
|
|
})
|
|
|
|
t.test('trust-cmd via trust github with user enters empty string', async t => {
|
|
const { npm } = await loadMockNpm(t, {
|
|
prefixDir: {
|
|
'package.json': JSON.stringify({
|
|
name: packageName,
|
|
version: '1.0.0',
|
|
}),
|
|
},
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
},
|
|
mocks: {
|
|
'proc-log': {
|
|
...realProcLog,
|
|
input: {
|
|
...realProcLog.input,
|
|
read: async () => '',
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
await t.rejects(
|
|
npm.exec('trust', ['github', '--allow-publish', packageName, '--file', 'workflow.yml', '--repository', 'npm/cli']),
|
|
{ message: 'User cancelled operation' },
|
|
'throws when user enters empty string'
|
|
)
|
|
})
|
|
|
|
t.test('trust-cmd via trust github with mismatched repo type', async t => {
|
|
const { npm } = await loadMockNpm(t, {
|
|
prefixDir: {
|
|
'package.json': JSON.stringify({
|
|
name: packageName,
|
|
version: '1.0.0',
|
|
repository: 'https://gitlab.com/npm/cli',
|
|
}),
|
|
},
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
},
|
|
})
|
|
|
|
await t.rejects(
|
|
npm.exec('trust', ['github', '--allow-publish', '--file', 'workflow.yml']),
|
|
{ message: /Repository in package.json is not a GitHub repository/ },
|
|
'throws when repository type does not match provider'
|
|
)
|
|
})
|
|
|
|
t.test('trust-cmd via trust github with mismatched repo type but flag provided', async t => {
|
|
const { npm, logs } = await loadMockNpm(t, {
|
|
prefixDir: {
|
|
'package.json': JSON.stringify({
|
|
name: packageName,
|
|
version: '1.0.0',
|
|
repository: 'https://gitlab.com/owner/old-repo',
|
|
}),
|
|
},
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
'dry-run': true,
|
|
},
|
|
})
|
|
|
|
await npm.exec('trust', ['github', '--allow-publish', '--file', 'workflow.yml', '--repository', 'owner/new-repo'])
|
|
|
|
t.ok(logs.warn.some(l => l.includes('Repository in package.json is not a GitHub repository')), 'warns about repository type mismatch')
|
|
})
|
|
|
|
t.test('trust-cmd via trust github with different repo in package.json', async t => {
|
|
const { npm, logs } = await loadMockNpm(t, {
|
|
prefixDir: {
|
|
'package.json': JSON.stringify({
|
|
name: packageName,
|
|
version: '1.0.0',
|
|
repository: 'https://github.com/owner/old-repo',
|
|
}),
|
|
},
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
'dry-run': true,
|
|
},
|
|
})
|
|
|
|
await npm.exec('trust', ['github', '--allow-publish', '--file', 'workflow.yml', '--repository', 'owner/new-repo'])
|
|
|
|
t.ok(logs.warn.some(l => l.includes('differs from provided')), 'warns about repository mismatch')
|
|
})
|
|
|
|
t.test('trust-cmd via trust github with user confirmation yes spelled out', async t => {
|
|
const { npm } = await loadMockNpm(t, {
|
|
prefixDir: {
|
|
'package.json': JSON.stringify({
|
|
name: packageName,
|
|
version: '1.0.0',
|
|
}),
|
|
},
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
},
|
|
mocks: {
|
|
'proc-log': {
|
|
...realProcLog,
|
|
input: {
|
|
...realProcLog.input,
|
|
read: async () => 'yes',
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
const registry = new MockRegistry({
|
|
tap: t,
|
|
registry: npm.config.get('registry'),
|
|
authorization: 'test-auth-token',
|
|
})
|
|
|
|
registry.trustCreate({ packageName })
|
|
|
|
await npm.exec('trust', ['github', '--allow-publish', packageName, '--file', 'workflow.yml', '--repository', 'npm/cli'])
|
|
})
|
|
|
|
t.test('trust-cmd via trust github showing response with id and type', async t => {
|
|
const { npm, joinedOutput } = await loadMockNpm(t, {
|
|
prefixDir: {
|
|
'package.json': JSON.stringify({
|
|
name: packageName,
|
|
version: '1.0.0',
|
|
}),
|
|
},
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
},
|
|
mocks: {
|
|
read: {
|
|
read: async () => 'y',
|
|
},
|
|
},
|
|
})
|
|
|
|
const registry = new MockRegistry({
|
|
tap: t,
|
|
registry: npm.config.get('registry'),
|
|
authorization: 'test-auth-token',
|
|
})
|
|
|
|
registry.trustCreate({
|
|
packageName,
|
|
body: {
|
|
id: 'config-id-123',
|
|
type: 'github',
|
|
claims: {
|
|
repository: 'npm/cli',
|
|
workflow_ref: {
|
|
file: 'workflow.yml',
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
await npm.exec('trust', ['github', '--allow-publish', packageName, '--file', 'workflow.yml', '--repository', 'npm/cli'])
|
|
|
|
const output = joinedOutput()
|
|
t.ok(output.includes('type:'), 'output shows type field')
|
|
t.ok(output.includes('id:'), 'output shows id field')
|
|
})
|
|
|
|
t.test('trust-cmd via trust github missing repository when package name differs', async t => {
|
|
const { npm } = await loadMockNpm(t, {
|
|
prefixDir: {
|
|
'package.json': JSON.stringify({
|
|
name: 'other-package',
|
|
}),
|
|
},
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
},
|
|
})
|
|
|
|
await t.rejects(
|
|
npm.exec('trust', ['github', '--allow-publish', packageName, '--file', 'workflow.yml']),
|
|
{ message: /must be specified with repository option/ },
|
|
'throws when no repository and package name differs'
|
|
)
|
|
})
|
|
|
|
t.test('TrustCommand - createConfig', async t => {
|
|
const { npm } = await loadMockNpm(t, {
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
},
|
|
})
|
|
|
|
class TestTrustCmd extends TrustCommand {
|
|
static name = 'test'
|
|
static description = 'Test command'
|
|
}
|
|
|
|
const cmd = new TestTrustCmd(npm)
|
|
|
|
const registry = new MockRegistry({
|
|
tap: t,
|
|
registry: npm.config.get('registry'),
|
|
authorization: 'test-auth-token',
|
|
})
|
|
|
|
registry.trustCreate({ packageName })
|
|
|
|
const response = await cmd.createConfig(packageName, [{ type: 'test' }])
|
|
t.ok(response, 'returns a response')
|
|
})
|
|
|
|
t.test('TrustCommand - bodyToOptions', t => {
|
|
const body = {
|
|
id: 'test-id',
|
|
type: 'test-type',
|
|
other: 'ignored',
|
|
}
|
|
|
|
const options = TrustCommand.bodyToOptions(body)
|
|
|
|
t.equal(options.id, 'test-id', 'includes id')
|
|
t.equal(options.type, 'test-type', 'includes type')
|
|
t.notOk(options.other, 'does not include other fields')
|
|
t.end()
|
|
})
|
|
|
|
t.test('TrustCommand - bodyToOptions with missing fields', t => {
|
|
const body = {}
|
|
|
|
const options = TrustCommand.bodyToOptions(body)
|
|
|
|
t.same(options, {}, 'returns empty object when no fields')
|
|
t.end()
|
|
})
|
|
|
|
t.test('TrustCommand - NPM_FRONTEND constant', t => {
|
|
t.equal(TrustCommand.NPM_FRONTEND, 'https://www.npmjs.com', 'exports NPM_FRONTEND constant')
|
|
t.end()
|
|
})
|
|
t.test('trust-cmd via trust github showing fromPackageJson indicator', async t => {
|
|
const { npm, joinedOutput } = await loadMockNpm(t, {
|
|
prefixDir: {
|
|
'package.json': JSON.stringify({
|
|
name: packageName,
|
|
version: '1.0.0',
|
|
repository: 'https://github.com/npm/cli',
|
|
}),
|
|
},
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
},
|
|
mocks: {
|
|
read: {
|
|
read: async () => 'y',
|
|
},
|
|
},
|
|
})
|
|
|
|
const registry = new MockRegistry({
|
|
tap: t,
|
|
registry: npm.config.get('registry'),
|
|
authorization: 'test-auth-token',
|
|
})
|
|
|
|
registry.trustCreate({
|
|
packageName,
|
|
body: {
|
|
id: 'config-id-123',
|
|
type: 'github',
|
|
claims: {
|
|
repository: 'npm/cli',
|
|
workflow_ref: {
|
|
file: 'workflow.yml',
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
await npm.exec('trust', ['github', '--allow-publish', packageName, '--file', 'workflow.yml'])
|
|
|
|
const output = joinedOutput()
|
|
t.ok(output.includes('from package.json'), 'output shows fromPackageJson indicator')
|
|
})
|
|
|
|
t.test('trust-cmd via trust github showing URLs for fields', async t => {
|
|
const { npm, joinedOutput } = await loadMockNpm(t, {
|
|
prefixDir: {
|
|
'package.json': JSON.stringify({
|
|
name: packageName,
|
|
version: '1.0.0',
|
|
}),
|
|
},
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
},
|
|
mocks: {
|
|
read: {
|
|
read: async () => 'y',
|
|
},
|
|
},
|
|
})
|
|
|
|
const registry = new MockRegistry({
|
|
tap: t,
|
|
registry: npm.config.get('registry'),
|
|
authorization: 'test-auth-token',
|
|
})
|
|
|
|
registry.trustCreate({
|
|
packageName,
|
|
body: {
|
|
id: 'config-id-123',
|
|
type: 'github',
|
|
claims: {
|
|
repository: 'npm/cli',
|
|
workflow_ref: {
|
|
file: 'workflow.yml',
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
await npm.exec('trust', ['github', '--allow-publish', packageName, '--file', 'workflow.yml', '--repository', 'npm/cli'])
|
|
|
|
const output = joinedOutput()
|
|
t.match(output, /https:\/\/github\.com\/npm\/cli\b/, 'output shows repository URL')
|
|
})
|
|
|
|
t.test('trust-cmd via trust github with yes=false flag', async t => {
|
|
const { npm } = await loadMockNpm(t, {
|
|
prefixDir: {
|
|
'package.json': JSON.stringify({
|
|
name: packageName,
|
|
version: '1.0.0',
|
|
}),
|
|
},
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
yes: false,
|
|
},
|
|
})
|
|
|
|
await t.rejects(
|
|
npm.exec('trust', ['github', '--allow-publish', packageName, '--file', 'workflow.yml', '--repository', 'npm/cli']),
|
|
{ message: /User cancelled operation/ },
|
|
'throws when yes is explicitly false'
|
|
)
|
|
})
|
|
|
|
t.test('TrustCommand - logOptions with no values', async t => {
|
|
const { npm } = await loadMockNpm(t, {
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
},
|
|
})
|
|
|
|
class TestTrustCmd extends TrustCommand {
|
|
static name = 'test'
|
|
static description = 'Test command'
|
|
}
|
|
|
|
const cmd = new TestTrustCmd(npm)
|
|
|
|
// Call logOptions with no values object
|
|
cmd.logOptions({})
|
|
t.pass('logOptions handles missing values object')
|
|
})
|
|
|
|
t.test('TrustCommand - logOptions with falsey value', async t => {
|
|
const { npm } = await loadMockNpm(t, {
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
},
|
|
})
|
|
|
|
class TestTrustCmd extends TrustCommand {
|
|
static name = 'test'
|
|
static description = 'Test command'
|
|
}
|
|
|
|
const cmd = new TestTrustCmd(npm)
|
|
|
|
// Call logOptions with a falsey but not null/undefined value
|
|
cmd.logOptions({ values: { type: 'test', falseyField: 0, anotherFalsey: false, emptyString: '' } })
|
|
t.pass('logOptions handles falsey values that are not null/undefined')
|
|
})
|
|
|
|
t.test('TrustCommand - logOptions with null and undefined values', async t => {
|
|
const { npm, joinedOutput } = await loadMockNpm(t, {
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
},
|
|
})
|
|
|
|
class TestTrustCmd extends TrustCommand {
|
|
static name = 'test'
|
|
static description = 'Test command'
|
|
}
|
|
|
|
const cmd = new TestTrustCmd(npm)
|
|
|
|
// Call logOptions with null and undefined values that should be skipped
|
|
cmd.logOptions({ values: { type: 'test', id: 'test-id', nullField: null, undefinedField: undefined, validField: 'value' } })
|
|
const output = joinedOutput()
|
|
t.ok(output.includes('validField'), 'shows valid field')
|
|
t.notOk(output.includes('nullField'), 'skips null field')
|
|
t.notOk(output.includes('undefinedField'), 'skips undefined field')
|
|
})
|
|
|
|
t.test('TrustCommand - logOptions with fromPackageJson and urls', async t => {
|
|
const { npm, joinedOutput } = await loadMockNpm(t, {
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
},
|
|
})
|
|
|
|
class TestTrustCmd extends TrustCommand {
|
|
static name = 'test'
|
|
static description = 'Test command'
|
|
}
|
|
|
|
const cmd = new TestTrustCmd(npm)
|
|
|
|
// Call logOptions with fromPackageJson and urls objects
|
|
cmd.logOptions({
|
|
values: {
|
|
type: 'github',
|
|
id: 'test-id',
|
|
repository: 'npm/cli',
|
|
file: 'workflow.yml',
|
|
},
|
|
fromPackageJson: {
|
|
repository: true,
|
|
},
|
|
urls: {
|
|
repository: 'https://github.com/npm/cli',
|
|
file: 'https://github.com/npm/cli/-/blob/HEAD/workflow.yml',
|
|
},
|
|
})
|
|
const output = joinedOutput()
|
|
t.ok(output.includes('from package.json'), 'shows fromPackageJson indicator')
|
|
t.match(output, /https:\/\/github\.com\/npm\/cli\b/, 'shows URL')
|
|
})
|
|
|
|
t.test('TrustCommand - logOptions with no urls', async t => {
|
|
const { npm, joinedOutput } = await loadMockNpm(t, {
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
},
|
|
})
|
|
|
|
class TestTrustCmd extends TrustCommand {
|
|
static name = 'test'
|
|
static description = 'Test command'
|
|
}
|
|
|
|
const cmd = new TestTrustCmd(npm)
|
|
|
|
// Call logOptions without urls object
|
|
cmd.logOptions({
|
|
values: {
|
|
type: 'github',
|
|
id: 'test-id',
|
|
repository: 'npm/cli',
|
|
file: 'workflow.yml',
|
|
},
|
|
})
|
|
const output = joinedOutput()
|
|
t.ok(output.includes('repository'), 'shows repository field')
|
|
t.ok(output.includes('file'), 'shows file field')
|
|
t.notOk(output.includes('Links to verify manually'), 'does not show links header when no urls')
|
|
})
|
|
|
|
t.test('TrustCommand - logOptions with urls but all values are null', async t => {
|
|
const { npm, joinedOutput } = await loadMockNpm(t, {
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
},
|
|
})
|
|
|
|
class TestTrustCmd extends TrustCommand {
|
|
static name = 'test'
|
|
static description = 'Test command'
|
|
}
|
|
|
|
const cmd = new TestTrustCmd(npm)
|
|
|
|
// Call logOptions with urls object but all values are null/undefined
|
|
cmd.logOptions({
|
|
values: {
|
|
type: 'github',
|
|
id: 'test-id',
|
|
repository: 'npm/cli',
|
|
file: 'workflow.yml',
|
|
},
|
|
urls: {
|
|
repository: null,
|
|
file: undefined,
|
|
},
|
|
})
|
|
const output = joinedOutput()
|
|
t.ok(output.includes('repository'), 'shows repository field')
|
|
t.ok(output.includes('file'), 'shows file field')
|
|
t.notOk(output.includes('Links to verify manually'), 'does not show links header when all urls are null')
|
|
})
|
|
|
|
t.test('formatPermissions with unknown permission falls back to raw value', t => {
|
|
const result = TrustCommand.formatPermissions(['unknownPermission'])
|
|
t.equal(result, 'unknownPermission', 'returns raw value for unknown permission')
|
|
t.end()
|
|
})
|
|
|
|
t.test('displayResponseBody with empty body', async t => {
|
|
const { npm, joinedOutput } = await loadMockNpm(t, {
|
|
config: {
|
|
'//registry.npmjs.org/:_authToken': 'test-auth-token',
|
|
},
|
|
})
|
|
|
|
class TestTrustCmd extends TrustCommand {
|
|
static name = 'test'
|
|
static description = 'Test command'
|
|
}
|
|
|
|
const cmd = new TestTrustCmd(npm)
|
|
cmd.displayResponseBody({ body: [], packageName: '@npmcli/test-package' })
|
|
|
|
const output = joinedOutput()
|
|
t.match(output, /No trust configurations found/, 'shows no configurations message')
|
|
})
|