<commit_before>describe('Core_datachange', function () {
  var id = 'testContainer';

  beforeEach(function () {
    this.$container = $('

').appendTo('body');
  });

  afterEach(function () {
    if (this.$container) {
      destroy();
      this.$container.remove();
    }
  });

  it('should call onChange callback', function () {
    var output = null;

    runs(function () {
      handsontable({
        onChange: function (changes) {
          output = changes;
        }
      });
      setDataAtCell(1, 2, "test");
    });

    waitsFor(function () {
      return (output != null)
    }, "onChange callback called", 100);

    runs(function () {
      expect(output[0][0]).toEqual(1);
      expect(output[0][1]).toEqual(2);
      expect(output[0][2]).toEqual(null);
      expect(output[0][3]).toEqual("test");
    });
  });

  it('should trigger datachange event', function () {
    var output = null;

    runs(function () {
      handsontable();
      Handsontable.PluginHooks.add("onChange", function (changes) {
        output = changes;
      });
      setDataAtCell(1, 2, "test");
    });

    waitsFor(function () {
      return (output != null)
    }, "datachange event triggered", 100);

    runs(function () {
      expect(output[0][0]).toEqual(1);
      expect(output[0][1]).toEqual(2);
      expect(output[0][2]).toEqual(null);
      expect(output[0][3]).toEqual("test");
    });
  });

  it('this.rootElement should point to handsontable rootElement', function () {
    var output = null;
    var $container = this.$container;

    runs(function () {
      handsontable({
        onChange: function () {
          output = this.rootElement[0];
        }
      });
      setDataAtCell(0, 0, "test");
    });

    waitsFor(function () {
      return (output != null)
    }, "onChange callback called", 100);

    runs(function () {
      expect(output).toEqual($container[0]);
    });
  });

  it('onChange should be triggered after data is rendered to DOM (init)', function () {
    var output = null;
    var $container = this.$container;

    runs(function () {
      handsontable({
        data: [
          ['Joe Red']
        ],
        onChange: function (changes, source) {
          if (source === 'loadData') {
            output = $container.find('table.htCore tbody td:first').html();
          }
        }
      });
    });

    waitsFor(function () {
      return (output != null)
    }, "onChange callback called", 100);

    runs(function () {
      expect(output).toEqual('Joe Red');
    });
  });

  it('onChange should be triggered after data is rendered to DOM (setDataAtCell)', function () {
    var output = null;
    var $container = this.$container;

    runs(function () {
      handsontable({
        data: [
          ['Joe Red']
        ],
        onChange: function (changes, source) {
          if (source === 'edit') {
            output = $container.find('table.htCore tbody td:first').html();
          }
        }
      });
      setDataAtCell(0, 0, 'Alice Red');
    });

    waitsFor(function () {
      return (output != null)
    }, "onChange callback called", 100);

    runs(function () {
      expect(output).toEqual('Alice Red');
    });
  });

  it('onChange event object should contain documented keys and values when triggered by edit', function () {
    var sampleData = [
      {
        col1: 'a',
        col2: 'b',
        col3: 'c'
      }
    ];
    var event = null;

    runs(function () {
      handsontable({
        data: sampleData,
        onChange: function (changes, source) {
          if ('edit' == source) {
            event = changes.shift();
          }
        }
      });
      setDataAtCell(0, 0, "test");
    });

    waitsFor(function () {
      return (event != null)
    }, "onChange callback called", 100);

    runs(function () {
      expect(event[0]).toEqual(0);
      expect(event[1]).toEqual('col1');
      expect(event[2]).toEqual('a');
      expect(event[3]).toEqual('test');
    });
  });

  it('source parameter should be `edit` when cell value is changed through editor', function () {
    var sources = [];

    handsontable({
      data: [
        ['Joe Red']
      ],
      onChange: function (changes, source) {
        sources.push(source);
      }
    });
    selectCell(0, 0);

    waitsFor(nextFrame, 'next frame', 60);

    runs(function () {
      keyDown('enter');
      document.activeElement.value = 'Ted';
      keyDown('enter');
    });

    waitsFor(nextFrame, 'next frame', 60);

    runs(function () {
      expect(sources).toEqual(['loadData', 'edit']); //loadData is always the first source
    });
  });

});<commit_msg>feature: sources in events - testcase<commit_after>describe('Core_datachange', function () {
  var id = 'testContainer';

  beforeEach(function () {
    this.$container = $('

').appendTo('body');
  });

  afterEach(function () {
    if (this.$container) {
      destroy();
      this.$container.remove();
    }
  });

  it('should call onChange callback', function () {
    var output = null;

    runs(function () {
      handsontable({
        onChange: function (changes) {
          output = changes;
        }
      });
      setDataAtCell(1, 2, "test");
    });

    waitsFor(function () {
      return (output != null)
    }, "onChange callback called", 100);

    runs(function () {
      expect(output[0][0]).toEqual(1);
      expect(output[0][1]).toEqual(2);
      expect(output[0][2]).toEqual(null);
      expect(output[0][3]).toEqual("test");
    });
  });

  it('should use custom source for datachange', function () {
    var output = null,
        src    = null;

    runs(function () {
      handsontable({
        onChange: function (changes, source) {
          output = changes;
          src = source;
        }
      });
      setDataAtCell(1, 2, "abc", "test");
    });

    waitsFor(function () {
      return (output != null)
    }, "onChange callback called", 100);

    runs(function () {
      expect(output[0][3]).toEqual("abc");
      expect(src).toEqual("test");
    });
  });

  it('should use custom source for datachange with array', function () {
    var output = null,
        src    = null;

    runs(function () {
      handsontable({
        onChange: function (changes, source) {
          output = changes;
          src = source;
        }
      });
      setDataAtCell([[1, 2, "abc"]], "test");
    });

    waitsFor(function () {
      return (output != null)
    }, "onChange callback called", 100);

    runs(function () {
      expect(output[0][3]).toEqual("abc");
      expect(src).toEqual("test");
    });
  });

  it('should trigger datachange event', function () {
    var output = null;

    runs(function () {
      handsontable();
      Handsontable.PluginHooks.add("onChange", function (changes) {
        output = changes;
      });
      setDataAtCell(1, 2, "test");
    });

    waitsFor(function () {
      return (output != null)
    }, "datachange event triggered", 100);

    runs(function () {
      expect(output[0][0]).toEqual(1);
      expect(output[0][1]).toEqual(2);
      expect(output[0][2]).toEqual(null);
      expect(output[0][3]).toEqual("test");
    });
  });

  it('this.rootElement should point to handsontable rootElement', function () {
    var output = null;
    var $container = this.$container;

    runs(function () {
      handsontable({
        onChange: function () {
          output = this.rootElement[0];
        }
      });
      setDataAtCell(0, 0, "test");
    });

    waitsFor(function () {
      return (output != null)
    }, "onChange callback called", 100);

    runs(function () {
      expect(output).toEqual($container[0]);
    });
  });

  it('onChange should be triggered after data is rendered to DOM (init)', function () {
    var output = null;
    var $container = this.$container;

    runs(function () {
      handsontable({
        data: [
          ['Joe Red']
        ],
        onChange: function (changes, source) {
          if (source === 'loadData') {
            output = $container.find('table.htCore tbody td:first').html();
          }
        }
      });
    });

    waitsFor(function () {
      return (output != null)
    }, "onChange callback called", 100);

    runs(function () {
      expect(output).toEqual('Joe Red');
    });
  });

  it('onChange should be triggered after data is rendered to DOM (setDataAtCell)', function () {
    var output = null;
    var $container = this.$container;

    runs(function () {
      handsontable({
        data: [
          ['Joe Red']
        ],
        onChange: function (changes, source) {
          if (source === 'edit') {
            output = $container.find('table.htCore tbody td:first').html();
          }
        }
      });
      setDataAtCell(0, 0, 'Alice Red');
    });

    waitsFor(function () {
      return (output != null)
    }, "onChange callback called", 100);

    runs(function () {
      expect(output).toEqual('Alice Red');
    });
  });

  it('onChange event object should contain documented keys and values when triggered by edit', function () {
    var sampleData = [
      {
        col1: 'a',
        col2: 'b',
        col3: 'c'
      }
    ];
    var event = null;

    runs(function () {
      handsontable({
        data: sampleData,
        onChange: function (changes, source) {
          if ('edit' == source) {
            event = changes.shift();
          }
        }
      });
      setDataAtCell(0, 0, "test");
    });

    waitsFor(function () {
      return (event != null)
    }, "onChange callback called", 100);

    runs(function () {
      expect(event[0]).toEqual(0);
      expect(event[1]).toEqual('col1');
      expect(event[2]).toEqual('a');
      expect(event[3]).toEqual('test');
    });
  });

  it('source parameter should be `edit` when cell value is changed through editor', function () {
    var sources = [];

    handsontable({
      data: [
        ['Joe Red']
      ],
      onChange: function (changes, source) {
        sources.push(source);
      }
    });
    selectCell(0, 0);

    waitsFor(nextFrame, 'next frame', 60);

    runs(function () {
      keyDown('enter');
      document.activeElement.value = 'Ted';
      keyDown('enter');
    });

    waitsFor(nextFrame, 'next frame', 60);

    runs(function () {
      expect(sources).toEqual(['loadData', 'edit']); //loadData is always the first source
    });
  });

});<|endoftext|>


<commit_before>import test from 'tape'
import {filter, map} from 'lodash/collection'
import contentful from '../../lib/contentful'

const client = contentful.createClient({
  accessToken: 'b4c0n73n7fu1',
  space: 'cfexampleapi'
})

test('Gets space', t => {
  client.getSpace()
  .then(response => {
    t.ok(response.sys, 'sys')
    t.ok(response.name, 'name')
    t.ok(response.locales, 'locales')
    t.end()
  })
})

test('Gets content type', t => {
  client.getContentType('1t9IbcfdCk6m04uISSsaIK')
  .then(response => {
    t.ok(response.sys, 'sys')
    t.ok(response.name, 'name')
    t.ok(response.fields, 'fields')
    t.end()
  })
})

test('Gets content types', t => {
  client.getContentTypes()
  .then(response => {
    t.ok(response.items, 'items')
    t.end()
  })
})

test('Gets entry', t => {
  client.getEntry('5ETMRzkl9KM4omyMwKAOki')
  .then(response => {
    t.ok(response.sys, 'sys')
    t.ok(response.fields, 'fields')
    t.end()
  })
})

test('Gets entries', t => {
  client.getEntries()
  .then(response => {
    t.ok(response.items, 'items')
    t.end()
  })
})

test('Gets entries with content type query param', t => {
  client.getEntries({content_type: 'cat'})
  .then(response => {
    t.equal(response.total, 3)
    t.looseEqual(map(response.items, 'sys.contentType.sys.id'), ['cat', 'cat', 'cat'])
    t.end()
  })
})

test('Gets entries with equality query', t => {
  client.getEntries({'sys.id': 'nyancat'})
  .then(response => {
    t.equal(response.total, 1)
    t.equal(response.items[0].sys.id, 'nyancat')
    t.end()
  })
})

test('Gets entries with inequality query', t => {
  client.getEntries({'sys.id[ne]': 'nyancat'})
  .then(response => {
    t.ok(response.total > 0)
    t.equal(filter(response.items, ['sys.id', 'nyancat']).length, 0)
    t.end()
  })
})

test('Gets entries with array equality query', t => {
  client.getEntries({
    content_type: 'cat',
    'fields.likes': 'lasagna'
  })
  .then(response => {
    t.equal(response.total, 1)
    t.equal(filter(response.items[0].fields.likes, i => i === 'lasagna').length, 1)
    t.end()
  })
})

test('Gets entries with array inequality query', t => {
  client.getEntries({
    content_type: 'cat',
    'fields.likes[ne]': 'lasagna'
  })
  .then(response => {
    t.ok(response.total > 0)
    t.equal(filter(response.items[0].fields.likes, i => i === 'lasagna').length, 0)
    t.end()
  })
})

test('Gets entries with inclusion query', t => {
  client.getEntries({'sys.id[in]': 'finn,jake'})
  .then(response => {
    t.equal(response.total, 2)
    t.equal(filter(response.items, ['sys.id', 'finn']).length, 1)
    t.equal(filter(response.items, ['sys.id', 'jake']).length, 1)
    t.end()
  })
})

test('Gets entries with exclusion query', t => {
  client.getEntries({
    content_type: 'cat',
    'fields.likes[nin]': 'rainbows,lasagna'
  })
  .then(response => {
    t.ok(response.total > 0)
    t.equal(filter(response.items[0].fields.likes, i => i === 'lasagna').length, 0)
    t.equal(filter(response.items[0].fields.likes, i => i === 'rainbows').length, 0)
    t.end()
  })
})

test('Gets entries with exists query', t => {
  client.getEntries({
    content_type: 'cat',
    'fields.likes[exists]': 'true'
  })
  .then(response => {
    t.equal(map(response.items, 'fields.likes').length, response.total)
    t.end()
  })
})

test('Gets entries with inverse exists query', t => {
  client.getEntries({
    content_type: 'cat',
    'fields.likes[exists]': 'false'
  })
  .then(response => {
    t.equal(map(response.items, 'fields.likes').length, 0)
    t.end()
  })
})

test('Gets entries with gte range query', t => {
  client.getEntries({
    'sys.updatedAt[gte]': '2013-01-01T00:00:00Z'
  })
  .then(response => {
    t.ok(response.total > 0)
    t.end()
  })
})

test('Gets entries with lte range query', t => {
  client.getEntries({
    'sys.updatedAt[lte]': '2013-01-01T00:00:00Z'
  })
  .then(response => {
    t.equal(response.total, 0)
    t.end()
  })
})

test('Gets entries with full text search query', t => {
  client.getEntries({
    query: 'bacon'
  })
  .then(response => {
    t.ok(response.items[0].fields.description.match(/bacon/))
    t.end()
  })
})

test('Gets entries with full text search query on field', t => {
  client.getEntries({
    content_type: 'dog',
    'fields.description[match]': 'bacon pancakes'
  })
  .then(response => {
    t.ok(response.items[0].fields.description.match(/bacon/))
    t.end()
  })
})

test('Gets entries with location proximity search', t => {
  client.getEntries({
    content_type: '1t9IbcfdCk6m04uISSsaIK',
    'fields.center[near]': '38,-122'
  })
  .then(response => {
    t.ok(response.items[0].fields.center.lat, 'has latitude')
    t.ok(response.items[0].fields.center.lon, 'has longitude')
    t.end()
  })
})

test('Gets entries with location in bounding object', t => {
  client.getEntries({
    content_type: '1t9IbcfdCk6m04uISSsaIK',
    'fields.center[within]': '40,-124,36,-120'
  })
  .then(response => {
    t.ok(response.items[0].fields.center.lat, 'has latitude')
    t.ok(response.items[0].fields.center.lon, 'has longitude')
    t.end()
  })
})

test('Gets entries by creation order', t => {
  client.getEntries({
    order: 'sys.createdAt'
  })
  .then(response => {
    t.ok(response.items[0].sys.createdAt < response.items[1].sys.createdAt)
    t.end()
  })
})

test('Gets entries by inverse creation order', t => {
  client.getEntries({
    order: '-sys.createdAt'
  })
  .then(response => {
    t.ok(response.items[0].sys.createdAt > response.items[1].sys.createdAt)
    t.end()
  })
})

test('Gets entries by creation order and id order', t => {
  client.getEntries({
    order: 'sys.createdAt,sys.id'
  })
  .then(response => {
    t.ok(response.items[0].sys.createdAt < response.items[1].sys.createdAt, 'createdAt')
    t.ok(response.items[0].sys.id < response.items[1].sys.id, 'id')
    t.end()
  })
})

test('Gets assets with only images', t => {
  client.getAssets({
    mimetype_group: 'image'
  })
  .then(response => {
    t.ok(response.items[0].fields.file.contentType.match(/image/))
    t.end()
  })
})

test('Gets asset', t => {
  client.getAsset('1x0xpXu4pSGS4OukSyWGUK')
  .then(response => {
    t.ok(response.sys, 'sys')
    t.ok(response.fields, 'fields')
    t.end()
  })
})

test('Gets assets', t => {
  client.getAssets()
  .then(response => {
    t.ok(response.items, 'items')
    t.end()
  })
})
<commit_msg>test(integration): Add test for linked includes<commit_after>import test from 'tape'
import {filter, map} from 'lodash/collection'
import contentful from '../../lib/contentful'

const client = contentful.createClient({
  accessToken: 'b4c0n73n7fu1',
  space: 'cfexampleapi'
})

test('Gets space', t => {
  client.getSpace()
  .then(response => {
    t.ok(response.sys, 'sys')
    t.ok(response.name, 'name')
    t.ok(response.locales, 'locales')
    t.end()
  })
})

test('Gets content type', t => {
  client.getContentType('1t9IbcfdCk6m04uISSsaIK')
  .then(response => {
    t.ok(response.sys, 'sys')
    t.ok(response.name, 'name')
    t.ok(response.fields, 'fields')
    t.end()
  })
})

test('Gets content types', t => {
  client.getContentTypes()
  .then(response => {
    t.ok(response.items, 'items')
    t.end()
  })
})

test('Gets entry', t => {
  client.getEntry('5ETMRzkl9KM4omyMwKAOki')
  .then(response => {
    t.ok(response.sys, 'sys')
    t.ok(response.fields, 'fields')
    t.end()
  })
})

test('Gets entries', t => {
  client.getEntries()
  .then(response => {
    t.ok(response.items, 'items')
    t.end()
  })
})

test('Gets entries with linked includes', t => {
  client.getEntries({include: 2})
  .then(response => {
    t.ok(response.includes, 'includes')
    t.ok(response.includes.Asset, 'includes for Assets')
    t.ok(Object.keys(response.includes.Asset).length > 0, 'list of includes has asset items')
    t.end()
  })
})

test('Gets entries with content type query param', t => {
  client.getEntries({content_type: 'cat'})
  .then(response => {
    t.equal(response.total, 3)
    t.looseEqual(map(response.items, 'sys.contentType.sys.id'), ['cat', 'cat', 'cat'])
    t.end()
  })
})

test('Gets entries with equality query', t => {
  client.getEntries({'sys.id': 'nyancat'})
  .then(response => {
    t.equal(response.total, 1)
    t.equal(response.items[0].sys.id, 'nyancat')
    t.end()
  })
})

test('Gets entries with inequality query', t => {
  client.getEntries({'sys.id[ne]': 'nyancat'})
  .then(response => {
    t.ok(response.total > 0)
    t.equal(filter(response.items, ['sys.id', 'nyancat']).length, 0)
    t.end()
  })
})

test('Gets entries with array equality query', t => {
  client.getEntries({
    content_type: 'cat',
    'fields.likes': 'lasagna'
  })
  .then(response => {
    t.equal(response.total, 1)
    t.equal(filter(response.items[0].fields.likes, i => i === 'lasagna').length, 1)
    t.end()
  })
})

test('Gets entries with array inequality query', t => {
  client.getEntries({
    content_type: 'cat',
    'fields.likes[ne]': 'lasagna'
  })
  .then(response => {
    t.ok(response.total > 0)
    t.equal(filter(response.items[0].fields.likes, i => i === 'lasagna').length, 0)
    t.end()
  })
})

test('Gets entries with inclusion query', t => {
  client.getEntries({'sys.id[in]': 'finn,jake'})
  .then(response => {
    t.equal(response.total, 2)
    t.equal(filter(response.items, ['sys.id', 'finn']).length, 1)
    t.equal(filter(response.items, ['sys.id', 'jake']).length, 1)
    t.end()
  })
})

test('Gets entries with exclusion query', t => {
  client.getEntries({
    content_type: 'cat',
    'fields.likes[nin]': 'rainbows,lasagna'
  })
  .then(response => {
    t.ok(response.total > 0)
    t.equal(filter(response.items[0].fields.likes, i => i === 'lasagna').length, 0)
    t.equal(filter(response.items[0].fields.likes, i => i === 'rainbows').length, 0)
    t.end()
  })
})

test('Gets entries with exists query', t => {
  client.getEntries({
    content_type: 'cat',
    'fields.likes[exists]': 'true'
  })
  .then(response => {
    t.equal(map(response.items, 'fields.likes').length, response.total)
    t.end()
  })
})

test('Gets entries with inverse exists query', t => {
  client.getEntries({
    content_type: 'cat',
    'fields.likes[exists]': 'false'
  })
  .then(response => {
    t.equal(map(response.items, 'fields.likes').length, 0)
    t.end()
  })
})

test('Gets entries with gte range query', t => {
  client.getEntries({
    'sys.updatedAt[gte]': '2013-01-01T00:00:00Z'
  })
  .then(response => {
    t.ok(response.total > 0)
    t.end()
  })
})

test('Gets entries with lte range query', t => {
  client.getEntries({
    'sys.updatedAt[lte]': '2013-01-01T00:00:00Z'
  })
  .then(response => {
    t.equal(response.total, 0)
    t.end()
  })
})

test('Gets entries with full text search query', t => {
  client.getEntries({
    query: 'bacon'
  })
  .then(response => {
    t.ok(response.items[0].fields.description.match(/bacon/))
    t.end()
  })
})

test('Gets entries with full text search query on field', t => {
  client.getEntries({
    content_type: 'dog',
    'fields.description[match]': 'bacon pancakes'
  })
  .then(response => {
    t.ok(response.items[0].fields.description.match(/bacon/))
    t.end()
  })
})

test('Gets entries with location proximity search', t => {
  client.getEntries({
    content_type: '1t9IbcfdCk6m04uISSsaIK',
    'fields.center[near]': '38,-122'
  })
  .then(response => {
    t.ok(response.items[0].fields.center.lat, 'has latitude')
    t.ok(response.items[0].fields.center.lon, 'has longitude')
    t.end()
  })
})

test('Gets entries with location in bounding object', t => {
  client.getEntries({
    content_type: '1t9IbcfdCk6m04uISSsaIK',
    'fields.center[within]': '40,-124,36,-120'
  })
  .then(response => {
    t.ok(response.items[0].fields.center.lat, 'has latitude')
    t.ok(response.items[0].fields.center.lon, 'has longitude')
    t.end()
  })
})

test('Gets entries by creation order', t => {
  client.getEntries({
    order: 'sys.createdAt'
  })
  .then(response => {
    t.ok(response.items[0].sys.createdAt < response.items[1].sys.createdAt)
    t.end()
  })
})

test('Gets entries by inverse creation order', t => {
  client.getEntries({
    order: '-sys.createdAt'
  })
  .then(response => {
    t.ok(response.items[0].sys.createdAt > response.items[1].sys.createdAt)
    t.end()
  })
})

test('Gets entries by creation order and id order', t => {
  client.getEntries({
    order: 'sys.createdAt,sys.id'
  })
  .then(response => {
    t.ok(response.items[0].sys.createdAt < response.items[1].sys.createdAt, 'createdAt')
    t.ok(response.items[0].sys.id < response.items[1].sys.id, 'id')
    t.end()
  })
})

test('Gets assets with only images', t => {
  client.getAssets({
    mimetype_group: 'image'
  })
  .then(response => {
    t.ok(response.items[0].fields.file.contentType.match(/image/))
    t.end()
  })
})

test('Gets asset', t => {
  client.getAsset('1x0xpXu4pSGS4OukSyWGUK')
  .then(response => {
    t.ok(response.sys, 'sys')
    t.ok(response.fields, 'fields')
    t.end()
  })
})

test('Gets assets', t => {
  client.getAssets()
  .then(response => {
    t.ok(response.items, 'items')
    t.end()
  })
})
<|endoftext|>


<commit_before>ace.define("ace/snippets/gherkin",["require","exports","module"], function(require, exports, module) {
"use strict";

exports.snippetText =undefined;
exports.scope = "gherkin";

});
<commit_msg>Update tmp/bower_components/ace-builds/src-noconflict/snippets/gherkin.js<commit_after><|endoftext|>


<commit_before>var lastTimestamp = 0;
var pollRate = 1000;
var alertTimeoutId = null;
var focused = true;
var title = document.title;

window.onfocus = function () {
    if (alertTimeoutId != null) {
        clearInterval(alertTimeoutId);
    }

    document.title = title;
    focused = true;
}

window.onblur = function() {
    focused = false;
}

function doNewMessageAlert() {
    var msg = "New Message";
    var timeoutId;
    var blink = function() { document.title = document.title == msg ? title : msg; };
    if (! timeoutId && !focused) {
        alertTimeoutId = setInterval(blink, 1000);
    }
}

function updateChatTimes() {
    //run though all the chat messages in the DOM and
    //update the "posted X hrs/days/etc ago" labels
    $(".chat-body .post-date span").each(function(index, elem) {
        var date = moment($(elem).attr('data-date'), 'x');
        var posted = moment.duration(date.diff(moment())).humanize();

        $(elem).html(posted);
    });
}

function addToChatBox(messages) {
    var tzoff = new Date().getTimezoneOffset();

    for (var i = 0, len=messages.length; i < len; i++) {
        var msg = messages[i];

        var liClass = 'left';
        var spanClass = 'pull-left';
        var smallClass = 'pull-right';
        var strongClass = '';

        if (msg.userId == userid) {
            liClass = 'right';
            spanClass = 'pull-right';
            smallClass = '';
            strongClass = 'pull-right ';
        }

        var localTimePostedOn = moment(msg.timestamp).zone(tzoff);
        var posted = moment.duration(localTimePostedOn.diff(moment())).humanize();

        var pimage;

        if (msg.user.profileImage != null) {
            pimage = msg.user.profileImage.slice(0, -4) + "-t.jpg";
        } else {
            pimage = "/images/blank.png";
        }

        $("ul.chat").append(
            '
' +
                '' +
                    '' +
                '' +
                '
' +
                    '
' +
                        '' +
                            msg.user.username +
                        '' +
                        '' +
                            '' + posted + ' ago' +
                        '' +
                    '
' +
                    '
' +
                        html_sanitize(msg.message) +
                    '
' +
                '
' +
            '
'
        );

        lastTimestamp = msg.timestamp;
    }

    if (messages.length > 0) {
        //something was added, scroll to the bottom
        document.getElementById('chat-body').scrollTop = 10000;
        //also alert
        doNewMessageAlert();
    }

}

function getChatSinceLastCheck() {
    var cid = conversationId;

    $.ajax({
        type: "GET",
        dataType: "json",
        url: "/chat/since/" + cid + "/" + lastTimestamp +"?timestamp="+$.now(),
        contentType: "application/json",
        success:
        function(data) {
            addToChatBox(data);
        }
    });
}

function sendChat() {
    var text = $("#btn-input").val();
    $("#btn-input").val('');
    var cid = conversationId;

    $.ajax({
        type: "POST",
        dataType: "json",
        url: "/chat/add",
        contentType: "application/json",
        data: JSON.stringify({"chatText": text, "conversationId": cid}),
        success:
        function(data) {
        }
    });
}

function chatRefresh() {
    getChatSinceLastCheck();
    updateChatTimes();
}

function chatTimer() {
    chatRefresh();
    setTimeout(chatTimer, pollRate);
}

$(document).ready(function() {
    var cid = conversationId;

    //grab the most recent chat messages
    $.ajax({
        type: "GET",
        dataType: "json",
        url: "/chat/recent/" + cid,
        contentType: "application/json",
        success:
        function(data) {
            addToChatBox(data);
        }
    });

    $("#btn-chat").click(function(evt) {
        sendChat();
    });

    $("#btn-input").keypress(function (e) {
        var key = e.which;
        if(key == 13)  { //enter key
            sendChat();
            return false;
        }
    });

    $("#chat-refresh").click(function (e) {
        chatRefresh();
        e.preventDefault();
    });

    setTimeout(chatTimer, pollRate);
});
<commit_msg>Bugfix: Window kept blinking sometimes because we were checking the wrong interval id<commit_after>var lastTimestamp = 0;
var pollRate = 1000;
var alertTimeoutId = null;
var focused = true;
var title = document.title;

window.onfocus = function () {
    if (alertTimeoutId != null) {
        clearInterval(alertTimeoutId);
    }

    document.title = title;
    focused = true;
}

window.onblur = function() {
    focused = false;
}

function doNewMessageAlert() {
    var msg = "New Message";
    var timeoutId;
    var blink = function() { document.title = document.title == msg ? title : msg; };
    if (!alertTimeoutId && !focused) {
        alertTimeoutId = setInterval(blink, 1000);
    }
}

function updateChatTimes() {
    //run though all the chat messages in the DOM and
    //update the "posted X hrs/days/etc ago" labels
    $(".chat-body .post-date span").each(function(index, elem) {
        var date = moment($(elem).attr('data-date'), 'x');
        var posted = moment.duration(date.diff(moment())).humanize();

        $(elem).html(posted);
    });
}

function addToChatBox(messages) {
    var tzoff = new Date().getTimezoneOffset();

    for (var i = 0, len=messages.length; i < len; i++) {
        var msg = messages[i];

        var liClass = 'left';
        var spanClass = 'pull-left';
        var smallClass = 'pull-right';
        var strongClass = '';

        if (msg.userId == userid) {
            liClass = 'right';
            spanClass = 'pull-right';
            smallClass = '';
            strongClass = 'pull-right ';
        }

        var localTimePostedOn = moment(msg.timestamp).zone(tzoff);
        var posted = moment.duration(localTimePostedOn.diff(moment())).humanize();

        var pimage;

        if (msg.user.profileImage != null) {
            pimage = msg.user.profileImage.slice(0, -4) + "-t.jpg";
        } else {
            pimage = "/images/blank.png";
        }

        $("ul.chat").append(
            '
' +
                '' +
                    '' +
                '' +
                '
' +
                    '
' +
                        '' +
                            msg.user.username +
                        '' +
                        '' +
                            '' + posted + ' ago' +
                        '' +
                    '
' +
                    '
' +
                        html_sanitize(msg.message) +
                    '
' +
                '
' +
            '
'
        );

        lastTimestamp = msg.timestamp;
    }

    if (messages.length > 0) {
        //something was added, scroll to the bottom
        document.getElementById('chat-body').scrollTop = 10000;
        //also alert
        doNewMessageAlert();
    }

}

function getChatSinceLastCheck() {
    var cid = conversationId;

    $.ajax({
        type: "GET",
        dataType: "json",
        url: "/chat/since/" + cid + "/" + lastTimestamp +"?timestamp="+$.now(),
        contentType: "application/json",
        success:
        function(data) {
            addToChatBox(data);
        }
    });
}

function sendChat() {
    var text = $("#btn-input").val();
    $("#btn-input").val('');
    var cid = conversationId;

    $.ajax({
        type: "POST",
        dataType: "json",
        url: "/chat/add",
        contentType: "application/json",
        data: JSON.stringify({"chatText": text, "conversationId": cid}),
        success:
        function(data) {
        }
    });
}

function chatRefresh() {
    getChatSinceLastCheck();
    updateChatTimes();
}

function chatTimer() {
    chatRefresh();
    setTimeout(chatTimer, pollRate);
}

$(document).ready(function() {
    var cid = conversationId;

    //grab the most recent chat messages
    $.ajax({
        type: "GET",
        dataType: "json",
        url: "/chat/recent/" + cid,
        contentType: "application/json",
        success:
        function(data) {
            addToChatBox(data);
        }
    });

    $("#btn-chat").click(function(evt) {
        sendChat();
    });

    $("#btn-input").keypress(function (e) {
        var key = e.which;
        if(key == 13)  { //enter key
            sendChat();
            return false;
        }
    });

    $("#chat-refresh").click(function (e) {
        chatRefresh();
        e.preventDefault();
    });

    setTimeout(chatTimer, pollRate);
});
<|endoftext|>


<commit_before>exports.run = async function (client, msg, args, db) {

	if (!permissions.isAdmin(msg.member, msg.channel.guild.id, db)) return msg.channel.createMessage({ embed: {
		color: 0x1E90FF,
		title: "Insufficient Permissions",
	}});

	if (!args[0]) return msg.channel.createMessage({ embed: {
		color: 0x1E90FF,
		title: "Specify a user"
	}});

	let usr = isNaN(args.join(" ")) ? msg.channel.guild.members.filter(u => u.username.toLowerCase().includes(args.join(" ").toLowerCase())) : msg.channel.guild.members.get(args.join(" "));
	if (typeof usr === Array && usr[0]) usr = usr[0].user;
	if (!usr) return msg.channel.createMessage({ embed: {
		color: 0x1E90FF,
		title: "No users found matching the specified name"
	}});
	await rethonk.db("data").table("guilds").update({ id: msg.channel.guild.id, admins: db.admins.filter(id => id !== usr.id) }).run()
	.catch(err => {
		return msg.channel.createMessage({	embed: {
			color: 0x1E90FF,
			title: "Failed to update admins",
			description: err.message
		}});
	});

	msg.channel.createMessage({	embed: {
		color: 0x1E90FF,
		title: `Removed ${usr.username}#${usr.discriminator} from admins.`
	}});

}

exports.usage = {
	main: "{prefix}{command}",
	args: "<@mention>"
};
<commit_msg>this would be easier if i had my test bench<commit_after>exports.run = async function (client, msg, args, db) {

	if (!permissions.isAdmin(msg.member, msg.channel.guild.id, db)) return msg.channel.createMessage({ embed: {
		color: 0x1E90FF,
		title: "Insufficient Permissions",
	}});

	if (!args[0]) return msg.channel.createMessage({ embed: {
		color: 0x1E90FF,
		title: "Specify a user"
	}});

	let usr = isNaN(args.join(" ")) ? msg.channel.guild.members.filter(u => u.username.toLowerCase().includes(args.join(" ").toLowerCase())) : msg.channel.guild.members.get(args.join(" "));
	if (typeof usr === Array && usr[0]) usr = usr[0].user;
	console.log(usr)
	if (!usr) return msg.channel.createMessage({ embed: {
		color: 0x1E90FF,
		title: "No users found matching the specified name"
	}});
	await rethonk.db("data").table("guilds").update({ id: msg.channel.guild.id, admins: db.admins.filter(id => id !== usr.id) }).run()
	.catch(err => {
		return msg.channel.createMessage({	embed: {
			color: 0x1E90FF,
			title: "Failed to update admins",
			description: err.message
		}});
	});

	msg.channel.createMessage({	embed: {
		color: 0x1E90FF,
		title: `Removed ${usr.username}#${usr.discriminator} from admins.`
	}});

}

exports.usage = {
	main: "{prefix}{command}",
	args: "<@mention>"
};
<|endoftext|>


<commit_before>/* eslint react/no-set-state:0 */

import './LoadingBar.css';
import React, { Component, PropTypes } from 'react';
import shallowCompare from 'react-addons-shallow-compare';

const autoUpdateInterval = 250;
const firstPercentage = 0.55;

export default class LoadingBar extends Component {
    constructor(props) {
        super(props);
        this.state = { percentage: 0 };
    }

    componentDidMount() {
        this._update();
    }

    shouldComponentUpdate(nextProps, nextState) {
        return shallowCompare(this, nextProps, nextState);
    }

    componentDidUpdate() {
        this._update();
    }

    componentWillUnmount() {
        if (this._interval) {
            clearInterval(this._interval);
            this._interval = null;
        }
    }

    render() {
        const hasFinished = this.state.percentage === 1;
        const className = `loading-bar-component ${hasFinished ? 'is-finished' : ''} ${this.state.instant ? 'disable-transition' : ''}`;
        const style = {
            transform: `scaleX(${this.state.percentage})`,
            opacity: this.state.percentage === 1 ? '0' : '1',
        };

        return (

        );
    }

    // ------------------------------------------------------

    _update() {
        if (this.props.running) {
            this._start();
        } else {
            this._finish();
        }
    }

    _start() {
        if (this._interval) {
            return;
        }

        this._interval = setInterval(() => this._autoIncrement(), autoUpdateInterval);

        this.setState({ percentage: 0, instant: true }, () => {
            setTimeout(() => this.props.running && this.setState({ percentage: firstPercentage, instant: false }), 0);
        });
    }

    _finish() {
        if (!this._interval) {
            return;
        }

        this.setState({ percentage: 1, instant: false });

        clearInterval(this._interval);
        this._interval = null;
    }

    _autoIncrement() {
        let percentage = this.state.percentage + Math.min(0.8, (1 - this.state.percentage) / 10);

        if (percentage > 0.95) {
            percentage = 0.95;
            clearInterval(this._interval);
        }

        this.setState({ percentage, instant: false });
    }
}

LoadingBar.propTypes = {
    running: PropTypes.bool.isRequired,
};

export default LoadingBar;
<commit_msg>Update LoadingBar.js<commit_after>/* eslint react/no-set-state:0 */

import './LoadingBar.css';
import React, { Component, PropTypes } from 'react';
import shallowCompare from 'react-addons-shallow-compare';

const autoUpdateInterval = 250;
const firstPercentage = 0.55;

class LoadingBar extends Component {
    constructor(props) {
        super(props);
        this.state = { percentage: 0 };
    }

    componentDidMount() {
        this._update();
    }

    shouldComponentUpdate(nextProps, nextState) {
        return shallowCompare(this, nextProps, nextState);
    }

    componentDidUpdate() {
        this._update();
    }

    componentWillUnmount() {
        if (this._interval) {
            clearInterval(this._interval);
            this._interval = null;
        }
    }

    render() {
        const hasFinished = this.state.percentage === 1;
        const className = `loading-bar-component ${hasFinished ? 'is-finished' : ''} ${this.state.instant ? 'disable-transition' : ''}`;
        const style = {
            transform: `scaleX(${this.state.percentage})`,
            opacity: this.state.percentage === 1 ? '0' : '1',
        };

        return (

        );
    }

    // ------------------------------------------------------

    _update() {
        if (this.props.running) {
            this._start();
        } else {
            this._finish();
        }
    }

    _start() {
        if (this._interval) {
            return;
        }

        this._interval = setInterval(() => this._autoIncrement(), autoUpdateInterval);

        this.setState({ percentage: 0, instant: true }, () => {
            setTimeout(() => this.props.running && this.setState({ percentage: firstPercentage, instant: false }), 0);
        });
    }

    _finish() {
        if (!this._interval) {
            return;
        }

        this.setState({ percentage: 1, instant: false });

        clearInterval(this._interval);
        this._interval = null;
    }

    _autoIncrement() {
        let percentage = this.state.percentage + Math.min(0.8, (1 - this.state.percentage) / 10);

        if (percentage > 0.95) {
            percentage = 0.95;
            clearInterval(this._interval);
        }

        this.setState({ percentage, instant: false });
    }
}

LoadingBar.propTypes = {
    running: PropTypes.bool.isRequired,
};

export default LoadingBar;
<|endoftext|>


<commit_before>// regExp parser
// helper module for parsing different types of messagess
var parser = {};

// regEx for finding a bikeID
var bikeIdRegEx = /^[0-9]+/;
// regEx for finding a validation code
var validationRegEx = /^\$[A-Za-z0-9_-]{8}/;

// getBikeId
parser.getBikeId = function(string) {

	var matches = string.match(bikeIdRegEx);
	return matches ? matches[0] : null;
};

// getValidationCode
parser.getValidationCode = function(string) {

	var matches = string.match(validationRegEx);
	return matches ? matches[0] : null;
};

// export
module.exports = parser;
<commit_msg>fix validation code regExParser<commit_after>// regExp parser
// helper module for parsing different types of messagess
var parser = {};

// regEx for finding a bikeID
var bikeIdRegEx = /^[0-9]+/;
// regEx for finding a validation code
var validationRegEx = /^\$[A-Za-z0-9_-]{9}/;

// getBikeId
parser.getBikeId = function(string) {

	var matches = string.match(bikeIdRegEx);
	return matches ? matches[0] : null;
};

// getValidationCode
parser.getValidationCode = function(string) {

	var matches = string.match(validationRegEx);
	return matches ? matches[0] : null;
};

// export
module.exports = parser;
<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import styled, {ThemeProvider}  from 'styled-components';
import PropTypes from 'prop-types';
import { get, size, isString } from 'lodash';

import { colors, typography, darkScrollbar } from '../styles';
import {defaultTheme} from './TextareaInputThemes'

const TextareaInputWrapper = styled.div`
  width: 100%;
`;

const TextareaBox = styled.div`
  background-color: ${props => props.theme.background};
  border: thin solid ${colors.black40};
  border-color: ${(props) => {
    if (props.error) {
      return colors.red;
    } else if (props.isFocused) {
      return colors.green;
    } else if (props.disabled) {
      return colors.black20;
    } else if (props.lineColor) {
      return props.lineColor;
    } else  {
      return props.theme.borderColor;
    }
  }};
  border-radius: 4px;
  border-width: ${(props) => {
    if (props.isFocused || props.error) {
      return '2px';
    }
    return '1px';
  }};
  box-sizing: border-box;
  cursor: ${(props) => {
    if (props.disabled) {
      return 'default';
    }
    return 'text';
  }};
  padding-top: ${(props) => {
    if (!props.open && !props.isFocused && props.collapsed) {
      return 0;
    } else if (props.error || props.isFocused) {
      return '27px';
    }

    return '28px';
  }};
  height: ${(props) => {
    if (!props.open && !props.isFocused && !props.error && props.collapsed) return '50px';

    return '100px';
  }};
  min-height: ${(props) => {
    if (!props.open && !props.isFocused && !props.error && props.collapsed) return '50px';

    return '100px';
  }};
  position: relative;
  transition: border-color 0.14s ease-in-out;
  width: 100%;

  &:hover {
    border-width: ${(props) => {
    if (props.disabled) {
      return '1px';
    }
    return '2px';
  }};
    padding-top: ${(props) => {
    if (!props.open && !props.isFocused && props.collapsed) {
      return 0;
    } else if (props.disabled) {
      return '28px';
    }
    return '27px';
  }};

    textarea {
      padding: ${(props) => {
    if ((props.error || props.isFocused || props.open) && !props.disabled) {
      return '0 15px';
    } else {
      return '0 16px';
    }
  }};
    }

    label {
      left: ${(props) => {
    if (props.disabled) {
      return '16px';
    }
    return '15px';
  }};
      top: ${(props) => {
    if (props.disabled) {
      return '0';
    }
    return '-1px';
  }};
    }
  }

  ${(props) => {
    if (props.disabled) {
      return `
        background-color: ${colors.black05};
        label {
          color: ${colors.black40};
        }
      `;
     }
  }}
  `;

const Textarea = styled.textarea`
background-color: transparent;
border: none;
color: ${(props) => props.theme.valueColor};
box-sizing: border-box;
height: 100%;
padding: ${(props) => {
    if (props.error || props.isFocused) {
      return '0 15px';
    } else {
      return '0 16px';
    }
  }};
resize: none;
text-align: left;
width: 100%;

  &:focus {
  outline: 0;
  padding: 0 15px;
}
${typography.subhead1}
${darkScrollbar}

  &::-webkit-input-placeholder {
    color: ${colors.black40};
  }
`;

const TextLabel = styled.label`
color: ${(props) => {
    if (props.error) {
      return colors.red;
    } else if (props.isFocused) {
      return colors.green;
    } else if (props.labelColor) {
      return props.labelColor;
    } else {
      return props.theme.labelColor;
    }
  }};
top: ${(props) => {
    if (props.error || props.isFocused || props.placeholder) {
      return '-1px';
    }
    return '0';
  }};;
left: ${(props) => {
    if (props.error || props.isFocused || props.placeholder) {
      return '15px';
    }
    return '16px';
  }};
position: absolute;
transform: ${(props) => {
    if (props.open || props.isFocused || props.placeholder) {
      return 'translateY(8px)';
    } else {
      return 'translateY(16px)';
    }
  }};
transition: font-size 0.14s ease-in-out, transform 0.14s ease-in-out, color 0.14s ease-in-out;
${(props) => {
    if (props.open || props.isFocused || props.placeholder) {
      return typography.caption
    } else {
      return typography.subhead1
    }
  }}
line-height: 16px;
`;

const charCountTextWidth = '110px';

export const CharCounterText = styled.div`
${typography.caption}
color: ${colors.green};
text-align: right;
width: ${charCountTextWidth};
`;

export const CharCounterErrorText = styled(CharCounterText)`
color: ${colors.red};
`;

export const FooterTextContainer = styled.div`
  color: ${colors.black40};
  padding-top: 4px;
  ${typography.caption}
  display: flex;
  justify-content: space-between;
`;

export const HelperTextContainer = styled.div`
  width:${props => props.hasCharLimit ? `calc(100% - ${charCountTextWidth})` : '100%'};
`;

export const HelperText = styled.span`
  color: ${props => props.theme.helperColor};
  ${typography.caption}
`;

const HelperErrorText = styled(HelperText)`
  color: ${colors.red};
`;

/**
 * Indicates if the string value has exceeded the char limit
 * @param {number} charLimit
 * @param {string} value
 */
export function charLimitExceeded(charLimit, value) {
  if (charLimit === 0 || size(value) === 0) {
    return false;
  }
  return size(value) > charLimit;
}

/**
 * Returns the char counter text string
 * @param {number} charLimit
 * @param {string} value
 */
export function determineCharCounterTextValue(charLimit, value) {
  if (!charLimit) return null;

  return `${size(value)} / ${charLimit}`;
}

export const ErrorTextContainer = (props) => {
  const { charLimit, error, localError } = props;
  return (
    <HelperTextContainer hasCharLimit={charLimit > 0}>
      {(error || localError) &&
        <HelperErrorText>{error || localError}</HelperErrorText>}
    </HelperTextContainer>
  );
};

export const TextareaHelper = (props) => {
  const { hasCharLimit, helper } = props;
  return (
    <HelperTextContainer hasCharLimit={hasCharLimit}>
      <HelperText>{helper}</HelperText>
    </HelperTextContainer>
  );
};

export const CharLimitExceededError = 'Character limit exceeded';

class TextareaInput extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      focused: false
    };
  }

  componentDidMount() {
    const {value} = this.props;

    if (value) {
      this.setState({
        value
      });
    }
  }

  focused = () => {
    this.setState({
      focused: true
    })
  }

  blurred = () => {
    if(!this.state.cancelBlur) {
      this.setState({
        focused: false
      });
    }
  }

  renderCharCounterText = () => {
    const inputValue = get(this.state, 'value', get(this.props, 'value', ''));
    const { charLimit } = this.props;
    if (!charLimit) return null;

    const charTextValue = determineCharCounterTextValue(charLimit, inputValue);

    if (charLimitExceeded(charLimit, inputValue)) {
      return (
        <CharCounterErrorText>{charTextValue}</CharCounterErrorText>
      );
    }

    return (
      <CharCounterText>{charTextValue}</CharCounterText>
    );
  };

  renderFooterText = () => {
    return (
      <FooterTextContainer>
        {this.renderHelperText()}
        {this.renderCharCounterText()}
      </FooterTextContainer>
    );
  };

  renderErrorText = () => {
    const { charLimit, error } = this.props;
    const localError = this.determineLocalError();
    return <ErrorTextContainer localError={localError} charLimit={charLimit} error={error} />;
  };

  determineLocalError = () => {
    const { charLimit } = this.props;
    const value = get(this.state, 'value', get(this.props, 'value', ''));
    if (charLimitExceeded(charLimit, value)) {
      return CharLimitExceededError;
    }
    return '';
  };

  renderHelperText = () => {
    const { error, helper, collapsed, charLimit } = this.props;
    const localError = this.determineLocalError();

    if (collapsed && !this.state.value && !this.state.focused && !(error || localError || helper)) {
      return null;
    }

    if (error || localError) {
      return this.renderErrorText();
    }

    return <TextareaHelper hasCharLimit={charLimit > 0} helper={helper} />;
  }

  focusOnTextarea = () => {
    if (this.textareaInput !== document.activeElement) {
      this.textareaInput.focus();
    }
  }

  cancelBlur = (e) => {
    this.setState({
      cancelBlur: true
    });
  }

  removeCancelBlur = () => {
    this.setState({
      cancelBlur: false
    });
  }

  onChange = (e) => {
    if (e) {
      e.preventDefault();
    }

    this.setState({
      value: get(e, 'target.value', this.textareaInput.value)
    }, () => {
      if (this.props.onChange) {
        this.props.onChange(this.state.value);
      }
    });
  }

  getValue(stateValue, overrideValue){
    if (isString(overrideValue)){
      return overrideValue;
    }
    return stateValue;
  }

  setValue = (value) => {
    this.setState({ value });
  };

  render() {
    const { className, label, name, error, disabled, collapsed, labelColor, lineColor, placeholder } = this.props;
    const localError = this.determineLocalError();

    return (
      <ThemeProvider theme={this.props.theme}>
      <TextareaInputWrapper className={className}>
        <TextareaBox
          onMouseUp={this.removeCancelBlur}
          onMouseDown={this.cancelBlur}
          onMouseLeave={this.removeCancelBlur}
          onClick={this.focusOnTextarea}
          lineColor={lineColor}
          isFocused={this.state.focused}
          error={error || localError}
          open={this.getValue(this.state.value,  this.props.overrideValue)}
          disabled={disabled}
          collapsed={collapsed}>
          <Textarea
            onFocus={this.focused}
            onBlur={this.blurred}
            id={name}
            name={name}
            disabled={disabled}
            error={error || localError}
            value={this.getValue(this.state.value)}
            ref={(input) => { this.textareaInput = ReactDOM.findDOMNode(input); }}
            onChange={this.onChange}
            placeholder={placeholder}>
          </Textarea>
          <TextLabel
            isFocused={this.state.focused}
            labelColor={labelColor}
            open={this.getValue(this.state.value,  this.props.overrideValue)}
            htmlFor={name}
            error={error || localError}
            placeholder={placeholder}>
            {label}
          </TextLabel>
        </TextareaBox>
        {this.renderFooterText()}
      </TextareaInputWrapper>
      </ThemeProvider>
    );
  }
}

