1const t = require('tap') 2const fs = require('fs/promises') 3const npmFetch = require('npm-registry-fetch') 4const mockNpm = require('../../fixtures/mock-npm') 5const { join } = require('path') 6 7const mockLogout = async (t, { userRc = [], ...npmOpts } = {}) => { 8 let result = null 9 10 const mock = await mockNpm(t, { 11 command: 'logout', 12 mocks: { 13 // XXX: refactor to use mock registry 14 'npm-registry-fetch': Object.assign(async (url, opts) => { 15 result = { url, opts } 16 }, npmFetch), 17 }, 18 ...npmOpts, 19 homeDir: { 20 '.npmrc': userRc.join('\n'), 21 }, 22 }) 23 24 return { 25 ...mock, 26 result: () => result, 27 // get only the message portion of the verbose log from the command 28 logMsg: () => mock.logs.verbose.find(l => l[0] === 'logout')[1], 29 userRc: () => fs.readFile(join(mock.home, '.npmrc'), 'utf-8').then(r => r.trim()), 30 } 31} 32 33t.test('token logout', async t => { 34 const { logout, logMsg, result, userRc } = await mockLogout(t, { 35 userRc: [ 36 '//registry.npmjs.org/:_authToken=@foo/', 37 'other-config=true', 38 ], 39 }) 40 41 await logout.exec([]) 42 43 t.equal( 44 logMsg(), 45 'clearing token for https://registry.npmjs.org/', 46 'should log message with correct registry' 47 ) 48 49 t.match( 50 result(), 51 { 52 url: '/-/user/token/%40foo%2F', 53 opts: { 54 registry: 'https://registry.npmjs.org/', 55 scope: '', 56 '//registry.npmjs.org/:_authToken': '@foo/', 57 method: 'DELETE', 58 ignoreBody: true, 59 }, 60 }, 61 'should call npm-registry-fetch with expected values' 62 ) 63 64 t.equal(await userRc(), 'other-config=true') 65}) 66 67t.test('token scoped logout', async t => { 68 const { logout, logMsg, result, userRc } = await mockLogout(t, { 69 config: { scope: '@myscope' }, 70 userRc: [ 71 '//diff-registry.npmjs.com/:_authToken=@bar/', 72 '//registry.npmjs.org/:_authToken=@foo/', 73 '@myscope:registry=https://diff-registry.npmjs.com/', 74 ], 75 }) 76 77 await logout.exec([]) 78 79 t.equal( 80 logMsg(), 81 'clearing token for https://diff-registry.npmjs.com/', 82 'should log message with correct registry' 83 ) 84 85 t.match( 86 result(), 87 { 88 url: '/-/user/token/%40bar%2F', 89 opts: { 90 registry: 'https://registry.npmjs.org/', 91 '@myscope:registry': 'https://diff-registry.npmjs.com/', 92 scope: '@myscope', 93 '//registry.npmjs.org/:_authToken': '@foo/', // <- removed by npm-registry-fetch 94 '//diff-registry.npmjs.com/:_authToken': '@bar/', 95 method: 'DELETE', 96 ignoreBody: true, 97 }, 98 }, 99 'should call npm-registry-fetch with expected values' 100 ) 101 102 t.equal(await userRc(), '//registry.npmjs.org/:_authToken=@foo/') 103}) 104 105t.test('user/pass logout', async t => { 106 const { logout, logMsg, userRc } = await mockLogout(t, { 107 userRc: [ 108 '//registry.npmjs.org/:username=foo', 109 '//registry.npmjs.org/:_password=bar', 110 'other-config=true', 111 ], 112 }) 113 114 await logout.exec([]) 115 116 t.equal( 117 logMsg(), 118 'clearing user credentials for https://registry.npmjs.org/', 119 'should log message with correct registry' 120 ) 121 122 t.equal(await userRc(), 'other-config=true') 123}) 124 125t.test('missing credentials', async t => { 126 const { logout } = await mockLogout(t) 127 128 await t.rejects( 129 logout.exec([]), 130 { 131 code: 'ENEEDAUTH', 132 message: /not logged in to https:\/\/registry.npmjs.org\/, so can't log out!/, 133 }, 134 'should throw with expected error code' 135 ) 136}) 137 138t.test('ignore invalid scoped registry config', async t => { 139 const { logout, logMsg, result, userRc } = await mockLogout(t, { 140 config: { scope: '@myscope' }, 141 userRc: [ 142 '//registry.npmjs.org/:_authToken=@foo/', 143 'other-config=true', 144 ], 145 }) 146 147 await logout.exec([]) 148 149 t.equal( 150 logMsg(), 151 'clearing token for https://registry.npmjs.org/', 152 'should log message with correct registry' 153 ) 154 155 t.match( 156 result(), 157 { 158 url: '/-/user/token/%40foo%2F', 159 opts: { 160 '//registry.npmjs.org/:_authToken': '@foo/', 161 registry: 'https://registry.npmjs.org/', 162 method: 'DELETE', 163 ignoreBody: true, 164 }, 165 }, 166 'should call npm-registry-fetch with expected values' 167 ) 168 169 t.equal(await userRc(), 'other-config=true') 170}) 171