m.fragment docs

public api tests
This commit is contained in:
Leo Horie 2016-08-24 00:26:15 -04:00
parent 53a83a58f2
commit ec07d76fcd
9 changed files with 291 additions and 18 deletions

View file

@ -6,14 +6,18 @@
<body>
<script src="../../module/module.js"></script>
<script src="../../ospec/ospec.js"></script>
<script src="../../querystring/parse.js"></script>
<script src="../../test-utils/callAsync.js"></script>
<script src="../../test-utils/parseURL.js"></script>
<script src="../../test-utils/domMock.js"></script>
<script src="../../test-utils/pushStateMock.js"></script>
<script src="../../test-utils/xhrMock.js"></script>
<script src="../../test-utils/browserMock.js"></script>
<script src="../../util/stream.js"></script>
<script src="../../render/vnode.js"></script>
<script src="../../render/trust.js"></script>
<script src="../../render/fragment.js"></script>
<script src="../../render/hyperscript.js"></script>
<script src="../../render/render.js"></script>
<script src="../../querystring/build.js"></script>

View file

@ -2,8 +2,7 @@
var o = require("../../ospec/ospec")
var callAsync = require("../../test-utils/callAsync")
var pushStateMock = require("../../test-utils/pushStateMock")
var domMock = require("../../test-utils/domMock")
var browserMock = require("../../test-utils/browserMock")
var m = require("../../render/hyperscript")
var coreRenderer = require("../../render/render")
@ -18,13 +17,7 @@ o.spec("route", function() {
var $window, root, redraw, route
o.beforeEach(function() {
$window = {}
var dom = domMock()
for (var key in dom) $window[key] = dom[key]
var loc = pushStateMock(env)
for (var key in loc) $window[key] = loc[key]
$window = browserMock(env)
root = $window.document.body

View file

@ -88,15 +88,7 @@ function traverseDirectory(pathname, callback) {
}
//init mocks
var domMock = require("../test-utils/domMock")()
var xhrMock = require("../test-utils/xhrMock")()
var pushStateMock = require("../test-utils/pushStateMock")()
global.window = {}
for (var key in domMock) if (!window[key]) window[key] = domMock[key]
for (var key in xhrMock) if (!window[key]) window[key] = xhrMock[key]
for (var key in pushStateMock) if (!window[key]) window[key] = pushStateMock[key]
global.window = require("../test-utils/browserMock")()
global.document = window.document
global.m = require("../index")

43
docs/fragment.md Normal file
View file

@ -0,0 +1,43 @@
# fragment(html)
- [API](#api)
- [How it works](#how-it-works)
---
### API
Generates a trusted HTML [vnode](vnodes.md)
`vnode = m.fragment(attrs, children)`
Argument | Type | Required | Description
----------- | -------------------- | -------- | ---
`attrs` | `Object` | Yes | A map of attributes
`children` | `Array<Vnode>` | Yes | A list of vnodes
**returns** | `Vnode` | | A fragment [vnode](vnodes.md)
[How to read signatures](signatures.md)
---
### How it works
`m.fragment()` creates a [fragment vnode](vnodes.md) with attributes. It is meant for advanced use cases involving keys or lifecyle methods.
Normally you can use simple arrays instead to denote a list of child nodes or a range of nodes within a node list:
```javascript
var groupVisible = true
m("ul", [
m("li", "child 1"),
m("li", "child 2"),
groupVisible ? [
m("li", "child 3"),
m("li", "child 4"),
] : null
])
```
There are a few benefits that come from using `m.fragment` instead of handwriting a vnode object structure: m.fragment creates [monomorphic objects](vnodes.md#monomorphic-objects), which have better performance characteristics than creating objects dynamically. In addition, using `m.fragment` makes your intentions clear, and it makes it less likely that you'll mistakenly set attributes on the vnode object rather than on the attrs object.

View file

@ -65,4 +65,7 @@ function hyperscript(selector) {
return Vnode(selector, attrs && attrs.key, attrs || {}, Vnode.normalizeChildren(children), undefined, undefined)
}
hyperscript.trust = require("./trust")
hyperscript.fragment = require("./fragment")
module.exports = hyperscript

View file

@ -11,10 +11,12 @@
<script src="../../render/vnode.js"></script>
<script src="../../render/trust.js"></script>
<script src="../../render/fragment.js"></script>
<script src="../../render/hyperscript.js"></script>
<script src="../../render/render.js"></script>
<script src="test-hyperscript.js"></script>
<script src="test-trust.js"></script>
<script src="test-fragment.js"></script>
<script src="test-normalize.js"></script>
<script src="test-normalizeChildren.js"></script>
<script src="test-createText.js"></script>

18
test-utils/browserMock.js Normal file
View file

@ -0,0 +1,18 @@
"use strict"
var pushStateMock = require("./pushStateMock")
var domMock = require("./domMock")
var xhrMock = require("./xhrMock")
module.exports = function(env) {
var $window = {}
var dom = domMock()
var xhr = xhrMock()
var ps = pushStateMock(env)
for (var key in dom) if (!$window[key]) $window[key] = dom[key]
for (var key in xhr) if (!$window[key]) $window[key] = xhr[key]
for (var key in ps) if (!$window[key]) $window[key] = ps[key]
return $window
}

21
tests/index.html Normal file
View file

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script src="../module/module.js"></script>
<script src="../ospec/ospec.js"></script>
<script src="../querystring/parse.js"></script>
<script src="../test-utils/parseURL.js"></script>
<script src="../test-utils/callAsync.js"></script>
<script src="../test-utils/domMock.js"></script>
<script src="../test-utils/pushStateMock.js"></script>
<script src="../test-utils/xhrMock.js"></script>
<script src="../test-utils/browserMock.js"></script>
<script src="../mithril.js"></script>
<script src="test-api.js"></script>
<script>require("../ospec/ospec").run()</script>
</body>
</html>

197
tests/test-api.js Normal file
View file

@ -0,0 +1,197 @@
"use strict"
var o = require("../ospec/ospec")
var browserMock = require("../test-utils/browserMock")
o.spec("api", function() {
var m
var FRAME_BUDGET = Math.floor(1000 / 60)
o.beforeEach(function() {
var mock = browserMock()
if (typeof global !== "undefined") global.window = mock, global.document = mock.document
m = require("../mithril")
})
o.spec("m", function() {
o("works", function() {
var vnode = m("div")
o(vnode.tag).equals("div")
})
})
o.spec("m.version", function() {
o("works", function() {
o(typeof m.version).equals("string")
o(m.version.indexOf(".") > -1).equals(true)
o(/\d/.test(m.version)).equals(true)
})
})
o.spec("m.trust", function() {
o("works", function() {
var vnode = m.trust("<br>")
o(vnode.tag).equals("<")
o(vnode.children).equals("<br>")
})
})
o.spec("m.fragment", function() {
o("works", function() {
var vnode = m.fragment({key: 123}, [m("div")])
o(vnode.tag).equals("[")
o(vnode.key).equals(123)
o(vnode.children.length).equals(1)
o(vnode.children[0].tag).equals("div")
})
})
o.spec("m.prop", function() {
o("works", function() {
var stream = m.prop(5)
var doubled = stream.run(function(value) {return value * 2})
o(doubled()).equals(10)
})
o("m.prop.combine works", function() {
var added = m.prop.combine(function(a, b) {return a() + b()}, [
m.prop(1),
m.prop(2),
])
o(added()).equals(3)
})
o("m.prop.merge works", function() {
var added = m.prop.merge([
m.prop(1),
m.prop(2),
])
.run(function(values) {return values[0] + values[1]})
o(added()).equals(3)
})
o("m.prop.reject works", function() {
var stream = m.prop.reject(new Error("error"))
o(stream.error().message).equals("error")
})
})
o.spec("m.withAttr", function() {
o("works", function() {
var spy = o.spy()
var handler = m.withAttr("value", spy)
handler({currentTarget: {value: 10}})
o(spy.args[0]).equals(10)
})
})
o.spec("m.parseQueryString", function() {
o("works", function() {
var query = m.parseQueryString("?a=1&b=2")
o(query).deepEquals({a: 1, b: 2})
})
})
o.spec("m.buildQueryString", function() {
o("works", function() {
var query = m.buildQueryString({a: 1, b: 2})
o(query).equals("a=1&b=2")
})
})
o.spec("m.render", function() {
o("works", function() {
var root = window.document.createElement("div")
m.render(root, m("div"))
o(root.childNodes.length).equals(1)
o(root.firstChild.nodeName).equals("DIV")
})
})
o.spec("m.mount", function() {
o("works", function() {
var root = window.document.createElement("div")
m.mount(root, {view: function() {return m("div")}})
o(root.childNodes.length).equals(1)
o(root.firstChild.nodeName).equals("DIV")
})
})
o.spec("m.route", function() {
o("works", function(done) {
var root = window.document.createElement("div")
m.route(root, "/a", {
"/a": {view: function() {return m("div")}}
})
setTimeout(function() {
o(root.childNodes.length).equals(1)
o(root.firstChild.nodeName).equals("DIV")
done()
}, FRAME_BUDGET)
})
o("m.route.prefix", function(done) {
var root = window.document.createElement("div")
m.route.prefix("#")
m.route(root, "/a", {
"/a": {view: function() {return m("div")}}
})
setTimeout(function() {
o(root.childNodes.length).equals(1)
o(root.firstChild.nodeName).equals("DIV")
done()
}, FRAME_BUDGET)
})
o("m.route.get", function(done) {
var root = window.document.createElement("div")
m.route(root, "/a", {
"/a": {view: function() {return m("div")}}
})
setTimeout(function() {
o(m.route.get()).equals("/a")
done()
}, FRAME_BUDGET)
})
o("m.route.set", function(done) {
var root = window.document.createElement("div")
m.route(root, "/a", {
"/:id": {view: function() {return m("div")}}
})
setTimeout(function() {
m.route.set("/b")
o(m.route.get()).equals("/b")
done()
}, FRAME_BUDGET)
})
})
o.spec("m.redraw", function() {
o("works", function(done) {
var count = 0
var root = window.document.createElement("div")
m.mount(root, {view: function() {count++}})
setTimeout(function() {
m.redraw()
o(count).equals(2)
done()
}, FRAME_BUDGET)
})
})
o.spec("m.request", function() {
o("works", function() {
o(typeof m.request).equals("function") // TODO improve
})
})
o.spec("m.jsonp", function() {
o("works", function() {
o(typeof m.jsonp).equals("function") // TODO improve
})
})
})