Skip to content

Instantly share code, notes, and snippets.

@HenriqueLimas
Created May 12, 2017 20:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save HenriqueLimas/f303a777dae1d22f1d82ec4bfbf578b1 to your computer and use it in GitHub Desktop.
Save HenriqueLimas/f303a777dae1d22f1d82ec4bfbf578b1 to your computer and use it in GitHub Desktop.

Testing and modular front-end

assert

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)
	})
}

problems with assert

  • exceptions stop execution
  • false positive when test blocks don't run

Test anything protocol (TAP)

old text protocol from the perl test suite

  • test cases begin with ok/not ok
  • must plain out a number of assertions

http://testanything.org

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)
	})
	
})

Stopped here.....

code coverage

How much of your code gets run when you test-

Avstract syntax tree

data structure for code

Some libraries:

  • acorn

nyc or coverify for code-coverage

npm scripts

Some automation scripts.

continous integration

run tests every time you push code

On travis just use .travis.yml

language: node_js
node_js:
	- "7"
	- "6"
	- "4"

travis-ci badge

example markdown and put the build status on the readme

====

Modular web dev

The web is these:

  • service workers
  • template strings
  • redux architecture

but also these:

  • indexDB
  • webaudio
  • webgl

starting from zero

echo '{}' > package.json
npm install --save ...

template strings

var n = 5
console.log(`hi
	n=${n}
	wow
`)

tagged template strings

var n = 5
console.log(tag`hi
	n=${n}
	wow
`)

console.log(['hi'\n n=', '\n wow'], n)

function tag (strings) {
	return arguments
}

hyperx

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>`)

yo-yo/bel/morphdom

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()
	}
}

Using states

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')
	})
}

routing

in server and in the browser

*hostory.pushtat

window.addEventListener('click', () => {
	var el = ev.target
	if ()
})

choo

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')
	})
}

building for prod

  • yo-yoify
  • unassertify
  • sheetify

or bankay includes these by default with no config;

bakai build ...

webgl

redraws, managin state

webgl perfomance tips

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()
	})
})

audio

npm i webaudion

or http://studio.substack.net

var baudio = require('webaudio')
var b = baudio(function (t) {
	return Math.sin(2*Math.PI*440*t)
})
b.play()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment