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  }