1const t = require('tap')
2const fs = require('fs/promises')
3const { load: loadMockNpm } = require('../../fixtures/mock-npm.js')
4const MockRegistry = require('@npmcli/mock-registry')
5const { join } = require('path')
6
7t.test('token logout - user config', async t => {
8  const { npm, home, logs } = await loadMockNpm(t, {
9    homeDir: {
10      '.npmrc': [
11        '//registry.npmjs.org/:_authToken=@foo/',
12        'other-config=true',
13      ].join('\n'),
14    },
15  })
16
17  const mockRegistry = new MockRegistry({ tap: t, registry: 'https://registry.npmjs.org/' })
18  mockRegistry.logout('@foo/')
19  await npm.exec('logout', [])
20  t.equal(
21    logs.verbose.find(l => l[0] === 'logout')[1],
22    'clearing token for https://registry.npmjs.org/',
23    'should log message with correct registry'
24  )
25  const userRc = await fs.readFile(join(home, '.npmrc'), 'utf-8')
26  t.equal(userRc.trim(), 'other-config=true')
27})
28
29t.test('token scoped logout - user config', async t => {
30  const { npm, home, logs } = await loadMockNpm(t, {
31    config: {
32      scope: '@myscope',
33    },
34    homeDir: {
35      '.npmrc': [
36        '//diff-registry.npmjs.com/:_authToken=@bar/',
37        '//registry.npmjs.org/:_authToken=@foo/',
38        '@myscope:registry=https://diff-registry.npmjs.com/',
39
40      ].join('\n'),
41    },
42  })
43
44  const mockRegistry = new MockRegistry({ tap: t, registry: 'https://diff-registry.npmjs.com/' })
45  mockRegistry.logout('@bar/')
46  await npm.exec('logout', [])
47  t.equal(
48    logs.verbose.find(l => l[0] === 'logout')[1],
49    'clearing token for https://diff-registry.npmjs.com/',
50    'should log message with correct registry'
51  )
52
53  const userRc = await fs.readFile(join(home, '.npmrc'), 'utf-8')
54  t.equal(userRc.trim(), '//registry.npmjs.org/:_authToken=@foo/')
55})
56
57t.test('user/pass logout - user config', async t => {
58  const { npm, home, logs } = await loadMockNpm(t, {
59    homeDir: {
60      '.npmrc': [
61        '//registry.npmjs.org/:username=foo',
62        '//registry.npmjs.org/:_password=bar',
63        'other-config=true',
64      ].join('\n'),
65    },
66  })
67
68  await npm.exec('logout', [])
69  t.equal(
70    logs.verbose.find(l => l[0] === 'logout')[1],
71    'clearing user credentials for https://registry.npmjs.org/',
72    'should log message with correct registry'
73  )
74
75  const userRc = await fs.readFile(join(home, '.npmrc'), 'utf-8')
76  t.equal(userRc.trim(), 'other-config=true')
77})
78
79t.test('missing credentials', async t => {
80  const { npm } = await loadMockNpm(t)
81
82  await t.rejects(
83    npm.exec('logout', []),
84    {
85      code: 'ENEEDAUTH',
86      message: /not logged in to https:\/\/registry.npmjs.org\/, so can't log out!/,
87    },
88    'should reject with expected error code'
89  )
90})
91
92t.test('ignore invalid scoped registry config', async t => {
93  const { npm, home, logs } = await loadMockNpm(t, {
94    config: { scope: '@myscope' },
95    homeDir: {
96      '.npmrc': [
97        '//registry.npmjs.org/:_authToken=@foo/',
98        'other-config=true',
99
100      ].join('\n'),
101    },
102  })
103
104  const mockRegistry = new MockRegistry({ tap: t, registry: 'https://registry.npmjs.org/' })
105  mockRegistry.logout('@foo/')
106  await npm.exec('logout', [])
107
108  t.equal(
109    logs.verbose.find(l => l[0] === 'logout')[1],
110    'clearing token for https://registry.npmjs.org/',
111    'should log message with correct registry'
112  )
113  const userRc = await fs.readFile(join(home, '.npmrc'), 'utf-8')
114  t.equal(userRc.trim(), 'other-config=true')
115})
116
117t.test('token logout - project config', async t => {
118  const { npm, home, logs, prefix } = await loadMockNpm(t, {
119    homeDir: {
120      '.npmrc': [
121        '//registry.npmjs.org/:_authToken=@foo/',
122        'other-config=true',
123      ].join('\n'),
124    },
125    prefixDir: {
126      '.npmrc': [
127        '//registry.npmjs.org/:_authToken=@bar/',
128        'other-config=true',
129      ].join('\n'),
130    },
131  })
132
133  const mockRegistry = new MockRegistry({ tap: t, registry: 'https://registry.npmjs.org/' })
134  mockRegistry.logout('@bar/')
135  await npm.exec('logout', [])
136
137  t.equal(
138    logs.verbose.find(l => l[0] === 'logout')[1],
139    'clearing token for https://registry.npmjs.org/',
140    'should log message with correct registry'
141  )
142  const userRc = await fs.readFile(join(home, '.npmrc'), 'utf-8')
143  t.equal(userRc.trim(), [
144    '//registry.npmjs.org/:_authToken=@foo/',
145    'other-config=true',
146  ].join('\n'), 'leaves user config alone')
147  t.equal(
148    logs.verbose.find(l => l[0] === 'logout')[1],
149    'clearing token for https://registry.npmjs.org/',
150    'should log message with correct registry'
151  )
152  const projectRc = await fs.readFile(join(prefix, '.npmrc'), 'utf-8')
153  t.equal(projectRc.trim(), 'other-config=true', 'removes project config')
154})
155