initial release

This commit is contained in:
Leo Horie 2014-03-16 22:07:53 -04:00
parent 554e8358cf
commit 70b2489539
81 changed files with 6702 additions and 2 deletions

7
tests/index.html Normal file
View file

@ -0,0 +1,7 @@
<!doctype html>
<script src="../mithril.js"></script>
<script src="test.js"></script>
<script src="mock.js"></script>
<script src="mithril-tests.js"></script>
<p>Open the console to see the test report</p>

226
tests/mithril-tests.js Normal file
View file

@ -0,0 +1,226 @@
function testMithril(mock) {
m.deps(mock)
//m
test(function() {return m("div").tag === "div"})
test(function() {return m(".foo").tag === "div"})
test(function() {return m(".foo").attrs.className === "foo"})
test(function() {return m("[title=bar]").tag === "div"})
test(function() {return m("[title=bar]").attrs.title === "bar"})
test(function() {return m("[title=\'bar\']").attrs.title === "bar"})
test(function() {return m("[title=\"bar\"]").attrs.title === "bar"})
test(function() {return m("div", "test").children === "test"})
test(function() {return m("div", ["test"]).children[0] === "test"})
test(function() {return m("div", {title: "bar"}, "test").attrs.title === "bar"})
test(function() {return m("div", {title: "bar"}, "test").children === "test"})
test(function() {return m("div", {title: "bar"}, ["test"]).children[0] === "test"})
test(function() {return m("div", {title: "bar"}, m("div")).children.tag === "div"})
test(function() {return m("div", {title: "bar"}, [m("div")]).children[0].tag === "div"})
test(function() {return m("div", ["a", "b"]).children.length === 2})
test(function() {return m("div", [m("div")]).children[0].tag === "div"})
test(function() {return m("div", m("div")).attrs.tag === "div"}) //yes, this is expected behavior: see method signature
//m.module
for (var i = 0; i < 2; i++) {
//first iteration tests immediate rendering
//second iteration tests deferred rendering
test(function() {
var root = mock.document.createElement("div")
m.module(root, {
controller: function() {this.value = "test"},
view: function(ctrl) {return ctrl.value}
})
return root.childNodes[0].nodeValue === "test"
})
}
//m.withAttr
test(function() {
var value
var handler = m.withAttr("test", function(data) {value = data})
handler({currentTarget: {test: "foo"}})
return value === "foo"
})
//m.trust
test(function() {return m.trust("test").valueOf() === "test"})
//m.render
test(function() {
var root = mock.document.createElement("div")
m.render(root, "test")
return root.childNodes[0].nodeValue === "test"
})
test(function() {
var root = mock.document.createElement("div")
m.render(root, m("div", {id: "a"}))
var elementBefore = root.childNodes[0]
m.render(root, m("div", {id: "b"}))
var elementAfter = root.childNodes[0]
return elementBefore === elementAfter
})
test(function() {
var root = mock.document.createElement("div")
m.render(root, m("#a"))
var elementBefore = root.childNodes[0]
m.render(root, m("#b"))
var elementAfter = root.childNodes[0]
return elementBefore === elementAfter
})
test(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"}))
var elementAfter = root.childNodes[0]
return elementBefore !== elementAfter
})
test(function() {
var root = mock.document.createElement("div")
m.render(root, m("#a"))
var elementBefore = root.childNodes[0]
m.render(root, m("[title=b]"))
var elementAfter = root.childNodes[0]
return elementBefore !== elementAfter
})
test(function() {
var root = mock.document.createElement("div")
m.render(root, m("#a"))
var elementBefore = root.childNodes[0]
m.render(root, "test")
var elementAfter = root.childNodes[0]
return elementBefore !== elementAfter
})
//m.redraw
test(function() {
var controller
var root = mock.document.createElement("div")
m.module(root, {
controller: function() {controller = this},
view: function(ctrl) {return ctrl.value}
})
controller.value = "foo"
m.redraw()
return root.childNodes[0].nodeValue === "foo"
})
//m.route
test(function() {
var root = mock.document.createElement("div")
m.route.mode = "search"
m.route(root, "/test1", {
"/test1": {controller: function() {}, view: function() {return "foo"}}
})
return mock.location.search == "?/test1" && root.childNodes[0].nodeValue === "foo"
})
test(function() {
var root = mock.document.createElement("div")
m.route.mode = "pathname"
m.route(root, "/test2", {
"/test2": {controller: function() {}, view: function() {return "foo"}}
})
return mock.location.pathname == "/test2" && root.childNodes[0].nodeValue === "foo"
})
test(function() {
var root = mock.document.createElement("div")
m.route.mode = "hash"
m.route(root, "/test3", {
"/test3": {controller: function() {}, view: function() {return "foo"}}
})
return mock.location.hash == "#/test3" && root.childNodes[0].nodeValue === "foo"
})
test(function() {
var root = mock.document.createElement("div")
m.route.mode = "search"
m.route(root, "/test4/foo", {
"/test4/:test": {controller: function() {}, view: function() {return m.route.param("test")}}
})
return mock.location.search == "?/test4/foo" && root.childNodes[0].nodeValue === "foo"
})
//m.prop
test(function() {
var prop = m.prop("test")
return prop() === "test"
})
test(function() {
var prop = m.prop("test")
prop("foo")
return prop() == "foo"
})
//m.request
test(function() {
var prop = m.request({method: "GET", url: "test"})
var e = mock.XMLHttpRequest.$events.pop()
e.target.onload(e)
return prop().method === "GET" && prop().url === "test"
})
test(function() {
var prop = m.request({method: "GET", url: "test"}).then(function(value) {return "foo"})
var e = mock.XMLHttpRequest.$events.pop()
e.target.onload(e)
return prop() === "foo"
})
//m.deferred
test(function() {
var value
var deferred = m.deferred()
deferred.promise.then(function(data) {value = data})
deferred.resolve("test")
return value === "test"
})
test(function() {
var value
var deferred = m.deferred()
deferred.promise.then(function(value) {return "foo"}).then(function(data) {value = data})
deferred.resolve("test")
return value === "foo"
})
test(function() {
var value
var deferred = m.deferred()
deferred.promise.then(null, function(data) {value = data})
deferred.reject("test")
return value === "test"
})
test(function() {
var value
var deferred = m.deferred()
deferred.promise.then(null, function(value) {return "foo"}).then(null, function(data) {value = data})
deferred.reject("test")
return value === "foo"
})
//m.sync
test(function() {
var value
var deferred1 = m.deferred()
var deferred2 = m.deferred()
m.sync([deferred1.promise, deferred2.promise]).then(function(data) {value = data})
deferred1.resolve("test")
deferred2.resolve("foo")
return value[0] === "test" && value[1] === "foo"
})
//m.startComputation/m.endComputation
test(function() {
var controller
var root = mock.document.createElement("div")
m.module(root, {
controller: function() {controller = this},
view: function(ctrl) {return ctrl.value}
})
m.startComputation()
controller.value = "foo"
m.endComputation()
return root.childNodes[0].nodeValue === "foo"
})
}
//mocks
testMithril(mock.window)
test.print(console.log)

