<commit_before>'use strict';

var fs = require('fs');
var express = require('express');
var prepare = require('../');

var app = express();

var HTML_STRING = fs.readFileSync(__dirname + '/test.html', 'utf8');
var JS_STRING = 'alert("foo");';
var html = prepare(HTML_STRING, {'content-type': 'html'});
var script = prepare(JS_STRING, {'content-type': 'js', 'cache-control': '1 year'});

app.get('/', function (req, res, next) {
  html.send(req, res, next);
});
app.get('/client.js', function (req, res, next) {
  script.send(req, res, next);
});

var server = app.listen(3000);

var assert = require('assert');
var http = require('http');
var zlib = require('zlib');
var Promise = require('promise');
var concat = require('concat-stream');
var test = require('testit');

function request(path, headers) {
  return new Promise(function (resolve, reject) {
    http.request({
      host: 'localhost',
      port: 3000,
      path: path,
      method: 'GET',
      headers: headers
    }, function (res) {
      res.on('error', reject);
      res.pipe(concat(function (body) {
        resolve({statusCode: res.statusCode, body: body, headers: res.headers});
      }));
    }).on('error', reject).end();
  });
}
function gunzip(body) {
  return new Promise(function (resolve, reject) {
    zlib.gunzip(body, function (err, res) {
      if (err) reject(err);
      else resolve(res);
    }.bind(this));
  });
}
test('raw-request', function () {
  return request('/', {}).then(function (res) {
    assert(res.statusCode === 200);
    assert(res.body.toString() === HTML_STRING);
    assert(res.headers.vary === 'Accept-Encoding');
    assert(res.headers.etag === '76f7dd7da1deaa8cec3648c1f4790852');
    assert(res.headers['content-length'] === '16530');
    assert(res.headers['content-type'] === 'text/html');
  });
});
test('gzip-request', function () {
  return request('/', {'accept-Encoding': 'gzip'}).then(function (res) {
    assert(res.statusCode === 200);
    assert(res.headers.vary === 'Accept-Encoding');
    assert(res.headers.etag === '76f7dd7da1deaa8cec3648c1f4790852');
    assert(res.headers['content-length'] === '4525');
    assert(res.headers['content-type'] === 'text/html');
    assert(res.headers['content-encoding'] === 'gzip');
    return gunzip(res.body);
  }).then(function (body) {
    assert(body.toString() === HTML_STRING);
  });
});
test('etag-request', function () {
  return request('/', {'if-None-Match': '76f7dd7da1deaa8cec3648c1f4790852'}).then(function (res) {
    assert(res.statusCode === 304);
    assert(res.body.length === 0);
  });
});

test('raw-request-2', function () {
  return request('/client.js', {}).then(function (res) {
    assert(res.statusCode === 200);
    assert(res.body.toString() === JS_STRING);
    assert(res.headers.vary === 'Accept-Encoding');
    assert(res.headers.etag === 'af5c77b360ffe88dbed4b3d71e3d0eba');
    assert(res.headers['content-length'] === '13');
    assert(res.headers['content-type'] === 'application/javascript');
    assert(res.headers['cache-control'] === 'public, max-age=31557600');
  });
});
test('gzip-request-2', function () {
  // won't actually gzip because the text response is shorter without gzip
  return request('/client.js', {'accept-Encoding': 'gzip'}).then(function (res) {
    assert(res.statusCode === 200);
    assert(res.body.toString() === JS_STRING);
    assert(res.headers.vary === 'Accept-Encoding');
    assert(res.headers.etag === 'af5c77b360ffe88dbed4b3d71e3d0eba');
    assert(res.headers['content-length'] === '13');
    assert(res.headers['content-type'] === 'application/javascript');
    assert(res.headers['cache-control'] === 'public, max-age=31557600');
    assert(res.headers['content-encoding'] !== 'gzip');
  });
});

test('cleanup', function () {
  server.close();
});
<commit_msg>Update test cases<commit_after>'use strict';

var fs = require('fs');
var express = require('express');
var prepare = require('../');

var app = express();

var HTML_STRING = fs.readFileSync(__dirname + '/test.html', 'utf8');
var JS_STRING = 'alert("foo");';
var html = prepare(HTML_STRING, {'content-type': 'html'});
var script = prepare(JS_STRING, {'content-type': 'js', 'cache-control': '1 year'});

app.get('/', function (req, res, next) {
  html.send(req, res, next);
});
app.get('/client.js', function (req, res, next) {
  script.send(req, res, next);
});

var server = app.listen(3000);

var assert = require('assert');
var http = require('http');
var zlib = require('zlib');
var Promise = require('promise');
var concat = require('concat-stream');
var test = require('testit');

function request(path, headers) {
  return new Promise(function (resolve, reject) {
    http.request({
      host: 'localhost',
      port: 3000,
      path: path,
      method: 'GET',
      headers: headers
    }, function (res) {
      res.on('error', reject);
      res.pipe(concat(function (body) {
        resolve({statusCode: res.statusCode, body: body, headers: res.headers});
      }));
    }).on('error', reject).end();
  });
}
function gunzip(body) {
  return new Promise(function (resolve, reject) {
    zlib.gunzip(body, function (err, res) {
      if (err) reject(err);
      else resolve(res);
    }.bind(this));
  });
}
test('raw-request', function () {
  return request('/', {}).then(function (res) {
    assert(res.statusCode === 200);
    assert(res.body.toString() === HTML_STRING);
    assert(res.headers.vary === 'Accept-Encoding');
    assert(res.headers.etag === '76f7dd7da1deaa8cec3648c1f4790852');
    assert(res.headers['content-length'] === '16530');
    assert(res.headers['content-type'] === 'text/html');
  });
});
test('gzip-request', function () {
  return request('/', {'accept-Encoding': 'gzip'}).then(function (res) {
    assert(res.statusCode === 200);
    assert(res.headers.vary === 'Accept-Encoding');
    assert(res.headers.etag === '76f7dd7da1deaa8cec3648c1f4790852');
    assert(res.headers['content-length'] === '4525');
    assert(res.headers['content-type'] === 'text/html');
    assert(res.headers['content-encoding'] === 'gzip');
    return gunzip(res.body);
  }).then(function (body) {
    assert(body.toString() === HTML_STRING);
  });
});
test('etag-request', function () {
  return request('/', {'if-None-Match': '76f7dd7da1deaa8cec3648c1f4790852'}).then(function (res) {
    assert(res.statusCode === 304);
    assert(res.body.length === 0);
  });
});

test('raw-request-2', function () {
  return request('/client.js', {}).then(function (res) {
    assert(res.statusCode === 200);
    assert(res.body.toString() === JS_STRING);
    assert(res.headers.vary !== 'Accept-Encoding');
    assert(res.headers.etag === 'af5c77b360ffe88dbed4b3d71e3d0eba');
    assert(res.headers['content-length'] === '13');
    assert(res.headers['content-type'] === 'application/javascript');
    assert(res.headers['cache-control'] === 'public, max-age=31557600');
  });
});
test('gzip-request-2', function () {
  // won't actually gzip because the text response is shorter without gzip
  return request('/client.js', {'accept-Encoding': 'gzip'}).then(function (res) {
    assert(res.statusCode === 200);
    assert(res.body.toString() === JS_STRING);
    assert(res.headers.vary !== 'Accept-Encoding');
    assert(res.headers.etag === 'af5c77b360ffe88dbed4b3d71e3d0eba');
    assert(res.headers['content-length'] === '13');
    assert(res.headers['content-type'] === 'application/javascript');
    assert(res.headers['cache-control'] === 'public, max-age=31557600');
    assert(res.headers['content-encoding'] !== 'gzip');
  });
});

test('cleanup', function () {
  server.close();
});
<|endoftext|>


<commit_before>const test = require('tape')
const Objectspy = require('../src/objectspy.js')

// polyfill
global.cancelAnimationFrame = id => clearTimeout(id)
global.requestAnimationFrame = callback => setTimeout(() => callback(), 1)

const initial_state = { foo: Math.random(), bar: Math.random(), deep: { deep1: Math.random(), deep2: Math.random() } }

test('Empty construct', assert => {
  assert.plan(1)

  const state = new Objectspy()
  assert.deepEqual(state.get(), {})
})

test('Construct with state', assert => {
  assert.plan(1)

  const state = new Objectspy(initial_state)
  assert.deepEqual(state.get(), initial_state)
})

test('Get exist path', assert => {
  assert.plan(1)

  const state = new Objectspy(initial_state)
  assert.deepEqual(state.get('foo'), initial_state.foo)
})

test('Get nested exist path', assert => {
  assert.plan(1)

  const state = new Objectspy(initial_state)
  assert.deepEqual(state.get('deep.deep1'), initial_state.deep.deep1)
})

test('Get no exist path', assert => {
  assert.plan(1)

  const state = new Objectspy(initial_state)
  assert.deepEqual(state.get('__' + Math.random()), undefined)
})

test('Get nested no exist path', assert => {
  assert.plan(1)

  const state = new Objectspy(initial_state)
  assert.deepEqual(state.get('deep.deep1.test'), undefined)
})

test('Update state', assert => {
  assert.plan(1)
  const value = Math.random()
  const state = new Objectspy(initial_state)
  state.set('foo', value)
  assert.deepEqual(state.get(), Object.assign({}, initial_state , { foo: value }))
})

test('Update state by object', assert => {
  assert.plan(1)
  const value = { deep3: Math.random() }
  const state = new Objectspy(initial_state)
  state.set('deep', value)
  assert.deepEqual(state.get(), Object.assign({}, initial_state , { deep: value }))
})

test('Update nested state', assert => {
  assert.plan(1)
  const value = Math.random()
  const state = new Objectspy(initial_state)
  state.set('deep.deep1', value)

  const expected_result = Object.assign({}, initial_state)
  expected_result.deep.deep1 = value

  assert.deepEqual(state.get(), expected_result)
})

test('Update similar path', assert => {
  assert.plan(1)
  const value = Math.random()
  const state = new Objectspy(initial_state)
  state.set('deep.deep1', value)
  state.set('deep', value)

  const expected_result = Object.assign({}, initial_state)
  expected_result.deep = value

  assert.deepEqual(state.get(), expected_result)
})

test('Delete state', assert => {
  assert.plan(1)

  const state = new Objectspy(initial_state)
  state.del('foo')

  const expected_result = Object.assign({}, initial_state)
  delete(expected_result.foo)

  assert.deepEqual(state.get(), expected_result)
})

test('Delete nested state', assert => {

  assert.plan(1)

  const state = new Objectspy(initial_state)
  state.del('deep.deep1')

  const expected_result = Object.assign({}, initial_state)
  delete(expected_result.deep.deep1)

  assert.deepEqual(state.get(), expected_result)
})

test('Add onchange callback', assert => {
  assert.plan(2)

  const state = new Objectspy(initial_state)

  let n = 0
  state.on('onchange', () => n++)

  // async call && requestAnimationFrame
  setTimeout(() => {
    state.set('foo', Math.random())
    assert.equal(n, 0)
    setTimeout(() => assert.equal(n, 1), 1) // only async callback execeution
  }, 1)
})

