@@ -199,6 +199,73 @@ describe('WebpackCodeInspectorPlugin', () => {
199199 expect ( codeInspectorRule . use [ 0 ] . options . vueLoader ) . toBe ( 'internal' ) ;
200200 } ) ;
201201
202+ it ( 'should register Vue template loader node transform when internal mode is enabled' , async ( ) => {
203+ vi . mocked ( isDev ) . mockReturnValueOnce ( true ) ;
204+ const templateLoaderOptions = { } ;
205+ mockCompiler . options . module . rules . push ( {
206+ test : / \. h t m l $ / ,
207+ use : [
208+ {
209+ loader : '/test/node_modules/vue-loader/dist/templateLoader.js' ,
210+ options : templateLoaderOptions ,
211+ } ,
212+ ] ,
213+ } ) ;
214+
215+ const plugin = new WebpackCodeInspectorPlugin ( {
216+ bundler : 'webpack' ,
217+ output : '/test' ,
218+ vueLoader : 'internal' ,
219+ } ) ;
220+
221+ await plugin . apply ( mockCompiler ) ;
222+
223+ expect ( templateLoaderOptions . compilerOptions . nodeTransforms ) . toHaveLength (
224+ 1 ,
225+ ) ;
226+ } ) ;
227+
228+ it ( 'should skip string-only vue loader entries' , async ( ) => {
229+ vi . mocked ( isDev ) . mockReturnValueOnce ( true ) ;
230+ mockCompiler . options . module . rules . push ( {
231+ test : / \. v u e $ / ,
232+ use : [ 'vue-loader' ] ,
233+ } ) ;
234+
235+ const plugin = new WebpackCodeInspectorPlugin ( {
236+ bundler : 'webpack' ,
237+ output : '/test' ,
238+ vueLoader : 'internal' ,
239+ } ) ;
240+
241+ await plugin . apply ( mockCompiler ) ;
242+
243+ expect ( createVueInspectorNodeTransform ) . not . toHaveBeenCalled ( ) ;
244+ } ) ;
245+
246+ it ( 'should skip non-vue loaders when internal mode is enabled' , async ( ) => {
247+ vi . mocked ( isDev ) . mockReturnValueOnce ( true ) ;
248+ mockCompiler . options . module . rules . push ( {
249+ test : / \. v u e $ / ,
250+ use : [
251+ {
252+ loader : '/test/node_modules/not-vue-loader/dist/index.js' ,
253+ options : { } ,
254+ } ,
255+ ] ,
256+ } ) ;
257+
258+ const plugin = new WebpackCodeInspectorPlugin ( {
259+ bundler : 'webpack' ,
260+ output : '/test' ,
261+ vueLoader : 'internal' ,
262+ } ) ;
263+
264+ await plugin . apply ( mockCompiler ) ;
265+
266+ expect ( createVueInspectorNodeTransform ) . not . toHaveBeenCalled ( ) ;
267+ } ) ;
268+
202269 it ( 'should keep vueLoader defaulting to custom' , async ( ) => {
203270 vi . mocked ( isDev ) . mockReturnValueOnce ( true ) ;
204271 const plugin = new WebpackCodeInspectorPlugin ( {
@@ -216,6 +283,108 @@ describe('WebpackCodeInspectorPlugin', () => {
216283 ) ;
217284 expect ( codeInspectorRule . use [ 0 ] . options . vueLoader ) . toBeUndefined ( ) ;
218285 } ) ;
286+
287+ it ( 'should skip string vue-loader entries while traversing nested rules' , async ( ) => {
288+ vi . mocked ( isDev ) . mockReturnValueOnce ( true ) ;
289+ const vueLoaderOptions = { compilerOptions : { nodeTransforms : [ ] } } ;
290+ mockCompiler . options . module . rules . push ( {
291+ oneOf : [
292+ {
293+ rules : [
294+ {
295+ use : [
296+ 'vue-loader' ,
297+ {
298+ loader : '/test/node_modules/vue-loader/dist/index.js' ,
299+ options : vueLoaderOptions ,
300+ } ,
301+ ] ,
302+ } ,
303+ ] ,
304+ } ,
305+ ] ,
306+ } ) ;
307+
308+ const plugin = new WebpackCodeInspectorPlugin ( {
309+ bundler : 'webpack' ,
310+ output : '/test' ,
311+ vueLoader : 'internal' ,
312+ } ) ;
313+
314+ await plugin . apply ( mockCompiler ) ;
315+
316+ expect ( vueLoaderOptions . compilerOptions . nodeTransforms ) . toHaveLength ( 1 ) ;
317+ } ) ;
318+
319+ it ( 'should create compilerOptions when vue-loader options are missing' , async ( ) => {
320+ vi . mocked ( isDev ) . mockReturnValueOnce ( true ) ;
321+ const useItem : any = {
322+ loader : '/test/node_modules/vue-loader/dist/index.js' ,
323+ } ;
324+ mockCompiler . options . module . rules . push ( {
325+ loader : '/test/node_modules/vue-loader/dist/index.js' ,
326+ use : [ useItem ] ,
327+ } ) ;
328+
329+ const plugin = new WebpackCodeInspectorPlugin ( {
330+ bundler : 'webpack' ,
331+ output : '/test' ,
332+ vueLoader : 'internal' ,
333+ } ) ;
334+
335+ await plugin . apply ( mockCompiler ) ;
336+
337+ expect ( useItem . options . compilerOptions . nodeTransforms ) . toHaveLength ( 1 ) ;
338+ } ) ;
339+
340+ it ( 'should initialize nodeTransforms when compilerOptions is empty' , async ( ) => {
341+ vi . mocked ( isDev ) . mockReturnValueOnce ( true ) ;
342+ const vueLoaderOptions = { compilerOptions : { } } ;
343+ mockCompiler . options . module . rules . push ( {
344+ test : / \. v u e $ / ,
345+ use : [
346+ {
347+ loader : '/test/node_modules/vue-loader/dist/index.js' ,
348+ options : vueLoaderOptions ,
349+ } ,
350+ ] ,
351+ } ) ;
352+
353+ const plugin = new WebpackCodeInspectorPlugin ( {
354+ bundler : 'webpack' ,
355+ output : '/test' ,
356+ vueLoader : 'internal' ,
357+ } ) ;
358+
359+ await plugin . apply ( mockCompiler ) ;
360+
361+ expect ( Array . isArray ( vueLoaderOptions . compilerOptions . nodeTransforms ) ) . toBe (
362+ true ,
363+ ) ;
364+ expect ( vueLoaderOptions . compilerOptions . nodeTransforms ) . toHaveLength ( 1 ) ;
365+ } ) ;
366+
367+ it ( 'should handle rule.loader shorthand and ignore falsy rules' , async ( ) => {
368+ vi . mocked ( isDev ) . mockReturnValueOnce ( true ) ;
369+ const vueLoaderOptions = { compilerOptions : { nodeTransforms : [ ] } } ;
370+ mockCompiler . options . module . rules . push (
371+ null ,
372+ {
373+ loader : '/test/node_modules/vue-loader/dist/index.js' ,
374+ options : vueLoaderOptions ,
375+ } ,
376+ ) ;
377+
378+ const plugin = new WebpackCodeInspectorPlugin ( {
379+ bundler : 'webpack' ,
380+ output : '/test' ,
381+ vueLoader : 'internal' ,
382+ } ) ;
383+
384+ await plugin . apply ( mockCompiler ) ;
385+
386+ expect ( vueLoaderOptions . compilerOptions . nodeTransforms ) . toHaveLength ( 1 ) ;
387+ } ) ;
219388 } ) ;
220389
221390 describe ( 'filesystem cache handling' , ( ) => {
@@ -346,6 +515,19 @@ describe('WebpackCodeInspectorPlugin', () => {
346515 expect ( cb ) . toHaveBeenCalled ( ) ;
347516 } ) ;
348517
518+ it ( 'should skip htmlScript injection when disabled' , async ( ) => {
519+ vi . mocked ( isDev ) . mockReturnValueOnce ( true ) ;
520+ const plugin = new WebpackCodeInspectorPlugin ( {
521+ bundler : 'webpack' ,
522+ output : '/test' ,
523+ skipSnippets : [ 'htmlScript' ] ,
524+ } ) ;
525+
526+ await plugin . apply ( mockCompiler ) ;
527+
528+ expect ( mockCompiler . hooks . emit . tapAsync ) . not . toHaveBeenCalled ( ) ;
529+ } ) ;
530+
349531 it ( 'should skip non-HTML files' , async ( ) => {
350532 vi . mocked ( isDev ) . mockReturnValueOnce ( true ) ;
351533 const plugin = new WebpackCodeInspectorPlugin ( {
0 commit comments