mithril-vndb/test/mithril.render.js

1553 lines
44 KiB
JavaScript

describe("m.render()", function () {
"use strict"
it("exists", function () {
expect(m.render).to.be.a("function")
})
it("renders a string", function () {
var root = mock.document.createElement("div")
m.render(root, "test")
expect(root.childNodes[0].nodeValue).to.equal("test")
})
it("does not replace nodes differing in only class attr", function () {
var root = mock.document.createElement("div")
m.render(root, m("div", {class: "a"}))
var elementBefore = root.childNodes[0]
m.render(root, m("div", {class: "b"}))
expect(root.childNodes[0]).to.equal(elementBefore)
})
it("does not replace nodes differing in only class syntax", function () {
var root = mock.document.createElement("div")
m.render(root, m(".a"))
var elementBefore = root.childNodes[0]
m.render(root, m(".b"))
expect(root.childNodes[0]).to.equal(elementBefore)
})
it("replaces nodes differing in id attr", function () {
var root = mock.document.createElement("div")
m.render(root, m("div", {id: "a"}))
var elementBefore = root.childNodes[0]
m.render(root, m("div", {title: "b"}))
expect(root.childNodes[0]).to.not.equal(elementBefore)
})
it("replaces nodes differing in id syntax", function () {
var root = mock.document.createElement("div")
m.render(root, m("#a"))
var elementBefore = root.childNodes[0]
m.render(root, m("[title=b]"))
expect(root.childNodes[0]).to.not.equal(elementBefore)
})
it("replaces id node with string node", function () {
var root = mock.document.createElement("div")
m.render(root, m("#a"))
var elementBefore = root.childNodes[0]
m.render(root, "test")
expect(root.childNodes[0]).to.not.equal(elementBefore)
})
it("renders `undefined` body to empty string", function () {
var root = mock.document.createElement("div")
m.render(root, m("div", [undefined]))
expect(root.childNodes[0].childNodes[0].nodeValue).to.equal("")
})
it("uses the W3C URI as default namespace for SVG children", function () {
var root = mock.document.createElement("div")
m.render(root, m("svg", [m("g")]))
expect(root.childNodes[0].childNodes[0]).to.contain.all.keys({
nodeName: "G",
namespaceURI: "http://www.w3.org/2000/svg"
})
})
it("renders HTML elements contained in SVG elements", function () {
var root = mock.document.createElement("div")
m.render(root, m("svg", [m("a[href='http://google.com']")]))
expect(root.childNodes[0].childNodes[0].nodeName).to.equal("A")
})
it("does not append rerendered items", function () {
var root = mock.document.createElement("div")
m.render(root, m("div.classname", [m("a", {href: "/first"})]))
m.render(root, m("div", [m("a", {href: "/second"})]))
expect(root.childNodes[0].childNodes).to.have.length(1)
})
it("renders an added `undefined` to an empty string", function () {
var root = mock.document.createElement("div")
m.render(root, m("ul", [m("li")]))
m.render(root, m("ul", [m("li"), undefined]))
expect(root.childNodes[0].childNodes[1].nodeValue).to.equal("")
})
it("renders a node replaced with `undefined` to an empty string", function () { // eslint-disable-line
var root = mock.document.createElement("div")
m.render(root, m("ul", [m("li"), m("li")]))
m.render(root, m("ul", [m("li"), undefined]))
expect(root.childNodes[0].childNodes[1].nodeValue).to.equal("")
})
it("renders a replaced first `undefined` to an empty string", function () {
var root = mock.document.createElement("div")
m.render(root, m("ul", [m("li")]))
m.render(root, m("ul", [undefined]))
expect(root.childNodes[0].childNodes[0].nodeValue).to.equal("")
})
it("does not render something replaced with empty object", function () {
var root = mock.document.createElement("div")
m.render(root, m("ul", [m("li")]))
m.render(root, m("ul", [{}]))
expect(root.childNodes[0].childNodes).to.be.empty
})
it("renders an incomplete tag with primitive tag type", function () {
var root = mock.document.createElement("div")
m.render(root, m("ul", [m("li")]))
m.render(root, m("ul", [{tag: "b", attrs: {}}]))
expect(root.childNodes[0].childNodes[0].nodeName).to.equal("B")
})
it("renders an incomplete tag with String object tag type", function () {
var root = mock.document.createElement("div")
m.render(root, m("ul", [m("li")]))
/* eslint-disable no-new-wrappers */
m.render(root, m("ul", [{tag: new String("b"), attrs: {}}]))
/* eslint-enable no-new-wrappers */
expect(root.childNodes[0].childNodes[0].nodeName).to.equal("B")
})
it("renders the last tag when `subtree: \"retain\"`", function () {
var root = mock.document.createElement("div")
m.render(root, m("ul", [m("li", [m("a")])]))
m.render(root, m("ul", [{subtree: "retain"}]))
expect(root.childNodes[0].childNodes[0].childNodes[0].nodeName)
.to.equal("A")
})
// https://github.com/lhorie/mithril.js/issues/43
it("rerenders anchors correctly with mode abstraction (`config: m.route`)", function () { // eslint-disable-line
var root = mock.document.createElement("div")
m.render(root, m("a", {config: m.route}, "test"))
m.render(root, m("a", {config: m.route}, "test"))
expect(root.childNodes[0].childNodes[0].nodeValue).to.equal("test")
})
// https://github.com/lhorie/mithril.js/issues/45
it("replaces initial null with string", function () {
var root = mock.document.createElement("div")
m.render(root, m("#foo", [null, m("#bar")]))
m.render(root, m("#foo", ["test", m("#bar")]))
expect(root.childNodes[0].childNodes[0].nodeValue).to.equal("test")
})
// https://github.com/lhorie/mithril.js/issues/45
it("replaces initial null with node", function () {
var root = mock.document.createElement("div")
m.render(root, m("#foo", [null, m("#bar")]))
m.render(root, m("#foo", [m("div"), m("#bar")]))
expect(root.childNodes[0].childNodes[0].nodeName).to.equal("DIV")
})
// https://github.com/lhorie/mithril.js/issues/45
it("replaces initial string with node", function () {
var root = mock.document.createElement("div")
m.render(root, m("#foo", ["test", m("#bar")]))
m.render(root, m("#foo", [m("div"), m("#bar")]))
expect(root.childNodes[0].childNodes[0].nodeName).to.equal("DIV")
})
// https://github.com/lhorie/mithril.js/issues/45
it("replaces initial node with string", function () {
var root = mock.document.createElement("div")
m.render(root, m("#foo", [m("div"), m("#bar")]))
m.render(root, m("#foo", ["test", m("#bar")]))
expect(root.childNodes[0].childNodes[0].nodeValue).to.equal("test")
})
// https://github.com/lhorie/mithril.js/issues/45
it("adds new duplicate node", function () {
var root = mock.document.createElement("div")
m.render(root, m("#foo", [m("#bar")]))
m.render(root, m("#foo", [m("#bar"), [m("#baz")]]))
expect(root.childNodes[0].childNodes[1].id).to.equal("baz")
})
// https://github.com/lhorie/mithril.js/issues/48
it("renders from html when base is document", function () {
var root = mock.document
m.render(root, m("html", [m("#foo")]))
var result = root.childNodes[0].childNodes[0].id
// Have to clean up before assertion, or this will break other tests
root.childNodes = [mock.document.createElement("html")]
expect(result).to.equal("foo")
})
// https://github.com/lhorie/mithril.js/issues/49
it("reattaches cached text nodes to original parent (1)", function () {
var root = mock.document.createElement("div")
m.render(root, m("a", "test"))
m.render(root, m("a.foo", "test"))
expect(root.childNodes[0].childNodes[0].nodeValue).to.equal("test")
})
// https://github.com/lhorie/mithril.js/issues/49
it("reattaches cached text nodes to original parent (2)", function () {
var root = mock.document.createElement("div")
m.render(root, m("a.foo", "test"))
m.render(root, m("a", "test"))
expect(root.childNodes[0].childNodes[0].nodeValue).to.equal("test")
})
// https://github.com/lhorie/mithril.js/issues/49
it("reattaches cached text nodes to original parent (3)", function () {
var root = mock.document.createElement("div")
m.render(root, m("a.foo", "test"))
m.render(root, m("a", "test1"))
expect(root.childNodes[0].childNodes[0].nodeValue).to.equal("test1")
})
// https://github.com/lhorie/mithril.js/issues/49
it("reattaches cached text nodes to original parent (4)", function () {
var root = mock.document.createElement("div")
m.render(root, m("a", "test"))
m.render(root, m("a", "test1"))
expect(root.childNodes[0].childNodes[0].nodeValue).to.equal("test1")
})
// https://github.com/lhorie/mithril.js/issues/50
it("renders nested arrays correctly (1)", function () {
var root = mock.document.createElement("div")
m.render(root, m("#foo", [[m("div", "a"), m("div", "b")], m("#bar")]))
expect(root.childNodes[0].childNodes[1].childNodes[0].nodeValue)
.to.equal("b")
})
// https://github.com/lhorie/mithril.js/issues/50
it("renders nested arrays correctly (2)", function () {
var root = mock.document.createElement("div")
m.render(root, m("#foo", [
[m("div", "a"), m("div", "b")],
[m("div", "c"), m("div", "d")],
m("#bar")
]))
expect(root.childNodes[0].childNodes[3].childNodes[0].nodeValue)
.to.equal("d")
expect(root.childNodes[0].childNodes[4].id).to.equal("bar")
})
// https://github.com/lhorie/mithril.js/issues/50
it("renders nested arrays correctly (3)", function () {
var root = mock.document.createElement("div")
m.render(root, m("#foo", [[m("div", "a"), m("div", "b")], "test"]))
expect(root.childNodes[0].childNodes[1].childNodes[0].nodeValue)
.to.equal("b")
expect(root.childNodes[0].childNodes[2].nodeValue).to.equal("test")
})
// https://github.com/lhorie/mithril.js/issues/50
it("renders nested arrays correctly (4)", function () {
var root = mock.document.createElement("div")
m.render(root, m("#foo", [["a", "b"], "test"]))
expect(root.childNodes[0].childNodes[1].nodeValue).to.equal("b")
expect(root.childNodes[0].childNodes[2].nodeValue).to.equal("test")
})
// https://github.com/lhorie/mithril.js/issues/156
it("renders nested arrays correctly (5)", function () {
var root = mock.document.createElement("div")
m.render(root, m("div", [
["a", "b", "c", "d"].map(function () {
return [m("div"), " "]
}),
m("span")
]))
expect(root.childNodes[0].childNodes[8].nodeName).to.equal("SPAN")
})
// https://github.com/lhorie/mithril.js/issues/50
it("reconciles nested list differences correctly", function () {
var root = mock.document.createElement("div")
m.render(root, m("#foo", [[m("div", "a"), m("div", "b")], m("#bar")]))
m.render(root, m("#foo", [
[m("div", "a"), m("div", "b"), m("div", "c")],
m("#bar")
]))
expect(root.childNodes[0].childNodes[2].childNodes[0].nodeValue)
.to.equal("c")
})
// https://github.com/lhorie/mithril.js/issues/51
it("reconciles nested node differences correctly (1)", function () {
var root = mock.document.createElement("div")
m.render(root, m("main", [
m("button"),
m("article", [m("section"), m("nav")])
]))
m.render(root, m("main", [
m("button"),
m("article", [m("span"), m("nav")])
]))
expect(root.childNodes[0].childNodes[1].childNodes[0].nodeName)
.to.equal("SPAN")
})
// https://github.com/lhorie/mithril.js/issues/51
it("reconciles nested node differences correctly (2)", function () {
var root = mock.document.createElement("div")
m.render(root, m("main", [
m("button"),
m("article", [m("section"), m("nav")])
]))
m.render(root, m("main", [
m("button"),
m("article", ["test", m("nav")])
]))
expect(root.childNodes[0].childNodes[1].childNodes[0].nodeValue)
.to.equal("test")
})
// https://github.com/lhorie/mithril.js/issues/51
it("reconciles nested node differences correctly (3)", function () {
var root = mock.document.createElement("div")
m.render(root, m("main", [
m("button"),
m("article", [m("section"), m("nav")])
]))
m.render(root, m("main", [
m("button"),
m("article", [m.trust("test"), m("nav")])
]))
expect(root.childNodes[0].childNodes[1].childNodes[0].nodeValue)
.to.equal("test")
})
// https://github.com/lhorie/mithril.js/issues/55
it("redraws when id attrs are different", function () {
var root = mock.document.createElement("div")
m.render(root, m("#a"))
var elementBefore = root.childNodes[0]
m.render(root, m("#b"))
expect(root.childNodes[0]).to.not.equal(elementBefore)
})
// https://github.com/lhorie/mithril.js/issues/56
it("doesn't duplicate with a preceding null element", function () {
var root = mock.document.createElement("div")
m.render(root, [null, "foo"])
m.render(root, ["bar"])
expect(root.childNodes).to.have.length(1)
})
// https://github.com/lhorie/mithril.js/issues/56
it("doesn't duplicate with a preceding element with same tag name", function () { // eslint-disable-line
var root = mock.document.createElement("div")
m.render(root, m("div", "foo"))
expect(root.childNodes).to.have.length(1)
})
it("removes single `undefined` child node in place", function () {
var root = mock.document.createElement("div")
m.render(root, m("div", [m("button"), m("ul")]))
expect(root.childNodes[0].childNodes[0])
.to.have.property("nodeName", "BUTTON")
m.render(root, m("div", [undefined, m("ul")]))
expect(root.childNodes[0].childNodes[0])
.to.have.property("nodeValue", "")
})
it("removes multiple `undefined` nodes in place", function () {
var root = mock.document.createElement("div")
m.render(root, m("div", [m("ul"), undefined]))
expect(root.childNodes[0].childNodes[0])
.to.have.property("nodeName", "UL")
expect(root.childNodes[0].childNodes[1])
.to.have.property("nodeValue", "")
m.render(root, m("div", [undefined, m("ul")]))
expect(root.childNodes[0].childNodes[0])
.to.have.property("nodeValue", "")
expect(root.childNodes[0].childNodes[1])
.to.have.property("nodeName", "UL")
})
// https://github.com/lhorie/mithril.js/issues/79
it("changes the style when specified in the node", function () {
var root = mock.document.createElement("div")
m.render(root, m("div", {style: {background: "red"}}))
expect(root.childNodes[0].style).to.have.property("background", "red")
m.render(root, m("div", {style: {}}))
expect(root.childNodes[0].style).to.have.property("background", "")
})
it("reads styles from syntax", function () {
var root = mock.document.createElement("div")
m.render(root, m("div[style='background:red']"))
expect(root.childNodes[0].style).to.equal("background:red")
})
it("removes styles when not passed", function () {
var root = mock.document.createElement("div")
m.render(root, m("div", {style: {background: "red"}}))
expect(root.childNodes[0].style.background).to.equal("red")
m.render(root, m("div", {}))
expect(root.childNodes[0].style.background).to.not.exist
})
// https://github.com/lhorie/mithril.js/issues/87
it("removes correct number of elements from nested lists (1)", function () {
var root = mock.document.createElement("div")
m.render(root, m("div", [[m("a"), m("a")], m("button")]))
m.render(root, m("div", [[m("a")], m("button")]))
expect(root.childNodes[0].childNodes).to.have.length(2)
expect(root.childNodes[0].childNodes[1])
.to.have.property("nodeName", "BUTTON")
})
// https://github.com/lhorie/mithril.js/issues/87
it("removes correct number of elements from nested lists (2)", function () {
var root = mock.document.createElement("div")
m.render(root, m("div", [m("a"), m("b"), m("button")]))
m.render(root, m("div", [m("a"), m("button")]))
expect(root.childNodes[0].childNodes).to.have.length(2)
expect(root.childNodes[0].childNodes[1])
.to.have.property("nodeName", "BUTTON")
})
// https://github.com/lhorie/mithril.js/issues/99
it("removes correct number of elements from nested lists (3)", function () {
var root = mock.document.createElement("div")
m.render(root, m("div", [m("img"), m("h1")]))
m.render(root, m("div", [m("a")]))
expect(root.childNodes[0].childNodes).to.have.length(1)
expect(root.childNodes[0].childNodes[0])
.to.have.property("nodeName", "A")
})
// https://github.com/lhorie/mithril.js/issues/120
it("avoids duplication in nested arrays (1)", function () {
var root = mock.document.createElement("div")
m.render(root, m("div", ["a", "b", "c", "d"]))
m.render(root, m("div", [["d", "e"]]))
var children = root.childNodes[0].childNodes
expect(children).to.have.length(2)
expect(children[0]).to.have.property("nodeValue", "d")
expect(children[1]).to.have.property("nodeValue", "e")
})
// https://github.com/lhorie/mithril.js/issues/120
it("avoids duplication in nested arrays (2)", function () {
var root = mock.document.createElement("div")
m.render(root, m("div", [["a", "b", "c", "d"]]))
m.render(root, m("div", ["d", "e"]))
var children = root.childNodes[0].childNodes
expect(children).to.have.length(2)
expect(children[0]).to.have.property("nodeValue", "d")
expect(children[1]).to.have.property("nodeValue", "e")
})
// https://github.com/lhorie/mithril.js/issues/120
it("avoids duplication in nested arrays (3)", function () {
var root = mock.document.createElement("div")
m.render(root, m("div", ["x", [["a"], "b", "c", "d"]]))
m.render(root, m("div", ["d", ["e"]]))
var children = root.childNodes[0].childNodes
expect(children).to.have.length(2)
expect(children[0]).to.have.property("nodeValue", "d")
expect(children[1]).to.have.property("nodeValue", "e")
})
// https://github.com/lhorie/mithril.js/issues/120
it("avoids duplication in nested arrays (4)", function () {
var root = mock.document.createElement("div")
m.render(root, m("div", ["b"]))
m.render(root, m("div", [["e"]]))
var children = root.childNodes[0].childNodes
expect(children).to.have.length(1)
expect(children[0]).to.have.property("nodeValue", "e")
})
// https://github.com/lhorie/mithril.js/issues/120
it("avoids duplication in nested arrays (5)", function () {
var root = mock.document.createElement("div")
m.render(root, m("div", ["a", ["b"]]))
m.render(root, m("div", ["d", [["e"]]]))
var children = root.childNodes[0].childNodes
expect(children).to.have.length(2)
expect(children[0]).to.have.property("nodeValue", "d")
expect(children[1]).to.have.property("nodeValue", "e")
})
// https://github.com/lhorie/mithril.js/issues/120
it("avoids duplication in nested arrays (6)", function () {
var root = mock.document.createElement("div")
m.render(root, m("div", ["a", [["b"]]]))
m.render(root, m("div", ["d", ["e"]]))
var children = root.childNodes[0].childNodes
expect(children).to.have.length(2)
expect(children[0]).to.have.property("nodeValue", "d")
expect(children[1]).to.have.property("nodeValue", "e")
})
// https://github.com/lhorie/mithril.js/issues/120
it("avoids duplication in nested arrays (7)", function () {
var root = mock.document.createElement("div")
m.render(root, m("div", ["a", [["b"], "c"]]))
m.render(root, m("div", ["d", [[["e"]], "x"]]))
var children = root.childNodes[0].childNodes
expect(children).to.have.length(3)
expect(children[0]).to.have.property("nodeValue", "d")
expect(children[1]).to.have.property("nodeValue", "e")
})
it("honors setting context properties in stateful config", function () {
var root = mock.document.createElement("div")
var config = sinon.spy()
m.render(root, m("div", {
config: function (el, init, ctx) { ctx.data = 1 }
}))
m.render(root, m("div", {config: config}))
expect(config.firstCall.args[2]).to.have.property("data", 1)
})
it("calls configs in order, first to last", function () {
var root = mock.document.createElement("div")
var config = sinon.spy()
var index = 0
var node = m("div", {
config: function (el, init, ctx) { ctx.data = index++ }
})
m.render(root, [node, node])
node = m("div", {config: config})
m.render(root, [node, node])
expect(config).to.have.been.called
config.args.forEach(function (args, i) {
expect(args[2]).to.have.property("data", i)
})
})
it("passes the correct node as the element", function () {
var root = mock.document.createElement("div")
var spy = sinon.spy()
m.render(root, m("div", m("a", {config: spy})))
expect(spy).to.have.been.calledWith(root.childNodes[0].childNodes[0])
})
it("does not recursively call the config if a separate node is rendered to", function () { // eslint-disable-line
var root = mock.document.createElement("div")
var spy = sinon.spy(function () {
var island = mock.document.createElement("div")
m.render(island, m("div"))
})
m.render(root, m("div", m("a", {config: spy})))
expect(spy).to.be.calledOnce
})
// https://github.com/lhorie/mithril.js/issues/129
it("does not throw replacing arrays with single entries", function () {
var root = mock.document.createElement("div")
expect(function () {
m.render(root, m("div", [
["foo", "bar"],
["foo", "bar"],
["foo", "bar"]
]))
m.render(root, m("div", ["asdf", "asdf2", "asdf3"]))
}).to.not.throw()
})
// https://github.com/lhorie/mithril.js/issues/98
it("correctly keeps key association to nodes (1)", function () {
// insert at beginning
var root = mock.document.createElement("div")
m.render(root, [
m("a", {key: 1}, 1),
m("a", {key: 2}, 2),
m("a", {key: 3}, 3)
])
var firstBefore = root.childNodes[0]
m.render(root, [
m("a", {key: 4}, 4),
m("a", {key: 1}, 1),
m("a", {key: 2}, 2),
m("a", {key: 3}, 3)
])
var firstAfter = root.childNodes[1]
expect(firstBefore).to.equal(firstAfter)
expect(root.childNodes[0].childNodes[0])
.to.have.property("nodeValue", "4")
expect(root.childNodes).to.have.length(4)
})
// https://github.com/lhorie/mithril.js/issues/98
it("correctly keeps key association to nodes (2)", function () {
var root = mock.document.createElement("div")
m.render(root, [
m("a", {key: 1}, 1),
m("a", {key: 2}, 2),
m("a", {key: 3}, 3)
])
var firstBefore = root.childNodes[0]
m.render(root, [
m("a", {key: 4}, 4),
m("a", {key: 1}, 1),
m("a", {key: 2}, 2)
])
var firstAfter = root.childNodes[1]
expect(firstBefore).to.equal(firstAfter)
expect(root.childNodes[0].childNodes[0])
.to.have.property("nodeValue", "4")
expect(root.childNodes).to.have.length(3)
})
// https://github.com/lhorie/mithril.js/issues/98
it("correctly keeps key association to nodes (3)", function () {
var root = mock.document.createElement("div")
m.render(root, [
m("a", {key: 1}, 1),
m("a", {key: 2}, 2),
m("a", {key: 3}, 3)
])
var firstBefore = root.childNodes[1]
m.render(root, [
m("a", {key: 2}, 2),
m("a", {key: 3}, 3),
m("a", {key: 4}, 4)
])
var firstAfter = root.childNodes[0]
expect(firstBefore).to.equal(firstAfter)
expect(root.childNodes[0].childNodes[0])
.to.have.property("nodeValue", "2")
expect(root.childNodes).to.have.length(3)
})
// https://github.com/lhorie/mithril.js/issues/98
it("correctly keeps key association to nodes (4)", function () {
var root = mock.document.createElement("div")
m.render(root, [
m("a", {key: 1}, 1),
m("a", {key: 2}, 2),
m("a", {key: 3}, 3),
m("a", {key: 4}, 4),
m("a", {key: 5}, 5)
])
var firstBefore = root.childNodes[0]
var secondBefore = root.childNodes[1]
var fourthBefore = root.childNodes[3]
m.render(root, [
m("a", {key: 4}, 4),
m("a", {key: 10}, 10),
m("a", {key: 1}, 1),
m("a", {key: 2}, 2)
])
var firstAfter = root.childNodes[2]
var secondAfter = root.childNodes[3]
var fourthAfter = root.childNodes[0]
expect(firstBefore).to.equal(firstAfter)
expect(secondBefore).to.equal(secondAfter)
expect(fourthBefore).to.equal(fourthAfter)
expect(root.childNodes[1].childNodes[0].nodeValue).to.equal("10")
expect(root.childNodes).to.have.length(4)
})
// https://github.com/lhorie/mithril.js/issues/98
it("correctly keeps key association to nodes (5)", function () {
var root = mock.document.createElement("div")
m.render(root, [
m("a", {key: 1}, 1),
m("a", {key: 2}, 2),
m("a", {key: 3}, 3),
m("a", {key: 4}, 4),
m("a", {key: 5}, 5)
])
var firstBefore = root.childNodes[0]
var secondBefore = root.childNodes[1]
var fourthBefore = root.childNodes[3]
m.render(root, [
m("a", {key: 4}, 4),
m("a", {key: 10}, 10),
m("a", {key: 2}, 2),
m("a", {key: 1}, 1),
m("a", {key: 6}, 6),
m("a", {key: 7}, 7)
])
var firstAfter = root.childNodes[3]
var secondAfter = root.childNodes[2]
var fourthAfter = root.childNodes[0]
expect(firstBefore).to.equal(firstAfter)
expect(secondBefore).to.equal(secondAfter)
expect(fourthBefore).to.equal(fourthAfter)
expect(root.childNodes[1].childNodes[0].nodeValue).to.equal("10")
expect(root.childNodes[4].childNodes[0].nodeValue).to.equal("6")
expect(root.childNodes[5].childNodes[0].nodeValue).to.equal("7")
expect(root.childNodes).to.have.length(6)
})
// https://github.com/lhorie/mithril.js/issues/149
it("correctly keeps key association to nodes (6)", function () {
var root = mock.document.createElement("div")
m.render(root, [
m("a", {key: 1}),
m("a", {key: 2}),
m("a"),
m("a", {key: 4}),
m("a", {key: 5})
])
var firstBefore = root.childNodes[0]
var secondBefore = root.childNodes[1]
var thirdBefore = root.childNodes[2]
var fourthBefore = root.childNodes[3]
var fifthBefore = root.childNodes[4]
m.render(root, [
m("a", {key: 4}),
m("a", {key: 5}),
m("a"),
m("a", {key: 1}),
m("a", {key: 2})
])
var firstAfter = root.childNodes[3]
var secondAfter = root.childNodes[4]
var thirdAfter = root.childNodes[2]
var fourthAfter = root.childNodes[0]
var fifthAfter = root.childNodes[1]
expect(firstBefore).to.equal(firstAfter)
expect(secondBefore).to.equal(secondAfter)
expect(thirdBefore).to.equal(thirdAfter)
expect(fourthBefore).to.equal(fourthAfter)
expect(fifthBefore).to.equal(fifthAfter)
})
// https://github.com/lhorie/mithril.js/issues/246
it("correctly renders non-keyed objects in the middle", function () {
var root = mock.document.createElement("div")
m.render(root, [m("a", {key: 1}, 1)])
var firstBefore = root.childNodes[0]
m.render(root, [m("a", {key: 2}, 2), m("br"), m("a", {key: 1}, 1)])
var firstAfter = root.childNodes[2]
expect(firstBefore).to.equal(firstAfter)
expect(root.childNodes[0].childNodes[0].nodeValue).to.equal("2")
expect(root.childNodes.length).to.equal(3)
})
// https://github.com/lhorie/mithril.js/issues/134
it("doesn't redraw when updating contenteditable", function () {
var root = mock.document.createElement("div")
m.render(root, m("div", {contenteditable: true}, "test"))
mock.document.activeElement = root.childNodes[0]
m.render(root, m("div", {contenteditable: true}, "test1"))
m.render(root, m("div", {contenteditable: false}, "test2"))
expect(root.childNodes[0].childNodes[0].nodeValue).to.equal("test2")
})
// https://github.com/lhorie/mithril.js/issues/136
it("redraws when a textarea updates its values", function () {
var root = mock.document.createElement("div")
m.render(root, m("textarea", ["test"]))
m.render(root, m("textarea", ["test1"]))
expect(root.childNodes[0].value).to.equal("test1")
})
it("doesn't call onunload when matching keys are given", function () {
var root = mock.document.createElement("div")
var spy = sinon.spy()
m.render(root, [
m("div", {
key: 1,
config: function (el, init, ctx) {
ctx.onunload = spy
}
})
])
m.render(root, [
m("div", {key: 2}),
m("div", {
key: 1,
config: function (el, init, ctx) {
ctx.onunload = spy
}
})
])
expect(spy).to.not.have.been.called
})
it("unloads the parent but not child, when parent changes and not child", function () { // eslint-disable-line
var root = mock.document.createElement("div")
var parentSpy = sinon.spy()
var childSpy = sinon.spy()
function parent(el, init, ctx) {
ctx.onunload = parentSpy
}
function child(el, init, ctx) {
ctx.onunload = childSpy
}
m.render(root, m("div", {config: parent}, m("a", {config: child})))
m.render(root, m("main", {config: parent}, m("a", {config: child})))
expect(parentSpy).to.be.calledOnce
expect(childSpy).to.not.have.been.called
})
it("unloads parent and child when both change", function () {
var root = mock.document.createElement("div")
var parentSpy = sinon.spy()
var childSpy = sinon.spy()
function parent(el, init, ctx) {
ctx.onunload = parentSpy
}
function child(el, init, ctx) {
ctx.onunload = childSpy
}
m.render(root, m("div", {config: parent}, m("a", {config: child})))
m.render(root, m("main", {config: parent}, m("b", {config: child})))
expect(parentSpy).to.have.been.calledOnce
expect(childSpy).to.have.been.calledOnce
})
// https://github.com/lhorie/mithril.js/issues/150
it("treats empty arrays similarly to `null` and `undefined`", function () {
var root = mock.document.createElement("div")
m.render(root, [m("a"), m("div")])
m.render(root, [[], m("div")])
expect(root.childNodes.length).to.equal(1)
expect(root.childNodes[0].nodeName).to.equal("DIV")
})
// https://github.com/lhorie/mithril.js/issues/157
it("renders nodes with new keys correctly", function () {
var root = mock.document.createElement("div")
m.render(root, m("ul", [
m("li", {key: 0}, 0),
m("li", {key: 2}, 2),
m("li", {key: 4}, 4)
]))
m.render(root, m("ul", [
m("li", {key: 0}, 0),
m("li", {key: 1}, 1),
m("li", {key: 2}, 2),
m("li", {key: 3}, 3),
m("li", {key: 4}, 4),
m("li", {key: 5}, 5)
]))
expect(
root.childNodes[0].childNodes.map(function (n) {
return n.childNodes[0].nodeValue
})
).to.eql(["0", "1", "2", "3", "4", "5"])
})
// https://github.com/lhorie/mithril.js/issues/157
it("doesn't render extra child nodes if none are given (1)", function () {
var root = mock.document.createElement("div")
m.render(root, m("input", {value: "a"}))
m.render(root, m("input", {value: "aa"}))
expect(root.childNodes[0].childNodes).to.be.empty
})
// https://github.com/lhorie/mithril.js/issues/157
it("doesn't render extra child nodes if none are given (2)", function () {
var root = mock.document.createElement("div")
m.render(root, m("br", {class: "a"}))
m.render(root, m("br", {class: "aa"}))
expect(root.childNodes[0].childNodes).to.be.empty
})
// https://github.com/lhorie/mithril.js/issues/194
it("removes removed contained keyed elements from DOM", function () {
var root = mock.document.createElement("div")
m.render(root, m("ul", [
m("li", {key: 0}, 0),
m("li", {key: 1}, 1),
m("li", {key: 2}, 2),
m("li", {key: 3}, 3),
m("li", {key: 4}, 4),
m("li", {key: 5}, 5)
]))
m.render(root, m("ul", [
m("li", {key: 0}, 0),
m("li", {key: 1}, 1),
m("li", {key: 2}, 2),
m("li", {key: 4}, 4),
m("li", {key: 5}, 5)
]))
expect(
root.childNodes[0].childNodes.map(function (n) {
return n.childNodes[0].nodeValue
})
).to.eql(["0", "1", "2", "4", "5"])
})
// https://github.com/lhorie/mithril.js/issues/194
it("removes removed list of keyed elements from DOM", function () {
var root = mock.document.createElement("div")
m.render(root, m("ul", [
m("li", {key: 0}, 0),
m("li", {key: 1}, 1),
m("li", {key: 2}, 2),
m("li", {key: 3}, 3),
m("li", {key: 4}, 4),
m("li", {key: 5}, 5)
]))
m.render(root, m("ul", [
m("li", {key: 1}, 1),
m("li", {key: 2}, 2),
m("li", {key: 3}, 3),
m("li", {key: 4}, 4),
m("li", {key: 5}, 5),
m("li", {key: 6}, 6)
]))
m.render(root, m("ul", [
m("li", {key: 12}, 12),
m("li", {key: 13}, 13),
m("li", {key: 14}, 14),
m("li", {key: 15}, 15),
m("li", {key: 16}, 16),
m("li", {key: 17}, 17)
]))
expect(
root.childNodes[0].childNodes.map(function (n) {
return n.childNodes[0].nodeValue
})
).to.eql(["12", "13", "14", "15", "16", "17"])
})
// https://github.com/lhorie/mithril.js/issues/206
it("removes `undefined` children", function () {
var root = mock.document.createElement("div")
m.render(root, m("div", undefined))
m.render(root, m("div", [m("div")]))
expect(root.childNodes[0].childNodes).to.have.length(1)
})
// https://github.com/lhorie/mithril.js/issues/206
it("removes `null` children", function () {
var root = mock.document.createElement("div")
m.render(root, m("div", null))
m.render(root, m("div", [m("div")]))
expect(root.childNodes[0].childNodes).to.have.length(1)
})
// https://github.com/lhorie/mithril.js/issues/200
it("calls onunload when updating a rendered collection", function () {
var root = mock.document.createElement("div")
var onunload1 = sinon.spy()
var onunload2 = sinon.spy()
m.render(root, [m("div", {
config: function (el, init, ctx) {
ctx.onunload = onunload1
}
})])
m.render(root, [])
m.render(root, [m("div", {
config: function (el, init, ctx) {
ctx.onunload = onunload2
}
})])
m.render(root, [])
expect(onunload1).to.be.called
expect(onunload2).to.be.called
})
it("should prepend new DOM elements", function () {
var root = mock.document.createElement("div")
m.render(root, [m("div.blue")])
m.render(root, [
m("div.green", [m("div")]),
m("div.blue")
])
expect(root.childNodes).to.have.length(2)
})
// https://github.com/lhorie/mithril.js/issues/277
it("adds objects that look like virtual nodes", function () {
var root = mock.document.createElement("div")
function Field() {
this.tag = "div"
this.attrs = {}
this.children = "hello"
}
m.render(root, new Field())
expect(root.childNodes).to.have.length(1)
})
it("doesn't add objects that don't look like virtual nodes", function () {
var root = mock.document.createElement("div")
m.render(root, {foo: 123})
expect(root.childNodes).to.have.length(0)
})
// https://github.com/lhorie/mithril.js/issues/299
it("retains key order in the presence of `null`s (1)", function () {
var root = mock.document.createElement("div")
m.render(root, m("div", [
m("div", {key: 1}, 1),
m("div", {key: 2}, 2),
m("div", {key: 3}, 3),
m("div", {key: 4}, 4),
m("div", {key: 5}, 5),
null, null, null, null, null, null, null, null, null, null
]))
m.render(root, m("div", [
null, null,
m("div", {key: 3}, 3),
null, null,
m("div", {key: 6}, 6),
null, null,
m("div", {key: 9}, 9),
null, null,
m("div", {key: 12}, 12),
null, null,
m("div", {key: 15}, 15)
]))
m.render(root, m("div", [
m("div", {key: 1}, 1),
m("div", {key: 2}, 2),
m("div", {key: 3}, 3),
m("div", {key: 4}, 4),
m("div", {key: 5}, 5),
null, null, null, null, null, null, null, null, null, null
]))
expect(
root.childNodes[0].childNodes.map(function (c) {
return c.childNodes ? c.childNodes[0].nodeValue : c.nodeValue
}).slice(0, 5)
).to.eql(["1", "2", "3", "4", "5"])
})
// https://github.com/lhorie/mithril.js/issues/299
// https://github.com/lhorie/mithril.js/issues/377
it("retains key order in the presence of `null`s (2)", function () {
var root = mock.document.createElement("div")
m.render(root, m("div", [
m("div", 1),
m("div", 2),
[
m("div", {key: 3}, 3),
m("div", {key: 4}, 4),
m("div", {key: 5}, 5)
],
[m("div", {key: 6}, 6)]
]))
m.render(root, m("div", [
m("div", 1),
null,
[
m("div", {key: 3}, 3),
m("div", {key: 4}, 4),
m("div", {key: 5}, 5)
],
[m("div", {key: 6}, 6)]
]))
expect(
root.childNodes[0].childNodes.map(function (c) {
return c.childNodes ? c.childNodes[0].nodeValue : c.nodeValue
})
).to.eql(["1", "", "3", "4", "5", "6"])
})
it("doesn't throw trying to render result of console.log()", function () {
var root = mock.document.createElement("div")
expect(function () {
/* eslint-disable no-console */
m.render(root, m("div", [console.log()]))
/* eslint-enable no-console */
}).to.not.throw()
})
it("retains key order for ids", function () {
var root = mock.document.createElement("div")
m.render(root, [
m("#div-1", {key: 1}),
m("#div-2", {key: 2}),
m("#div-3", {key: 3})
])
root.appendChild(root.childNodes[1])
m.render(root, [
m("#div-1", {key: 1}),
m("#div-3", {key: 3}),
m("#div-2", {key: 2})
])
expect(
root.childNodes.map(function (node) { return node.id })
).to.eql(["div-1", "div-3", "div-2"])
})
it("doesn't render functions as nodes", function () {
var root = mock.document.createElement("div")
m.render(root, m("div", function () {}))
expect(root.childNodes[0].childNodes).to.have.length(0)
})
it("removes nodes that result in only a single text node", function () {
var root = mock.document.createElement("div")
m.render(root, m("div", "foo", m("a")))
m.render(root, m("div", "test"))
expect(root.childNodes[0].childNodes).to.have.length(1)
})
it("keeps identity if the element is preceded by conditional", function () {
var root = mock.document.createElement("div")
m.render(root, m("div", [m("a"), m("input[autofocus]")]))
var before = root.childNodes[0].childNodes[1]
m.render(root, m("div", [undefined, m("input[autofocus]")]))
var after = root.childNodes[0].childNodes[1]
expect(before).to.equal(after)
})
it("keeps unkeyed identity if mixed with keyed elements and identity can be inferred", function () { // eslint-disable-line
var root = mock.document.createElement("div")
m.render(root, m("div", [
m("a", {key: 1}),
m("a", {key: 2}),
m("a", {key: 3}),
m("i")
]))
var before = root.childNodes[0].childNodes[3]
m.render(root, m("div", [
m("b", {key: 3}),
m("b", {key: 4}),
m("i"),
m("b", {key: 1})
]))
var after = root.childNodes[0].childNodes[2]
expect(before).to.equal(after)
})
it("keeps unkeyed identity if mixed with keyed/text elements and identity can be inferred", function () { // eslint-disable-line
var root = mock.document.createElement("div")
m.render(root, m("div", [
m("a", {key: 1}),
m("a", {key: 2}),
"foo",
m("a", {key: 3}),
m("i")
]))
var before = root.childNodes[0].childNodes[4]
m.render(root, m("div", [
m("a", {key: 3}),
m("a", {key: 4}),
"bar",
m("i"),
m("a", {key: 1})
]))
var after = root.childNodes[0].childNodes[3]
expect(before).to.equal(after)
})
it("keeps unkeyed identity if mixed with elements/nulls and identity can be inferred", function () { // eslint-disable-line
var root = mock.document.createElement("div")
m.render(root, m("div", [
m("a", {key: 1}),
m("a", {key: 2}),
null,
m("a", {key: 3}),
m("i")
]))
var before = root.childNodes[0].childNodes[4]
m.render(root, m("div", [
m("a", {key: 3}),
m("a", {key: 4}),
null,
m("i"),
m("a", {key: 1})
]))
var after = root.childNodes[0].childNodes[3]
expect(before).to.equal(after)
})
it("keeps unkeyed identity if mixed with elements/undefined and identity can be inferred", function () { // eslint-disable-line
var root = mock.document.createElement("div")
m.render(root, m("div", [
m("a", {key: 1}),
m("a", {key: 2}),
undefined,
m("a", {key: 3}),
m("i")
]))
var before = root.childNodes[0].childNodes[4]
m.render(root, m("div", [
m("a", {key: 3}),
m("a", {key: 4}),
undefined,
m("i"),
m("a", {key: 1})
]))
var after = root.childNodes[0].childNodes[3]
expect(before).to.equal(after)
})
// FIXME: implement document.createRange().createContextualFragment() in the
// mock document to fix this test
it("keeps unkeyed identity if mixed with elements/trusted text and identity can be inferred", function () { // eslint-disable-line
var root = mock.document.createElement("div")
m.render(root, m("div", [
m("a", {key: 1}),
m("a", {key: 2}),
m.trust("a"),
m("a", {key: 3}),
m("i")
]))
var before = root.childNodes[0].childNodes[4]
m.render(root, m("div", [
m("a", {key: 3}),
m("a", {key: 4}),
m.trust("a"),
m("i"),
m("a", {key: 1})
]))
var after = root.childNodes[0].childNodes[3]
expect(before).to.equal(after)
})
it("uses the syntax class if it's given as `undefined` in attr", function () { // eslint-disable-line
var root = mock.document.createElement("div")
var vdom = m("div.a", {class: undefined})
m.render(root, vdom)
expect(root.childNodes[0].class).to.equal("a")
})
it("updates div with syntax class and removed body", function () {
var root = mock.document.createElement("div")
m.render(root, m(".a", [1]))
m.render(root, m(".a", []))
expect(root.childNodes[0].childNodes).to.have.length(0)
})
it("renders removed elements in div with empty attrs correctly", function () { // eslint-disable-line
var root = mock.document.createElement("div")
m.render(root, m("div", {}, [
m("div", {}, "0"),
m("div", {}, "1"),
m("div", {}, "2")
]))
expect(
root.childNodes[0].childNodes.map(function (node) {
return node.childNodes[0].nodeValue
})
).to.eql(["0", "1", "2"])
m.render(root, m("div", {}, [
m("div", {}, "0")
]))
expect(
root.childNodes[0].childNodes.map(function (node) {
return node.childNodes[0].nodeValue
})
).to.eql(["0"])
})
it("renders removed elements in span with empty attrs correctly", function () { // eslint-disable-line
var root = mock.document.createElement("div")
m.render(root, m("span", {}, [
m("div", {}, "0"),
m("div", {}, "1"),
m("div", {}, "2")
]))
expect(
root.childNodes[0].childNodes.map(function (node) {
return node.childNodes[0].nodeValue
})
).to.eql(["0", "1", "2"])
m.render(root, m("span", {}, [
m("div", {}, "0")
]))
expect(
root.childNodes[0].childNodes.map(function (node) {
return node.childNodes[0].nodeValue
})
).to.eql(["0"])
})
function emit(el, ev) {
el[ev]({currentTarget: el})
}
// https://github.com/lhorie/mithril.js/issues/214
it("keeps all input events", function () {
var root = mock.document.createElement("div")
var ctrl = m.mount(root, {
controller: function () {
this.inputValue = m.prop("")
},
view: function (ctrl) {
return m("input", {
value: ctrl.inputValue(),
onkeyup: m.withAttr("value", ctrl.inputValue)
})
}
})
mock.requestAnimationFrame.$resolve()
var input = mock.document.activeElement = root.childNodes[0]
var expected = ""
var keys = "0123456789abcdef"
function writeKey(key) {
input.value += key[0]
emit(input, "onkeyup")
mock.requestAnimationFrame.$resolve()
}
for (var i = 0; i < 4; i++) {
expected += keys
keys.split("").forEach(writeKey)
}
expect(ctrl.inputValue()).to.equal(expected)
expect(input.value).to.equal(expected)
mock.document.activeElement = null
})
// https://github.com/lhorie/mithril.js/issues/288
it("doesn't reset if the input value is submitted with <enter>", function () { // eslint-disable-line
var root = mock.document.createElement("div")
var ctrl = m.mount(root, {
controller: function () {
this.inputValue = m.prop("")
this.submit = function () {
if (this.inputValue()) {
this.inputValue("")
}
}.bind(this)
},
view: function (ctrl) {
return m("form", {onsubmit: ctrl.submit}, [
m("input", {
onkeyup: m.withAttr("value", ctrl.inputValue),
value: ctrl.inputValue()
}),
m("button[type=submit]")
])
}
})
var form = root.childNodes[0]
var input = mock.document.activeElement = form.childNodes[0]
function writeKey(key) {
if (key === "[enter]") {
emit(form, "onsubmit")
} else {
input.value += key[0]
emit(input, "onkeyup")
}
mock.requestAnimationFrame.$resolve()
}
writeKey("a")
writeKey("b")
writeKey("c")
writeKey("d")
writeKey("[enter]")
expect(ctrl.inputValue()).to.equal("")
expect(input.value).to.equal("")
mock.document.activeElement = null
})
// https://github.com/lhorie/mithril.js/issues/278
it("renders multiple select correctly", function () {
var root = mock.document.createElement("div")
m.mount(root, {
controller: function () {
this.values = [1, 2, 3, 4, 5]
this.value = m.prop([2, 3])
},
view: function (ctrl) {
return m("select", {
size: ctrl.values.length,
multiple: "multiple"
}, [
ctrl.values.map(function (v) {
var opts = {value: v}
if (ctrl.value().indexOf(v) !== -1) {
opts.selected = "selected"
}
return m("option", opts, v)
})
])
}
})
mock.requestAnimationFrame.$resolve()
var select = root.childNodes[0]
expect(select.childNodes[0].selected).to.not.be.ok
expect(select.childNodes[1].selected).to.be.ok
expect(select.childNodes[2].selected).to.be.ok
expect(select.childNodes[3].selected).to.not.be.ok
expect(select.childNodes[4].selected).to.not.be.ok
})
it("doesn't treat 0 as an empty string", function () {
var root = mock.document.createElement("div")
m.render(root, m("div", {class: ""}))
m.render(root, m("div", {class: 0}))
expect(root.childNodes[0].class).to.equal("0")
})
dom(function () {
it("renders empty `value` in <option> as an existing attribute", function () { // eslint-disable-line
var root = document.createElement("div")
m.render(root, m("select", m("option", {value: ""}, "aaa")))
expect(root.childNodes[0].innerHTML)
.to.equal('<option value="">aaa</option>')
})
})
})