test('Remove onchange callback', assert => {
  assert.plan(1)
  const state = new Objectspy(initial_state)

  let n = 0
  const callback = () => n++
  state.on('onchange', callback)

  state.set('foo', Math.random())

  setTimeout(() => {
    state.off('onchange', callback)
    state.set('foo', Math.random())
    setTimeout(() => assert.equal(n, 1), 1)
  }, 1)
})

test('Update w/o run onchange callback (silent mode)', assert => {
  assert.plan(1)
  const state = new Objectspy(initial_state)
  let n = 0
  state.on('onchange', () => n++)
  state.set('foo', Math.random(), true)
  setTimeout(() => assert.equal(n, 0), 20)
})

test('Add path callback', assert => {
  assert.plan(1)
  const state = new Objectspy(initial_state)

  let n = 0
  state.on('foo', () => n++)

  state.set('foo', Math.random())
  state.set('bar', Math.random())
  setTimeout(() => assert.equal(n, 1), 1)
})

test('Add nested path callback', assert => {
  assert.plan(1)
  const state = new Objectspy(initial_state)

  let n = 0
  state.on('deep.deep1', () => n++)

  state.set('deep.deep1', Math.random())
  state.set('deep.deep2', Math.random())

  setTimeout(() => assert.equal(n, 1), 1)
})

test('Prevent callback on set similar value', assert => {
  assert.plan(2)
  const state = new Objectspy(initial_state)

  let n = 0
  const val = Math.random()

  state.on('foo', () => n++)
  state.set('foo', val)

  setTimeout(() => {
    assert.equal(n, 1)
    state.set('foo', val)
    setTimeout(() => assert.equal(n, 1), 1)
  }, 1)
})

test('Add similar callbacks', assert => {
  assert.plan(1)
  const state = new Objectspy(initial_state)

  let n = 0
  state.on('deep', () => n++)
  state.on('deep.deep1', () => n++)
  state.set('deep.deep1', Math.random())

  setTimeout(() => assert.equal(n, 2), 1)
})

test('Add null callback', assert => {
  assert.plan(1)
  const state = new Objectspy(initial_state)

  let n = 0
  state.on(null, () => n++)

  state.set('foo', 2)
  state.set('bar', 2)
  state.set(null, 3)
  state.set(null, {foo: 3})

  setTimeout(() => assert.equal(n, 0), 1)
})

test('Remove path callback', assert => {
  assert.plan(1)
  const state = new Objectspy(initial_state)
  let n = 0
  const callback = () => n++
  state.on('foo', callback)
  state.set('foo', Math.random())

  setTimeout(() => {
    state.off('foo', callback)
    state.set('foo', Math.random())
    setTimeout(() => assert.equal(n, 1), 1)
  }, 1)
})

test('Update w/o call path callback (silent mode)', assert => {
  assert.plan(1)
  const state = new Objectspy(initial_state)
  let n = 0

  state.on('foo', () => n++)
  state.set('foo', Math.random(), true)
  setTimeout(() => assert.equal(n, 0), 1)
})

test('GC', assert => {
  assert.plan(1)

  const state = new Objectspy(initial_state, { gc: true, gc_interval: 1 })
  state.on('foo', () => {})
  state.on('deep.deep1', () => {})

  setTimeout(() => {
    assert.deepEqual(state.get(), { foo: initial_state.foo, deep: { deep1: initial_state.deep.deep1 } })
    state.destructor()
  }, 1001)
})
<commit_msg>Tests: delete all state<commit_after>const test = require('tape')
const Objectspy = require('../src/objectspy.js')

// polyfill
global.cancelAnimationFrame = id => clearTimeout(id)
global.requestAnimationFrame = callback => setTimeout(() => callback(), 1)

const initial_state = { foo: Math.random(), bar: Math.random(), deep: { deep1: Math.random(), deep2: Math.random() } }

test('Empty construct', assert => {
  assert.plan(1)

  const state = new Objectspy()
  assert.deepEqual(state.get(), {})
})

test('Construct with state', assert => {
  assert.plan(1)

  const state = new Objectspy(initial_state)
  assert.deepEqual(state.get(), initial_state)
})

test('Get exist path', assert => {
  assert.plan(1)

  const state = new Objectspy(initial_state)
  assert.deepEqual(state.get('foo'), initial_state.foo)
})

test('Get nested exist path', assert => {
  assert.plan(1)

  const state = new Objectspy(initial_state)
  assert.deepEqual(state.get('deep.deep1'), initial_state.deep.deep1)
})

test('Get no exist path', assert => {
  assert.plan(1)

  const state = new Objectspy(initial_state)
  assert.deepEqual(state.get('__' + Math.random()), undefined)
})

test('Get nested no exist path', assert => {
  assert.plan(1)

  const state = new Objectspy(initial_state)
  assert.deepEqual(state.get('deep.deep1.test'), undefined)
})

test('Update state', assert => {
  assert.plan(1)
  const value = Math.random()
  const state = new Objectspy(initial_state)
  state.set('foo', value)
  assert.deepEqual(state.get(), Object.assign({}, initial_state , { foo: value }))
})

test('Update state by object', assert => {
  assert.plan(1)
  const value = { deep3: Math.random() }
  const state = new Objectspy(initial_state)
  state.set('deep', value)
  assert.deepEqual(state.get(), Object.assign({}, initial_state , { deep: value }))
})

test('Update nested state', assert => {
  assert.plan(1)
  const value = Math.random()
  const state = new Objectspy(initial_state)
  state.set('deep.deep1', value)

  const expected_result = Object.assign({}, initial_state)
  expected_result.deep.deep1 = value

  assert.deepEqual(state.get(), expected_result)
})

test('Update similar path', assert => {
  assert.plan(1)
  const value = Math.random()
  const state = new Objectspy(initial_state)
  state.set('deep.deep1', value)
  state.set('deep', value)

  const expected_result = Object.assign({}, initial_state)
  expected_result.deep = value

  assert.deepEqual(state.get(), expected_result)
})

test('Delete state', assert => {
  assert.plan(1)

  const state = new Objectspy(initial_state)
  state.del('foo')

  const expected_result = Object.assign({}, initial_state)
  delete(expected_result.foo)

  assert.deepEqual(state.get(), expected_result)
})

test('Delete nested state', assert => {

  assert.plan(1)

  const state = new Objectspy(initial_state)
  state.del('deep.deep1')

  const expected_result = Object.assign({}, initial_state)
  delete(expected_result.deep.deep1)

  assert.deepEqual(state.get(), expected_result)
})

test('Delete all', assert => {
  assert.plan(2)
  const state = new Objectspy(initial_state)

  let n = 0
  const callback = () => n++
  state.on('onchange', callback)
  state.on('foo', callback)
  state.del('')
  assert.deepEqual(state.get(), {})
  setTimeout(() => assert.equal(n, 2), 1)
})

test('Add onchange callback', assert => {
  assert.plan(2)

  const state = new Objectspy(initial_state)

  let n = 0
  const handler = () => n++
  state.on('', handler)
  state.on('*', handler)
  state.on('onchange', handler)

  state.set('foo', Math.random())
  assert.equal(n, 0)

  // async call && requestAnimationFrame
  setTimeout(() => {
    state.set('', { foo: Math.random() })
    setTimeout(() => assert.equal(n, 2 * 3), 1) // only async callback execeution
  }, 1)
})

test('Remove onchange callback', assert => {
  assert.plan(1)
  const state = new Objectspy(initial_state)

  let n = 0
  const callback = () => n++
  state.on('onchange', callback)

  state.set('foo', Math.random())

  setTimeout(() => {
    state.off('onchange', callback)
    state.set('foo', Math.random())
    setTimeout(() => assert.equal(n, 1), 1)
  }, 1)
})

test('Update w/o run onchange callback (silent mode)', assert => {
  assert.plan(1)
  const state = new Objectspy(initial_state)
  let n = 0
  state.on('onchange', () => n++)
  state.set('foo', Math.random(), true)
  setTimeout(() => assert.equal(n, 0), 20)
})

test('Add path callback', assert => {
  assert.plan(1)
  const state = new Objectspy(initial_state)

  let n = 0
  state.on('foo', () => n++)

  state.set('foo', Math.random())
  state.set('bar', Math.random())
  setTimeout(() => assert.equal(n, 1), 1)
})

test('Add nested path callback', assert => {
  assert.plan(1)
  const state = new Objectspy(initial_state)

  let n = 0
  state.on('deep.deep1', () => n++)

  state.set('deep.deep1', Math.random())
  state.set('deep.deep2', Math.random())

  setTimeout(() => assert.equal(n, 1), 1)
})

test('Prevent callback on set similar value', assert => {
  assert.plan(2)
  const state = new Objectspy(initial_state)

  let n = 0
  const val = Math.random()

  state.on('foo', () => n++)
  state.set('foo', val)

  setTimeout(() => {
    assert.equal(n, 1)
    state.set('foo', val)
    setTimeout(() => assert.equal(n, 1), 1)
  }, 1)
})

test('Add similar callbacks', assert => {
  assert.plan(1)
  const state = new Objectspy(initial_state)

  let n = 0
  state.on('deep', () => n++)
  state.on('deep.deep1', () => n++)
  state.set('deep.deep1', Math.random())

  setTimeout(() => assert.equal(n, 2), 1)
})

test('Add null callback', assert => {
  assert.plan(1)
  const state = new Objectspy(initial_state)

  let n = 0
  state.on(null, () => n++)

  state.set('foo', 2)
  state.set('bar', 2)
  state.set(null, 3)
  state.set(null, {foo: 3})

  setTimeout(() => assert.equal(n, 0), 1)
})

test('Remove path callback', assert => {
  assert.plan(1)
  const state = new Objectspy(initial_state)
  let n = 0
  const callback = () => n++
  state.on('foo', callback)
  state.set('foo', Math.random())

  setTimeout(() => {
    state.off('foo', callback)
    state.set('foo', Math.random())
    setTimeout(() => assert.equal(n, 1), 1)
  }, 1)
})

test('Update w/o call path callback (silent mode)', assert => {
  assert.plan(1)
  const state = new Objectspy(initial_state)
  let n = 0

  state.on('foo', () => n++)
  state.set('foo', Math.random(), true)
  setTimeout(() => assert.equal(n, 0), 1)
})

test('GC', assert => {
  assert.plan(1)

  const state = new Objectspy(initial_state, { gc: true, gc_interval: 0.01 })
  state.on('foo', () => {})
  state.on('deep.deep1', () => {})

  setTimeout(() => {
    assert.deepEqual(state.get(), { foo: initial_state.foo, deep: { deep1: initial_state.deep.deep1 } })
    state.destructor()
  }, 10)
})
<|endoftext|>


<commit_before>'use strict';

require('./support/bootstrap');

