diff --git a/dist/morphlex.js b/dist/morphlex.js index c332f32..40c5e82 100644 --- a/dist/morphlex.js +++ b/dist/morphlex.js @@ -9,10 +9,10 @@ export function morph(node, reference, options = {}) { } if (isElement(node)) { node.ariaBusy = "true"; - new Morph(options).morph(node, reference); + new Morph(options).morph([node, reference]); node.ariaBusy = null; } else { - new Morph(options).morph(node, reference); + new Morph(options).morph([node, reference]); } } class Morph { @@ -47,17 +47,24 @@ class Morph { this.#afterPropertyUpdated = options.afterPropertyUpdated; Object.freeze(this); } - morph(node, reference) { - if (isParentNode(node) && isParentNode(reference)) { - this.#mapIdSets(node); - this.#mapIdSets(reference); - this.#mapSensivity(node); - Object.freeze(this.#idMap); - Object.freeze(this.#sensivityMap); + morph(pair) { + if (isParentNodePair(pair)) this.#buildMaps(pair); + this.#morphNode(pair); + } + morphInner(pair) { + this.#buildMaps(pair); + if (isMatchingElementPair(pair)) { + this.#morphMatchingElementContent(pair); + } else { + throw new Error("You can only do an inner morph with matching elements."); } - requestAnimationFrame(() => { - this.#morphNode(node, reference); - }); + } + #buildMaps([node, reference]) { + this.#mapIdSets(node); + this.#mapIdSets(reference); + this.#mapSensivity(node); + Object.freeze(this.#idMap); + Object.freeze(this.#sensivityMap); } #mapSensivity(node) { const sensitiveElements = node.querySelectorAll("audio,canvas,embed,iframe,input,object,textarea,video"); @@ -99,30 +106,34 @@ class Morph { } } // This is where we actually morph the nodes. The `morph` function (above) exists only to set up the `idMap`. - #morphNode(node, reference) { - if (isElement(node) && isElement(reference) && node.localName === reference.localName) { - this.#morphMatchingElementNode(node, reference); - } else { - this.#morphOtherNode(node, reference); - } + #morphNode(pair) { + if (isMatchingElementPair(pair)) this.#morphMatchingElementNode(pair); + else this.#morphOtherNode(pair); } - #morphMatchingElementNode(node, reference) { - if (!(this.#beforeNodeMorphed?.(node, reference) ?? true)) return; - if (node.hasAttributes() || reference.hasAttributes()) this.#morphAttributes(node, reference); - if (isHead(node)) { - this.#morphHead(node, reference); - } else if (node.hasChildNodes() || reference.hasChildNodes()) this.#morphChildNodes(node, reference); - this.#afterNodeMorphed?.(node, reference); + #morphMatchingElementNode(pair) { + const [node, reference] = pair; + if (!(this.#beforeNodeMorphed?.(node, writableNode(reference)) ?? true)) return; + if (node.hasAttributes() || reference.hasAttributes()) this.#morphAttributes(pair); + // TODO: Should use a branded pair here. + this.#morphMatchingElementContent(pair); + this.#afterNodeMorphed?.(node, writableNode(reference)); } - #morphOtherNode(node, reference) { - if (!(this.#beforeNodeMorphed?.(node, reference) ?? true)) return; + #morphOtherNode([node, reference]) { + if (!(this.#beforeNodeMorphed?.(node, writableNode(reference)) ?? true)) return; if (node.nodeType === reference.nodeType && node.nodeValue !== null && reference.nodeValue !== null) { // Handle text nodes, comments, and CDATA sections. this.#updateProperty(node, "nodeValue", reference.nodeValue); } else this.#replaceNode(node, reference.cloneNode(true)); - this.#afterNodeMorphed?.(node, reference); + this.#afterNodeMorphed?.(node, writableNode(reference)); } - #morphHead(node, reference) { + #morphMatchingElementContent(pair) { + const [node, reference] = pair; + if (isHead(node)) { + // We can pass the reference as a head here becuase we know it's the same as the node. + this.#morphHeadContents(pair); + } else if (node.hasChildNodes() || reference.hasChildNodes()) this.#morphChildNodes(pair); + } + #morphHeadContents([node, reference]) { const refChildNodesMap = new Map(); // Generate a map of the reference head element’s child nodes, keyed by their outerHTML. for (const child of reference.children) refChildNodesMap.set(child.outerHTML, child); @@ -136,7 +147,7 @@ class Morph { // Any remaining nodes in the map should be appended to the head. for (const refChild of refChildNodesMap.values()) this.#appendChild(node, refChild.cloneNode(true)); } - #morphAttributes(element, reference) { + #morphAttributes([element, reference]) { // Remove any excess attributes from the element that aren’t present in the reference. for (const { name, value } of element.attributes) { if (!reference.hasAttribute(name) && (this.#beforeAttributeUpdated?.(element, name, null) ?? true)) { @@ -179,18 +190,22 @@ class Morph { } } // Iterates over the child nodes of the reference element, morphing the main element’s child nodes to match. - #morphChildNodes(element, reference) { + #morphChildNodes(pair) { + const [element, reference] = pair; const childNodes = element.childNodes; const refChildNodes = reference.childNodes; for (let i = 0; i < refChildNodes.length; i++) { const child = childNodes[i]; const refChild = refChildNodes[i]; if (child && refChild) { - if (isElement(child) && isElement(refChild) && child.localName === refChild.localName) { - if (isHead(child)) { - this.#morphHead(child, refChild); - } else this.#morphChildElement(child, refChild, element); - } else this.#morphOtherNode(child, refChild); + const pair = [child, refChild]; + if (isMatchingElementPair(pair)) { + if (isHead(pair[0])) { + this.#morphHeadContents(pair); + } else { + this.#morphChildElement(pair, element); + } + } else this.#morphOtherNode(pair); } else if (refChild) { this.#appendChild(element, refChild.cloneNode(true)); } else if (child) { @@ -203,8 +218,8 @@ class Morph { if (child) this.#removeNode(child); } } - #morphChildElement(child, reference, parent) { - if (!(this.#beforeNodeMorphed?.(child, reference) ?? true)) return; + #morphChildElement([child, reference], parent) { + if (!(this.#beforeNodeMorphed?.(child, writableNode(reference)) ?? true)) return; const refIdSet = this.#idMap.get(reference); // Generate the array in advance of the loop const refSetArray = refIdSet ? [...refIdSet] : []; @@ -220,12 +235,12 @@ class Morph { if (id !== "") { if (id === reference.id) { this.#insertBefore(parent, currentNode, child); - return this.#morphNode(currentNode, reference); + return this.#morphNode([currentNode, reference]); } else { const currentIdSet = this.#idMap.get(currentNode); if (currentIdSet && refSetArray.some((it) => currentIdSet.has(it))) { this.#insertBefore(parent, currentNode, child); - return this.#morphNode(currentNode, reference); + return this.#morphNode([currentNode, reference]); } } } @@ -234,7 +249,7 @@ class Morph { } if (nextMatchByTagName) { this.#insertBefore(parent, nextMatchByTagName, child); - this.#morphNode(nextMatchByTagName, reference); + this.#morphNode([nextMatchByTagName, reference]); } else { const newNode = reference.cloneNode(true); if (this.#beforeNodeAdded?.(newNode) ?? true) { @@ -242,7 +257,7 @@ class Morph { this.#afterNodeAdded?.(newNode); } } - this.#afterNodeMorphed?.(child, reference); + this.#afterNodeMorphed?.(child, writableNode(reference)); } #updateProperty(node, propertyName, newValue) { const previousValue = node[propertyName]; @@ -289,6 +304,20 @@ class Morph { } } } +// We cannot use `instanceof` when nodes might be from different documents, +// so we use type guards instead. This keeps TypeScript happy, while doing +// the necessary checks at runtime. +function writableNode(node) { + return node; +} +function isMatchingElementPair(pair) { + const [a, b] = pair; + return isElement(a) && isElement(b) && a.localName === b.localName; +} +function isParentNodePair(pair) { + const [a, b] = pair; + return isParentNode(a) && isParentNode(b); +} function isElement(node) { return node.nodeType === 1; } diff --git a/package-lock.json b/package-lock.json index cb958be..75c65a6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "morphlex", - "version": "0.0.11", + "version": "0.0.14", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "morphlex", - "version": "0.0.11", + "version": "0.0.14", "license": "MIT", "devDependencies": { "@open-wc/testing": "^3.0.0-next.5", @@ -14,7 +14,7 @@ "gzip-size-cli": "^5.1.0", "prettier": "^3.2.5", "terser": "^5.28.1", - "typescript": "^5.3.3", + "typescript": "^5.4.2", "typescript-eslint": "^7.0.2" }, "funding": { diff --git a/package.json b/package.json index c31f2f1..6dd153a 100644 --- a/package.json +++ b/package.json @@ -18,8 +18,8 @@ "scripts": { "test": "web-test-runner test/**/*.test.js --node-resolve", "t": "web-test-runner --node-resolve", - "build": "tsc && prettier --write ./src ./dist", - "watch": "tsc -w", + "build": "npx tsc && prettier --write ./src ./dist", + "watch": "npx tsc -w", "test:watch": "npm run test -- --watch", "lint": "prettier --check ./src ./dist ./test", "minify": "terser dist/morphlex.js -o dist/morphlex.min.js --config-file terser-config.json", @@ -34,7 +34,7 @@ "gzip-size-cli": "^5.1.0", "prettier": "^3.2.5", "terser": "^5.28.1", - "typescript": "^5.3.3", + "typescript": "^5.4.2", "typescript-eslint": "^7.0.2" } } diff --git a/src/morphlex.ts b/src/morphlex.ts index 1334e22..6995bcd 100644 --- a/src/morphlex.ts +++ b/src/morphlex.ts @@ -5,6 +5,12 @@ type SensivityMap = WeakMap, number>; // Maps to a type that can only read properties type StrongReadonly = { readonly [K in keyof T as T[K] extends Function ? never : K]: T[K] }; +declare const brand: unique symbol; +type Branded = T & { [brand]: B }; + +type NodeReferencePair = Readonly<[N, ReadonlyNode]>; +type MatchingElementReferencePair = Branded, "MatchingElementPair">; + // Maps a Node to a type limited to read-only properties and methods for that Node type ReadonlyNode = | T @@ -55,10 +61,10 @@ export function morph(node: ChildNode, reference: ChildNode | string, options: O if (isElement(node)) { node.ariaBusy = "true"; - new Morph(options).morph(node, reference); + new Morph(options).morph([node, reference]); node.ariaBusy = null; } else { - new Morph(options).morph(node, reference); + new Morph(options).morph([node, reference]); } } @@ -99,19 +105,28 @@ class Morph { Object.freeze(this); } - morph(node: ChildNode, reference: ChildNode): void { - if (isParentNode(node) && isParentNode(reference)) { - this.#mapIdSets(node); - this.#mapIdSets(reference); - this.#mapSensivity(node); + morph(pair: NodeReferencePair): void { + if (isParentNodePair(pair)) this.#buildMaps(pair); + this.#morphNode(pair); + } + + morphInner(pair: NodeReferencePair): void { + this.#buildMaps(pair); - Object.freeze(this.#idMap); - Object.freeze(this.#sensivityMap); + if (isMatchingElementPair(pair)) { + this.#morphMatchingElementContent(pair); + } else { + throw new Error("You can only do an inner morph with matching elements."); } + } + + #buildMaps([node, reference]: NodeReferencePair): void { + this.#mapIdSets(node); + this.#mapIdSets(reference); + this.#mapSensivity(node); - requestAnimationFrame(() => { - this.#morphNode(node, reference); - }); + Object.freeze(this.#idMap); + Object.freeze(this.#sensivityMap); } #mapSensivity(node: ReadonlyNode): void { @@ -164,38 +179,45 @@ class Morph { } // This is where we actually morph the nodes. The `morph` function (above) exists only to set up the `idMap`. - #morphNode(node: ChildNode, reference: ReadonlyNode): void { - if (isElement(node) && isElement(reference) && node.localName === reference.localName) { - this.#morphMatchingElementNode(node, reference); - } else { - this.#morphOtherNode(node, reference); - } + #morphNode(pair: NodeReferencePair): void { + if (isMatchingElementPair(pair)) this.#morphMatchingElementNode(pair); + else this.#morphOtherNode(pair); } - #morphMatchingElementNode(node: Element, reference: ReadonlyNode): void { - if (!(this.#beforeNodeMorphed?.(node, reference as ChildNode) ?? true)) return; + #morphMatchingElementNode(pair: MatchingElementReferencePair): void { + const [node, reference] = pair; - if (node.hasAttributes() || reference.hasAttributes()) this.#morphAttributes(node, reference); + if (!(this.#beforeNodeMorphed?.(node, writableNode(reference)) ?? true)) return; - if (isHead(node)) { - this.#morphHead(node, reference as ReadonlyNode); - } else if (node.hasChildNodes() || reference.hasChildNodes()) this.#morphChildNodes(node, reference); + if (node.hasAttributes() || reference.hasAttributes()) this.#morphAttributes(pair); - this.#afterNodeMorphed?.(node, reference as ChildNode); + // TODO: Should use a branded pair here. + this.#morphMatchingElementContent(pair); + + this.#afterNodeMorphed?.(node, writableNode(reference)); } - #morphOtherNode(node: ChildNode, reference: ReadonlyNode): void { - if (!(this.#beforeNodeMorphed?.(node, reference as ChildNode) ?? true)) return; + #morphOtherNode([node, reference]: NodeReferencePair): void { + if (!(this.#beforeNodeMorphed?.(node, writableNode(reference)) ?? true)) return; if (node.nodeType === reference.nodeType && node.nodeValue !== null && reference.nodeValue !== null) { // Handle text nodes, comments, and CDATA sections. this.#updateProperty(node, "nodeValue", reference.nodeValue); } else this.#replaceNode(node, reference.cloneNode(true)); - this.#afterNodeMorphed?.(node, reference as ChildNode); + this.#afterNodeMorphed?.(node, writableNode(reference)); } - #morphHead(node: HTMLHeadElement, reference: ReadonlyNode): void { + #morphMatchingElementContent(pair: MatchingElementReferencePair): void { + const [node, reference] = pair; + + if (isHead(node)) { + // We can pass the reference as a head here becuase we know it's the same as the node. + this.#morphHeadContents(pair as MatchingElementReferencePair); + } else if (node.hasChildNodes() || reference.hasChildNodes()) this.#morphChildNodes(pair); + } + + #morphHeadContents([node, reference]: MatchingElementReferencePair): void { const refChildNodesMap: Map> = new Map(); // Generate a map of the reference head element’s child nodes, keyed by their outerHTML. @@ -214,7 +236,7 @@ class Morph { for (const refChild of refChildNodesMap.values()) this.#appendChild(node, refChild.cloneNode(true)); } - #morphAttributes(element: Element, reference: ReadonlyNode): void { + #morphAttributes([element, reference]: MatchingElementReferencePair): void { // Remove any excess attributes from the element that aren’t present in the reference. for (const { name, value } of element.attributes) { if (!reference.hasAttribute(name) && (this.#beforeAttributeUpdated?.(element, name, null) ?? true)) { @@ -261,7 +283,9 @@ class Morph { } // Iterates over the child nodes of the reference element, morphing the main element’s child nodes to match. - #morphChildNodes(element: Element, reference: ReadonlyNode): void { + #morphChildNodes(pair: MatchingElementReferencePair): void { + const [element, reference] = pair; + const childNodes = element.childNodes; const refChildNodes = reference.childNodes; @@ -270,11 +294,15 @@ class Morph { const refChild = refChildNodes[i] as ReadonlyNode | null; if (child && refChild) { - if (isElement(child) && isElement(refChild) && child.localName === refChild.localName) { - if (isHead(child)) { - this.#morphHead(child, refChild as ReadonlyNode); - } else this.#morphChildElement(child, refChild, element); - } else this.#morphOtherNode(child, refChild); + const pair: NodeReferencePair = [child, refChild]; + + if (isMatchingElementPair(pair)) { + if (isHead(pair[0])) { + this.#morphHeadContents(pair as MatchingElementReferencePair); + } else { + this.#morphChildElement(pair, element); + } + } else this.#morphOtherNode(pair); } else if (refChild) { this.#appendChild(element, refChild.cloneNode(true)); } else if (child) { @@ -289,8 +317,8 @@ class Morph { } } - #morphChildElement(child: Element, reference: ReadonlyNode, parent: Element): void { - if (!(this.#beforeNodeMorphed?.(child, reference as ChildNode) ?? true)) return; + #morphChildElement([child, reference]: MatchingElementReferencePair, parent: Element): void { + if (!(this.#beforeNodeMorphed?.(child, writableNode(reference)) ?? true)) return; const refIdSet = this.#idMap.get(reference); @@ -312,13 +340,13 @@ class Morph { if (id !== "") { if (id === reference.id) { this.#insertBefore(parent, currentNode, child); - return this.#morphNode(currentNode, reference); + return this.#morphNode([currentNode, reference]); } else { const currentIdSet = this.#idMap.get(currentNode); if (currentIdSet && refSetArray.some((it) => currentIdSet.has(it))) { this.#insertBefore(parent, currentNode, child); - return this.#morphNode(currentNode, reference); + return this.#morphNode([currentNode, reference]); } } } @@ -329,7 +357,7 @@ class Morph { if (nextMatchByTagName) { this.#insertBefore(parent, nextMatchByTagName, child); - this.#morphNode(nextMatchByTagName, reference); + this.#morphNode([nextMatchByTagName, reference]); } else { const newNode = reference.cloneNode(true); if (this.#beforeNodeAdded?.(newNode) ?? true) { @@ -338,7 +366,7 @@ class Morph { } } - this.#afterNodeMorphed?.(child, reference as ChildNode); + this.#afterNodeMorphed?.(child, writableNode(reference)); } #updateProperty(node: N, propertyName: P, newValue: N[P]): void { @@ -402,6 +430,20 @@ class Morph { // so we use type guards instead. This keeps TypeScript happy, while doing // the necessary checks at runtime. +function writableNode(node: ReadonlyNode): N { + return node as N; +} + +function isMatchingElementPair(pair: NodeReferencePair): pair is MatchingElementReferencePair { + const [a, b] = pair; + return isElement(a) && isElement(b) && a.localName === b.localName; +} + +function isParentNodePair(pair: NodeReferencePair): pair is NodeReferencePair { + const [a, b] = pair; + return isParentNode(a) && isParentNode(b); +} + function isElement(node: Node): node is Element; function isElement(node: ReadonlyNode): node is ReadonlyNode; function isElement(node: Node | ReadonlyNode): boolean { diff --git a/test/alpine-morph.test.js b/test/alpine-morph.test.js index 20b0295..ea041f0 100644 --- a/test/alpine-morph.test.js +++ b/test/alpine-morph.test.js @@ -1,6 +1,5 @@ import { fixture, html, expect } from "@open-wc/testing"; import { morph } from "../"; -import { nextFrame } from "./helpers"; // adapted from: https://github.com/alpinejs/alpine/blob/891d68503960a39826e89f2f666d9b1e7ce3f0c9/tests/jest/morph/external.spec.js describe("alpine-morph", () => { @@ -10,8 +9,6 @@ describe("alpine-morph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); @@ -21,8 +18,6 @@ describe("alpine-morph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); @@ -37,8 +32,6 @@ describe("alpine-morph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); @@ -53,8 +46,6 @@ describe("alpine-morph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); @@ -64,8 +55,6 @@ describe("alpine-morph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); @@ -75,8 +64,6 @@ describe("alpine-morph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); @@ -86,8 +73,6 @@ describe("alpine-morph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); }); diff --git a/test/helpers.js b/test/helpers.js deleted file mode 100644 index 8b54144..0000000 --- a/test/helpers.js +++ /dev/null @@ -1,7 +0,0 @@ -export function nextFrame() { - return new Promise((resolve) => { - requestAnimationFrame(() => { - resolve(); - }); - }); -} diff --git a/test/morphdom.test.js b/test/morphdom.test.js index 9ad00d9..2252602 100644 --- a/test/morphdom.test.js +++ b/test/morphdom.test.js @@ -1,6 +1,5 @@ import { fixture, html, expect } from "@open-wc/testing"; import { morph } from "../"; -import { nextFrame } from "./helpers"; // adapted from: https://github.com/patrick-steele-idem/morphdom/blob/e98d69e125cda814dd6d1ba71d6c7c9d93edc01e/test/browser/test.js describe("morphdom", () => { @@ -9,7 +8,6 @@ describe("morphdom", () => { const b = await fixture(html`
`); morph(a, b); - await nextFrame(); expect(a.outerHTML).to.equal(b.outerHTML); expect(a.className).to.equal("bar"); @@ -25,7 +23,6 @@ describe("morphdom", () => { const b = await fixture(html``); morph(a, b); - await nextFrame(); expect(a.outerHTML).to.equal(b.outerHTML); expect(a.nodeName).to.equal("BODY"); @@ -37,7 +34,6 @@ describe("morphdom", () => { const b = await fixture(html`
B
`); morph(a, b); - await nextFrame(); expect(a.outerHTML).to.equal(b.outerHTML); expect(a.className).to.equal("bar"); @@ -51,7 +47,6 @@ describe("morphdom", () => { const b = await fixture(html`
B
`); morph(a, b); - await nextFrame(); expect(a.outerHTML).to.equal(b.outerHTML); expect(a.className).to.equal("zoo"); @@ -72,7 +67,6 @@ describe("morphdom", () => { const b = await fixture(html`

A

`); morph(a, b); - await nextFrame(); expect(a.outerHTML).to.equal(b.outerHTML); expect(a.children.length).to.equal(2); @@ -95,7 +89,6 @@ describe("morphdom", () => { const b = await fixture(html`

C

`); morph(a, b); - await nextFrame(); expect(a.outerHTML).to.equal(b.outerHTML); expect(a.children.length).to.equal(1); @@ -109,7 +102,6 @@ describe("morphdom", () => { const b = await fixture(html``); morph(a, b); - await nextFrame(); expect(a.outerHTML).to.equal(b.outerHTML); expect(a.value).to.equal("Hello World 2"); @@ -121,7 +113,6 @@ describe("morphdom", () => { const b = await fixture(html``); morph(a, b); - await nextFrame(); expect(a.outerHTML).to.equal(b.outerHTML); expect(a.checked).to.equal(true); @@ -135,7 +126,6 @@ describe("morphdom", () => { b.checked = true; morph(a, b); - await nextFrame(); expect(a.outerHTML).to.equal(b.outerHTML); expect(a.checked).to.equal(true); diff --git a/test/morphlex.test.js b/test/morphlex.test.js index ff1e0ba..5962599 100644 --- a/test/morphlex.test.js +++ b/test/morphlex.test.js @@ -1,6 +1,5 @@ import { fixture, html, expect } from "@open-wc/testing"; import { morph } from "../"; -import { nextFrame } from "./helpers"; describe("morph", () => { it("doesn't cause iframes to reload", async () => { @@ -21,8 +20,6 @@ describe("morph", () => { const originalIframe = original.querySelector("iframe"); morph(original, reference); - await nextFrame(); - expect(original.outerHTML).to.equal(reference.outerHTML); }); @@ -38,8 +35,6 @@ describe("morph", () => { morph(original, eventual); - await nextFrame(); - expect(original.textContent).to.equal("Hello Joel"); }); @@ -53,8 +48,6 @@ describe("morph", () => { morph(a, b); - await nextFrame(); - expect(a.textContent).to.equal(b.textContent); }); @@ -64,8 +57,6 @@ describe("morph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); }); diff --git a/test/nanomorph.test.js b/test/nanomorph.test.js index 85daf1b..90b8c48 100644 --- a/test/nanomorph.test.js +++ b/test/nanomorph.test.js @@ -1,6 +1,5 @@ import { fixture, html, expect } from "@open-wc/testing"; import { morph } from "../"; -import { nextFrame } from "./helpers"; // adapted from: https://github.com/choojs/nanomorph/blob/b8088d03b1113bddabff8aa0e44bd8db88d023c7/test/diff.js describe("nanomorph", () => { @@ -13,8 +12,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); @@ -24,8 +21,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); @@ -35,8 +30,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); @@ -46,8 +39,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); @@ -56,8 +47,6 @@ describe("nanomorph", () => { morph(a, a); - await nextFrame(); - expect(a.outerHTML).to.equal(a.outerHTML); }); }); @@ -69,8 +58,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); @@ -80,8 +67,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); @@ -90,8 +75,6 @@ describe("nanomorph", () => { morph(a, a); - await nextFrame(); - expect(a.outerHTML).to.equal(a.outerHTML); }); @@ -101,8 +84,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); @@ -112,8 +93,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); @@ -123,8 +102,6 @@ describe("nanomorph", () => { morph(a, b, { childrenOnly: true }); - await nextFrame(); - expect(a.outerHTML).to.equal("

hello you

"); }); }); @@ -136,8 +113,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); expect(a.getAttribute("value")).to.equal(null); expect(a.value).to.equal(""); @@ -149,8 +124,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); expect(a.getAttribute("value")).to.equal(null); expect(a.value).to.equal(""); @@ -162,8 +135,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); expect(a.value).to.equal("hi"); }); @@ -176,8 +147,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); expect(a.value).to.equal("hi"); }); @@ -189,8 +158,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); expect(a.value).to.equal("hi"); }); @@ -202,8 +169,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); expect(a.value).to.equal("hi"); }); @@ -217,8 +182,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); expect(a.checked).to.equal(false); }); @@ -229,8 +192,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); expect(a.checked).to.equal(true); }); @@ -241,8 +202,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); expect(a.checked).to.equal(true); }); @@ -253,8 +212,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); expect(a.checked).to.equal(false); }); @@ -266,8 +223,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); expect(a.checked).to.equal(true); }); @@ -279,8 +234,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); expect(a.checked).to.equal(true); }); @@ -292,8 +245,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); expect(a.checked).to.equal(false); }); @@ -304,8 +255,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); expect(a.checked).to.equal(true); }); @@ -318,8 +267,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); expect(a.disabled).to.equal(false); }); @@ -330,8 +277,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); expect(a.disabled).to.equal(true); }); @@ -342,8 +287,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); expect(a.disabled).to.equal(true); }); @@ -354,8 +297,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); expect(a.disabled).to.equal(false); }); @@ -367,8 +308,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); expect(a.disabled).to.equal(true); }); @@ -380,8 +319,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); expect(a.disabled).to.equal(true); }); @@ -393,8 +330,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); expect(a.disabled).to.equal(false); }); @@ -405,8 +340,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); expect(a.disabled).to.equal(true); }); @@ -420,8 +353,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); expect(a.indeterminate).to.equal(true); }); @@ -433,8 +364,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); expect(a.indeterminate).to.equal(false); }); @@ -456,8 +385,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); @@ -475,8 +402,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); }); @@ -495,8 +420,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); @@ -515,8 +438,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); @@ -533,8 +454,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); @@ -553,8 +472,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); @@ -574,8 +491,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); @@ -595,8 +510,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); @@ -616,8 +529,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); }); @@ -644,8 +555,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); @@ -663,8 +572,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); const c = await fixture( @@ -679,8 +586,6 @@ describe("nanomorph", () => { morph(a, c); - await nextFrame(); - expect(a.outerHTML).to.equal(c.outerHTML); }); @@ -708,8 +613,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); expect(a.children[0]).to.equal(oldFirst); expect(a.children[1]).to.equal(oldSecond); @@ -743,8 +646,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); expect(a.children[1]).to.equal(oldSecond); expect(a.children[3]).to.equal(oldThird); @@ -767,8 +668,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); @@ -792,8 +691,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); expect(a.children[0]).to.equal(oldFirst); expect(a.children[1]).to.equal(oldThird); @@ -805,8 +702,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); @@ -826,8 +721,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); @@ -842,8 +735,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); }); @@ -857,8 +748,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); @@ -871,8 +760,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); @@ -888,8 +775,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); @@ -899,8 +784,6 @@ describe("nanomorph", () => { morph(a, b); - await nextFrame(); - expect(a.outerHTML).to.equal(b.outerHTML); }); });