mirror of https://github.com/webpack/webpack.git
				
				
				
			
		
			
	
	
		
			142 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
		
		
			
		
	
	
			142 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
|  | const AssetPrefetchPreloadRuntimeModule = require("../../lib/runtime/AssetPrefetchPreloadRuntimeModule"); | ||
|  | const Template = require("../../lib/Template"); | ||
|  | 
 | ||
|  | describe("AssetPrefetchPreloadRuntimeModule", () => { | ||
|  | 	const mockCompilation = { | ||
|  | 		outputOptions: { | ||
|  | 			crossOriginLoading: false | ||
|  | 		} | ||
|  | 	}; | ||
|  | 	const mockRuntimeTemplate = { | ||
|  | 		basicFunction: (args, body) => { | ||
|  | 			if (typeof body === "string") { | ||
|  | 				return `function(${args}){${body}}`; | ||
|  | 			} | ||
|  | 			return `function(${args}){${Template.asString(body)}}`; | ||
|  | 		} | ||
|  | 	}; | ||
|  | 
 | ||
|  | 	beforeEach(() => { | ||
|  | 		// Mock for runtime environment
 | ||
|  | 		global.__webpack_require__ = { | ||
|  | 			p: "/", | ||
|  | 			u: id => `${id}.js` | ||
|  | 		}; | ||
|  | 		global.RuntimeGlobals = { | ||
|  | 			prefetchAsset: "__webpack_require__.PA", | ||
|  | 			preloadAsset: "__webpack_require__.LA" | ||
|  | 		}; | ||
|  | 		global.document = { | ||
|  | 			head: { | ||
|  | 				appendChild: jest.fn() | ||
|  | 			}, | ||
|  | 			createElement: jest.fn(tag => ({ | ||
|  | 				tag, | ||
|  | 				setAttribute: jest.fn() | ||
|  | 			})) | ||
|  | 		}; | ||
|  | 	}); | ||
|  | 
 | ||
|  | 	afterEach(() => { | ||
|  | 		delete global.__webpack_require__; | ||
|  | 		delete global.RuntimeGlobals; | ||
|  | 		delete global.document; | ||
|  | 	}); | ||
|  | 
 | ||
|  | 	describe("prefetch module", () => { | ||
|  | 		it("should generate runtime code for prefetch", () => { | ||
|  | 			const module = new AssetPrefetchPreloadRuntimeModule("prefetch"); | ||
|  | 			module.compilation = mockCompilation; | ||
|  | 			module.runtimeTemplate = mockRuntimeTemplate; | ||
|  | 
 | ||
|  | 			const code = module.generate(); | ||
|  | 
 | ||
|  | 			expect(code).toContain("__webpack_require__.PAQueue = [];"); | ||
|  | 			expect(code).toContain("__webpack_require__.PAQueueProcessing = false;"); | ||
|  | 			expect(code).toContain("processPrefetchQueue"); | ||
|  | 			expect(code).toContain("link.rel = 'prefetch';"); | ||
|  | 			expect(code).toContain("PAQueue.sort"); | ||
|  | 			expect(code).toContain("order: order || 0"); | ||
|  | 		}); | ||
|  | 
 | ||
|  | 		it("should support fetchPriority attribute", () => { | ||
|  | 			const module = new AssetPrefetchPreloadRuntimeModule("prefetch"); | ||
|  | 			module.compilation = mockCompilation; | ||
|  | 			module.runtimeTemplate = mockRuntimeTemplate; | ||
|  | 
 | ||
|  | 			const code = module.generate(); | ||
|  | 
 | ||
|  | 			expect(code).toContain("if(item.fetchPriority)"); | ||
|  | 			expect(code).toContain("link.fetchPriority = item.fetchPriority;"); | ||
|  | 			expect(code).toContain("link.setAttribute('fetchpriority', item.fetchPriority);"); | ||
|  | 		}); | ||
|  | 
 | ||
|  | 		it("should handle numeric order for queue sorting", () => { | ||
|  | 			const module = new AssetPrefetchPreloadRuntimeModule("prefetch"); | ||
|  | 			module.compilation = mockCompilation; | ||
|  | 			module.runtimeTemplate = mockRuntimeTemplate; | ||
|  | 
 | ||
|  | 			const code = module.generate(); | ||
|  | 
 | ||
|  | 			expect(code).toContain("// Sort queue by order (lower numbers first)"); | ||
|  | 			expect(code).toContain("return a.order - b.order;"); | ||
|  | 		}); | ||
|  | 	}); | ||
|  | 
 | ||
|  | 	describe("preload module", () => { | ||
|  | 		it("should generate runtime code for preload", () => { | ||
|  | 			const module = new AssetPrefetchPreloadRuntimeModule("preload"); | ||
|  | 			module.compilation = mockCompilation; | ||
|  | 			module.runtimeTemplate = mockRuntimeTemplate; | ||
|  | 
 | ||
|  | 			const code = module.generate(); | ||
|  | 
 | ||
|  | 			expect(code).toContain("__webpack_require__.LAQueue = [];"); | ||
|  | 			expect(code).toContain("__webpack_require__.LAQueueProcessing = false;"); | ||
|  | 			expect(code).toContain("processPreloadQueue"); | ||
|  | 			expect(code).toContain("link.rel = 'preload';"); | ||
|  | 			expect(code).toContain("LAQueue.sort"); | ||
|  | 			expect(code).toContain("order: order || 0"); | ||
|  | 		}); | ||
|  | 
 | ||
|  | 		it("should add nonce when crossOriginLoading is enabled", () => { | ||
|  | 			const module = new AssetPrefetchPreloadRuntimeModule("preload"); | ||
|  | 			module.compilation = { | ||
|  | 				outputOptions: { | ||
|  | 					crossOriginLoading: true | ||
|  | 				} | ||
|  | 			}; | ||
|  | 			module.runtimeTemplate = mockRuntimeTemplate; | ||
|  | 
 | ||
|  | 			const code = module.generate(); | ||
|  | 
 | ||
|  | 			expect(code).toContain("if(__webpack_require__.nc)"); | ||
|  | 			expect(code).toContain("link.setAttribute('nonce', __webpack_require__.nc);"); | ||
|  | 		}); | ||
|  | 	}); | ||
|  | 
 | ||
|  | 	describe("queue processing", () => { | ||
|  | 		it("should process items sequentially with setTimeout", () => { | ||
|  | 			const module = new AssetPrefetchPreloadRuntimeModule("prefetch"); | ||
|  | 			module.compilation = mockCompilation; | ||
|  | 			module.runtimeTemplate = mockRuntimeTemplate; | ||
|  | 
 | ||
|  | 			const code = module.generate(); | ||
|  | 
 | ||
|  | 			expect(code).toContain("// Process next item after a small delay to avoid blocking"); | ||
|  | 			expect(code).toContain("setTimeout(processNext, 0);"); | ||
|  | 		}); | ||
|  | 
 | ||
|  | 		it("should handle empty queue", () => { | ||
|  | 			const module = new AssetPrefetchPreloadRuntimeModule("prefetch"); | ||
|  | 			module.compilation = mockCompilation; | ||
|  | 			module.runtimeTemplate = mockRuntimeTemplate; | ||
|  | 
 | ||
|  | 			const code = module.generate(); | ||
|  | 
 | ||
|  | 			expect(code).toContain("if (__webpack_require__.PAQueue.length === 0)"); | ||
|  | 			expect(code).toContain("__webpack_require__.PAQueueProcessing = false;"); | ||
|  | 			expect(code).toContain("return;"); | ||
|  | 		}); | ||
|  | 	}); | ||
|  | }); |