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

8
tests/index.html Normal file
View file

@ -0,0 +1,8 @@
<!doctype html>
<!--<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.0.3/es5-shim.min.js"></script>-->
<script src="test.js"></script>
<script src="mock.js"></script>
<script src="../mithril.js"></script>
<script src="mithril-tests.js"></script>
<p>Open the console to see the test report</p>

48
tests/input-cursor.html Normal file
View file

@ -0,0 +1,48 @@
<p>Typing in the fields below should not move the cursor to the end of the input. Especially in Chrome</p>
<p>All inputs should update with the same value</p>
<p>Typing in an input should not prevent it from being updated by other inputs</p>
<div id="test"></div>
<script src="../mithril.js"></script>
<script>
var app = {}
app.controller = function() {
this.title = m.prop("hello world");
}
app.view = function(ctrl) {
return m("body", [
m("h1", ["Title: ", ctrl.title()]),
m("input[list=data]", {
onkeyup: m.withAttr("value", ctrl.title),
value: ctrl.title()
}),
m("datalist#data", [
m("option", "John"),
m("option", "Bob"),
m("option", "Mary")
]),
m("br"),
m("textarea", {
onkeyup: m.withAttr("value", ctrl.title),
value: ctrl.title()
}),
m("br"),
m("textarea", {
onkeyup: m.withAttr("value", ctrl.title)
}, ctrl.title()),
m("br"),
m("div[contenteditable]", {
style: {border: "1px solid #888"},
onkeyup: m.withAttr("innerHTML", ctrl.title)
}, ctrl.title()),
m("br"),
m("div[contenteditable]", {
style: {border: "1px solid #888"},
onkeyup: m.withAttr("innerHTML", ctrl.title)
}, m.trust(ctrl.title())),
]);
}
m.module(document.getElementById("test"), app);
</script>

135
tests/isolation-test.html Normal file
View file

@ -0,0 +1,135 @@
<!doctype html>
<!--<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.0.3/es5-shim.min.js"></script>-->
<script src="test.js"></script>
<script src="mock.js"></script>
<script src="../mithril.js"></script>
<p>Open the console to see the test report</p>
<script>
function testMithril(mock) {
m.deps(mock)
test(function() {
var root = mock.document.createElement("div")
var retain = false
var flag = true
var loaded1 = null, loaded2 = null, loaded1a = null, loaded2a = null
var Root = {
view: function() {
return flag ? Comp1 : Comp2
}
}
var Comp1 = {
controller: function() {
loaded1 = true
this.onunload = function() {
loaded1 = false
}
},
view: function(ctrl) {
return retain ? {subtree: "retain"} : m("a", {config: function(el, init, ctx) {
if (!init) {
loaded1a = true
ctx.onunload = function() {
loaded1a = false
}
}
}})
}
}
var Comp2 = {
controller: function() {
loaded2 = true
this.onunload = function() {
loaded2 = false
}
},
view: function(ctrl) {
return retain ? {subtree: "retain"} : m("b", {config: function(el, init, ctx) {
if (!init) {
loaded2a = true
ctx.onunload = function() {
loaded2a = false
}
}
}})
}
}
m.mount(root, Root)
mock.requestAnimationFrame.$resolve()
//loaded 1
var result1 = loaded1 === true && loaded2 === null && loaded1a === true && loaded2a === null
retain = true
m.redraw(true)
mock.requestAnimationFrame.$resolve()
//retained
var result2 = loaded1 === true && loaded2 === null && loaded1a === true && loaded2a === null
flag = false
m.redraw(true)
mock.requestAnimationFrame.$resolve()
//loaded 2 while retained: both controllers are alive at the same time because dom element is retained
var result3 = loaded1 === true && loaded2 === true && loaded1a === true && loaded2a === null
retain = false
m.redraw(true)
mock.requestAnimationFrame.$resolve()
//unretained, i.e. 2 is now dynamic
var result4 = loaded1 === false && loaded2 === true && loaded1a === false && loaded2a === true
flag = true
m.redraw(true)
mock.requestAnimationFrame.$resolve()
//loaded 1 while dynamic
var result5 = loaded1 === true && loaded2 === false && loaded1a === true && loaded2a === false
return result1 && result2 && result3 && result4 && result5
})
/*
test(function() {
var root = mock.document.createElement("div")
var redraws = 0, data
var Root = {
view: function() {
return Comp
}
}
var Comp = {
controller: function() {
this.foo = m.request({method: "GET", url: "/foo"})
},
view: function(ctrl) {
redraws++
data = ctrl.foo()
return m("div")
}
}
m.mount(root, Root)
mock.requestAnimationFrame.$resolve()
mock.XMLHttpRequest.$instances.pop().onreadystatechange()
return redraws == 1 && data.url == "/foo"
})
*/
}
//mocks
testMithril(mock.window)
test.print(function(value) {console.log(value)})
</script>

4425
tests/mithril-tests.js Normal file

File diff suppressed because it is too large Load diff

170
tests/mock.js Normal file
View file

