#510 allow recursive nesting of components
This commit is contained in:
parent
c1ea98fd09
commit
9f110774aa
2 changed files with 367 additions and 22 deletions
|
|
@ -195,6 +195,45 @@ function testMithril(mock) {
|
|||
|
||||
return count1 == 1 && count2 == 2
|
||||
})
|
||||
test(function() {
|
||||
//sub component controller should only run once
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
|
||||
var root = mock.document.createElement("div")
|
||||
var count1 = 0, count2 = 0, count3 = 0, count4 = 0
|
||||
var module = {
|
||||
view: function(ctrl) {
|
||||
return m.module(sub)
|
||||
}
|
||||
}
|
||||
var sub = {
|
||||
controller: function() {
|
||||
count1++
|
||||
},
|
||||
view: function(ctrl) {
|
||||
count2++
|
||||
return subsub
|
||||
}
|
||||
}
|
||||
var subsub = {
|
||||
controller: function() {
|
||||
count3++
|
||||
},
|
||||
view: function(ctrl) {
|
||||
count4++
|
||||
return m("div", "test")
|
||||
}
|
||||
}
|
||||
m.module(root, module)
|
||||
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
|
||||
m.redraw(true)
|
||||
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
|
||||
return count1 == 1 && count2 == 2 && count3 == 1 && count4 == 2
|
||||
})
|
||||
test(function() {
|
||||
//keys in components should work
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
|
|
@ -230,6 +269,46 @@ function testMithril(mock) {
|
|||
|
||||
return firstBefore === firstAfter
|
||||
})
|
||||
test(function() {
|
||||
//keys in subcomponents should work
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
|
||||
var root = mock.document.createElement("div")
|
||||
var list = [1, 2, 3]
|
||||
var module = {
|
||||
controller: function() {},
|
||||
view: function(ctrl) {
|
||||
return list.map(function(i) {
|
||||
return m.module(sub, {key: i})
|
||||
})
|
||||
}
|
||||
}
|
||||
var sub = {
|
||||
view: function() {
|
||||
return m.module(subsub)
|
||||
}
|
||||
}
|
||||
var subsub = {
|
||||
controller: function() {},
|
||||
view: function() {
|
||||
return m("div")
|
||||
}
|
||||
}
|
||||
m.module(root, module)
|
||||
|
||||
var firstBefore = root.childNodes[0]
|
||||
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
|
||||
list.reverse()
|
||||
m.redraw(true)
|
||||
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
|
||||
var firstAfter = root.childNodes[2]
|
||||
|
||||
return firstBefore === firstAfter
|
||||
})
|
||||
test(function() {
|
||||
//keys in components should work even if component internally messes them up
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
|
|
@ -265,6 +344,47 @@ function testMithril(mock) {
|
|||
|
||||
return firstBefore === firstAfter
|
||||
})
|
||||
test(function() {
|
||||
//keys in subcomponents should work even if component internally messes them up
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
|
||||
var root = mock.document.createElement("div")
|
||||
var list = [1, 2, 3]
|
||||
var module = {
|
||||
controller: function() {},
|
||||
view: function(ctrl) {
|
||||
return list.map(function(i) {
|
||||
return m.module(sub, {key: i})
|
||||
})
|
||||
}
|
||||
}
|
||||
var sub = {
|
||||
controller: function() {},
|
||||
view: function() {
|
||||
return subsub
|
||||
}
|
||||
}
|
||||
var subsub = {
|
||||
controller: function() {},
|
||||
view: function() {
|
||||
return m("div", {key: 1})
|
||||
}
|
||||
}
|
||||
m.module(root, module)
|
||||
|
||||
var firstBefore = root.childNodes[0]
|
||||
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
|
||||
list.reverse()
|
||||
m.redraw(true)
|
||||
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
|
||||
var firstAfter = root.childNodes[2]
|
||||
|
||||
return firstBefore === firstAfter
|
||||
})
|
||||
test(function() {
|
||||
//component identity should stay intact if components are descendants of keyed elements
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
|
|
@ -300,6 +420,47 @@ function testMithril(mock) {
|
|||
|
||||
return firstBefore === firstAfter
|
||||
})
|
||||
test(function() {
|
||||
//subcomponent identity should stay intact if components are descendants of keyed elements
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
|
||||
var root = mock.document.createElement("div")
|
||||
var list = [1, 2, 3]
|
||||
var module = {
|
||||
controller: function() {},
|
||||
view: function(ctrl) {
|
||||
return list.map(function(i) {
|
||||
return m("div", {key: i}, m.module(sub))
|
||||
})
|
||||
}
|
||||
}
|
||||
var sub = {
|
||||
controller: function() {},
|
||||
view: function() {
|
||||
return subsub
|
||||
}
|
||||
}
|
||||
var subsub = {
|
||||
controller: function() {},
|
||||
view: function() {
|
||||
return m("div")
|
||||
}
|
||||
}
|
||||
m.module(root, module)
|
||||
|
||||
var firstBefore = root.childNodes[0].childNodes[0]
|
||||
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
|
||||
list.reverse()
|
||||
m.redraw(true)
|
||||
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
|
||||
var firstAfter = root.childNodes[2].childNodes[0]
|
||||
|
||||
return firstBefore === firstAfter
|
||||
})
|
||||
test(function() {
|
||||
//component should call onunload when removed from template
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
|
|
@ -338,6 +499,54 @@ function testMithril(mock) {
|
|||
|
||||
return unloaded === 3
|
||||
})
|
||||
test(function() {
|
||||
//subcomponent should call onunload when removed from template
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
|
||||
var root = mock.document.createElement("div")
|
||||
var list = [1, 2, 3]
|
||||
var unloaded1, unloaded2
|
||||
var module = {
|
||||
controller: function() {},
|
||||
view: function(ctrl) {
|
||||
return list.map(function(i) {
|
||||
return m.module(sub, {key: i})
|
||||
})
|
||||
}
|
||||
}
|
||||
var sub = {
|
||||
controller: function(opts) {
|
||||
this.onunload = function() {
|
||||
unloaded1 = opts.key
|
||||
}
|
||||
},
|
||||
view: function(ctrl, opts) {
|
||||
return m.module(subsub, {key: opts.key})
|
||||
}
|
||||
}
|
||||
var subsub = {
|
||||
controller: function(opts) {
|
||||
this.onunload = function() {
|
||||
unloaded2 = opts.key
|
||||
}
|
||||
},
|
||||
view: function() {
|
||||
return m("div")
|
||||
}
|
||||
}
|
||||
m.module(root, module)
|
||||
|
||||
var firstBefore = root.childNodes[0]
|
||||
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
|
||||
list.pop()
|
||||
m.redraw(true)
|
||||
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
|
||||
return unloaded1 === 3 && unloaded2 === 3
|
||||
})
|
||||
test(function() {
|
||||
//calling m.redraw synchronously from controller constructor should not trigger extra redraws
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
|
|
@ -365,6 +574,39 @@ function testMithril(mock) {
|
|||
|
||||
return count === 1
|
||||
})
|
||||
test(function() {
|
||||
//calling m.redraw synchronously from controller constructor should not trigger extra redraws
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
|
||||
var root = mock.document.createElement("div")
|
||||
var count = 0
|
||||
var module = {
|
||||
controller: function() {},
|
||||
view: function(ctrl) {
|
||||
return m.module(sub)
|
||||
}
|
||||
}
|
||||
var sub = {
|
||||
controller: function(opts) {},
|
||||
view: function() {
|
||||
return subsub
|
||||
}
|
||||
}
|
||||
var subsub = {
|
||||
controller: function(opts) {
|
||||
m.redraw()
|
||||
},
|
||||
view: function() {
|
||||
count++
|
||||
return m("div")
|
||||
}
|
||||
}
|
||||
m.module(root, module)
|
||||
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
|
||||
return count === 1
|
||||
})
|
||||
test(function() {
|
||||
//calling preventDefault from component's onunload should prevent route change
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
|
|
@ -402,6 +644,50 @@ function testMithril(mock) {
|
|||
|
||||
return loaded === false
|
||||
})
|
||||
test(function() {
|
||||
//calling preventDefault from subcomponent's onunload should prevent route change
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
mock.location.search = "?"
|
||||
|
||||
var root = mock.document.createElement("div")
|
||||
var loaded = false
|
||||
var testEnabled = true
|
||||
var module = {
|
||||
controller: function() {},
|
||||
view: function() {
|
||||
return m.module(sub)
|
||||
}
|
||||
}
|
||||
var sub = {
|
||||
controller: function(opts) {
|
||||
},
|
||||
view: function() {
|
||||
return m.module(subsub)
|
||||
}
|
||||
}
|
||||
var subsub = {
|
||||
controller: function(opts) {
|
||||
controller = this
|
||||
this.onunload = function(e) {if (testEnabled) e.preventDefault()}
|
||||
},
|
||||
view: function() {
|
||||
return m("div")
|
||||
}
|
||||
}
|
||||
m.route(root, "/a", {
|
||||
"/a": module,
|
||||
"/b": {controller: function() {loaded = true}, view: function() {}}
|
||||
})
|
||||
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
|
||||
m.route("/b")
|
||||
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
testEnabled = false
|
||||
|
||||
return loaded === false
|
||||
})
|
||||
test(function() {
|
||||
//calling preventDefault from non-curried component's onunload should prevent route change
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
|
|
@ -439,6 +725,49 @@ function testMithril(mock) {
|
|||
|
||||
return loaded === false
|
||||
})
|
||||
test(function() {
|
||||
//calling preventDefault from non-curried subcomponent's onunload should prevent route change
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
mock.location.search = "?"
|
||||
|
||||
var root = mock.document.createElement("div")
|
||||
var loaded = false
|
||||
var testEnabled = true
|
||||
var module = {
|
||||
controller: function() {},
|
||||
view: function() {
|
||||
return sub
|
||||
}
|
||||
}
|
||||
var sub = {
|
||||
controller: function(opts) {},
|
||||
view: function() {
|
||||
return subsub
|
||||
}
|
||||
}
|
||||
var subsub = {
|
||||
controller: function(opts) {
|
||||
controller = this
|
||||
this.onunload = function(e) {if (testEnabled) e.preventDefault()}
|
||||
},
|
||||
view: function() {
|
||||
return m("div")
|
||||
}
|
||||
}
|
||||
m.route(root, "/a", {
|
||||
"/a": module,
|
||||
"/b": {controller: function() {loaded = true}, view: function() {}}
|
||||
})
|
||||
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
|
||||
m.route("/b")
|
||||
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
testEnabled = false
|
||||
|
||||
return loaded === false
|
||||
})
|
||||
test(function() {
|
||||
// nested modules under keyed components should render
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue