1const t = require('tap') 2const fs = require('fs') 3const path = require('path') 4const ini = require('ini') 5 6const { load: loadMockNpm } = require('../../fixtures/mock-npm.js') 7const mockGlobals = require('@npmcli/mock-globals') 8const MockRegistry = require('@npmcli/mock-registry') 9const stream = require('stream') 10 11const mockAddUser = async (t, { stdin: stdinLines, registry: registryUrl, ...options } = {}) => { 12 let stdin 13 if (stdinLines) { 14 stdin = new stream.PassThrough() 15 for (const l of stdinLines) { 16 stdin.write(l + '\n') 17 } 18 mockGlobals(t, { 19 'process.stdin': stdin, 20 'process.stdout': new stream.PassThrough(), // to quiet readline 21 }, { replace: true }) 22 } 23 const mock = await loadMockNpm(t, { 24 ...options, 25 command: 'adduser', 26 }) 27 const registry = new MockRegistry({ 28 tap: t, 29 registry: registryUrl ?? mock.npm.config.get('registry'), 30 }) 31 return { 32 registry, 33 stdin, 34 rc: () => ini.parse(fs.readFileSync(path.join(mock.home, '.npmrc'), 'utf8')), 35 ...mock, 36 } 37} 38 39t.test('usage', async t => { 40 const { adduser } = await loadMockNpm(t, { command: 'adduser' }) 41 t.match(adduser.usage, 'adduser', 'usage has command name in it') 42}) 43 44t.test('legacy', async t => { 45 t.test('simple adduser', async t => { 46 const { npm, rc, registry, adduser } = await mockAddUser(t, { 47 stdin: ['test-user', 'test-password', 'test-email@npmjs.org'], 48 config: { 'auth-type': 'legacy' }, 49 homeDir: { 50 '.npmrc': [ 51 '//registry.npmjs.org/:_authToken=user', 52 '//registry.npmjs.org/:always-auth=user', 53 '//registry.npmjs.org/:email=test-email-old@npmjs.org', 54 ].join('\n'), 55 }, 56 }) 57 registry.couchadduser({ 58 username: 'test-user', 59 password: 'test-password', 60 email: 'test-email@npmjs.org', 61 token: 'npm_test-token', 62 }) 63 await adduser.exec([]) 64 t.same(npm.config.get('email'), 'test-email-old@npmjs.org') 65 t.same(npm.config.get('//registry.npmjs.org/:_authToken'), 'npm_test-token') 66 t.same(rc(), { 67 '//registry.npmjs.org/:_authToken': 'npm_test-token', 68 email: 'test-email-old@npmjs.org', 69 }, 'should only have token and un-nerfed old email') 70 }) 71 72 t.test('scoped adduser', async t => { 73 const { npm, rc, registry, adduser } = await mockAddUser(t, { 74 stdin: ['test-user', 'test-password', 'test-email@npmjs.org'], 75 config: { 76 'auth-type': 'legacy', 77 scope: '@myscope', 78 }, 79 }) 80 registry.couchadduser({ 81 username: 'test-user', 82 password: 'test-password', 83 email: 'test-email@npmjs.org', 84 token: 'npm_test-token', 85 }) 86 await adduser.exec([]) 87 t.same(npm.config.get('//registry.npmjs.org/:_authToken'), 'npm_test-token') 88 t.same(npm.config.get('@myscope:registry'), 'https://registry.npmjs.org/') 89 t.same(rc(), { 90 '//registry.npmjs.org/:_authToken': 'npm_test-token', 91 '@myscope:registry': 'https://registry.npmjs.org/', 92 }, 'should only have token and scope:registry') 93 }) 94 95 t.test('scoped adduser with valid scoped registry config', async t => { 96 const { npm, rc, registry, adduser } = await mockAddUser(t, { 97 stdin: ['test-user', 'test-password', 'test-email@npmjs.org'], 98 registry: 'https://diff-registry.npmjs.org', 99 homeDir: { 100 '.npmrc': '@myscope:registry=https://diff-registry.npmjs.org', 101 }, 102 config: { 103 'auth-type': 'legacy', 104 scope: '@myscope', 105 }, 106 }) 107 registry.couchadduser({ 108 username: 'test-user', 109 password: 'test-password', 110 email: 'test-email@npmjs.org', 111 token: 'npm_test-token', 112 }) 113 await adduser.exec([]) 114 t.same(npm.config.get('//diff-registry.npmjs.org/:_authToken'), 'npm_test-token') 115 t.same(npm.config.get('@myscope:registry'), 'https://diff-registry.npmjs.org') 116 t.same(rc(), { 117 '@myscope:registry': 'https://diff-registry.npmjs.org', 118 '//diff-registry.npmjs.org/:_authToken': 'npm_test-token', 119 }, 'should only have token and scope:registry') 120 }) 121 122 t.test('save config failure', async t => { 123 const { registry, adduser } = await mockAddUser(t, { 124 stdin: ['test-user', 'test-password', 'test-email@npmjs.org'], 125 config: { 'auth-type': 'legacy' }, 126 homeDir: { 127 '.npmrc': {}, 128 }, 129 }) 130 registry.couchadduser({ 131 username: 'test-user', 132 password: 'test-password', 133 email: 'test-email@npmjs.org', 134 token: 'npm_test-token', 135 }) 136 await t.rejects(adduser.exec([])) 137 }) 138 t.end() 139}) 140 141t.test('web', t => { 142 t.test('basic adduser', async t => { 143 const { npm, rc, registry, adduser } = await mockAddUser(t, { 144 config: { 'auth-type': 'web' }, 145 }) 146 registry.webadduser({ token: 'npm_test-token' }) 147 await adduser.exec([]) 148 t.same(npm.config.get('//registry.npmjs.org/:_authToken'), 'npm_test-token') 149 t.same(rc(), { 150 '//registry.npmjs.org/:_authToken': 'npm_test-token', 151 }) 152 }) 153 154 t.test('server error', async t => { 155 const { adduser, registry } = await mockAddUser(t, { 156 config: { 'auth-type': 'web' }, 157 }) 158 registry.nock.post(registry.fullPath('/-/v1/login')) 159 .reply(503, {}) 160 await t.rejects( 161 adduser.exec([]), 162 { message: /503/ } 163 ) 164 }) 165 166 t.test('fallback', async t => { 167 const { npm, registry, adduser } = await mockAddUser(t, { 168 stdin: ['test-user', 'test-password', 'test-email@npmjs.org'], 169 config: { 'auth-type': 'web' }, 170 }) 171 registry.nock.post(registry.fullPath('/-/v1/login')) 172 .reply(404, {}) 173 registry.couchadduser({ 174 username: 'test-user', 175 password: 'test-password', 176 email: 'test-email@npmjs.org', 177 token: 'npm_test-token', 178 }) 179 await adduser.exec([]) 180 t.same(npm.config.get('//registry.npmjs.org/:_authToken'), 'npm_test-token') 181 }) 182 t.end() 183}) 184