TextareaInput.defaultProps = {
  name: 'Name',
  label: 'Label',
  charLimit: 0,
  error: '',
  placeholder: '',
  theme: defaultTheme,
  overrideValue: null
};

TextareaInput.propTypes = {
  name: PropTypes.string.isRequired,
  label: PropTypes.string.isRequired,
  helper: PropTypes.string,
  error: PropTypes.string,
  disabled: PropTypes.bool,
  value: PropTypes.string,
  overrideValue: PropTypes.string,
  onChange: PropTypes.func,
  collapsed: PropTypes.bool,
  charLimit: PropTypes.number,
  placeholder: PropTypes.string,
  theme: PropTypes.object
};

export default TextareaInput;
<commit_msg>remove value override, no longer needed<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import styled, {ThemeProvider}  from 'styled-components';
import PropTypes from 'prop-types';
import { get, size, isString } from 'lodash';

import { colors, typography, darkScrollbar } from '../styles';
import {defaultTheme} from './TextareaInputThemes'

const TextareaInputWrapper = styled.div`
  width: 100%;
`;

const TextareaBox = styled.div`
  background-color: ${props => props.theme.background};
  border: thin solid ${colors.black40};
  border-color: ${(props) => {
    if (props.error) {
      return colors.red;
    } else if (props.isFocused) {
      return colors.green;
    } else if (props.disabled) {
      return colors.black20;
    } else if (props.lineColor) {
      return props.lineColor;
    } else  {
      return props.theme.borderColor;
    }
  }};
  border-radius: 4px;
  border-width: ${(props) => {
    if (props.isFocused || props.error) {
      return '2px';
    }
    return '1px';
  }};
  box-sizing: border-box;
  cursor: ${(props) => {
    if (props.disabled) {
      return 'default';
    }
    return 'text';
  }};
  padding-top: ${(props) => {
    if (!props.open && !props.isFocused && props.collapsed) {
      return 0;
    } else if (props.error || props.isFocused) {
      return '27px';
    }

    return '28px';
  }};
  height: ${(props) => {
    if (!props.open && !props.isFocused && !props.error && props.collapsed) return '50px';

    return '100px';
  }};
  min-height: ${(props) => {
    if (!props.open && !props.isFocused && !props.error && props.collapsed) return '50px';

    return '100px';
  }};
  position: relative;
  transition: border-color 0.14s ease-in-out;
  width: 100%;

  &:hover {
    border-width: ${(props) => {
    if (props.disabled) {
      return '1px';
    }
    return '2px';
  }};
    padding-top: ${(props) => {
    if (!props.open && !props.isFocused && props.collapsed) {
      return 0;
    } else if (props.disabled) {
      return '28px';
    }
    return '27px';
  }};

    textarea {
      padding: ${(props) => {
    if ((props.error || props.isFocused || props.open) && !props.disabled) {
      return '0 15px';
    } else {
      return '0 16px';
    }
  }};
    }

    label {
      left: ${(props) => {
    if (props.disabled) {
      return '16px';
    }
    return '15px';
  }};
      top: ${(props) => {
    if (props.disabled) {
      return '0';
    }
    return '-1px';
  }};
    }
  }

  ${(props) => {
    if (props.disabled) {
      return `
        background-color: ${colors.black05};
        label {
          color: ${colors.black40};
        }
      `;
     }
  }}
  `;

