Merge branch 'test-all-component-kinds' of https://github.com/pygy/mithril.js into next

This commit is contained in:
Isiah Meadows 2017-02-25 23:00:20 -05:00
commit aefee3b88e
14 changed files with 1381 additions and 1247 deletions

View file

@ -8,6 +8,7 @@
<script src="../../ospec/ospec.js"></script>
<script src="../../test-utils/callAsync.js"></script>
<script src="../../test-utils/domMock.js"></script>
<script src="../../test-utils/component.js"></script>
<script src="../../render/vnode.js"></script>
<script src="../../render/trust.js"></script>

File diff suppressed because it is too large Load diff

View file

@ -2,6 +2,7 @@
var o = require("../../ospec/ospec")
var callAsync = require("../../test-utils/callAsync")
var components = require("../../test-utils/components")
var domMock = require("../../test-utils/domMock")
var vdom = require("../../render/render")
var Promise = require("../../promise/promise")
@ -169,39 +170,44 @@ o.spec("onbeforeremove", function() {
done()
})
})
o("finalizes the remove phase asynchronously when promise is returned synchronously from both attrs- and tag.onbeforeremove", function(done) {
var onremove = o.spy()
var onbeforeremove = function(){return Promise.resolve()}
var component = {
onbeforeremove: onbeforeremove,
onremove: onremove,
view: function() {},
}
render(root, [{tag: component, attrs: {onbeforeremove: onbeforeremove, onremove: onremove}}])
render(root, [])
callAsync(function() {
o(onremove.callCount).equals(2) // once for `tag`, once for `attrs`
done()
})
})
o("awaits promise resolution before removing the node", function(done) {
var view = o.spy()
var onremove = o.spy()
var onbeforeremove = function(){return new Promise(function(resolve){callAsync(resolve)})}
var component = {
onbeforeremove: onbeforeremove,
onremove: onremove,
view: view,
}
render(root, [{tag: component}])
render(root, [])
components.forEach(function(cmp){
o.spec(cmp.kind, function(){
var createComponent = cmp.create
o("finalizes the remove phase asynchronously when promise is returned synchronously from both attrs- and tag.onbeforeremove", function(done) {
var onremove = o.spy()
var onbeforeremove = function(){return Promise.resolve()}
var component = createComponent({
onbeforeremove: onbeforeremove,
onremove: onremove,
view: function() {},
})
render(root, [{tag: component, attrs: {onbeforeremove: onbeforeremove, onremove: onremove}}])
render(root, [])
callAsync(function() {
o(onremove.callCount).equals(2) // once for `tag`, once for `attrs`
done()
})
})
o("awaits promise resolution before removing the node", function(done) {
var view = o.spy()
var onremove = o.spy()
var onbeforeremove = function(){return new Promise(function(resolve){callAsync(resolve)})}
var component = createComponent({
onbeforeremove: onbeforeremove,
onremove: onremove,
view: view,
})
render(root, [{tag: component}])
render(root, [])
callAsync(function(){
o(onremove.callCount).equals(0)
callAsync(function(){
o(onremove.callCount).equals(0)
callAsync(function() {
o(onremove.callCount).equals(1)
done()
callAsync(function() {
o(onremove.callCount).equals(1)
done()
})
})
})
})
})

View file

@ -1,6 +1,7 @@
"use strict"
var o = require("../../ospec/ospec")
var components = require("../../test-utils/components")
var domMock = require("../../test-utils/domMock")
var vdom = require("../../render/render")
@ -56,86 +57,6 @@ o.spec("onbeforeupdate", function() {
o(root.firstChild.nodeValue).equals("a")
})
o("prevents update in component", function() {
var component = {
onbeforeupdate: function() {return false},
view: function(vnode) {
return {tag: "div", children: vnode.children}
},
}
var vnode = {tag: component, children: [{tag: "#", children: "a"}]}
var updated = {tag: component, children: [{tag: "#", children: "b"}]}
render(root, [vnode])
render(root, [updated])
o(root.firstChild.firstChild.nodeValue).equals("a")
})
o("prevents update if returning false in component and false in vnode", function() {
var component = {
onbeforeupdate: function() {return false},
view: function(vnode) {
return {tag: "div", attrs: {id: vnode.attrs.id}}
},
}
var vnode = {tag: component, attrs: {id: "a", onbeforeupdate: function() {return false}}}
var updated = {tag: component, attrs: {id: "b", onbeforeupdate: function() {return false}}}
render(root, [vnode])
render(root, [updated])
o(root.firstChild.attributes["id"].nodeValue).equals("a")
})
o("does not prevent update if returning true in component and true in vnode", function() {
var component = {
onbeforeupdate: function() {return true},
view: function(vnode) {
return {tag: "div", attrs: {id: vnode.attrs.id}}
},
}
var vnode = {tag: component, attrs: {id: "a", onbeforeupdate: function() {return true}}}
var updated = {tag: component, attrs: {id: "b", onbeforeupdate: function() {return true}}}
render(root, [vnode])
render(root, [updated])
o(root.firstChild.attributes["id"].nodeValue).equals("b")
})
o("does not prevent update if returning false in component but true in vnode", function() {
var component = {
onbeforeupdate: function() {return false},
view: function(vnode) {
return {tag: "div", attrs: {id: vnode.attrs.id}}
},
}
var vnode = {tag: component, attrs: {id: "a", onbeforeupdate: function() {return true}}}
var updated = {tag: component, attrs: {id: "b", onbeforeupdate: function() {return true}}}
render(root, [vnode])
render(root, [updated])
o(root.firstChild.attributes["id"].nodeValue).equals("b")
})
o("does not prevent update if returning true in component but false in vnode", function() {
var component = {
onbeforeupdate: function() {return true},
view: function(vnode) {
return {tag: "div", attrs: {id: vnode.attrs.id}}
},
}
var vnode = {tag: component, attrs: {id: "a", onbeforeupdate: function() {return false}}}
var updated = {tag: component, attrs: {id: "b", onbeforeupdate: function() {return false}}}
render(root, [vnode])
render(root, [updated])
o(root.firstChild.attributes["id"].nodeValue).equals("b")
})
o("does not prevent update if returning true", function() {
var onbeforeupdate = function() {return true}
var vnode = {tag: "div", attrs: {id: "a", onbeforeupdate: onbeforeupdate}}
@ -147,22 +68,6 @@ o.spec("onbeforeupdate", function() {
o(root.firstChild.attributes["id"].nodeValue).equals("b")
})
o("does not prevent update if returning true from component", function() {
var component = {
onbeforeupdate: function() {return true},
view: function(vnode) {
return {tag: "div", attrs: vnode.attrs}
},
}
var vnode = {tag: component, attrs: {id: "a"}}
var updated = {tag: component, attrs: {id: "b"}}
render(root, [vnode])
render(root, [updated])
o(root.firstChild.attributes["id"].nodeValue).equals("b")
})
o("accepts arguments for comparison", function() {
var count = 0
var vnode = {tag: "div", attrs: {id: "a", onbeforeupdate: onbeforeupdate}}
@ -184,33 +89,6 @@ o.spec("onbeforeupdate", function() {
o(root.firstChild.attributes["id"].nodeValue).equals("b")
})
o("accepts arguments for comparison in component", function() {
var component = {
onbeforeupdate: onbeforeupdate,
view: function(vnode) {
return {tag: "div", attrs: vnode.attrs}
},
}
var count = 0
var vnode = {tag: component, attrs: {id: "a"}}
var updated = {tag: component, attrs: {id: "b"}}
render(root, [vnode])
render(root, [updated])
function onbeforeupdate(vnode, old) {
count++
o(old.attrs.id).equals("a")
o(vnode.attrs.id).equals("b")
return old.attrs.id !== vnode.attrs.id
}
o(count).equals(1)
o(root.firstChild.attributes["id"].nodeValue).equals("b")
})
o("is not called on creation", function() {
var count = 0
var vnode = {tag: "div", attrs: {id: "a", onbeforeupdate: onbeforeupdate}}
@ -226,28 +104,6 @@ o.spec("onbeforeupdate", function() {
o(count).equals(0)
})
o("is not called on component creation", function() {
var component = {
onbeforeupdate: onbeforeupdate,
view: function(vnode) {
return {tag: "div", attrs: vnode.attrs}
},
}
var count = 0
var vnode = {tag: "div", attrs: {id: "a"}}
var updated = {tag: "div", attrs: {id: "b"}}
render(root, [vnode])
function onbeforeupdate(vnode, old) {
count++
return true
}
o(count).equals(0)
})
o("is called only once on update", function() {
var count = 0
var vnode = {tag: "div", attrs: {id: "a", onbeforeupdate: onbeforeupdate}}
@ -264,26 +120,177 @@ o.spec("onbeforeupdate", function() {
o(count).equals(1)
})
o("is called only once on component update", function() {
var component = {
onbeforeupdate: onbeforeupdate,
view: function(vnode) {
return {tag: "div", attrs: vnode.attrs}
},
}
components.forEach(function(cmp){
o.spec(cmp.kind, function(){
var createComponent = cmp.create
var count = 0
var vnode = {tag: component, attrs: {id: "a"}}
var updated = {tag: component, attrs: {id: "b"}}
o("prevents update in component", function() {
var component = createComponent({
onbeforeupdate: function() {return false},
view: function(vnode) {
return {tag: "div", children: vnode.children}
},
})
var vnode = {tag: component, children: [{tag: "#", children: "a"}]}
var updated = {tag: component, children: [{tag: "#", children: "b"}]}
render(root, [vnode])
render(root, [updated])
render(root, [vnode])
render(root, [updated])
function onbeforeupdate(vnode, old) {
count++
return true
}
o(root.firstChild.firstChild.nodeValue).equals("a")
})
o(count).equals(1)
o("prevents update if returning false in component and false in vnode", function() {
var component = createComponent({
onbeforeupdate: function() {return false},
view: function(vnode) {
return {tag: "div", attrs: {id: vnode.attrs.id}}
},
})
var vnode = {tag: component, attrs: {id: "a", onbeforeupdate: function() {return false}}}
var updated = {tag: component, attrs: {id: "b", onbeforeupdate: function() {return false}}}
render(root, [vnode])
render(root, [updated])
o(root.firstChild.attributes["id"].nodeValue).equals("a")
})
o("does not prevent update if returning true in component and true in vnode", function() {
var component = createComponent({
onbeforeupdate: function() {return true},
view: function(vnode) {
return {tag: "div", attrs: {id: vnode.attrs.id}}
},
})
var vnode = {tag: component, attrs: {id: "a", onbeforeupdate: function() {return true}}}
var updated = {tag: component, attrs: {id: "b", onbeforeupdate: function() {return true}}}
render(root, [vnode])
render(root, [updated])
o(root.firstChild.attributes["id"].nodeValue).equals("b")
})
o("does not prevent update if returning false in component but true in vnode", function() {
var component = createComponent({
onbeforeupdate: function() {return false},
view: function(vnode) {
return {tag: "div", attrs: {id: vnode.attrs.id}}
},
})
var vnode = {tag: component, attrs: {id: "a", onbeforeupdate: function() {return true}}}
var updated = {tag: component, attrs: {id: "b", onbeforeupdate: function() {return true}}}
render(root, [vnode])
render(root, [updated])
o(root.firstChild.attributes["id"].nodeValue).equals("b")
})
o("does not prevent update if returning true in component but false in vnode", function() {
var component = createComponent({
onbeforeupdate: function() {return true},
view: function(vnode) {
return {tag: "div", attrs: {id: vnode.attrs.id}}
},
})
var vnode = {tag: component, attrs: {id: "a", onbeforeupdate: function() {return false}}}
var updated = {tag: component, attrs: {id: "b", onbeforeupdate: function() {return false}}}
render(root, [vnode])
render(root, [updated])
o(root.firstChild.attributes["id"].nodeValue).equals("b")
})
o("does not prevent update if returning true from component", function() {
var component = createComponent({
onbeforeupdate: function() {return true},
view: function(vnode) {
return {tag: "div", attrs: vnode.attrs}
},
})
var vnode = {tag: component, attrs: {id: "a"}}
var updated = {tag: component, attrs: {id: "b"}}
render(root, [vnode])
render(root, [updated])
o(root.firstChild.attributes["id"].nodeValue).equals("b")
})
o("accepts arguments for comparison in component", function() {
var component = createComponent({
onbeforeupdate: onbeforeupdate,
view: function(vnode) {
return {tag: "div", attrs: vnode.attrs}
},
})
var count = 0
var vnode = {tag: component, attrs: {id: "a"}}
var updated = {tag: component, attrs: {id: "b"}}
render(root, [vnode])
render(root, [updated])
function onbeforeupdate(vnode, old) {
count++
o(old.attrs.id).equals("a")
o(vnode.attrs.id).equals("b")
return old.attrs.id !== vnode.attrs.id
}
o(count).equals(1)
o(root.firstChild.attributes["id"].nodeValue).equals("b")
})
o("is not called on component creation", function() {
var component = createComponent({
onbeforeupdate: onbeforeupdate,
view: function(vnode) {
return {tag: "div", attrs: vnode.attrs}
},
})
var count = 0
var vnode = {tag: "div", attrs: {id: "a"}}
var updated = {tag: "div", attrs: {id: "b"}}
render(root, [vnode])
function onbeforeupdate(vnode, old) {
count++
return true
}
o(count).equals(0)
})
o("is called only once on component update", function() {
var component = createComponent({
onbeforeupdate: onbeforeupdate,
view: function(vnode) {
return {tag: "div", attrs: vnode.attrs}
},
})
var count = 0
var vnode = {tag: component, attrs: {id: "a"}}
var updated = {tag: component, attrs: {id: "b"}}
render(root, [vnode])
render(root, [updated])
function onbeforeupdate(vnode, old) {
count++
return true
}
o(count).equals(1)
})
})
})
})
})

View file

@ -1,6 +1,7 @@
"use strict"
var o = require("../../ospec/ospec")
var components = require("../../test-utils/components")
var domMock = require("../../test-utils/domMock")
var vdom = require("../../render/render")
var m = require("../../render/hyperscript")
@ -80,39 +81,6 @@ o.spec("onremove", function() {
o(remove.this).equals(vnode.state)
o(remove.args[0]).equals(vnode)
})
o("calls onremove on nested component", function() {
var spy = o.spy()
var comp = {
view: function() {return m(outer)}
}
var outer = {
view: function() {return m(inner)}
}
var inner = {
onremove: spy,
view: function() {return m("div")}
}
render(root, {tag: comp})
render(root, null)
o(spy.callCount).equals(1)
})
o("calls onremove on nested component child", function() {
var spy = o.spy()
var comp = {
view: function() {return m(outer)}
}
var outer = {
view: function() {return m(inner, m("a", {onremove: spy}))}
}
var inner = {
view: function(vnode) {return m("div", vnode.children)}
}
render(root, {tag: comp})
render(root, null)
o(spy.callCount).equals(1)
})
o("does not set onremove as an event handler", function() {
var remove = o.spy()
var vnode = {tag: "div", attrs: {onremove: remove}, children: []}
@ -145,4 +113,43 @@ o.spec("onremove", function() {
o(vnode.dom).notEquals(updated.dom)
})
})
components.forEach(function(cmp){
o.spec(cmp.kind, function(){
var createComponent = cmp.create
o("calls onremove on nested component", function() {
var spy = o.spy()
var comp = createComponent({
view: function() {return m(outer)}
})
var outer = createComponent({
view: function() {return m(inner)}
})
var inner = createComponent({
onremove: spy,
view: function() {return m("div")}
})
render(root, {tag: comp})
render(root, null)
o(spy.callCount).equals(1)
})
o("calls onremove on nested component child", function() {
var spy = o.spy()
var comp = createComponent({
view: function() {return m(outer)}
})
var outer = createComponent({
view: function() {return m(inner, m("a", {onremove: spy}))}
})
var inner = createComponent({
view: function(vnode) {return m("div", vnode.children)}
})
render(root, {tag: comp})
render(root, null)
o(spy.callCount).equals(1)
})
})
})
})

View file

@ -1,6 +1,7 @@
"use strict"
var o = require("../../ospec/ospec")
var components = require("../../test-utils/components")
var domMock = require("../../test-utils/domMock")
var vdom = require("../../render/render")
@ -118,7 +119,7 @@ o.spec("render", function() {
o(oninit.callCount).equals(0)
o(onbeforeupdate.callCount).equals(0)
})
o("does not try to re-initialize a factory component whose view has thrown", function() {
o("does not try to re-initialize a closure component whose view has thrown", function() {
var oninit = o.spy()
var onbeforeupdate = o.spy()
function A() {
@ -141,7 +142,7 @@ o.spec("render", function() {
o(oninit.callCount).equals(1)
o(onbeforeupdate.callCount).equals(0)
})
o("does not try to re-initialize a factory component whose oninit has thrown", function() {
o("does not try to re-initialize a closure component whose oninit has thrown", function() {
var oninit = o.spy(function(vnode) {throw new Error("error")})
var onbeforeupdate = o.spy()
function A() {
@ -164,7 +165,7 @@ o.spec("render", function() {
o(oninit.callCount).equals(1)
o(onbeforeupdate.callCount).equals(0)
})
o("does not try to re-initialize a factory component whose factory has thrown", function() {
o("does not try to re-initialize a closure component whose closure has thrown", function() {
function A() {
throw new Error("error")
}

View file

@ -1,6 +1,7 @@
"use strict"
var o = require("../../ospec/ospec")
var components = require("../../test-utils/components")
var domMock = require("../../test-utils/domMock")
var vdom = require("../../render/render")
@ -838,38 +839,6 @@ o.spec("updateNodes", function() {
o(root.childNodes[0].nodeName).equals("A")
o(root.childNodes[1].nodeName).equals("B")
})
o("fragment child toggles from null when followed by null component then tag", function() {
var component = {view: function() {return null}}
var vnodes = [{tag: "[", children: [{tag: "a"}, {tag: component}, {tag: "b"}]}]
var temp = [{tag: "[", children: [null, {tag: component}, {tag: "b"}]}]
var updated = [{tag: "[", children: [{tag: "a"}, {tag: component}, {tag: "b"}]}]
render(root, vnodes)
render(root, temp)
render(root, updated)
o(root.childNodes.length).equals(2)
o(root.childNodes[0].nodeName).equals("A")
o(root.childNodes[1].nodeName).equals("B")
})
o("fragment child toggles from null in component when followed by null component then tag", function() {
var flag = true
var a = {view: function() {return flag ? {tag: "a"} : null}}
var b = {view: function() {return null}}
var vnodes = [{tag: "[", children: [{tag: a}, {tag: b}, {tag: "s"}]}]
var temp = [{tag: "[", children: [{tag: a}, {tag: b}, {tag: "s"}]}]
var updated = [{tag: "[", children: [{tag: a}, {tag: b}, {tag: "s"}]}]
render(root, vnodes)
flag = false
render(root, temp)
flag = true
render(root, updated)
o(root.childNodes.length).equals(2)
o(root.childNodes[0].nodeName).equals("A")
o(root.childNodes[1].nodeName).equals("S")
})
o("cached, non-keyed nodes skip diff", function () {
var onupdate = o.spy();
var cached = {tag:"a", attrs:{onupdate: onupdate}}
@ -926,7 +895,7 @@ o.spec("updateNodes", function() {
o(update.callCount).equals(2)
o(remove.callCount).equals(0)
})
o("component is recreated if key changes to undefined", function () {
o("node is recreated if key changes to undefined", function () {
var vnode = {tag: "b", key: 1}
var updated = {tag: "b"}
@ -936,4 +905,42 @@ o.spec("updateNodes", function() {
o(vnode.dom).notEquals(updated.dom)
})
})
components.forEach(function(cmp){
o.spec(cmp.kind, function(){
var createComponent = cmp.create
o("fragment child toggles from null when followed by null component then tag", function() {
var component = createComponent({view: function() {return null}})
var vnodes = [{tag: "[", children: [{tag: "a"}, {tag: component}, {tag: "b"}]}]
var temp = [{tag: "[", children: [null, {tag: component}, {tag: "b"}]}]
var updated = [{tag: "[", children: [{tag: "a"}, {tag: component}, {tag: "b"}]}]
render(root, vnodes)
render(root, temp)
render(root, updated)
o(root.childNodes.length).equals(2)
o(root.childNodes[0].nodeName).equals("A")
o(root.childNodes[1].nodeName).equals("B")
})
o("fragment child toggles from null in component when followed by null component then tag", function() {
var flag = true
var a = createComponent({view: function() {return flag ? {tag: "a"} : null}})
var b = createComponent({view: function() {return null}})
var vnodes = [{tag: "[", children: [{tag: a}, {tag: b}, {tag: "s"}]}]
var temp = [{tag: "[", children: [{tag: a}, {tag: b}, {tag: "s"}]}]
var updated = [{tag: "[", children: [{tag: a}, {tag: b}, {tag: "s"}]}]
render(root, vnodes)
flag = false
render(root, temp)
flag = true
render(root, updated)
o(root.childNodes.length).equals(2)
o(root.childNodes[0].nodeName).equals("A")
o(root.childNodes[1].nodeName).equals("S")
})
})
})
})