summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/fastdom-promised-test.js48
-rw-r--r--test/fastdom-sandbox-test.js87
-rw-r--r--test/fastdom-strict-test.js78
-rw-r--r--test/fastdom-test.js389
-rw-r--r--test/index.html29
-rw-r--r--test/karma.conf.js56
-rw-r--r--test/setup.js18
-rw-r--r--test/test.clear.js110
-rw-r--r--test/test.defer.js176
-rw-r--r--test/test.set.js319
10 files changed, 658 insertions, 652 deletions
diff --git a/test/fastdom-promised-test.js b/test/fastdom-promised-test.js
new file mode 100644
index 0000000..959800e
--- /dev/null
+++ b/test/fastdom-promised-test.js
@@ -0,0 +1,48 @@
+/*global suite, setup, test, assert, sinon, fastdomPromised*/
+/*jshint maxlen:false*/
+
+suite('fastdom-promised', function() {
+ var fastdom;
+
+ setup(function() {
+ fastdom = window.fastdom.extend(fastdomPromised);
+ });
+
+ test('it returns a Promise that resolves after the task is run', function(done) {
+ var spy = sinon.spy();
+
+ fastdom.measure(spy)
+ .then(function() {
+ sinon.assert.calledOnce(spy);
+ done();
+ });
+ });
+
+ test('promises can be returned from tasks', function() {
+ var spy1 = sinon.spy();
+ var spy2 = sinon.spy();
+
+ return fastdom.measure(function() {
+ spy1();
+ return fastdom.mutate(spy2);
+ })
+
+ .then(function() {
+ sinon.assert.calledOnce(spy1);
+ sinon.assert.calledOnce(spy2);
+ assert.isTrue(spy1.calledBefore(spy2));
+ });
+ });
+
+ test('calling `fastdom.clear(promise)` works', function(done) {
+ var spy = sinon.spy();
+ var task = fastdom.measure(spy);
+
+ fastdom.clear(task);
+
+ requestAnimationFrame(function() {
+ sinon.assert.notCalled(spy);
+ done();
+ });
+ });
+});
diff --git a/test/fastdom-sandbox-test.js b/test/fastdom-sandbox-test.js
new file mode 100644
index 0000000..43b6626
--- /dev/null
+++ b/test/fastdom-sandbox-test.js
@@ -0,0 +1,87 @@
+/*global suite, setup, test, assert, sinon, fastdomSandbox, fastdomPromised*/
+/* jshint maxlen:false */
+
+suite('fastdom-sandbox', function() {
+ var raf = window.requestAnimationFrame;
+ var fastdom;
+
+ setup(function() {
+ fastdom = new window.fastdom.constructor();
+ fastdom = fastdom.extend(window.fastdomSandbox);
+ });
+
+ test('It works as normal', function(done) {
+ var sandbox = fastdom.sandbox();
+
+ sandbox.measure(function() {
+ sandbox.mutate(function() {
+ done();
+ });
+ });
+ });
+
+ test('Its possible to clear all sandbox jobs', function(done) {
+ var sandbox = fastdom.sandbox();
+ var spy = sinon.spy();
+
+ sandbox.measure(spy);
+ sandbox.mutate(spy);
+
+ fastdom.measure(function() {
+ fastdom.mutate(function() {
+ assert.isTrue(spy.notCalled);
+ done();
+ });
+ });
+
+ sandbox.clear();
+ });
+
+ test('It clears individual tasks', function(done) {
+ var sandbox = fastdom.sandbox();
+ var spy = sinon.spy();
+
+ var task = sandbox.measure(spy);
+ sandbox.clear(task);
+ sandbox.measure(function() {
+ assert.isTrue(spy.notCalled);
+ done();
+ });
+ });
+
+ test('it works with fastdom-promised', function(done) {
+ var myFastdom = fastdom
+ .extend(fastdomPromised)
+ .extend(fastdomSandbox);
+
+ var sandbox = myFastdom.sandbox();
+ var spy1 = sinon.spy();
+ var spy2 = sinon.spy();
+
+ sandbox.measure(spy1)
+ .then(function() {
+ return sandbox.mutate(spy2);
+ })
+
+ .then(function() {
+ sinon.assert.calledOnce(spy1);
+ sinon.assert.calledOnce(spy2);
+
+ spy1.reset();
+ spy2.reset();
+
+ sandbox.measure(spy1);
+ sandbox.measure(spy2);
+ sandbox.clear();
+
+ raf(function() {
+ console.log(3);
+ sinon.assert.notCalled(spy1);
+ sinon.assert.notCalled(spy2);
+ done();
+ });
+ })
+
+ .catch(done);
+ });
+});
diff --git a/test/fastdom-strict-test.js b/test/fastdom-strict-test.js
new file mode 100644
index 0000000..688e8b2
--- /dev/null
+++ b/test/fastdom-strict-test.js
@@ -0,0 +1,78 @@
+/*global suite, setup, suiteSetup, suiteTeardown, teardown, test, assert, fastdomPromised*/
+/*jshint maxlen:false*/
+
+suite('fastdom-strict', function() {
+ var fastdom;
+ var el;
+
+ suiteSetup(function(done) {
+ var script = document.createElement('script');
+ script.src = '/base/fastdom-strict.js';
+ document.head.appendChild(script);
+ script.onload = function() {
+ fastdom = window.fastdom.extend(fastdomPromised);
+ done();
+ };
+ });
+
+ suiteTeardown(function() {
+ fastdom.strict(false);
+ });
+
+ setup(function() {
+ return fastdom.mutate(function() {
+ el = document.createElement('div');
+ el.style.height = '100px';
+ el.style.width = '100px';
+ document.body.appendChild(el);
+ });
+ });
+
+ teardown(function() {
+ return fastdom.mutate(function() {
+ el.remove();
+ });
+ });
+
+ test('measuring throws outside of fastdom', function() {
+ assert.throws(function() {
+ return el.clientWidth;
+ });
+ });
+
+ test('measuring does not throws inside `fastdom.measure()`', function() {
+ return fastdom.measure(function() {
+ return el.clientWidth;
+ });
+ });
+
+ test('mutating throws outside of fastdom', function() {
+ assert.throws(function() {
+ el.innerHTML = 'foo';
+ });
+ });
+
+ test('mutating does not throws inside `fastdom.mutate()`', function() {
+ return fastdom.mutate(function() {
+ el.innerHTML = 'foo';
+ });
+ });
+
+ test('it can be disabled and enabled', function(done) {
+ fastdom.strict(false);
+
+ assert.doesNotThrow(function() {
+ return el.clientWidth;
+ });
+
+ fastdom.strict(true);
+
+ assert.throws(function() {
+ return el.clientWidth;
+ });
+
+ fastdom.measure(function() {
+ el.clientWidth;
+ }).then(done);
+ });
+});
diff --git a/test/fastdom-test.js b/test/fastdom-test.js
new file mode 100644
index 0000000..f28dff6
--- /dev/null
+++ b/test/fastdom-test.js
@@ -0,0 +1,389 @@
+/*jshint maxlen:false*/
+/*global suite, setup, teardown, test, assert, sinon, fastdomSandbox, fastdomPromised*/
+
+suite('fastdom', function() {
+ var raf = window.requestAnimationFrame;
+ var fastdom;
+
+ setup(function() {
+ fastdom = new window.fastdom.constructor();
+ });
+
+ test('it runs reads before writes', function(done) {
+ var read = sinon.spy(function() {
+ assert(!write.called);
+ });
+
+ var write = sinon.spy(function() {
+ assert(read.called);
+ done();
+ });
+
+ fastdom.measure(read);
+ fastdom.mutate(write);
+ });
+
+ test('it calls all reads together, followed by all writes', function(done) {
+ var read1 = sinon.spy();
+ var read2 = sinon.spy();
+ var write1 = sinon.spy();
+ var write2 = sinon.spy();
+
+ // Assign unsorted
+ fastdom.measure(read1);
+ fastdom.mutate(write1);
+ fastdom.measure(read2);
+ fastdom.mutate(write2);
+
+ // After the queue has been emptied
+ // check the callbacks were called
+ // in the correct order.
+ raf(function() {
+ assert(read1.calledBefore(read2));
+ assert(read2.calledBefore(write1));
+ assert(write1.calledBefore(write2));
+ done();
+ });
+ });
+
+ test('it calls a read in the same frame if scheduled inside a read callback', function(done) {
+ var cb = sinon.spy();
+
+ fastdom.measure(function() {
+
+ // Schedule a callback for *next* frame
+ raf(cb);
+
+ // Schedule a read callback
+ // that should be run in the
+ // current frame checking that
+ // the RAF callback has not
+ // yet been fired.
+ fastdom.measure(function() {
+ assert(!cb.called);
+ done();
+ }, this);
+ }, this);
+ });
+
+ test('it calls a write in the same frame if scheduled inside a read callback', function(done) {
+ var cb = sinon.spy();
+
+ fastdom.measure(function() {
+
+ // Schedule a callback for *next* frame
+ raf(cb);
+
+ // Schedule a read callback
+ // that should be run in the
+ // current frame checking that
+ // the RAF callback has not
+ // yet been fired.
+ fastdom.mutate(function() {
+ assert(!cb.called);
+ done();
+ }, this);
+ }, this);
+ });
+
+ test('it calls a read in the *next* frame if scheduled inside a write callback', function(done) {
+ var cb = sinon.spy();
+
+ fastdom.mutate(function() {
+
+ // Schedule a callback for *next* frame
+ raf(cb);
+
+ // Schedule a read that should be
+ // called in the next frame, meaning
+ // the test callback should have already
+ // been called.
+ fastdom.measure(function() {
+ assert(cb.called);
+ done();
+ }, this);
+ }, this);
+ });
+
+ test('it does not request a new frame when a write is requested inside a nested read', function(done) {
+ var callback = sinon.spy();
+
+ fastdom.mutate(function() {
+ fastdom.measure(function() {
+
+ // Schedule a callback for *next* frame
+ raf(callback);
+
+ // Schedule a read callback
+ // that should be run in the
+ // current frame checking that
+ // the RAF callback has not
+ // yet been fired.
+ fastdom.mutate(function() {
+ assert(!callback.called);
+ done();
+ });
+ });
+ });
+ });
+
+ test('it schedules a new frame when a read is requested in a nested write', function(done) {
+ fastdom.raf = sinon.spy(fastdom, 'raf');
+
+ fastdom.measure(function() {
+ fastdom.mutate(function() {
+ fastdom.measure(function(){
+
+ // Should have scheduled a new frame
+ assert(fastdom.raf.calledTwice);
+ done();
+ });
+ });
+ });
+ });
+
+ test('it runs nested reads in the same frame', function(done) {
+ sinon.spy(fastdom, 'raf');
+
+ fastdom.measure(function() {
+ fastdom.measure(function() {
+ fastdom.measure(function() {
+ fastdom.measure(function() {
+
+ // Should not have scheduled a new frame
+ sinon.assert.calledOnce(fastdom.raf);
+ done();
+ });
+ });
+ });
+ });
+ });
+
+ test('it runs nested writes in the same frame', function(done) {
+ fastdom.raf = sinon.spy(fastdom, 'raf');
+
+ fastdom.mutate(function() {
+ fastdom.mutate(function() {
+ fastdom.mutate(function() {
+ fastdom.mutate(function() {
+
+ // Should not have scheduled a new frame
+ sinon.assert.calledOnce(fastdom.raf);
+ done();
+ });
+ });
+ });
+ });
+ });
+
+ test('it calls a "read" callback with the given context', function(done) {
+ fastdom.measure(function() {
+ assert.equal(this.foo, 'bar');
+ done();
+ }, { foo: 'bar' });
+ });
+
+ test('it calls a "write" callback with the given context', function(done) {
+ fastdom.mutate(function() {
+ assert.equal(this.foo, 'bar');
+ done();
+ }, { foo: 'bar' });
+ });
+
+ test('it has an empty job hash when batch complete', function(done) {
+ var ran = 0;
+
+ fastdom.measure(function(){ ran += 1; });
+ fastdom.measure(function(){ ran += 2; });
+ fastdom.mutate(function(){ ran += 4; });
+ fastdom.mutate(function(){ ran += 8; });
+
+ // Check there are four jobs stored
+ assert.equal(ran, 0);
+
+ raf(function() {
+ assert.equal(ran, 15);
+ done();
+ });
+ });
+
+ test('it maintains correct context if single method is registered twice', function(done) {
+ var ctx1 = { foo: 'bar' };
+ var ctx2 = { bar: 'baz' };
+
+ function shared() {}
+
+ var spy1 = sinon.spy(shared);
+ var spy2 = sinon.spy(shared);
+
+ fastdom.measure(spy1, ctx1);
+ fastdom.measure(spy2, ctx2);
+
+ raf(function() {
+ assert(spy1.calledOn(ctx1));
+ assert(spy2.calledOn(ctx2));
+ done();
+ });
+ });
+
+ test('it runs .catch() handler on error if one has been registered', function(done) {
+ fastdom.catch = sinon.spy();
+
+ fastdom.measure(function() { throw 'err1'; });
+ fastdom.mutate(function() { throw 'err2'; });
+
+ raf(function() {
+ raf(function() {
+ assert(fastdom.catch.calledTwice, 'twice');
+ assert(fastdom.catch.getCall(0).calledWith('err1'), 'bla');
+ assert(fastdom.catch.getCall(1).calledWith('err2'), 'bl2');
+ done();
+ });
+ });
+ });
+
+ suite('exceptions', function() {
+
+ // temporarily disable mocha error detection
+ setup(function() {
+ this.onerror = window.onerror;
+ window.onerror = null;
+ });
+
+ // re-enable mocha error detection
+ teardown(function() {
+ window.onerror = this.onerror;
+ });
+
+ test('it flushes remaining tasks in next frame if prior task throws', function(done) {
+ var spy = sinon.spy();
+
+ fastdom.measure(function() { throw new Error('error'); });
+ fastdom.measure(spy);
+
+ raf(function() {
+ sinon.assert.notCalled(spy);
+ raf(function() {
+ sinon.assert.calledOnce(spy);
+ done();
+ });
+ });
+ });
+ });
+
+ test('it stops rAF loop once frame queue is empty', function(done) {
+ var callback = sinon.spy();
+
+ sinon.spy(fastdom, 'raf');
+ fastdom.measure(callback);
+
+ raf(function() {
+ assert(callback.called);
+ assert(fastdom.raf.calledOnce);
+ done();
+ });
+ });
+
+ suite('clear', function() {
+ test('it does not run "read" job if cleared (sync)', function(done) {
+ var read = sinon.spy();
+ var id = fastdom.measure(read);
+ fastdom.clear(id);
+
+ raf(function() {
+ raf(function() {
+ assert(!read.called);
+ done();
+ });
+ });
+ });
+
+ test('it fails silently if job not found in queue', function(done) {
+ var read = sinon.spy();
+ var read2 = sinon.spy();
+
+ var id = fastdom.measure(read);
+ fastdom.clear(id);
+
+ raf(function() {
+ assert(!read2.called);
+ done();
+ });
+ });
+
+ test('it does not run "write" job if cleared (async)', function(done) {
+ var read = sinon.spy();
+ var write = sinon.spy();
+
+ var id = fastdom.mutate(write);
+ fastdom.measure(function() {
+ fastdom.clear(id);
+
+ raf(function() {
+ assert(!read.called);
+ done();
+ });
+ });
+ });
+
+ test('it does not run "write" job if cleared', function(done) {
+ var write = sinon.spy();
+ var id = fastdom.mutate(write);
+
+ fastdom.clear(id);
+
+ raf(function() {
+ assert(!write.called);
+ done();
+ });
+ });
+
+ test('it removes reference to the job if cleared', function(done) {
+ var write = sinon.spy();
+ var id = fastdom.mutate(2, write);
+
+ fastdom.clear(id);
+
+ raf(function() {
+ raf(function() {
+ raf(function() {
+ assert(!write.called);
+ done();
+ });
+ });
+ });
+ });
+ });
+
+ suite('FastDom#extend()', function() {
+ test('it has the properties of given object', function() {
+ var fastdom2 = fastdom.extend({ prop: 'foo' });
+ assert.equal(fastdom2.prop, 'foo');
+ });
+
+ test('it can extend an extension', function() {
+ var fastdom2 = fastdom.extend({ prop: 'foo' });
+ var fastdom3 = fastdom2.extend({ prop: 'bar' });
+
+ assert.equal(fastdom2.prop, 'foo');
+ assert.equal(fastdom3.prop, 'bar');
+
+ assert.equal(fastdom2.fastdom, fastdom);
+ assert.equal(fastdom3.fastdom, fastdom2);
+ });
+
+ test('it throws if argument is not object', function() {
+ assert.throws(function() {
+ fastdom.extend();
+ });
+
+ assert.throws(function() {
+ fastdom.extend('oopsie');
+ });
+
+ assert.throws(function() {
+ fastdom.extend(999);
+ });
+ });
+ });
+});
diff --git a/test/index.html b/test/index.html
deleted file mode 100644
index f757410..0000000
--- a/test/index.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <meta charset="utf-8">
- <title>Mocha Tests</title>
- <link rel="stylesheet" href="../node_modules/mocha/mocha.css" />
-</head>
-<body>
- <div id="mocha"></div>
- <script src="../node_modules/mocha/mocha.js"></script>
- <script src="../node_modules/chai/chai.js"></script>
- <script src="../node_modules/sinon/lib/sinon.js"></script>
- <script src="../node_modules/sinon/lib/sinon/match.js"></script>
- <script src="../node_modules/sinon/lib/sinon/spy.js"></script>
- <script src="../node_modules/sinon/lib/sinon/stub.js"></script>
- <script>mocha.setup('tdd')</script>
- <script src="../index.js"></script>
- <script src="setup.js"></script>
- <script src="test.set.js"></script>
- <script src="test.clear.js"></script>
- <script src="test.defer.js"></script>
- <script>
- mocha.checkLeaks();
-
- if (window.mochaPhantomJS) mochaPhantomJS.run();
- else mocha.run();
- </script>
-</body>
-</html> \ No newline at end of file
diff --git a/test/karma.conf.js b/test/karma.conf.js
new file mode 100644
index 0000000..d639b36
--- /dev/null
+++ b/test/karma.conf.js
@@ -0,0 +1,56 @@
+'use strict';
+
+module.exports = function(config) {
+ config.set({
+ basePath: '..',
+
+ browsers: [
+ 'chrome',
+ 'Firefox'
+ ],
+
+ frameworks: [
+ 'mocha',
+ 'chai-sinon'
+ ],
+
+ reporters: [
+ 'mocha',
+ 'coverage'
+ ],
+
+ coverageReporter: {
+ type : 'lcov',
+ dir : 'test/',
+ subdir: 'coverage'
+ },
+
+ preprocessors: {
+ 'fastdom.js': ['coverage'],
+ 'extensions/*.js': ['coverage']
+ },
+
+ client: {
+ captureConsole: true,
+ mocha: { ui: 'tdd' }
+ },
+
+ customLaunchers: {
+ chrome: {
+ base: 'Chrome',
+ flags: ['--no-sandbox']
+ }
+ },
+
+ files: [
+ 'fastdom.js',
+ 'extensions/fastdom-promised.js',
+ 'extensions/fastdom-sandbox.js',
+ 'test/fastdom-sandbox-test.js',
+ 'test/fastdom-promised-test.js',
+ 'test/fastdom-strict-test.js',
+ 'test/fastdom-test.js',
+ { pattern: 'fastdom-strict.js', included: false }
+ ]
+ });
+};
diff --git a/test/setup.js b/test/setup.js
deleted file mode 100644
index 0844695..0000000
--- a/test/setup.js
+++ /dev/null
@@ -1,18 +0,0 @@
-
-// RequestAnimationFrame Polyfill
-var raf = window.requestAnimationFrame
- || window.webkitRequestAnimationFrame
- || window.mozRequestAnimationFrame
- || function(cb) { window.setTimeout(cb, 1000 / 60); };
-
-// Make constructor
-var FastDom = fastdom.constructor;
-
-// Alias chai.assert
-var assert = chai.assert;
-
-function objectLength(object) {
- var l = 0;
- for (var key in object) l++;
- return l;
-} \ No newline at end of file
diff --git a/test/test.clear.js b/test/test.clear.js
deleted file mode 100644
index 1230b16..0000000
--- a/test/test.clear.js
+++ /dev/null
@@ -1,110 +0,0 @@
-
-suite('clear', function(){
-
- test('Should not run "read" job if cleared (sync)', function(done) {
- var fastdom = new FastDom();
- var read = sinon.spy();
-
- var id = fastdom.read(read);
- fastdom.clear(id);
-
- raf(function() {
- assert(!read.called);
- done();
- });
- });
-
- test('Should fail silently if job not found in queue', function(done) {
- var fastdom = new FastDom();
- var read = sinon.spy();
- var read2 = sinon.spy();
-
- var id = fastdom.read(read);
- fastdom.clear(id);
-
- raf(function() {
- assert(!read2.called);
- done();
- });
- });
-
- test('Should not run "write" job if cleared (async)', function(done) {
- var fastdom = new FastDom();
- var read = sinon.spy();
- var write = sinon.spy();
-
- var id = fastdom.write(write);
- fastdom.read(function() {
- fastdom.clear(id);
-
- raf(function() {
- assert(!read.called);
- done();
- });
- });
- });
-
- test('Should not run "write" job if cleared', function(done) {
- var fastdom = new FastDom();
- var write = sinon.spy();
- var id = fastdom.write(write);
-
- fastdom.clear(id);
-
- raf(function() {
- assert(!write.called);
- done();
- });
- });
-
- test('Should not run "defer" job if cleared', function(done) {
- var fastdom = new FastDom();
- var callback = sinon.spy();
- var id = fastdom.defer(3, callback);
-
- fastdom.clear(id);
-
- raf(function() {
- raf(function() {
- raf(function() {
- raf(function() {
- assert(!callback.called);
- done();
- });
- });
- });
- });
- });
-
- test('Should remove reference to the job if cleared', function(done) {
- var fastdom = new FastDom();
- var write = sinon.spy();
- var id = fastdom.write(2, write);
-
- fastdom.clear(id);
-
- raf(function() {
- raf(function() {
- raf(function() {
- assert(!write.called);
- assert(!fastdom.batch.hash[id]);
- done();
- });
- });
- });
- });
-
- test('Should accept String ids', function(done) {
- var fastdom = new FastDom();
- var read = sinon.spy();
-
- var id = fastdom.read(read);
-
- fastdom.clear(id.toString());
-
- raf(function() {
- assert(!read.called);
- done();
- });
- });
-}); \ No newline at end of file
diff --git a/test/test.defer.js b/test/test.defer.js
deleted file mode 100644
index 89b5729..0000000
--- a/test/test.defer.js
+++ /dev/null
@@ -1,176 +0,0 @@
-
-suite('defer', function(){
-
- test('Should run the job after the specified number of frames', function(done) {
- var fastdom = new FastDom();
- var job = sinon.spy();
-
- fastdom.defer(3, job);
-
- raf(function() {
- assert(!job.called);
- raf(function() {
- assert(!job.called);
- raf(function() {
- assert(job.called);
- done();
- });
- });
- });
- });
-
- test('Should call a deferred callback with the given context', function(done) {
- var fastdom = new FastDom();
- var cb = sinon.spy();
- var ctx = { foo: 'bar' };
-
- fastdom.defer(2, function() {
- assert.equal(this.foo, 'bar');
- done();
- }, ctx);
- });
-
- test('Should run work at next frame if frames argument not supplied.', function(done) {
- var fastdom = new FastDom();
- var callback1 = sinon.spy();
- var callback2 = sinon.spy();
-
- fastdom.defer(callback1);
-
- raf(function() {
- assert(callback1.called);
- done();
- });
- });
-
- test('Should run each job on a different frame.', function(done) {
- var fastdom = new FastDom();
- var callback1 = sinon.spy();
- var callback2 = sinon.spy();
- var callback3 = sinon.spy();
-
- fastdom.defer(callback1);
- fastdom.defer(callback2);
- fastdom.defer(callback3);
-
- raf(function() {
- assert(callback1.called);
- assert(!callback2.called);
- assert(!callback3.called);
- raf(function() {
- assert(callback2.called);
- assert(!callback3.called);
- raf(function() {
- assert(callback3.called);
- done();
- });
- });
- });
- });
-
- test('Should run fill empty frames before later work is run.', function(done) {
- var fastdom = new FastDom();
- var callback1 = sinon.spy();
- var callback2 = sinon.spy();
- var callback3 = sinon.spy();
- var callback4 = sinon.spy();
-
- // Frame 3
- fastdom.defer(3, callback3);
-
- // Frame 1
- fastdom.defer(callback1);
-
- // Frame 2
- fastdom.defer(callback2);
-
- // Frame 4
- fastdom.defer(callback4);
-
- raf(function() {
- assert(callback1.called);
- assert(!callback2.called);
- assert(!callback3.called);
- assert(!callback4.called);
- raf(function() {
- assert(callback2.called);
- assert(!callback3.called);
- assert(!callback4.called);
- raf(function() {
- assert(callback3.called);
- assert(!callback4.called);
- raf(function() {
- assert(callback4.called);
- done();
- });
- });
- });
- });
- });
-
- test('Should run the next frame even if frame before it errors', function(done) {
- var fastdom = new FastDom();
- var rafOld = fastdom.raf;
- var error = sinon.stub().throws();
- var callback = sinon.spy();
-
- // Wrap requestAnimationFrame method
- // so that we can catch any errors
- // that may be thrown in the callback
- sinon.stub(fastdom, 'raf', function(fn) {
- var wrapped = function() {
- try { fn(); } catch (e) {}
- };
-
- rafOld(wrapped);
- });
-
- fastdom.defer(error);
- fastdom.defer(callback);
-
- raf(function() {
- raf(function() {
- assert(callback.called, 'The second job was run');
- done();
- });
- });
- });
-
- test('Should continue to run future jobs when the last frame errors', function(done) {
- var fastdom = new FastDom();
- var rafOld = fastdom.raf;
- var error = sinon.stub().throws();
- var callback1 = sinon.spy();
- var callback2 = sinon.spy();
-
- // Wrap requestAnimationFrame method
- // so that we can catch any errors
- // that may be thrown in the callback
- sinon.stub(fastdom, 'raf', function(fn) {
- var wrapped = function() {
- try { fn(); } catch (e) {}
- };
-
- rafOld(wrapped);
- });
-
- fastdom.defer(callback1);
- fastdom.defer(error);
-
- setTimeout(function() {
- fastdom.defer(callback2);
- }, 40);
-
- raf(function() {
- assert(callback1.called, 'the first job was run');
- raf(function() {
- setTimeout(function(){
- raf(function() {
- assert(callback2.called, 'the third job was run');
- done();
- });
- }, 40);
- });
- });
- });
-});
diff --git a/test/test.set.js b/test/test.set.js
deleted file mode 100644
index 811c489..0000000
--- a/test/test.set.js
+++ /dev/null
@@ -1,319 +0,0 @@
-
-suite('set', function() {
-
- test('Should run reads before writes', function(done) {
- var fastdom = new FastDom();
-
- var read = sinon.spy(function() {
- assert(!write.called);
- });
-
- var write = sinon.spy(function() {
- assert(read.called);
- done();
- });
-
- fastdom.read(read);
- fastdom.write(write);
- });
-
- test('Should call all reads together, followed by all writes', function(done) {
- var fastdom = new FastDom();
- var read1 = sinon.spy();
- var read2 = sinon.spy();
- var write1 = sinon.spy();
- var write2 = sinon.spy();
-
- // Assign unsorted
- fastdom.read(read1);
- fastdom.write(write1);
- fastdom.read(read2);
- fastdom.write(write2);
-
- // After the queue has been emptied
- // check the callbacks were called
- // in the correct order.
- raf(function() {
- assert(read1.calledBefore(read2));
- assert(read2.calledBefore(write1));
- assert(write1.calledBefore(write2));
- done();
- });
- });
-
- test('Should call a read in the same frame if scheduled inside a read callback', function(done) {
- var fastdom = new FastDom();
- var cb = sinon.spy();
-
- fastdom.read(function() {
-
- // Schedule a callback for *next* frame
- raf(cb);
-
- // Schedule a read callback
- // that should be run in the
- // current frame checking that
- // the RAF callback has not
- // yet been fired.
- fastdom.read(function() {
- assert(!cb.called);
- done();
- });
-
- // Should not have scheduled a new frame
- assert(fastdom.frames.length === 0);
- });
- });
-
- test('Should call a write in the same frame if scheduled inside a read callback', function(done) {
- var fastdom = new FastDom();
- var cb = sinon.spy();
-
- fastdom.read(function() {
-
- // Schedule a callback for *next* frame
- raf(cb);
-
- // Schedule a read callback
- // that should be run in the
- // current frame checking that
- // the RAF callback has not
- // yet been fired.
- fastdom.write(function() {
- assert(!cb.called);
- done();
- });
-
- // Should not have scheduled a new frame
- assert(fastdom.frames.length === 0);
- });
- });
-
- test('Should call a read in the *next* frame if scheduled inside a write callback', function(done) {
- var fastdom = new FastDom();
- var cb = sinon.spy();
-
- fastdom.write(function() {
-
- // Schedule a callback for *next* frame
- raf(cb);
-
- // Schedule a read that should be
- // called in the next frame, meaning
- // the test callback should have already
- // been called.
- fastdom.read(function() {
- assert(cb.called);
- done();
- });
-
- // Should have scheduled a new frame
- assert(fastdom.frames.length === 1, 'the is one pending frame');
- });
- });
-
- test('Should not request a new frame when a write is requested inside a nested read', function(done) {
- var fastdom = new FastDom();
- var callback = sinon.spy();
-
- fastdom.write(function() {
- fastdom.read(function() {
-
- // Schedule a callback for *next* frame
- raf(callback);
-
- // Schedule a read callback
- // that should be run in the
- // current frame checking that
- // the RAF callback has not
- // yet been fired.
- fastdom.write(function() {
- assert(!callback.called);
- done();
- });
-
- // Should not have scheduled a new frame
- assert(fastdom.frames.length === 0);
- });
- });
- });
-
- test('Should schedule a new frame when a read is requested in a nested write', function(done) {
- var fastdom = new FastDom();
-
- fastdom.read(function() {
- fastdom.write(function() {
- fastdom.read(function(){});
-
- // Should have scheduled a new frame
- assert(fastdom.frames.length === 1);
- done();
- });
- });
- });
-
- test('Should run nested reads in the same frame', function(done) {
- var fastdom = new FastDom();
- var callback = sinon.spy();
-
- fastdom.read(function() {
- fastdom.read(function() {
- fastdom.read(function() {
- fastdom.read(function() {
-
- // Should not have scheduled a new frame
- assert(fastdom.frames.length === 0);
- done();
- });
- });
- });
- });
- });
-
- test('Should run nested writes in the same frame', function(done) {
- var fastdom = new FastDom();
- var callback = sinon.spy();
-
- fastdom.write(function() {
- fastdom.write(function() {
- fastdom.write(function() {
- fastdom.write(function() {
-
- // Should not have scheduled a new frame
- assert(fastdom.frames.length === 0);
- done();
- });
- });
- });
- });
- });
-
- test('Should call a "read" callback with the given context', function(done) {
- var fastdom = new FastDom();
- var cb = sinon.spy();
- var ctx = { foo: 'bar' };
-
- fastdom.read(function() {
- assert.equal(this.foo, 'bar');
- done();
- }, ctx);
- });
-
- test('Should call a "write" callback with the given context', function(done) {
- var fastdom = new FastDom();
- var cb = sinon.spy();
- var ctx = { foo: 'bar' };
-
- fastdom.write(function() {
- assert.equal(this.foo, 'bar');
- done();
- }, ctx);
- });
-
- test('Should have empty job hash when batch complete', function(done) {
- var fastdom = new FastDom();
-
- fastdom.read(function(){});
- fastdom.read(function(){});
- fastdom.write(function(){});
- fastdom.write(function(){});
-
- // Check there are four jobs stored
- assert.equal(objectLength(fastdom.batch.hash), 4);
-
- raf(function() {
- assert.equal(objectLength(fastdom.batch.hash), 0);
- done();
- });
- });
-
- test('Should maintain correct context if single method is registered twice', function(done) {
- var fastdom = new FastDom();
- var ctx1 = { foo: 'bar' };
- var ctx2 = { bar: 'baz' };
-
- function shared(){}
-
- var spy1 = sinon.spy(shared);
- var spy2 = sinon.spy(shared);
-
- fastdom.read(spy1, ctx1);
- fastdom.read(spy2, ctx2);
-
- raf(function() {
- assert(spy1.calledOn(ctx1));
- assert(spy2.calledOn(ctx2));
- done();
- });
- });
-
- test('Should run onError handler if one has been registered', function(done) {
- var fastdom = new FastDom();
- var err1 = { some: 'error1' };
- var err2 = { some: 'error2' };
-
- fastdom.onError = sinon.spy();
-
- fastdom.read(function() {
- throw err1;
- });
-
- fastdom.write(function() {
- throw err2;
- });
-
- raf(function() {
- assert(fastdom.onError.calledTwice);
- assert(fastdom.onError.getCall(0).calledWith(err1));
- assert(fastdom.onError.getCall(1).calledWith(err2));
- done();
- });
- });
-
- test('Should stop rAF loop once frame queue is empty', function(done) {
- var fastdom = new FastDom();
- var callback = sinon.spy();
-
- fastdom.read(callback);
-
- raf(function() {
- assert(callback.called);
- assert(fastdom.looping === false);
- done();
- });
- });
-
-
- test('Should continue to flush the queue until empty even if a job errors', function(done) {
- var fastdom = new FastDom();
- var read = sinon.spy();
- var write = sinon.spy();
- var flush = fastdom.runBatch;
- var error = sinon.stub().throws();
- var errorsThrown = false;
-
- sinon.stub(fastdom, 'runBatch', function() {
- try {
- flush.apply(fastdom, arguments);
- } catch (e) {
- errorsThrown = true;
- }
- });
-
- fastdom.read(read);
- fastdom.write(write);
- fastdom.read(error);
- fastdom.read(read);
- fastdom.write(error);
- fastdom.write(write);
-
- raf(function() {
- assert(read.calledTwice, 'the callback was called both times');
- assert(write.calledTwice, 'the callback was called both times');
- assert(fastdom.batch.read.length === 0, 'the queue is empty');
- assert(fastdom.batch.write.length === 0, 'the queue is empty');
- assert(errorsThrown, 'real errors were thrown');
- done();
- });
- });
-});