const Textarea = styled.textarea`
background-color: transparent;
border: none;
color: ${(props) => props.theme.valueColor};
box-sizing: border-box;
height: 100%;
padding: ${(props) => {
    if (props.error || props.isFocused) {
      return '0 15px';
    } else {
      return '0 16px';
    }
  }};
resize: none;
text-align: left;
width: 100%;

  &:focus {
  outline: 0;
  padding: 0 15px;
}
${typography.subhead1}
${darkScrollbar}

  &::-webkit-input-placeholder {
    color: ${colors.black40};
  }
`;

const TextLabel = styled.label`
color: ${(props) => {
    if (props.error) {
      return colors.red;
    } else if (props.isFocused) {
      return colors.green;
    } else if (props.labelColor) {
      return props.labelColor;
    } else {
      return props.theme.labelColor;
    }
  }};
top: ${(props) => {
    if (props.error || props.isFocused || props.placeholder) {
      return '-1px';
    }
    return '0';
  }};;
left: ${(props) => {
    if (props.error || props.isFocused || props.placeholder) {
      return '15px';
    }
    return '16px';
  }};
position: absolute;
transform: ${(props) => {
    if (props.open || props.isFocused || props.placeholder) {
      return 'translateY(8px)';
    } else {
      return 'translateY(16px)';
    }
  }};
transition: font-size 0.14s ease-in-out, transform 0.14s ease-in-out, color 0.14s ease-in-out;
${(props) => {
    if (props.open || props.isFocused || props.placeholder) {
      return typography.caption
    } else {
      return typography.subhead1
    }
  }}
line-height: 16px;
`;

