79 lines
2.5 KiB
Go
79 lines
2.5 KiB
Go
//go:build dev
|
|
|
|
package jsbundler
|
|
|
|
import (
|
|
"errors"
|
|
"net/http/httptest"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
esbuild "github.com/evanw/esbuild/pkg/api"
|
|
)
|
|
|
|
// errorModule must emit a valid ES module that imports the client's
|
|
// showErrorOverlay and calls it with the error text + file, so a failed
|
|
// transform pops the compile-error overlay instead of just logging.
|
|
func TestErrorModuleShape(t *testing.T) {
|
|
src := errorModule("ui/Broken.tsx", errors.New("Unexpected \"}\" at line 3"))
|
|
|
|
for _, want := range []string{
|
|
`from "/@hmr/client"`,
|
|
"showErrorOverlay",
|
|
"__hmrShowError(",
|
|
"ui/Broken.tsx",
|
|
`Unexpected`,
|
|
} {
|
|
if !strings.Contains(src, want) {
|
|
t.Errorf("errorModule() missing %q:\n%s", want, src)
|
|
}
|
|
}
|
|
|
|
// It must parse as an ES module (the payload is embedded JSON-as-JS).
|
|
res := esbuild.Transform(src, esbuild.TransformOptions{
|
|
Loader: esbuild.LoaderJS, Format: esbuild.FormatESModule, LogLevel: esbuild.LogLevelSilent,
|
|
})
|
|
if len(res.Errors) > 0 {
|
|
msgs := esbuild.FormatMessages(res.Errors, esbuild.FormatMessagesOptions{})
|
|
t.Fatalf("errorModule() is not valid JS:\n%s\n--- source ---\n%s", strings.Join(msgs, "\n"), src)
|
|
}
|
|
}
|
|
|
|
// A source file that fails to compile must be served as the overlay stub (HTTP
|
|
// 200, not a 500 that would tear the module graph), so the browser shows the
|
|
// error and the next save can recover.
|
|
func TestServeModuleCompileErrorServesOverlay(t *testing.T) {
|
|
root, err := filepath.Abs("../..")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Chdir(root)
|
|
frontendAbs, _ := filepath.Abs(frontendDir)
|
|
|
|
tmpSrc := evalSymlinks(t.TempDir())
|
|
// Deliberately broken JSX: an unclosed tag the compiler/esbuild must reject.
|
|
os.WriteFile(filepath.Join(tmpSrc, "Broken.tsx"),
|
|
[]byte("export default function Broken() {\n return <div><span></div>;\n}\n"), 0o644)
|
|
|
|
eps, _ := loadVendorManifest([]string{filepath.Join(frontendAbs, "vendor")})
|
|
d := &devServer{hub: newHub(), frontend: frontendAbs, srcRoot: tmpSrc,
|
|
vendorDirs: []string{filepath.Join(frontendAbs, "vendor")}, graph: newModuleGraph(),
|
|
vendorCache: map[string][]byte{}, cssTrigger: make(chan struct{}, 1), vendorEntrypoints: eps}
|
|
|
|
req := httptest.NewRequest("GET", srcURLPrefix+"Broken.tsx", nil)
|
|
w := httptest.NewRecorder()
|
|
d.serveModule(w, req)
|
|
|
|
if w.Code != 200 {
|
|
t.Fatalf("broken module served status %d, want 200 (overlay stub)", w.Code)
|
|
}
|
|
body := w.Body.String()
|
|
for _, want := range []string{"showErrorOverlay", `from "/@hmr/client"`, "Broken.tsx"} {
|
|
if !strings.Contains(body, want) {
|
|
t.Errorf("overlay stub missing %q:\n%s", want, body)
|
|
}
|
|
}
|
|
}
|