@ -0,0 +1,170 @@
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (item) {
for (var i = 0; i < this.length; i++) {
if (this[i] === item) return i
}
return -1
}
}
if (!Array.prototype.map) {
Array.prototype.map = function (callback) {
var results = []
for (var i = 0; i < this.length; i++) {
results[i] = callback(this[i], i, this)
}
return results
}
}
if (!Array.prototype.filter) {
Array.prototype.filter = function (callback) {
var results = []
for (var i = 0; i < this.length; i++) {
if (callback(this[i], i, this)) results.push(this[i])
}
return results
}
}
if (!Object.keys) {
Object.keys = function () {
var keys = []
for (var i in this) keys.push(i)
return keys
}
}
var mock = {}
mock.window = (function () {
var window = {}
window.document = {}
window.document.childNodes = []
window.document.createElement = function (tag) {
return {
style: {},
childNodes: [],
nodeType: 1,
nodeName: tag.toUpperCase(),
appendChild: window.document.appendChild,
removeChild: window.document.removeChild,
replaceChild: window.document.replaceChild,
insertBefore: function (node, reference) {
node.parentNode = this
var referenceIndex = this.childNodes.indexOf(reference)
var index = this.childNodes.indexOf(node)
if (index > -1) this.childNodes.splice(index, 1)
if (referenceIndex < 0) this.childNodes.push(node)
else this.childNodes.splice(referenceIndex, 0, node)
},
insertAdjacentHTML: function (position, html) {
//todo: accept markup
if (position === "beforebegin") {
this.parentNode.insertBefore(window.document.createTextNode(html), this)
}
else if (position === "beforeend") {
this.appendChild(window.document.createTextNode(html))
}
},
setAttribute: function (name, value) {
this[name] = value.toString()
},
setAttributeNS: function (namespace, name, value) {
this.namespaceURI = namespace
this[name] = value.toString()
},
getAttribute: function (name, value) {
return this[name]
},
addEventListener: function () {},
removeEventListener: function () {}
}
}
window.document.createElementNS = function (namespace, tag) {
var element = window.document.createElement(tag)
element.namespaceURI = namespace
return element
}
window.document.createTextNode = function (text) {
return {nodeValue: text.toString()}
}
window.document.documentElement = window.document.createElement("html")
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) {
var index = this.childNodes.indexOf(child)
if (index > -1) this.childNodes.splice(index, 1)
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
}
//getElementsByTagName is only used by JSONP tests, it's not required by Mithril
window.document.getElementsByTagName = function (name){
name = name.toLowerCase()
var out = []
var traverse = function (node){
if (node.childNodes && node.childNodes.length > 0){
node.childNodes.map(function (curr){
if (curr.nodeName.toLowerCase() === name)
out.push(curr)
traverse(curr)
})
}
}
traverse(window.document)
return out
}
window.scrollTo = function () {}
window.cancelAnimationFrame = function () {}
window.requestAnimationFrame = function (callback) {
window.requestAnimationFrame.$callback = callback
return window.requestAnimationFrame.$id++
}
window.requestAnimationFrame.$id = 1
window.requestAnimationFrame.$resolve = function () {
if (window.requestAnimationFrame.$callback) {
var callback = window.requestAnimationFrame.$callback
window.requestAnimationFrame.$callback = null
callback()
}
}
window.XMLHttpRequest = (function () {
var request = function () {
this.$headers = {}
this.setRequestHeader = function (key, value) {
this.$headers[key] = value
}
this.open = function (method, url) {
this.method = method
this.url = url
}
this.send = function () {
this.responseText = JSON.stringify(this)
this.readyState = 4
this.status = 200
request.$instances.push(this)
}
}
request.$instances = []
return request
}())
window.location = {search: "", pathname: "", hash: ""},
window.history = {}
window.history.$$length = 0
window.history.pushState = function (data, title, url) {
window.history.$$length++
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
}())

19
tests/npm-debug.log Normal file
View file

@ -0,0 +1,19 @@
0 info it worked if it ends with ok
1 verbose cli [ 'c:\\Program Files\\nodejs\\node.exe',
1 verbose cli 'c:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js',
1 verbose cli 'test' ]
2 info using npm@1.4.3
3 info using node@v0.10.26
4 error Error: ENOENT, open 'C:\Users\Leo\Desktop\shared\work\mithril.js\tests\package.json'
5 error If you need help, you may report this *entire* log,
5 error including the npm and node versions, at:
5 error <http://github.com/npm/npm/issues>
6 error System Windows_NT 6.1.7601
7 error command "c:\\Program Files\\nodejs\\node.exe" "c:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "test"
8 error cwd C:\Users\Leo\Desktop\shared\work\mithril.js\tests
9 error node -v v0.10.26
10 error npm -v 1.4.3
11 error path C:\Users\Leo\Desktop\shared\work\mithril.js\tests\package.json
12 error code ENOENT
13 error errno 34
14 verbose exit [ 34, true ]

97
tests/svg.html Normal file
View file

