v0.2.2-rc.1

This commit is contained in:
Leo Horie 2015-12-20 09:14:28 -05:00
parent 484a9d6c70
commit 270b20a2b0
110 changed files with 17357 additions and 3070 deletions

View file

@ -5,9 +5,8 @@
<!-- Dependencies -->
<script src="../node_modules/chai/chai.js"></script>
<script src="../node_modules/chai-string/chai-string.js"></script>
<script src="../node_modules/sinon/pkg/sinon.js"></script>
<script src="../node_modules/sinon-chai/lib/sinon-chai.js"></script>
<script src="../node_modules/sinon/pkg/sinon.js" charset="utf-8"></script>
<script src="../node_modules/sinon-chai/lib/sinon-chai.js" charset="utf-8"></script>
<link rel="stylesheet" href="../node_modules/mocha/mocha.css">
<script src="../node_modules/mocha/mocha.js"></script>
@ -68,7 +67,7 @@ runner.on('fail', function (test, err) {
result: false,
message: err.message,
stack: err.stack,
titles: flattenTitles(test)
titles: flattenTitles(test),
})
})
</script>

View file

@ -26,7 +26,7 @@ function test(sel) {
m.module(document.getElementById("test"), {
controller: function() {
this.title = m.prop("hello world")
this.title = m.prop("hello world");
},
view: function (ctrl) {
@ -55,7 +55,7 @@ m.module(document.getElementById("test"), {
m("div[contenteditable]", {
style: {border: "1px solid #888"},
onkeyup: m.withAttr("innerHTML", ctrl.title)
}, ctrl.title())
}, ctrl.title()),
]),
m("li", [
@ -64,10 +64,10 @@ m.module(document.getElementById("test"), {
m("div[contenteditable]", {
style: {border: "1px solid #888"},
onkeyup: m.withAttr("innerHTML", ctrl.title)
}, m.trust(ctrl.title()))
}, m.trust(ctrl.title())),
])
])
])
]);
}
})
});
</script>

View file

@ -285,4 +285,26 @@ describe("m.deferred()", function () {
deferred.reject(1)
expect(deferred.promise()).to.be.undefined
})
it("resolves to value of returned promise", function () {
var prmA = m.deferred()
var prmB = m.deferred()
prmA.resolve("A")
prmB.resolve("B")
prmA.promise.then(function (A) {
return prmB.promise
}).then(function(B) {
expect(B).to.equal("B")
})
})
it("yields immutable promises", function () {
var d = m.deferred()
d.resolve(5)
d.resolve(6)
d.promise.then(function(v) {
expect(v).to.equal(5)
})
})
})

View file

@ -17,21 +17,6 @@ describe("m()", function () {
expect(m).to.be.a("function")
})
it("throws with an empty tag name", function () {
expect(function () {
m("")
}).to.throw(TypeError)
})
it("throws when the tag is not a string or object", function () {
expect(function () { m(0) }).to.throw(TypeError)
expect(function () { m(1) }).to.throw(TypeError)
expect(function () { m(true) }).to.throw(TypeError)
expect(function () { m(null) }).to.throw(TypeError)
expect(function () { m(undefined) }).to.throw(TypeError)
expect(function () { m([]) }).to.throw(TypeError)
})
it("sets correct tag name", function () {
expect(m("div")).to.have.property("tag", "div")
})

View file

