@@ -97,6 +97,122 @@ describe('util', () => {
9797 } ) ;
9898 } ) ;
9999
100+ describe ( 'supportsNativeDebugIds' , ( ) => {
101+ describe ( 'supported versions' , ( ) => {
102+ it . each ( [
103+ // Next.js 16+ stable versions
104+ [ '16.0.0' , 'Next.js 16.0.0 stable' ] ,
105+ [ '16.0.1' , 'Next.js 16.0.1 stable' ] ,
106+ [ '16.1.0' , 'Next.js 16.1.0 stable' ] ,
107+ [ '16.2.5' , 'Next.js 16.2.5 stable' ] ,
108+
109+ // Next.js 16+ pre-release versions
110+ [ '16.0.0-rc.1' , 'Next.js 16.0.0-rc.1' ] ,
111+ [ '16.0.0-canary.1' , 'Next.js 16.0.0-canary.1' ] ,
112+ [ '16.1.0-beta.2' , 'Next.js 16.1.0-beta.2' ] ,
113+
114+ // Next.js 17+
115+ [ '17.0.0' , 'Next.js 17.0.0' ] ,
116+ [ '18.0.0' , 'Next.js 18.0.0' ] ,
117+ [ '20.0.0' , 'Next.js 20.0.0' ] ,
118+
119+ // Next.js 15.6.0-canary.36+ (boundary case)
120+ [ '15.6.0-canary.36' , 'Next.js 15.6.0-canary.36 (exact threshold)' ] ,
121+ [ '15.6.0-canary.37' , 'Next.js 15.6.0-canary.37' ] ,
122+ [ '15.6.0-canary.38' , 'Next.js 15.6.0-canary.38' ] ,
123+ [ '15.6.0-canary.40' , 'Next.js 15.6.0-canary.40' ] ,
124+ [ '15.6.0-canary.100' , 'Next.js 15.6.0-canary.100' ] ,
125+
126+ // Next.js 15.7+ canary versions
127+ [ '15.7.0-canary.1' , 'Next.js 15.7.0-canary.1' ] ,
128+ [ '15.7.0-canary.50' , 'Next.js 15.7.0-canary.50' ] ,
129+ [ '15.8.0-canary.1' , 'Next.js 15.8.0-canary.1' ] ,
130+ [ '15.10.0-canary.1' , 'Next.js 15.10.0-canary.1' ] ,
131+ ] ) ( 'returns true for %s (%s)' , version => {
132+ expect ( util . supportsNativeDebugIds ( version ) ) . toBe ( true ) ;
133+ } ) ;
134+ } ) ;
135+
136+ describe ( 'unsupported versions' , ( ) => {
137+ it . each ( [
138+ // Next.js 15.6.0-canary.35 and below
139+ [ '15.6.0-canary.35' , 'Next.js 15.6.0-canary.35 (just below threshold)' ] ,
140+ [ '15.6.0-canary.34' , 'Next.js 15.6.0-canary.34' ] ,
141+ [ '15.6.0-canary.0' , 'Next.js 15.6.0-canary.0' ] ,
142+ [ '15.6.0-canary.1' , 'Next.js 15.6.0-canary.1' ] ,
143+
144+ // Next.js 15.6.x stable releases (NOT canary)
145+ [ '15.6.0' , 'Next.js 15.6.0 stable' ] ,
146+ [ '15.6.1' , 'Next.js 15.6.1 stable' ] ,
147+ [ '15.6.2' , 'Next.js 15.6.2 stable' ] ,
148+ [ '15.6.10' , 'Next.js 15.6.10 stable' ] ,
149+
150+ // Next.js 15.6.x rc releases (NOT canary)
151+ [ '15.6.0-rc.1' , 'Next.js 15.6.0-rc.1' ] ,
152+ [ '15.6.0-rc.2' , 'Next.js 15.6.0-rc.2' ] ,
153+
154+ // Next.js 15.7+ stable releases (NOT canary)
155+ [ '15.7.0' , 'Next.js 15.7.0 stable' ] ,
156+ [ '15.8.0' , 'Next.js 15.8.0 stable' ] ,
157+ [ '15.10.0' , 'Next.js 15.10.0 stable' ] ,
158+
159+ // Next.js 15.7+ rc/beta releases (NOT canary)
160+ [ '15.7.0-rc.1' , 'Next.js 15.7.0-rc.1' ] ,
161+ [ '15.7.0-beta.1' , 'Next.js 15.7.0-beta.1' ] ,
162+
163+ // Next.js 15.5 and below (all versions)
164+ [ '15.5.0' , 'Next.js 15.5.0' ] ,
165+ [ '15.5.0-canary.100' , 'Next.js 15.5.0-canary.100' ] ,
166+ [ '15.4.1' , 'Next.js 15.4.1' ] ,
167+ [ '15.0.0' , 'Next.js 15.0.0' ] ,
168+ [ '15.0.0-canary.1' , 'Next.js 15.0.0-canary.1' ] ,
169+
170+ // Next.js 14.x and below
171+ [ '14.2.0' , 'Next.js 14.2.0' ] ,
172+ [ '14.0.0' , 'Next.js 14.0.0' ] ,
173+ [ '14.0.0-canary.50' , 'Next.js 14.0.0-canary.50' ] ,
174+ [ '13.5.0' , 'Next.js 13.5.0' ] ,
175+ [ '13.0.0' , 'Next.js 13.0.0' ] ,
176+ [ '12.0.0' , 'Next.js 12.0.0' ] ,
177+ ] ) ( 'returns false for %s (%s)' , version => {
178+ expect ( util . supportsNativeDebugIds ( version ) ) . toBe ( false ) ;
179+ } ) ;
180+ } ) ;
181+
182+ describe ( 'edge cases' , ( ) => {
183+ it . each ( [
184+ [ '' , 'empty string' ] ,
185+ [ 'invalid' , 'invalid version string' ] ,
186+ [ '15' , 'missing minor and patch' ] ,
187+ [ '15.6' , 'missing patch' ] ,
188+ [ 'not.a.version' , 'completely invalid' ] ,
189+ [ '15.6.0-alpha.1' , 'alpha prerelease (not canary)' ] ,
190+ [ '15.6.0-beta.1' , 'beta prerelease (not canary)' ] ,
191+ ] ) ( 'returns false for %s (%s)' , version => {
192+ expect ( util . supportsNativeDebugIds ( version ) ) . toBe ( false ) ;
193+ } ) ;
194+ } ) ;
195+
196+ describe ( 'canary number parsing edge cases' , ( ) => {
197+ it . each ( [
198+ [ '15.6.0-canary.' , 'canary with no number' ] ,
199+ [ '15.6.0-canary.abc' , 'canary with non-numeric value' ] ,
200+ [ '15.6.0-canary.35.extra' , 'canary with extra segments' ] ,
201+ ] ) ( 'handles malformed canary versions: %s (%s)' , version => {
202+ // Should not throw, just return appropriate boolean
203+ expect ( ( ) => util . supportsNativeDebugIds ( version ) ) . not . toThrow ( ) ;
204+ } ) ;
205+
206+ it ( 'handles canary.36 exactly (boundary)' , ( ) => {
207+ expect ( util . supportsNativeDebugIds ( '15.6.0-canary.36' ) ) . toBe ( true ) ;
208+ } ) ;
209+
210+ it ( 'handles canary.35 exactly (boundary)' , ( ) => {
211+ expect ( util . supportsNativeDebugIds ( '15.6.0-canary.35' ) ) . toBe ( false ) ;
212+ } ) ;
213+ } ) ;
214+ } ) ;
215+
100216 describe ( 'isTurbopackDefaultForVersion' , ( ) => {
101217 describe ( 'returns true for versions where turbopack is default' , ( ) => {
102218 it . each ( [
0 commit comments