• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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