const _                  = require('lodash');
const Promise            = require('pinkie-promise');
const CacheableOperation = require('./../lib/CacheableOperation');
const Cache              = require('./../lib/Cache');
const sinon              = require('sinon');
const pify               = require('pify');
const fs                 = require('fs');
const fsExtra            = require('fs-extra');
const del                = require('del');

require('sinon-as-promised');

const copy = function () {
    return pify(fsExtra.copy)('test/sample/assets/foo.txt', 'test/sample/build/foo.txt');
};

const uncopy = function () {
    return del(['test/sample/build']);
};

const modify = function () {
    return pify(fsExtra.copy)('test/sample/assets/foo.txt', 'test/sample/assets/foo2.txt');
};

const resetWorkspace = function () {
    return del(['test/sample/build', '.johnny', 'test/sample/assets/foo2.txt']);
};

const defaultOptions = {
    action: 'op',
    input:  ['test/sample/assets/*'],
    output: ['test/sample/build/*'],
    ttl:    60000
};

var defaultOptionBuilder = () => _.assign({}, defaultOptions, {
    onStore:   sinon.spy(),
    onRestore: sinon.spy()
});

describe('Cache', () => {

    let cache;

    beforeEach(()=> {
        cache = new Cache();
    });

    afterEach(()=> {
        return resetWorkspace();
    });

    describe('.doCached', ()=> {

        _.forEach({

            'input and output with wildcard': () => defaultOptionBuilder(),

            'input and output as folder names (and strings)': () => _.assign({}, defaultOptionBuilder(), {
                input:  'test/sample/assets',
                output: 'test/sample/build'
            }),

            'no input given': () => _.omit(defaultOptionBuilder(), 'input')

        }, (optionBuilder, description) => {

            describe(description, () => {

                let defaultOptions;

                beforeEach(() => {
                    defaultOptions = optionBuilder();
                });

                it('should correctly invoke the callbacks', () => {
                    let run = sinon.spy();
                    return cache.doCached(run, defaultOptions)
                        .then(() => {
                            defaultOptions.onStore.should.have.been.calledOnce;
                            defaultOptions.onRestore.should.not.have.been.called;
                            return uncopy();
                        })
                        .then(() => cache.doCached(run, defaultOptions))
                        .then(() => {
                            defaultOptions.onStore.should.have.been.calledOnce;
                            defaultOptions.onRestore.should.have.been.calledOnce;
                        });
                });

                it('should not run the callable a second time if the input files stayed the same', () => {
                    let run = sinon.spy();
                    return cache.doCached(run, defaultOptions)
                        .then(() => uncopy())
                        .then(() => cache.doCached(run, defaultOptions))
                        .then(() => run.should.have.been.calledOnce);
                });

                if (optionBuilder().input)
                    it('should run the callable twice if the input files were modified', () => {
                        let run = sinon.spy(copy);
                        return cache.doCached(run, defaultOptions)
                            .then(() => modify())
                            .then(() => cache.doCached(run, defaultOptions))
                            .then(() => run.should.have.been.calledTwice);
                    });

                it('should run the callable twice if the output argument is different', () => {
                    let run = sinon.spy(copy);
                    return cache.doCached(run, defaultOptions)
                        .then(() => cache.doCached(run, _.assign(defaultOptions, {
                            output: ['test/sample/build/*.txt']
                        })))
                        .then(() => run.should.have.been.calledTwice);
                });

                it('should run the callable twice if the cached version has expired', () => {
                    let run     = sinon.spy(copy);
                    let options = _.assign({}, defaultOptions, {'ttl': -1});
                    return cache.doCached(run, options)
                        .then(() => uncopy())
                        .then(() => cache.doCached(run, options))
                        .then(() => run.should.have.been.calledTwice);
                });

                it('should restore the operation from cache the second time if the input files stayed the same', () => {
                    return cache.doCached(copy, defaultOptions)
                        .then(() => uncopy())
                        .then(() => cache.doCached(copy, defaultOptions))
                        .then(() => pify(fs.readFile)('test/sample/build/foo.txt', {encoding: 'utf8'}))
                        .then((data) => {
                            data.should.equal('bar');
                        });
                });

                it('should work with the compress option set to true', () => {
                    let options = _.assign({}, defaultOptions, {'compress': true});
                    return cache.doCached(copy, options)
                        .then(() => uncopy())
                        .then(() => cache.doCached(copy, options))
                        .then(() => pify(fs.readFile)('test/sample/build/foo.txt', {encoding: 'utf8'}))
                        .then((data) => {
                            data.should.equal('bar');
                        });
                });

                it('should generate a file at the location corresponding to the cached result', () => {
                    let run = sinon.spy(copy);
                    return cache.doCached(run, defaultOptions)
                        .then(cachedResult => pify(fs.access)(cache.getStorageLocation(cachedResult)));
                });

                it('should fallback gracefully if the cached result has no corresponding file', () => {
                    let run = sinon.spy(copy);
                    return cache.doCached(run, defaultOptions)
                        .then(cachedResult => del(cache.getStorageLocation(cachedResult)))
                        .then(() => cache.doCached(run, defaultOptions))
                        .then(() => run.should.have.been.calledTwice);
                });
            });

        });
    });

    describe('assignFileSize', () => {
        it('should assign the filesize to the cachedResult object', () => {
            return cache.doCached(sinon.spy(), defaultOptions)
                .then(result => {
                    result.fileSize.should.be.a('number');
                    result.fileSize.should.be.above(0);
                });
        });
    });

    describe('.sync', () => {
        it('should delete the files of expired cache entries', () => {
            let expiresLater       = defaultOptions;
            let expiresImmediately = _.assign({}, defaultOptions, {'ttl': -1, 'action': 'op2'});
            let resultExpiresImmediately, resultExpiresLater;
            return cache.doCached(copy, expiresImmediately)
                .then(r => resultExpiresImmediately = r)
                .then(() => cache.doCached(copy, expiresLater))
                .then(r => resultExpiresLater = r)
                .then(() => cache.sync())
                .then(() => Promise.all([
                    pify(fs.access)(cache.getStorageLocation(resultExpiresImmediately)).should.be.rejected,
                    pify(fs.access)(cache.getStorageLocation(resultExpiresLater)).should.be.resolved
                ]));
        });
    });

    describe('.prepareResult', () => {
        it('should prevent hash collisions', () => {
            let result1, result2;
            const fakeOp = () => {
                let fakeOp         = new CacheableOperation(() => Promise.resolve(), defaultOptions);
                fakeOp.getFileHash = () => Promise.resolve('bar');
                return fakeOp;
            };
            return cache.run(fakeOp())
                .then(result => {
                    result1 = result;
                    return cache.prepareResult(fakeOp());
                })
                .then(result => {
                    result2 = result;
                    result1.fileName.should.not.eql(result2.fileName);
                });
        });
    });
});<commit_msg>Add test for onRun callback<commit_after>'use strict';

require('./support/bootstrap');

const _                  = require('lodash');
const Promise            = require('pinkie-promise');
const CacheableOperation = require('./../lib/CacheableOperation');
const Cache              = require('./../lib/Cache');
const sinon              = require('sinon');
const pify               = require('pify');
const fs                 = require('fs');
const fsExtra            = require('fs-extra');
const del                = require('del');

require('sinon-as-promised');

const copy = function () {
    return pify(fsExtra.copy)('test/sample/assets/foo.txt', 'test/sample/build/foo.txt');
};

const uncopy = function () {
    return del(['test/sample/build']);
};

const modify = function () {
    return pify(fsExtra.copy)('test/sample/assets/foo.txt', 'test/sample/assets/foo2.txt');
};

const resetWorkspace = function () {
    return del(['test/sample/build', '.johnny', 'test/sample/assets/foo2.txt']);
};

const defaultOptions = {
    action: 'op',
    input:  ['test/sample/assets/*'],
    output: ['test/sample/build/*'],
    ttl:    60000
};

var defaultOptionBuilder = () => _.assign({}, defaultOptions, {
    onRun:     sinon.spy(),
    onStore:   sinon.spy(),
    onRestore: sinon.spy()
});

