package jsbundler import ( "os" "path/filepath" "strings" "testing" ) // TestCrossTreeJSBundle proves the bundler resolves the shared kit across the // app/kjol tree boundary: a temp app entry imports @ui/Buttons, which pulls the // real kjol jsruntime/uikit (Buttons -> ./Icons -> @appgen/faIcons stub) and the solid // runtime from jsruntime/runtime. If the alias plugin, merged vendor manifest, and // multi-dir NodePaths all work, esbuild produces a non-empty bundle. func TestCrossTreeJSBundle(t *testing.T) { webAbs, err := filepath.Abs(filepath.Join("..", "jsruntime")) if err != nil { t.Fatal(err) } if _, err := os.Stat(filepath.Join(webAbs, "uikit", "Buttons.tsx")); err != nil { t.Skipf("kjol JS kit not present (%v)", err) } app := t.TempDir() gen := t.TempDir() out := t.TempDir() if err := os.MkdirAll(filepath.Join(app, "src"), 0o755); err != nil { t.Fatal(err) } entry := filepath.Join(app, "src", "app.ts") entrySrc := "import * as Buttons from \"@ui/Buttons\";\n" + "(globalThis as any).__kit = Buttons;\n" if err := os.WriteFile(entry, []byte(entrySrc), 0o644); err != nil { t.Fatal(err) } // Stub the app-owned generated FA registry that Icons.tsx imports via @appgen. if err := os.WriteFile(filepath.Join(gen, "faIcons.ts"), []byte("export const FA_ICONS = {};\n"), 0o644); err != nil { t.Fatal(err) } Configure(Config{AppFrontend: app, WebDir: webAbs, Output: out, GenTSDir: gen}) if _, err := bundleJSEntry(entry, "app.test.js"); err != nil { t.Fatalf("cross-tree bundle failed: %v", err) } data, err := os.ReadFile(filepath.Join(out, "app.test.js")) if err != nil { t.Fatalf("no output bundle: %v", err) } if len(data) == 0 { t.Fatal("empty bundle") } t.Logf("cross-tree bundle produced %d bytes", len(data)) } // TestCrossTreeCSS confirms the CSS pipeline compiles with the kit tree scanned // for utility candidates across the boundary (WebDir set) without error, and // that an app-side utility class makes it into the output. func TestCrossTreeCSS(t *testing.T) { webAbs, err := filepath.Abs(filepath.Join("..", "jsruntime")) if err != nil { t.Fatal(err) } if _, err := os.Stat(filepath.Join(webAbs, "uikit")); err != nil { t.Skipf("kjol JS kit not present (%v)", err) } app := t.TempDir() out := t.TempDir() if err := os.MkdirAll(filepath.Join(app, "css"), 0o755); err != nil { t.Fatal(err) } if err := os.MkdirAll(filepath.Join(app, "src"), 0o755); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(app, "css", "style.css"), []byte("@import \"tailwindcss\";\n"), 0o644); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(app, "src", "app.ts"), []byte("export const x = `
`;\n"), 0o644); err != nil { t.Fatal(err) } Configure(Config{AppFrontend: app, WebDir: webAbs, Output: out}) if _, err := compileCSSBundle("test", []string{"../src/**/*.ts"}, "test.css"); err != nil { t.Fatalf("cross-tree css compile failed: %v", err) } data, err := os.ReadFile(filepath.Join(out, "test.css")) if err != nil { t.Fatalf("no output css: %v", err) } if !strings.Contains(string(data), "padding") { t.Errorf("expected the app utility .p-4 to compile into the output") } t.Logf("cross-tree css produced %d bytes", len(data)) }