//go:build js && wasm

package wasmruntime

import (
	"testing"

	"kjol/wasmruntime/vdom"
)

// An <svg> built with document.createElement() is NOT an SVG element — it is an
// HTMLUnknownElement that happens to be spelled "svg". It has no geometry and it
// draws nothing, while still looking perfectly correct in the DOM inspector.
//
// This only bit on NAVIGATION: a server-rendered page's icons come from the HTML
// parser, which handles <svg> as foreign content correctly, and hydration merely
// adopts those nodes. Every icon the CLIENT created afterwards was inert.
func TestSVGIsCreatedInTheSVGNamespace(t *testing.T) {
	root := document.Call("createElement", "div")

	icon := vdom.El("svg",
		vdom.Attr("viewBox", "0 0 24 24"),
		vdom.El("path", vdom.Attr("d", "M4 4h16")),
	)
	patchChildren(root, nil, one(icon))

	svg := root.Get("childNodes").Index(0)
	if got := svg.Get("namespaceURI").String(); got != svgNamespace {
		t.Fatalf("<svg> namespace = %q, want %q — it will render nothing", got, svgNamespace)
	}

	// The subtree inherits it: a <path> in the HTML namespace draws nothing either.
	path := svg.Get("childNodes").Index(0)
	if got := path.Get("namespaceURI").String(); got != svgNamespace {
		t.Errorf("<path> namespace = %q, want %q", got, svgNamespace)
	}
}

// Ordinary HTML must NOT end up in the SVG namespace, including siblings that follow
// an icon.
func TestHTMLStaysInTheHTMLNamespace(t *testing.T) {
	root := document.Call("createElement", "div")

	tree := vdom.El("div",
		vdom.El("svg", vdom.El("path")),
		vdom.El("span", vdom.Text("after the icon")),
	)
	patchChildren(root, nil, one(tree))

	div := root.Get("childNodes").Index(0)
	span := div.Get("childNodes").Index(1)
	if got := span.Get("namespaceURI").String(); got == svgNamespace {
		t.Errorf("<span> after an <svg> leaked into the SVG namespace")
	}
}

// The navigation case, end to end: page A's tree is replaced by page B's, and the
// icon page B creates mid-diff must still be a real SVG. This is the one that broke.
func TestIconCreatedDuringNavigationIsRealSVG(t *testing.T) {
	root := document.Call("createElement", "div")

	pageA := vdom.El("div", vdom.El("p", vdom.Text("no icons here")))
	patchChildren(root, nil, one(pageA))

	// Navigate: same tag at the same index, so the diff reuses the <div> and creates
	// the icon *underneath* it rather than from a fresh mount.
	pageB := vdom.El("div", vdom.El("svg", vdom.Attr("viewBox", "0 0 24 24"), vdom.El("path")))
	patchChildren(root, one(pageA), one(pageB))

	svg := root.Get("childNodes").Index(0).Get("childNodes").Index(0)
	if got := svg.Get("tag").String(); got != "svg" {
		t.Fatalf("expected an <svg>, got <%s>", got)
	}
	if got := svg.Get("namespaceURI").String(); got != svgNamespace {
		t.Errorf("icon created during navigation has namespace %q, want %q — this is the bug", got, svgNamespace)
	}
}

// A <foreignObject> switches back to HTML for its contents.
func TestForeignObjectReturnsToHTML(t *testing.T) {
	root := document.Call("createElement", "div")

	tree := vdom.El("svg", vdom.El("foreignObject", vdom.El("div", vdom.Text("html again"))))
	patchChildren(root, nil, one(tree))

	fo := root.Get("childNodes").Index(0).Get("childNodes").Index(0)
	inner := fo.Get("childNodes").Index(0)
	if got := inner.Get("namespaceURI").String(); got == svgNamespace {
		t.Error("content inside <foreignObject> should be HTML, not SVG")
	}
}