describe('Cache', () => {

    let cache;

    beforeEach(()=> {
        cache = new Cache();
    });

    afterEach(()=> {
        return resetWorkspace();
    });

    describe('.doCached', ()=> {

        _.forEach({

            'input and output with wildcard': () => defaultOptionBuilder(),

            'input and output as folder names (and strings)': () => _.assign({}, defaultOptionBuilder(), {
                input:  'test/sample/assets',
                output: 'test/sample/build'
            }),

            'no input given': () => _.omit(defaultOptionBuilder(), 'input')

        }, (optionBuilder, description) => {

            describe(description, () => {

                let defaultOptions;

                beforeEach(() => {
                    defaultOptions = optionBuilder();
                });

                it('should correctly invoke the callbacks', () => {
                    let run = sinon.spy();
                    return cache.doCached(run, defaultOptions)
                        .then(() => {
                            defaultOptions.onStore.should.have.been.calledAfter(run);
                            defaultOptions.onRun.should.have.been.calledBefore(run);
                            defaultOptions.onRestore.should.not.have.been.called;
                            return uncopy();
                        })
                        .then(() => cache.doCached(run, defaultOptions))
                        .then(() => {
                            defaultOptions.onStore.should.have.been.calledOnce;
                            defaultOptions.onRun.should.have.been.calledOnce;
                            defaultOptions.onRestore.should.have.been.calledOnce;
                        });
                });

                it('should not run the callable a second time if the input files stayed the same', () => {
                    let run = sinon.spy();
                    return cache.doCached(run, defaultOptions)
                        .then(() => uncopy())
                        .then(() => cache.doCached(run, defaultOptions))
                        .then(() => run.should.have.been.calledOnce);
                });

                if (optionBuilder().input)
                    it('should run the callable twice if the input files were modified', () => {
                        let run = sinon.spy(copy);
                        return cache.doCached(run, defaultOptions)
                            .then(() => modify())
                            .then(() => cache.doCached(run, defaultOptions))
                            .then(() => run.should.have.been.calledTwice);
                    });

                it('should run the callable twice if the output argument is different', () => {
                    let run = sinon.spy(copy);
                    return cache.doCached(run, defaultOptions)
                        .then(() => cache.doCached(run, _.assign(defaultOptions, {
                            output: ['test/sample/build/*.txt']
                        })))
                        .then(() => run.should.have.been.calledTwice);
                });

                it('should run the callable twice if the cached version has expired', () => {
                    let run     = sinon.spy(copy);
                    let options = _.assign({}, defaultOptions, {'ttl': -1});
                    return cache.doCached(run, options)
                        .then(() => uncopy())
                        .then(() => cache.doCached(run, options))
                        .then(() => run.should.have.been.calledTwice);
                });

                it('should restore the operation from cache the second time if the input files stayed the same', () => {
                    return cache.doCached(copy, defaultOptions)
                        .then(() => uncopy())
                        .then(() => cache.doCached(copy, defaultOptions))
                        .then(() => pify(fs.readFile)('test/sample/build/foo.txt', {encoding: 'utf8'}))
                        .then((data) => {
                            data.should.equal('bar');
                        });
                });

                it('should work with the compress option set to true', () => {
                    let options = _.assign({}, defaultOptions, {'compress': true});
                    return cache.doCached(copy, options)
                        .then(() => uncopy())
                        .then(() => cache.doCached(copy, options))
                        .then(() => pify(fs.readFile)('test/sample/build/foo.txt', {encoding: 'utf8'}))
                        .then((data) => {
                            data.should.equal('bar');
                        });
                });

                it('should generate a file at the location corresponding to the cached result', () => {
                    let run = sinon.spy(copy);
                    return cache.doCached(run, defaultOptions)
                        .then(cachedResult => pify(fs.access)(cache.getStorageLocation(cachedResult)));
                });

                it('should fallback gracefully if the cached result has no corresponding file', () => {
                    let run = sinon.spy(copy);
                    return cache.doCached(run, defaultOptions)
                        .then(cachedResult => del(cache.getStorageLocation(cachedResult)))
                        .then(() => cache.doCached(run, defaultOptions))
                        .then(() => run.should.have.been.calledTwice);
                });
            });

        });
    });

    describe('assignFileSize', () => {
        it('should assign the filesize to the cachedResult object', () => {
            return cache.doCached(sinon.spy(), defaultOptions)
                .then(result => {
                    result.fileSize.should.be.a('number');
                    result.fileSize.should.be.above(0);
                });
        });
    });

    describe('.sync', () => {
        it('should delete the files of expired cache entries', () => {
            let expiresLater       = defaultOptions;
            let expiresImmediately = _.assign({}, defaultOptions, {'ttl': -1, 'action': 'op2'});
            let resultExpiresImmediately, resultExpiresLater;
            return cache.doCached(copy, expiresImmediately)
                .then(r => resultExpiresImmediately = r)
                .then(() => cache.doCached(copy, expiresLater))
                .then(r => resultExpiresLater = r)
                .then(() => cache.sync())
                .then(() => Promise.all([
                    pify(fs.access)(cache.getStorageLocation(resultExpiresImmediately)).should.be.rejected,
                    pify(fs.access)(cache.getStorageLocation(resultExpiresLater)).should.be.resolved
                ]));
        });
    });

    describe('.prepareResult', () => {
        it('should prevent hash collisions', () => {
            let result1, result2;
            const fakeOp = () => {
                let fakeOp         = new CacheableOperation(() => Promise.resolve(), defaultOptions);
                fakeOp.getFileHash = () => Promise.resolve('bar');
                return fakeOp;
            };
            return cache.run(fakeOp())
                .then(result => {
                    result1 = result;
                    return cache.prepareResult(fakeOp());
                })
                .then(result => {
                    result2 = result;
                    result1.fileName.should.not.eql(result2.fileName);
                });
        });
    });
});<|endoftext|>


<commit_before>/* global describe, it, before, beforeEach, after, afterEach */

'use strict';

var chai = require('chai');
chai.use(require('chai-string'));

var should = chai.should();

var metrics = require('../lib/metrics');

describe('Metric', function() {
    it('should set its initial state correctly', function() {
        var m = new metrics.Metric('the.key', ['tag1'], 'myhost');
        m.key.should.equal('the.key');
        m.tags.should.deep.equal(['tag1']);
        m.host.should.equal('myhost');
    });

    it('should update the timestamp when a data point is added', function() {
        var m = new metrics.Metric();
        m.updateTimestamp(123);
        m.timestamp.should.exist();
    });
});

describe('Gauge', function() {
    it('should extend Metric', function() {
        var g = new metrics.Gauge();
        g.updateTimestamp.should.exist();
    });

    it('should flush correctly', function() {
        var g = new metrics.Gauge('the.key', ['mytag'], 'myhost');
        g.addPoint(1);
        var f = g.flush();
        f.should.have.length(1);
        f[0].should.have.deep.property('metric', 'the.key');
        f[0].should.have.deep.property('tags[0]', 'mytag');
        f[0].should.have.deep.property('host', 'myhost');
        f[0].should.have.deep.property('points[0][0]', g.timestamp);
        f[0].should.have.deep.property('points[0][1]', 1);
    });
});

describe('Histogram', function() {
    it('should extend Metric', function() {
        var h = new metrics.Histogram();
        h.updateTimestamp.should.exist();
    });

    it('should report the min and max of all values', function() {
        var h = new metrics.Histogram('hist');
        var f = h.flush();

        f.should.have.deep.property('[0].metric', 'hist.min');
        f.should.have.deep.property('[0].points[0][1]', Infinity);
        f.should.have.deep.property('[1].metric', 'hist.max');
        f.should.have.deep.property('[1].points[0][1]', -Infinity);

        h.addPoint(23);

        f = h.flush();
        f.should.have.deep.property('[0].metric', 'hist.min');
        f.should.have.deep.property('[0].points[0][1]', 23);
        f.should.have.deep.property('[1].metric', 'hist.max');
        f.should.have.deep.property('[1].points[0][1]', 23);
    });

    it('should report a sum of all values', function() {
        var h = new metrics.Histogram('hist');
        var f = h.flush();

        f.should.have.deep.property('[2].metric', 'hist.sum');
        f.should.have.deep.property('[2].points[0][1]', 0);

        h.addPoint(2);
        h.addPoint(3);

        f = h.flush();
        f.should.have.deep.property('[2].metric', 'hist.sum');
        f.should.have.deep.property('[2].points[0][1]', 5);
    });

    it('should report the number of samples (count)', function() {
        var h = new metrics.Histogram('hist');
        var f = h.flush();

        f.should.have.deep.property('[3].metric', 'hist.count');
        f.should.have.deep.property('[3].points[0][1]', 0);

        h.addPoint(2);
        h.addPoint(3);

        f = h.flush();
        f.should.have.deep.property('[3].metric', 'hist.count');
        f.should.have.deep.property('[3].points[0][1]', 2);
    });

    it('should report the average', function() {
        var h = new metrics.Histogram('hist');
        var f = h.flush();

        f.should.have.deep.property('[4].metric', 'hist.avg');
        f.should.have.deep.property('[4].points[0][1]', 0);

        h.addPoint(2);
        h.addPoint(3);

        f = h.flush();
        f.should.have.deep.property('[4].metric', 'hist.avg');
        f.should.have.deep.property('[4].points[0][1]', 2.5);
    });

    it('should report the correct percentiles', function() {
        var h = new metrics.Histogram('hist');
        h.addPoint(1);
        var f = h.flush();

        f.should.have.deep.property('[5].metric', 'hist.75percentile');
        f.should.have.deep.property('[5].points[0][1]', 1);
        f.should.have.deep.property('[6].metric', 'hist.85percentile');
        f.should.have.deep.property('[6].points[0][1]', 1);
        f.should.have.deep.property('[7].metric', 'hist.95percentile');
        f.should.have.deep.property('[7].points[0][1]', 1);
        f.should.have.deep.property('[8].metric', 'hist.99percentile');
        f.should.have.deep.property('[8].points[0][1]', 1);

        // Create 100 samples from [1..100] so we can
        // verify the calculated percentiles.
        for (var i = 2; i <= 100; i++) {
            h.addPoint(i);
        }
        f = h.flush();

        f.should.have.deep.property('[5].metric', 'hist.75percentile');
        f.should.have.deep.property('[5].points[0][1]', 75);
        f.should.have.deep.property('[6].metric', 'hist.85percentile');
        f.should.have.deep.property('[6].points[0][1]', 85);
        f.should.have.deep.property('[7].metric', 'hist.95percentile');
        f.should.have.deep.property('[7].points[0][1]', 95);
        f.should.have.deep.property('[8].metric', 'hist.99percentile');
        f.should.have.deep.property('[8].points[0][1]', 99);
    });
});

describe('Aggregator', function() {
    it('should flush correctly when empty', function() {
        var agg = new metrics.Aggregator();
        agg.flush().should.have.length(0);
    });

    it('should flush a single metric correctly', function() {
        var agg = new metrics.Aggregator();
        agg.addPoint(metrics.Gauge, 'mykey', 23, ['mytag'], 'myhost');
        agg.flush().should.have.length(1);
    });

    it('should flush multiple metrics correctly', function() {
        var agg = new metrics.Aggregator();
        agg.addPoint(metrics.Gauge, 'mykey', 23, ['mytag'], 'myhost');
        agg.addPoint(metrics.Gauge, 'mykey2', 42, ['mytag'], 'myhost');
        agg.flush().should.have.length(2);
    });

    it('should clear the buffer after flushing', function() {
        var agg = new metrics.Aggregator();
        agg.addPoint(metrics.Gauge, 'mykey', 23, ['mytag'], 'myhost');
        agg.flush().should.have.length(1);
        agg.flush().should.have.length(0);
    });

    it('should update an existing metric correctly', function() {
        var agg = new metrics.Aggregator();
        agg.addPoint(metrics.Counter, 'test.mykey', 2, ['mytag'], 'myhost');
        agg.addPoint(metrics.Counter, 'test.mykey', 3, ['mytag'], 'myhost');
        var f = agg.flush();
        f.should.have.length(1);
        f[0].should.have.deep.property('points[0][1]', 5);
        // console.log(JSON.stringify(f));
        // metrics.sendToDataDog('', f,
        //   function() {console.log('onsuccess');},
        //   function() {console.log('onerror', arguments);});
    });
});

describe('BufferedMetricsLogger', function() {
    it('should have a gauge() metric', function() {
        var l = new metrics.BufferedMetricsLogger({});
        l.gauge('test.gauge', 23);
    });

    it('should have a counter() metric', function() {
        var l = new metrics.BufferedMetricsLogger({});
        l.gauge('test.counter', 23);
    });

    it('should have a histogram() metric', function() {
        var l = new metrics.BufferedMetricsLogger({});
        l.gauge('test.histogram', 23);
    });

    it('setDefaultHost should work', function() {
        var l = new metrics.BufferedMetricsLogger({});
        l.setDefaultHost('myhost');
        l.aggregator = {
            addPoint: function(Type, key, value, tags, host) {
                host.should.equal('myhost');
            }
        };
        l.gauge('test.counter', 23);
        l.counter('test.gauge', 23);
        l.histogram('test.histogram', 23);
    });

    it('setDefaultPrefix should work', function() {
        var l = new metrics.BufferedMetricsLogger({});
        l.setDefaultPrefix('mynamespace.');
        l.aggregator = {
            addPoint: function(Type, key, value, tags, host) {
                key.should.startsWith('mynamespace.test.');
            }
        };
        l.gauge('test.counter', 23);
        l.counter('test.gauge', 23);
        l.histogram('test.histogram', 23);
    });
});
<commit_msg>Cleanups<commit_after>/* global describe, it, before, beforeEach, after, afterEach */

'use strict';

