1var fs = require('fs') 2var path = require('path') 3var rimraf = require('rimraf') 4var mr = require('npm-registry-mock') 5 6var test = require('tap').test 7var common = require('../common-tap.js') 8 9var opts = { cwd: common.pkg } 10var outfile = path.resolve(common.pkg, '_npmrc') 11var responses = { 12 'Username': 'u\n', 13 'Password': 'p\n', 14 'Email': 'u@p.me\n' 15} 16 17function verifyStdout (runner, successMessage, t) { 18 var remaining = Object.keys(responses).length 19 return function (chunk) { 20 if (remaining > 0) { 21 remaining-- 22 23 var label = chunk.toString('utf8').split(':')[0] 24 runner.stdin.write(responses[label]) 25 26 if (remaining === 0) runner.stdin.end() 27 } else { 28 var message = chunk.toString('utf8').trim() 29 t.equal(message, successMessage) 30 } 31 } 32} 33 34function mocks (server) { 35 server.filteringRequestBody(function (r) { 36 if (r.match(/"_id":"org\.couchdb\.user:u"/)) { 37 return 'auth' 38 } else { 39 return 'invalid' 40 } 41 }) 42 server.post('/-/v1/login', 'invalid').reply(404, 'not found') 43 server.put('/-/user/org.couchdb.user:u', 'auth') 44 .reply(201, { username: 'u', password: 'p', email: 'u@p.me' }) 45} 46 47test('npm login', function (t) { 48 mr({ port: common.port, plugin: mocks }, function (er, s) { 49 var runner = common.npm( 50 [ 51 'login', 52 '--registry', common.registry, 53 '--loglevel', 'silent', 54 '--userconfig', outfile 55 ], 56 opts, 57 function (err, code) { 58 t.notOk(code, 'exited OK') 59 t.notOk(err, 'no error output') 60 var config = fs.readFileSync(outfile, 'utf8') 61 t.like(config, /:always-auth=false/, 'always-auth is scoped and false (by default)') 62 s.close() 63 rimraf(outfile, function (err) { 64 t.ifError(err, 'removed config file OK') 65 t.end() 66 }) 67 }) 68 69 var message = 'Logged in as u on ' + common.registry + '/.' 70 runner.stdout.on('data', verifyStdout(runner, message, t)) 71 }) 72}) 73 74test('npm login --scope <scope> uses <scope>:registry as its URI', function (t) { 75 var port = common.port + 1 76 var uri = 'http://localhost:' + port + '/' 77 var scope = '@myco' 78 common.npm( 79 [ 80 'config', 81 '--userconfig', outfile, 82 'set', 83 scope + ':registry', 84 uri 85 ], 86 opts, 87 function (err, code) { 88 t.notOk(code, 'exited OK') 89 t.notOk(err, 'no error output') 90 91 mr({ port: port, plugin: mocks }, function (er, s) { 92 var runner = common.npm( 93 [ 94 'login', 95 '--loglevel', 'silent', 96 '--userconfig', outfile, 97 '--scope', scope 98 ], 99 opts, 100 function (err, code) { 101 t.equal(code, 0, 'exited OK') 102 t.notOk(err, 'no error output') 103 var config = fs.readFileSync(outfile, 'utf8') 104 t.like(config, new RegExp(scope + ':registry=' + uri), 'scope:registry is set') 105 s.close() 106 rimraf(outfile, function (err) { 107 t.ifError(err, 'removed config file OK') 108 t.end() 109 }) 110 }) 111 112 var message = 'Logged in as u to scope ' + scope + ' on ' + uri + '.' 113 runner.stdout.on('data', verifyStdout(runner, message, t)) 114 }) 115 }) 116}) 117 118test('npm login --scope <scope> makes sure <scope> is prefixed by an @', function (t) { 119 var port = common.port + 1 120 var uri = 'http://localhost:' + port + '/' 121 var scope = 'myco' 122 var prefixedScope = '@' + scope 123 common.npm( 124 [ 125 '--userconfig', outfile, 126 'config', 127 'set', 128 prefixedScope + ':registry', 129 uri 130 ], 131 opts, 132 function (err, code) { 133 t.notOk(code, 'exited OK') 134 t.notOk(err, 'no error output') 135 136 mr({ port: port, plugin: mocks }, function (er, s) { 137 var runner = common.npm( 138 [ 139 'login', 140 '--loglevel', 'silent', 141 '--userconfig', outfile, 142 '--scope', scope 143 ], 144 opts, 145 function (err, code) { 146 t.notOk(code, 'exited OK') 147 t.notOk(err, 'no error output') 148 var config = fs.readFileSync(outfile, 'utf8') 149 t.like(config, new RegExp(prefixedScope + ':registry=' + uri), 'scope:registry is set') 150 s.close() 151 rimraf(outfile, function (err) { 152 t.ifError(err, 'removed config file OK') 153 t.end() 154 }) 155 }) 156 157 var message = 'Logged in as u to scope ' + prefixedScope + ' on ' + uri + '.' 158 runner.stdout.on('data', verifyStdout(runner, message, t)) 159 }) 160 }) 161}) 162 163test('npm login --scope <scope> --registry <registry> uses <registry> as its URI', function (t) { 164 var scope = '@myco' 165 common.npm( 166 [ 167 '--userconfig', outfile, 168 'config', 169 'set', 170 scope + ':registry', 171 'invalidurl' 172 ], 173 opts, 174 function (err, code) { 175 t.notOk(code, 'exited OK') 176 t.notOk(err, 'no error output') 177 178 mr({ port: common.port, plugin: mocks }, function (er, s) { 179 var runner = common.npm( 180 [ 181 'login', 182 '--registry', common.registry, 183 '--loglevel', 'silent', 184 '--userconfig', outfile, 185 '--scope', scope 186 ], 187 opts, 188 function (err, code) { 189 t.notOk(code, 'exited OK') 190 t.notOk(err, 'no error output') 191 var config = fs.readFileSync(outfile, 'utf8') 192 t.like(config, new RegExp(scope + ':registry=' + common.registry), 'scope:registry is set') 193 s.close() 194 rimraf(outfile, function (err) { 195 t.ifError(err, 'removed config file OK') 196 t.end() 197 }) 198 }) 199 200 var message = 'Logged in as u to scope ' + scope + ' on ' + common.registry + '/.' 201 runner.stdout.on('data', verifyStdout(runner, message, t)) 202 }) 203 }) 204}) 205 206test('npm login --always-auth', function (t) { 207 mr({ port: common.port, plugin: mocks }, function (er, s) { 208 var runner = common.npm( 209 [ 210 'login', 211 '--registry', common.registry, 212 '--loglevel', 'silent', 213 '--userconfig', outfile, 214 '--always-auth' 215 ], 216 opts, 217 function (err, code) { 218 t.notOk(code, 'exited OK') 219 t.notOk(err, 'no error output') 220 var config = fs.readFileSync(outfile, 'utf8') 221 t.like(config, /:always-auth=true/, 'always-auth is scoped and true') 222 s.close() 223 rimraf(outfile, function (err) { 224 t.ifError(err, 'removed config file OK') 225 t.end() 226 }) 227 }) 228 229 var message = 'Logged in as u on ' + common.registry + '/.' 230 runner.stdout.on('data', verifyStdout(runner, message, t)) 231 }) 232}) 233 234test('npm login --no-always-auth', function (t) { 235 mr({ port: common.port, plugin: mocks }, function (er, s) { 236 var runner = common.npm( 237 [ 238 'login', 239 '--registry', common.registry, 240 '--loglevel', 'silent', 241 '--userconfig', outfile, 242 '--no-always-auth' 243 ], 244 opts, 245 function (err, code) { 246 t.notOk(code, 'exited OK') 247 t.notOk(err, 'no error output') 248 var config = fs.readFileSync(outfile, 'utf8') 249 t.like(config, /:always-auth=false/, 'always-auth is scoped and false') 250 s.close() 251 rimraf(outfile, function (err) { 252 t.ifError(err, 'removed config file OK') 253 t.end() 254 }) 255 }) 256 257 var message = 'Logged in as u on ' + common.registry + '/.' 258 runner.stdout.on('data', verifyStdout(runner, message, t)) 259 }) 260}) 261 262test('cleanup', function (t) { 263 rimraf.sync(outfile) 264 t.pass('cleaned up') 265 t.end() 266}) 267