@ -0,0 +1,97 @@
<!doctype html>
<html>
<head>
<title>SVG test</title>
<style>
.path {
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
animation: dash 5s linear alternate infinite;
-webkit-animation: dash 5s linear alternate infinite;
}
@keyframes dash {
from {
stroke-dashoffset: 1000;
}
to {
stroke-dashoffset: 0;
}
}
@-webkit-keyframes dash {
from {
stroke-dashoffset: 1000;
}
to {
stroke-dashoffset: 0;
}
}
</style>
</head>
<body>
<p>Since it's not possible to test SVG functionality from a NodeJS environment, this page can be used to test it in a browser.</p>
<p>This page should contain:</p>
<ul>
<li>an HTML link labeled "HTML link"</li>
<li>an SVG link labeled "SVG link"</li>
<li>a tilted blue square</li>
<li>a cat picture</li>
<li>an animated line drawing</li>
<li>a clock with the current time</li>
</ul>
<p>The links should open in a new tab. All items should display title tooltips when hovered over.</p>
<div id="test"></div>
<script src="../mithril.js"></script>
<script>
var svg = [
m("a[href='http://google.com'][target='_blank'][title='HTML link']", "HTML link"),
m("br"),
m("svg[width=180][height=200]", [
m("rect[x=50][y=50][height=100][width=100][transform='translate(30) rotate(45 50 50)'][title='Square']", {style: {stroke: "#000", fill: "#0086b2"}}),
m("a[href='http://google.com'][title='SVG link'][target=_new]", {style: {textDecoration: "underline"}}, [
m("text[x=0][y=20]", "SVG Link")
])
]),
m("svg[height='201px'][width='201px']", [
m("image[href='http://placekitten.com/201/201'][height='200px'][width='200px'][title='Cat picture']")
]),
m("svg[enable-background='new 0 0 340 333'][height='333px'][viewBox='0 0 340 333'][width='340px'][x='0px'][y='0px'][title='Line drawings']", [
m("path.path[d='M66.039,133.545c0,0-21-57,18-67s49-4,65,8s30,41,53,27s66,4,58,32s-5,44,18,57s22,46,0,45s-54-40-68-16s-40,88-83,48s11-61-11-80s-79-7-70-41C46.039,146.545,53.039,128.545,66.039,133.545z'][fill='#FFFFFF'][stroke='#000000'][stroke-miterlimit='10'][stroke-width='4']")
]),
m("svg[height='270px'][width='270px'][viewBox='0 0 270 270']", [
m("g[transform='translate(150,150)'][title='Clock']", [
m("g", [
m("circle[r='108'][fill='none'][stroke-width='4'][stroke='gray']"),
m("circle[r='97'][fill='none'][stroke-width='11'][stroke='black'][stroke-dasharray='4,46.789082'][transform='rotate(-1.5)']"),
m("circle[r='100'][fill='none'][stroke-width='5'][stroke='black'][stroke-dasharray='2,8.471976'][transform='rotate(-.873)']"),
]),
m("g[transform='rotate(180)']", [
m("g[id='hour']", [
m("line[stroke-width='5'][y2='75'][stroke-linecap='round'][stroke='blue'][opacity='.5']"),
m("animateTransform[attributeName='transform'][type='rotate'][repeatCount='indefinite'][dur='12h'][by='360']"),
m("circle[r='7']")
]),
m("g[id='minute']", [
m("line[stroke-width='4'][y2='93'][stroke-linecap='round'][stroke='green'][opacity='.9']"),
m("animateTransform[attributeName='transform'][type='rotate'][repeatCount='indefinite'][dur='60min'][by='360']"),
m("circle[r='6'][fill='red']")
]),
m("g[id='second']", [
m("line[stroke-width='2'][y1='-20'][y2=102][stroke-linecap='round'][stroke='red']"),
m("animateTransform[attributeName='transform'][type='rotate'][repeatCount='indefinite'][dur='60s'][by='360']"),
m("circle[r='4'][fill='blue']")
])
])
]),
m("script", 'var a=new Date,b=parseInt(a.getHours());b=b>12?b-12:b;var c=parseInt(a.getMinutes()),d=parseInt(a.getSeconds()),e=6*d,f=6*(c+d/60),g=30*(b+c/60+d/3600),h=document.getElementById("hour"),i=document.getElementById("minute"),j=document.getElementById("second");h.setAttribute("transform","rotate("+g.toString()+")"),i.setAttribute("transform","rotate("+f.toString()+")"),j.setAttribute("transform","rotate("+e.toString()+")")'),
]),
m("svg[height='200px'][width='200px']", [
m("foreignObject[x=0][y=0][width='100px'][height='100px'][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">SVG foreignObject</strong>')))
])
]
m.render(document.getElementById("test"), svg)
</script>
</body>
</html>

28
tests/test.js Normal file
View file

@ -0,0 +1,28 @@
if (!this.console) {
var log = function (value) { document.write("<pre>" + value + "</pre>") }
this.console = {log: log, error: log}
}
function test(condition) {
test.total++
try {
if (!condition()) throw new Error("failed")
}
catch (e) {
console.error(e)
test.failures.push(condition)
}
}
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)
if (test.failures.length > 0) {
throw new Error(test.failures.length + " tests did not pass")
}
}