var chai = require('chai');
chai.use(require('chai-string'));

var should = chai.should();

var metrics = require('../lib/metrics');

describe('Metric', function() {
    it('should set its initial state correctly', function() {
        var m = new metrics.Metric('the.key', ['tag1'], 'myhost');
        m.key.should.equal('the.key');
        m.tags.should.deep.equal(['tag1']);
        m.host.should.equal('myhost');
    });

    it('should update the timestamp when a data point is added', function() {
        var m = new metrics.Metric();
        m.updateTimestamp(123);
        m.timestamp.should.exist();
    });
});

describe('Gauge', function() {
    it('should extend Metric', function() {
        var g = new metrics.Gauge();
        g.updateTimestamp.should.exist();
    });

    it('should flush correctly', function() {
        var g = new metrics.Gauge('the.key', ['mytag'], 'myhost');
        g.addPoint(1);
        var f = g.flush();
        f.should.have.length(1);
        f[0].should.have.deep.property('metric', 'the.key');
        f[0].should.have.deep.property('tags[0]', 'mytag');
        f[0].should.have.deep.property('host', 'myhost');
        f[0].should.have.deep.property('points[0][0]', g.timestamp);
        f[0].should.have.deep.property('points[0][1]', 1);
    });
});

describe('Histogram', function() {
    it('should extend Metric', function() {
        var h = new metrics.Histogram();
        h.updateTimestamp.should.exist();
    });

    it('should report the min and max of all values', function() {
        var h = new metrics.Histogram('hist');
        var f = h.flush();

        f.should.have.deep.property('[0].metric', 'hist.min');
        f.should.have.deep.property('[0].points[0][1]', Infinity);
        f.should.have.deep.property('[1].metric', 'hist.max');
        f.should.have.deep.property('[1].points[0][1]', -Infinity);

        h.addPoint(23);

        f = h.flush();
        f.should.have.deep.property('[0].metric', 'hist.min');
        f.should.have.deep.property('[0].points[0][1]', 23);
        f.should.have.deep.property('[1].metric', 'hist.max');
        f.should.have.deep.property('[1].points[0][1]', 23);
    });

    it('should report a sum of all values', function() {
        var h = new metrics.Histogram('hist');
        var f = h.flush();

        f.should.have.deep.property('[2].metric', 'hist.sum');
        f.should.have.deep.property('[2].points[0][1]', 0);

        h.addPoint(2);
        h.addPoint(3);

        f = h.flush();
        f.should.have.deep.property('[2].metric', 'hist.sum');
        f.should.have.deep.property('[2].points[0][1]', 5);
    });

    it('should report the number of samples (count)', function() {
        var h = new metrics.Histogram('hist');
        var f = h.flush();

        f.should.have.deep.property('[3].metric', 'hist.count');
        f.should.have.deep.property('[3].points[0][1]', 0);

        h.addPoint(2);
        h.addPoint(3);

        f = h.flush();
        f.should.have.deep.property('[3].metric', 'hist.count');
        f.should.have.deep.property('[3].points[0][1]', 2);
    });

    it('should report the average', function() {
        var h = new metrics.Histogram('hist');
        var f = h.flush();

        f.should.have.deep.property('[4].metric', 'hist.avg');
        f.should.have.deep.property('[4].points[0][1]', 0);

        h.addPoint(2);
        h.addPoint(3);

        f = h.flush();
        f.should.have.deep.property('[4].metric', 'hist.avg');
        f.should.have.deep.property('[4].points[0][1]', 2.5);
    });

    it('should report the correct percentiles', function() {
        var h = new metrics.Histogram('hist');
        h.addPoint(1);
        var f = h.flush();

        f.should.have.deep.property('[5].metric', 'hist.75percentile');
        f.should.have.deep.property('[5].points[0][1]', 1);
        f.should.have.deep.property('[6].metric', 'hist.85percentile');
        f.should.have.deep.property('[6].points[0][1]', 1);
        f.should.have.deep.property('[7].metric', 'hist.95percentile');
        f.should.have.deep.property('[7].points[0][1]', 1);
        f.should.have.deep.property('[8].metric', 'hist.99percentile');
        f.should.have.deep.property('[8].points[0][1]', 1);

        // Create 100 samples from [1..100] so we can
        // verify the calculated percentiles.
        for (var i = 2; i <= 100; i++) {
            h.addPoint(i);
        }
        f = h.flush();

        f.should.have.deep.property('[5].metric', 'hist.75percentile');
        f.should.have.deep.property('[5].points[0][1]', 75);
        f.should.have.deep.property('[6].metric', 'hist.85percentile');
        f.should.have.deep.property('[6].points[0][1]', 85);
        f.should.have.deep.property('[7].metric', 'hist.95percentile');
        f.should.have.deep.property('[7].points[0][1]', 95);
        f.should.have.deep.property('[8].metric', 'hist.99percentile');
        f.should.have.deep.property('[8].points[0][1]', 99);
    });
});

describe('Aggregator', function() {
    it('should flush correctly when empty', function() {
        var agg = new metrics.Aggregator();
        agg.flush().should.have.length(0);
    });

    it('should flush a single metric correctly', function() {
        var agg = new metrics.Aggregator();
        agg.addPoint(metrics.Gauge, 'mykey', 23, ['mytag'], 'myhost');
        agg.flush().should.have.length(1);
    });

    it('should flush multiple metrics correctly', function() {
        var agg = new metrics.Aggregator();
        agg.addPoint(metrics.Gauge, 'mykey', 23, ['mytag'], 'myhost');
        agg.addPoint(metrics.Gauge, 'mykey2', 42, ['mytag'], 'myhost');
        agg.flush().should.have.length(2);
    });

    it('should clear the buffer after flushing', function() {
        var agg = new metrics.Aggregator();
        agg.addPoint(metrics.Gauge, 'mykey', 23, ['mytag'], 'myhost');
        agg.flush().should.have.length(1);
        agg.flush().should.have.length(0);
    });

    it('should update an existing metric correctly', function() {
        var agg = new metrics.Aggregator();
        agg.addPoint(metrics.Counter, 'test.mykey', 2, ['mytag'], 'myhost');
        agg.addPoint(metrics.Counter, 'test.mykey', 3, ['mytag'], 'myhost');
        var f = agg.flush();
        f.should.have.length(1);
        f[0].should.have.deep.property('points[0][1]', 5);
        // console.log(JSON.stringify(f));
        // metrics.sendToDataDog('', f,
        //   function() {console.log('onsuccess');},
        //   function() {console.log('onerror', arguments);});
    });
});

describe('BufferedMetricsLogger', function() {
    it('should have a gauge() metric', function() {
        var l = new metrics.BufferedMetricsLogger({});
        l.gauge('test.gauge', 23);
    });

    it('should have a counter() metric', function() {
        var l = new metrics.BufferedMetricsLogger({});
        l.gauge('test.counter', 23);
    });

    it('should have a histogram() metric', function() {
        var l = new metrics.BufferedMetricsLogger({});
        l.gauge('test.histogram', 23);
    });

    it('should allow setting a default host', function() {
        var l = new metrics.BufferedMetricsLogger({});
        l.setDefaultHost('myhost');
        l.aggregator = {
            addPoint: function(Type, key, value, tags, host) {
                host.should.equal('myhost');
            }
        };
        l.gauge('test.counter', 23);
        l.counter('test.gauge', 23);
        l.histogram('test.histogram', 23);
    });

    it('should allow setting a default key prefix', function() {
        var l = new metrics.BufferedMetricsLogger({});
        l.setDefaultPrefix('mynamespace.');
        l.aggregator = {
            addPoint: function(Type, key, value, tags, host) {
                key.should.startsWith('mynamespace.test.');
            }
        };
        l.gauge('test.counter', 23);
        l.counter('test.gauge', 23);
        l.histogram('test.histogram', 23);
    });
});
<|endoftext|>


<commit_before>'use strict';

(() => {
  // include dependencies
  const unit = require('unit.js');
  const express = require('express');
  const virtual = require('../index');
  const app = express();

  app.use(virtual);

  app.get('/test', (req, res, next) => {
    res
      .status(200)
      .set('Content-Type', req.headers.accept)
      .set('X-Request-URL', req.url)
      .send();
  }); // end app.get

  // describe #virtual
  describe('#virtual', () => {
    it('should be a function', () => {
      unit
        .function(virtual);
    }); // end it

    it('should do nothing when url has no ext', (done) => {
      unit
        .httpAgent(app)
        .get('/test')
        .set('Accept', 'text/html')
        .expect(200)
        .expect('Content-Type', /^text\/html/i)
        .expect('X-Request-URL', '/test')
        .end(done);
    }); // end it

    it('should replace js ext in url with appropriate accept header', (done) => {
      unit
        .httpAgent(app)
        .get('/test.js')
        .expect(200)
        .expect('Content-Type', /^application\/javascript/i)
        .expect('X-Request-URL', '/test')
        .end(done);
    }); // end it

    it('should replace json ext in url with appropriate accept header', (done) => {
      unit
        .httpAgent(app)
        .get('/test.json')
        .expect(200)
        .expect('Content-Type', /^application\/json/i)
        .expect('X-Request-URL', '/test')
        .end(done);
    }); // end it

    it('should replace xml ext in url with appropriate accept header', (done) => {
      unit
        .httpAgent(app)
        .get('/test.xml')
        .expect(200)
        .expect('Content-Type', /^application\/xml/i)
        .expect('X-Request-URL', '/test')
        .end(done);
    }); // end it

    it('should replace html ext in url with appropriate accept header', (done) => {
      unit
        .httpAgent(app)
        .get('/test.html')
        .expect(200)
        .expect('Content-Type', /^text\/html/i)
        .expect('X-Request-URL', '/test')
        .end(done);
    }); // end it

    it('should replace txt ext in url with appropriate accept header', (done) => {
      unit
        .httpAgent(app)
        .get('/test.txt')
        .expect(200)
        .expect('Content-Type', /^text\/plain/i)
        .expect('X-Request-URL', '/test')
        .end(done);
    }); // end it

    it('should replace jpg ext in url with appropriate accept header', (done) => {
      unit
        .httpAgent(app)
        .get('/test.jpg')
        .expect(200)
        .expect('Content-Type', /^image\/jpeg/i)
        .expect('X-Request-URL', '/test')
        .end(done);
    }); // end it

    it('should replace ext in url and retain query parameters', (done) => {
      unit
        .httpAgent(app)
        .get('/test.json?q=hi&test=1')
        .expect(200)
        .expect('Content-Type', /^application\/json/i)
        .expect('X-Request-URL', '/test?q=hi&test=1')
        .end(done);
    }); // end it
  }); // end describe #virtual
})(); // end IIFE<commit_msg>remove iife from test/index.js<commit_after>'use strict';

// include dependencies
const unit = require('unit.js');
const express = require('express');
const virtual = require('../index');
const app = express();

app.use(virtual);

