@@ -21,11 +21,39 @@ import (
2121 "time"
2222)
2323
24+ func TestGetPagesRouterScriptsCapturesAllChunksPerRoute (t * testing.T ) {
25+ // a route array can list several chunks; every one is a real script to scan,
26+ // not just the first element after the opening bracket.
27+ manifest := `self.__BUILD_MANIFEST={"/":["static/chunks/pages/index-a.js","static/chunks/shared-b.js"]}`
28+
29+ srv := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , _ * http.Request ) {
30+ w .Write ([]byte (manifest ))
31+ }))
32+ defer srv .Close ()
33+
34+ scripts , err := GetPagesRouterScripts (srv .URL + "/_buildManifest.js" , 5 * time .Second )
35+ if err != nil {
36+ t .Fatalf ("GetPagesRouterScripts: %v" , err )
37+ }
38+
39+ found := func (needle string ) bool {
40+ for _ , s := range scripts {
41+ if strings .Contains (s , needle ) {
42+ return true
43+ }
44+ }
45+ return false
46+ }
47+ if ! found ("index-a.js" ) || ! found ("shared-b.js" ) {
48+ t .Errorf ("want both chunks index-a.js and shared-b.js, got %v" , scripts )
49+ }
50+ }
51+
2452func TestGetPagesRouterScriptsReadsPastLongLine (t * testing.T ) {
2553 // a manifest token past bufio's 64k cap must not truncate the read and
2654 // drop the script references that follow it.
2755 huge := strings .Repeat ("x" , bufio .MaxScanTokenSize + 1 )
28- manifest := `["early.js"]` + "\n " + huge + "\n " + `["late.js"]`
56+ manifest := `["static/ early.js"]` + "\n " + huge + "\n " + `["static/ late.js"]`
2957
3058 srv := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , _ * http.Request ) {
3159 w .Write ([]byte (manifest ))
@@ -50,6 +78,62 @@ func TestGetPagesRouterScriptsReadsPastLongLine(t *testing.T) {
5078 }
5179}
5280
81+ func TestGetPagesRouterScriptsRealisticManifest (t * testing.T ) {
82+ // routes map to multi-chunk arrays, shared chunks are IIFE args, and
83+ // non-chunk .js strings appear in __rewrites and sortedPages; only the
84+ // former may end up in scripts, or a rewrite destination could steer a fetch.
85+ manifest := `self.__BUILD_MANIFEST=(function(a,b,c){return{` +
86+ `__rewrites:{afterFiles:[{"source":"/proxy/legacy.js","destination":"https://cdn.evil.example/tracker.js"}],beforeFiles:[],fallback:[]},` +
87+ `"/":[a,b,"static/chunks/pages/index-1a2b.js"],` +
88+ `"/_error":[a,"static/chunks/pages/_error-3c4d.js"],` +
89+ `"/blog/[slug]":[a,b,c,"static/chunks/pages/blog/[slug]-5e6f.js"],` +
90+ `sortedPages:["/","/_app","/_error","/blog/[slug]"],` +
91+ `ampFirstPages:[]` +
92+ `}}("static/chunks/webpack-9f8e.js","static/chunks/main-0d1c.js","static/chunks/framework-2b3a.js"));` +
93+ `self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();`
94+
95+ srv := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , _ * http.Request ) {
96+ w .Write ([]byte (manifest ))
97+ }))
98+ defer srv .Close ()
99+
100+ scripts , err := GetPagesRouterScripts (srv .URL + "/_buildManifest.js" , 5 * time .Second )
101+ if err != nil {
102+ t .Fatalf ("GetPagesRouterScripts: %v" , err )
103+ }
104+
105+ found := func (needle string ) bool {
106+ for _ , s := range scripts {
107+ if strings .Contains (s , needle ) {
108+ return true
109+ }
110+ }
111+ return false
112+ }
113+
114+ // every real chunk, including the trailing IIFE-arg shared chunks
115+ wantChunks := []string {
116+ "static/chunks/pages/index-1a2b.js" ,
117+ "static/chunks/pages/_error-3c4d.js" ,
118+ "static/chunks/pages/blog/[slug]-5e6f.js" ,
119+ "static/chunks/webpack-9f8e.js" ,
120+ "static/chunks/main-0d1c.js" ,
121+ "static/chunks/framework-2b3a.js" ,
122+ }
123+ for _ , c := range wantChunks {
124+ if ! found (c ) {
125+ t .Errorf ("missing chunk %q, got %v" , c , scripts )
126+ }
127+ }
128+
129+ // no non-chunk .js string may leak into the fetch list
130+ for _ , bad := range []string {"legacy.js" , "tracker.js" , "cdn.evil.example" } {
131+ if found (bad ) {
132+ t .Errorf ("false positive: captured non-chunk %q in %v" , bad , scripts )
133+ }
134+ }
135+ }
136+
53137func TestGetPagesRouterScriptsHonorsTimeout (t * testing.T ) {
54138 // a slow manifest host must not hang the scan: the fetch has to give up
55139 // once the caller's timeout elapses instead of reading with no deadline.
0 commit comments