Details: 1. All tests now live in `test`. All test dependencies that aren't from npm live in `test-deps`. 2. The QUnit tests are gone, as well as their dependencies. Half of them duplicated existing tests, and some of them depended on the real DOM to properly test. 3. All tests are now using Mocha to run the tests, Chai for assertions, and Sinon and Sinon Chai for testing some callbacks. 4. Tests are run through mocha-phantomjs. If you want to run just the tests, run `grunt mocha_phantomjs` or fire up a server in the root and open `http://localhost:<port>/test/index.html`, e.g. `python3 -m http.server`. 5. The linter I chose is ESLint. It is relatively easy to configure, but with a lot of flexibility. The rules I chose mostly were in tune to the style the project was already using. I'm not including a style guide in this commit, but one will likely come. You can check out the `.eslintrc` in the root and in `test/` for the two configs. The `.eslintignore` includes a TODO for `mithril.js` itself targeted at me, in the root. Other info: - As a drive-by fix, I fixed line endings on a few of the files. - I also took care of a few other files and linted them as I went: - `Gruntfile.js` - `test/input-cursor.html` (was in `tests/`) - `test/svg.html` (was in `tests/`) - `docs/layout/tools/template-converter.html` - `docs/layout/tools/template-converter.js` I didn't test the template converter after linting it, because it needs further scrutiny to ensure it works with the latest version of Mithril. I know the API has changed a little, which is why I want to be sure. - I simplified the `.travis.yml` file because none of the tests are run directly through Node anymore. They are always run in a browser of some kind. Hopefully, this turned out all right...
1554 lines
44 KiB
JavaScript
1554 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
|
|
xit("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>')
|
|
})
|
|
})
|
|
})
|