app.get('/test', (req, res, next) => {
  res
    .status(200)
    .set('Content-Type', req.headers.accept)
    .set('X-Request-URL', req.url)
    .send();
}); // end app.get

// describe #virtual
describe('#virtual', () => {
  it('should be a function', () => {
    unit
      .function(virtual);
  }); // end it

  it('should do nothing when url has no ext', (done) => {
    unit
      .httpAgent(app)
      .get('/test')
      .set('Accept', 'text/html')
      .expect(200)
      .expect('Content-Type', /^text\/html/i)
      .expect('X-Request-URL', '/test')
      .end(done);
  }); // end it

  it('should replace js ext in url with appropriate accept header', (done) => {
    unit
      .httpAgent(app)
      .get('/test.js')
      .expect(200)
      .expect('Content-Type', /^application\/javascript/i)
      .expect('X-Request-URL', '/test')
      .end(done);
  }); // end it

  it('should replace json ext in url with appropriate accept header', (done) => {
    unit
      .httpAgent(app)
      .get('/test.json')
      .expect(200)
      .expect('Content-Type', /^application\/json/i)
      .expect('X-Request-URL', '/test')
      .end(done);
  }); // end it

  it('should replace xml ext in url with appropriate accept header', (done) => {
    unit
      .httpAgent(app)
      .get('/test.xml')
      .expect(200)
      .expect('Content-Type', /^application\/xml/i)
      .expect('X-Request-URL', '/test')
      .end(done);
  }); // end it

  it('should replace html ext in url with appropriate accept header', (done) => {
    unit
      .httpAgent(app)
      .get('/test.html')
      .expect(200)
      .expect('Content-Type', /^text\/html/i)
      .expect('X-Request-URL', '/test')
      .end(done);
  }); // end it

  it('should replace txt ext in url with appropriate accept header', (done) => {
    unit
      .httpAgent(app)
      .get('/test.txt')
      .expect(200)
      .expect('Content-Type', /^text\/plain/i)
      .expect('X-Request-URL', '/test')
      .end(done);
  }); // end it

  it('should replace jpg ext in url with appropriate accept header', (done) => {
    unit
      .httpAgent(app)
      .get('/test.jpg')
      .expect(200)
      .expect('Content-Type', /^image\/jpeg/i)
      .expect('X-Request-URL', '/test')
      .end(done);
  }); // end it

  it('should replace ext in url and retain query parameters', (done) => {
    unit
      .httpAgent(app)
      .get('/test.json?q=hi&test=1')
      .expect(200)
      .expect('Content-Type', /^application\/json/i)
      .expect('X-Request-URL', '/test?q=hi&test=1')
      .end(done);
  }); // end it
}); // end describe #virtual<|endoftext|>


<commit_before>var moment = require('moment-timezone');

var expect = require('chai').expect;
var prettyDates = require('../src/');

describe('Pretty dates', function() {

  it('should handle AM same day', function() {
    var dates = prettyDates({
      startDate: moment('2015-02-08 09:30:00').toDate(),
      endDate: moment('2015-02-08 10:30:00').toDate(),
      timeZone: 'Europe/Berlin',
      timeFormat: '12'
    });
    expect(dates).to.equal('8 Feb 09:30 AM - 10:30 AM');
  });

  it('should handle AM on two days', function() {
    var dates = prettyDates({
      startDate: moment('2015-02-08 09:30:00').toDate(),
      endDate: moment('2015-02-09 10:30:00').toDate(),
      timeZone: 'Europe/Berlin',
      timeFormat: '12'
    });
    expect(dates).to.equal('8 - 9 Feb');
  });

  it('should handle 24 hours same day', function() {
    var dates = prettyDates({
      startDate: moment('2015-02-08 09:30:00').toDate(),
      endDate: moment('2015-02-08 10:30:00').toDate(),
      timeZone: 'Europe/Berlin',
      timeFormat: '24'
    });
    expect(dates).to.equal('8 Feb 09:30 - 10:30');
  });

  it('should handle events that end late', function() {
    var dates = prettyDates({
      startDate: moment('2015-02-08 21:00:00').toDate(),
      endDate: moment('2015-02-09 03:00:00').toDate(),
      timeZone: 'Europe/Berlin',
      timeFormat: '24'
    });
    expect(dates).to.equal('8 Feb 21:00 - 03:00');
  });

  it('should handle single day events with 24h clock', function() {
    var dates = prettyDates({
      startDate: moment('2015-02-08 21:00:00').toDate(),
      endDate: null,
      timeZone: 'Europe/Berlin',
      timeFormat: '24'
    });
    expect(dates).to.equal('8 Feb 21:00');
  });

  it('should handle single day events with 12h clock', function() {
    var dates = prettyDates({
      startDate: moment('2015-02-08 21:00:00').toDate(),
      endDate: null,
      timeZone: 'Europe/Berlin',
      timeFormat: '12'
    });
    expect(dates).to.equal('8 Feb 09:00 PM');
  });
});

<commit_msg>Add locale test<commit_after>var moment = require('moment-timezone');

var expect = require('chai').expect;
var prettyDates = require('../src/');

describe('Pretty dates', function() {

  it('should handle AM same day', function() {
    var dates = prettyDates({
      startDate: moment('2015-02-08 09:30:00').toDate(),
      endDate: moment('2015-02-08 10:30:00').toDate(),
      timeZone: 'Europe/Berlin',
      timeFormat: '12'
    });
    expect(dates).to.equal('8 Feb 09:30 AM - 10:30 AM');
  });

  it('should handle AM on two days', function() {
    var dates = prettyDates({
      startDate: moment('2015-02-08 09:30:00').toDate(),
      endDate: moment('2015-02-09 10:30:00').toDate(),
      timeZone: 'Europe/Berlin',
      timeFormat: '12'
    });
    expect(dates).to.equal('8 - 9 Feb');
  });

  it('should handle 24 hours same day', function() {
    var dates = prettyDates({
      startDate: moment('2015-02-08 09:30:00').toDate(),
      endDate: moment('2015-02-08 10:30:00').toDate(),
      timeZone: 'Europe/Berlin',
      timeFormat: '24'
    });
    expect(dates).to.equal('8 Feb 09:30 - 10:30');
  });

  it('should handle events that end late', function() {
    var dates = prettyDates({
      startDate: moment('2015-02-08 21:00:00').toDate(),
      endDate: moment('2015-02-09 03:00:00').toDate(),
      timeZone: 'Europe/Berlin',
      timeFormat: '24'
    });
    expect(dates).to.equal('8 Feb 21:00 - 03:00');
  });

  it('should handle single day events with 24h clock', function() {
    var dates = prettyDates({
      startDate: moment('2015-02-08 21:00:00').toDate(),
      endDate: null,
      timeZone: 'Europe/Berlin',
      timeFormat: '24'
    });
    expect(dates).to.equal('8 Feb 21:00');
  });

  it('should handle single day events with 12h clock', function() {
    var dates = prettyDates({
      startDate: moment('2015-02-08 21:00:00').toDate(),
      endDate: null,
      timeZone: 'Europe/Berlin',
      timeFormat: '12'
    });
    expect(dates).to.equal('8 Feb 09:00 PM');
  });

  it('should handle locales', function() {
    var dates = prettyDates({
      startDate: moment('2015-02-08 21:00:00').toDate(),
      locale: 'en'
    });
    expect(dates).to.equal('8 Feb 21:00');

    var dates = prettyDates({
      startDate: moment('2015-02-08 21:00:00').toDate(),
      locale: 'sv'
    });
    expect(dates).to.equal('8 feb 21:00');
  });
});

<|endoftext|>


<commit_before>var s3 = require('s3'),
	path = require('path'),
	fs = require('fs'),
	os = require('os'),
	assert = require('assert'),
	swintS3Upload = require('../lib');

global.swintVar.printLevel = 5;

describe('secret', function() {
	this.timeout(20000);
	var randKey = String(Math.floor(Math.random() * 10000000));

	it('Error when no callback', function() {
		assert.throws(function() {
			swintS3Upload({});
		});
	});

	it('Error when inDir doesn\'t exist', function(done) {
		swintS3Upload({
			inDir: '/this-directory-does-not-exist'
		}, function(err, res) {
			assert.notEqual(err, null);
			done();
		});
	});

	it('Simple case', function(done) {
		var credPath = path.join(process.env.HOME, '.swint', 'swint-s3upload-test.json'),
			cred;

		try {
			fs.accessSync(credPath);
			cred = JSON.parse(fs.readFileSync(credPath));
		} catch(e) {
			cred = {
				key: process.env.SWINT_S3UPLOAD_TEST_KEY,
				secret: process.env.SWINT_S3UPLOAD_TEST_SECRET,
				bucket: process.env.SWINT_S3UPLOAD_TEST_BUCKET
			};
		}

		var	client = s3.createClient({
				s3Options: {
					accessKeyId: cred.key,
					secretAccessKey: cred.secret
				}
			}),
			params = {
				localDir: path.join(os.tmpDir(), 'swint-s3upload-download'),
				s3Params: {
					Bucket: cred.bucket,
					Prefix: randKey
				}
			},
			ss = swintS3Upload({
				inDir: path.join(__dirname, '../test_case'),
				outDir: randKey,
				s3Info: {
					key: cred.key,
					secret: cred.secret,
					bucket: cred.bucket
				}
			}, function(err, res) {
				fs.mkdirSync(path.join(os.tmpDir(), 'swint-s3upload-download'));

				var downloader = client.downloadDir(params);

				downloader.on('error', function(err) {
					print(4, err);
					process.exit(-1);
				});

				downloader.on('end', function() {
					assert.deepEqual(
						fs.readFileSync(path.join(__dirname, '../test_case/common.js')),
						fs.readFileSync(path.join(os.tmpDir(), 'swint-s3upload-download/common.js'))
					);

					assert.deepEqual(
						fs.readFileSync(path.join(__dirname, '../test_case/common.css')),
						fs.readFileSync(path.join(os.tmpDir(), 'swint-s3upload-download/common.css'))
					);

					assert.deepEqual(
						fs.readFileSync(path.join(__dirname, '../test_case/img/flags.png')),
						fs.readFileSync(path.join(os.tmpDir(), 'swint-s3upload-download/img/flags.png'))
					);

					assert.deepEqual(
						fs.readFileSync(path.join(__dirname, '../test_case/img/tech.svg')),
						fs.readFileSync(path.join(os.tmpDir(), 'swint-s3upload-download/img/tech.svg'))
					);

					done();
				});

			});
	});

	after(function(done) {
		var credPath = path.join(process.env.HOME, '.swint', 'swint-s3upload-test.json'),
			cred;

		try {
			fs.accessSync(credPath);
			cred = JSON.parse(fs.readFileSync(credPath));
		} catch(e) {
			cred = {
				key: process.env.SWINT_S3UPLOAD_TEST_KEY,
				secret: process.env.SWINT_S3UPLOAD_TEST_SECRET,
				bucket: process.env.SWINT_S3UPLOAD_TEST_BUCKET
			};
		}

		var client = s3.createClient({
				s3Options: {
					accessKeyId: cred.key,
					secretAccessKey: cred.secret
				}
			}),
			params = {
				localDir: path.join(os.tmpDir(), 'swint-s3upload-empty'),
				deleteRemoved: true,
				s3Params: {
					Bucket: cred.bucket,
					Prefix: randKey
				}
			};

		try {
			fs.accessSync(path.join(os.tmpDir(), 'swint-s3upload-download/.DS_Store'));
			fs.unlinkSync(path.join(os.tmpDir(), 'swint-s3upload-download/.DS_Store'));
		} catch(e) {
			;
		}
		fs.unlinkSync(path.join(os.tmpDir(), 'swint-s3upload-download/common.js'));
		fs.unlinkSync(path.join(os.tmpDir(), 'swint-s3upload-download/common.css'));
		fs.unlinkSync(path.join(os.tmpDir(), 'swint-s3upload-download/img/flags.png'));
		fs.unlinkSync(path.join(os.tmpDir(), 'swint-s3upload-download/img/tech.svg'));
		fs.rmdirSync(path.join(os.tmpDir(), 'swint-s3upload-download/img'));
		fs.rmdirSync(path.join(os.tmpDir(), 'swint-s3upload-download'));

		fs.mkdirSync(path.join(os.tmpDir(), 'swint-s3upload-empty'));

		var uploader = client.uploadDir(params);

		uploader.on('error', function(err) {
			print(4, err);
			process.exit(-1);
		});

		uploader.on('end', function() {
			fs.rmdirSync(path.join(os.tmpDir(), 'swint-s3upload-empty'));
			done();
		});
	});
});
<commit_msg>Build: Added s3 folder elimination<commit_after>var s3 = require('s3'),
	path = require('path'),
	fs = require('fs'),
	os = require('os'),
	assert = require('assert'),
	swintS3Upload = require('../lib');