71
tests/mock.js Normal file
View file

@ -0,0 +1,71 @@
var mock = {}
mock.window = new function() {
var window = {}
window.document = {}
window.document.childNodes = []
window.document.createElement = function(tag) {
return {
childNodes: [],
nodeName: tag.toUpperCase(),
appendChild: window.document.appendChild,
removeChild: window.document.removeChild,
replaceChild: window.document.replaceChild,
setAttribute: function(name, value) {
this[name] = value.toString()
},
getAttribute: function(name, value) {
return this[name]
},
}
}
window.document.createTextNode = function(text) {
return {nodeValue: text.toString()}
}
window.document.documentElement = null
window.document.replaceChild = function(newChild, oldChild) {
var index = this.childNodes.indexOf(oldChild)
if (index > -1) this.childNodes.splice(index, 1, newChild)
else this.childNodes.push(newChild)
newChild.parentNode = this
oldChild.parentNode = null
}
window.document.appendChild = function(child) {
this.childNodes.push(child)
child.parentNode = this
}
window.document.removeChild = function(child) {
var index = this.childNodes.indexOf(child)
this.childNodes.splice(index, 1)
child.parentNode = null
}
window.performance = new function () {
var timestamp = 50
this.$elapse = function(amount) {timestamp = amount}
this.now = function() {return timestamp}
}
window.cancelAnimationFrame = function() {}
window.requestAnimationFrame = function(callback) {callback()}
window.XMLHttpRequest = new function() {
var request = function() {
this.open = function(method, url) {
this.method = method
this.url = url
}
this.send = function() {
this.responseText = JSON.stringify(this)
request.$events.push({type: "load", target: this})
}
}
request.$events = []
return request
}
window.location = {search: "", pathname: "", hash: ""},
window.history = {}
window.history.pushState = function(data, title, url) {
window.location.pathname = window.location.search = window.location.hash = url
},
window.history.replaceState = function(data, title, url) {
window.location.pathname = window.location.search = window.location.hash = url
}
return window
}

13
tests/test.js Normal file
View file

@ -0,0 +1,13 @@
function test(condition) {
try {if (!condition()) throw new Error}
catch (e) {test.failures.push(condition)}
test.total++
}
test.total = 0
test.failures = []
test.print = function(print) {
for (var i = 0; i < test.failures.length; i++) {
print(test.failures[i].toString())
}
print("tests: " + test.total + "\nfailures: " + test.failures.length)
}