From 996a2f6b130d6678998a2f6a5ec97d75534d5f66 Mon Sep 17 00:00:00 2001 From: nlf Date: Tue, 15 Dec 2020 09:01:03 -0800 Subject: [PATCH] add tests for org command PR-URL: https://github.com/npm/cli/pull/2353 Credit: @nlf Close: #2353 Reviewed-by: @ruyadorno --- lib/org.js | 4 +- test/lib/org.js | 585 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 587 insertions(+), 2 deletions(-) create mode 100644 test/lib/org.js diff --git a/lib/org.js b/lib/org.js index d430131f83750..b7af3f3a3022a 100644 --- a/lib/org.js +++ b/lib/org.js @@ -73,9 +73,9 @@ function orgSet (org, user, role, opts) { memDeets.org.size, memDeets.user, memDeets.role, - ]) + ].join('\t')) } else if (!opts.silent && opts.loglevel !== 'silent') - output(`Added ${memDeets.user} as ${memDeets.role} to ${memDeets.org.name}. You now ${memDeets.org.size} member${memDeets.org.size === 1 ? '' : 's'} in this org.`) + output(`Added ${memDeets.user} as ${memDeets.role} to ${memDeets.org.name}. You now have ${memDeets.org.size} member${memDeets.org.size === 1 ? '' : 's'} in this org.`) return memDeets }) diff --git a/test/lib/org.js b/test/lib/org.js new file mode 100644 index 0000000000000..68e3c9f0d6c8b --- /dev/null +++ b/test/lib/org.js @@ -0,0 +1,585 @@ +const { test } = require('tap') +const requireInject = require('require-inject') +const ansiTrim = require('../../lib/utils/ansi-trim.js') + +const npm = { + flatOptions: { + json: false, + parseable: false, + silent: false, + loglevel: 'info', + }, +} + +const output = [] + +let orgSize = 1 +let orgSetArgs = null +let orgRmArgs = null +let orgLsArgs = null +let orgList = {} +const libnpmorg = { + set: async (org, user, role, opts) => { + orgSetArgs = { org, user, role, opts } + return { + org: { + name: org, + size: orgSize, + }, + user, + role, + } + }, + rm: async (org, user, opts) => { + orgRmArgs = { org, user, opts } + }, + ls: async (org, opts) => { + orgLsArgs = { org, opts } + return orgList + }, +} + +const org = requireInject('../../lib/org.js', { + '../../lib/npm.js': npm, + '../../lib/utils/otplease.js': async (opts, fn) => fn(opts), + '../../lib/utils/output.js': (msg) => { + output.push(msg) + }, + libnpmorg, +}) + +test('completion', async t => { + const completion = (argv) => new Promise((resolve, reject) => { + org.completion({ conf: { argv: { remain: argv } } }, (err, res) => { + if (err) + return reject(err) + return resolve(res) + }) + }) + + const assertions = [ + [['npm', 'org'], ['set', 'rm', 'ls']], + [['npm', 'org', 'ls'], []], + [['npm', 'org', 'add'], []], + [['npm', 'org', 'rm'], []], + [['npm', 'org', 'set'], []], + ] + + for (const [argv, expected] of assertions) + t.strictSame(await completion(argv), expected, `completion for: ${argv.join(', ')}`) + + t.rejects(completion(['npm', 'org', 'flurb']), /flurb not recognized/, 'errors for unknown subcommand') +}) + +test('npm org - invalid subcommand', t => { + return org(['foo'], (err) => { + t.match(err, /npm org set/, 'prints usage information') + t.end() + }) +}) + +test('npm org add', t => { + t.teardown(() => { + orgSetArgs = null + output.length = 0 + }) + + return org(['add', 'orgname', 'username'], (err) => { + if (err) + throw err + + t.strictSame(orgSetArgs, { + org: 'orgname', + user: 'username', + role: 'developer', + opts: npm.flatOptions, + }, 'received the correct arguments') + t.equal(output[0], 'Added username as developer to orgname. You now have 1 member in this org.', 'printed the correct output') + t.end() + }) +}) + +test('npm org add - no org', t => { + t.teardown(() => { + orgSetArgs = null + output.length = 0 + }) + + return org(['add', '', 'username'], (err) => { + t.match(err, /`orgname` is required/, 'returns the correct error') + t.end() + }) +}) + +test('npm org add - no user', t => { + t.teardown(() => { + orgSetArgs = null + output.length = 0 + }) + + return org(['add', 'orgname', ''], (err) => { + t.match(err, /`username` is required/, 'returns the correct error') + t.end() + }) +}) + +test('npm org add - invalid role', t => { + t.teardown(() => { + orgSetArgs = null + output.length = 0 + }) + + return org(['add', 'orgname', 'username', 'person'], (err) => { + t.match(err, /`role` must be one of/, 'returns the correct error') + t.end() + }) +}) + +test('npm org add - more users', t => { + orgSize = 5 + t.teardown(() => { + orgSize = 1 + orgSetArgs = null + output.length = 0 + }) + + return org(['add', 'orgname', 'username'], (err) => { + if (err) + throw err + + t.strictSame(orgSetArgs, { + org: 'orgname', + user: 'username', + role: 'developer', + opts: npm.flatOptions, + }, 'received the correct arguments') + t.equal(output[0], 'Added username as developer to orgname. You now have 5 members in this org.', 'printed the correct output') + t.end() + }) +}) + +test('npm org add - json output', t => { + npm.flatOptions.json = true + t.teardown(() => { + npm.flatOptions.json = false + orgSetArgs = null + output.length = 0 + }) + + return org(['add', 'orgname', 'username'], (err) => { + if (err) + throw err + + t.strictSame(orgSetArgs, { + org: 'orgname', + user: 'username', + role: 'developer', + opts: npm.flatOptions, + }, 'received the correct arguments') + t.strictSame(JSON.parse(output[0]), { + org: { + name: 'orgname', + size: 1, + }, + user: 'username', + role: 'developer', + }, 'printed the correct output') + t.end() + }) +}) + +test('npm org add - parseable output', t => { + npm.flatOptions.parseable = true + t.teardown(() => { + npm.flatOptions.parseable = false + orgSetArgs = null + output.length = 0 + }) + + return org(['add', 'orgname', 'username'], (err) => { + if (err) + throw err + + t.strictSame(orgSetArgs, { + org: 'orgname', + user: 'username', + role: 'developer', + opts: npm.flatOptions, + }, 'received the correct arguments') + t.strictSame(output.map(line => line.split(/\t/)), [ + ['org', 'orgsize', 'user', 'role'], + ['orgname', '1', 'username', 'developer'], + ], 'printed the correct output') + t.end() + }) +}) + +test('npm org add - silent output', t => { + npm.flatOptions.silent = true + t.teardown(() => { + npm.flatOptions.silent = false + orgSetArgs = null + output.length = 0 + }) + + return org(['add', 'orgname', 'username'], (err) => { + if (err) + throw err + + t.strictSame(orgSetArgs, { + org: 'orgname', + user: 'username', + role: 'developer', + opts: npm.flatOptions, + }, 'received the correct arguments') + t.strictSame(output, [], 'prints no output') + t.end() + }) +}) + +test('npm org rm', t => { + t.teardown(() => { + orgRmArgs = null + orgLsArgs = null + output.length = 0 + }) + + return org(['rm', 'orgname', 'username'], (err) => { + if (err) + throw err + + t.strictSame(orgRmArgs, { + org: 'orgname', + user: 'username', + opts: npm.flatOptions, + }, 'libnpmorg.rm received the correct args') + t.strictSame(orgLsArgs, { + org: 'orgname', + opts: npm.flatOptions, + }, 'libnpmorg.ls received the correct args') + t.equal(output[0], 'Successfully removed username from orgname. You now have 0 members in this org.', 'printed the correct output') + t.end() + }) +}) + +test('npm org rm - no org', t => { + t.teardown(() => { + orgRmArgs = null + orgLsArgs = null + output.length = 0 + }) + + return org(['rm', '', 'username'], (err) => { + t.match(err, /`orgname` is required/, 'threw the correct error') + t.end() + }) +}) + +test('npm org rm - no user', t => { + t.teardown(() => { + orgRmArgs = null + orgLsArgs = null + output.length = 0 + }) + + return org(['rm', 'orgname'], (err) => { + t.match(err, /`username` is required/, 'threw the correct error') + t.end() + }) +}) + +test('npm org rm - one user left', t => { + orgList = { + one: 'developer', + } + + t.teardown(() => { + orgList = {} + orgRmArgs = null + orgLsArgs = null + output.length = 0 + }) + + return org(['rm', 'orgname', 'username'], (err) => { + if (err) + throw err + + t.strictSame(orgRmArgs, { + org: 'orgname', + user: 'username', + opts: npm.flatOptions, + }, 'libnpmorg.rm received the correct args') + t.strictSame(orgLsArgs, { + org: 'orgname', + opts: npm.flatOptions, + }, 'libnpmorg.ls received the correct args') + t.equal(output[0], 'Successfully removed username from orgname. You now have 1 member in this org.', 'printed the correct output') + t.end() + }) +}) + +test('npm org rm - json output', t => { + npm.flatOptions.json = true + t.teardown(() => { + npm.flatOptions.json = false + orgRmArgs = null + orgLsArgs = null + output.length = 0 + }) + + return org(['rm', 'orgname', 'username'], (err) => { + if (err) + throw err + + t.strictSame(orgRmArgs, { + org: 'orgname', + user: 'username', + opts: npm.flatOptions, + }, 'libnpmorg.rm received the correct args') + t.strictSame(orgLsArgs, { + org: 'orgname', + opts: npm.flatOptions, + }, 'libnpmorg.ls received the correct args') + t.strictSame(JSON.parse(output[0]), { + user: 'username', + org: 'orgname', + userCount: 0, + deleted: true, + }, 'printed the correct output') + t.end() + }) +}) + +test('npm org rm - parseable output', t => { + npm.flatOptions.parseable = true + t.teardown(() => { + npm.flatOptions.parseable = false + orgRmArgs = null + orgLsArgs = null + output.length = 0 + }) + + return org(['rm', 'orgname', 'username'], (err) => { + if (err) + throw err + + t.strictSame(orgRmArgs, { + org: 'orgname', + user: 'username', + opts: npm.flatOptions, + }, 'libnpmorg.rm received the correct args') + t.strictSame(orgLsArgs, { + org: 'orgname', + opts: npm.flatOptions, + }, 'libnpmorg.ls received the correct args') + t.strictSame(output.map(line => line.split(/\t/)), [ + ['user', 'org', 'userCount', 'deleted'], + ['username', 'orgname', '0', 'true'], + ], 'printed the correct output') + t.end() + }) +}) + +test('npm org rm - silent output', t => { + npm.flatOptions.silent = true + t.teardown(() => { + npm.flatOptions.silent = false + orgRmArgs = null + orgLsArgs = null + output.length = 0 + }) + + return org(['rm', 'orgname', 'username'], (err) => { + if (err) + throw err + + t.strictSame(orgRmArgs, { + org: 'orgname', + user: 'username', + opts: npm.flatOptions, + }, 'libnpmorg.rm received the correct args') + t.strictSame(orgLsArgs, { + org: 'orgname', + opts: npm.flatOptions, + }, 'libnpmorg.ls received the correct args') + t.strictSame(output, [], 'printed no output') + t.end() + }) +}) + +test('npm org ls', t => { + orgList = { + one: 'developer', + two: 'admin', + three: 'owner', + } + t.teardown(() => { + orgList = {} + orgLsArgs = null + output.length = 0 + }) + + return org(['ls', 'orgname'], (err) => { + if (err) + throw err + + t.strictSame(orgLsArgs, { + org: 'orgname', + opts: npm.flatOptions, + }, 'receieved the correct args') + const out = ansiTrim(output[0]) + t.match(out, /one.*developer/, 'contains the developer member') + t.match(out, /two.*admin/, 'contains the admin member') + t.match(out, /three.*owner/, 'contains the owner member') + t.end() + }) +}) + +test('npm org ls - user filter', t => { + orgList = { + username: 'admin', + missing: 'admin', + } + t.teardown(() => { + orgList = {} + orgLsArgs = null + output.length = 0 + }) + + return org(['ls', 'orgname', 'username'], (err) => { + if (err) + throw err + + t.strictSame(orgLsArgs, { + org: 'orgname', + opts: npm.flatOptions, + }, 'receieved the correct args') + const out = ansiTrim(output[0]) + t.match(out, /username.*admin/, 'contains the filtered member') + t.notMatch(out, /missing.*admin/, 'does not contain other members') + t.end() + }) +}) + +test('npm org ls - user filter, missing user', t => { + orgList = { + missing: 'admin', + } + t.teardown(() => { + orgList = {} + orgLsArgs = null + output.length = 0 + }) + + return org(['ls', 'orgname', 'username'], (err) => { + if (err) + throw err + + t.strictSame(orgLsArgs, { + org: 'orgname', + opts: npm.flatOptions, + }, 'receieved the correct args') + const out = ansiTrim(output[0]) + t.notMatch(out, /username/, 'does not contain the requested member') + t.notMatch(out, /missing.*admin/, 'does not contain other members') + t.end() + }) +}) + +test('npm org ls - no org', t => { + t.teardown(() => { + orgLsArgs = null + output.length = 0 + }) + + return org(['ls'], (err) => { + t.match(err, /`orgname` is required/, 'throws the correct error') + t.end() + }) +}) + +test('npm org ls - json output', t => { + npm.flatOptions.json = true + orgList = { + one: 'developer', + two: 'admin', + three: 'owner', + } + t.teardown(() => { + npm.flatOptions.json = false + orgList = {} + orgLsArgs = null + output.length = 0 + }) + + return org(['ls', 'orgname'], (err) => { + if (err) + throw err + + t.strictSame(orgLsArgs, { + org: 'orgname', + opts: npm.flatOptions, + }, 'receieved the correct args') + t.strictSame(JSON.parse(output[0]), orgList, 'prints the correct output') + t.end() + }) +}) + +test('npm org ls - parseable output', t => { + npm.flatOptions.parseable = true + orgList = { + one: 'developer', + two: 'admin', + three: 'owner', + } + t.teardown(() => { + npm.flatOptions.parseable = false + orgList = {} + orgLsArgs = null + output.length = 0 + }) + + return org(['ls', 'orgname'], (err) => { + if (err) + throw err + + t.strictSame(orgLsArgs, { + org: 'orgname', + opts: npm.flatOptions, + }, 'receieved the correct args') + t.strictSame(output.map(line => line.split(/\t/)), [ + ['user', 'role'], + ['one', 'developer'], + ['two', 'admin'], + ['three', 'owner'], + ], 'printed the correct output') + t.end() + }) +}) + +test('npm org ls - silent output', t => { + npm.flatOptions.silent = true + orgList = { + one: 'developer', + two: 'admin', + three: 'owner', + } + t.teardown(() => { + npm.flatOptions.silent = false + orgList = {} + orgLsArgs = null + output.length = 0 + }) + + return org(['ls', 'orgname'], (err) => { + if (err) + throw err + + t.strictSame(orgLsArgs, { + org: 'orgname', + opts: npm.flatOptions, + }, 'receieved the correct args') + t.strictSame(output, [], 'printed no output') + t.end() + }) +})