github.com/derat/nup@v0.0.0-20230418113745-15592ba7c620/server/static_test.go (about) 1 // Copyright 2022 Daniel Erat. 2 // All rights reserved. 3 4 package main 5 6 import ( 7 "bytes" 8 "os" 9 "strings" 10 "testing" 11 12 "golang.org/x/net/html" 13 ) 14 15 // callGetStaticFile moves to the repository root, calls getStaticFile, 16 // and moves back to the original directory before returning the result. 17 func callGetStaticFile(t *testing.T, p string, minify bool) []byte { 18 dir, err := os.Getwd() 19 if err != nil { 20 t.Fatal(err) 21 } 22 if err := os.Chdir(".."); err != nil { 23 t.Fatal(err) 24 } 25 defer func() { 26 if err := os.Chdir(dir); err != nil { 27 t.Fatal(err) 28 } 29 }() 30 31 b, err := getStaticFile(p, minify) 32 if err != nil { 33 t.Fatalf("getStaticFile(%q, %v) failed: %v", p, minify, err) 34 } 35 return b 36 } 37 38 const ( 39 wsTag = " <script>" // tag with whitespace in non-minified index.js 40 commonFn = "common.js" // file imported by unbundled index.js 41 ) 42 43 func TestGetStaticFile_Index_Minify(t *testing.T) { 44 out := callGetStaticFile(t, indexFile, true) 45 if _, err := html.Parse(bytes.NewReader(out)); err != nil { 46 t.Errorf(`getStaticFile(%q, true) returned invalid HTML: %v`, indexFile, err) 47 } 48 if bytes.Contains(out, []byte(wsTag)) { 49 t.Errorf(`getStaticFile(%q, true) contains %q`, indexFile, wsTag) 50 } 51 if !bytes.Contains(out, []byte(bundleFile)) { 52 t.Errorf(`getStaticFile(%q, true) doesn't contain %q`, indexFile, bundleFile) 53 } 54 } 55 56 func TestGetStaticFile_Index_NoMinify(t *testing.T) { 57 out := callGetStaticFile(t, indexFile, false) 58 if _, err := html.Parse(bytes.NewReader(out)); err != nil { 59 t.Errorf(`getStaticFile(%q, false) returned invalid HTML: %v`, indexFile, err) 60 } 61 if !bytes.Contains(out, []byte(wsTag)) { 62 t.Errorf(`getStaticFile(%q, false) doesn't contain %q`, indexFile, wsTag) 63 } 64 if want := replaceSuffix(bundleEntryPoint, ".ts", ".js"); !bytes.Contains(out, []byte(want)) { 65 t.Errorf(`getStaticFile(%q, false) doesn't contain %q`, indexFile, want) 66 } 67 } 68 69 func TestGetStaticFile_Bundle(t *testing.T) { 70 if out := callGetStaticFile(t, bundleFile, true); bytes.Contains(out, []byte(commonFn)) { 71 t.Errorf("getStaticFile(%q, true) unexpectedly contains %q", bundleFile, commonFn) 72 } 73 } 74 75 func TestGetStaticFile_IndexScript(t *testing.T) { 76 index := replaceSuffix(bundleEntryPoint, ".ts", ".js") 77 if out := callGetStaticFile(t, index, false); !bytes.Contains(out, []byte(commonFn)) { 78 t.Errorf("getStaticFile(%q, false) doesn't contain %q", index, commonFn) 79 } 80 } 81 82 func TestGetStaticFile_Transform(t *testing.T) { 83 const fn = "common.js" 84 const funcName = "createElement" 85 if out := callGetStaticFile(t, fn, true); !bytes.Contains(out, []byte(funcName)) { 86 t.Errorf("getStaticFile(%q, true) doesn't contain %q", fn, funcName) 87 } 88 } 89 90 func TestMinifyAndTransformData(t *testing.T) { 91 for _, tc := range []struct { 92 in, ctype, want string 93 }{ 94 {"body {\n margin: 0;\n}\n", cssType, "body{margin:0}"}, 95 {"<!DOCTYPE html>\n<html>\nfoo\n</html>\n", htmlType, "<!doctype html>foo"}, 96 {"{\n \"foo\": 2\n}\n", jsonType, `{"foo":2}`}, 97 {"// comment\nexport const foo = 3;\n", jsType, "const o=3;export{o as foo};\n"}, 98 {"// comment\nexport const foo: number = 3;\n", tsType, "const o=3;export{o as foo};\n"}, 99 } { 100 if got, err := minifyAndTransformData(strings.NewReader(tc.in), tc.ctype); err != nil { 101 t.Errorf("minifyAndTransformData(%q, %q) failed: %v", tc.in, tc.ctype, err) 102 } else if string(got) != tc.want { 103 t.Errorf("minifyAndTransformData(%q, %q) = %q; want %q", tc.in, tc.ctype, got, tc.want) 104 } 105 } 106 } 107 108 func TestMinifyTemplates(t *testing.T) { 109 const bt = "`" 110 got, err := minifyTemplates(strings.NewReader(` 111 // Here's an HTML template: 112 const html = createTemplate(` + bt + ` 113 <!DOCTYPE html> 114 <html> 115 foo 116 </html> 117 ` + bt + `); 118 119 // And here's some CSS: 120 const css = new CSSStyleSheet(); 121 css.replaceSync(` + bt + ` 122 body { 123 margin: 0; 124 } 125 ` + bt + `); 126 127 const foo = 3; 128 `)) 129 130 if err != nil { 131 t.Fatal("minifyTemplates failed: ", err) 132 } 133 if want := ` 134 // Here's an HTML template: 135 const html = createTemplate(` + bt + `<!doctype html>foo` + bt + `); 136 137 // And here's some CSS: 138 const css = new CSSStyleSheet(); 139 css.replaceSync(` + bt + `body{margin:0}` + bt + `); 140 141 const foo = 3; 142 `; string(got) != want { 143 t.Errorf("minifyTemplates returned:\n%s\nwant:\n%s", got, want) 144 } 145 }