//go:build !js package main import ( "bytes" "context" "os" "strings" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestRun_Good(t *testing.T) { input := strings.NewReader(`{"H":"nav-bar","C":"main-content"}`) var output bytes.Buffer err := run(input, &output) require.NoError(t, err) js := output.String() assert.Contains(t, js, "NavBar") assert.Contains(t, js, "MainContent") assert.Contains(t, js, "customElements.define") assert.Equal(t, 2, strings.Count(js, "extends HTMLElement")) } func TestRunTypeDefinitions_Good(t *testing.T) { input := strings.NewReader(`{"H":"nav-bar","C":"main-content"}`) var output bytes.Buffer err := runTypeDefinitions(input, &output) require.NoError(t, err) dts := output.String() assert.Contains(t, dts, "declare global") assert.Contains(t, dts, `"nav-bar": NavBar;`) assert.Contains(t, dts, `"main-content": MainContent;`) assert.Contains(t, dts, "export {};") } func TestRun_Bad_InvalidJSON(t *testing.T) { input := strings.NewReader(`not json`) var output bytes.Buffer err := run(input, &output) assert.Error(t, err) assert.Contains(t, err.Error(), "invalid JSON") } func TestRun_Bad_InvalidTag(t *testing.T) { input := strings.NewReader(`{"H":"notag"}`) var output bytes.Buffer err := run(input, &output) assert.Error(t, err) assert.Contains(t, err.Error(), "hyphen") } func TestRun_Good_Empty(t *testing.T) { input := strings.NewReader(`{}`) var output bytes.Buffer err := run(input, &output) require.NoError(t, err) assert.Empty(t, output.String()) } func TestRunDaemon_WritesBundle(t *testing.T) { dir := t.TempDir() inputPath := dir + "/slots.json" outputPath := dir + "/bundle.js" require.NoError(t, writeTestFile(inputPath, `{"H":"nav-bar","C":"main-content"}`)) ctx, cancel := context.WithCancel(context.Background()) defer cancel() done := make(chan error, 1) go func() { done <- runDaemon(ctx, inputPath, outputPath, false, 5*time.Millisecond) }() require.Eventually(t, func() bool { got, err := readTestFile(outputPath) if err != nil { return false } return strings.Contains(got, "NavBar") && strings.Contains(got, "MainContent") }, time.Second, 10*time.Millisecond) cancel() require.NoError(t, <-done) } func TestRunDaemon_RecoversFromInvalidJSON(t *testing.T) { dir := t.TempDir() inputPath := dir + "/slots.json" outputPath := dir + "/bundle.js" require.NoError(t, writeTestFile(inputPath, `not json`)) ctx, cancel := context.WithCancel(context.Background()) defer cancel() done := make(chan error, 1) go func() { done <- runDaemon(ctx, inputPath, outputPath, false, 5*time.Millisecond) }() time.Sleep(20 * time.Millisecond) require.NoError(t, writeTestFile(inputPath, `{"H":"nav-bar","C":"main-content"}`)) require.Eventually(t, func() bool { got, err := readTestFile(outputPath) if err != nil { return false } return strings.Contains(got, "NavBar") && strings.Contains(got, "MainContent") }, time.Second, 10*time.Millisecond) cancel() require.NoError(t, <-done) } func TestRunDaemon_MissingPaths(t *testing.T) { err := runDaemon(context.Background(), "", "", false, time.Millisecond) require.Error(t, err) assert.Contains(t, err.Error(), "watch mode requires -input") } func writeTestFile(path, content string) error { return os.WriteFile(path, []byte(content), 0o600) } func readTestFile(path string) (string, error) { data, err := os.ReadFile(path) if err != nil { return "", err } return string(data), nil }