Its inside the node core. This are things that we wanna test.
- assert.ok
- assert.equal
- assert.deepEqaul()
- assert.notOk()
- assert.notEqual()
var assert = require('assert')
var fs = require('fs')
assert.equal(1+2, 3)
countLines((err, n) => {
assert.ifError(err)
assert.equal(n, 3)
})
function countLines () {
fs.readFile('file.txt', 'utf8', function (err, src) {
if (err) cb(err)
else cb(null, src.trim().split('\n').length)
})
}
- exceptions stop execution
- false positive when test blocks don't run
old text protocol from the perl test suite
- test cases begin with ok/not ok
- must plain out a number of assertions
var test = require('tape')
test('this test has a name', t => {
t.equal(1+1, 2)
t.equal(1+1, 2)
t.end()
})
test('this test has a name', t => {
t.plan(2)
t.equal(1+1, 2)
t.equal(1+1, 2)
})
It executes all the assertions. Without blocking it. Its easy to support async test.
var test = require('tape')
test('this test has a name', t => {
t.plan(3)
t.equal(1+1, 2)
t.equal(1+1, 2)
setTimeout(() => {
t.ok(true)
})
})
How much of your code gets run when you test-
data structure for code
Some libraries:
- acorn
nyc
or coverify
for code-coverage
Some automation scripts.
run tests every time you push code
On travis just use .travis.yml
language: node_js
node_js:
- "7"
- "6"
- "4"
example markdown and put the build status on the readme
====
The web is these:
- service workers
- template strings
- redux architecture
but also these:
- indexDB
- webaudio
- webgl
echo '{}' > package.json
npm install --save ...
var n = 5
console.log(`hi
n=${n}
wow
`)
var n = 5
console.log(tag`hi
n=${n}
wow
`)
console.log(['hi'\n n=', '\n wow'], n)
function tag (strings) {
return arguments
}
var hyperx = require('hyperx')
var html = hyperx((tagName, props, children) => {
console.log(tagName, props, children)
})
var n = 3
console.log(html`<div><h1>${n*1000}</h1></div>`)
dom diffing with real DOM nodes
- faster in some cases than a virtual dom
- interop with vanilla DOM modules
In the server
var html = require('yo-yo')
var n = 5
console.log(html`<div>
<h1>${n}</h1>
</div>`.toString())
In the browser
var html = require('yo-yo')
var n = 5
var x = 0
var root = document.body.appendChild(document.createElement('div'))
update()
function update() {
html.update(root, html`<div>
<h1>${n}</h1>
<div>${x}</div>
<button onclick=${onclick}>CLICK ME</button>
</div>`)
function onclick() {
x++
update()
}
}
var html = require('yo-yo')
var state = {
n: 5,
x: 0
}
var EventEmitter = require('events')
var bus = new EventEmitter
require('./reduce.js')(bus, state)
var root = document.body.appendChild(document.createElement('div'))
update()
bus.on('update', update)
function update() {
html.update(root, html`<div>
<h1>${n}</h1>
<div>${x}</div>
<button onclick=${onclick}>CLICK ME</button>
</div>`)
function onclick() {
bus.emit('increment-x')
}
}
reduce.js
module.export = function (bus, state) {
bus.on('increment-n', () => {
state.n++
bus.emit('update')
})
bus.on('increment-n', () => {
state.x = (state.x +1) % 4
bus.emit('update')
})
}
server.js
var wsock = require('websocket-stream')
var http = require('http')
var onend = require('end-of-stream')
var ecstatic = require('ecstatic')
var st = ecstatic(__dirname + '/public')
var server = http.createServer((req, res) => {
st(req, res)
})
server.listen(5000)
var count = 0
var streams = []
wsock.createServer({server}, stream => {
streams.push(stream) // adding the stream to our streams
count++
// for each stream write the counter
streams.forEach(s => {
s.write(count + '\n')
})
onend(stream, () => {
var ix = stream.indexOf(stream)
stream.splice(ix, 1)
})
})
Watch the repo, a lot of interresting scripts there.
Client with a socket
var html = require('yo-yo')
var wsock = require('websocket-stream')
var split = require('split2')
var to = require('to2')
var stream = wsock('ws://' + location.host)
stream.pipe(split())
.pipe(to((buf, enc, next) => {
bus.emit('set-visitors', Number(buf.toString())
next()
})
var state = {
visitors: 0,
x: 0
}
var EventEmitter = require('events')
var bus = new EventEmitter
require('./reduce.js')(bus, state)
var root = document.body.appendChild(document.createElement('div'))
update()
bus.on('update', update)
function update() {
html.update(root, html`<div>
<h1>${state.visitors}</h1>
<div>${state.x}</div>
<button onclick=${onclick}>CLICK ME</button>
</div>`)
function onclick() {
bus.emit('increment-x')
}
}
reduce.js
module.export = function (bus, state) {
bus.on('set-visitors', (visitors) => {
state.visitors = visitors
bus.emit('update')
})
bus.on('increment-n', () => {
state.x = (state.x +1) % 4
bus.emit('update')
})
}
in server and in the browser
*hostory.pushtat
window.addEventListener('click', () => {
var el = ev.target
if ()
})
minimal modular redux architecture
it uses:
- yoyo/bel/hyperx
- sheetify
var choo = reuqire('choo')
var html = require('choo/html')
var wsock = require('websocket-stream')
var split = require('split2')
var to = require('to2')
var stream = wsock('ws://' + location.host)
var app = choo()
app.route('/', (state, emit) => {
return html`<body><div>
<h1>${state.visitors}</h1>
<div>${state.x}</div>
<button onclick=${onclick}>CLICK ME</button>
</div></body>`)
function onclick() {
emit('increment-x')
}
})
app.mount('body')
app.use((state, emit) => {
stream
.pipe(split())
.pipe(to((buf, enc, next) => {
app.emit('set-visitors', Number(buf.toString())
next()
})
})
app.use(require('./reduce.js'))
reduce.js
module.export = function (state, bus) {
state.visitors = 0
state.x = 0
bus.on('set-visitors', (visitors) => {
state.visitors = visitors
bus.emit('update')
})
bus.on('increment-n', () => {
state.x = (state.x +1) % 4
bus.emit('update')
})
}
- yo-yoify
- unassertify
- sheetify
or bankay
includes these by default with no config;
bakai build ...
redraws, managin state
60fps = 1 frame / 60 seconds
1 frame = 1/60 seconds ~ 16.7 milliseconds
avoid allocations and the GC
For example don't create an array inside a draw function
var regl = require('regl')()
var camera = require('regl-camera')(regl, { distance: 4 })
var icosphere = require('icosphere')
var anormals = require('angle-normals')
var glsl = require('gls')
var mesh = icosphere(3)
var draw = regl({
frag: glsl`
precision highp float;
#pragam glslify: snoise = require('glsl-noise/simplex/4d')
varying vec3 vnorm, vpos;
void main() {
gl_FragColor = vec4((vnorm+1.0)*0.5* vec3(0,1,0) + hsl2rgb(snoise(vec4(vpos, time*0.1)),1.0,0.5)
}
`,
vert: glsl`
precision highp float;
#pragma glsify: snoise = require('gsls-noise/simplex/4d')
attribute vec3 position, normal;
uniform mat4 projection, view;
varying vec3 vnorm, vpos;
uniform float time;
void main() {
vpos = position;
vnorm = normal
gl_Poistion = projection * view
* vec4(position + normal * snoise/(, 1);
}
`,
attributes: {
position: mesh.positions.
normal: anormals(mesh.cells, mes.positoins)
},
uniforms: {
time: regl.context('time')
},
elements: mesh.cells
})
regl.fram(function () {
regl.clear({ color: [0,1,1,1], depth: true })
camera(() => {
draw()
})
})
npm i webaudion
var baudio = require('webaudio')
var b = baudio(function (t) {
return Math.sin(2*Math.PI*440*t)
})
b.play()