Convert tests to Mocha/Chai/Sinon and lint them.
Details: 1. All tests now live in `test`. All test dependencies that aren't from npm live in `test-deps`. 2. The QUnit tests are gone, as well as their dependencies. Half of them duplicated existing tests, and some of them depended on the real DOM to properly test. 3. All tests are now using Mocha to run the tests, Chai for assertions, and Sinon and Sinon Chai for testing some callbacks. 4. Tests are run through mocha-phantomjs. If you want to run just the tests, run `grunt mocha_phantomjs` or fire up a server in the root and open `http://localhost:<port>/test/index.html`, e.g. `python3 -m http.server`. 5. The linter I chose is ESLint. It is relatively easy to configure, but with a lot of flexibility. The rules I chose mostly were in tune to the style the project was already using. I'm not including a style guide in this commit, but one will likely come. You can check out the `.eslintrc` in the root and in `test/` for the two configs. The `.eslintignore` includes a TODO for `mithril.js` itself targeted at me, in the root. Other info: - As a drive-by fix, I fixed line endings on a few of the files. - I also took care of a few other files and linted them as I went: - `Gruntfile.js` - `test/input-cursor.html` (was in `tests/`) - `test/svg.html` (was in `tests/`) - `docs/layout/tools/template-converter.html` - `docs/layout/tools/template-converter.js` I didn't test the template converter after linting it, because it needs further scrutiny to ensure it works with the latest version of Mithril. I know the API has changed a little, which is why I want to be sure. - I simplified the `.travis.yml` file because none of the tests are run directly through Node anymore. They are always run in a browser of some kind. Hopefully, this turned out all right...
This commit is contained in:
parent
8737c7e2c1
commit
12b8f044f1
39 changed files with 6210 additions and 10822 deletions
|
|
@ -1,244 +0,0 @@
|
|||
/**
|
||||
* QUnit v1.12.0 - A JavaScript Unit Testing Framework
|
||||
*
|
||||
* http://qunitjs.com
|
||||
*
|
||||
* Copyright 2012 jQuery Foundation and other contributors
|
||||
* Released under the MIT license.
|
||||
* http://jquery.org/license
|
||||
*/
|
||||
|
||||
/** Font Family and Sizes */
|
||||
|
||||
#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
|
||||
font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
|
||||
#qunit-tests { font-size: smaller; }
|
||||
|
||||
|
||||
/** Resets */
|
||||
|
||||
#qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
/** Header */
|
||||
|
||||
#qunit-header {
|
||||
padding: 0.5em 0 0.5em 1em;
|
||||
|
||||
color: #8699a4;
|
||||
background-color: #0d3349;
|
||||
|
||||
font-size: 1.5em;
|
||||
line-height: 1em;
|
||||
font-weight: normal;
|
||||
|
||||
border-radius: 5px 5px 0 0;
|
||||
-moz-border-radius: 5px 5px 0 0;
|
||||
-webkit-border-top-right-radius: 5px;
|
||||
-webkit-border-top-left-radius: 5px;
|
||||
}
|
||||
|
||||
#qunit-header a {
|
||||
text-decoration: none;
|
||||
color: #c2ccd1;
|
||||
}
|
||||
|
||||
#qunit-header a:hover,
|
||||
#qunit-header a:focus {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#qunit-testrunner-toolbar label {
|
||||
display: inline-block;
|
||||
padding: 0 .5em 0 .1em;
|
||||
}
|
||||
|
||||
#qunit-banner {
|
||||
height: 5px;
|
||||
}
|
||||
|
||||
#qunit-testrunner-toolbar {
|
||||
padding: 0.5em 0 0.5em 2em;
|
||||
color: #5E740B;
|
||||
background-color: #eee;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#qunit-userAgent {
|
||||
padding: 0.5em 0 0.5em 2.5em;
|
||||
background-color: #2b81af;
|
||||
color: #fff;
|
||||
text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
|
||||
}
|
||||
|
||||
#qunit-modulefilter-container {
|
||||
float: right;
|
||||
}
|
||||
|
||||
/** Tests: Pass/Fail */
|
||||
|
||||
#qunit-tests {
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
#qunit-tests li {
|
||||
padding: 0.4em 0.5em 0.4em 2.5em;
|
||||
border-bottom: 1px solid #fff;
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#qunit-tests li strong {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#qunit-tests li a {
|
||||
padding: 0.5em;
|
||||
color: #c2ccd1;
|
||||
text-decoration: none;
|
||||
}
|
||||
#qunit-tests li a:hover,
|
||||
#qunit-tests li a:focus {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
#qunit-tests li .runtime {
|
||||
float: right;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
.qunit-assert-list {
|
||||
margin-top: 0.5em;
|
||||
padding: 0.5em;
|
||||
|
||||
background-color: #fff;
|
||||
|
||||
border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
}
|
||||
|
||||
.qunit-collapsed {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#qunit-tests table {
|
||||
border-collapse: collapse;
|
||||
margin-top: .2em;
|
||||
}
|
||||
|
||||
#qunit-tests th {
|
||||
text-align: right;
|
||||
vertical-align: top;
|
||||
padding: 0 .5em 0 0;
|
||||
}
|
||||
|
||||
#qunit-tests td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#qunit-tests pre {
|
||||
margin: 0;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
#qunit-tests del {
|
||||
background-color: #e0f2be;
|
||||
color: #374e0c;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#qunit-tests ins {
|
||||
background-color: #ffcaca;
|
||||
color: #500;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/*** Test Counts */
|
||||
|
||||
#qunit-tests b.counts { color: black; }
|
||||
#qunit-tests b.passed { color: #5E740B; }
|
||||
#qunit-tests b.failed { color: #710909; }
|
||||
|
||||
#qunit-tests li li {
|
||||
padding: 5px;
|
||||
background-color: #fff;
|
||||
border-bottom: none;
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
/*** Passing Styles */
|
||||
|
||||
#qunit-tests li li.pass {
|
||||
color: #3c510c;
|
||||
background-color: #fff;
|
||||
border-left: 10px solid #C6E746;
|
||||
}
|
||||
|
||||
#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
|
||||
#qunit-tests .pass .test-name { color: #366097; }
|
||||
|
||||
#qunit-tests .pass .test-actual,
|
||||
#qunit-tests .pass .test-expected { color: #999999; }
|
||||
|
||||
#qunit-banner.qunit-pass { background-color: #C6E746; }
|
||||
|
||||
/*** Failing Styles */
|
||||
|
||||
#qunit-tests li li.fail {
|
||||
color: #710909;
|
||||
background-color: #fff;
|
||||
border-left: 10px solid #EE5757;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
#qunit-tests > li:last-child {
|
||||
border-radius: 0 0 5px 5px;
|
||||
-moz-border-radius: 0 0 5px 5px;
|
||||
-webkit-border-bottom-right-radius: 5px;
|
||||
-webkit-border-bottom-left-radius: 5px;
|
||||
}
|
||||
|
||||
#qunit-tests .fail { color: #000000; background-color: #EE5757; }
|
||||
#qunit-tests .fail .test-name,
|
||||
#qunit-tests .fail .module-name { color: #000000; }
|
||||
|
||||
#qunit-tests .fail .test-actual { color: #EE5757; }
|
||||
#qunit-tests .fail .test-expected { color: green; }
|
||||
|
||||
#qunit-banner.qunit-fail { background-color: #EE5757; }
|
||||
|
||||
|
||||
/** Result */
|
||||
|
||||
#qunit-testresult {
|
||||
padding: 0.5em 0.5em 0.5em 2.5em;
|
||||
|
||||
color: #2b81af;
|
||||
background-color: #D2E0E6;
|
||||
|
||||
border-bottom: 1px solid white;
|
||||
}
|
||||
#qunit-testresult .module-name {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/** Fixture */
|
||||
|
||||
#qunit-fixture {
|
||||
position: absolute;
|
||||
top: -10000px;
|
||||
left: -10000px;
|
||||
width: 1000px;
|
||||
height: 1000px;
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,18 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Basic Test Suite</title>
|
||||
<!-- Load local QUnit. -->
|
||||
<link rel="stylesheet" href="libs/qunit.css" media="screen">
|
||||
<script src="libs/qunit.js"></script>
|
||||
<!-- Load local lib and tests. -->
|
||||
<script src="libs/syn.js"></script>
|
||||
<script src="../../mithril.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="qunit"></div>
|
||||
<div id="dummy"></div>
|
||||
</body>
|
||||
<script src="tests.js"></script>
|
||||
</html>
|
||||
|
|
@ -1,437 +0,0 @@
|
|||
//saucelabs reporting; see https://github.com/axemclion/grunt-saucelabs#test-result-details-with-qunit
|
||||
|
||||
var log = []
|
||||
|
||||
QUnit.done(function (test_results) {
|
||||
var tests = []
|
||||
for (var i = 0, len = log.length; i < len; i++) {
|
||||
var details = log[i]
|
||||
tests.push({
|
||||
name: details.name,
|
||||
result: details.result,
|
||||
expected: details.expected,
|
||||
actual: details.actual,
|
||||
source: details.source
|
||||
})
|
||||
}
|
||||
test_results.tests = tests
|
||||
|
||||
window.global_test_results = test_results
|
||||
})
|
||||
QUnit.testStart(function (testDetails) {
|
||||
QUnit.log(function (details) {
|
||||
if (!details.result) {
|
||||
details.name = testDetails.name
|
||||
log.push(details)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
//qunit doesn't support Function.prototype.bind...
|
||||
if (!Function.prototype.bind) {
|
||||
Function.prototype.bind = function (oThis) {
|
||||
if (typeof this !== "function") {
|
||||
// closest thing possible to the ECMAScript 5
|
||||
// internal IsCallable function
|
||||
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable")
|
||||
}
|
||||
|
||||
var aArgs = Array.prototype.slice.call(arguments, 1),
|
||||
fToBind = this,
|
||||
fNOP = function () {},
|
||||
fBound = function () {
|
||||
return fToBind.apply(this instanceof fNOP && oThis
|
||||
? this
|
||||
: oThis,
|
||||
aArgs.concat(Array.prototype.slice.call(arguments)))
|
||||
}
|
||||
|
||||
fNOP.prototype = this.prototype
|
||||
fBound.prototype = new fNOP()
|
||||
|
||||
return fBound
|
||||
}
|
||||
}
|
||||
|
||||
//tests
|
||||
var dummyEl = document.getElementById('dummy')
|
||||
|
||||
test('Mithril accessible as window.m', function() {
|
||||
expect(1)
|
||||
ok(window.m)
|
||||
})
|
||||
|
||||
test('m.trust w/ html entities', function() {
|
||||
expect(1)
|
||||
var view1 = m('div', "a", m.trust("&"), "b")
|
||||
|
||||
m.render(dummyEl, view1)
|
||||
equal(dummyEl.innerHTML, '<div>a&b</div>', 'view1 rendered correctly')
|
||||
})
|
||||
|
||||
test('m.trust w/ html entities 2', function() {
|
||||
expect(1)
|
||||
var view1 = m('div', "a", m.trust("&"), "b", m.trust("&"), "c")
|
||||
|
||||
m.render(dummyEl, view1)
|
||||
equal(dummyEl.innerHTML, '<div>a&b&c</div>', 'view1 rendered correctly')
|
||||
})
|
||||
|
||||
test('array item removal', function() {
|
||||
expect(2)
|
||||
var view1 = m('div', {}, [
|
||||
m('div', {}, '0'),
|
||||
m('div', {}, '1'),
|
||||
m('div', {}, '2')
|
||||
])
|
||||
|
||||
var view2 = m('div', {}, [
|
||||
m('div', {}, '0')
|
||||
])
|
||||
|
||||
m.render(dummyEl, view1)
|
||||
equal(dummyEl.innerHTML, '<div><div>0</div><div>1</div><div>2</div></div>', 'view1 rendered correctly')
|
||||
|
||||
m.render(dummyEl, view2)
|
||||
equal(dummyEl.innerHTML, '<div><div>0</div></div>', 'view2 should be rendered correctly')
|
||||
})
|
||||
|
||||
test('issue99 regression', function() {
|
||||
// see https://github.com/lhorie/mithril.js/issues/99
|
||||
expect(2)
|
||||
var view1 = m('div', {}, [
|
||||
m('div', {}, '0'),
|
||||
m('div', {}, '1'),
|
||||
m('div', {}, '2')
|
||||
])
|
||||
|
||||
var view2 = m('div', {}, [
|
||||
m('span', {}, '0')
|
||||
])
|
||||
|
||||
m.render(dummyEl, view1)
|
||||
equal(dummyEl.innerHTML, '<div><div>0</div><div>1</div><div>2</div></div>', 'view1 rendered correctly')
|
||||
|
||||
m.render(dummyEl, view2)
|
||||
equal(dummyEl.innerHTML, '<div><span>0</span></div>', 'view2 should be rendered correctly')
|
||||
})
|
||||
|
||||
test('config handler context', function() {
|
||||
expect(3)
|
||||
var view = m('div', {config: function(evt, isInitialized, context) {
|
||||
equal(context instanceof Object, true)
|
||||
context.data = 1
|
||||
}})
|
||||
m.render(dummyEl, view)
|
||||
|
||||
view = m('div', {config: function(evt, isInitialized, context) {
|
||||
equal(context instanceof Object, true)
|
||||
equal(context.data, 1)
|
||||
}})
|
||||
m.render(dummyEl, view)
|
||||
})
|
||||
|
||||
test('node identity remove firstChild', function() {
|
||||
expect(2)
|
||||
var view1 = m('div', {}, [
|
||||
m('div', {key:1}, 'E1'),
|
||||
m('div', {key:2}, 'E2')
|
||||
])
|
||||
m.render(dummyEl, view1)
|
||||
|
||||
var node2 = dummyEl.firstChild.lastChild
|
||||
equal(node2.innerHTML, 'E2')
|
||||
|
||||
var view2 = m('div', {}, [
|
||||
m('div', {key:2}, 'E2')
|
||||
])
|
||||
m.render(dummyEl, view2)
|
||||
|
||||
equal(dummyEl.firstChild.firstChild, node2)
|
||||
})
|
||||
|
||||
test('node identity change order', function() {
|
||||
expect(2)
|
||||
var view1 = m('div', {}, [
|
||||
m('div', {key:1}, 'E1'),
|
||||
m('div', {key:2}, 'E2'),
|
||||
m('div', {key:3}, 'E3')
|
||||
])
|
||||
m.render(dummyEl, view1)
|
||||
|
||||
var e2 = dummyEl.firstChild.firstChild.nextSibling
|
||||
equal(e2.innerHTML, 'E2')
|
||||
|
||||
var view2 = m('div', {}, [
|
||||
m('div', {key:2}, 'E2'),
|
||||
m('div', {key:1}, 'E1'),
|
||||
m('div', {key:3}, 'E3')
|
||||
])
|
||||
m.render(dummyEl, view2)
|
||||
|
||||
equal(dummyEl.firstChild.firstChild, e2)
|
||||
})
|
||||
|
||||
test('node identity remove in the middle', function() {
|
||||
expect(2)
|
||||
var view1 = m('div', {}, [
|
||||
m('div', {key:1}, 'E1'),
|
||||
m('div', {key:2}, 'E2'),
|
||||
m('div', {key:3}, 'E3')
|
||||
])
|
||||
m.render(dummyEl, view1)
|
||||
|
||||
var e3 = dummyEl.firstChild.lastChild
|
||||
equal(e3.innerHTML, 'E3')
|
||||
|
||||
var view2 = m('div', {}, [
|
||||
m('div', {key:1}, 'E1'),
|
||||
m('div', {key:3}, 'E3')
|
||||
])
|
||||
m.render(dummyEl, view2)
|
||||
|
||||
equal(dummyEl.firstChild.firstChild.nextSibling, e3)
|
||||
})
|
||||
|
||||
test('node identity remove last', function() {
|
||||
expect(4)
|
||||
var view1 = m('div', {}, [
|
||||
m('div', {key:1}, 'E1'),
|
||||
m('div', {key:2}, 'E2'),
|
||||
m('div', {key:3}, 'E3')
|
||||
])
|
||||
m.render(dummyEl, view1)
|
||||
|
||||
var e1 = dummyEl.firstChild.firstChild
|
||||
equal(e1.innerHTML, 'E1')
|
||||
var e2 = dummyEl.firstChild.firstChild.nextSibling
|
||||
equal(e2.innerHTML, 'E2')
|
||||
|
||||
var view2 = m('div', {}, [
|
||||
m('div', {key:1}, 'E1'),
|
||||
m('div', {key:2}, 'E2')
|
||||
])
|
||||
m.render(dummyEl, view2)
|
||||
|
||||
equal(dummyEl.firstChild.firstChild, e1)
|
||||
equal(dummyEl.firstChild.firstChild.nextSibling, e2)
|
||||
})
|
||||
|
||||
test('node identity shuffle and remove', function() {
|
||||
expect(8)
|
||||
var view1 = m('div', {}, [
|
||||
m('div', {key:1}, 'E1'),
|
||||
m('div', {key:2}, 'E2'),
|
||||
m('div', {key:3}, 'E3'),
|
||||
m('div', {key:4}, 'E4'),
|
||||
m('div', {key:5}, 'E5')
|
||||
])
|
||||
m.render(dummyEl, view1)
|
||||
|
||||
var e1 = dummyEl.firstChild.firstChild
|
||||
equal(e1.innerHTML, 'E1')
|
||||
var e2 = e1.nextSibling
|
||||
equal(e2.innerHTML, 'E2')
|
||||
var e3 = e2.nextSibling
|
||||
equal(e3.innerHTML, 'E3')
|
||||
var e4 = e3.nextSibling
|
||||
equal(e4.innerHTML, 'E4')
|
||||
var e5 = e4.nextSibling
|
||||
equal(e5.innerHTML, 'E5')
|
||||
|
||||
var view2 = m('div', {}, [
|
||||
m('div', {key:4}, 'E4'),
|
||||
m('div', {key:10}, 'E10'),
|
||||
m('div', {key:1}, 'E1'),
|
||||
m('div', {key:2}, 'E2')
|
||||
])
|
||||
m.render(dummyEl, view2)
|
||||
|
||||
equal(dummyEl.firstChild.firstChild, e4, 'e4 is first element')
|
||||
equal(dummyEl.firstChild.firstChild.nextSibling.nextSibling, e1, 'e1 is third element')
|
||||
equal(dummyEl.firstChild.firstChild.nextSibling.nextSibling.nextSibling, e2, 'e2 is fourth element')
|
||||
})
|
||||
|
||||
asyncTest('issue214 regression', function() {
|
||||
// see https://github.com/lhorie/mithril.js/issues/214
|
||||
expect(2)
|
||||
|
||||
function controller() {
|
||||
this.inputValue = m.prop('')
|
||||
}
|
||||
|
||||
function view(ctrl) {
|
||||
return m('input#testinput', {
|
||||
value: ctrl.inputValue(),
|
||||
onkeyup: m.withAttr('value', ctrl.inputValue)
|
||||
})
|
||||
}
|
||||
|
||||
var ctrl = m.module(dummyEl, { controller: controller, view: view })
|
||||
|
||||
Syn.click({}, 'testinput')
|
||||
.type('0').delay(10)
|
||||
.type('1').delay(10)
|
||||
.type('2').delay(10)
|
||||
.type('3').delay(10)
|
||||
.type('4').delay(10)
|
||||
.type('5').delay(10)
|
||||
.type('6').delay(10)
|
||||
.type('7').delay(10)
|
||||
.type('8').delay(10)
|
||||
.type('9').delay(10)
|
||||
.type('a').delay(10)
|
||||
.type('b').delay(10)
|
||||
.type('c').delay(10)
|
||||
.type('d').delay(10)
|
||||
.type('e').delay(10)
|
||||
.type('f').delay(10)
|
||||
.type('0').delay(10)
|
||||
.type('1').delay(10)
|
||||
.type('2').delay(10)
|
||||
.type('3').delay(10)
|
||||
.type('4').delay(10)
|
||||
.type('5').delay(10)
|
||||
.type('6').delay(10)
|
||||
.type('7').delay(10)
|
||||
.type('8').delay(10)
|
||||
.type('9').delay(10)
|
||||
.type('a').delay(10)
|
||||
.type('b').delay(10)
|
||||
.type('c').delay(10)
|
||||
.type('d').delay(10)
|
||||
.type('e').delay(10)
|
||||
.type('f').delay(10)
|
||||
.type('0').delay(10)
|
||||
.type('1').delay(10)
|
||||
.type('2').delay(10)
|
||||
.type('3').delay(10)
|
||||
.type('4').delay(10)
|
||||
.type('5').delay(10)
|
||||
.type('6').delay(10)
|
||||
.type('7').delay(10)
|
||||
.type('8').delay(10)
|
||||
.type('9').delay(10)
|
||||
.type('a').delay(10)
|
||||
.type('b').delay(10)
|
||||
.type('c').delay(10)
|
||||
.type('d').delay(10)
|
||||
.type('e').delay(10)
|
||||
.type('f').delay(10)
|
||||
.type('0').delay(10)
|
||||
.type('1').delay(10)
|
||||
.type('2').delay(10)
|
||||
.type('3').delay(10)
|
||||
.type('4').delay(10)
|
||||
.type('5').delay(10)
|
||||
.type('6').delay(10)
|
||||
.type('7').delay(10)
|
||||
.type('8').delay(10)
|
||||
.type('9').delay(10)
|
||||
.type('a').delay(10)
|
||||
.type('b').delay(10)
|
||||
.type('c').delay(10)
|
||||
.type('d').delay(10)
|
||||
.type('e').delay(10)
|
||||
.type('f', function() {
|
||||
equal(ctrl.inputValue(), '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef')
|
||||
equal(document.getElementById('testinput').value, '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef')
|
||||
start()
|
||||
})
|
||||
})
|
||||
|
||||
asyncTest('issue288 regression', function() {
|
||||
// see https://github.com/lhorie/mithril.js/issues/288
|
||||
expect(2)
|
||||
|
||||
function controller() {
|
||||
this.inputValue = m.prop('')
|
||||
|
||||
this.submit = function() {
|
||||
if (this.inputValue()) {
|
||||
this.inputValue('')
|
||||
}
|
||||
}.bind(this);
|
||||
}
|
||||
|
||||
function view(ctrl) {
|
||||
return m('form', { onsubmit: ctrl.submit }, [
|
||||
m('input#testinput', {
|
||||
onkeyup: m.withAttr('value', ctrl.inputValue),
|
||||
value: ctrl.inputValue()
|
||||
}),
|
||||
m('button[type=submit]')
|
||||
])
|
||||
}
|
||||
|
||||
var ctrl = m.module(dummyEl, { controller: controller, view: view })
|
||||
|
||||
Syn.click({}, 'testinput')
|
||||
.type('a').delay(10)
|
||||
.type('b').delay(10)
|
||||
.type('c').delay(10)
|
||||
.type('d').delay(10)
|
||||
.type('[enter]', function() {
|
||||
equal(ctrl.inputValue(), '')
|
||||
equal(document.getElementById('testinput').value, '')
|
||||
start()
|
||||
})
|
||||
})
|
||||
|
||||
test('issue278 regression', function() {
|
||||
// see https://github.com/lhorie/mithril.js/issues/278
|
||||
expect(1)
|
||||
|
||||
var test = {
|
||||
controller: function() {
|
||||
this.values = [1, 2, 3, 4, 5]
|
||||
this.value = m.prop([2, 3])
|
||||
},
|
||||
|
||||
view: function(ctrl) {
|
||||
return m('select#testselect', {
|
||||
size: ctrl.values.length,
|
||||
multiple: 'multiple'
|
||||
}, [
|
||||
ctrl.values.map(function(v){
|
||||
var opts = {value: v}
|
||||
if (ctrl.value().indexOf(v) !== -1) opts.selected = 'selected'
|
||||
return m('option', opts, v)
|
||||
})
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
m.render(dummyEl, test.view(new test.controller))
|
||||
|
||||
var select = document.getElementById('testselect')
|
||||
|
||||
for (var i = 0, selected = 0; i < select.options.length; i++) {
|
||||
if (select.options[i].selected) selected++
|
||||
}
|
||||
|
||||
equal(selected, 2)
|
||||
})
|
||||
test("mixing trusted content", function() {
|
||||
m.render(dummyEl, [m.trust("<p>1</p><p>2</p>"), m("i", "foo")])
|
||||
equal(dummyEl.childNodes[2].nodeName, "I")
|
||||
})
|
||||
test("mixing trusted content w/ text nodes", function() {
|
||||
m.render(dummyEl, [m.trust("<p>1</p>123<p>2</p>"), m("i", "foo")])
|
||||
equal(dummyEl.childNodes[3].nodeName, "I")
|
||||
})
|
||||
test("mixing trusted content w/ td", function() {
|
||||
m.render(dummyEl, [m.trust("<td>1</td><td>2</td>"), m("i", "foo")])
|
||||
equal(dummyEl.childNodes[1].nodeName, "I")
|
||||
})
|
||||
|
||||
test("0 should not be treated as empty string", function() {
|
||||
m.render(dummyEl, m("input", {value: ""}))
|
||||
m.render(dummyEl, m("input", {value: 0}))
|
||||
equal(dummyEl.childNodes[0].value, "0")
|
||||
})
|
||||
|
||||
test("empty value in <option> should show as attribute", function() {
|
||||
m.render(dummyEl, m("select", m("option", {value: ""}, "aaa")))
|
||||
equal(dummyEl.childNodes[0].innerHTML, '<option value="">aaa</option>')
|
||||
})
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
<!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>
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
<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>
|
||||
File diff suppressed because it is too large
Load diff
172
tests/mock.js
172
tests/mock.js
|
|
@ -1,172 +0,0 @@
|
|||
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
|
||||
}())
|
||||
|
|
@ -1,97 +0,0 @@
|
|||
<!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>
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
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")
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue