<commit_before>
var Analytics = require('analytics.js').constructor;
var integration = require('analytics.js-integration');
var sandbox = require('clear-env');
var tester = require('analytics.js-integration-tester');
var HubSpot = require('../lib/');

describe('HubSpot', function() {
  var analytics;
  var hubspot;
  var options = {
    portalId: 62515
  };

  beforeEach(function() {
    analytics = new Analytics();
    hubspot = new HubSpot(options);
    analytics.use(HubSpot);
    analytics.use(tester);
    analytics.add(hubspot);
  });

  afterEach(function() {
    analytics.restore();
    analytics.reset();
    hubspot.reset();
    sandbox();
  });

  it('should have the right settings', function() {
    analytics.compare(HubSpot, integration('HubSpot')
      .assumesPageview()
      .global('_hsq')
      .option('portalId', null));
  });

  describe('before loading', function() {
    beforeEach(function() {
      analytics.stub(hubspot, 'load');
    });

    describe('#initialize', function() {
      it('should create window._hsq', function() {
        analytics.assert(!window._hsq);
        analytics.initialize();
        analytics.page();
        analytics.assert(window._hsq instanceof Array);
      });
    });
  });

  describe('loading', function() {
    it('should load', function(done) {
      analytics.load(hubspot, done);
    });
  });

  describe('after loading', function() {
    beforeEach(function(done) {
      analytics.once('ready', done);
      analytics.initialize();
      analytics.page();
    });

    describe('#identify', function() {
      beforeEach(function() {
        analytics.stub(window._hsq, 'push');
      });

      it('should not send traits without an email', function() {
        analytics.identify('id');
        analytics.didNotCall(window._hsq.push);
      });

      it('should send traits with an email', function() {
        analytics.identify({ email: 'name@example.com' });
        analytics.called(window._hsq.push, ['identify', { email: 'name@example.com' }]);
      });

      it('should send an id and traits with an email', function() {
        analytics.identify('id', { email: 'name@example.com' });
        analytics.called(window._hsq.push, ['identify', {
          id: 'id',
          email: 'name@example.com'
        }]);
      });

      it('should convert dates to milliseconds', function() {
        var date = new Date();
        analytics.identify({
          email: 'name@example.com',
          date: date
        });
        analytics.called(window._hsq.push, ['identify', {
          email: 'name@example.com',
          date: date.getTime()
        }]);
      });
    });

    describe('#track', function() {
      beforeEach(function() {
        analytics.stub(window._hsq, 'push');
      });

      it('should send an event', function() {
        analytics.track('event');
        analytics.called(window._hsq.push, ['trackEvent', 'event', { id: 'event' }]);
      });

      it('should send an event and properties', function() {
        analytics.track('event', { property: true });
        analytics.called(window._hsq.push, ['trackEvent', 'event', { property: true, id: 'event' }]);
      });

      it('should convert dates to milliseconds', function() {
        var date = new Date();
        var ms = date.getTime();

        analytics.track('event', { date: date });
        analytics.called(window._hsq.push, ['trackEvent', 'event', { date: ms, id: 'event' }]);
      });

      it('should attach track.event to properties.id', function() {
        analytics.track('Viewed Product', {});
        analytics.called(window._hsq.push, ['trackEvent', 'Viewed Product', { id: 'Viewed Product' }]);
      });

      it('should move properties.id to properties._id', function() {
        analytics.track('Viewed Product', { id: '12345' });
        analytics.called(window._hsq.push, ['trackEvent', 'Viewed Product', { id: 'Viewed Product', _id: '12345' }]);
      });

    });

    describe('#page', function() {
      beforeEach(function() {
        analytics.stub(window._hsq, 'push');
      });

      it('should send a page view', function() {
        analytics.page();
        analytics.called(window._hsq.push, ['trackPageView']);
      });
    });
  });
});
<commit_msg>Fix linting error<commit_after>
var Analytics = require('analytics.js').constructor;
var integration = require('analytics.js-integration');
var sandbox = require('clear-env');
var tester = require('analytics.js-integration-tester');
var HubSpot = require('../lib/');

describe('HubSpot', function() {
  var analytics;
  var hubspot;
  var options = {
    portalId: 62515
  };

  beforeEach(function() {
    analytics = new Analytics();
    hubspot = new HubSpot(options);
    analytics.use(HubSpot);
    analytics.use(tester);
    analytics.add(hubspot);
  });

  afterEach(function() {
    analytics.restore();
    analytics.reset();
    hubspot.reset();
    sandbox();
  });

  it('should have the right settings', function() {
    analytics.compare(HubSpot, integration('HubSpot')
      .assumesPageview()
      .global('_hsq')
      .option('portalId', null));
  });

  describe('before loading', function() {
    beforeEach(function() {
      analytics.stub(hubspot, 'load');
    });

    describe('#initialize', function() {
      it('should create window._hsq', function() {
        analytics.assert(!window._hsq);
        analytics.initialize();
        analytics.page();
        analytics.assert(window._hsq instanceof Array);
      });
    });
  });

  describe('loading', function() {
    it('should load', function(done) {
      analytics.load(hubspot, done);
    });
  });

  describe('after loading', function() {
    beforeEach(function(done) {
      analytics.once('ready', done);
      analytics.initialize();
      analytics.page();
    });

    describe('#identify', function() {
      beforeEach(function() {
        analytics.stub(window._hsq, 'push');
      });

      it('should not send traits without an email', function() {
        analytics.identify('id');
        analytics.didNotCall(window._hsq.push);
      });

      it('should send traits with an email', function() {
        analytics.identify({ email: 'name@example.com' });
        analytics.called(window._hsq.push, ['identify', { email: 'name@example.com' }]);
      });

      it('should send an id and traits with an email', function() {
        analytics.identify('id', { email: 'name@example.com' });
        analytics.called(window._hsq.push, ['identify', {
          id: 'id',
          email: 'name@example.com'
        }]);
      });

      it('should convert dates to milliseconds', function() {
        var date = new Date();
        analytics.identify({
          email: 'name@example.com',
          date: date
        });
        analytics.called(window._hsq.push, ['identify', {
          email: 'name@example.com',
          date: date.getTime()
        }]);
      });
    });

    describe('#track', function() {
      beforeEach(function() {
        analytics.stub(window._hsq, 'push');
      });

      it('should send an event', function() {
        analytics.track('event');
        analytics.called(window._hsq.push, ['trackEvent', 'event', { id: 'event' }]);
      });

      it('should send an event and properties', function() {
        analytics.track('event', { property: true });
        analytics.called(window._hsq.push, ['trackEvent', 'event', { property: true, id: 'event' }]);
      });

      it('should convert dates to milliseconds', function() {
        var date = new Date();
        var ms = date.getTime();

        analytics.track('event', { date: date });
        analytics.called(window._hsq.push, ['trackEvent', 'event', { date: ms, id: 'event' }]);
      });

      it('should attach track.event to properties.id', function() {
        analytics.track('Viewed Product', {});
        analytics.called(window._hsq.push, ['trackEvent', 'Viewed Product', { id: 'Viewed Product' }]);
      });

      it('should move properties.id to properties._id', function() {
        analytics.track('Viewed Product', { id: '12345' });
        analytics.called(window._hsq.push, ['trackEvent', 'Viewed Product', { id: 'Viewed Product', _id: '12345' }]);
      });
    });

    describe('#page', function() {
      beforeEach(function() {
        analytics.stub(window._hsq, 'push');
      });

      it('should send a page view', function() {
        analytics.page();
        analytics.called(window._hsq.push, ['trackPageView']);
      });
    });
  });
});
<|endoftext|>


<commit_before>var errors = require('../');
var assert = require('assert');
var expect = require('chai').expect;
var boom = require('boom');

describe('mongodb-errors', function() {
  it('should work', function() {
    assert(errors);
  });

  describe('express', function() {
    it('should be requireable', function() {
      assert(require('../express'));
    });
    it('should work', function(done) {
      var d = new Error('Something weird...');
      d.name = 'MongoError';
      require('../express')(d, {}, {}, function(err) {
        assert(err);
        done();
      });
    });
  });

  describe('#translate', function() {
    context('when the regex matches', function() {
      var expected = 'MongoDB not running on the provided host and port';

      it('returns the mapping', function() {
        expect(errors.translate('ENOTFOUND').message).to.equal(expected);
      });
    });

    context('when the regex does not match', function() {
      it('returns null', function() {
        expect(errors.translate('not an error')).to.equal(null);
      });
    });

    context('when the error is internal', function() {
      it('returns a ServerError', function() {
        var result = errors.translate('BSONObj size: 26360608 (0x1923B20) is invalid. Size must be between 0 and 16793600(16MB)');
        expect(result.message).to.equal('Response from server was too large to process');
        expect(result.func).to.equal(boom.badImplementation);
      });
    });
  });
});
<commit_msg>:white_check_mark: Add unit tests for isNotAuthorized<commit_after>var errors = require('../');
var assert = require('assert');
var expect = require('chai').expect;
var boom = require('boom');

describe('mongodb-errors', function() {
  it('should work', function() {
    assert(errors);
  });

  describe('express', function() {
    it('should be requireable', function() {
      assert(require('../express'));
    });
    it('should work', function(done) {
      var d = new Error('Something weird...');
      d.name = 'MongoError';
      require('../express')(d, {}, {}, function(err) {
        assert(err);
        done();
      });
    });
  });

  describe('#isNotAuthorized', function() {
    it('should not match null', function() {
      expect(errors.isNotAuthorized(null)).to.equal(false);
    });
    it('should not match `operation exceeded time limit` errors', function() {
      var err = new Error('operation exceeded time limit');
      expect(errors.isNotAuthorized(err)).to.equal(false);
    });

    it('should match `not authorized on <db> to execute command <cmdSpec>`', function() {
      var err = new Error('not authorized on admin to execute command { getCmdLineOpts: 1 }');
      expect(errors.isNotAuthorized(err)).to.equal(true);
    });
  });

  describe('#translate', function() {
    context('when the regex matches', function() {
      var expected = 'MongoDB not running on the provided host and port';

      it('returns the mapping', function() {
        expect(errors.translate('ENOTFOUND').message).to.equal(expected);
      });
    });

    context('when the regex does not match', function() {
      it('returns null', function() {
        expect(errors.translate('not an error')).to.equal(null);
      });
    });

    context('when the error is internal', function() {
      it('returns a ServerError', function() {
        var result = errors.translate('BSONObj size: 26360608 (0x1923B20) is invalid. Size must be between 0 and 16793600(16MB)');
        expect(result.message).to.equal('Response from server was too large to process');
        expect(result.func).to.equal(boom.badImplementation);
      });
    });
  });
});
<|endoftext|>


<commit_before>/**
 * @fileoverview Export symbols needed by generated code in CommonJS style.
 *
 * This effectively is our canonical list of what we publicly export from
 * the google-protobuf.js file that we build at distribution time.
 */

goog.require('goog.object');
goog.require('jspb.BinaryReader');
goog.require('jspb.BinaryWriter');
goog.require('jspb.ExtensionFieldBinaryInfo');
goog.require('jspb.ExtensionFieldInfo');
goog.require('jspb.Message');

exports.Message = jspb.Message;
exports.BinaryReader = jspb.BinaryReader;
exports.BinaryWriter = jspb.BinaryWriter;
exports.ExtensionFieldInfo = jspb.ExtensionFieldInfo;
exports.ExtensionFieldBinaryInfo = jspb.ExtensionFieldBinaryInfo;

// These are used by generated code but should not be used directly by clients.
exports.exportSymbol = goog.exportSymbol;
exports.inherits = goog.inherits;
exports.object = {extend: goog.object.extend};
<commit_msg>Fix missing import of jspb.Map (#1885)<commit_after>/**
 * @fileoverview Export symbols needed by generated code in CommonJS style.
 *
 * This effectively is our canonical list of what we publicly export from
 * the google-protobuf.js file that we build at distribution time.
 */

goog.require('goog.object');
goog.require('jspb.BinaryReader');
goog.require('jspb.BinaryWriter');
goog.require('jspb.ExtensionFieldBinaryInfo');
goog.require('jspb.ExtensionFieldInfo');
goog.require('jspb.Message');
goog.require('jspb.Map');

exports.Map = jspb.Map;
exports.Message = jspb.Message;
exports.BinaryReader = jspb.BinaryReader;
exports.BinaryWriter = jspb.BinaryWriter;
exports.ExtensionFieldInfo = jspb.ExtensionFieldInfo;
exports.ExtensionFieldBinaryInfo = jspb.ExtensionFieldBinaryInfo;

// These are used by generated code but should not be used directly by clients.
exports.exportSymbol = goog.exportSymbol;
exports.inherits = goog.inherits;
exports.object = {extend: goog.object.extend};
<|endoftext|>


<commit_before>// ==UserScript==
// @name MLViewer
// @version 01
// @author Undo
// @description Show ML results inline
// @license MIT
// @include *://stackoverflow.com/questions*
// ==/UserScript==

function with_jquery(f) {
     var script = document.createElement("script");
     script.type = "text/javascript";
     script.textContent = "(" + f.toString() + ")(jQuery)";
     document.body.appendChild(script);
};

with_jquery(function($){
    $('document').ready(function(){
        var body = $(".post-text")[0].innerHTML
        $.get("https://ml.erwaysoftware.com/", { "body": body }, function(data) {

            if (data["prediction"] == "Recommendation request") {
                $(".inner-content.clearfix").prepend('ML: recommendation request')
            } else {
                $(".inner-content.clearfix").prepend('ML: not-recommendation request')
            }
        });
	    return false;
    });
});

<commit_msg>placeholder<commit_after>// ==UserScript==
// @name MLViewer
// @version 01
// @author Undo
// @description Show ML results inline
// @license MIT
// @include *://stackoverflow.com/questions*
// ==/UserScript==

function with_jquery(f) {
     var script = document.createElement("script");
     script.type = "text/javascript";
     script.textContent = "(" + f.toString() + ")(jQuery)";
     document.body.appendChild(script);
};

with_jquery(function($){
    $('document').ready(function(){
        var body = $(".post-text")[0].innerHTML
	$(".inner-content.clearfix").prepend('ML: loading...');
        $.get("https://ml.erwaysoftware.com/", { "body": body }, function(data) {
      	    $(".ml-loading").remove();
            if (data["prediction"] == "Recommendation request") {
                $(".inner-content.clearfix").prepend('ML: recommendation request');
            } else {
                $(".inner-content.clearfix").prepend('ML: not-recommendation request');
            }
        });
	    return false;
    });
});

<|endoftext|>


<commit_before>var should  = require('should')
  , connect = require('connect')
  , Poll    = require(__dirname + '../');

// Serve the fixtures.
connect()
  .use(connect.static(__dirname + "/fixtures"))
  .listen(4477);

var host = "http://127.0.0.1:4477"
  , feeds =
    [ host + "/atom.xml"
    , host + "/google-news.rss"
    ];

describe("feed-poll", function() {
  it("polls for articles", function(done) {
    var poll          = Poll(feeds)
      , article_count = 0;

    poll.on("article", function(article) {
      article.title.should.be.a("string");
      article_count++;
      if (article_count == 11) {
        poll.stop();
        done();
      }
    });

    poll.on("error", function(err) {
      poll.stop();
      done(err);
    });

    poll.start();
  });

  it("does not repeat articles", function(done) {
    var poll          = Poll(feeds, 0.5)
      , article_count = 0;

    poll.on("article", function(article) {
      article.title.should.be.a("string");
      article_count++;
      (article_count > 11).should.be.false;
      if (article_count == 11) {
        setTimeout(function() {
          poll.stop();
          done();
        }, 200);
      }
    });

    poll.start();
  });
});
<commit_msg>fix typo<commit_after>var should  = require('should')
  , connect = require('connect')
  , Poll    = require(__dirname + '/../');

// Serve the fixtures.
connect()
  .use(connect.static(__dirname + "/fixtures"))
  .listen(4477);

var host = "http://127.0.0.1:4477"
  , feeds =
    [ host + "/atom.xml"
    , host + "/google-news.rss"
    ];

describe("feed-poll", function() {
  it("polls for articles", function(done) {
    var poll          = Poll(feeds)
      , article_count = 0;

    poll.on("article", function(article) {
      article.title.should.be.a("string");
      article_count++;
      if (article_count == 11) {
        poll.stop();
        done();
      }
    });

    poll.on("error", function(err) {
      poll.stop();
      done(err);
    });

    poll.start();
  });

  it("does not repeat articles", function(done) {
    var poll          = Poll(feeds, 0.5)
      , article_count = 0;

    poll.on("article", function(article) {
      article.title.should.be.a("string");
      article_count++;
      (article_count > 11).should.be.false;
      if (article_count == 11) {
        setTimeout(function() {
          poll.stop();
          done();
        }, 200);
      }
    });

    poll.start();
  });
});
<|endoftext|>


<commit_before>/* eslint no-underscore-dangle: 0 */
const test = require('ava').test;
const Promise = require('bluebird');
const mongoose = require('mongoose');

const stringColleciton = require('../');

mongoose.Promise = Promise;
const db = mongoose.createConnection('localhost');
const getModel = (schema) => {
  const collectionId = mongoose.Types.ObjectId().toString();
  const collectionName = `tmp${collectionId}`;

  return db.model(collectionName, schema);
};
const minimalValidate = (t, pathOption, casterType = 'String') => {
  t.is(pathOption.instance, 'Array');
  t.is(pathOption.caster.instance, casterType);
};

test.after.always('clean up tmp collection', () => {
  const dropCollection = collectionName =>
    Promise.fromNode((callback) => {
      db.db.dropCollection(collectionName, callback);
    });

  return Promise.fromNode(callback =>
    db.db.listCollections({ name: /^tmp/ }).toArray(callback)
  )
    .map(collection => collection.name)
    .map(dropCollection);
});

test('elementOptions: should override default element options with type:ObjectId', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton, {
    elementOptions: {
      type: mongoose.Schema.Types.ObjectId,
    },
  });
  const pathOption = schema.path('tags');

  t.truthy(pathOption);
  minimalValidate(t, pathOption, 'ObjectID');
});

test('elementOptions: should use ObjectI in the database', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton, {
    elementOptions: {
      type: mongoose.Schema.Types.ObjectId,
    },
  });
  const model = getModel(schema);
  const bus = {
    foo: mongoose.Types.ObjectId(),
    bar: mongoose.Types.ObjectId(),
  };

  return model
    .create({ tags: [bus.foo] })
    .then((doc) => {
      t.truthy(doc);

      return model.addTags({ _id: doc._id }, [bus.bar]);
    })
    .then((doc) => {
      t.deepEqual(doc.tags, [bus.foo, bus.bar]);

      return model.findById(doc._id);
    })
    .then(doc => t.deepEqual(doc.tags, [bus.foo, bus.bar]));
});

test('elementOptions: should override default element options', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton, {
    elementOptions: {
      index: true,
    },
  });
  const pathOption = schema.path('tags');

  t.truthy(pathOption);
  minimalValidate(t, pathOption);
  t.true(pathOption.caster.options.index);
});

test('updateOptions: should override default update options', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton, {
    updateOptions: {
      new: false,
    },
  });
  const model = getModel(schema);

  const bus = {};
  return model
    .create({ tags: ['t', 't1'] })
    .then((doc) => {
      t.truthy(doc);
      bus.docId = doc._id;

      return model.addTags({ _id: doc._id }, ['t2']);
    })
    .then((doc) => {
      t.deepEqual(doc.tags, ['t', 't1']);

      return model.findById(bus.docId);
    })
    .then(doc => t.deepEqual(doc.tags, ['t', 't1', 't2']));
});

test('updateOptions: should override default update options on specify method', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton, {
    updateOptions: {
      new: false,
    },
  });
  const model = getModel(schema);

  const bus = {};
  return model
    .create({ tags: ['t', 't1'] })
    .then((doc) => {
      t.truthy(doc);
      bus.docId = doc._id;

      return model.addTags({ _id: doc._id }, ['t2'], { new: true });
    })
    .then((doc) => {
      t.deepEqual(doc.tags, ['t', 't1', 't2']);

      return model.findById(bus.docId);
    })
    .then(doc => t.deepEqual(doc.tags, ['t', 't1', 't2']));
});

test('fieldName: should exists target filed name', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const pathOption = schema.path('tags');

  t.truthy(pathOption);
  minimalValidate(t, pathOption);
  t.false(pathOption.caster.options.index);
});

test('fieldName: should index in caster field', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton, { isIndex: true });
  const pathOption = schema.path('tags');

  t.truthy(pathOption);
  t.true(pathOption.caster.options.index);
});

test('fieldName: should use input field name', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton, { fieldName: 't' });
  const pathOption = schema.path('t');

  minimalValidate(t, pathOption);
});

test('get: should success get collection', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  return model
    .create({ tags: ['t3'] })
    .then(doc => model.getTags({ _id: doc._id }))
    .then((tags) => {
      t.deepEqual(tags, ['t3']);
    });
});

test('get: should still get tags withou input', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  return model
    .create({ tags: ['t3'] })
    .then(() => model.getTags())
    .then(tags => t.deepEqual(tags, ['t3']));
});

test('add: should success add to collection', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const bus = {};
  return model
    .create({ tags: ['test'] })
    .then((doc) => {
      t.truthy(doc);
      bus.docId = doc._id;

      return model.addTags({ _id: doc._id }, ['test2']);
    })
    .then(() => model.findById(bus.docId))
    .then(doc => t.deepEqual(doc.tags, ['test', 'test2']));
});

test('add: should success add to collection with unique opions', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton, { isUnique: false });
  const model = getModel(schema);

  const bus = {};
  return model
    .create({ tags: ['t', 't1'] })
    .then((doc) => {
      t.truthy(doc);
      bus.docId = doc._id;

      return model.addTags({ _id: doc._id }, ['t1']);
    })
    .then(() => model.findById(bus.docId))
    .then(doc => t.deepEqual(doc.tags, ['t', 't1', 't1']));
});

test('add: should success add to collection with unique opions', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton, { isUnique: true });
  const model = getModel(schema);

  const bus = {};
  return model
    .create({ tags: ['t', 't1'] })
    .then((doc) => {
      t.truthy(doc);
      bus.docId = doc._id;

      return model.addTags({ _id: doc._id }, ['t1']);
    })
    .then((doc) => {
      t.deepEqual(doc.tags, ['t', 't1']);

      return model.findById(bus.docId);
    })
    .then((doc) => {
      t.deepEqual(doc.tags, ['t', 't1']);
    });
});

test('add: should reject emtpy query error', async (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const promise = model.addTags();
  await t.throws(promise, 'query should not be empty');
});

test('batchAdddd: should success add tags to collections', (t) => {
  const schema = new mongoose.Schema({ id: Number });
  schema.plugin(stringColleciton, { isUnique: true });
  const model = getModel(schema);

  return model
    .create([{ tags: ['t', 't1'], id: 1 }, { tags: ['t', 't1'], id: 2 }])
    .then((docs) => {
      t.truthy(docs);

      return model.batchAddTags({ id: { $in: [1, 2] } }, ['t3']);
    })
    .then(({ nModified }) => {
      t.is(nModified, 2);

      return model.find();
    })
    .then((docs) => {
      t.is(docs.length, 2);
      docs.forEach((doc) => {
        t.deepEqual(doc.tags, ['t', 't1', 't3']);
      });
    });
});

test('batchAdd: should reject emtpy query error', async (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const promise = model.batchAddTags();
  await t.throws(promise, 'query should not be empty');
});

test('remove: should success remove from collection', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const bus = {};
  return model
    .create({ tags: ['t', 't1', 't2'] })
    .then((doc) => {
      t.truthy(doc);
      bus.docId = doc._id;

      return model.removeTags({ _id: doc._id }, ['t', 't2']);
    })
    .then(() => model.findById(bus.docId))
    .then(doc => t.deepEqual(doc.tags, ['t1']));
});

test('remove: should success remove all elements', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const bus = {};
  return model
    .create({ tags: ['t', 't1', 't2'] })
    .then((doc) => {
      t.truthy(doc);
      bus.docId = doc._id;

      return model.removeTags({ _id: doc._id }, ['t', 't2']);
    })
    .then((doc) => {
      t.deepEqual(doc.tags, ['t1']);

      return model.removeTags({ _id: doc._id }, ['t', 't1']);
    })
    .then((doc) => {
      t.deepEqual(doc.tags, []);
      return model.findById(bus.docId);
    })
    .then(doc => t.deepEqual(doc.tags, []));
});

test('remove: should reject emtpy query error', async (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const promise = model.removeTags();
  await t.throws(promise, 'query should not be empty');
});

test('replace: should success replace original collection', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const bus = {};
  return model
    .create({ tags: ['t', 't1'] })
    .then((doc) => {
      t.truthy(doc);
      bus.docId = doc._id;

      return model.replaceTags({ _id: doc._id }, ['t2']);
    })
    .then((doc) => {
      t.deepEqual(doc.tags, ['t2']);

      return model.findById(doc._id);
    })
    .then(doc => t.deepEqual(doc.tags, ['t2']));
});

test('replace: should reject emtpy query error', async (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const promise = model.replaceTags();
  await t.throws(promise, 'query should not be empty');
});

test('batchReplace: should success batchReplace original collection', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const bus = {};
  return model
    .create({ tags: ['t', 't1'] })
    .then((doc) => {
      t.truthy(doc);
      bus.docId = doc._id;

      return model.batchReplaceTags({ _id: doc._id }, ['t2']);
    })
    .then(({ nModified }) => {
      t.is(nModified, 1);

      return model.findById(bus.docId);
    })
    .then(doc => t.deepEqual(doc.tags, ['t2']));
});

test('batchReplace: should reject emtpy query error', async (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const promise = model.batchReplaceTags();
  await t.throws(promise, 'query should not be empty');
});
<commit_msg>test(batchReplace): test for update multi docuemtns<commit_after>/* eslint no-underscore-dangle: 0 */
const test = require('ava').test;
const Promise = require('bluebird');
const mongoose = require('mongoose');

const stringColleciton = require('../');

mongoose.Promise = Promise;
const db = mongoose.createConnection('localhost');
const getModel = (schema) => {
  const collectionId = mongoose.Types.ObjectId().toString();
  const collectionName = `tmp${collectionId}`;

  return db.model(collectionName, schema);
};
const minimalValidate = (t, pathOption, casterType = 'String') => {
  t.is(pathOption.instance, 'Array');
  t.is(pathOption.caster.instance, casterType);
};

test.after.always('clean up tmp collection', () => {
  const dropCollection = collectionName =>
    Promise.fromNode((callback) => {
      db.db.dropCollection(collectionName, callback);
    });

  return Promise.fromNode(callback =>
    db.db.listCollections({ name: /^tmp/ }).toArray(callback)
  )
    .map(collection => collection.name)
    .map(dropCollection);
});

test('elementOptions: should override default element options with type:ObjectId', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton, {
    elementOptions: {
      type: mongoose.Schema.Types.ObjectId,
    },
  });
  const pathOption = schema.path('tags');

  t.truthy(pathOption);
  minimalValidate(t, pathOption, 'ObjectID');
});

test('elementOptions: should use ObjectI in the database', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton, {
    elementOptions: {
      type: mongoose.Schema.Types.ObjectId,
    },
  });
  const model = getModel(schema);
  const bus = {
    foo: mongoose.Types.ObjectId(),
    bar: mongoose.Types.ObjectId(),
  };

  return model
    .create({ tags: [bus.foo] })
    .then((doc) => {
      t.truthy(doc);

      return model.addTags({ _id: doc._id }, [bus.bar]);
    })
    .then((doc) => {
      t.deepEqual(doc.tags, [bus.foo, bus.bar]);

      return model.findById(doc._id);
    })
    .then(doc => t.deepEqual(doc.tags, [bus.foo, bus.bar]));
});

test('elementOptions: should override default element options', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton, {
    elementOptions: {
      index: true,
    },
  });
  const pathOption = schema.path('tags');

  t.truthy(pathOption);
  minimalValidate(t, pathOption);
  t.true(pathOption.caster.options.index);
});

test('updateOptions: should override default update options', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton, {
    updateOptions: {
      new: false,
    },
  });
  const model = getModel(schema);

  const bus = {};
  return model
    .create({ tags: ['t', 't1'] })
    .then((doc) => {
      t.truthy(doc);
      bus.docId = doc._id;

      return model.addTags({ _id: doc._id }, ['t2']);
    })
    .then((doc) => {
      t.deepEqual(doc.tags, ['t', 't1']);

      return model.findById(bus.docId);
    })
    .then(doc => t.deepEqual(doc.tags, ['t', 't1', 't2']));
});

test('updateOptions: should override default update options on specify method', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton, {
    updateOptions: {
      new: false,
    },
  });
  const model = getModel(schema);

  const bus = {};
  return model
    .create({ tags: ['t', 't1'] })
    .then((doc) => {
      t.truthy(doc);
      bus.docId = doc._id;

      return model.addTags({ _id: doc._id }, ['t2'], { new: true });
    })
    .then((doc) => {
      t.deepEqual(doc.tags, ['t', 't1', 't2']);

      return model.findById(bus.docId);
    })
    .then(doc => t.deepEqual(doc.tags, ['t', 't1', 't2']));
});

test('fieldName: should exists target filed name', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const pathOption = schema.path('tags');

  t.truthy(pathOption);
  minimalValidate(t, pathOption);
  t.false(pathOption.caster.options.index);
});

test('fieldName: should index in caster field', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton, { isIndex: true });
  const pathOption = schema.path('tags');

  t.truthy(pathOption);
  t.true(pathOption.caster.options.index);
});

test('fieldName: should use input field name', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton, { fieldName: 't' });
  const pathOption = schema.path('t');

  minimalValidate(t, pathOption);
});

test('get: should success get collection', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  return model
    .create({ tags: ['t3'] })
    .then(doc => model.getTags({ _id: doc._id }))
    .then((tags) => {
      t.deepEqual(tags, ['t3']);
    });
});

test('get: should still get tags withou input', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  return model
    .create({ tags: ['t3'] })
    .then(() => model.getTags())
    .then(tags => t.deepEqual(tags, ['t3']));
});

test('add: should success add to collection', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const bus = {};
  return model
    .create({ tags: ['test'] })
    .then((doc) => {
      t.truthy(doc);
      bus.docId = doc._id;

      return model.addTags({ _id: doc._id }, ['test2']);
    })
    .then(() => model.findById(bus.docId))
    .then(doc => t.deepEqual(doc.tags, ['test', 'test2']));
});

test('add: should success add to collection with unique opions', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton, { isUnique: false });
  const model = getModel(schema);

  const bus = {};
  return model
    .create({ tags: ['t', 't1'] })
    .then((doc) => {
      t.truthy(doc);
      bus.docId = doc._id;

      return model.addTags({ _id: doc._id }, ['t1']);
    })
    .then(() => model.findById(bus.docId))
    .then(doc => t.deepEqual(doc.tags, ['t', 't1', 't1']));
});

test('add: should success add to collection with unique opions', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton, { isUnique: true });
  const model = getModel(schema);

  const bus = {};
  return model
    .create({ tags: ['t', 't1'] })
    .then((doc) => {
      t.truthy(doc);
      bus.docId = doc._id;

      return model.addTags({ _id: doc._id }, ['t1']);
    })
    .then((doc) => {
      t.deepEqual(doc.tags, ['t', 't1']);

      return model.findById(bus.docId);
    })
    .then((doc) => {
      t.deepEqual(doc.tags, ['t', 't1']);
    });
});

test('add: should reject emtpy query error', async (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const promise = model.addTags();
  await t.throws(promise, 'query should not be empty');
});

test('batchAdd: should success add tags to collections', (t) => {
  const schema = new mongoose.Schema({ id: Number });
  schema.plugin(stringColleciton, { isUnique: true });
  const model = getModel(schema);

  return model
    .create([{ tags: ['t', 't1'], id: 1 }, { tags: ['t', 't1'], id: 2 }])
    .then((docs) => {
      t.truthy(docs);

      return model.batchAddTags({ id: { $in: [1, 2] } }, ['t3']);
    })
    .then(({ nModified }) => {
      t.is(nModified, 2);

      return model.find();
    })
    .then((docs) => {
      t.is(docs.length, 2);
      docs.forEach((doc) => {
        t.deepEqual(doc.tags, ['t', 't1', 't3']);
      });
    });
});

test('batchAdd: should reject emtpy query error', async (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const promise = model.batchAddTags();
  await t.throws(promise, 'query should not be empty');
});

test('remove: should success remove from collection', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const bus = {};
  return model
    .create({ tags: ['t', 't1', 't2'] })
    .then((doc) => {
      t.truthy(doc);
      bus.docId = doc._id;

      return model.removeTags({ _id: doc._id }, ['t', 't2']);
    })
    .then(() => model.findById(bus.docId))
    .then(doc => t.deepEqual(doc.tags, ['t1']));
});

test('remove: should success remove all elements', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const bus = {};
  return model
    .create({ tags: ['t', 't1', 't2'] })
    .then((doc) => {
      t.truthy(doc);
      bus.docId = doc._id;

      return model.removeTags({ _id: doc._id }, ['t', 't2']);
    })
    .then((doc) => {
      t.deepEqual(doc.tags, ['t1']);

      return model.removeTags({ _id: doc._id }, ['t', 't1']);
    })
    .then((doc) => {
      t.deepEqual(doc.tags, []);
      return model.findById(bus.docId);
    })
    .then(doc => t.deepEqual(doc.tags, []));
});

test('remove: should reject emtpy query error', async (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const promise = model.removeTags();
  await t.throws(promise, 'query should not be empty');
});

test('replace: should success replace original collection', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const bus = {};
  return model
    .create({ tags: ['t', 't1'] })
    .then((doc) => {
      t.truthy(doc);
      bus.docId = doc._id;

      return model.replaceTags({ _id: doc._id }, ['t2']);
    })
    .then((doc) => {
      t.deepEqual(doc.tags, ['t2']);

      return model.findById(doc._id);
    })
    .then(doc => t.deepEqual(doc.tags, ['t2']));
});

test('replace: should reject emtpy query error', async (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const promise = model.replaceTags();
  await t.throws(promise, 'query should not be empty');
});

test('batchReplace: should success batchReplace original collection', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const bus = {};
  return model
    .create({ tags: ['t', 't1'] })
    .then((doc) => {
      t.truthy(doc);
      bus.docId = doc._id;

      return model.batchReplaceTags({ _id: doc._id }, ['t2']);
    })
    .then(({ nModified }) => {
      t.is(nModified, 1);

      return model.findById(bus.docId);
    })
    .then(doc => t.deepEqual(doc.tags, ['t2']));
});

test('batchReplace: should success Replace tags to collections', (t) => {
  const schema = new mongoose.Schema({ id: Number });
  schema.plugin(stringColleciton, { isUnique: true });
  const model = getModel(schema);

  return model
    .create([{ tags: ['t', 't1'], id: 1 }, { tags: ['t', 't1'], id: 2 }])
    .then((docs) => {
      t.truthy(docs);

      return model.batchReplaceTags({ id: { $in: [1, 2] } }, ['t3']);
    })
    .then(({ nModified }) => {
      t.is(nModified, 2);

      return model.find();
    })
    .then((docs) => {
      t.is(docs.length, 2);
      docs.forEach((doc) => {
        t.deepEqual(doc.tags, ['t3']);
      });
    });
});

test('batchReplace: should reject emtpy query error', async (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const promise = model.batchReplaceTags();
  await t.throws(promise, 'query should not be empty');
});
<|endoftext|>


<commit_before>// Dynamically set the css background images for all the sprites
import React from "react";
import { createPortal } from "react-dom";
import { connect } from "react-redux";

import { LETTERS } from "../constants";
import { imageSelectors, cursorSelectors } from "../skinSelectors";

const CSS_PREFIX = "#webamp";

const mapRegionNamesToIds = {
  normal: "mainWindowClipPath",
  windowshade: "shadeMainWindowClipPath",
  equalizer: "equalizerWindowClipPath",
  equalizerws: "shadeEqualizerWindowClipPath",
};

const mapRegionNamesToMatcher = {
  normal: "#main-window:not(.shade)",
  windowshade: "#main-window.shade",
  equalizer: "#equalizer-window:not(.shade)",
  equalizerws: "#equalizer-window.shade",
};

const numExIsUsed = skinImages => !!skinImages.DIGIT_0_EX;

class Css extends React.Component {
  componentWillMount() {
    const style = document.createElement("style");
    style.type = "text/css";
    style.id = "webamp-skin";
    document.head.appendChild(style);
    this.style = style;
  }

  componentWillUnmount() {
    this.style.remove();
    this.style = null;
  }

  render() {
    return createPortal(this.props.children, this.style);
  }
}

class ClipPaths extends React.Component {
  componentWillMount() {
    const paths = document.createElement("div");
    document.body.appendChild(paths);
    this.paths = paths;
  }

  componentWillUnmount() {
    this.paths.remove();
    this.paths = null;
  }

  render() {
    // this.props.children should be an object containing arrays of strings. The
    // keys are ids, and the arrays are arrays of polygon point strings
    const { children } = this.props;

    return createPortal(
      <svg height={0} width={0}>
        <defs>
          {Object.keys(children).map(id => (
            <clipPath id={id} key={id}>
              {children[id].map((points, i) => (
                <polygon points={points} key={i} />
              ))}
            </clipPath>
          ))}
        </defs>
      </svg>,
      this.paths
    );
  }
}

const FALLBACKS = {
  MAIN_BALANCE_BACKGROUND: "MAIN_VOLUME_BACKGROUND",
  MAIN_BALANCE_THUMB: "MAIN_VOLUME_THUMB",
  MAIN_BALANCE_THUMB_ACTIVE: "MAIN_VOLUME_THUMB_SELECTED",
};

function cssRulesFromProps(props) {
  const { skinImages, skinCursors, skinGenLetterWidths } = props;
  if (!skinImages || !skinCursors) {
    return null;
  }
  const cssRules = [];
  Object.keys(imageSelectors).forEach(imageName => {
    const imageUrl = skinImages[imageName] || skinImages[FALLBACKS[imageName]];
    if (imageUrl) {
      imageSelectors[imageName].forEach(selector => {
        cssRules.push(
          `${CSS_PREFIX} ${selector} {background-image: url(${imageUrl})}`
        );
      });
    }
  });

  if (skinGenLetterWidths != null) {
    LETTERS.forEach(letter => {
      const width = skinGenLetterWidths[`GEN_TEXT_${letter}`];
      const selectedWidth = skinGenLetterWidths[`GEN_TEXT_SELECTED_${letter}`];
      cssRules.push(
        `${CSS_PREFIX} .gen-text-${letter.toLowerCase()} {width: ${width}px;}`
      );
      cssRules.push(
        `${CSS_PREFIX} .selected .gen-text-${letter.toLowerCase()} {width: ${selectedWidth}px;}`
      );
    });
  }
  Object.keys(cursorSelectors).forEach(cursorName => {
    const cursorUrl = skinCursors[cursorName];
    if (cursorUrl) {
      cursorSelectors[cursorName].forEach(selector => {
        cssRules.push(
          `${
            // TODO: Fix this hack
            // Maybe our CSS name spacing should be based on some other class/id
            // than the one we use for defining the main div.
            // That way it could be shared by both the player and the context menu.
            selector.startsWith("#webamp-context-menu") ? "" : CSS_PREFIX
          } ${selector} {cursor: url(${cursorUrl}), auto}`
        );
      });
    }
  });

  if (numExIsUsed(skinImages)) {
    // This alternate number file requires that the minus sign be
    // formatted differently.
    cssRules.push(
      `${CSS_PREFIX} .status #time #minus-sign { top: 0px; left: -1px; width: 9px; height: 13px; }`
    );
  }

  for (const [regionName, polygons] of Object.entries(props.skinRegion)) {
    if (polygons) {
      const matcher = mapRegionNamesToMatcher[regionName];
      const id = mapRegionNamesToIds[regionName];
      cssRules.push(`${CSS_PREFIX} ${matcher} { clip-path: url(#${id}); }`);
    }
  }

  // TODO: Find a way to make this declarative.
  cssRules.push(
    `#webamp-media-library {
       background-color: ${props.skinGenExColors.windowBackground};
       color: ${props.skinGenExColors.windowText};
    }`
  );
  cssRules.push(
    `#webamp-media-library input {
       caret-color: ${props.skinGenExColors.windowText};
    }`
  );
  cssRules.push(
    `#webamp-media-library .webamp-media-library-item {
       color: ${props.skinGenExColors.itemForeground};
       background-color: ${props.skinGenExColors.itemBackground};
       border-right: 1px solid ${props.skinGenExColors.divider};
       border-bottom: 1px solid ${props.skinGenExColors.divider};
    }`
  );
  cssRules.push(
    `#webamp-media-library .library-button-center {
       color: ${props.skinGenExColors.buttonText};
    }`
  );
  cssRules.push(
    `#webamp-media-library .webamp-media-library-vertical-divider {
    }`
  );
  cssRules.push(
    `#webamp-media-library .webamp-media-library-vertical-divider-line,
     #webamp-media-library .webamp-media-library-horizontal-divider-line
     {
       background-color: ${props.skinGenExColors.divider};
    }`
  );
  cssRules.push(
    `#webamp-media-library .webamp-media-library-table {
       color: ${props.skinGenExColors.itemForeground};
       background-color: ${props.skinGenExColors.itemBackground};
    }`
  );

  cssRules.push(
    `#webamp-media-library .webamp-media-library-table .library-table-heading {
       background-color: ${props.skinGenExColors.listHeaderFramePressed};
    }`
  );

  cssRules.push(
    `#webamp-media-library .webamp-media-library-table .library-table-heading > div {
       color: ${props.skinGenExColors.listHeaderText};
       background-color: ${props.skinGenExColors.listHeaderBackground};
       border-top: 1px solid ${props.skinGenExColors.listHeaderFrameTopAndLeft};
       border-left: 1px solid ${
         props.skinGenExColors.listHeaderFrameTopAndLeft
       };
       border-bottom: 1px solid ${
         props.skinGenExColors.listHeaderFrameBottomAndRight
       };
       border-right: 1px solid ${
         props.skinGenExColors.listHeaderFrameBottomAndRight
       };
    }`
  );
  cssRules.push(
    `#webamp-media-library .webamp-media-library-table .library-table-row.selected {
      background-color: ${props.skinGenExColors.playlistSelection};
      color: ${props.skinGenExColors.listHeaderText};
    }`
  );
  return cssRules;
}

function clipPathsFromProps(props) {
  const clipPaths = {};
  for (const [regionName, polygons] of Object.entries(props.skinRegion)) {
    if (polygons) {
      const id = mapRegionNamesToIds[regionName];
      clipPaths[id] = polygons;
    }
  }
  return clipPaths;
}

const Skin = props => {
  const cssRules = cssRulesFromProps(props);
  if (cssRules == null) {
    return null;
  }
  const clipPaths = clipPathsFromProps(props);
  return (

      <Css>{cssRules.join("\n")}</Css>
      <ClipPaths>{clipPaths}</ClipPaths>

  );
};

export default connect(state => ({
  skinImages: state.display.skinImages,
  skinCursors: state.display.skinCursors,
  skinRegion: state.display.skinRegion,
  skinGenLetterWidths: state.display.skinGenLetterWidths,
  skinGenExColors: state.display.skinGenExColors,
}))(Skin);
<commit_msg>Refactor portals to use hooks rather than deprecated lifecycle methods<commit_after>// Dynamically set the css background images for all the sprites
import React from "react";
import { createPortal } from "react-dom";
import { connect } from "react-redux";

import { LETTERS } from "../constants";
import { imageSelectors, cursorSelectors } from "../skinSelectors";

const CSS_PREFIX = "#webamp";

const mapRegionNamesToIds = {
  normal: "mainWindowClipPath",
  windowshade: "shadeMainWindowClipPath",
  equalizer: "equalizerWindowClipPath",
  equalizerws: "shadeEqualizerWindowClipPath",
};

const mapRegionNamesToMatcher = {
  normal: "#main-window:not(.shade)",
  windowshade: "#main-window.shade",
  equalizer: "#equalizer-window:not(.shade)",
  equalizerws: "#equalizer-window.shade",
};

const numExIsUsed = skinImages => !!skinImages.DIGIT_0_EX;

function Css({ children }) {
  const style = React.useMemo(() => {
    const s = document.createElement("style");
    s.type = "text/css";
    s.id = "webamp-skin";
    return s;
  }, []);

  React.useLayoutEffect(() => {
    document.head.appendChild(style);
    return () => style.remove();
  }, [style]);

  return createPortal(children, style);
}
// this.props.children should be an object containing arrays of strings. The
// keys are ids, and the arrays are arrays of polygon point strings
function ClipPaths({ children }) {
  const paths = React.useMemo(() => {
    return document.createElement("div");
  }, []);

  React.useLayoutEffect(() => {
    document.body.appendChild(paths);
    return () => paths.remove();
  }, [paths]);

  return createPortal(
    <svg height={0} width={0}>
      <defs>
        {Object.keys(children).map(id => (
          <clipPath id={id} key={id}>
            {children[id].map((points, i) => (
              <polygon points={points} key={i} />
            ))}
          </clipPath>
        ))}
      </defs>
    </svg>,
    paths
  );
}

const FALLBACKS = {
  MAIN_BALANCE_BACKGROUND: "MAIN_VOLUME_BACKGROUND",
  MAIN_BALANCE_THUMB: "MAIN_VOLUME_THUMB",
  MAIN_BALANCE_THUMB_ACTIVE: "MAIN_VOLUME_THUMB_SELECTED",
};

function cssRulesFromProps(props) {
  const { skinImages, skinCursors, skinGenLetterWidths } = props;
  if (!skinImages || !skinCursors) {
    return null;
  }
  const cssRules = [];
  Object.keys(imageSelectors).forEach(imageName => {
    const imageUrl = skinImages[imageName] || skinImages[FALLBACKS[imageName]];
    if (imageUrl) {
      imageSelectors[imageName].forEach(selector => {
        cssRules.push(
          `${CSS_PREFIX} ${selector} {background-image: url(${imageUrl})}`
        );
      });
    }
  });

  if (skinGenLetterWidths != null) {
    LETTERS.forEach(letter => {
      const width = skinGenLetterWidths[`GEN_TEXT_${letter}`];
      const selectedWidth = skinGenLetterWidths[`GEN_TEXT_SELECTED_${letter}`];
      cssRules.push(
        `${CSS_PREFIX} .gen-text-${letter.toLowerCase()} {width: ${width}px;}`
      );
      cssRules.push(
        `${CSS_PREFIX} .selected .gen-text-${letter.toLowerCase()} {width: ${selectedWidth}px;}`
      );
    });
  }
  Object.keys(cursorSelectors).forEach(cursorName => {
    const cursorUrl = skinCursors[cursorName];
    if (cursorUrl) {
      cursorSelectors[cursorName].forEach(selector => {
        cssRules.push(
          `${
            // TODO: Fix this hack
            // Maybe our CSS name spacing should be based on some other class/id
            // than the one we use for defining the main div.
            // That way it could be shared by both the player and the context menu.
            selector.startsWith("#webamp-context-menu") ? "" : CSS_PREFIX
          } ${selector} {cursor: url(${cursorUrl}), auto}`
        );
      });
    }
  });

  if (numExIsUsed(skinImages)) {
    // This alternate number file requires that the minus sign be
    // formatted differently.
    cssRules.push(
      `${CSS_PREFIX} .status #time #minus-sign { top: 0px; left: -1px; width: 9px; height: 13px; }`
    );
  }

  for (const [regionName, polygons] of Object.entries(props.skinRegion)) {
    if (polygons) {
      const matcher = mapRegionNamesToMatcher[regionName];
      const id = mapRegionNamesToIds[regionName];
      cssRules.push(`${CSS_PREFIX} ${matcher} { clip-path: url(#${id}); }`);
    }
  }

  // TODO: Find a way to make this declarative.
  cssRules.push(
    `#webamp-media-library {
       background-color: ${props.skinGenExColors.windowBackground};
       color: ${props.skinGenExColors.windowText};
    }`
  );
  cssRules.push(
    `#webamp-media-library input {
       caret-color: ${props.skinGenExColors.windowText};
    }`
  );
  cssRules.push(
    `#webamp-media-library .webamp-media-library-item {
       color: ${props.skinGenExColors.itemForeground};
       background-color: ${props.skinGenExColors.itemBackground};
       border-right: 1px solid ${props.skinGenExColors.divider};
       border-bottom: 1px solid ${props.skinGenExColors.divider};
    }`
  );
  cssRules.push(
    `#webamp-media-library .library-button-center {
       color: ${props.skinGenExColors.buttonText};
    }`
  );
  cssRules.push(
    `#webamp-media-library .webamp-media-library-vertical-divider {
    }`
  );
  cssRules.push(
    `#webamp-media-library .webamp-media-library-vertical-divider-line,
     #webamp-media-library .webamp-media-library-horizontal-divider-line
     {
       background-color: ${props.skinGenExColors.divider};
    }`
  );
  cssRules.push(
    `#webamp-media-library .webamp-media-library-table {
       color: ${props.skinGenExColors.itemForeground};
       background-color: ${props.skinGenExColors.itemBackground};
    }`
  );

  cssRules.push(
    `#webamp-media-library .webamp-media-library-table .library-table-heading {
       background-color: ${props.skinGenExColors.listHeaderFramePressed};
    }`
  );

  cssRules.push(
    `#webamp-media-library .webamp-media-library-table .library-table-heading > div {
       color: ${props.skinGenExColors.listHeaderText};
       background-color: ${props.skinGenExColors.listHeaderBackground};
       border-top: 1px solid ${props.skinGenExColors.listHeaderFrameTopAndLeft};
       border-left: 1px solid ${
         props.skinGenExColors.listHeaderFrameTopAndLeft
       };
       border-bottom: 1px solid ${
         props.skinGenExColors.listHeaderFrameBottomAndRight
       };
       border-right: 1px solid ${
         props.skinGenExColors.listHeaderFrameBottomAndRight
       };
    }`
  );
  cssRules.push(
    `#webamp-media-library .webamp-media-library-table .library-table-row.selected {
      background-color: ${props.skinGenExColors.playlistSelection};
      color: ${props.skinGenExColors.listHeaderText};
    }`
  );
  return cssRules;
}

function clipPathsFromProps(props) {
  const clipPaths = {};
  for (const [regionName, polygons] of Object.entries(props.skinRegion)) {
    if (polygons) {
      const id = mapRegionNamesToIds[regionName];
      clipPaths[id] = polygons;
    }
  }
  return clipPaths;
}

const Skin = props => {
  const cssRules = cssRulesFromProps(props);
  if (cssRules == null) {
    return null;
  }
  const clipPaths = clipPathsFromProps(props);
  return (

      <Css>{cssRules.join("\n")}</Css>
      <ClipPaths>{clipPaths}</ClipPaths>

  );
};

export default connect(state => ({
  skinImages: state.display.skinImages,
  skinCursors: state.display.skinCursors,
  skinRegion: state.display.skinRegion,
  skinGenLetterWidths: state.display.skinGenLetterWidths,
  skinGenExColors: state.display.skinGenExColors,
}))(Skin);
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { connect } from 'react-redux';
import {
  View,
  RefreshControl,
  TouchableOpacity,
  Alert,
  Platform
} from 'react-native';

import {
  List,
  ListItem,
  Text,
  Content,
  Left,
  Body,
  Thumbnail,
  Right,
  Icon
} from 'native-base';
import { Actions } from 'react-native-router-flux';
const PLColors = require('PLColors');
import { getFollowers, unFollowers, acceptFollowers } from 'PLActions';
import styles from './styles';
import ContentPlaceholder from '../../../components/ContentPlaceholder';
import PLOverlayLoader from 'PLOverlayLoader';

class Followers extends Component {
  static propTypes = {
    token: React.PropTypes.string
  }

  constructor(props) {
    super(props);

    this.state = {
      followers: [],
      page: 1,
      per_page: 10,
      items: 10,
      totalItems: 0,
      refreshing: false
    }
  }

  componentWillMount() {
    this._onRefresh();
  }

  loadFollowers() {
    var { token } = this.props;
    var { page, per_page } = this.state;

    getFollowers(token, page, per_page)
      .then(ret => {
        this.setState({
          followers: ret.payload,
          page: ret.page,
          items: ret.items,
          totalItems: ret.totalItems,
          refreshing: false
        });
      })
      .catch(err => {

      });
  }