global.swintVar.printLevel = 5;

describe('secret', function() {
	this.timeout(20000);
	var randKey = String(Math.floor(Math.random() * 10000000));

	it('Error when no callback', function() {
		assert.throws(function() {
			swintS3Upload({});
		});
	});

	it('Error when inDir doesn\'t exist', function(done) {
		swintS3Upload({
			inDir: '/this-directory-does-not-exist'
		}, function(err, res) {
			assert.notEqual(err, null);
			done();
		});
	});

	it('Simple case', function(done) {
		var credPath = path.join(process.env.HOME, '.swint', 'swint-s3upload-test.json'),
			cred;

		try {
			fs.accessSync(credPath);
			cred = JSON.parse(fs.readFileSync(credPath));
		} catch(e) {
			cred = {
				key: process.env.SWINT_S3UPLOAD_TEST_KEY,
				secret: process.env.SWINT_S3UPLOAD_TEST_SECRET,
				bucket: process.env.SWINT_S3UPLOAD_TEST_BUCKET
			};
		}

		var	client = s3.createClient({
				s3Options: {
					accessKeyId: cred.key,
					secretAccessKey: cred.secret
				}
			}),
			params = {
				localDir: path.join(os.tmpDir(), 'swint-s3upload-download'),
				s3Params: {
					Bucket: cred.bucket,
					Prefix: randKey
				}
			},
			ss = swintS3Upload({
				inDir: path.join(__dirname, '../test_case'),
				outDir: randKey,
				s3Info: {
					key: cred.key,
					secret: cred.secret,
					bucket: cred.bucket
				}
			}, function(err, res) {
				fs.mkdirSync(path.join(os.tmpDir(), 'swint-s3upload-download'));

				var downloader = client.downloadDir(params);

				downloader.on('error', function(err) {
					print(4, err);
					process.exit(-1);
				});

				downloader.on('end', function() {
					assert.deepEqual(
						fs.readFileSync(path.join(__dirname, '../test_case/common.js')),
						fs.readFileSync(path.join(os.tmpDir(), 'swint-s3upload-download/common.js'))
					);

					assert.deepEqual(
						fs.readFileSync(path.join(__dirname, '../test_case/common.css')),
						fs.readFileSync(path.join(os.tmpDir(), 'swint-s3upload-download/common.css'))
					);

					assert.deepEqual(
						fs.readFileSync(path.join(__dirname, '../test_case/img/flags.png')),
						fs.readFileSync(path.join(os.tmpDir(), 'swint-s3upload-download/img/flags.png'))
					);

					assert.deepEqual(
						fs.readFileSync(path.join(__dirname, '../test_case/img/tech.svg')),
						fs.readFileSync(path.join(os.tmpDir(), 'swint-s3upload-download/img/tech.svg'))
					);

					done();
				});
			});
	});

	after(function(done) {
		var credPath = path.join(process.env.HOME, '.swint', 'swint-s3upload-test.json'),
			cred;

		try {
			fs.accessSync(credPath);
			cred = JSON.parse(fs.readFileSync(credPath));
		} catch(e) {
			cred = {
				key: process.env.SWINT_S3UPLOAD_TEST_KEY,
				secret: process.env.SWINT_S3UPLOAD_TEST_SECRET,
				bucket: process.env.SWINT_S3UPLOAD_TEST_BUCKET
			};
		}

		var client = s3.createClient({
				s3Options: {
					accessKeyId: cred.key,
					secretAccessKey: cred.secret
				}
			}),
			params = {
				localDir: path.join(os.tmpDir(), 'swint-s3upload-empty'),
				deleteRemoved: true,
				s3Params: {
					Bucket: cred.bucket,
					Prefix: randKey
				}
			};

		try {
			fs.accessSync(path.join(os.tmpDir(), 'swint-s3upload-download/.DS_Store'));
			fs.unlinkSync(path.join(os.tmpDir(), 'swint-s3upload-download/.DS_Store'));
		} catch(e) {
			;
		}
		fs.unlinkSync(path.join(os.tmpDir(), 'swint-s3upload-download/common.js'));
		fs.unlinkSync(path.join(os.tmpDir(), 'swint-s3upload-download/common.css'));
		fs.unlinkSync(path.join(os.tmpDir(), 'swint-s3upload-download/img/flags.png'));
		fs.unlinkSync(path.join(os.tmpDir(), 'swint-s3upload-download/img/tech.svg'));
		fs.rmdirSync(path.join(os.tmpDir(), 'swint-s3upload-download/img'));
		fs.rmdirSync(path.join(os.tmpDir(), 'swint-s3upload-download'));

		fs.mkdirSync(path.join(os.tmpDir(), 'swint-s3upload-empty'));

		var uploader = client.uploadDir(params);

		uploader.on('error', function(err) {
			print(4, err);
			process.exit(-1);
		});

		uploader.on('end', function() {
			fs.rmdirSync(path.join(os.tmpDir(), 'swint-s3upload-empty'));

			var deleter = client.deleteDir({
				Bucket: cred.bucket,
				Prefix: randKey
			});

			deleter.on('error', function(err) {
				print(4, err);
				process.exit(-1);
			});

			deleter.on('end', function() {
				done();
			});
		});
	});
});
<|endoftext|>


<commit_before>const describe = require('mocha').describe
const it = require('mocha').it
const beforeEach = require('mocha').beforeEach
const afterEach = require('mocha').afterEach
const assert = require('chai').assert
const sinon = require('sinon')

const database = require('../lib/storage/database')
const encryption = require('../lib/storage/encryption')
const route = require('../lib/http/route')
const response = require('../lib/http/response')
const receiveHandler = require('../handlers/receive/handler')
const receiveRequest = require('../handlers/receive/request')
const encryptHandler = require('../handlers/encrypt/handler')

const eventReceiveSuccess = require('../events/receive-success.json')
const eventReceiveSuccessJson = require('../events/receive-success-json.json')
const eventReceiveBadEmail = require('../events/receive-bad-email.json')
const eventReceiveNoEmail = require('../events/receive-no-email.json')
const eventReceiveHoneypot = require('../events/receive-honeypot.json')
const eventEncryptSuccess = require('../events/encrypt-success.json')
const eventEncryptSuccessJson = require('../events/encrypt-success-json.json')

describe('receive', function () {
  var spy, stub
  beforeEach(function () {
    spy = sinon.spy(response, 'build')
    stub = sinon.stub(database, 'put').callsFake((data, callback) => callback())
  })
  afterEach(function () {
    spy.restore()
    stub.restore()
  })
  describe('success', function () {
    it('html', function () {
      responseAssert('receive-success', eventReceiveSuccess, spy)
    })
    it('json', function () {
      responseAssert('receive-success', eventReceiveSuccessJson, spy)
    })
  })
  describe('error', function () {
    it('bad email', function () {
      responseAssert('receive-bad-email', eventReceiveBadEmail, spy)
    })
    it('no email', function () {
      responseAssert('receive-no-email', eventReceiveNoEmail, spy)
    })
    it('honeypot', function () {
      responseAssert('receive-honeypot', eventReceiveHoneypot, spy)
    })
  })
})

describe('encrypt', function () {
  var spy
  beforeEach(function () {
    spy = sinon.spy(response, 'build')
  })
  afterEach(function () {
    spy.restore()
  })
  describe('success', function () {
    it('html', function () {
      responseAssert('encrypt-success', eventEncryptSuccess, spy)
    })
    it('json', function () {
      responseAssert('encrypt-success', eventEncryptSuccessJson, spy)
    })
  })
})

function responseAssert (type, event, spy) {
  let data = receiveRequest.getParams(event)
  switch (type.split('-')[0]) {
    case 'receive':
      receiveHandler.handle(event, {}, sinon.stub())
      break
    case 'encrypt':
      encryptHandler.handle(event, {}, sinon.stub())
      data['_encrypted'] = encryption.encrypt(data['_email'])
      break
    default:
      logErrorAndExit('Route not recognised')
  }
  let routeDetails = route.getRouteDetails(type, data)
  assert(spy.calledOnce)
  let result = spy.firstCall.returnValue
  assert.equal(result.statusCode, routeDetails.statusCode)
  let expectedContentType = data['_format'] === 'json' ? 'application/json' : 'text/html'
  assert.equal(result.headers['Content-Type'], expectedContentType)
  assert.include(result.body, routeDetails.message)
}

function logErrorAndExit (error) {
  console.log(error)
  process.exit(1)
}
<commit_msg>move encrypt tests and imports above require tests<commit_after>const describe = require('mocha').describe
const it = require('mocha').it
const beforeEach = require('mocha').beforeEach
const afterEach = require('mocha').afterEach
const assert = require('chai').assert
const sinon = require('sinon')

const database = require('../lib/storage/database')
const encryption = require('../lib/storage/encryption')
const route = require('../lib/http/route')
const response = require('../lib/http/response')
const encryptHandler = require('../handlers/encrypt/handler')
const receiveHandler = require('../handlers/receive/handler')
const receiveRequest = require('../handlers/receive/request')

