diff --git a/.editorconfig b/.editorconfig index 7db968e..ac72573 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,5 +8,5 @@ charset = utf-8 end_of_line = lf insert_final_newline = true indent_style = space -indent_size = 4 +indent_size = 2 trim_trailing_whitespace = true diff --git a/examples/persistence/index.js b/examples/persistence/index.js index ea5f4aa..1adb291 100644 --- a/examples/persistence/index.js +++ b/examples/persistence/index.js @@ -12,26 +12,26 @@ const rb = new Rubidium(); // Load the persisted queue when redis is ready. redis.hgetall('rubidium-queue').then(stringifiedJobs => { - for (const uuid of Object.keys(stringifiedJobs)) { - // Add the persisted jobs to the queue, taking care to silence them so - // they are not duplicated in redis. - rb.add(JSON.parse(stringifiedJobs[uuid]), true); - } + for (const uuid of Object.keys(stringifiedJobs)) { + // Add the persisted jobs to the queue, taking care to silence them so + // they are not duplicated in redis. + rb.add(JSON.parse(stringifiedJobs[uuid]), true); + } }); rb.on('addJob', job => { - redis.hset('rubidium-queue', job.uuid, JSON.stringify(job)).then(() => { - console.log(`Job ${job.uuid} persisted.`); - }); + redis.hset('rubidium-queue', job.uuid, JSON.stringify(job)).then(() => { + console.log(`Job ${job.uuid} persisted.`); + }); }); rb.on('job', job => { - redis.hdel('rubidium-queue', job.uuid); - console.log(`Job ${job.uuid} emitted, message: ${job.message}`); + redis.hdel('rubidium-queue', job.uuid); + console.log(`Job ${job.uuid} emitted, message: ${job.message}`); }); rb.on('removeJob', job => { - redis.hdel('rubidium-queue', job.uuid); + redis.hdel('rubidium-queue', job.uuid); }); rb.add({ time: Date.now() + 10000, message: '10 seconds have passed.' }); diff --git a/examples/server/index.js b/examples/server/index.js index 14ad89b..834baa3 100644 --- a/examples/server/index.js +++ b/examples/server/index.js @@ -14,14 +14,14 @@ const rb = new Rubidium(); // callback in the message with the message itself as the body. Requests have // a custom header so that registered jobs can't create another job. rb.on('job', job => { - const options = { - method: 'POST', - headers: { 'Content-Type': 'application/json', 'FROM-ATD-SERVER': 'true' }, - body: JSON.stringify(job.message) - }; - - return fetch(job.message.callbackUrl, options) - .catch(err => console.error(err.stack || err.message)); + const options = { + method: 'POST', + headers: { 'Content-Type': 'application/json', 'FROM-ATD-SERVER': 'true' }, + body: JSON.stringify(job.message) + }; + + return fetch(job.message.callbackUrl, options) + .catch(err => console.error(err.stack || err.message)); }); // Create a router for the Toisu! server. @@ -30,36 +30,36 @@ const router = new Router(); // This middleware will use the :timestamp parameter and the request body to // create a job, and then add it to the rubidium instance. function addJobMiddleware(req, res) { - const params = this.get('params'); - const time = parseInt(params.timestamp, 10); - const message = this.get('body'); + const params = this.get('params'); + const time = parseInt(params.timestamp, 10); + const message = this.get('body'); - // Stop callbacks registering new jobs. - if (req.headers['FROM-ATD-SERVER'] !== 'true') { - rb.add({ time, message }); - } + // Stop callbacks registering new jobs. + if (req.headers['FROM-ATD-SERVER'] !== 'true') { + rb.add({ time, message }); + } - res.statusCode = 202; - res.end(); + res.statusCode = 202; + res.end(); } // Use this to accept requests from itself as a test. function testMiddleware(req, res) { - const message = this.get('body'); + const message = this.get('body'); - console.log('Received callback request:', message); + console.log('Received callback request:', message); - res.statusCode = 204; - res.end(); + res.statusCode = 204; + res.end(); } // Give the router the JSON body parsing middleware and the add job middleware. router.route('/add/:timestamp', { - post: [body.json(), addJobMiddleware] + post: [body.json(), addJobMiddleware] }); router.route('/test', { - post: [body.json(), testMiddleware] + post: [body.json(), testMiddleware] }); // Create a Toisu! instance. diff --git a/lib/Job.js b/lib/Job.js index 9c0471f..0661eba 100644 --- a/lib/Job.js +++ b/lib/Job.js @@ -1,23 +1,23 @@ import uuid from './uuidv4'; export default class Job { - constructor(spec) { - if (!spec) { - throw new Error('Spec must be an object'); - } + constructor(spec) { + if (!spec) { + throw new Error('Spec must be an object'); + } - if (spec.message === undefined) { - throw new Error('Message argument must be populated.'); - } + if (spec.message === undefined) { + throw new Error('Message argument must be populated.'); + } - this.time = spec.time instanceof Date ? spec.time.getTime() : parseInt(spec.time, 10); + this.time = spec.time instanceof Date ? spec.time.getTime() : parseInt(spec.time, 10); - if (!this.time) { - throw new TypeError('Time must be a Date object or an integer.'); - } + if (!this.time) { + throw new TypeError('Time must be a Date object or an integer.'); + } - this.message = spec.message; + this.message = spec.message; - this.uuid = spec.uuid || uuid(); - } + this.uuid = spec.uuid || uuid(); + } } diff --git a/lib/Rubidium.js b/lib/Rubidium.js index 4f62f92..97a8ac8 100644 --- a/lib/Rubidium.js +++ b/lib/Rubidium.js @@ -5,108 +5,108 @@ const jobs = new WeakMap(); const timeouts = new WeakMap(); function getJobFromQueue(queue, uuid) { - for (let i = 0, len = queue.length; i < len; i++) { - if (queue[i].uuid === uuid) { - return queue[i]; - } + for (let i = 0, len = queue.length; i < len; i++) { + if (queue[i].uuid === uuid) { + return queue[i]; } + } } function makeTimeout(rb, queue) { - clearTimeout(timeouts.get(rb)); + clearTimeout(timeouts.get(rb)); - if (!queue.length) { - return timeouts.set(rb, null); - } + if (!queue.length) { + return timeouts.set(rb, null); + } - // setTimeout accepts 32bit integers for the time value. If the next job is - // later than this, we'll set a shorter timeout as a waypoint. - const dt = Math.min(Math.max(queue[0].time - Date.now(), 0), 2147483647); + // setTimeout accepts 32bit integers for the time value. If the next job is + // later than this, we'll set a shorter timeout as a waypoint. + const dt = Math.min(Math.max(queue[0].time - Date.now(), 0), 2147483647); - timeouts.set(rb, setTimeout(() => { - while (queue.length && queue[0].time <= Date.now()) { - rb.emit('job', queue.shift()); - } + timeouts.set(rb, setTimeout(() => { + while (queue.length && queue[0].time <= Date.now()) { + rb.emit('job', queue.shift()); + } - makeTimeout(rb, queue); - }, dt)); + makeTimeout(rb, queue); + }, dt)); } export default class Rubidium extends EventEmitter { - constructor() { - super(); - - jobs.set(this, []); - - timeouts.set(this, null); - } + constructor() { + super(); - add(spec, silent) { - const queue = jobs.get(this); - const job = new Job(spec); + jobs.set(this, []); - queue.push(job); - queue.sort((a, b) => a.time - b.time); + timeouts.set(this, null); + } - if (!silent) { - this.emit('addJob', job); - } + add(spec, silent) { + const queue = jobs.get(this); + const job = new Job(spec); - if (job === queue[0]) { - makeTimeout(this, queue); - } + queue.push(job); + queue.sort((a, b) => a.time - b.time); - return job; + if (!silent) { + this.emit('addJob', job); } - find(uuid) { - return getJobFromQueue(jobs.get(this), uuid); + if (job === queue[0]) { + makeTimeout(this, queue); } - remove(uuid, silent) { - const queue = jobs.get(this); - const job = getJobFromQueue(queue, uuid); + return job; + } - if (!job) { - return; - } + find(uuid) { + return getJobFromQueue(jobs.get(this), uuid); + } - const index = queue.indexOf(job); + remove(uuid, silent) { + const queue = jobs.get(this); + const job = getJobFromQueue(queue, uuid); - queue.splice(index, 1); + if (!job) { + return; + } - if (!silent) { - this.emit('removeJob', job); - } + const index = queue.indexOf(job); - if (index === 0) { - makeTimeout(this, queue); - } + queue.splice(index, 1); - return job; + if (!silent) { + this.emit('removeJob', job); } - clear(silent) { - const newJobs = []; + if (index === 0) { + makeTimeout(this, queue); + } - makeTimeout(this, newJobs); + return job; + } - const oldJobs = jobs.get(this); + clear(silent) { + const newJobs = []; - jobs.set(this, newJobs); + makeTimeout(this, newJobs); - if (silent) { - return; - } + const oldJobs = jobs.get(this); - for (let i = 0, len = oldJobs.length; i < len; i++) { - this.emit('removeJob', oldJobs[i]); - } + jobs.set(this, newJobs); - this.emit('clearJobs'); + if (silent) { + return; } - get hasPendingJobs() { - return jobs.get(this).length !== 0; + for (let i = 0, len = oldJobs.length; i < len; i++) { + this.emit('removeJob', oldJobs[i]); } + + this.emit('clearJobs'); + } + + get hasPendingJobs() { + return jobs.get(this).length !== 0; + } } diff --git a/lib/uuidv4.js b/lib/uuidv4.js index 89afbf9..7da6971 100644 --- a/lib/uuidv4.js +++ b/lib/uuidv4.js @@ -1,23 +1,23 @@ function randomHexByte() { - const hexByte = Math.floor(Math.random() * 256).toString(16); + const hexByte = Math.floor(Math.random() * 256).toString(16); - return hexByte.length === 2 ? hexByte : '0' + hexByte; + return hexByte.length === 2 ? hexByte : `0${hexByte}`; } function bytes(num) { - let randomHex = ''; + let randomHex = ''; - for (let i = 0; i < num; i++) { - randomHex += randomHexByte(); - } + for (let i = 0; i < num; i++) { + randomHex += randomHexByte(); + } - return randomHex; + return randomHex; } function special() { - return ['8', '9', 'a', 'b'][Math.floor(Math.random() * 4)]; + return ['8', '9', 'a', 'b'][Math.floor(Math.random() * 4)]; } export default function uuidv4() { - return `${bytes(4)}-${bytes(2)}-4${bytes(3)}-${special()}${bytes(3)}-${bytes(6)}`; + return `${bytes(4)}-${bytes(2)}-4${bytes(3)}-${special()}${bytes(3)}-${bytes(6)}`; } diff --git a/test/test-Rubidium.js b/test/test-Rubidium.js index f08f5e5..4dd5f9b 100644 --- a/test/test-Rubidium.js +++ b/test/test-Rubidium.js @@ -6,574 +6,574 @@ const sinon = require('sinon'); const assert = require('assert'); describe('Rubidium', () => { - let callback; - let clock; - let rb; + let callback; + let clock; + let rb; - beforeEach(() => { - callback = sinon.stub(); - rb = new Rubidium(); - clock = sinon.useFakeTimers(); - }); + beforeEach(() => { + callback = sinon.stub(); + rb = new Rubidium(); + clock = sinon.useFakeTimers(); + }); - afterEach(() => { - rb.clear(); - clock.restore(); - }); + afterEach(() => { + rb.clear(); + clock.restore(); + }); - describe('add', () => { - describe('not silenced', () => { - it('returns the job when add is called', () => { - const job = rb.add({ time: 100, message: 'hi' }); + describe('add', () => { + describe('not silenced', () => { + it('returns the job when add is called', () => { + const job = rb.add({ time: 100, message: 'hi' }); - assert.equal(job.time, 100); - assert.equal(job.message, 'hi'); - }); + assert.equal(job.time, 100); + assert.equal(job.message, 'hi'); + }); - it('emits "addJob" with the added job when a job is added', () => { - rb.on('addJob', callback); + it('emits "addJob" with the added job when a job is added', () => { + rb.on('addJob', callback); - const job = rb.add({ time: 100, message: 'hi' }); + const job = rb.add({ time: 100, message: 'hi' }); - assert.equal(callback.callCount, 1); - assert.equal(callback.args[0][0], job); - }); + assert.equal(callback.callCount, 1); + assert.equal(callback.args[0][0], job); + }); - it('adds a uuid to an added job when it does not have one', () => { - const job = rb.add({ time: 100, message: 'hi' }); + it('adds a uuid to an added job when it does not have one', () => { + const job = rb.add({ time: 100, message: 'hi' }); - assert.equal(typeof job.uuid, 'string'); - assert.ok(job.uuid.length); - }); + assert.equal(typeof job.uuid, 'string'); + assert.ok(job.uuid.length); + }); - it('does not change the uuid when the the added job has one', () => { - const job = rb.add({ time: 100, message: 'hi', uuid: 'abcd' }); + it('does not change the uuid when the the added job has one', () => { + const job = rb.add({ time: 100, message: 'hi', uuid: 'abcd' }); - assert.equal(job.uuid, 'abcd'); - }); + assert.equal(job.uuid, 'abcd'); + }); - it('emits the added job when the timeout has elapsed', () => { - rb.on('job', callback); + it('emits the added job when the timeout has elapsed', () => { + rb.on('job', callback); - const job = rb.add({ time: 100, message: 'hi' }); + const job = rb.add({ time: 100, message: 'hi' }); - assert.equal(callback.callCount, 0); + assert.equal(callback.callCount, 0); - clock.tick(105); + clock.tick(105); - assert.equal(callback.callCount, 1); - assert.equal(callback.args[0][0], job); - }); + assert.equal(callback.callCount, 1); + assert.equal(callback.args[0][0], job); + }); - it('emits jobs submitted in wrong order in the correct order', () => { - rb.on('job', callback); + it('emits jobs submitted in wrong order in the correct order', () => { + rb.on('job', callback); - const job2 = rb.add({ time: 200, message: 'bye' }); - const job1 = rb.add({ time: 100, message: 'hi' }); + const job2 = rb.add({ time: 200, message: 'bye' }); + const job1 = rb.add({ time: 100, message: 'hi' }); - assert.equal(callback.callCount, 0); + assert.equal(callback.callCount, 0); - clock.tick(105); + clock.tick(105); - assert.equal(callback.callCount, 1); - assert.equal(callback.args[0][0], job1); + assert.equal(callback.callCount, 1); + assert.equal(callback.args[0][0], job1); - clock.tick(200); + clock.tick(200); - assert.equal(callback.callCount, 2); - assert.equal(callback.args[1][0], job2); - }); + assert.equal(callback.callCount, 2); + assert.equal(callback.args[1][0], job2); + }); - it('emits jobs submitted in order in the correct order', () => { - rb.on('job', callback); + it('emits jobs submitted in order in the correct order', () => { + rb.on('job', callback); - const job1 = rb.add({ time: 100, message: 'hi' }); - const job2 = rb.add({ time: 200, message: 'bye' }); + const job1 = rb.add({ time: 100, message: 'hi' }); + const job2 = rb.add({ time: 200, message: 'bye' }); - assert.equal(callback.callCount, 0); + assert.equal(callback.callCount, 0); - clock.tick(105); + clock.tick(105); - assert.equal(callback.callCount, 1); - assert.equal(callback.args[0][0], job1); + assert.equal(callback.callCount, 1); + assert.equal(callback.args[0][0], job1); - clock.tick(200); + clock.tick(200); - assert.equal(callback.callCount, 2); - assert.equal(callback.args[1][0], job2); - }); + assert.equal(callback.callCount, 2); + assert.equal(callback.args[1][0], job2); + }); - it('emits a job in the next tick when it is scheduled for the past', () => { - rb.on('job', callback); + it('emits a job in the next tick when it is scheduled for the past', () => { + rb.on('job', callback); - const job = rb.add({ time: -100, message: 'test' }); + const job = rb.add({ time: -100, message: 'test' }); - assert.equal(callback.callCount, 0); + assert.equal(callback.callCount, 0); - clock.tick(1); + clock.tick(1); - assert.equal(callback.callCount, 1); - assert.equal(callback.args[0][0], job); - }); + assert.equal(callback.callCount, 1); + assert.equal(callback.args[0][0], job); + }); - it('emits a job beyond the resolution of setTimeout', () => { - rb.on('job', callback); + it('emits a job beyond the resolution of setTimeout', () => { + rb.on('job', callback); - const job = rb.add({ time: 3e9, message: 'test' }); + const job = rb.add({ time: 3e9, message: 'test' }); - clock.tick(10); + clock.tick(10); - assert.equal(callback.callCount, 0); + assert.equal(callback.callCount, 0); - clock.tick(3e9); + clock.tick(3e9); - assert.equal(callback.callCount, 1); - assert.equal(callback.args[0][0], job); - }); + assert.equal(callback.callCount, 1); + assert.equal(callback.args[0][0], job); + }); - it('emits clustered jobs simultaneously', () => { - rb.on('job', callback); + it('emits clustered jobs simultaneously', () => { + rb.on('job', callback); - const jobs = [ - rb.add({ time: 100, message: 'test0' }), - rb.add({ time: 100, message: 'test1' }), - rb.add({ time: 100, message: 'test2' }) - ]; + const jobs = [ + rb.add({ time: 100, message: 'test0' }), + rb.add({ time: 100, message: 'test1' }), + rb.add({ time: 100, message: 'test2' }) + ]; - clock.tick(10); + clock.tick(10); - assert.equal(callback.callCount, 0); + assert.equal(callback.callCount, 0); - clock.tick(90); + clock.tick(90); - assert.equal(callback.callCount, 3); - assert.ok(callback.calledWithExactly(jobs[0])); - assert.ok(callback.calledWithExactly(jobs[1])); - assert.ok(callback.calledWithExactly(jobs[2])); - }); - }); + assert.equal(callback.callCount, 3); + assert.ok(callback.calledWithExactly(jobs[0])); + assert.ok(callback.calledWithExactly(jobs[1])); + assert.ok(callback.calledWithExactly(jobs[2])); + }); + }); - describe('silenced', () => { - it('returns the job when add is called', () => { - const job = rb.add({ time: 100, message: 'hi' }, true); + describe('silenced', () => { + it('returns the job when add is called', () => { + const job = rb.add({ time: 100, message: 'hi' }, true); - assert.equal(job.time, 100); - assert.equal(job.message, 'hi'); - }); + assert.equal(job.time, 100); + assert.equal(job.message, 'hi'); + }); - it('does not emit "addJob"', () => { - rb.on('addJob', callback); - rb.add({ time: 100, message: 'hi' }, true); + it('does not emit "addJob"', () => { + rb.on('addJob', callback); + rb.add({ time: 100, message: 'hi' }, true); - assert.equal(callback.callCount, 0); - }); + assert.equal(callback.callCount, 0); + }); - it('adds a uuid to an added job when it does not have one', () => { - const job = rb.add({ time: 100, message: 'hi' }, true); + it('adds a uuid to an added job when it does not have one', () => { + const job = rb.add({ time: 100, message: 'hi' }, true); - assert.equal(typeof job.uuid, 'string'); - assert.ok(job.uuid.length); - }); + assert.equal(typeof job.uuid, 'string'); + assert.ok(job.uuid.length); + }); - it('does not change the uuid when the the added job has one', () => { - const job = rb.add({ time: 100, message: 'hi', uuid: 'abcd' }, true); + it('does not change the uuid when the the added job has one', () => { + const job = rb.add({ time: 100, message: 'hi', uuid: 'abcd' }, true); - assert.equal(job.uuid, 'abcd'); - }); + assert.equal(job.uuid, 'abcd'); + }); - it('emits the added job when the timeout has elapsed', () => { - rb.on('job', callback); + it('emits the added job when the timeout has elapsed', () => { + rb.on('job', callback); - const job = rb.add({ time: 100, message: 'hi' }, true); + const job = rb.add({ time: 100, message: 'hi' }, true); - assert.equal(callback.callCount, 0); + assert.equal(callback.callCount, 0); - clock.tick(105); + clock.tick(105); - assert.equal(callback.callCount, 1); - assert.equal(callback.args[0][0], job); - }); + assert.equal(callback.callCount, 1); + assert.equal(callback.args[0][0], job); + }); - it('emits jobs submitted in wrong order in the correct order', () => { - rb.on('job', callback); + it('emits jobs submitted in wrong order in the correct order', () => { + rb.on('job', callback); - const job2 = rb.add({ time: 200, message: 'bye' }, true); - const job1 = rb.add({ time: 100, message: 'hi' }, true); + const job2 = rb.add({ time: 200, message: 'bye' }, true); + const job1 = rb.add({ time: 100, message: 'hi' }, true); - assert.equal(callback.callCount, 0); + assert.equal(callback.callCount, 0); - clock.tick(105); + clock.tick(105); - assert.equal(callback.callCount, 1); - assert.equal(callback.args[0][0], job1); + assert.equal(callback.callCount, 1); + assert.equal(callback.args[0][0], job1); - clock.tick(200); + clock.tick(200); - assert.equal(callback.callCount, 2); - assert.equal(callback.args[1][0], job2); - }); + assert.equal(callback.callCount, 2); + assert.equal(callback.args[1][0], job2); + }); - it('emits jobs submitted in order in the correct order', () => { - rb.on('job', callback); + it('emits jobs submitted in order in the correct order', () => { + rb.on('job', callback); - const job1 = rb.add({ time: 100, message: 'hi' }, true); - const job2 = rb.add({ time: 200, message: 'bye' }, true); + const job1 = rb.add({ time: 100, message: 'hi' }, true); + const job2 = rb.add({ time: 200, message: 'bye' }, true); - assert.equal(callback.callCount, 0); + assert.equal(callback.callCount, 0); - clock.tick(105); + clock.tick(105); - assert.equal(callback.callCount, 1); - assert.equal(callback.args[0][0], job1); + assert.equal(callback.callCount, 1); + assert.equal(callback.args[0][0], job1); - clock.tick(200); + clock.tick(200); - assert.equal(callback.callCount, 2); - assert.equal(callback.args[1][0], job2); - }); + assert.equal(callback.callCount, 2); + assert.equal(callback.args[1][0], job2); + }); - it('emits a job in the next tick when it is scheduled for the past', () => { - rb.on('job', callback); + it('emits a job in the next tick when it is scheduled for the past', () => { + rb.on('job', callback); - const job = rb.add({ time: -100, message: 'test' }, true); + const job = rb.add({ time: -100, message: 'test' }, true); - assert.equal(callback.callCount, 0); + assert.equal(callback.callCount, 0); - clock.tick(1); + clock.tick(1); - assert.equal(callback.callCount, 1); - assert.equal(callback.args[0][0], job); - }); + assert.equal(callback.callCount, 1); + assert.equal(callback.args[0][0], job); + }); - it('emits a job beyond the resolution of setTimeout', () => { - rb.on('job', callback); + it('emits a job beyond the resolution of setTimeout', () => { + rb.on('job', callback); - const job = rb.add({ time: 3e9, message: 'test' }, true); + const job = rb.add({ time: 3e9, message: 'test' }, true); - clock.tick(10); + clock.tick(10); - assert.equal(callback.callCount, 0); + assert.equal(callback.callCount, 0); - clock.tick(3e9); + clock.tick(3e9); - assert.equal(callback.callCount, 1); - assert.equal(callback.args[0][0], job); - }); + assert.equal(callback.callCount, 1); + assert.equal(callback.args[0][0], job); + }); - it('emits clustered jobs simultaneously', () => { - rb.on('job', callback); + it('emits clustered jobs simultaneously', () => { + rb.on('job', callback); - const jobs = [ - rb.add({ time: 100, message: 'test0' }), - rb.add({ time: 100, message: 'test1' }), - rb.add({ time: 100, message: 'test2' }) - ]; + const jobs = [ + rb.add({ time: 100, message: 'test0' }), + rb.add({ time: 100, message: 'test1' }), + rb.add({ time: 100, message: 'test2' }) + ]; - clock.tick(10); + clock.tick(10); - assert.equal(callback.callCount, 0); + assert.equal(callback.callCount, 0); - clock.tick(90); + clock.tick(90); - assert.equal(callback.callCount, 3); - assert.ok(callback.calledWithExactly(jobs[0])); - assert.ok(callback.calledWithExactly(jobs[1])); - assert.ok(callback.calledWithExactly(jobs[2])); - }); - }); + assert.equal(callback.callCount, 3); + assert.ok(callback.calledWithExactly(jobs[0])); + assert.ok(callback.calledWithExactly(jobs[1])); + assert.ok(callback.calledWithExactly(jobs[2])); + }); }); + }); - describe('remove', () => { - describe('not silenced', () => { - it('returns the job when removeJob is called', () => { - const job = rb.add({ time: 100, message: 'hi' }); - const removed = rb.remove(job.uuid); + describe('remove', () => { + describe('not silenced', () => { + it('returns the job when removeJob is called', () => { + const job = rb.add({ time: 100, message: 'hi' }); + const removed = rb.remove(job.uuid); - assert.equal(removed, job); - }); + assert.equal(removed, job); + }); - it('emits "removeJob"', () => { - rb.on('removeJob', callback); + it('emits "removeJob"', () => { + rb.on('removeJob', callback); - const job = rb.add({ time: 100, message: 'hi' }); + const job = rb.add({ time: 100, message: 'hi' }); - assert.equal(callback.callCount, 0); + assert.equal(callback.callCount, 0); - rb.remove(job.uuid); + rb.remove(job.uuid); - assert.equal(callback.callCount, 1); - assert.equal(callback.args[0][0], job); - }); + assert.equal(callback.callCount, 1); + assert.equal(callback.args[0][0], job); + }); - it('does not emit removed jobs with "job"', () => { - rb.on('job', callback); + it('does not emit removed jobs with "job"', () => { + rb.on('job', callback); - const job = rb.add({ time: Date.now() + 100, message: 'test' }); + const job = rb.add({ time: Date.now() + 100, message: 'test' }); - rb.remove(job.uuid); + rb.remove(job.uuid); - clock.tick(105); + clock.tick(105); - assert.equal(callback.callCount, 0); - }); + assert.equal(callback.callCount, 0); + }); - it('returns undefined when removing a non-existent job', () => { - const removed = rb.remove('abcd'); + it('returns undefined when removing a non-existent job', () => { + const removed = rb.remove('abcd'); - assert.strictEqual(removed, undefined); - }); + assert.strictEqual(removed, undefined); + }); - it('does not affect the following job when the next is removed', () => { - rb.on('job', callback); + it('does not affect the following job when the next is removed', () => { + rb.on('job', callback); - const job1 = rb.add({ time: 100, message: 'test1' }); - const job2 = rb.add({ time: 200, message: 'test2' }); + const job1 = rb.add({ time: 100, message: 'test1' }); + const job2 = rb.add({ time: 200, message: 'test2' }); - rb.remove(job1.uuid); + rb.remove(job1.uuid); - clock.tick(105); + clock.tick(105); - assert.equal(callback.callCount, 0); + assert.equal(callback.callCount, 0); - clock.tick(100); + clock.tick(100); - assert.equal(callback.callCount, 1); - assert.equal(callback.args[0][0], job2); - }); + assert.equal(callback.callCount, 1); + assert.equal(callback.args[0][0], job2); + }); - it('does not affect the job following when a job (not next) is removed', () => { - rb.on('job', callback); + it('does not affect the job following when a job (not next) is removed', () => { + rb.on('job', callback); - const job2 = rb.add({ time: 200, message: 'test2' }); - const job1 = rb.add({ time: 100, message: 'test1' }); - const job3 = rb.add({ time: 300, message: 'test3' }); + const job2 = rb.add({ time: 200, message: 'test2' }); + const job1 = rb.add({ time: 100, message: 'test1' }); + const job3 = rb.add({ time: 300, message: 'test3' }); - rb.remove(job2.uuid); + rb.remove(job2.uuid); - clock.tick(105); + clock.tick(105); - assert.equal(callback.callCount, 1); - assert.equal(callback.args[0][0], job1); + assert.equal(callback.callCount, 1); + assert.equal(callback.args[0][0], job1); - clock.tick(100); + clock.tick(100); - assert.equal(callback.callCount, 1); + assert.equal(callback.callCount, 1); - clock.tick(100); + clock.tick(100); - assert.equal(callback.callCount, 2); - assert.equal(callback.args[1][0], job3); - }); - }); + assert.equal(callback.callCount, 2); + assert.equal(callback.args[1][0], job3); + }); + }); - describe('silenced', () => { - it('returns the job when removeJob is called', () => { - const job = rb.add({ time: 100, message: 'hi' }); - const removed = rb.remove(job.uuid, true); + describe('silenced', () => { + it('returns the job when removeJob is called', () => { + const job = rb.add({ time: 100, message: 'hi' }); + const removed = rb.remove(job.uuid, true); - assert.equal(removed, job); - }); + assert.equal(removed, job); + }); - it('does not emit "removeJob"', () => { - rb.on('removeJob', callback); + it('does not emit "removeJob"', () => { + rb.on('removeJob', callback); - const job = rb.add({ time: 100, message: 'hi' }); + const job = rb.add({ time: 100, message: 'hi' }); - assert.equal(callback.callCount, 0); + assert.equal(callback.callCount, 0); - rb.remove(job.uuid, true); + rb.remove(job.uuid, true); - assert.equal(callback.callCount, 0); - }); + assert.equal(callback.callCount, 0); + }); - it('does not emit removed jobs with "job"', () => { - rb.on('job', callback); + it('does not emit removed jobs with "job"', () => { + rb.on('job', callback); - const job = rb.add({ time: Date.now() + 100, message: 'test' }); + const job = rb.add({ time: Date.now() + 100, message: 'test' }); - rb.remove(job.uuid, true); + rb.remove(job.uuid, true); - clock.tick(105); + clock.tick(105); - assert.equal(callback.callCount, 0); - }); + assert.equal(callback.callCount, 0); + }); - it('returns undefined when removing a non-existent job', () => { - const removed = rb.remove('abcd', true); + it('returns undefined when removing a non-existent job', () => { + const removed = rb.remove('abcd', true); - assert.strictEqual(removed, undefined); - }); + assert.strictEqual(removed, undefined); + }); - it('does not affect the following job when the next is removed', () => { - rb.on('job', callback); + it('does not affect the following job when the next is removed', () => { + rb.on('job', callback); - const job1 = rb.add({ time: 100, message: 'test1' }); - const job2 = rb.add({ time: 200, message: 'test2' }); + const job1 = rb.add({ time: 100, message: 'test1' }); + const job2 = rb.add({ time: 200, message: 'test2' }); - rb.remove(job1.uuid, true); + rb.remove(job1.uuid, true); - clock.tick(105); + clock.tick(105); - assert.equal(callback.callCount, 0); + assert.equal(callback.callCount, 0); - clock.tick(100); + clock.tick(100); - assert.equal(callback.callCount, 1); - assert.equal(callback.args[0][0], job2); - }); + assert.equal(callback.callCount, 1); + assert.equal(callback.args[0][0], job2); + }); - it('does not affect the job following when a job (not next) is removed', () => { - rb.on('job', callback); + it('does not affect the job following when a job (not next) is removed', () => { + rb.on('job', callback); - const job2 = rb.add({ time: 200, message: 'test2' }); - const job1 = rb.add({ time: 100, message: 'test1' }); - const job3 = rb.add({ time: 300, message: 'test3' }); + const job2 = rb.add({ time: 200, message: 'test2' }); + const job1 = rb.add({ time: 100, message: 'test1' }); + const job3 = rb.add({ time: 300, message: 'test3' }); - rb.remove(job2.uuid, true); + rb.remove(job2.uuid, true); - clock.tick(105); + clock.tick(105); - assert.equal(callback.callCount, 1); - assert.equal(callback.args[0][0], job1); + assert.equal(callback.callCount, 1); + assert.equal(callback.args[0][0], job1); - clock.tick(100); + clock.tick(100); - assert.equal(callback.callCount, 1); + assert.equal(callback.callCount, 1); - clock.tick(100); + clock.tick(100); - assert.equal(callback.callCount, 2); - assert.equal(callback.args[1][0], job3); - }); - }); + assert.equal(callback.callCount, 2); + assert.equal(callback.args[1][0], job3); + }); }); + }); - describe('find', () => { - it('finds the correct job with the find method and a uuid', () => { - rb.add({ time: 100, message: 'test' }); + describe('find', () => { + it('finds the correct job with the find method and a uuid', () => { + rb.add({ time: 100, message: 'test' }); - const job = rb.add({ time: 200, message: 'test' }); + const job = rb.add({ time: 200, message: 'test' }); - rb.add({ time: 300, message: 'test' }); - rb.add({ time: 400, message: 'test' }); - rb.add({ time: 500, message: 'test' }); + rb.add({ time: 300, message: 'test' }); + rb.add({ time: 400, message: 'test' }); + rb.add({ time: 500, message: 'test' }); - assert.equal(rb.find(job.uuid), job); - }); + assert.equal(rb.find(job.uuid), job); + }); - it('does not find a non-existent job', () => { - rb.add({ time: 100, message: 'test' }); + it('does not find a non-existent job', () => { + rb.add({ time: 100, message: 'test' }); - const job = rb.add({ time: 200, message: 'test' }); + const job = rb.add({ time: 200, message: 'test' }); - rb.add({ time: 300, message: 'test' }); - rb.add({ time: 400, message: 'test' }); - rb.add({ time: 500, message: 'test' }); + rb.add({ time: 300, message: 'test' }); + rb.add({ time: 400, message: 'test' }); + rb.add({ time: 500, message: 'test' }); - rb.remove(job.uuid); + rb.remove(job.uuid); - assert.strictEqual(rb.find(job.uuid), undefined); - }); + assert.strictEqual(rb.find(job.uuid), undefined); }); + }); - describe('clear', () => { - let clearCallback; - let removeCallback; - let jobs; - - beforeEach(() => { - clearCallback = sinon.stub(); - removeCallback = sinon.stub(); - - rb.on('job', callback); - rb.on('clearJobs', clearCallback); - rb.on('removeJob', removeCallback); - - jobs = [ - rb.add({ time: 200, message: 'test2' }), - rb.add({ time: 100, message: 'test1' }), - rb.add({ time: 300, message: 'test3' }) - ]; - }); - - describe('not silenced', () => { - beforeEach(() => { - rb.clear(); - }); - - it('emits "clearJobs"', () => { - assert.equal(clearCallback.callCount, 1); - }); - - it('emits "removeJob" for each job', () => { - assert.equal(removeCallback.callCount, 3); - - for (const job of jobs) { - assert.ok(removeCallback.calledWithExactly(job)); - } - }); - - it('prevents previously scheduled jobs from being emitted', () => { - clock.tick(310); - - assert.equal(callback.callCount, 0); - }); - }); - - describe('silenced', () => { - beforeEach(() => { - rb.clear(true); - }); - - it('does not emit "clearJobs"', () => { - assert.equal(clearCallback.callCount, 0); - }); - - it('does not emit "removeJob"', () => { - assert.equal(removeCallback.callCount, 0); - }); - - it('prevents previously scheduled jobs from being emitted', () => { - clock.tick(310); - - assert.equal(callback.callCount, 0); - }); - }); + describe('clear', () => { + let clearCallback; + let removeCallback; + let jobs; + + beforeEach(() => { + clearCallback = sinon.stub(); + removeCallback = sinon.stub(); + + rb.on('job', callback); + rb.on('clearJobs', clearCallback); + rb.on('removeJob', removeCallback); + + jobs = [ + rb.add({ time: 200, message: 'test2' }), + rb.add({ time: 100, message: 'test1' }), + rb.add({ time: 300, message: 'test3' }) + ]; }); - describe('hasPendingJobs', () => { - it('is false before jobs are added', () => { - assert.strictEqual(rb.hasPendingJobs, false); - }); + describe('not silenced', () => { + beforeEach(() => { + rb.clear(); + }); - it('is true when a job is added', () => { - rb.add({ time: 100, message: 'test1' }); + it('emits "clearJobs"', () => { + assert.equal(clearCallback.callCount, 1); + }); - assert.strictEqual(rb.hasPendingJobs, true); - }); + it('emits "removeJob" for each job', () => { + assert.equal(removeCallback.callCount, 3); - it('is false once all jobs have been emitted', () => { - rb.add({ time: 100, message: 'test1' }); + for (const job of jobs) { + assert.ok(removeCallback.calledWithExactly(job)); + } + }); - clock.tick(110); + it('prevents previously scheduled jobs from being emitted', () => { + clock.tick(310); - assert.strictEqual(rb.hasPendingJobs, false); - }); + assert.equal(callback.callCount, 0); + }); + }); - it('is false once all jobs have been removed', () => { - const job = rb.add({ time: 100, message: 'test1' }); + describe('silenced', () => { + beforeEach(() => { + rb.clear(true); + }); - rb.remove(job.uuid); + it('does not emit "clearJobs"', () => { + assert.equal(clearCallback.callCount, 0); + }); - assert.strictEqual(rb.hasPendingJobs, false); - }); + it('does not emit "removeJob"', () => { + assert.equal(removeCallback.callCount, 0); + }); + + it('prevents previously scheduled jobs from being emitted', () => { + clock.tick(310); + + assert.equal(callback.callCount, 0); + }); + }); + }); + + describe('hasPendingJobs', () => { + it('is false before jobs are added', () => { + assert.strictEqual(rb.hasPendingJobs, false); + }); + + it('is true when a job is added', () => { + rb.add({ time: 100, message: 'test1' }); + + assert.strictEqual(rb.hasPendingJobs, true); + }); + + it('is false once all jobs have been emitted', () => { + rb.add({ time: 100, message: 'test1' }); + + clock.tick(110); + + assert.strictEqual(rb.hasPendingJobs, false); + }); + + it('is false once all jobs have been removed', () => { + const job = rb.add({ time: 100, message: 'test1' }); + + rb.remove(job.uuid); + + assert.strictEqual(rb.hasPendingJobs, false); + }); - it('is false once all jobs have been cleared', () => { - rb.add({ time: 100, message: 'test1' }); + it('is false once all jobs have been cleared', () => { + rb.add({ time: 100, message: 'test1' }); - rb.clear(); + rb.clear(); - assert.strictEqual(rb.hasPendingJobs, false); - }); + assert.strictEqual(rb.hasPendingJobs, false); }); + }); }); diff --git a/test/test-uuidv4.js b/test/test-uuidv4.js index f13bc79..fe0fe6c 100644 --- a/test/test-uuidv4.js +++ b/test/test-uuidv4.js @@ -5,65 +5,65 @@ const assert = require('assert'); const uuidv4 = require('../build/uuidv4.common.js'); describe('uuidv4', () => { - it('is a function', () => { - assert.equal(typeof uuidv4, 'function'); - }); + it('is a function', () => { + assert.equal(typeof uuidv4, 'function'); + }); - describe('sample', () => { - const expected = 'c2d06e01-217b-4f6d6d5-80ccc42-642e8573401b'; + describe('sample', () => { + const expected = 'c2d06e01-217b-4f6d6d5-80ccc42-642e8573401b'; - beforeEach(() => { - sinon.stub(Math, 'random'); + beforeEach(() => { + sinon.stub(Math, 'random'); - Math.random.onCall(0).returns(0.7598701265952619); - Math.random.onCall(1).returns(0.8134768956731693); - Math.random.onCall(2).returns(0.4324240063309106); - Math.random.onCall(3).returns(0.004501034384116309); - Math.random.onCall(4).returns(0.13056163393263187); - Math.random.onCall(5).returns(0.483824321959035); - Math.random.onCall(6).returns(0.962755439322031); - Math.random.onCall(7).returns(0.8385543919513738); - Math.random.onCall(8).returns(0.832324777600663); - Math.random.onCall(9).returns(0.051273026356071005); - Math.random.onCall(10).returns(0.04931980291567517); - Math.random.onCall(11).returns(0.7970684833761694); - Math.random.onCall(12).returns(0.25914385183758615); - Math.random.onCall(13).returns(0.390900363131224); - Math.random.onCall(14).returns(0.1808070966332891); - Math.random.onCall(15).returns(0.5228907810351897); - Math.random.onCall(16).returns(0.45064177320914434); - Math.random.onCall(17).returns(0.2501263934740454); - Math.random.onCall(18).returns(0.1073328779456526); - }); + Math.random.onCall(0).returns(0.7598701265952619); + Math.random.onCall(1).returns(0.8134768956731693); + Math.random.onCall(2).returns(0.4324240063309106); + Math.random.onCall(3).returns(0.004501034384116309); + Math.random.onCall(4).returns(0.13056163393263187); + Math.random.onCall(5).returns(0.483824321959035); + Math.random.onCall(6).returns(0.962755439322031); + Math.random.onCall(7).returns(0.8385543919513738); + Math.random.onCall(8).returns(0.832324777600663); + Math.random.onCall(9).returns(0.051273026356071005); + Math.random.onCall(10).returns(0.04931980291567517); + Math.random.onCall(11).returns(0.7970684833761694); + Math.random.onCall(12).returns(0.25914385183758615); + Math.random.onCall(13).returns(0.390900363131224); + Math.random.onCall(14).returns(0.1808070966332891); + Math.random.onCall(15).returns(0.5228907810351897); + Math.random.onCall(16).returns(0.45064177320914434); + Math.random.onCall(17).returns(0.2501263934740454); + Math.random.onCall(18).returns(0.1073328779456526); + }); - afterEach(() => { - Math.random.restore(); - }); + afterEach(() => { + Math.random.restore(); + }); - it('is the expected string', () => { - const sample = uuidv4(); + it('is the expected string', () => { + const sample = uuidv4(); - assert.equal(sample, expected); - }); + assert.equal(sample, expected); }); + }); - it('produces UUID strings of the correct length', () => { - for (let i = 0; i < 10000; i++) { - assert.equal(uuidv4().length, 42); - } - }); + it('produces UUID strings of the correct length', () => { + for (let i = 0; i < 10000; i++) { + assert.equal(uuidv4().length, 42); + } + }); - it('does not easily produce duplicates', () => { - const uuids = new Set(); + it('does not easily produce duplicates', () => { + const uuids = new Set(); - for (let i = 0; i < 10000; i++) { - const uuid = uuidv4(); + for (let i = 0; i < 10000; i++) { + const uuid = uuidv4(); - if (uuids.has(uuid)) { - throw new Error(`Duplicate UUID produced: ${uuid}`); - } + if (uuids.has(uuid)) { + throw new Error(`Duplicate UUID produced: ${uuid}`); + } - uuids.add(uuid); - } - }); + uuids.add(uuid); + } + }); });