  _onRefresh() {
    this.setState({ refreshing: true });
    this.loadFollowers();
  }

  unFollowers(index) {
    var { token } = this.props;

    Alert.alert("Confirm", "Do you want to stop " + this.state.followers[index].username + " from following you ?", [
      {
        text: 'Cancel'
      },
      {
        text: 'OK',
        onPress: () => {
          unFollowers(token, this.state.followers[index].id)
            .then((ret) => {
              this.state.followers.splice(index, 1);
              this.setState({
                per_page: this.state.per_page
              });
            })
            .catch(err => {

            });
        }
      }
    ]);
  }

  acceptFollower(index) {
    var { token } = this.props;

    Alert.alert("Confirm", "Do you want to approve " + this.state.followers[index].username + " ?", [
      {
        text: 'Cancel'
      },
      {
        text: 'OK',
        onPress: () => {
          acceptFollowers(token, this.state.followers[index].id)
            .then((ret) => {
              this.state.followers[index].status = 'active';
              this.setState({
                per_page: this.state.per_page
              });
            })
            .catch(err => {

            });
        }
      }
    ]);
  }

  goToProfile(id) {
    Actions.profile({ id: id });
  }

  render() {
    const { followers, refreshing } = this.state;

    return (
      <ContentPlaceholder
        empty={followers.length === 0}
        title="Hmm. Looks like you don't have any followers yet. Create a post!"
        refreshControl={Platform.OS === 'android' &&
          <RefreshControl
            refreshing={false}
            onRefresh={this._onRefresh.bind(this)}
          />
        }
        onScroll={(e) => {
          var offset = e.nativeEvent.contentOffset.y;

          if (Platform.OS === 'ios' && offset < -3) {
            this._onRefresh();
          }
        }}
      >
        { followers.length > 0 &&
          <List>
            {
              followers.map((follow, index) => {
                return (
                  <ListItem avatar key={index} onPress={() => this.goToProfile(follow.id)}>
                    <Left>
                      { follow.avatar_file_name &&
                        <Thumbnail source={{ uri: follow.avatar_file_name + '&w=50&h=50&auto=compress,format,q=95' }} />
                      }
                    </Left>
                    <Body>
                      <Text>{follow.username}</Text>
                      <Text note>{follow.full_name}</Text>
                    </Body>
                    <Right style={styles.itemRightContainer}>
                      {follow.status === 'active' ?
                        <TouchableOpacity onPress={() => this.unFollowers(index)}>
                          <View style={styles.buttonContainer}>
                            <Icon name="ios-person" style={styles.activeIconLarge} />
                            <Icon name="remove-circle" style={styles.activeIconSmall} />
                          </View>
                        </TouchableOpacity>
                        :
                        <View style={styles.buttonContainer}>
                          <TouchableOpacity onPress={() => this.acceptFollower(index)}>
                            <Icon name="checkmark" style={styles.acceptIcon} />
                          </TouchableOpacity>
                          <TouchableOpacity onPress={() => this.unFollowers(index)}>
                            <Icon name="close" style={styles.rejectIcon} />
                          </TouchableOpacity>
                        </View>
                      }
                    </Right>
                  </ListItem>
                );
              })
            }
          </List>
        }
        <PLOverlayLoader visible={refreshing} logo />
      </ContentPlaceholder>
    );
  }

}

const mapStateToProps = state => ({
  token: state.user.token
});

export default connect(mapStateToProps)(Followers);<commit_msg>Issue #259<commit_after>import React, { Component } from 'react';
import { connect } from 'react-redux';
import {
  View,
  RefreshControl,
  TouchableOpacity,
  Alert,
  Platform
} from 'react-native';

import {
  List,
  ListItem,
  Text,
  Content,
  Left,
  Body,
  Thumbnail,
  Right,
  Icon
} from 'native-base';
import { Actions } from 'react-native-router-flux';
const PLColors = require('PLColors');
import { getFollowers, unFollowers, acceptFollowers } from 'PLActions';
import styles from './styles';
import ContentPlaceholder from '../../../components/ContentPlaceholder';
import PLOverlayLoader from 'PLOverlayLoader';

class Followers extends Component {
  static propTypes = {
    token: React.PropTypes.string
  }

  constructor(props) {
    super(props);

    this.state = {
      followers: [],
      page: 1,
      per_page: 10,
      items: 10,
      totalItems: 0,
      refreshing: false
    }
  }

  componentWillMount() {
    this._onRefresh();
  }

  loadFollowers() {
    var { token } = this.props;
    var { page, per_page } = this.state;

    getFollowers(token, page, per_page)
      .then(ret => {
        this.setState({
          followers: ret.payload,
          page: ret.page,
          items: ret.items,
          totalItems: ret.totalItems,
          refreshing: false
        });
      })
      .catch(err => {

      });
  }

  _onRefresh() {
    this.setState({ refreshing: true });
    this.loadFollowers();
  }

  unFollowers(index) {
    var { token } = this.props;

    Alert.alert("Confirm", "Do you want to unapprove " + this.state.followers[index].username + " from following you ?", [
      {
        text: 'Cancel'
      },
      {
        text: 'OK',
        onPress: () => {
          unFollowers(token, this.state.followers[index].id)
            .then((ret) => {
              this.state.followers.splice(index, 1);
              this.setState({
                per_page: this.state.per_page
              });
            })
            .catch(err => {

            });
        }
      }
    ]);
  }

  acceptFollower(index) {
    var { token } = this.props;

    Alert.alert("Confirm", "Do you want to approve " + this.state.followers[index].username + " ?", [
      {
        text: 'Cancel'
      },
      {
        text: 'OK',
        onPress: () => {
          acceptFollowers(token, this.state.followers[index].id)
            .then((ret) => {
              this.state.followers[index].status = 'active';
              this.setState({
                per_page: this.state.per_page
              });
            })
            .catch(err => {

            });
        }
      }
    ]);
  }

  goToProfile(id) {
    Actions.profile({ id: id });
  }

  render() {
    const { followers, refreshing } = this.state;

    return (
      <ContentPlaceholder
        empty={followers.length === 0}
        title="Hmm. Looks like you don't have any followers yet. The best way to gain followers is to create posts!"
        refreshControl={Platform.OS === 'android' &&
          <RefreshControl
            refreshing={false}
            onRefresh={this._onRefresh.bind(this)}
          />
        }
        onScroll={(e) => {
          var offset = e.nativeEvent.contentOffset.y;

          if (Platform.OS === 'ios' && offset < -3) {
            this._onRefresh();
          }
        }}
      >
        { followers.length > 0 &&
          <List>
            {
              followers.map((follow, index) => {
                return (
                  <ListItem avatar key={index} onPress={() => this.goToProfile(follow.id)}>
                    <Left>
                      { follow.avatar_file_name &&
                        <Thumbnail source={{ uri: follow.avatar_file_name + '&w=50&h=50&auto=compress,format,q=95' }} />
                      }
                    </Left>
                    <Body>
                      <Text>{follow.username}</Text>
                      <Text note>{follow.full_name}</Text>
                    </Body>
                    <Right style={styles.itemRightContainer}>
                      {follow.status === 'active' ?
                        <TouchableOpacity onPress={() => this.unFollowers(index)}>
                          <View style={styles.buttonContainer}>
                            <Icon name="ios-person" style={styles.activeIconLarge} />
                            <Icon name="remove-circle" style={styles.activeIconSmall} />
                          </View>
                        </TouchableOpacity>
                        :
                        <View style={styles.buttonContainer}>
                          <TouchableOpacity onPress={() => this.acceptFollower(index)}>
                            <Icon name="checkmark" style={styles.acceptIcon} />
                          </TouchableOpacity>
                          <TouchableOpacity onPress={() => this.unFollowers(index)}>
                            <Icon name="close" style={styles.rejectIcon} />
                          </TouchableOpacity>
                        </View>
                      }
                    </Right>
                  </ListItem>
                );
              })
            }
          </List>
        }
        <PLOverlayLoader visible={refreshing} logo />
      </ContentPlaceholder>
    );
  }

}

const mapStateToProps = state => ({
  token: state.user.token
});

export default connect(mapStateToProps)(Followers);<|endoftext|>


<commit_before>describe('Test First Build', function(){
  it('should fail due to error on jshint', function(){

  })
});
<commit_msg>build should pass now<commit_after>describe('Test First Build', function(){
  it('build should pass now', function(){
  });
});
<|endoftext|>


<commit_before>"use strict";
/*global describe, it, assert*/