const eventEncryptSuccess = require('../events/encrypt-success.json')
const eventEncryptSuccessJson = require('../events/encrypt-success-json.json')
const eventReceiveSuccess = require('../events/receive-success.json')
const eventReceiveSuccessJson = require('../events/receive-success-json.json')
const eventReceiveBadEmail = require('../events/receive-bad-email.json')
const eventReceiveNoEmail = require('../events/receive-no-email.json')
const eventReceiveHoneypot = require('../events/receive-honeypot.json')

describe('encrypt', function () {
  var spy
  beforeEach(function () {
    spy = sinon.spy(response, 'build')
  })
  afterEach(function () {
    spy.restore()
  })
  describe('success', function () {
    it('html', function () {
      responseAssert('encrypt-success', eventEncryptSuccess, spy)
    })
    it('json', function () {
      responseAssert('encrypt-success', eventEncryptSuccessJson, spy)
    })
  })
})

describe('receive', function () {
  var spy, stub
  beforeEach(function () {
    spy = sinon.spy(response, 'build')
    stub = sinon.stub(database, 'put').callsFake((data, callback) => callback())
  })
  afterEach(function () {
    spy.restore()
    stub.restore()
  })
  describe('success', function () {
    it('html', function () {
      responseAssert('receive-success', eventReceiveSuccess, spy)
    })
    it('json', function () {
      responseAssert('receive-success', eventReceiveSuccessJson, spy)
    })
  })
  describe('error', function () {
    it('bad email', function () {
      responseAssert('receive-bad-email', eventReceiveBadEmail, spy)
    })
    it('no email', function () {
      responseAssert('receive-no-email', eventReceiveNoEmail, spy)
    })
    it('honeypot', function () {
      responseAssert('receive-honeypot', eventReceiveHoneypot, spy)
    })
  })
})

function responseAssert (type, event, spy) {
  let data = receiveRequest.getParams(event)
  switch (type.split('-')[0]) {
    case 'receive':
      receiveHandler.handle(event, {}, sinon.stub())
      break
    case 'encrypt':
      encryptHandler.handle(event, {}, sinon.stub())
      data['_encrypted'] = encryption.encrypt(data['_email'])
      break
    default:
      logErrorAndExit('Route not recognised')
  }
  let routeDetails = route.getRouteDetails(type, data)
  assert(spy.calledOnce)
  let result = spy.firstCall.returnValue
  assert.equal(result.statusCode, routeDetails.statusCode)
  let expectedContentType = data['_format'] === 'json' ? 'application/json' : 'text/html'
  assert.equal(result.headers['Content-Type'], expectedContentType)
  assert.include(result.body, routeDetails.message)
}

function logErrorAndExit (error) {
  console.log(error)
  process.exit(1)
}
<|endoftext|>


<commit_before>var chai = require('chai'),
    sinon = require('sinon'),
    sinonChai = require('sinon-chai'),
    ws = require('ws'),
    http= require('http'),
    Websocket = require('../app'),
    expect = require('chai').expect;

chai.should();
chai.use(sinonChai);

describe('#start', function() {
    var websocket;

    afterEach(function() {
        websocket.stop();
    });

    it('config with port', function(done) {
        websocket = new Websocket({port: 8080});

        var wsInstance = new ws('ws://localhost:8080');

        wsInstance.on('open', function() {
            done();
        });

        setTimeout(function() {
            done('connection not called');
        }, 100);
    });

    it('config with server', function(done) {
       var httpServer = http.createServer().listen(8080, '127.0.0.1');

        websocket = new Websocket({server: httpServer});

        var wsInstance = new ws('ws://localhost:8080');

        wsInstance.on('open', function() {
            done();
        });

        setTimeout(function() {
            done('connection not called');
        }, 100);
    });
});

describe('#listener', function() {
    var websocket, wsInstance;

    beforeEach(function(done) {
        wsInstance = new ws('ws://localhost:8080');
        websocket = new Websocket({port: 8080});

        wsInstance.on('open', function() {
            done();
        });
    });

    afterEach(function() {
        websocket.stop();
    });

    it('register', function() {
        var echoListener = {
                default: function() {
                }
            },
            listener;

        websocket.registerListener('echo', echoListener);
        listener = websocket.getListener();

        expect(listener).not.to.be.null;
        expect(listener).to.have.property('echo');
        expect(listener.echo).to.be.equal(echoListener);
    });

    it('default callback', function(done) {
        var echoListener = {
            default: function() {
                done();
            }
        };

        websocket.registerListener('test', echoListener);

        wsInstance.send(JSON.stringify({to: 'test'}));

        setTimeout(function() {
            done('default not called');
        }, 100);
    });

    it('command callback', function(done) {
        var echoListener = {
            default: function() {
                done('wrong callback called');
            },

            test: function() {
                done();
            }
        };

        websocket.registerListener('test', echoListener);

        wsInstance.send(JSON.stringify({to: 'test', cmd: 'test'}));

        setTimeout(function() {
            done('test not called');
        }, 100);
    });

    it('parameter', function(done) {
        var echoListener = {
            default: function(socket, params, data) {
                expect(socket).not.to.be.null;

                expect(params).not.to.be.null;
                expect(params).to.be.eql([1, 2, 3]);

                expect(data).not.to.be.null;
                expect(data).to.be.eql('testdata');

                done();
            }
        };

        websocket.registerListener('test', echoListener);

        wsInstance.send(JSON.stringify({to: 'test', params: [1, 2, 3], data: 'testdata'}));

        setTimeout(function() {
            done('test not called');
        }, 100);
    });

    it('send back', function(done) {
        var echoListener = {
            default: function(socket, params, data) {
                socket.send(data);
            }
        };

        websocket.registerListener('test', echoListener);

        wsInstance.on('message', function(message) {
            expect(message).to.be.eql('testdata');

            done();
        });

        wsInstance.send(JSON.stringify({to: 'test', data: 'testdata'}));

        setTimeout(function() {
            done('callback not called');
        }, 100);
    });
});

describe('#listener', function() {
    var websocket, wsInstance1, wsInstance2;

    beforeEach(function(done) {
        websocket = new Websocket({port: 8080});
        wsInstance1 = new ws('ws://localhost:8080');

        wsInstance1.on('open', function() {
            wsInstance2 = new ws('ws://localhost:8080');

            wsInstance2.on('open', function() {
                done();
            });
        });
    });

    afterEach(function() {
        websocket.stop();
    });

    it('multiple clients', function(done) {
        wsInstance1.on('message', function(message) {
            expect(message).to.be.eql('testdata');

            wsInstance2.on('message', function(message) {
                expect(message).to.be.eql('testdata');

                done();
            });

            wsInstance2.send(JSON.stringify({to: 'test', data: message}));
        });

        wsInstance1.send(JSON.stringify({to: 'test', data: 'testdata'}));

        setTimeout(function() {
            done('callback not called');
        }, 100);
    });
});
<commit_msg>added todo<commit_after>var chai = require('chai'),
    sinonChai = require('sinon-chai'),
    ws = require('ws'),
    http= require('http'),
    Websocket = require('../app'),
    expect = require('chai').expect;

chai.should();
chai.use(sinonChai);

describe('#start', function() {
    var websocket;

    afterEach(function() {
        websocket.stop();
    });

    it('config with port', function(done) {
        websocket = new Websocket({port: 8080});

        var wsInstance = new ws('ws://localhost:8080');

        wsInstance.on('open', function() {
            done();
        });

        setTimeout(function() {
            done('connection not called');
        }, 100);
    });

    it('config with server', function(done) {
       var httpServer = http.createServer().listen(8080, '127.0.0.1');

        websocket = new Websocket({server: httpServer});

        var wsInstance = new ws('ws://localhost:8080');

        wsInstance.on('open', function() {
            done();
        });

        setTimeout(function() {
            done('connection not called');
        }, 100);
    });
});

describe('#listener', function() {
    var websocket, wsInstance;

    beforeEach(function(done) {
        wsInstance = new ws('ws://localhost:8080');
        websocket = new Websocket({port: 8080});

        wsInstance.on('open', function() {
            done();
        });
    });

    afterEach(function() {
        websocket.stop();
    });

    it('register', function() {
        var echoListener = {
                default: function() {
                }
            },
            listener;

        websocket.registerListener('echo', echoListener);
        listener = websocket.getListener();

        expect(listener).not.to.be.null;
        expect(listener).to.have.property('echo');
        expect(listener.echo).to.be.equal(echoListener);
    });

    it('default callback', function(done) {
        var echoListener = {
            default: function() {
                done();
            }
        };

        websocket.registerListener('test', echoListener);

        wsInstance.send(JSON.stringify({to: 'test'}));

        setTimeout(function() {
            done('default not called');
        }, 100);
    });

    it('command callback', function(done) {
        var echoListener = {
            default: function() {
                done('wrong callback called');
            },

            test: function() {
                done();
            }
        };

        websocket.registerListener('test', echoListener);

        wsInstance.send(JSON.stringify({to: 'test', cmd: 'test'}));

        setTimeout(function() {
            done('test not called');
        }, 100);
    });

    it('parameter', function(done) {
        var echoListener = {
            default: function(socket, params, data) {
                expect(socket).not.to.be.null;

                expect(params).not.to.be.null;
                expect(params).to.be.eql([1, 2, 3]);

                expect(data).not.to.be.null;
                expect(data).to.be.eql('testdata');

                done();
            }
        };

        websocket.registerListener('test', echoListener);

        wsInstance.send(JSON.stringify({to: 'test', params: [1, 2, 3], data: 'testdata'}));

        setTimeout(function() {
            done('test not called');
        }, 100);
    });

    it('send back', function(done) {
        var echoListener = {
            default: function(socket, params, data) {
                socket.send(data);
            }
        };

        websocket.registerListener('test', echoListener);

        wsInstance.on('message', function(message) {
            expect(message).to.be.eql('testdata');

            done();
        });

        wsInstance.send(JSON.stringify({to: 'test', data: 'testdata'}));

        setTimeout(function() {
            done('callback not called');
        }, 100);
    });
});

describe('#listener', function() {
    var websocket, wsInstance1, wsInstance2;

    beforeEach(function(done) {
        websocket = new Websocket({port: 8080});
        wsInstance1 = new ws('ws://localhost:8080');

        wsInstance1.on('open', function() {
            wsInstance2 = new ws('ws://localhost:8080');

            wsInstance2.on('open', function() {
                done();
            });
        });
    });

    afterEach(function() {
        websocket.stop();
    });

    it('multiple clients', function(done) {
        wsInstance1.on('message', function(message) {
            expect(message).to.be.eql('testdata');

            wsInstance2.on('message', function(message) {
                expect(message).to.be.eql('testdata');

                done();
            });

            wsInstance2.send(JSON.stringify({to: 'test', data: message}));
        });

        wsInstance1.send(JSON.stringify({to: 'test', data: 'testdata'}));

        setTimeout(function() {
            done('callback not called');
        }, 100);
    });
});

// TODO multiple listener
<|endoftext|>