@ -54,8 +54,6 @@ describe("m.mount()", function () {
})
it("reloads components correctly", function () {
if (mock.phantom) return
mock.requestAnimationFrame.$resolve()
var root1 = mock.document.createElement("div")
@ -546,8 +544,6 @@ describe("m.mount()", function () {
// https://github.com/lhorie/mithril.js/issues/551
it("only redraws a component when clicked", function () {
if (mock.phantom) return
var root = mock.document.createElement("div")
var a = false
var found = {}
@ -630,8 +626,6 @@ describe("m.mount()", function () {
})
it("redraws when clicked and click handler forces redraw", function () {
if (mock.phantom) return
var root = mock.document.createElement("div")
var view = sinon.stub().returns(m("div", {
onclick: function () { m.redraw(true) }
@ -648,7 +642,7 @@ describe("m.mount()", function () {
})
function resolveXhr() {
mock.XMLHttpRequest.$instances.pop().$resolve()
mock.XMLHttpRequest.$instances.pop().$resolve().onreadystatechange()
mock.requestAnimationFrame.$resolve()
}

View file

@ -31,8 +31,6 @@ describe("m.redraw()", function () {
})
it("runs unnecessary redraws asynchronously", function () {
if (mock.phantom) return
var root = mock.document.createElement("div")
var view = sinon.spy()
@ -198,8 +196,6 @@ describe("m.redraw()", function () {
})
dit("recreates the component when \"all\"", function (root) {
if (mock.phantom) return
var count = 0
function config(el, init) {
if (!init) count++

View file

@ -1315,31 +1315,30 @@ describe("m.render()", function () {
expect(before).to.equal(after)
})
// FIXME: implement document.createRange().createContextualFragment()
dom(function () {
it("keeps unkeyed identity if mixed with elements/trusted text and identity can be inferred", function () { // eslint-disable-line
var root = document.createElement("div")
// 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: 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]
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)
})
expect(before).to.equal(after)
})
it("uses the syntax class if it's given as `undefined` in attr", function () { // eslint-disable-line
@ -1412,7 +1411,6 @@ describe("m.render()", function () {
// https://github.com/lhorie/mithril.js/issues/214
it("keeps all input events", function () {
this.timeout(3000) // eslint-disable-line no-invalid-this
var root = mock.document.createElement("div")
var ctrl = m.mount(root, {

View file

@ -5,6 +5,7 @@ describe("m.request()", function () {
function resolve() {
var xhr = mock.XMLHttpRequest.$instances.pop()
xhr.$resolve.apply(xhr, arguments)
xhr.onreadystatechange()
return xhr
}
@ -66,7 +67,7 @@ describe("m.request()", function () {
})().url).to.equal("http://domain.com:80/foo")
})
it("propogates errors through the promise (1)", function () {
it("propagates errors through the promise (1)", function () {
var error = m.prop()
var prop = m.request({
@ -80,7 +81,7 @@ describe("m.request()", function () {
expect(error().message).to.equal("error occurred")
})
it("propogates errors through the promise (2)", function () {
it("propagates errors through the promise (2)", function () {
var error = m.prop()
var prop = m.request({
@ -94,7 +95,7 @@ describe("m.request()", function () {
expect(error().message).to.equal("error occurred")
})
it("does not propogate results to `finally`", function () {
xit("does not propagate results to `finally`", function () {
// Data returned by then() functions do *not* propagate to finally().
var data = m.prop()
var prop = m.request({
@ -110,7 +111,7 @@ describe("m.request()", function () {
expect(data()).to.not.exist
})
it("does not propogate `finally` results to the next promise", function () {
it("does not propagate `finally` results to the next promise", function () {
var data = m.prop()
var prop = m.request({method: "GET", url: "test"})
@ -123,7 +124,7 @@ describe("m.request()", function () {
expect(data()).to.equal("foo")
})
it("propogates `finally` errors", function () {
it("propagates `finally` errors", function () {
var error = m.prop()
var prop = m.request({method: "GET", url: "test"})
@ -181,7 +182,8 @@ describe("m.request()", function () {
data: {foo: 1}
}).then(null, error)
var xhr = mock.XMLHttpRequest.$instances.pop().$resolve()
var xhr = mock.XMLHttpRequest.$instances.pop()
xhr.onreadystatechange()
expect(xhr.$headers).to.have.property(
"Content-Type",
@ -196,7 +198,8 @@ describe("m.request()", function () {
url: "test"
}).then(null, error)
var xhr = mock.XMLHttpRequest.$instances.pop().$resolve()
var xhr = mock.XMLHttpRequest.$instances.pop()
xhr.onreadystatechange()
expect(xhr.$headers).to.not.have.property("Content-Type")
})
@ -214,7 +217,7 @@ describe("m.request()", function () {
expect(initialValue).to.equal("foo")
})
it("correctly propogates initial value when not completed", function () {
it("correctly propagates initial value when not completed", function () {
var prop = m.request({
method: "POST",
url: "test",
@ -256,7 +259,7 @@ describe("m.request()", function () {
expect(prop().url).to.equal("test?foo=1&foo=2")
})
it("propogates initial value in call before request is completed", function () { // eslint-disable-line
it("propagates initial value in call before request is completed", function () { // eslint-disable-line
var value
var prop1 = m.request({method: "GET", url: "test", initialValue: 123})
expect(prop1()).to.equal(123)

View file

@ -102,7 +102,7 @@ describe("m.route()", function () {
expect(route2).to.equal("/test13")
})
// FIXME: this causes others to fail, even though it passes
// FIXME: this causes others to fail
xdit("skips route change if component ctrl.onunload calls preventDefault", function (root) { // eslint-disable-line
mode("search")
var spy = sinon.spy()
@ -130,7 +130,7 @@ describe("m.route()", function () {
expect(spy).to.not.have.been.called
})
// FIXME: this causes others to fail, even though it passes
// FIXME: this causes others to fail
xdit("skips route change if subcomponent ctrl.onunload calls preventDefault", function (root) { // eslint-disable-line
mode("search")
@ -161,7 +161,7 @@ describe("m.route()", function () {
expect(spy).to.not.have.been.called
})
// FIXME: this causes others to fail, even though it passes
// FIXME: this causes others to fail
xdit("skips route change if non-curried component ctrl.onunload calls preventDefault", function (root) { // eslint-disable-line
mode("search")
@ -190,7 +190,7 @@ describe("m.route()", function () {
expect(spy).to.not.have.been.called
})
// FIXME: this causes others to fail, even though it passes
// FIXME: this causes others to fail
xdit("skips route change if non-curried subcomponent ctrl.onunload calls preventDefault", function (root) { // eslint-disable-line
mode("search")

View file

@ -29,9 +29,7 @@ describe("m.trust()", function () {
it("works with mixed trusted content in div", function () {
var root = document.createElement("div")
m.render(root, [m.trust("<p>1</p><p>2</p>"), m("i", "foo")])
// Case-insensitive test to work around weird heisenbug with the
// browser
expect(root.childNodes[2].tagName).to.equalIgnoreCase("I")
expect(root.childNodes[2].tagName).to.equal("I")
})
it("works with mixed trusted content in text nodes", function () {
@ -40,14 +38,12 @@ describe("m.trust()", function () {
m.trust("<p>1</p>123<p>2</p>"),
m("i", "foo")
])
// Case-insensitive test to work around weird heisenbug with the
// browser
expect(root.childNodes[3].tagName).to.equalIgnoreCase("I")
expect(root.childNodes[3].tagName).to.equal("I")
})
// FIXME: this is a bug (trusted string's contents rendered as just
// textual contents)
it("works with mixed trusted content in td", function () {
xit("works with mixed trusted content in td", function () {
var root = document.createElement("table")
root.appendChild(root = document.createElement("tr"))
@ -56,9 +52,7 @@ describe("m.trust()", function () {
m("td", "foo")
])
// Case-insensitive test to work around weird heisenbug with the
// browser
expect(root.childNodes[2].tagName).to.equalIgnoreCase("TD")
expect(root.childNodes[2].tagName).to.equal("TD")
})
})
})

View file

@ -94,13 +94,13 @@ m.render(document.getElementById("test"), [
"s 11 -61 -11 -80",
"s -79 -7 -70 -41",
"C 46.039,146.545,53.039,128.545,66.039,133.545",
"z"
"z",
].join(" "),
fill: "#FFFFFF",
stroke: "#000000",
"stroke-miterlimit": 10,
"stroke-width": 4
})
"stroke-width": 4,
}),
]),
m("svg[height=270px][width=270px][viewBox='0 0 270 270']", [
m("g[transform='translate(150,150)'][title=Clock]", [
@ -109,7 +109,7 @@ m.render(document.getElementById("test"), [
r: 108,
fill: "none",
"stroke-width": 4,
stroke: "gray"
stroke: "gray",
}),
m("circle", {
r: 97,
@ -117,7 +117,7 @@ m.render(document.getElementById("test"), [
"stroke-width": 11,
stroke: "black",
"stroke-dasharray": "4,46.789082",
transform: "rotate(-1.5)"
transform: "rotate(-1.5)",
}),
m("circle", {
r: 100,
@ -125,8 +125,8 @@ m.render(document.getElementById("test"), [
"stroke-width": 5,
stroke: "black",
"stroke-dasharray": "2,8.471976",
transform: "rotate(-.873)"
})
transform: "rotate(-.873)",
}),
]),
m("g[transform='rotate(180)']", [
m("g#hour", [
@ -135,7 +135,7 @@ m.render(document.getElementById("test"), [
y2: 75,
"stroke-linecap": "round",
stroke: "blue",
opacity: 0.5
opacity: 0.5,
}),
m("animateTransform[attributeName=transform]", {
type: "rotate",
@ -143,7 +143,7 @@ m.render(document.getElementById("test"), [
dur: "12h",
by: 360
}),
m("circle[r=7]")
m("circle[r=7]"),
]),
m("g#minute", [
m("line", {
@ -157,9 +157,9 @@ m.render(document.getElementById("test"), [
type: "rotate",
repeatCount: "indefinite",
dur: "60min",
by: 360
by: 360,
}),
m("circle[r=6][fill=red]")
m("circle[r=6][fill=red]"),
]),
m("g#second", [
m("line", {
@ -175,9 +175,9 @@ m.render(document.getElementById("test"), [
dur: "60s",
by: 360
}),
m("circle[r=4][fill=blue]")
])
])
m("circle[r=4][fill=blue]"),
]),
]),
]),
m("script", "(" + function () {
"use strict"
@ -195,7 +195,7 @@ m.render(document.getElementById("test"), [
rotate("hour", 30 * (hours + minutes / 60 + seconds / 3600))
rotate("minute", 6 * (minutes + seconds / 60))
rotate("second", 6 * seconds)
}.toString() + ")()")
}.toString() + ")()"),
]),
m("svg[height=200px][width=200px]", [
m("foreignObject", {
@ -203,7 +203,7 @@ m.render(document.getElementById("test"), [
y: 0,
width: "100px",
height: "100px",
transform: "translate(0,0)"
transform: "translate(0,0)",
}, m("div", {xmlns: "http://www.w3.org/1999/xhtml"}, [
m.trust("this is a piece of html rendered as " +
"<a href=\"http://www.w3.org/TR/SVG11/extend.html\">" +

View file

@ -1,101 +0,0 @@
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Mithril unloading test</title>
<!-- Reference: https://github.com/lhorie/mithril.js/issues/694 -->
</head>
<body>
<script src="../mithril.js"></script>
<h4>This tests unloading of components which have an unloader method.</h4>
<p>
The test mounts Component1 on div "one" with a nested internal component and an "open" button.
The internal component displays its creation time and an input field.
The open button when clicked will in turn mount Component2 on div "two" with a close button.
The close button will unmount the second component.
</p>
<p>When the second component is mounted or unmounted, the expected behavior is:</p>
<ul>
<li>The first component and its subcomponent should be redrawn.</li>
<li>The first component and internal component should <strong>not</strong> be reinitialized.</li>
<li>The time displayed in the internal component should <strong>not</strong> change.</li>
<li>Any text entered in the input component should <strong>not</strong> change.</li>
</ul>
<p>Check the console for logging as to redraws and unload events.</p>
<div id="one"></div>
<div id="two"></div>
<script>
var InternalComponent = {
controller: function(args) {
console.log("+ made internal for 1");
return {
text: "initial",
created: new Date().toISOString(),
onunload: function() {
console.log("- unload internal for 1");
}
};
},
view: function(controller, args) {
console.log("^ view internal for 1");
return m("div", [
controller.created,
m("br"),
m("input", {value: controller.text, onchange: function(event) { controller.text = event.target.value; } })
]);
}
}
var Component1 = {
controller: function() {
console.log("+ made 1");
return {
onunload: function() {
console.log("- unload 1");
}
};
},
view: function() {
console.log("^ view 1");
return m("div", [
"Component 1",
m.component(InternalComponent),
m('button', {onclick: function() {
console.log("==== mount 2");
m.mount(document.getElementById("two"), Component2);
}}, "Open")
]);
}
}
var Component2 = {
controller: function() {
console.log("+ made 2");
return {
onunload: function() {
console.log("- unload 2");
}
};
},
view: function() {
console.log("^ view 2");
return m("div", {style: "border: dotted"}, [
"Component 2",
m('button', {onclick: function() {
console.log("==== unmount 2");
m.mount(document.getElementById("two"), null);
}}, "Close")
]);
}
}
console.log("==== mount 1");
m.mount(document.getElementById("one"), Component1);
</script>
</body>
</html>