describe("interfaces", function () {

    var
        gpfIEventDispatcher = gpf.interfaces.IEventDispatcher,
        SampleEventDispatcherWithAddOnly = function () {},
        SampleEventDispatcherComplete = function () {},
        fakeAddEventListener = function (a, b, c) {
            a = b + c; // Just to avoid unused parameters warning
            return this;
        },
        fakeRemoveEventListener = function (a, b) {
            a = b;
            return this;
        };

    SampleEventDispatcherWithAddOnly.prototype = {

        addEventListener: fakeAddEventListener

    };

    SampleEventDispatcherComplete.prototype
        = new SampleEventDispatcherWithAddOnly();

    SampleEventDispatcherComplete.prototype.removeEventListener
        = fakeRemoveEventListener;

    describe("gpf.interfaces.isImplementedBy", function () {

        it("verifies that an object implements an interface", function () {
            var test = {
                addEventListener: fakeAddEventListener,
                removeEventListener: fakeRemoveEventListener
            };
            assert(true === gpf.interfaces.isImplementedBy(test,
                gpfIEventDispatcher));
        });

        it("checks function signatures", function () {
            var test = {
                addEventListener: function (a, b) {
                    return a + b;
                },
                removeEventListener: fakeRemoveEventListener
            };
            assert(false === gpf.interfaces.isImplementedBy(test,
                gpfIEventDispatcher));
        });

        it("works through inheritance", function () {
            assert(true === gpf.interfaces.isImplementedBy(
              new SampleEventDispatcherComplete(), gpfIEventDispatcher));
        });

        it("works with classes", function () {
            assert(true === gpf.interfaces.isImplementedBy(
              SampleEventDispatcherComplete, gpfIEventDispatcher));
        });

    });

    describe("gpf.interfaces.query", function () {

        it("generates an error if interface not available", function () {
            var caught;
            try {
                gpf.interfaces.query({}, gpfIEventDispatcher);
            } catch (e) {
                caught = e;
            }
            assert(null !== caught);
            assert(caught.code === gpf.Error.CODE_INTERFACEEXPECTED);
            assert(caught.code === gpf.Error.InterfaceExpected.CODE);
            assert(caught.name === "InterfaceExpected");
            assert(caught.message === "Expected interface not implemented: " +
                "gpf.interfaces.IEventDispatcher");
        });

        it("can also just return null if interface not available", function () {
            assert(null === gpf.interfaces.query({}, gpfIEventDispatcher,
                false));
        });

        it("retrieves an object for the expected interface", function () {
            var instance = new SampleEventDispatcherComplete(),
                iEventDispatcher = gpf.interfaces.query(instance,
                    gpfIEventDispatcher, false);
            assert(null !== iEventDispatcher);
            assert(instance === iEventDispatcher);
            assert(true === gpf.interfaces.isImplementedBy(iEventDispatcher,
                gpfIEventDispatcher));
        });

    });

    describe("IUnknown", function () {

        var
            SampleBuilder = function () {};
        SampleBuilder.prototype.queryInterface = function (iDefinition) {
            if (gpfIEventDispatcher === iDefinition) {
                return new SampleEventDispatcherComplete();
            }
            return null;
        };

        it("exposes queryInterface", function () {
            assert(true === gpf.interfaces.isImplementedBy(SampleBuilder,
                gpf.interfaces.IUnknown));
        });

        it("is used by gpf.interfaces.query", function () {
            var instance = new SampleBuilder(),
                iEventDispatcher = gpf.interfaces.query(instance,
                    gpfIEventDispatcher, false);
            assert(null !== iEventDispatcher);
            assert(true === gpf.interfaces.isImplementedBy(iEventDispatcher,
                gpfIEventDispatcher));
        });

    });

    describe("$InterfaceImplement", function () {

        var
            SampleBuilder = gpf.define("SampleBuilder", {
                "[Class]": [gpf.$InterfaceImplement(gpfIEventDispatcher,
                    "_getAswEventDispatcher")],

                private: {
                    _getAswEventDispatcher: function () {
                        return new SampleEventDispatcherComplete();
                    }
                }
            });

        it("exposes queryInterface", function () {
            assert(true === gpf.interfaces.isImplementedBy(SampleBuilder,
                gpf.interfaces.IUnknown));
        });

        it("is used by gpf.interfaces.query", function () {
            var instance = new SampleBuilder(),
                iEventDispatcher = gpf.interfaces.query(instance,
                    gpfIEventDispatcher, false);
            assert(null !== iEventDispatcher);
            assert(true === gpf.interfaces.isImplementedBy(iEventDispatcher,
                gpfIEventDispatcher));
        });

    });

});<commit_msg>Tested both member name & function builders<commit_after>"use strict";
/*global describe, it, assert*/

describe("interfaces", function () {

    var
        gpfIEventDispatcher = gpf.interfaces.IEventDispatcher,
        SampleEventDispatcherWithAddOnly = function () {},
        SampleEventDispatcherComplete = function () {},
        fakeAddEventListener = function (a, b, c) {
            a = b + c; // Just to avoid unused parameters warning
            return this;
        },
        fakeRemoveEventListener = function (a, b) {
            a = b;
            return this;
        };

    SampleEventDispatcherWithAddOnly.prototype = {

        addEventListener: fakeAddEventListener

    };

    SampleEventDispatcherComplete.prototype
        = new SampleEventDispatcherWithAddOnly();

    SampleEventDispatcherComplete.prototype.removeEventListener
        = fakeRemoveEventListener;

    describe("gpf.interfaces.isImplementedBy", function () {

        it("verifies that an object implements an interface", function () {
            var test = {
                addEventListener: fakeAddEventListener,
                removeEventListener: fakeRemoveEventListener
            };
            assert(true === gpf.interfaces.isImplementedBy(test,
                gpfIEventDispatcher));
        });

        it("checks function signatures", function () {
            var test = {
                addEventListener: function (a, b) {
                    return a + b;
                },
                removeEventListener: fakeRemoveEventListener
            };
            assert(false === gpf.interfaces.isImplementedBy(test,
                gpfIEventDispatcher));
        });

        it("works through inheritance", function () {
            assert(true === gpf.interfaces.isImplementedBy(
              new SampleEventDispatcherComplete(), gpfIEventDispatcher));
        });

        it("works with classes", function () {
            assert(true === gpf.interfaces.isImplementedBy(
              SampleEventDispatcherComplete, gpfIEventDispatcher));
        });

    });

    describe("gpf.interfaces.query", function () {

        it("generates an error if interface not available", function () {
            var caught;
            try {
                gpf.interfaces.query({}, gpfIEventDispatcher);
            } catch (e) {
                caught = e;
            }
            assert(null !== caught);
            assert(caught.code === gpf.Error.CODE_INTERFACEEXPECTED);
            assert(caught.code === gpf.Error.InterfaceExpected.CODE);
            assert(caught.name === "InterfaceExpected");
            assert(caught.message === "Expected interface not implemented: " +
                "gpf.interfaces.IEventDispatcher");
        });

        it("can also just return null if interface not available", function () {
            assert(null === gpf.interfaces.query({}, gpfIEventDispatcher,
                false));
        });

        it("retrieves an object for the expected interface", function () {
            var instance = new SampleEventDispatcherComplete(),
                iEventDispatcher = gpf.interfaces.query(instance,
                    gpfIEventDispatcher, false);
            assert(null !== iEventDispatcher);
            assert(instance === iEventDispatcher);
            assert(true === gpf.interfaces.isImplementedBy(iEventDispatcher,
                gpfIEventDispatcher));
        });

    });

    describe("IUnknown", function () {

        var
            SampleBuilder = function () {};
        SampleBuilder.prototype.queryInterface = function (iDefinition) {
            if (gpfIEventDispatcher === iDefinition) {
                return new SampleEventDispatcherComplete();
            }
            return null;
        };

        it("exposes queryInterface", function () {
            assert(true === gpf.interfaces.isImplementedBy(SampleBuilder,
                gpf.interfaces.IUnknown));
        });

        it("is used by gpf.interfaces.query", function () {
            var instance = new SampleBuilder(),
                iEventDispatcher = gpf.interfaces.query(instance,
                    gpfIEventDispatcher, false);
            assert(null !== iEventDispatcher);
            assert(true === gpf.interfaces.isImplementedBy(iEventDispatcher,
                gpfIEventDispatcher));
        });

    });

    describe("$InterfaceImplement", function () {

        describe("member name", function () {

            var
              SampleBuilder = gpf.define("SampleBuilder", {
                  "[Class]": [gpf.$InterfaceImplement(gpfIEventDispatcher,
                    "_getAswEventDispatcher")],

                  private: {
                      _getAswEventDispatcher: function () {
                          return new SampleEventDispatcherComplete();
                      }
                  }
              });

            it("exposes queryInterface", function () {
                assert(true === gpf.interfaces.isImplementedBy(SampleBuilder,
                    gpf.interfaces.IUnknown));
            });

            it("is used by gpf.interfaces.query", function () {
                var instance = new SampleBuilder(),
                    iEventDispatcher = gpf.interfaces.query(instance,
                    gpfIEventDispatcher, false);
                assert(null !== iEventDispatcher);
                assert(true === gpf.interfaces.isImplementedBy(iEventDispatcher,
                    gpfIEventDispatcher));
            });

        });

        describe("builder function", function () {

            var
              _getAswEventDispatcher = function (that) {
                  assert(null !== that);
                  return new SampleEventDispatcherComplete();
              },
              SampleBuilder = gpf.define("SampleBuilder", {
                  "[Class]": [gpf.$InterfaceImplement(gpfIEventDispatcher,
                    _getAswEventDispatcher)]
              });

            it("exposes queryInterface", function () {
                assert(true === gpf.interfaces.isImplementedBy(SampleBuilder,
                    gpf.interfaces.IUnknown));
            });

            it("is used by gpf.interfaces.query", function () {
                var instance = new SampleBuilder(),
                  iEventDispatcher = gpf.interfaces.query(instance,
                    gpfIEventDispatcher, false);
                assert(null !== iEventDispatcher);
                assert(true === gpf.interfaces.isImplementedBy(iEventDispatcher,
                    gpfIEventDispatcher));
            });

        });

    });

});<|endoftext|>


<commit_before>//= require "codemirror"
//= require "mobileCodeMirror"
//= require "library"
//= require "unsaved"
var focusPanel = 'javascript';
var editors = {};
var row = {};
var sql = new Array();

window.editors = editors;

editors.html = CodeMirror.fromTextArea(document.getElementById('html'), {
  parserfile: [],
  tabMode: 'shift',
  mode: 'text/html',
  onChange: changecontrol,
  theme: "ankur",
  indentUnit: 4,
  lineNumbers: true
});

editors.javascript = CodeMirror.fromTextArea(document.getElementById('javascript'), {
  mode: 'css',
  tabMode: 'shift',
  onChange: changecontrol,
  theme: "ankur",
  matchBrackets: true,
  indentUnit: 4,
  lineNumbers: true
});

setupEditor('javascript');
setupEditor('html');

var editorsReady = setInterval(function () {
  if (editors.html.ready && editors.javascript.ready) {

    editors.html.setCursor(7, 8);

    clearInterval(editorsReady);
    editors.ready = true;
    if (typeof editors.onReady == 'function') editors.onReady();

    var scrollers = {
      html: $(editors.html.getScrollerElement()),
      javascript: $(editors.javascript.getScrollerElement())
    };

    $document.bind('sizeeditors', function () {
      var top = 0, //$el.offset().top,
          height = $('#bin').height();
      scrollers.html.height(height - top);
      scrollers.javascript.height(height - top - $error.filter(':visible').height());
      editors.javascript.refresh();
      editors.html.refresh();
    });

    $(window).resize(function () {
      setTimeout(function () {
        $document.trigger('sizeeditors');
      }, 100);
    });

    $document.trigger('sizeeditors');
    $document.trigger('jsbinReady');
  }
}, 100);

// $('#javascript').replaceWith('

');
// $('#javascript').css({ height: '100%', width: '100%' });
// $('#html').replaceWith('

');
// $('#html').css({ height: '100%', width: '100%' });
//
// editors.javascript = ace.edit("javascript");
// editors.html = ace.edit("html");
//
// var JavaScriptMode = require("ace/mode/javascript").Mode,
//     HTMLMode = require("ace/mode/html").Mode;
//
// setupAce(editors, 'javascript');
// setupAce(editors, 'html');
//
// function setupAce(editor, type) {
//   var session = editors[type].getSession(),
//       renderer = editors[type].renderer;
//   if (type == 'javascript') {
//     session.setMode(new JavaScriptMode());
//   } else {
//     session.setMode(new HTMLMode());
//   }
//
//   editors[type].setHighlightActiveLine(false);
//   session.setUseWrapMode(true);
//   session.setUseSoftTabs(true);
//   session.setWrapLimitRange(null, null);
//
//   renderer.setShowPrintMargin(false);
//   renderer.setShowGutter(false);
//   renderer.setHScrollBarAlwaysVisible(false);
// }