const charCountTextWidth = '110px';

export const CharCounterText = styled.div`
${typography.caption}
color: ${colors.green};
text-align: right;
width: ${charCountTextWidth};
`;

export const CharCounterErrorText = styled(CharCounterText)`
color: ${colors.red};
`;

export const FooterTextContainer = styled.div`
  color: ${colors.black40};
  padding-top: 4px;
  ${typography.caption}
  display: flex;
  justify-content: space-between;
`;

export const HelperTextContainer = styled.div`
  width:${props => props.hasCharLimit ? `calc(100% - ${charCountTextWidth})` : '100%'};
`;

export const HelperText = styled.span`
  color: ${props => props.theme.helperColor};
  ${typography.caption}
`;

const HelperErrorText = styled(HelperText)`
  color: ${colors.red};
`;

/**
 * Indicates if the string value has exceeded the char limit
 * @param {number} charLimit
 * @param {string} value
 */
export function charLimitExceeded(charLimit, value) {
  if (charLimit === 0 || size(value) === 0) {
    return false;
  }
  return size(value) > charLimit;
}

/**
 * Returns the char counter text string
 * @param {number} charLimit
 * @param {string} value
 */
export function determineCharCounterTextValue(charLimit, value) {
  if (!charLimit) return null;

  return `${size(value)} / ${charLimit}`;
}

