const { test } = require('tap') const requireInject = require('require-inject') const npm = { flatOptions: { json: false, parseable: false, silent: false, loglevel: 'info', unicode: false, }, } const pkgTypes = { semver: 'package', '@npmcli': 'scope', npm: 'owner', } const now = Date.now() let hookResponse = null let hookArgs = null const libnpmhook = { add: async (pkg, uri, secret, opts) => { hookArgs = { pkg, uri, secret, opts } return { id: 1, name: pkg.replace(/^@/, ''), type: pkgTypes[pkg], endpoint: uri } }, ls: async (opts) => { hookArgs = opts let id = 0 if (hookResponse) return hookResponse return Object.keys(pkgTypes).map((name) => ({ id: ++id, name: name.replace(/^@/, ''), type: pkgTypes[name], endpoint: 'https://google.com', last_delivery: id % 2 === 0 ? now : undefined, })) }, rm: async (id, opts) => { hookArgs = { id, opts } const pkg = Object.keys(pkgTypes)[0] return { id: 1, name: pkg.replace(/^@/, ''), type: pkgTypes[pkg], endpoint: 'https://google.com' } }, update: async (id, uri, secret, opts) => { hookArgs = { id, uri, secret, opts } const pkg = Object.keys(pkgTypes)[0] return { id, name: pkg.replace(/^@/, ''), type: pkgTypes[pkg], endpoint: uri } }, } const output = [] const Hook = requireInject('../../lib/hook.js', { '../../lib/utils/otplease.js': async (opts, fn) => fn(opts), '../../lib/utils/output.js': (msg) => { output.push(msg) }, libnpmhook, }) const hook = new Hook(npm) test('npm hook no args', t => { return hook.exec([], (err) => { t.match(err, /npm hook add/, 'throws usage with no arguments') t.end() }) }) test('npm hook add', t => { t.teardown(() => { hookArgs = null output.length = 0 }) return hook.exec(['add', 'semver', 'https://google.com', 'some-secret'], (err) => { if (err) throw err t.strictSame(hookArgs, { pkg: 'semver', uri: 'https://google.com', secret: 'some-secret', opts: npm.flatOptions, }, 'provided the correct arguments to libnpmhook') t.strictSame(output, ['+ semver -> https://google.com'], 'prints the correct output') t.end() }) }) test('npm hook add - unicode output', t => { npm.flatOptions.unicode = true t.teardown(() => { npm.flatOptions.unicode = false hookArgs = null output.length = 0 }) return hook.exec(['add', 'semver', 'https://google.com', 'some-secret'], (err) => { if (err) throw err t.strictSame(hookArgs, { pkg: 'semver', uri: 'https://google.com', secret: 'some-secret', opts: npm.flatOptions, }, 'provided the correct arguments to libnpmhook') t.strictSame(output, ['+ semver ➜ https://google.com'], 'prints the correct output') t.end() }) }) test('npm hook add - json output', t => { npm.flatOptions.json = true t.teardown(() => { npm.flatOptions.json = false hookArgs = null output.length = 0 }) return hook.exec(['add', '@npmcli', 'https://google.com', 'some-secret'], (err) => { if (err) throw err t.strictSame(hookArgs, { pkg: '@npmcli', uri: 'https://google.com', secret: 'some-secret', opts: npm.flatOptions, }, 'provided the correct arguments to libnpmhook') t.strictSame(JSON.parse(output[0]), { id: 1, name: 'npmcli', endpoint: 'https://google.com', type: 'scope', }, 'prints the correct json output') t.end() }) }) test('npm hook add - parseable output', t => { npm.flatOptions.parseable = true t.teardown(() => { npm.flatOptions.parseable = false hookArgs = null output.length = 0 }) return hook.exec(['add', '@npmcli', 'https://google.com', 'some-secret'], (err) => { if (err) throw err t.strictSame(hookArgs, { pkg: '@npmcli', uri: 'https://google.com', secret: 'some-secret', opts: npm.flatOptions, }, 'provided the correct arguments to libnpmhook') t.strictSame(output[0].split(/\t/), [ 'id', 'name', 'type', 'endpoint', ], 'prints the correct parseable output headers') t.strictSame(output[1].split(/\t/), [ '1', 'npmcli', 'scope', 'https://google.com', ], 'prints the correct parseable values') t.end() }) }) test('npm hook add - silent output', t => { npm.flatOptions.silent = true t.teardown(() => { npm.flatOptions.silent = false hookArgs = null output.length = 0 }) return hook.exec(['add', '@npmcli', 'https://google.com', 'some-secret'], (err) => { if (err) throw err t.strictSame(hookArgs, { pkg: '@npmcli', uri: 'https://google.com', secret: 'some-secret', opts: npm.flatOptions, }, 'provided the correct arguments to libnpmhook') t.strictSame(output, [], 'printed no output') t.end() }) }) test('npm hook ls', t => { t.teardown(() => { hookArgs = null output.length = 0 }) return hook.exec(['ls'], (err) => { if (err) throw err t.strictSame(hookArgs, { ...npm.flatOptions, package: undefined, }, 'received the correct arguments') t.equal(output[0], 'You have 3 hooks configured.', 'prints the correct header') const out = require('../../lib/utils/ansi-trim')(output[1]) t.match(out, /semver.*https:\/\/google.com.*\n.*\n.*never triggered/, 'prints package hook') t.match(out, /@npmcli.*https:\/\/google.com.*\n.*\n.*triggered just now/, 'prints scope hook') t.match(out, /~npm.*https:\/\/google.com.*\n.*\n.*never triggered/, 'prints owner hook') t.end() }) }) test('npm hook ls, no results', t => { hookResponse = [] t.teardown(() => { hookResponse = null hookArgs = null output.length = 0 }) return hook.exec(['ls'], (err) => { if (err) throw err t.strictSame(hookArgs, { ...npm.flatOptions, package: undefined, }, 'received the correct arguments') t.equal(output[0], 'You don\'t have any hooks configured yet.', 'prints the correct result') t.end() }) }) test('npm hook ls, single result', t => { hookResponse = [{ id: 1, name: 'semver', type: 'package', endpoint: 'https://google.com', }] t.teardown(() => { hookResponse = null hookArgs = null output.length = 0 }) return hook.exec(['ls'], (err) => { if (err) throw err t.strictSame(hookArgs, { ...npm.flatOptions, package: undefined, }, 'received the correct arguments') t.equal(output[0], 'You have one hook configured.', 'prints the correct header') const out = require('../../lib/utils/ansi-trim')(output[1]) t.match(out, /semver.*https:\/\/google.com.*\n.*\n.*never triggered/, 'prints package hook') t.end() }) }) test('npm hook ls - json output', t => { npm.flatOptions.json = true t.teardown(() => { npm.flatOptions.json = false hookArgs = null output.length = 0 }) return hook.exec(['ls'], (err) => { if (err) throw err t.strictSame(hookArgs, { ...npm.flatOptions, package: undefined, }, 'received the correct arguments') const out = JSON.parse(output[0]) t.match(out, [{ id: 1, name: 'semver', type: 'package', endpoint: 'https://google.com', }, { id: 2, name: 'npmcli', type: 'scope', endpoint: 'https://google.com', }, { id: 3, name: 'npm', type: 'owner', endpoint: 'https://google.com', }], 'prints the correct output') t.end() }) }) test('npm hook ls - parseable output', t => { npm.flatOptions.parseable = true t.teardown(() => { npm.flatOptions.parseable = false hookArgs = null output.length = 0 }) return hook.exec(['ls'], (err) => { if (err) throw err t.strictSame(hookArgs, { ...npm.flatOptions, package: undefined, }, 'received the correct arguments') t.strictSame(output.map(line => line.split(/\t/)), [ ['id', 'name', 'type', 'endpoint', 'last_delivery'], ['1', 'semver', 'package', 'https://google.com', ''], ['2', 'npmcli', 'scope', 'https://google.com', `${now}`], ['3', 'npm', 'owner', 'https://google.com', ''], ], 'prints the correct result') t.end() }) }) test('npm hook ls - silent output', t => { npm.flatOptions.silent = true t.teardown(() => { npm.flatOptions.silent = false hookArgs = null output.length = 0 }) return hook.exec(['ls'], (err) => { if (err) throw err t.strictSame(hookArgs, { ...npm.flatOptions, package: undefined, }, 'received the correct arguments') t.strictSame(output, [], 'printed no output') t.end() }) }) test('npm hook rm', t => { t.teardown(() => { hookArgs = null output.length = 0 }) return hook.exec(['rm', '1'], (err) => { if (err) throw err t.strictSame(hookArgs, { id: '1', opts: npm.flatOptions, }, 'received the correct arguments') t.strictSame(output, [ '- semver X https://google.com', ], 'printed the correct output') t.end() }) }) test('npm hook rm - unicode output', t => { npm.flatOptions.unicode = true t.teardown(() => { npm.flatOptions.unicode = false hookArgs = null output.length = 0 }) return hook.exec(['rm', '1'], (err) => { if (err) throw err t.strictSame(hookArgs, { id: '1', opts: npm.flatOptions, }, 'received the correct arguments') t.strictSame(output, [ '- semver ✘ https://google.com', ], 'printed the correct output') t.end() }) }) test('npm hook rm - silent output', t => { npm.flatOptions.silent = true t.teardown(() => { npm.flatOptions.silent = false hookArgs = null output.length = 0 }) return hook.exec(['rm', '1'], (err) => { if (err) throw err t.strictSame(hookArgs, { id: '1', opts: npm.flatOptions, }, 'received the correct arguments') t.strictSame(output, [], 'printed no output') t.end() }) }) test('npm hook rm - json output', t => { npm.flatOptions.json = true t.teardown(() => { npm.flatOptions.json = false hookArgs = null output.length = 0 }) return hook.exec(['rm', '1'], (err) => { if (err) throw err t.strictSame(hookArgs, { id: '1', opts: npm.flatOptions, }, 'received the correct arguments') t.strictSame(JSON.parse(output[0]), { id: 1, name: 'semver', type: 'package', endpoint: 'https://google.com', }, 'printed correct output') t.end() }) }) test('npm hook rm - parseable output', t => { npm.flatOptions.parseable = true t.teardown(() => { npm.flatOptions.parseable = false hookArgs = null output.length = 0 }) return hook.exec(['rm', '1'], (err) => { if (err) throw err t.strictSame(hookArgs, { id: '1', opts: npm.flatOptions, }, 'received the correct arguments') t.strictSame(output.map(line => line.split(/\t/)), [ ['id', 'name', 'type', 'endpoint'], ['1', 'semver', 'package', 'https://google.com'], ], 'printed correct output') t.end() }) }) test('npm hook update', t => { t.teardown(() => { hookArgs = null output.length = 0 }) return hook.exec(['update', '1', 'https://google.com', 'some-secret'], (err) => { if (err) throw err t.strictSame(hookArgs, { id: '1', uri: 'https://google.com', secret: 'some-secret', opts: npm.flatOptions, }, 'received the correct arguments') t.strictSame(output, [ '+ semver -> https://google.com', ], 'printed the correct output') t.end() }) }) test('npm hook update - unicode', t => { npm.flatOptions.unicode = true t.teardown(() => { npm.flatOptions.unicode = false hookArgs = null output.length = 0 }) return hook.exec(['update', '1', 'https://google.com', 'some-secret'], (err) => { if (err) throw err t.strictSame(hookArgs, { id: '1', uri: 'https://google.com', secret: 'some-secret', opts: npm.flatOptions, }, 'received the correct arguments') t.strictSame(output, [ '+ semver ➜ https://google.com', ], 'printed the correct output') t.end() }) }) test('npm hook update - json output', t => { npm.flatOptions.json = true t.teardown(() => { npm.flatOptions.json = false hookArgs = null output.length = 0 }) return hook.exec(['update', '1', 'https://google.com', 'some-secret'], (err) => { if (err) throw err t.strictSame(hookArgs, { id: '1', uri: 'https://google.com', secret: 'some-secret', opts: npm.flatOptions, }, 'received the correct arguments') t.strictSame(JSON.parse(output[0]), { id: '1', name: 'semver', type: 'package', endpoint: 'https://google.com', }, 'printed the correct output') t.end() }) }) test('npm hook update - parseable output', t => { npm.flatOptions.parseable = true t.teardown(() => { npm.flatOptions.parseable = false hookArgs = null output.length = 0 }) return hook.exec(['update', '1', 'https://google.com', 'some-secret'], (err) => { if (err) throw err t.strictSame(hookArgs, { id: '1', uri: 'https://google.com', secret: 'some-secret', opts: npm.flatOptions, }, 'received the correct arguments') t.strictSame(output.map(line => line.split(/\t/)), [ ['id', 'name', 'type', 'endpoint'], ['1', 'semver', 'package', 'https://google.com'], ], 'printed the correct output') t.end() }) }) test('npm hook update - silent output', t => { npm.flatOptions.silent = true t.teardown(() => { npm.flatOptions.silent = false hookArgs = null output.length = 0 }) return hook.exec(['update', '1', 'https://google.com', 'some-secret'], (err) => { if (err) throw err t.strictSame(hookArgs, { id: '1', uri: 'https://google.com', secret: 'some-secret', opts: npm.flatOptions, }, 'received the correct arguments') t.strictSame(output, [], 'printed no output') t.end() }) })