From d4a1015c8652c61b97136ff8ee6f3cc37b2b79c5 Mon Sep 17 00:00:00 2001 From: Snider Date: Wed, 15 Apr 2026 19:31:12 +0100 Subject: [PATCH] test: cover gui spec gaps --- pkg/deno/sidecar_test.go | 32 +++++++ pkg/display/background_test.go | 111 ++++++++++++++++++++++ pkg/display/hlcrf_test.go | 74 +++++++++++++++ pkg/display/manifest_test.go | 57 ++++++++++++ pkg/display/network_test.go | 81 ++++++++++++++++ pkg/display/preload_test.go | 15 +++ pkg/display/sidecar_test.go | 72 +++++++++++++++ pkg/display/storage_test.go | 43 +++++++++ pkg/window/options_test.go | 163 +++++++++++++++++++++++++++++++++ 9 files changed, 648 insertions(+) create mode 100644 pkg/deno/sidecar_test.go create mode 100644 pkg/display/background_test.go create mode 100644 pkg/display/hlcrf_test.go create mode 100644 pkg/display/network_test.go create mode 100644 pkg/display/sidecar_test.go create mode 100644 pkg/window/options_test.go diff --git a/pkg/deno/sidecar_test.go b/pkg/deno/sidecar_test.go new file mode 100644 index 00000000..2990058a --- /dev/null +++ b/pkg/deno/sidecar_test.go @@ -0,0 +1,32 @@ +package deno + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestSidecar_New_Good(t *testing.T) { + manager := New(Options{}) + + status := manager.Status() + assert.Equal(t, "deno", status.Binary) + assert.False(t, status.Running) + assert.Zero(t, status.PID) +} + +func TestSidecar_New_Bad(t *testing.T) { + manager := New(Options{Binary: "/usr/local/bin/deno-custom", Args: []string{"fmt"}}) + + status := manager.Status() + assert.Equal(t, "/usr/local/bin/deno-custom", status.Binary) + assert.False(t, status.Running) +} + +func TestSidecar_New_Ugly(t *testing.T) { + manager := New(Options{Binary: " "}) + + status := manager.Status() + assert.Equal(t, "deno", status.Binary) + assert.False(t, status.Running) +} diff --git a/pkg/display/background_test.go b/pkg/display/background_test.go new file mode 100644 index 00000000..684aebc2 --- /dev/null +++ b/pkg/display/background_test.go @@ -0,0 +1,111 @@ +package display + +import ( + "context" + "testing" + + core "dappco.re/go/core" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestBackground_CloneMap_Good(t *testing.T) { + source := map[string]any{"alpha": "one", "beta": 2} + + cloned := cloneMap(source) + + require.NotNil(t, cloned) + assert.Equal(t, source, cloned) + + source["alpha"] = "mutated" + assert.Equal(t, "one", cloned["alpha"]) +} + +func TestBackground_CloneMap_Bad(t *testing.T) { + cloned := cloneMap(nil) + + require.NotNil(t, cloned) + assert.Empty(t, cloned) +} + +func TestBackground_CloneMap_Ugly(t *testing.T) { + source := map[string]any{"nested": map[string]any{"value": "original"}} + + cloned := cloneMap(source) + require.NotNil(t, cloned) + + source["nested"] = map[string]any{"value": "changed"} + assert.Equal(t, map[string]any{"value": "original"}, cloned["nested"]) +} + +func TestBackground_DecodeMap_Good(t *testing.T) { + decoded := decodeMap(map[string]any{"scope": "/app"}) + + require.NotNil(t, decoded) + assert.Equal(t, map[string]any{"scope": "/app"}, decoded) +} + +func TestBackground_DecodeMap_Bad(t *testing.T) { + decoded := decodeMap("not-a-map") + + require.NotNil(t, decoded) + assert.Empty(t, decoded) +} + +func TestBackground_DecodeMap_Ugly(t *testing.T) { + decoded := decodeMap(nil) + + require.NotNil(t, decoded) + assert.Empty(t, decoded) +} + +func TestBackground_RegisterBackgroundActions_Good(t *testing.T) { + svc, c := newTestDisplayService(t) + svc.background = NewBackgroundRegistry() + + result := c.Action("core.background.serviceWorker.register").Run(context.Background(), core.NewOptions( + core.Option{Key: "scriptURL", Value: "https://example.com/sw.js"}, + core.Option{Key: "options", Value: map[string]any{"scope": "/app"}}, + )) + + require.True(t, result.OK) + payload, ok := result.Value.(map[string]any) + require.True(t, ok) + assert.Equal(t, "/app", payload["scope"]) + require.Contains(t, payload, "active") + assert.Equal(t, map[string]any{"scriptURL": "https://example.com/sw.js"}, payload["active"]) +} + +func TestBackground_RegisterBackgroundActions_Bad(t *testing.T) { + svc, c := newTestDisplayService(t) + svc.background = NewBackgroundRegistry() + + result := c.Action("core.background.fetch").Run(context.Background(), core.NewOptions( + core.Option{Key: "id", Value: " "}, + core.Option{Key: "requests", Value: nil}, + core.Option{Key: "options", Value: nil}, + )) + + require.True(t, result.OK) + payload, ok := result.Value.(map[string]any) + require.True(t, ok) + assert.Equal(t, "", payload["id"]) + assert.Equal(t, "registered", payload["state"]) + assert.Nil(t, payload["requests"]) +} + +func TestBackground_RegisterBackgroundActions_Ugly(t *testing.T) { + svc, c := newTestDisplayService(t) + svc.background = NewBackgroundRegistry() + + result := c.Action("core.payment.instrument.set").Run(context.Background(), core.NewOptions( + core.Option{Key: "key", Value: " card-01 "}, + core.Option{Key: "details", Value: map[string]any{"network": "visa", "last4": "4242"}}, + )) + + require.True(t, result.OK) + payload, ok := result.Value.(map[string]any) + require.True(t, ok) + assert.Equal(t, "card-01", payload["key"]) + assert.Equal(t, map[string]any{"network": "visa", "last4": "4242"}, payload["details"]) +} diff --git a/pkg/display/hlcrf_test.go b/pkg/display/hlcrf_test.go new file mode 100644 index 00000000..a846e371 --- /dev/null +++ b/pkg/display/hlcrf_test.go @@ -0,0 +1,74 @@ +package display + +import ( + "os" + "path/filepath" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestHLCRF_DefaultHLCRFTag_Good(t *testing.T) { + assert.Equal(t, "core-widget", defaultHLCRFTag("Widget.ts")) +} + +func TestHLCRF_DefaultHLCRFTag_Bad(t *testing.T) { + assert.Equal(t, "feature-card", defaultHLCRFTag("feature_card.html")) +} + +func TestHLCRF_DefaultHLCRFTag_Ugly(t *testing.T) { + assert.Equal(t, "core-", defaultHLCRFTag("")) +} + +func TestHLCRF_BuildHLCRFComponents_Good(t *testing.T) { + root := t.TempDir() + require.NoError(t, os.MkdirAll(filepath.Join(root, ".core"), 0o755)) + require.NoError(t, os.WriteFile(filepath.Join(root, "index.html"), []byte(""), 0o644)) + require.NoError(t, os.WriteFile(filepath.Join(root, "card.html"), []byte("
Card
"), 0o644)) + require.NoError(t, os.WriteFile(filepath.Join(root, ".core", "view.yaml"), []byte(strings.Join([]string{ + "hlcrf:", + " - name: card.html", + " - tag: core-inline", + " template:
Inline
", + }, "\n")), 0o644)) + + svc := &Service{} + + script := svc.buildHLCRFComponents(filepath.Join(root, "index.html")) + + require.NotEmpty(t, script) + assert.Contains(t, script, "customElements.define") + assert.Contains(t, script, "article>Card") + assert.Contains(t, script, "
Inline
") + assert.Contains(t, script, "core-card") + assert.Contains(t, script, "core-inline") +} + +func TestHLCRF_BuildHLCRFComponents_Bad(t *testing.T) { + svc := &Service{} + + script := svc.buildHLCRFComponents(filepath.Join(t.TempDir(), "missing.html")) + + assert.Empty(t, script) +} + +func TestHLCRF_BuildHLCRFComponents_Ugly(t *testing.T) { + root := t.TempDir() + require.NoError(t, os.MkdirAll(filepath.Join(root, ".core"), 0o755)) + require.NoError(t, os.WriteFile(filepath.Join(root, "index.html"), []byte(""), 0o644)) + require.NoError(t, os.WriteFile(filepath.Join(root, ".core", "view.yaml"), []byte(strings.Join([]string{ + "hlcrf:", + " - name: missing.html", + " - template: Fallback", + }, "\n")), 0o644)) + + svc := &Service{} + + script := svc.buildHLCRFComponents(filepath.Join(root, "index.html")) + + require.NotEmpty(t, script) + assert.Contains(t, script, "Fallback") + assert.NotContains(t, script, "missing.html") +} diff --git a/pkg/display/manifest_test.go b/pkg/display/manifest_test.go index b0445d05..92024b52 100644 --- a/pkg/display/manifest_test.go +++ b/pkg/display/manifest_test.go @@ -6,6 +6,7 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -37,3 +38,59 @@ func TestInjectAppPreloads_RejectsTraversal(t *testing.T) { _, err = svc.injectAppPreloads(filepath.Join(root, "index.html")) require.Error(t, err) } + +func TestManifest_SafeManifestPreloadPath_Good(t *testing.T) { + root := t.TempDir() + got, err := safeManifestPreloadPath(root, "preload.js") + + require.NoError(t, err) + assert.Equal(t, filepath.Join(root, "preload.js"), got) +} + +func TestManifest_SafeManifestPreloadPath_Bad(t *testing.T) { + root := t.TempDir() + _, err := safeManifestPreloadPath(root, "") + + require.Error(t, err) + assert.Contains(t, err.Error(), "empty") +} + +func TestManifest_SafeManifestPreloadPath_Ugly(t *testing.T) { + root := t.TempDir() + _, err := safeManifestPreloadPath(root, "../preload.js") + + require.Error(t, err) + assert.Contains(t, err.Error(), "escapes") +} + +func TestManifest_DiscoverManifestPath_Good(t *testing.T) { + root := t.TempDir() + require.NoError(t, os.MkdirAll(filepath.Join(root, ".core"), 0o755)) + manifestPath := filepath.Join(root, ".core", "view.yaml") + require.NoError(t, os.WriteFile(manifestPath, []byte("name: demo\n"), 0o644)) + require.NoError(t, os.WriteFile(filepath.Join(root, "index.html"), []byte(""), 0o644)) + + got, err := discoverManifestPath(filepath.Join(root, "index.html")) + + require.NoError(t, err) + assert.Equal(t, manifestPath, got) +} + +func TestManifest_DiscoverManifestPath_Bad(t *testing.T) { + _, err := discoverManifestPath(filepath.Join(t.TempDir(), "missing.html")) + + require.Error(t, err) + assert.Contains(t, err.Error(), "not found") +} + +func TestManifest_DiscoverManifestPath_Ugly(t *testing.T) { + root := t.TempDir() + require.NoError(t, os.MkdirAll(filepath.Join(root, ".core"), 0o755)) + manifestPath := filepath.Join(root, ".core", "view.yaml") + require.NoError(t, os.WriteFile(manifestPath, []byte("name: remote\n"), 0o644)) + + got, err := discoverManifestPath(root) + + require.NoError(t, err) + assert.Equal(t, manifestPath, got) +} diff --git a/pkg/display/network_test.go b/pkg/display/network_test.go new file mode 100644 index 00000000..588ea0c9 --- /dev/null +++ b/pkg/display/network_test.go @@ -0,0 +1,81 @@ +package display + +import ( + "net" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestNetwork_InterfaceFlags_Good(t *testing.T) { + flags := interfaceFlags(net.FlagUp | net.FlagLoopback | net.FlagRunning) + + assert.Equal(t, []string{"up", "loopback", "running"}, flags) +} + +func TestNetwork_InterfaceFlags_Bad(t *testing.T) { + assert.Empty(t, interfaceFlags(0)) +} + +func TestNetwork_InterfaceFlags_Ugly(t *testing.T) { + assert.Empty(t, interfaceFlags(net.Flags(1<<30))) +} + +func TestNetwork_RenderNetworkPage_Good(t *testing.T) { + svc := &Service{} + state := NetworkState{ + Hostname: "core-host", + ObservedAt: time.Unix(1_700_000_000, 0).UTC(), + Interfaces: []NetworkInterfaceState{ + { + Name: "en0", + Index: 2, + MTU: 1500, + Addresses: []string{"192.168.0.10/24", "fe80::1/64"}, + Up: true, + }, + }, + Peers: []NetworkPeerState{ + {ID: "peer-1", Topic: "timeline", Connected: true, SeenAt: time.Unix(1_700_000_100, 0).UTC()}, + }, + } + + body := svc.renderNetworkPage(state) + + assert.Contains(t, body, "core://network") + assert.Contains(t, body, "core-host") + assert.Contains(t, body, "en0") + assert.Contains(t, body, "192.168.0.10/24") + assert.Contains(t, body, "Registered peers") + assert.Contains(t, body, "peer-1") +} + +func TestNetwork_RenderNetworkPage_Bad(t *testing.T) { + svc := &Service{} + + body := svc.renderNetworkPage(NetworkState{ + Hostname: "", + ObservedAt: time.Unix(1, 0).UTC(), + }) + + assert.Contains(t, body, "No network interfaces were detected.") + assert.Contains(t, body, "<host>") +} + +func TestNetwork_RenderNetworkPage_Ugly(t *testing.T) { + svc := &Service{} + + body := svc.renderNetworkPage(NetworkState{ + Hostname: strings.Repeat("x", 128), + ObservedAt: time.Unix(1, 0).UTC(), + Interfaces: []NetworkInterfaceState{ + {Name: "\"quoted\"", Index: 99, MTU: 9, Addresses: []string{""}, Up: false, Loopback: true}, + }, + }) + + assert.Contains(t, body, ""quoted"") + assert.Contains(t, body, "<addr>") + assert.Contains(t, body, "loopback") +} diff --git a/pkg/display/preload_test.go b/pkg/display/preload_test.go index 2eecf856..39f573b6 100644 --- a/pkg/display/preload_test.go +++ b/pkg/display/preload_test.go @@ -62,3 +62,18 @@ func TestDisplay_Good_CoreSchemeRoutesThroughBackend(t *testing.T) { require.Len(t, platform.Windows, 1) assert.True(t, strings.Contains(platform.Windows[0].HTMLContent(), "core://settings")) } + +func TestPreload_ValidatedLocalMLAPIURL_Good(t *testing.T) { + assert.Equal(t, "http://localhost:8090", validatedLocalMLAPIURL("http://localhost:8090/")) + assert.Equal(t, "https://127.0.0.1:9443", validatedLocalMLAPIURL("https://127.0.0.1:9443/")) +} + +func TestPreload_ValidatedLocalMLAPIURL_Bad(t *testing.T) { + assert.Equal(t, "http://localhost:8090", validatedLocalMLAPIURL("https://example.com")) + assert.Equal(t, "http://localhost:8090", validatedLocalMLAPIURL("ftp://localhost:8090")) +} + +func TestPreload_ValidatedLocalMLAPIURL_Ugly(t *testing.T) { + assert.Equal(t, "http://localhost:8090", validatedLocalMLAPIURL("")) + assert.Equal(t, "http://localhost:8090", validatedLocalMLAPIURL("not a url")) +} diff --git a/pkg/display/sidecar_test.go b/pkg/display/sidecar_test.go new file mode 100644 index 00000000..681f2e36 --- /dev/null +++ b/pkg/display/sidecar_test.go @@ -0,0 +1,72 @@ +package display + +import ( + "context" + "testing" + + core "dappco.re/go/core" + "forge.lthn.ai/core/gui/pkg/deno" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestSidecar_SplitCommandArgs_Good(t *testing.T) { + assert.Equal(t, []string{"--import-map", "map.json", "--watch"}, splitCommandArgs("--import-map map.json --watch")) +} + +func TestSidecar_SplitCommandArgs_Bad(t *testing.T) { + assert.Nil(t, splitCommandArgs("")) + assert.Nil(t, splitCommandArgs(" ")) +} + +func TestSidecar_SplitCommandArgs_Ugly(t *testing.T) { + assert.Equal(t, []string{"--flag", "--another", "value"}, splitCommandArgs("\t--flag\n--another value\t")) +} + +func TestSidecar_EnsureSidecar_Good(t *testing.T) { + t.Setenv("CORE_DENO_BINARY", "/usr/local/bin/deno-custom") + t.Setenv("CORE_DENO_DIR", "/tmp/core-deno") + t.Setenv("CORE_DENO_ARGS", "--import-map map.json") + + svc := &Service{} + manager := svc.ensureSidecar() + + require.NotNil(t, manager) + status := manager.Status() + assert.Equal(t, "/usr/local/bin/deno-custom", status.Binary) + assert.False(t, status.Running) +} + +func TestSidecar_EnsureSidecar_Bad(t *testing.T) { + svc := &Service{sidecar: deno.New(deno.Options{Binary: "custom-deno"})} + + manager := svc.ensureSidecar() + + require.Same(t, svc.sidecar, manager) + assert.Equal(t, "custom-deno", manager.Status().Binary) +} + +func TestSidecar_EnsureSidecar_Ugly(t *testing.T) { + t.Setenv("CORE_DENO_BINARY", " ") + t.Setenv("CORE_DENO_DIR", "") + t.Setenv("CORE_DENO_ARGS", " ") + + svc := &Service{} + manager := svc.ensureSidecar() + + require.NotNil(t, manager) + assert.Equal(t, "deno", manager.Status().Binary) +} + +func TestSidecar_StatusAction_Good(t *testing.T) { + t.Setenv("CORE_DENO_BINARY", "/opt/core/deno") + + _, c := newTestDisplayService(t) + result := c.Action("display.sidecar.status").Run(context.Background(), core.Options{}) + + require.True(t, result.OK) + status, ok := result.Value.(deno.Status) + require.True(t, ok) + assert.Equal(t, "/opt/core/deno", status.Binary) + assert.False(t, status.Running) +} diff --git a/pkg/display/storage_test.go b/pkg/display/storage_test.go index e9455868..d6d2aae6 100644 --- a/pkg/display/storage_test.go +++ b/pkg/display/storage_test.go @@ -107,3 +107,46 @@ func TestStorageRegistry_Snapshot_Good(t *testing.T) { _, otherOriginPresent := snapshot["other"] assert.False(t, otherOriginPresent) } + +func TestStorage_StorageOriginForPageURL_Good(t *testing.T) { + assert.Equal(t, "https://app.example.com", storageOriginForPageURL("https://app.example.com/path?q=1")) + assert.Equal(t, "core://settings", storageOriginForPageURL("core://settings/view")) +} + +func TestStorage_StorageOriginForPageURL_Bad(t *testing.T) { + assert.Equal(t, "custom://host/path", storageOriginForPageURL("custom://host/path")) +} + +func TestStorage_StorageOriginForPageURL_Ugly(t *testing.T) { + assert.Equal(t, "", storageOriginForPageURL("")) + assert.Equal(t, "", storageOriginForPageURL(" ")) +} + +func TestStorage_CompositeKey_Good(t *testing.T) { + key := storageCompositeKey("origin", "bucket", "item") + + origin, bucket, item, ok := decodeStorageCompositeKey(key) + require.True(t, ok) + assert.Equal(t, "origin", origin) + assert.Equal(t, "bucket", bucket) + assert.Equal(t, "item", item) + assert.Equal(t, "origin\x00bucket\x00item", makeStorageEntryKey("origin", "bucket", "item")) +} + +func TestStorage_CompositeKey_Bad(t *testing.T) { + origin, bucket, item, ok := decodeStorageCompositeKey("not-json") + + assert.False(t, ok) + assert.Empty(t, origin) + assert.Empty(t, bucket) + assert.Empty(t, item) +} + +func TestStorage_CompositeKey_Ugly(t *testing.T) { + origin, bucket, item, ok := decodeStorageCompositeKey(`["one","two"]`) + + assert.False(t, ok) + assert.Empty(t, origin) + assert.Empty(t, bucket) + assert.Empty(t, item) +} diff --git a/pkg/window/options_test.go b/pkg/window/options_test.go new file mode 100644 index 00000000..ac2df4a2 --- /dev/null +++ b/pkg/window/options_test.go @@ -0,0 +1,163 @@ +package window + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func applyWindowOptions(t *testing.T, options ...WindowOption) *Window { + t.Helper() + w, err := ApplyOptions(options...) + require.NoError(t, err) + return w +} + +func TestOptions_WindowOptionSetters_Good(t *testing.T) { + w := applyWindowOptions(t, + WithName("main"), + WithTitle("Core GUI"), + WithURL("/dashboard"), + WithHTML("
Ready
"), + WithJS("globalThis.__CORE_READY__ = true"), + WithSize(1280, 800), + WithPosition(160, 120), + WithMinSize(640, 480), + WithMaxSize(1920, 1080), + WithFrameless(true), + WithHidden(false), + WithAlwaysOnTop(true), + WithBackgroundColour(12, 34, 56, 78), + WithFileDrop(true), + ) + + assert.Equal(t, "main", w.Name) + assert.Equal(t, "Core GUI", w.Title) + assert.Equal(t, "/dashboard", w.URL) + assert.Equal(t, "
Ready
", w.HTML) + assert.Equal(t, "globalThis.__CORE_READY__ = true", w.JS) + assert.Equal(t, 1280, w.Width) + assert.Equal(t, 800, w.Height) + assert.Equal(t, 160, w.X) + assert.Equal(t, 120, w.Y) + assert.Equal(t, 640, w.MinWidth) + assert.Equal(t, 480, w.MinHeight) + assert.Equal(t, 1920, w.MaxWidth) + assert.Equal(t, 1080, w.MaxHeight) + assert.True(t, w.Frameless) + assert.False(t, w.Hidden) + assert.True(t, w.AlwaysOnTop) + assert.Equal(t, [4]uint8{12, 34, 56, 78}, w.BackgroundColour) + assert.True(t, w.EnableFileDrop) +} + +func TestOptions_WindowOptionSetters_Bad(t *testing.T) { + w := applyWindowOptions(t, + WithName(""), + WithTitle(""), + WithURL(""), + WithHTML(""), + WithJS(""), + WithSize(0, 0), + WithPosition(0, 0), + WithMinSize(0, 0), + WithMaxSize(0, 0), + WithFrameless(false), + WithHidden(false), + WithAlwaysOnTop(false), + WithBackgroundColour(0, 0, 0, 0), + WithFileDrop(false), + ) + + assert.Equal(t, "", w.Name) + assert.Equal(t, "", w.Title) + assert.Equal(t, "", w.URL) + assert.Equal(t, "", w.HTML) + assert.Equal(t, "", w.JS) + assert.Equal(t, 0, w.Width) + assert.Equal(t, 0, w.Height) + assert.Equal(t, 0, w.X) + assert.Equal(t, 0, w.Y) + assert.Equal(t, 0, w.MinWidth) + assert.Equal(t, 0, w.MinHeight) + assert.Equal(t, 0, w.MaxWidth) + assert.Equal(t, 0, w.MaxHeight) + assert.False(t, w.Frameless) + assert.False(t, w.Hidden) + assert.False(t, w.AlwaysOnTop) + assert.Equal(t, [4]uint8{0, 0, 0, 0}, w.BackgroundColour) + assert.False(t, w.EnableFileDrop) +} + +func TestOptions_WindowOptionSetters_Ugly(t *testing.T) { + w := applyWindowOptions(t, + WithName("⚙︎core-window"), + WithTitle("A very long title that stays intact"), + WithURL("core://settings?tab=%F0%9F%93%81"), + WithHTML("
unsafe-looking but literal
"), + WithJS("globalThis.__CORE_STATE__ = { mode: 'worker', value: -1 };"), + WithSize(-1920, -1080), + WithPosition(-42, 99999), + WithMinSize(-1, -2), + WithMaxSize(32767, 32767), + WithFrameless(true), + WithHidden(true), + WithAlwaysOnTop(true), + WithBackgroundColour(255, 254, 253, 252), + WithFileDrop(true), + ) + + assert.Equal(t, "⚙︎core-window", w.Name) + assert.Equal(t, "A very long title that stays intact", w.Title) + assert.Equal(t, "core://settings?tab=%F0%9F%93%81", w.URL) + assert.Equal(t, "
unsafe-looking but literal
", w.HTML) + assert.Equal(t, "globalThis.__CORE_STATE__ = { mode: 'worker', value: -1 };", w.JS) + assert.Equal(t, -1920, w.Width) + assert.Equal(t, -1080, w.Height) + assert.Equal(t, -42, w.X) + assert.Equal(t, 99999, w.Y) + assert.Equal(t, -1, w.MinWidth) + assert.Equal(t, -2, w.MinHeight) + assert.Equal(t, 32767, w.MaxWidth) + assert.Equal(t, 32767, w.MaxHeight) + assert.True(t, w.Frameless) + assert.True(t, w.Hidden) + assert.True(t, w.AlwaysOnTop) + assert.Equal(t, [4]uint8{255, 254, 253, 252}, w.BackgroundColour) + assert.True(t, w.EnableFileDrop) +} + +func TestOptions_ApplyOptions_Good(t *testing.T) { + w, err := ApplyOptions( + nil, + WithName("main"), + WithTitle("Core"), + ) + + require.NoError(t, err) + require.NotNil(t, w) + assert.Equal(t, "main", w.Name) + assert.Equal(t, "Core", w.Title) +} + +func TestOptions_ApplyOptions_Bad(t *testing.T) { + boom := assert.AnError + + w, err := ApplyOptions( + WithName("before"), + func(*Window) error { return boom }, + WithTitle("after"), + ) + + require.ErrorIs(t, err, boom) + assert.Nil(t, w) +} + +func TestOptions_ApplyOptions_Ugly(t *testing.T) { + w, err := ApplyOptions() + + require.NoError(t, err) + require.NotNil(t, w) + assert.Equal(t, &Window{}, w) +}