export const ErrorTextContainer = (props) => {
  const { charLimit, error, localError } = props;
  return (
    <HelperTextContainer hasCharLimit={charLimit > 0}>
      {(error || localError) &&
        <HelperErrorText>{error || localError}</HelperErrorText>}
    </HelperTextContainer>
  );
};

export const TextareaHelper = (props) => {
  const { hasCharLimit, helper } = props;
  return (
    <HelperTextContainer hasCharLimit={hasCharLimit}>
      <HelperText>{helper}</HelperText>
    </HelperTextContainer>
  );
};

export const CharLimitExceededError = 'Character limit exceeded';

class TextareaInput extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      focused: false
    };
  }

  componentDidMount() {
    const {value} = this.props;

    if (value) {
      this.setState({
        value
      });
    }
  }

  focused = () => {
    this.setState({
      focused: true
    })
  }

  blurred = () => {
    if(!this.state.cancelBlur) {
      this.setState({
        focused: false
      });
    }
  }

  renderCharCounterText = () => {
    const inputValue = get(this.state, 'value', get(this.props, 'value', ''));
    const { charLimit } = this.props;
    if (!charLimit) return null;

    const charTextValue = determineCharCounterTextValue(charLimit, inputValue);

    if (charLimitExceeded(charLimit, inputValue)) {
      return (
        <CharCounterErrorText>{charTextValue}</CharCounterErrorText>
      );
    }

    return (
      <CharCounterText>{charTextValue}</CharCounterText>
    );
  };

  renderFooterText = () => {
    return (
      <FooterTextContainer>
        {this.renderHelperText()}
        {this.renderCharCounterText()}
      </FooterTextContainer>
    );
  };

  renderErrorText = () => {
    const { charLimit, error } = this.props;
    const localError = this.determineLocalError();
    return <ErrorTextContainer localError={localError} charLimit={charLimit} error={error} />;
  };

  determineLocalError = () => {
    const { charLimit } = this.props;
    const value = get(this.state, 'value', get(this.props, 'value', ''));
    if (charLimitExceeded(charLimit, value)) {
      return CharLimitExceededError;
    }
    return '';
  };

  renderHelperText = () => {
    const { error, helper, collapsed, charLimit } = this.props;
    const localError = this.determineLocalError();

    if (collapsed && !this.state.value && !this.state.focused && !(error || localError || helper)) {
      return null;
    }

    if (error || localError) {
      return this.renderErrorText();
    }

    return <TextareaHelper hasCharLimit={charLimit > 0} helper={helper} />;
  }

  focusOnTextarea = () => {
    if (this.textareaInput !== document.activeElement) {
      this.textareaInput.focus();
    }
  }

  cancelBlur = (e) => {
    this.setState({
      cancelBlur: true
    });
  }

  removeCancelBlur = () => {
    this.setState({
      cancelBlur: false
    });
  }

  onChange = (e) => {
    if (e) {
      e.preventDefault();
    }

    this.setState({
      value: get(e, 'target.value', this.textareaInput.value)
    }, () => {
      if (this.props.onChange) {
        this.props.onChange(this.state.value);
      }
    });
  }

  setValue = (value) => {
    this.setState({ value });
  };

  render() {
    const { className, label, name, error, disabled, collapsed, labelColor, lineColor, placeholder } = this.props;
    const localError = this.determineLocalError();

    return (
      <ThemeProvider theme={this.props.theme}>
      <TextareaInputWrapper className={className}>
        <TextareaBox
          onMouseUp={this.removeCancelBlur}
          onMouseDown={this.cancelBlur}
          onMouseLeave={this.removeCancelBlur}
          onClick={this.focusOnTextarea}
          lineColor={lineColor}
          isFocused={this.state.focused}
          error={error || localError}
          open={this.state.value}
          disabled={disabled}
          collapsed={collapsed}>
          <Textarea
            onFocus={this.focused}
            onBlur={this.blurred}
            id={name}
            name={name}
            disabled={disabled}
            error={error || localError}
            value={this.state.value}
            ref={(input) => { this.textareaInput = ReactDOM.findDOMNode(input); }}
            onChange={this.onChange}
            placeholder={placeholder}>
          </Textarea>
          <TextLabel
            isFocused={this.state.focused}
            labelColor={labelColor}
            open={this.state.value}
            htmlFor={name}
            error={error || localError}
            placeholder={placeholder}>
            {label}
          </TextLabel>
        </TextareaBox>
        {this.renderFooterText()}
      </TextareaInputWrapper>
      </ThemeProvider>
    );
  }
}

