import { describe, it, expect, beforeEach, afterEach } from "vitest"
import { morph, morphInner } from "../src/morphlex"
describe("Morphlex Browser Tests", () => {
let container: HTMLElement
beforeEach(() => {
container = document.createElement("div")
container.id = "test-container"
document.body.appendChild(container)
})
afterEach(() => {
if (container && container.parentNode) {
container.parentNode.removeChild(container)
}
})
describe("Browser-specific DOM interactions", () => {
it("should handle real browser events after morphing", async () => {
const original = document.createElement("button")
original.textContent = "Click me"
let clicked = false
original.addEventListener("click", () => {
clicked = true
})
container.appendChild(original)
// Morph with new text but preserve the element
const reference = document.createElement("button")
reference.textContent = "Updated button"
morph(original, reference)
// Verify the button text changed
expect(original.textContent).toBe("Updated button")
// Click the button in the real browser
original.click()
// Event listener should still work
expect(clicked).toBe(true)
})
it("should handle CSS transitions in real browser", async () => {
const original = document.createElement("div")
original.style.cssText = "width: 100px; transition: width 0.1s;"
container.appendChild(original)
// Force browser to compute styles
const computedStyle = getComputedStyle(original)
expect(computedStyle.width).toBe("100px")
// Morph with new styles
const reference = document.createElement("div")
reference.style.cssText = "width: 200px; transition: width 0.1s;"
morph(original, reference)
// Verify styles were updated
expect(original.style.width).toBe("200px")
})
it("should handle focus state correctly", () => {
const original = document.createElement("input")
original.type = "text"
original.value = "initial"
container.appendChild(original)
// Focus the input
original.focus()
expect(document.activeElement).toBe(original)
// Morph with new attributes
const reference = document.createElement("input")
reference.type = "text"
reference.value = "updated"
reference.placeholder = "Enter text"
morph(original, reference)
// Focus should be preserved on the same element
expect(document.activeElement).toBe(original)
// Value is NOT updated - morphlex no longer updates input values
expect(original.value).toBe("initial")
expect(original.placeholder).toBe("Enter text")
})
it("should handle complex nested structures", () => {
container.innerHTML = `
Title
Item 1
Item 2
Item 3
`
const original = container.firstElementChild as HTMLElement
const originalH1 = original.querySelector("h1")
const referenceHTML = `
Updated Title
Item 1 - Modified
Item 2
New Item 3
Item 4
`
morph(original, referenceHTML)
// Check the structure is updated
expect(original.className).toBe("parent modified")
expect(originalH1?.textContent).toBe("Updated Title")
const newItems = Array.from(original.querySelectorAll("li"))
expect(newItems.length).toBe(4)
expect(newItems[0].textContent).toBe("Item 1 - Modified")
expect(newItems[3].textContent).toBe("Item 4")
})
it("should handle SVG elements in real browser", () => {
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg")
svg.setAttribute("width", "100")
svg.setAttribute("height", "100")
const circle = document.createElementNS("http://www.w3.org/2000/svg", "circle")
circle.setAttribute("cx", "50")
circle.setAttribute("cy", "50")
circle.setAttribute("r", "40")
circle.setAttribute("fill", "red")
svg.appendChild(circle)
container.appendChild(svg)
const referenceSVG = document.createElementNS("http://www.w3.org/2000/svg", "svg")
referenceSVG.setAttribute("width", "200")
referenceSVG.setAttribute("height", "200")
const referenceCircle = document.createElementNS("http://www.w3.org/2000/svg", "circle")
referenceCircle.setAttribute("cx", "100")
referenceCircle.setAttribute("cy", "100")
referenceCircle.setAttribute("r", "80")
referenceCircle.setAttribute("fill", "blue")
referenceSVG.appendChild(referenceCircle)
morph(svg, referenceSVG)
expect(svg.getAttribute("width")).toBe("200")
expect(svg.getAttribute("height")).toBe("200")
const morphedCircle = svg.querySelector("circle")
expect(morphedCircle?.getAttribute("cx")).toBe("100")
expect(morphedCircle?.getAttribute("cy")).toBe("100")
expect(morphedCircle?.getAttribute("r")).toBe("80")
expect(morphedCircle?.getAttribute("fill")).toBe("blue")
})
it("should handle form inputs and maintain state", () => {
const form = document.createElement("form")
form.innerHTML = `
`
container.appendChild(form)
const textInput = form.querySelector('input[name="username"]') as HTMLInputElement
const checkbox = form.querySelector('input[name="remember"]') as HTMLInputElement
const select = form.querySelector('select[name="country"]') as HTMLSelectElement
// Modify the values in the browser
textInput.value = "jane"
checkbox.checked = false
select.value = "us"
// Create reference with different structure but same form fields
const referenceForm = document.createElement("form")
referenceForm.className = "updated-form"
referenceForm.innerHTML = `
`
morph(form, referenceForm)
// Form should have new structure
expect(form.className).toBe("updated-form")
expect(form.querySelectorAll(".form-group").length).toBe(3)
// The form elements should be the same instances (preserved)
const newTextInput = form.querySelector('input[name="username"]') as HTMLInputElement
const newCheckbox = form.querySelector('input[name="remember"]') as HTMLInputElement
const newSelect = form.querySelector('select[name="country"]') as HTMLSelectElement
// Values are NOT updated - morphlex no longer updates input values, checked states, or selected options
// The input elements are reused, so they keep their existing values
expect(newTextInput.value).toBe("john")
expect(newCheckbox.checked).toBe(true)
expect(newSelect.value).toBe("uk")
// New attributes should be applied
expect(newTextInput.placeholder).toBe("Username")
expect(newSelect.className).toBe("country-select")
})
it("should handle morphInner with browser content", () => {
const testContainer = document.createElement("div")
testContainer.innerHTML = `