function focused(editor, event) {
  focusPanel = editor.id;
  snapshot(focusPanel);
  console.log(focusPanel);
}

function getFocusedPanel() {
  return focusPanel;
}

function setupEditor(panel) {
  var e = editors[panel],
      focusedPanel = sessionStorage.getItem('panel');

  // overhang from CodeMirror1
  e.setCode = function (str) {
    e.setValue(str);
  };

  e.getCode = function () {
    return e.getValue();
  };

  e.currentLine = function () {
    var pos = e.getCursor();
    return pos.line;
  };

  e.setOption('onChange', changecontrol);
  e.setOption('onKeyEvent', keycontrol);
  e.setOption('onFocus', focused);

  e.id = panel;

  e.win = e.getWrapperElement();
  e.scroller = $(e.getScrollerElement());

  $(e.win).click(function () {
    e.focus();
  });

  var $label = $('.code.' + panel + ' > .label');
  if (document.body.className.indexOf('ie6') === -1) {
    e.scroller.scroll(function (event) {
      if (this.scrollTop > 10) {
        $label.stop().animate({ opacity: 0 }, 50, function () {
          $(this).hide();
        });
      } else {
        $label.show().stop().animate({ opacity: 1 }, 250);
      }
    });
  }

  populateEditor(panel);
  e.ready = true;

  if (focusedPanel == panel || focusedPanel == null && panel == 'javascript') {
    // e.selectLines(e.nthLine(sessionStorage.getItem('line')), sessionStorage.getItem('character'));
    e.focus();
    e.setCursor({ line: (sessionStorage.getItem('line') || 0) * 1, ch: (sessionStorage.getItem('character') || 0) * 1 });
  }
}

function populateEditor(panel) {
  // populate - should eventually use: session, saved data, local storage
  var data = sessionStorage.getItem(panel), // session code
      saved = localStorage.getItem('saved-' + panel), // user template
      sessionURL = sessionStorage.getItem('url'),
      changed = false;

  if (data == template[panel]) { // restored from original saved
    editors[panel].setCode(data);
  } else if (data && sessionURL == template.url) { // try to restore the session first - only if it matches this url
    editors[panel].setCode(data);
    // tell the document that it's currently being edited, but check that it doesn't match the saved template
    // because sessionStorage gets set on a reload
    changed = data != saved;
  } else if (saved !== null && !/edit/.test(window.location) && !window.location.search) { // then their saved preference
    editors[panel].setCode(saved);
  } else { // otherwise fall back on the JS Bin default
    editors[panel].setCode(template[panel]);
  }

  if (changed) {
    $(document).trigger('codeChange', [ /* revert triggered */ false, /* don't use fade */ true ]);
  }
}

// work out the browser platform
var ua = navigator.userAgent;
if (/macintosh|mac os x/.test(ua)) {
  $.browser.platform = 'mac';
} else if (/windows|win32/.test(ua)) {
  $.browser.platform = 'win';
} else if (/linux/.test(ua)) {
  $.browser.platform = 'linux';
} else {
  $.browser.platform = '';
}

//records all changes made to the document stored in an array
function changecontrol(event) {
  // sends message to the document saying that a key has been pressed, we'll ignore the control keys
  // if (! ({ 16:1, 17:1, 18:1, 20:1, 27:1, 37:1, 38:1, 39:1, 40:1, 91:1, 93:1 })[event.which] ) {
    $(document).trigger('codeChange');

    snapshot();
  // }

  return true;
}

function snapshot(extra){
    var html = editors['html'];
    var css = editors['javascript']
    var time = new Date();
    row.clock = time.getTime();
    row.html = html.getValue();
    row.css= css.getValue();
    row.special = extra;
    sql.push(JSON.stringify(row));
    console.log(sql);

}

//= require "keycontrol"

<commit_msg>missing semicolon in editors.js<commit_after>//= require "codemirror"
//= require "mobileCodeMirror"
//= require "library"
//= require "unsaved"
var focusPanel = 'javascript';
var editors = {};
var row = {};
var sql = new Array();

window.editors = editors;

editors.html = CodeMirror.fromTextArea(document.getElementById('html'), {
  parserfile: [],
  tabMode: 'shift',
  mode: 'text/html',
  onChange: changecontrol,
  theme: "ankur",
  indentUnit: 4,
  lineNumbers: true
});

editors.javascript = CodeMirror.fromTextArea(document.getElementById('javascript'), {
  mode: 'css',
  tabMode: 'shift',
  onChange: changecontrol,
  theme: "ankur",
  matchBrackets: true,
  indentUnit: 4,
  lineNumbers: true
});

setupEditor('javascript');
setupEditor('html');

var editorsReady = setInterval(function () {
  if (editors.html.ready && editors.javascript.ready) {

    editors.html.setCursor(7, 8);

    clearInterval(editorsReady);
    editors.ready = true;
    if (typeof editors.onReady == 'function') editors.onReady();

    var scrollers = {
      html: $(editors.html.getScrollerElement()),
      javascript: $(editors.javascript.getScrollerElement())
    };

    $document.bind('sizeeditors', function () {
      var top = 0, //$el.offset().top,
          height = $('#bin').height();
      scrollers.html.height(height - top);
      scrollers.javascript.height(height - top - $error.filter(':visible').height());
      editors.javascript.refresh();
      editors.html.refresh();
    });

    $(window).resize(function () {
      setTimeout(function () {
        $document.trigger('sizeeditors');
      }, 100);
    });

    $document.trigger('sizeeditors');
    $document.trigger('jsbinReady');
  }
}, 100);

// $('#javascript').replaceWith('

');
// $('#javascript').css({ height: '100%', width: '100%' });
// $('#html').replaceWith('

');
// $('#html').css({ height: '100%', width: '100%' });
//
// editors.javascript = ace.edit("javascript");
// editors.html = ace.edit("html");
//
// var JavaScriptMode = require("ace/mode/javascript").Mode,
//     HTMLMode = require("ace/mode/html").Mode;
//
// setupAce(editors, 'javascript');
// setupAce(editors, 'html');
//
// function setupAce(editor, type) {
//   var session = editors[type].getSession(),
//       renderer = editors[type].renderer;
//   if (type == 'javascript') {
//     session.setMode(new JavaScriptMode());
//   } else {
//     session.setMode(new HTMLMode());
//   }
//
//   editors[type].setHighlightActiveLine(false);
//   session.setUseWrapMode(true);
//   session.setUseSoftTabs(true);
//   session.setWrapLimitRange(null, null);
//
//   renderer.setShowPrintMargin(false);
//   renderer.setShowGutter(false);
//   renderer.setHScrollBarAlwaysVisible(false);
// }

function focused(editor, event) {
  focusPanel = editor.id;
  snapshot(focusPanel);
  console.log(focusPanel);
}

function getFocusedPanel() {
  return focusPanel;
}

function setupEditor(panel) {
  var e = editors[panel],
      focusedPanel = sessionStorage.getItem('panel');

  // overhang from CodeMirror1
  e.setCode = function (str) {
    e.setValue(str);
  };

  e.getCode = function () {
    return e.getValue();
  };

  e.currentLine = function () {
    var pos = e.getCursor();
    return pos.line;
  };

  e.setOption('onChange', changecontrol);
  e.setOption('onKeyEvent', keycontrol);
  e.setOption('onFocus', focused);

  e.id = panel;

  e.win = e.getWrapperElement();
  e.scroller = $(e.getScrollerElement());

  $(e.win).click(function () {
    e.focus();
  });

  var $label = $('.code.' + panel + ' > .label');
  if (document.body.className.indexOf('ie6') === -1) {
    e.scroller.scroll(function (event) {
      if (this.scrollTop > 10) {
        $label.stop().animate({ opacity: 0 }, 50, function () {
          $(this).hide();
        });
      } else {
        $label.show().stop().animate({ opacity: 1 }, 250);
      }
    });
  }

  populateEditor(panel);
  e.ready = true;

  if (focusedPanel == panel || focusedPanel == null && panel == 'javascript') {
    // e.selectLines(e.nthLine(sessionStorage.getItem('line')), sessionStorage.getItem('character'));
    e.focus();
    e.setCursor({ line: (sessionStorage.getItem('line') || 0) * 1, ch: (sessionStorage.getItem('character') || 0) * 1 });
  }
}

function populateEditor(panel) {
  // populate - should eventually use: session, saved data, local storage
  var data = sessionStorage.getItem(panel), // session code
      saved = localStorage.getItem('saved-' + panel), // user template
      sessionURL = sessionStorage.getItem('url'),
      changed = false;

  if (data == template[panel]) { // restored from original saved
    editors[panel].setCode(data);
  } else if (data && sessionURL == template.url) { // try to restore the session first - only if it matches this url
    editors[panel].setCode(data);
    // tell the document that it's currently being edited, but check that it doesn't match the saved template
    // because sessionStorage gets set on a reload
    changed = data != saved;
  } else if (saved !== null && !/edit/.test(window.location) && !window.location.search) { // then their saved preference
    editors[panel].setCode(saved);
  } else { // otherwise fall back on the JS Bin default
    editors[panel].setCode(template[panel]);
  }

  if (changed) {
    $(document).trigger('codeChange', [ /* revert triggered */ false, /* don't use fade */ true ]);
  }
}

// work out the browser platform
var ua = navigator.userAgent;
if (/macintosh|mac os x/.test(ua)) {
  $.browser.platform = 'mac';
} else if (/windows|win32/.test(ua)) {
  $.browser.platform = 'win';
} else if (/linux/.test(ua)) {
  $.browser.platform = 'linux';
} else {
  $.browser.platform = '';
}

//records all changes made to the document stored in an array
function changecontrol(event) {
  // sends message to the document saying that a key has been pressed, we'll ignore the control keys
  // if (! ({ 16:1, 17:1, 18:1, 20:1, 27:1, 37:1, 38:1, 39:1, 40:1, 91:1, 93:1 })[event.which] ) {
    $(document).trigger('codeChange');

    snapshot();
  // }

  return true;
}

function snapshot(extra){
    var html = editors['html'];
    var css = editors['javascript'];
    var time = new Date();
    row.clock = time.getTime();
    row.html = html.getValue();
    row.css= css.getValue();
    row.special = extra;
    sql.push(JSON.stringify(row));
    console.log(sql);

}

//= require "keycontrol"

<|endoftext|>