TextareaInput.defaultProps = {
  name: 'Name',
  label: 'Label',
  charLimit: 0,
  error: '',
  placeholder: '',
  theme: defaultTheme,
  overrideValue: null
};

TextareaInput.propTypes = {
  name: PropTypes.string.isRequired,
  label: PropTypes.string.isRequired,
  helper: PropTypes.string,
  error: PropTypes.string,
  disabled: PropTypes.bool,
  value: PropTypes.string,
  overrideValue: PropTypes.string,
  onChange: PropTypes.func,
  collapsed: PropTypes.bool,
  charLimit: PropTypes.number,
  placeholder: PropTypes.string,
  theme: PropTypes.object
};

export default TextareaInput;
<|endoftext|>


<commit_before>(function () {
    var Module = {};

    var isSupported = Module.isSupported = function () {
        return typeof(window.Notification) === 'function';
    };

    var hasPermission = Module.hasPermission = function () {
        return Notification.permission === 'granted';
    };

    var getPermission = Module.getPermission = function (f) {
        Notification.requestPermission(function (permission) {
            if (permission === "granted") { f(true); }
            else { f(false); }
        });
    };

    var create = Module.create = function (msg, title) {
        return new Notification(title,{
            // icon: icon,
            body: msg,
        });
    };

    Module.system = function (msg, title, icon) {
        // Let's check if the browser supports notifications
        if (!isSupported()) { console.log("Notifications are not supported"); }

        // Let's check whether notification permissions have already been granted
        else if (hasPermission()) {
            // If it's okay let's create a notification
            return create(msg, title, icon);
        }

        // Otherwise, we need to ask the user for permission
        else if (Notification.permission !== 'denied') {
            getPermission(function (state) {
                if (state) { create(msg, title, icon); }
            });
        }
    };

    var DEFAULT_MAIN = '/customize/main-favicon.png';
    var DEFAULT_ALT = '/customize/alt-favicon.png';

    var createFavicon = function () {
        console.log("creating favicon");
        var fav = document.createElement('link');
        var attrs = {
            id: 'favicon',
            type: 'image/png',
            rel: 'icon',
            'data-main-favicon': DEFAULT_MAIN,
            'data-alt-favicon': DEFAULT_ALT,
            href: DEFAULT_MAIN,
        };
        Object.keys(attrs).forEach(function (k) {
            fav.setAttribute(k, attrs[k]);
        });
        document.head.appendChild(fav);
    };

    if (!document.getElementById('favicon')) { createFavicon(); }

    Module.tab = function (frequency, count) {
        var key = '_pendingTabNotification';

        var favicon = document.getElementById('favicon');

        var main = DEFAULT_MAIN;
        var alt = DEFAULT_ALT;

        if (favicon) {
            main = favicon.getAttribute('data-main-favicon') || DEFAULT_MAIN;
            alt = favicon.getAttribute('data-alt-favicon') || DEFAULT_ALT;
            favicon.setAttribute('href', main);
        }

        var cancel = function (pending) {
            // only run one tab notification at a time
            if (Module[key]) {
                window.clearInterval(Module[key]);
                if (favicon) {
                    favicon.setAttribute('href', pending? alt : main);
                }

                return true;
            }
            return false;
        };

        cancel();

        var step = function () {
            if (favicon) {
                favicon.setAttribute('href', favicon.getAttribute('href') === main? alt : main);
            }
            --count;
        };

        Module[key] = window.setInterval(function () {
            if (count > 0) { return step(); }
            cancel(true);

        }, frequency);
        step();

        return {
            cancel: cancel,
        };
    };

    if (typeof(module) !== 'undefined' && module.exports) {
        module.exports = Module;
    } else if ((typeof(define) !== 'undefined' && define !== null) && (define.amd !== null)) {
        define(function () {
            return Module;
        });
    } else {
        window.Visible = Module;
    }
}());
<commit_msg>fix caching on favicon<commit_after>define(['/api/config'], function (ApiConfig) {
    var Module = {};

    var isSupported = Module.isSupported = function () {
        return typeof(window.Notification) === 'function';
    };

    var hasPermission = Module.hasPermission = function () {
        return Notification.permission === 'granted';
    };

    var getPermission = Module.getPermission = function (f) {
        Notification.requestPermission(function (permission) {
            if (permission === "granted") { f(true); }
            else { f(false); }
        });
    };

    var create = Module.create = function (msg, title) {
        return new Notification(title,{
            // icon: icon,
            body: msg,
        });
    };

    Module.system = function (msg, title, icon) {
        // Let's check if the browser supports notifications
        if (!isSupported()) { console.log("Notifications are not supported"); }

        // Let's check whether notification permissions have already been granted
        else if (hasPermission()) {
            // If it's okay let's create a notification
            return create(msg, title, icon);
        }

        // Otherwise, we need to ask the user for permission
        else if (Notification.permission !== 'denied') {
            getPermission(function (state) {
                if (state) { create(msg, title, icon); }
            });
        }
    };

    var DEFAULT_MAIN = '/customize/main-favicon.png?' + ApiConfig.requireConf.urlArgs;
    var DEFAULT_ALT = '/customize/alt-favicon.png?' + ApiConfig.requireConf.urlArgs;

    var createFavicon = function () {
        console.log("creating favicon");
        var fav = document.createElement('link');
        var attrs = {
            id: 'favicon',
            type: 'image/png',
            rel: 'icon',
            'data-main-favicon': DEFAULT_MAIN,
            'data-alt-favicon': DEFAULT_ALT,
            href: DEFAULT_MAIN,
        };
        Object.keys(attrs).forEach(function (k) {
            fav.setAttribute(k, attrs[k]);
        });
        document.head.appendChild(fav);
    };

    if (!document.getElementById('favicon')) { createFavicon(); }

    Module.tab = function (frequency, count) {
        var key = '_pendingTabNotification';

        var favicon = document.getElementById('favicon');

        var main = DEFAULT_MAIN;
        var alt = DEFAULT_ALT;

        if (favicon) {
            main = favicon.getAttribute('data-main-favicon') || DEFAULT_MAIN;
            alt = favicon.getAttribute('data-alt-favicon') || DEFAULT_ALT;
            favicon.setAttribute('href', main);
        }

        var cancel = function (pending) {
            // only run one tab notification at a time
            if (Module[key]) {
                window.clearInterval(Module[key]);
                if (favicon) {
                    favicon.setAttribute('href', pending? alt : main);
                }

                return true;
            }
            return false;
        };

        cancel();

        var step = function () {
            if (favicon) {
                favicon.setAttribute('href', favicon.getAttribute('href') === main? alt : main);
            }
            --count;
        };

        Module[key] = window.setInterval(function () {
            if (count > 0) { return step(); }
            cancel(true);

        }, frequency);
        step();

        return {
            cancel: cancel,
        };
    };

    return Module;
});<|endoftext|>


