@@ -2,21 +2,60 @@ const t = require('tap')
22const { basename } = require ( 'node:path' )
33const tmock = require ( '../../fixtures/tmock' )
44const mockNpm = require ( '../../fixtures/mock-npm' )
5+ const MockRegistry = require ( '@npmcli/mock-registry' )
6+ const pacote = require ( 'pacote' )
7+ const mockGlobals = require ( '@npmcli/mock-globals' )
58
69const CURRENT_VERSION = '123.420.69'
710const CURRENT_MAJOR = '122.420.69'
811const CURRENT_MINOR = '123.419.69'
912const CURRENT_PATCH = '123.420.68'
1013const NEXT_VERSION = '123.421.70'
14+ const NEXT_VERSION_ENGINE_COMPATIBLE = '123.421.60'
15+ const NEXT_VERSION_ENGINE_COMPATIBLE_MINOR = `123.420.70`
16+ const NEXT_VERSION_ENGINE_COMPATIBLE_PATCH = `123.421.58`
1117const NEXT_MINOR = '123.420.70'
1218const NEXT_PATCH = '123.421.69'
1319const CURRENT_BETA = '124.0.0-beta.99999'
1420const HAVE_BETA = '124.0.0-beta.0'
1521
22+ const pacumentResponse = {
23+ _id : 'npm' ,
24+ name : 'npm' ,
25+ 'dist-tags' : {
26+ latest : CURRENT_VERSION ,
27+ } ,
28+ access : 'public' ,
29+ versions : {
30+ [ CURRENT_VERSION ] : { version : CURRENT_VERSION , engines : { node : '>1' } } ,
31+ [ CURRENT_MAJOR ] : { version : CURRENT_MAJOR , engines : { node : '>1' } } ,
32+ [ CURRENT_MINOR ] : { version : CURRENT_MINOR , engines : { node : '>1' } } ,
33+ [ CURRENT_PATCH ] : { version : CURRENT_PATCH , engines : { node : '>1' } } ,
34+ [ NEXT_VERSION ] : { version : NEXT_VERSION , engines : { node : '>1' } } ,
35+ [ NEXT_MINOR ] : { version : NEXT_MINOR , engines : { node : '>1' } } ,
36+ [ NEXT_PATCH ] : { version : NEXT_PATCH , engines : { node : '>1' } } ,
37+ [ CURRENT_BETA ] : { version : CURRENT_BETA , engines : { node : '>1' } } ,
38+ [ HAVE_BETA ] : { version : HAVE_BETA , engines : { node : '>1' } } ,
39+ [ NEXT_VERSION_ENGINE_COMPATIBLE ] : {
40+ version : NEXT_VERSION_ENGINE_COMPATIBLE ,
41+ engiges : { node : '<=1' } ,
42+ } ,
43+ [ NEXT_VERSION_ENGINE_COMPATIBLE_MINOR ] : {
44+ version : NEXT_VERSION_ENGINE_COMPATIBLE_MINOR ,
45+ engines : { node : '<=1' } ,
46+ } ,
47+ [ NEXT_VERSION_ENGINE_COMPATIBLE_PATCH ] : {
48+ version : NEXT_VERSION_ENGINE_COMPATIBLE_PATCH ,
49+ engines : { node : '<=1' } ,
50+ } ,
51+ } ,
52+ }
53+
1654const runUpdateNotifier = async ( t , {
1755 STAT_ERROR ,
1856 WRITE_ERROR ,
1957 PACOTE_ERROR ,
58+ PACOTE_MOCK_REQ_COUNT = 1 ,
2059 STAT_MTIME = 0 ,
2160 mocks : _mocks = { } ,
2261 command = 'help' ,
@@ -53,17 +92,15 @@ const runUpdateNotifier = async (t, {
5392
5493 const MANIFEST_REQUEST = [ ]
5594 const mockPacote = {
56- manifest : async ( spec ) => {
95+ manifest : async ( spec , ... opts ) => {
5796 if ( ! spec . match ( / ^ n p m @ / ) ) {
5897 t . fail ( 'no pacote manifest allowed for non npm packages' )
5998 }
6099 MANIFEST_REQUEST . push ( spec )
61100 if ( PACOTE_ERROR ) {
62101 throw PACOTE_ERROR
63102 }
64- const manifestV = spec === 'npm@*' ? CURRENT_VERSION
65- : / - / . test ( spec ) ? CURRENT_BETA : NEXT_VERSION
66- return { version : manifestV }
103+ return pacote . manifest ( spec , ...opts )
67104 } ,
68105 }
69106
@@ -83,6 +120,15 @@ const runUpdateNotifier = async (t, {
83120 prefixDir,
84121 argv,
85122 } )
123+ const registry = new MockRegistry ( {
124+ tap : t ,
125+ registry : mock . npm . config . get ( 'registry' ) ,
126+ } )
127+
128+ if ( PACOTE_MOCK_REQ_COUNT > 0 ) {
129+ registry . nock . get ( '/npm' ) . times ( PACOTE_MOCK_REQ_COUNT ) . reply ( 200 , pacumentResponse )
130+ }
131+
86132 const updateNotifier = tmock ( t , '{LIB}/cli/update-notifier.js' , mocks )
87133
88134 const result = await updateNotifier ( mock . npm )
@@ -104,6 +150,7 @@ t.test('duration has elapsed, no updates', async t => {
104150t . test ( 'situations in which we do not notify' , t => {
105151 t . test ( 'nothing to do if notifier disabled' , async t => {
106152 const { wroteFile, result, MANIFEST_REQUEST } = await runUpdateNotifier ( t , {
153+ PACOTE_MOCK_REQ_COUNT : 0 ,
107154 'update-notifier' : false ,
108155 } )
109156 t . equal ( wroteFile , false )
@@ -113,6 +160,7 @@ t.test('situations in which we do not notify', t => {
113160
114161 t . test ( 'do not suggest update if already updating' , async t => {
115162 const { wroteFile, result, MANIFEST_REQUEST } = await runUpdateNotifier ( t , {
163+ PACOTE_MOCK_REQ_COUNT : 0 ,
116164 command : 'install' ,
117165 prefixDir : { 'package.json' : `{"name":"${ t . testName } "}` } ,
118166 argv : [ 'npm' ] ,
@@ -125,9 +173,10 @@ t.test('situations in which we do not notify', t => {
125173
126174 t . test ( 'do not suggest update if already updating with spec' , async t => {
127175 const { wroteFile, result, MANIFEST_REQUEST } = await runUpdateNotifier ( t , {
176+ PACOTE_MOCK_REQ_COUNT : 0 ,
128177 command : 'install' ,
129178 prefixDir : { 'package.json' : `{"name":"${ t . testName } "}` } ,
130- argv : [ 'npm@* ' ] ,
179+ argv : [ 'npm@latest ' ] ,
131180 global : true ,
132181 } )
133182 t . equal ( wroteFile , false )
@@ -157,7 +206,9 @@ t.test('situations in which we do not notify', t => {
157206 } )
158207 t . test ( 'ignore pacote failures (here for coverage)' , async t => {
159208 const PACOTE_ERROR = new Error ( 'pah-KO-tchay' )
160- const { wroteFile, result, MANIFEST_REQUEST } = await runUpdateNotifier ( t , { PACOTE_ERROR } )
209+ const { wroteFile, result, MANIFEST_REQUEST } = await runUpdateNotifier ( t , {
210+ PACOTE_ERROR , PACOTE_MOCK_REQ_COUNT : 0 ,
211+ } )
161212 t . equal ( result , null )
162213 t . equal ( wroteFile , true )
163214 t . strictSame ( MANIFEST_REQUEST , [ 'npm@*' ] , 'requested latest version' )
@@ -188,7 +239,8 @@ t.test('situations in which we do not notify', t => {
188239 t . test ( 'do not update in CI' , async t => {
189240 const { wroteFile, result, MANIFEST_REQUEST } = await runUpdateNotifier ( t , { mocks : {
190241 'ci-info' : { isCI : true , name : 'something' } ,
191- } } )
242+ } ,
243+ PACOTE_MOCK_REQ_COUNT : 0 } )
192244 t . equal ( wroteFile , false )
193245 t . equal ( result , null )
194246 t . strictSame ( MANIFEST_REQUEST , [ ] , 'no requests for manifests' )
@@ -197,7 +249,10 @@ t.test('situations in which we do not notify', t => {
197249 t . test ( 'only check weekly for GA releases' , async t => {
198250 // One week (plus five minutes to account for test environment fuzziness)
199251 const STAT_MTIME = Date . now ( ) - 1000 * 60 * 60 * 24 * 7 + 1000 * 60 * 5
200- const { wroteFile, result, MANIFEST_REQUEST } = await runUpdateNotifier ( t , { STAT_MTIME } )
252+ const { wroteFile, result, MANIFEST_REQUEST } = await runUpdateNotifier ( t , {
253+ STAT_MTIME ,
254+ PACOTE_MOCK_REQ_COUNT : 0 ,
255+ } )
201256 t . equal ( wroteFile , false , 'duration was not reset' )
202257 t . equal ( result , null )
203258 t . strictSame ( MANIFEST_REQUEST , [ ] , 'no requests for manifests' )
@@ -210,7 +265,7 @@ t.test('situations in which we do not notify', t => {
210265 wroteFile,
211266 result,
212267 MANIFEST_REQUEST ,
213- } = await runUpdateNotifier ( t , { STAT_MTIME , version : HAVE_BETA } )
268+ } = await runUpdateNotifier ( t , { STAT_MTIME , version : HAVE_BETA , PACOTE_MOCK_REQ_COUNT : 0 } )
214269 t . equal ( wroteFile , false , 'duration was not reset' )
215270 t . equal ( result , null )
216271 t . strictSame ( MANIFEST_REQUEST , [ ] , 'no requests for manifests' )
@@ -236,11 +291,27 @@ t.test('notification situations', async t => {
236291 wroteFile,
237292 result,
238293 MANIFEST_REQUEST ,
239- } = await runUpdateNotifier ( t , { version, color } )
294+ } = await runUpdateNotifier ( t , { version, color, PACOTE_MOCK_REQ_COUNT : reqs . length } )
240295 t . matchSnapshot ( result )
241296 t . equal ( wroteFile , true )
242297 t . strictSame ( MANIFEST_REQUEST , reqs . map ( r => `npm@${ r . replace ( '{V}' , version ) } ` ) )
243298 } )
244299 }
245300 }
246301} )
302+
303+ t . test ( 'notification situation with engine compatibility' , async t => {
304+ mockGlobals ( t , { 'process.version' : 'v1.0.0' } , { replace : true } )
305+
306+ const {
307+ wroteFile,
308+ result,
309+ MANIFEST_REQUEST ,
310+ } = await runUpdateNotifier ( t , {
311+ version : NEXT_VERSION_ENGINE_COMPATIBLE_MINOR ,
312+ PACOTE_MOCK_REQ_COUNT : 1 } )
313+
314+ t . matchSnapshot ( result )
315+ t . equal ( wroteFile , true )
316+ t . strictSame ( MANIFEST_REQUEST , [ `npm@*` ] )
317+ } )
0 commit comments