@@ -2,21 +2,59 @@ const t = require('tap')
2
2
const { basename } = require ( 'node:path' )
3
3
const tmock = require ( '../../fixtures/tmock' )
4
4
const mockNpm = require ( '../../fixtures/mock-npm' )
5
+ const MockRegistry = require ( '@npmcli/mock-registry' )
6
+ const mockGlobals = require ( '@npmcli/mock-globals' )
5
7
6
8
const CURRENT_VERSION = '123.420.69'
7
9
const CURRENT_MAJOR = '122.420.69'
8
10
const CURRENT_MINOR = '123.419.69'
9
11
const CURRENT_PATCH = '123.420.68'
10
12
const NEXT_VERSION = '123.421.70'
13
+ const NEXT_VERSION_ENGINE_COMPATIBLE = '123.421.60'
14
+ const NEXT_VERSION_ENGINE_COMPATIBLE_MINOR = `123.420.70`
15
+ const NEXT_VERSION_ENGINE_COMPATIBLE_PATCH = `123.421.58`
11
16
const NEXT_MINOR = '123.420.70'
12
17
const NEXT_PATCH = '123.421.69'
13
18
const CURRENT_BETA = '124.0.0-beta.99999'
14
19
const HAVE_BETA = '124.0.0-beta.0'
15
20
21
+ const packumentResponse = {
22
+ _id : 'npm' ,
23
+ name : 'npm' ,
24
+ 'dist-tags' : {
25
+ latest : CURRENT_VERSION ,
26
+ } ,
27
+ access : 'public' ,
28
+ versions : {
29
+ [ CURRENT_VERSION ] : { version : CURRENT_VERSION , engines : { node : '>1' } } ,
30
+ [ CURRENT_MAJOR ] : { version : CURRENT_MAJOR , engines : { node : '>1' } } ,
31
+ [ CURRENT_MINOR ] : { version : CURRENT_MINOR , engines : { node : '>1' } } ,
32
+ [ CURRENT_PATCH ] : { version : CURRENT_PATCH , engines : { node : '>1' } } ,
33
+ [ NEXT_VERSION ] : { version : NEXT_VERSION , engines : { node : '>1' } } ,
34
+ [ NEXT_MINOR ] : { version : NEXT_MINOR , engines : { node : '>1' } } ,
35
+ [ NEXT_PATCH ] : { version : NEXT_PATCH , engines : { node : '>1' } } ,
36
+ [ CURRENT_BETA ] : { version : CURRENT_BETA , engines : { node : '>1' } } ,
37
+ [ HAVE_BETA ] : { version : HAVE_BETA , engines : { node : '>1' } } ,
38
+ [ NEXT_VERSION_ENGINE_COMPATIBLE ] : {
39
+ version : NEXT_VERSION_ENGINE_COMPATIBLE ,
40
+ engiges : { node : '<=1' } ,
41
+ } ,
42
+ [ NEXT_VERSION_ENGINE_COMPATIBLE_MINOR ] : {
43
+ version : NEXT_VERSION_ENGINE_COMPATIBLE_MINOR ,
44
+ engines : { node : '<=1' } ,
45
+ } ,
46
+ [ NEXT_VERSION_ENGINE_COMPATIBLE_PATCH ] : {
47
+ version : NEXT_VERSION_ENGINE_COMPATIBLE_PATCH ,
48
+ engines : { node : '<=1' } ,
49
+ } ,
50
+ } ,
51
+ }
52
+
16
53
const runUpdateNotifier = async ( t , {
17
54
STAT_ERROR ,
18
55
WRITE_ERROR ,
19
56
PACOTE_ERROR ,
57
+ PACOTE_MOCK_REQ_COUNT = 1 ,
20
58
STAT_MTIME = 0 ,
21
59
mocks : _mocks = { } ,
22
60
command = 'help' ,
@@ -51,24 +89,7 @@ const runUpdateNotifier = async (t, {
51
89
} ,
52
90
}
53
91
54
- const MANIFEST_REQUEST = [ ]
55
- const mockPacote = {
56
- manifest : async ( spec ) => {
57
- if ( ! spec . match ( / ^ n p m @ / ) ) {
58
- t . fail ( 'no pacote manifest allowed for non npm packages' )
59
- }
60
- MANIFEST_REQUEST . push ( spec )
61
- if ( PACOTE_ERROR ) {
62
- throw PACOTE_ERROR
63
- }
64
- const manifestV = spec === 'npm@latest' ? CURRENT_VERSION
65
- : / - / . test ( spec ) ? CURRENT_BETA : NEXT_VERSION
66
- return { version : manifestV }
67
- } ,
68
- }
69
-
70
92
const mocks = {
71
- pacote : mockPacote ,
72
93
'node:fs/promises' : mockFs ,
73
94
'{ROOT}/package.json' : { version } ,
74
95
'ci-info' : { isCI : false , name : null } ,
@@ -83,124 +104,125 @@ const runUpdateNotifier = async (t, {
83
104
prefixDir,
84
105
argv,
85
106
} )
107
+ const registry = new MockRegistry ( {
108
+ tap : t ,
109
+ registry : mock . npm . config . get ( 'registry' ) ,
110
+ } )
111
+
112
+ if ( PACOTE_MOCK_REQ_COUNT > 0 ) {
113
+ registry . nock . get ( '/npm' ) . times ( PACOTE_MOCK_REQ_COUNT ) . reply ( 200 , packumentResponse )
114
+ }
115
+
86
116
const updateNotifier = tmock ( t , '{LIB}/cli/update-notifier.js' , mocks )
87
117
88
118
const result = await updateNotifier ( mock . npm )
89
119
90
120
return {
91
121
wroteFile,
92
122
result,
93
- MANIFEST_REQUEST ,
94
123
}
95
124
}
96
125
97
126
t . test ( 'duration has elapsed, no updates' , async t => {
98
- const { wroteFile, result, MANIFEST_REQUEST } = await runUpdateNotifier ( t )
127
+ const { wroteFile, result } = await runUpdateNotifier ( t )
99
128
t . equal ( wroteFile , true )
100
129
t . not ( result )
101
- t . equal ( MANIFEST_REQUEST . length , 1 )
102
130
} )
103
131
104
132
t . test ( 'situations in which we do not notify' , t => {
105
133
t . test ( 'nothing to do if notifier disabled' , async t => {
106
- const { wroteFile, result, MANIFEST_REQUEST } = await runUpdateNotifier ( t , {
134
+ const { wroteFile, result } = await runUpdateNotifier ( t , {
135
+ PACOTE_MOCK_REQ_COUNT : 0 ,
107
136
'update-notifier' : false ,
108
137
} )
109
138
t . equal ( wroteFile , false )
110
139
t . equal ( result , null )
111
- t . strictSame ( MANIFEST_REQUEST , [ ] , 'no requests for manifests' )
112
140
} )
113
141
114
142
t . test ( 'do not suggest update if already updating' , async t => {
115
- const { wroteFile, result, MANIFEST_REQUEST } = await runUpdateNotifier ( t , {
143
+ const { wroteFile, result } = await runUpdateNotifier ( t , {
144
+ PACOTE_MOCK_REQ_COUNT : 0 ,
116
145
command : 'install' ,
117
146
prefixDir : { 'package.json' : `{"name":"${ t . testName } "}` } ,
118
147
argv : [ 'npm' ] ,
119
148
global : true ,
120
149
} )
121
150
t . equal ( wroteFile , false )
122
151
t . equal ( result , null )
123
- t . strictSame ( MANIFEST_REQUEST , [ ] , 'no requests for manifests' )
124
152
} )
125
153
126
154
t . test ( 'do not suggest update if already updating with spec' , async t => {
127
- const { wroteFile, result, MANIFEST_REQUEST } = await runUpdateNotifier ( t , {
155
+ const { wroteFile, result } = await runUpdateNotifier ( t , {
156
+ PACOTE_MOCK_REQ_COUNT : 0 ,
128
157
command : 'install' ,
129
158
prefixDir : { 'package.json' : `{"name":"${ t . testName } "}` } ,
130
159
argv : [ 'npm@latest' ] ,
131
160
global : true ,
132
161
} )
133
162
t . equal ( wroteFile , false )
134
163
t . equal ( result , null )
135
- t . strictSame ( MANIFEST_REQUEST , [ ] , 'no requests for manifests' )
136
164
} )
137
165
138
166
t . test ( 'do not update if same as latest' , async t => {
139
- const { wroteFile, result, MANIFEST_REQUEST } = await runUpdateNotifier ( t )
167
+ const { wroteFile, result } = await runUpdateNotifier ( t )
140
168
t . equal ( wroteFile , true )
141
169
t . equal ( result , null )
142
- t . strictSame ( MANIFEST_REQUEST , [ 'npm@latest' ] , 'requested latest version' )
143
170
} )
144
171
t . test ( 'check if stat errors (here for coverage)' , async t => {
145
172
const STAT_ERROR = new Error ( 'blorg' )
146
- const { wroteFile, result, MANIFEST_REQUEST } = await runUpdateNotifier ( t , { STAT_ERROR } )
173
+ const { wroteFile, result } = await runUpdateNotifier ( t , { STAT_ERROR } )
147
174
t . equal ( wroteFile , true )
148
175
t . equal ( result , null )
149
- t . strictSame ( MANIFEST_REQUEST , [ 'npm@latest' ] , 'requested latest version' )
150
176
} )
151
177
t . test ( 'ok if write errors (here for coverage)' , async t => {
152
178
const WRITE_ERROR = new Error ( 'grolb' )
153
- const { wroteFile, result, MANIFEST_REQUEST } = await runUpdateNotifier ( t , { WRITE_ERROR } )
179
+ const { wroteFile, result } = await runUpdateNotifier ( t , { WRITE_ERROR } )
154
180
t . equal ( wroteFile , true )
155
181
t . equal ( result , null )
156
- t . strictSame ( MANIFEST_REQUEST , [ 'npm@latest' ] , 'requested latest version' )
157
182
} )
158
183
t . test ( 'ignore pacote failures (here for coverage)' , async t => {
159
184
const PACOTE_ERROR = new Error ( 'pah-KO-tchay' )
160
- const { wroteFile, result, MANIFEST_REQUEST } = await runUpdateNotifier ( t , { PACOTE_ERROR } )
185
+ const { wroteFile, result } = await runUpdateNotifier ( t , {
186
+ PACOTE_ERROR , PACOTE_MOCK_REQ_COUNT : 0 ,
187
+ } )
161
188
t . equal ( result , null )
162
189
t . equal ( wroteFile , true )
163
- t . strictSame ( MANIFEST_REQUEST , [ 'npm@latest' ] , 'requested latest version' )
164
190
} )
165
191
t . test ( 'do not update if newer than latest, but same as next' , async t => {
166
192
const {
167
193
wroteFile,
168
194
result,
169
- MANIFEST_REQUEST ,
170
195
} = await runUpdateNotifier ( t , { version : NEXT_VERSION } )
171
196
t . equal ( result , null )
172
197
t . equal ( wroteFile , true )
173
- const reqs = [ 'npm@latest' , `npm@^${ NEXT_VERSION } ` ]
174
- t . strictSame ( MANIFEST_REQUEST , reqs , 'requested latest and next versions' )
175
198
} )
176
199
t . test ( 'do not update if on the latest beta' , async t => {
177
200
const {
178
201
wroteFile,
179
202
result,
180
- MANIFEST_REQUEST ,
181
203
} = await runUpdateNotifier ( t , { version : CURRENT_BETA } )
182
204
t . equal ( result , null )
183
205
t . equal ( wroteFile , true )
184
- const reqs = [ `npm@^${ CURRENT_BETA } ` ]
185
- t . strictSame ( MANIFEST_REQUEST , reqs , 'requested latest and next versions' )
186
206
} )
187
207
188
208
t . test ( 'do not update in CI' , async t => {
189
- const { wroteFile, result, MANIFEST_REQUEST } = await runUpdateNotifier ( t , { mocks : {
209
+ const { wroteFile, result } = await runUpdateNotifier ( t , { mocks : {
190
210
'ci-info' : { isCI : true , name : 'something' } ,
191
- } } )
211
+ } ,
212
+ PACOTE_MOCK_REQ_COUNT : 0 } )
192
213
t . equal ( wroteFile , false )
193
214
t . equal ( result , null )
194
- t . strictSame ( MANIFEST_REQUEST , [ ] , 'no requests for manifests' )
195
215
} )
196
216
197
217
t . test ( 'only check weekly for GA releases' , async t => {
198
218
// One week (plus five minutes to account for test environment fuzziness)
199
219
const STAT_MTIME = Date . now ( ) - 1000 * 60 * 60 * 24 * 7 + 1000 * 60 * 5
200
- const { wroteFile, result, MANIFEST_REQUEST } = await runUpdateNotifier ( t , { STAT_MTIME } )
220
+ const { wroteFile, result } = await runUpdateNotifier ( t , {
221
+ STAT_MTIME ,
222
+ PACOTE_MOCK_REQ_COUNT : 0 ,
223
+ } )
201
224
t . equal ( wroteFile , false , 'duration was not reset' )
202
225
t . equal ( result , null )
203
- t . strictSame ( MANIFEST_REQUEST , [ ] , 'no requests for manifests' )
204
226
} )
205
227
206
228
t . test ( 'only check daily for betas' , async t => {
@@ -209,37 +231,48 @@ t.test('situations in which we do not notify', t => {
209
231
const {
210
232
wroteFile,
211
233
result,
212
- MANIFEST_REQUEST ,
213
- } = await runUpdateNotifier ( t , { STAT_MTIME , version : HAVE_BETA } )
234
+ } = await runUpdateNotifier ( t , { STAT_MTIME , version : HAVE_BETA , PACOTE_MOCK_REQ_COUNT : 0 } )
214
235
t . equal ( wroteFile , false , 'duration was not reset' )
215
236
t . equal ( result , null )
216
- t . strictSame ( MANIFEST_REQUEST , [ ] , 'no requests for manifests' )
217
237
} )
218
238
219
239
t . end ( )
220
240
} )
221
241
242
+ t . test ( 'notification situation with engine compatibility' , async t => {
243
+ // no version which are greater than node 1.0.0 should be selected.
244
+ mockGlobals ( t , { 'process.version' : 'v1.0.0' } , { replace : true } )
245
+
246
+ const {
247
+ wroteFile,
248
+ result,
249
+ } = await runUpdateNotifier ( t , {
250
+ version : NEXT_VERSION_ENGINE_COMPATIBLE_MINOR ,
251
+ PACOTE_MOCK_REQ_COUNT : 1 } )
252
+
253
+ t . matchSnapshot ( result )
254
+ t . equal ( wroteFile , true )
255
+ } )
256
+
222
257
t . test ( 'notification situations' , async t => {
223
258
const cases = {
224
- [ HAVE_BETA ] : [ `^{V}` ] ,
225
- [ NEXT_PATCH ] : [ `latest` , `^{V}` ] ,
226
- [ NEXT_MINOR ] : [ `latest` , `^{V}` ] ,
227
- [ CURRENT_PATCH ] : [ 'latest' ] ,
228
- [ CURRENT_MINOR ] : [ 'latest' ] ,
229
- [ CURRENT_MAJOR ] : [ 'latest' ] ,
259
+ [ HAVE_BETA ] : 1 ,
260
+ [ NEXT_PATCH ] : 2 ,
261
+ [ NEXT_MINOR ] : 2 ,
262
+ [ CURRENT_PATCH ] : 1 ,
263
+ [ CURRENT_MINOR ] : 1 ,
264
+ [ CURRENT_MAJOR ] : 1 ,
230
265
}
231
266
232
- for ( const [ version , reqs ] of Object . entries ( cases ) ) {
267
+ for ( const [ version , requestCount ] of Object . entries ( cases ) ) {
233
268
for ( const color of [ false , 'always' ] ) {
234
269
await t . test ( `${ version } - color=${ color } ` , async t => {
235
270
const {
236
271
wroteFile,
237
272
result,
238
- MANIFEST_REQUEST ,
239
- } = await runUpdateNotifier ( t , { version, color } )
273
+ } = await runUpdateNotifier ( t , { version, color, PACOTE_MOCK_REQ_COUNT : requestCount } )
240
274
t . matchSnapshot ( result )
241
275
t . equal ( wroteFile , true )
242
- t . strictSame ( MANIFEST_REQUEST , reqs . map ( r => `npm@${ r . replace ( '{V}' , version ) } ` ) )
243
276
} )
244
277
}
245
278
}
0 commit comments