<commit_before>var _        = require('lodash');
var should   = require('should');
var helper   = require('../support/spec_helper');
var async    = require('async');
var ORM      = require('../../');

describe("Hook", function() {
	var db = null;
	var Person = null;
	var triggeredHooks = {};
	var getTimestamp; // Calling it 'getTime' causes strangeness.

	if (process.hrtime) {
		getTimestamp = function () { return parseFloat(process.hrtime().join('.')); };
	} else {
		getTimestamp = function () { return Date.now(); };
	}

	var checkHook = function (hook) {
		triggeredHooks[hook] = false;

		return function () {
			triggeredHooks[hook] = getTimestamp();
		};
	};

	var setup = function (hooks) {
		if (typeof hooks == "undefined") {
			hooks = {
				afterCreate      : checkHook("afterCreate"),
				beforeCreate     : checkHook("beforeCreate"),
				afterSave        : checkHook("afterSave"),
				beforeSave       : checkHook("beforeSave"),
				beforeValidation : checkHook("beforeValidation"),
				beforeRemove     : checkHook("beforeRemove"),
				afterRemove      : checkHook("afterRemove")
			};
		}

		return function (done) {
			Person = db.define("person", {
				name   : String
			}, {
				hooks  : hooks
			});

			Person.settings.set("instance.returnAllErrors", false);

			return helper.dropSync(Person, done);
		};
	};

	before(function (done) {
		helper.connect(function (connection) {
			db = connection;

			return done();
		});
	});

	after(function () {
		return db.close();
	});

	// there are a lot of timeouts in this suite and Travis or other test runners can
	// have hickups that could force this suite to timeout to the default value (2 secs)
	this.timeout(30000);

	describe("after Model creation", function () {
		before(setup({}));

		it("can be changed", function (done) {
			var triggered = false;

			Person.afterCreate(function () {
				triggered = true;
			});
			Person.create([{ name: "John Doe" }], function () {
				triggered.should.be.true;

				return done();
			});
		});

		it("can be removed", function (done) {
			var triggered = false;

			Person.afterCreate(function () {
				triggered = true;
			});
			Person.create([{ name: "John Doe" }], function () {
				triggered.should.be.true;

				triggered = false;

				Person.afterCreate(); // clears hook

				Person.create([{ name: "Jane Doe" }], function () {
					triggered.should.be.false;

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

	describe("beforeCreate", function () {
		before(setup());

		it("should trigger before creating instance", function (done) {
			Person.create([{ name: "John Doe" }], function () {
				triggeredHooks.afterCreate.should.be.a("number");
				triggeredHooks.beforeCreate.should.be.a("number");
				triggeredHooks.beforeCreate.should.not.be.above(triggeredHooks.afterCreate);

				return done();
			});
		});

		describe("when setting properties", function () {
			before(setup({
				beforeCreate : function () {
					this.name = "Jane Doe";
				}
			}));

			it("should not be discarded", function (done) {
				Person.create([{ }], function (err, items) {
					should.equal(err, null);

					items.should.be.a("object");
					items.should.have.property("length", 1);
					items[0].name.should.equal("Jane Doe");

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

		describe("if hook method has 1 argument", function () {
			var beforeCreate = false;

			before(setup({
				beforeCreate : function (next) {
					setTimeout(function () {
						beforeCreate = true;

						return next();
					}.bind(this), 200);
				}
			}));

			it("should wait for hook to finish", function (done) {
				this.timeout(500);

				Person.create([{ name: "John Doe" }], function () {
					beforeCreate.should.be.true;

					return done();
				});
			});

			describe("if hook triggers error", function () {
				before(setup({
					beforeCreate : function (next) {
						setTimeout(function () {
							return next(new Error('beforeCreate-error'));
						}, 200);
					}
				}));

				it("should trigger error", function (done) {
					this.timeout(500);

					Person.create([{ name: "John Doe" }], function (err) {
						err.should.be.a("object");
						err.message.should.equal("beforeCreate-error");

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

	describe("afterCreate", function () {
		before(setup());

		it("should trigger after creating instance", function (done) {
			Person.create([{ name: "John Doe" }], function () {
				triggeredHooks.afterCreate.should.be.a("number");
				triggeredHooks.beforeCreate.should.be.a("number");
				triggeredHooks.afterCreate.should.not.be.below(triggeredHooks.beforeCreate);

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

	describe("beforeSave", function () {
		before(setup());

		it("should trigger before saving an instance", function (done) {
			Person.create([{ name: "John Doe" }], function () {
				triggeredHooks.afterSave.should.be.a("number");
				triggeredHooks.beforeSave.should.be.a("number");
				triggeredHooks.beforeSave.should.not.be.above(triggeredHooks.afterSave);

				return done();
			});
		});

		describe("if hook method has 1 argument", function () {
			var beforeSave = false;

			before(setup({
				beforeSave : function (next) {
					setTimeout(function () {
						beforeSave = true;

						return next();
					}.bind(this), 200);
				}
			}));

			it("should wait for hook to finish", function (done) {
				this.timeout(500);

				Person.create([{ name: "John Doe" }], function () {
					beforeSave.should.be.true;

					return done();
				});

			});

			describe("if hook triggers error", function () {
				before(setup({
					beforeSave : function (next) {
						if (this.name == "John Doe") {
							return next();
						}
						setTimeout(function () {
							return next(new Error('beforeSave-error'));
						}, 200);
					}
				}));

				it("should trigger error when creating", function (done) {
					this.timeout(500);

					Person.create([{ name: "Jane Doe" }], function (err) {
						err.should.be.a("object");
						err.message.should.equal("beforeSave-error");

						return done();
					});
				});

				it("should trigger error when saving", function (done) {
					this.timeout(500);

					Person.create([{ name: "John Doe" }], function (err, John) {
						should.equal(err, null);

						John[0].name = "Jane Doe";
						John[0].save(function (err) {
							err.should.be.a("object");
							err.message.should.equal("beforeSave-error");

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

	describe("afterSave", function () {
		before(setup());

		it("should trigger after saving an instance", function (done) {
			Person.create([{ name: "John Doe" }], function () {
				triggeredHooks.afterSave.should.be.a("number");
				triggeredHooks.beforeSave.should.be.a("number");
				triggeredHooks.afterSave.should.not.be.below(triggeredHooks.beforeSave);

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

	describe("beforeValidation", function () {
		before(setup());

		it("should trigger before instance validation", function (done) {
			Person.create([{ name: "John Doe" }], function () {
				triggeredHooks.beforeValidation.should.be.a("number");
				triggeredHooks.beforeCreate.should.be.a("number");
				triggeredHooks.beforeSave.should.be.a("number");
				triggeredHooks.beforeValidation.should.not.be.above(triggeredHooks.beforeCreate);
				triggeredHooks.beforeValidation.should.not.be.above(triggeredHooks.beforeSave);

				return done();
			});
		});

		describe("if hook method has 1 argument", function () {
			var beforeValidation = false;
			this.timeout(500);

			before(setup({
				beforeValidation : function (next) {
					setTimeout(function () {
						beforeValidation = true;

						if (!this.name) return next("Name is missing");

						return next();
					}.bind(this), 200);
				}
			}));

			beforeEach(function () {
				beforeValidation = false;
			});

			it("should wait for hook to finish", function (done) {
				Person.create([{ name: "John Doe" }], function () {
					beforeValidation.should.be.true;

					return done();
				});
			});

			it("should trigger error if hook passes an error", function (done) {
				Person.create([{ name: "" }], function (err) {
					beforeValidation.should.be.true;

					err.should.equal("Name is missing");

					return done();
				});
			});

			it("should trigger when calling #validate", function (done) {
				var person = new Person();

				person.validate(function (err, validationErrors) {
					beforeValidation.should.be.true;

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

	describe("afterLoad", function () {
		var afterLoad = false;

		before(setup({
			afterLoad: function () {
				afterLoad = true;
			}
		}));

		it("should trigger when defining a model", function (done) {
			var John = new Person({ name: "John" });

			afterLoad.should.be.true;

			return done();
		});

		describe("if hook method has 1 argument", function () {
			var afterLoad = false;

			before(setup({
				afterLoad : function (next) {
					setTimeout(function () {
						afterLoad = true;

						return next();
					}.bind(this), 200);
				}
			}));

			it("should wait for hook to finish", function (done) {
				this.timeout(500);

				Person.create([{ name: "John Doe" }], function (err, items) {
					afterLoad.should.be.true;

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

	describe("afterAutoFetch", function () {
		var afterAutoFetch = false;

		before(setup({
			afterAutoFetch: function () {
				afterAutoFetch = true;
			}
		}));

		it("should trigger when defining a model", function (done) {
			var John = new Person({ name: "John" });

			afterAutoFetch.should.be.true;

			return done();
		});

		describe("if hook method has 1 argument", function () {
			var afterAutoFetch = false;

			before(setup({
				afterAutoFetch : function (next) {
					setTimeout(function () {
						afterAutoFetch = true;

						return next();
					}.bind(this), 200);
				}
			}));

			it("should wait for hook to finish", function (done) {
				this.timeout(500);

				Person.create([{ name: "John Doe" }], function (err, items) {
					afterAutoFetch.should.be.true;

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

	describe("beforeRemove", function () {
		before(setup());

		it("should trigger before removing an instance", function (done) {
			Person.create([{ name: "John Doe" }], function (err, items) {
				items[0].remove(function () {
					triggeredHooks.afterRemove.should.be.a("number");
					triggeredHooks.beforeRemove.should.be.a("number");
					triggeredHooks.beforeRemove.should.not.be.above(triggeredHooks.afterRemove);

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

		describe("if hook method has 1 argument", function () {
			var beforeRemove = false;

			before(setup({
				beforeRemove : function (next) {
					setTimeout(function () {
						beforeRemove = true;

						return next();
					}.bind(this), 200);
				}
			}));

			it("should wait for hook to finish", function (done) {
				this.timeout(500);

				Person.create([{ name: "John Doe" }], function (err, items) {
					items[0].remove(function () {
						beforeRemove.should.be.true;

						return done();
					});
				});

			});

			describe("if hook triggers error", function () {
				before(setup({
					beforeRemove : function (next) {
						setTimeout(function () {
							return next(new Error('beforeRemove-error'));
						}, 200);
					}
				}));

				it("should trigger error", function (done) {
					this.timeout(500);

					Person.create([{ name: "John Doe" }], function (err, items) {
						items[0].remove(function (err) {
							err.should.be.a("object");
							err.message.should.equal("beforeRemove-error");

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

	describe("afterRemove", function () {
		before(setup());

		it("should trigger after removing an instance", function (done) {
			Person.create([{ name: "John Doe" }], function (err, items) {
				items[0].remove(function () {
					triggeredHooks.afterRemove.should.be.a("number");
					triggeredHooks.beforeRemove.should.be.a("number");
					triggeredHooks.afterRemove.should.not.be.below(triggeredHooks.beforeRemove);

					return done();
				});
			});
		});
	});
});
<commit_msg>Disabled usage of process.hrtime() in hook test<commit_after>var _        = require('lodash');
var should   = require('should');
var helper   = require('../support/spec_helper');
var async    = require('async');
var ORM      = require('../../');

describe("Hook", function() {
	var db = null;
	var Person = null;
	var triggeredHooks = {};
	var getTimestamp; // Calling it 'getTime' causes strangeness.

	getTimestamp = function () { return Date.now(); };
	// this next lines are failing...
	// if (process.hrtime) {
	// 	getTimestamp = function () { return parseFloat(process.hrtime().join('.')); };
	// } else {
	// 	getTimestamp = function () { return Date.now(); };
	// }

	var checkHook = function (hook) {
		triggeredHooks[hook] = false;

		return function () {
			triggeredHooks[hook] = getTimestamp();
		};
	};

	var setup = function (hooks) {
		if (typeof hooks == "undefined") {
			hooks = {
				afterCreate      : checkHook("afterCreate"),
				beforeCreate     : checkHook("beforeCreate"),
				afterSave        : checkHook("afterSave"),
				beforeSave       : checkHook("beforeSave"),
				beforeValidation : checkHook("beforeValidation"),
				beforeRemove     : checkHook("beforeRemove"),
				afterRemove      : checkHook("afterRemove")
			};
		}

		return function (done) {
			Person = db.define("person", {
				name   : String
			}, {
				hooks  : hooks
			});

			Person.settings.set("instance.returnAllErrors", false);

			return helper.dropSync(Person, done);
		};
	};

	before(function (done) {
		helper.connect(function (connection) {
			db = connection;

			return done();
		});
	});

	after(function () {
		return db.close();
	});

	// there are a lot of timeouts in this suite and Travis or other test runners can
	// have hickups that could force this suite to timeout to the default value (2 secs)
	this.timeout(30000);

	describe("after Model creation", function () {
		before(setup({}));

		it("can be changed", function (done) {
			var triggered = false;

			Person.afterCreate(function () {
				triggered = true;
			});
			Person.create([{ name: "John Doe" }], function () {
				triggered.should.be.true;

				return done();
			});
		});

		it("can be removed", function (done) {
			var triggered = false;

			Person.afterCreate(function () {
				triggered = true;
			});
			Person.create([{ name: "John Doe" }], function () {
				triggered.should.be.true;

				triggered = false;

				Person.afterCreate(); // clears hook

				Person.create([{ name: "Jane Doe" }], function () {
					triggered.should.be.false;

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

	describe("beforeCreate", function () {
		before(setup());

		it("should trigger before creating instance", function (done) {
			Person.create([{ name: "John Doe" }], function () {
				triggeredHooks.afterCreate.should.be.a("number");
				triggeredHooks.beforeCreate.should.be.a("number");
				triggeredHooks.beforeCreate.should.not.be.above(triggeredHooks.afterCreate);

				return done();
			});
		});

		describe("when setting properties", function () {
			before(setup({
				beforeCreate : function () {
					this.name = "Jane Doe";
				}
			}));

			it("should not be discarded", function (done) {
				Person.create([{ }], function (err, items) {
					should.equal(err, null);

					items.should.be.a("object");
					items.should.have.property("length", 1);
					items[0].name.should.equal("Jane Doe");

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

		describe("if hook method has 1 argument", function () {
			var beforeCreate = false;

			before(setup({
				beforeCreate : function (next) {
					setTimeout(function () {
						beforeCreate = true;

						return next();
					}.bind(this), 200);
				}
			}));

			it("should wait for hook to finish", function (done) {
				this.timeout(500);

				Person.create([{ name: "John Doe" }], function () {
					beforeCreate.should.be.true;

					return done();
				});
			});

			describe("if hook triggers error", function () {
				before(setup({
					beforeCreate : function (next) {
						setTimeout(function () {
							return next(new Error('beforeCreate-error'));
						}, 200);
					}
				}));

				it("should trigger error", function (done) {
					this.timeout(500);

					Person.create([{ name: "John Doe" }], function (err) {
						err.should.be.a("object");
						err.message.should.equal("beforeCreate-error");

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

	describe("afterCreate", function () {
		before(setup());

		it("should trigger after creating instance", function (done) {
			Person.create([{ name: "John Doe" }], function () {
				triggeredHooks.afterCreate.should.be.a("number");
				triggeredHooks.beforeCreate.should.be.a("number");
				triggeredHooks.afterCreate.should.not.be.below(triggeredHooks.beforeCreate);

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

	describe("beforeSave", function () {
		before(setup());

		it("should trigger before saving an instance", function (done) {
			Person.create([{ name: "John Doe" }], function () {
				triggeredHooks.afterSave.should.be.a("number");
				triggeredHooks.beforeSave.should.be.a("number");
				triggeredHooks.beforeSave.should.not.be.above(triggeredHooks.afterSave);

				return done();
			});
		});

		describe("if hook method has 1 argument", function () {
			var beforeSave = false;

			before(setup({
				beforeSave : function (next) {
					setTimeout(function () {
						beforeSave = true;

						return next();
					}.bind(this), 200);
				}
			}));

			it("should wait for hook to finish", function (done) {
				this.timeout(500);

				Person.create([{ name: "John Doe" }], function () {
					beforeSave.should.be.true;

					return done();
				});

			});

			describe("if hook triggers error", function () {
				before(setup({
					beforeSave : function (next) {
						if (this.name == "John Doe") {
							return next();
						}
						setTimeout(function () {
							return next(new Error('beforeSave-error'));
						}, 200);
					}
				}));

				it("should trigger error when creating", function (done) {
					this.timeout(500);

					Person.create([{ name: "Jane Doe" }], function (err) {
						err.should.be.a("object");
						err.message.should.equal("beforeSave-error");

						return done();
					});
				});

				it("should trigger error when saving", function (done) {
					this.timeout(500);

					Person.create([{ name: "John Doe" }], function (err, John) {
						should.equal(err, null);

						John[0].name = "Jane Doe";
						John[0].save(function (err) {
							err.should.be.a("object");
							err.message.should.equal("beforeSave-error");

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

	describe("afterSave", function () {
		before(setup());

		it("should trigger after saving an instance", function (done) {
			Person.create([{ name: "John Doe" }], function () {
				triggeredHooks.afterSave.should.be.a("number");
				triggeredHooks.beforeSave.should.be.a("number");
				triggeredHooks.afterSave.should.not.be.below(triggeredHooks.beforeSave);

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

	describe("beforeValidation", function () {
		before(setup());

		it("should trigger before instance validation", function (done) {
			Person.create([{ name: "John Doe" }], function () {
				triggeredHooks.beforeValidation.should.be.a("number");
				triggeredHooks.beforeCreate.should.be.a("number");
				triggeredHooks.beforeSave.should.be.a("number");
				triggeredHooks.beforeValidation.should.not.be.above(triggeredHooks.beforeCreate);
				triggeredHooks.beforeValidation.should.not.be.above(triggeredHooks.beforeSave);

				return done();
			});
		});

		describe("if hook method has 1 argument", function () {
			var beforeValidation = false;
			this.timeout(500);

			before(setup({
				beforeValidation : function (next) {
					setTimeout(function () {
						beforeValidation = true;

						if (!this.name) return next("Name is missing");

						return next();
					}.bind(this), 200);
				}
			}));

			beforeEach(function () {
				beforeValidation = false;
			});

			it("should wait for hook to finish", function (done) {
				Person.create([{ name: "John Doe" }], function () {
					beforeValidation.should.be.true;

					return done();
				});
			});

			it("should trigger error if hook passes an error", function (done) {
				Person.create([{ name: "" }], function (err) {
					beforeValidation.should.be.true;

					err.should.equal("Name is missing");

					return done();
				});
			});

			it("should trigger when calling #validate", function (done) {
				var person = new Person();

				person.validate(function (err, validationErrors) {
					beforeValidation.should.be.true;

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

	describe("afterLoad", function () {
		var afterLoad = false;

		before(setup({
			afterLoad: function () {
				afterLoad = true;
			}
		}));

		it("should trigger when defining a model", function (done) {
			var John = new Person({ name: "John" });

			afterLoad.should.be.true;

			return done();
		});

		describe("if hook method has 1 argument", function () {
			var afterLoad = false;

			before(setup({
				afterLoad : function (next) {
					setTimeout(function () {
						afterLoad = true;

						return next();
					}.bind(this), 200);
				}
			}));

			it("should wait for hook to finish", function (done) {
				this.timeout(500);

				Person.create([{ name: "John Doe" }], function (err, items) {
					afterLoad.should.be.true;

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

	describe("afterAutoFetch", function () {
		var afterAutoFetch = false;

		before(setup({
			afterAutoFetch: function () {
				afterAutoFetch = true;
			}
		}));

		it("should trigger when defining a model", function (done) {
			var John = new Person({ name: "John" });

			afterAutoFetch.should.be.true;

			return done();
		});

		describe("if hook method has 1 argument", function () {
			var afterAutoFetch = false;

			before(setup({
				afterAutoFetch : function (next) {
					setTimeout(function () {
						afterAutoFetch = true;

						return next();
					}.bind(this), 200);
				}
			}));

			it("should wait for hook to finish", function (done) {
				this.timeout(500);

				Person.create([{ name: "John Doe" }], function (err, items) {
					afterAutoFetch.should.be.true;

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

	describe("beforeRemove", function () {
		before(setup());

		it("should trigger before removing an instance", function (done) {
			Person.create([{ name: "John Doe" }], function (err, items) {
				items[0].remove(function () {
					triggeredHooks.afterRemove.should.be.a("number");
					triggeredHooks.beforeRemove.should.be.a("number");
					triggeredHooks.beforeRemove.should.not.be.above(triggeredHooks.afterRemove);

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

		describe("if hook method has 1 argument", function () {
			var beforeRemove = false;

			before(setup({
				beforeRemove : function (next) {
					setTimeout(function () {
						beforeRemove = true;

						return next();
					}.bind(this), 200);
				}
			}));

			it("should wait for hook to finish", function (done) {
				this.timeout(500);

				Person.create([{ name: "John Doe" }], function (err, items) {
					items[0].remove(function () {
						beforeRemove.should.be.true;

						return done();
					});
				});

			});

			describe("if hook triggers error", function () {
				before(setup({
					beforeRemove : function (next) {
						setTimeout(function () {
							return next(new Error('beforeRemove-error'));
						}, 200);
					}
				}));

				it("should trigger error", function (done) {
					this.timeout(500);

					Person.create([{ name: "John Doe" }], function (err, items) {
						items[0].remove(function (err) {
							err.should.be.a("object");
							err.message.should.equal("beforeRemove-error");

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

	describe("afterRemove", function () {
		before(setup());

		it("should trigger after removing an instance", function (done) {
			Person.create([{ name: "John Doe" }], function (err, items) {
				items[0].remove(function () {
					triggeredHooks.afterRemove.should.be.a("number");
					triggeredHooks.beforeRemove.should.be.a("number");
					triggeredHooks.afterRemove.should.not.be.below(triggeredHooks.beforeRemove);

					return done();
				});
			});
		});
	});
});
<|endoftext|>