<commit_before>"use strict";
let expect = require("chai").use(require("sinon-chai")).expect;
import proxyquire from "proxyquire";
import sinon from "sinon";

/* eslint-disable no-unused-vars */

describe("NotificationsIOS", () => {
  let deviceEvents = [
    "pushKitRegistered",
    "remoteNotificationsRegistered",
    "notificationReceivedForeground",
    "notificationReceivedBackground",
    "notificationOpened"
  ];

  /*eslint-disable indent*/
  let deviceAddEventListener,
      deviceRemoveEventListener,
      nativeAppAddEventListener,
      nativeAppRemoveEventListener,
      nativeRequestPermissionsWithCategories,
      nativeAbandonPermissions,
      nativeRegisterPushKit,
      nativeBackgroundTimeRemaining;
  let NotificationsIOS, NotificationAction, NotificationCategory;
  let someHandler = () => {};
  /*eslint-enable indent*/

  before(() => {
    deviceAddEventListener = sinon.spy();
    deviceRemoveEventListener = sinon.spy();
    nativeAppAddEventListener = sinon.spy();
    nativeAppRemoveEventListener = sinon.spy();
    nativeRequestPermissionsWithCategories = sinon.spy();
    nativeAbandonPermissions = sinon.spy();
    nativeRegisterPushKit = sinon.spy();
    nativeBackgroundTimeRemaining = sinon.spy();

    let libUnderTest = proxyquire("../index.ios", {
      "react-native": {
        NativeModules: {
          RNNotifications: {
            requestPermissionsWithCategories: nativeRequestPermissionsWithCategories,
            abandonPermissions: nativeAbandonPermissions,
            registerPushKit: nativeRegisterPushKit,
            backgroundTimeRemaining: nativeBackgroundTimeRemaining
          }
        },
        NativeAppEventEmitter: {
          addListener: (...args) => {
            nativeAppAddEventListener(...args);

            return { remove: nativeAppRemoveEventListener };
          }
        },
        DeviceEventEmitter: {
          addListener: (...args) => {
            deviceAddEventListener(...args);

            return { remove: deviceRemoveEventListener };
          }
        },
        "@noCallThru": true
      }
    });

    NotificationsIOS = libUnderTest.default;
    NotificationAction = libUnderTest.NotificationAction;
    NotificationCategory = libUnderTest.NotificationCategory;
  });

  afterEach(() => {
    deviceAddEventListener.reset();
    deviceRemoveEventListener.reset();
    nativeAppAddEventListener.reset();
    nativeAppRemoveEventListener.reset();
    nativeRequestPermissionsWithCategories.reset();
    nativeAbandonPermissions.reset();
    nativeRegisterPushKit.reset();
    nativeBackgroundTimeRemaining.reset();
  });

  after(() => {
    deviceAddEventListener = null;
    deviceRemoveEventListener = null;
    nativeAppAddEventListener = null;
    nativeAppRemoveEventListener = null;
    nativeRequestPermissionsWithCategories = null;
    nativeAbandonPermissions = null;
    nativeRegisterPushKit = null;
    nativeBackgroundTimeRemaining = null;

    NotificationsIOS = null;
    NotificationAction = null;
    NotificationCategory = null;
  });

  describe("Add Event Listener", () => {
    deviceEvents.forEach(event => {
      it(`should subscribe the given handler to device event: ${event}`, () => {
        NotificationsIOS.addEventListener(event, someHandler);

        expect(deviceAddEventListener).to.have.been.calledWith(event, sinon.match.func);
      });
    });

    it("should not subscribe to unknown device events", () => {
      NotificationsIOS.addEventListener("someUnsupportedEvent", someHandler);

      expect(deviceAddEventListener).to.not.have.been.called;
    });
  });

  describe("Remove Event Listener", () => {
    deviceEvents.forEach(event => {
      it(`should unsubscribe the given handler from device event: ${event}`, () => {
        NotificationsIOS.addEventListener(event, someHandler);
        NotificationsIOS.removeEventListener(event, someHandler);

        expect(deviceRemoveEventListener).to.have.been.calledOnce;
      });
    });

    it("should not unsubscribe to unknown device events", () => {
      let someUnsupportedEvent = "someUnsupportedEvent";
      NotificationsIOS.addEventListener(someUnsupportedEvent, someHandler);
      NotificationsIOS.removeEventListener(someUnsupportedEvent, someHandler);

      expect(deviceRemoveEventListener).to.not.have.been.called;
    });
  });

  describe("Notification actions handling", () => {
    let someAction, someCategory;

    let actionOpts = {
      activationMode: "foreground",
      title: "someAction",
      behavior: "default",
      identifier: "SOME_ACTION"
    };

    beforeEach(() => {
      someAction = new NotificationAction(actionOpts, () => {});

      someCategory = new NotificationCategory({
        identifier: "SOME_CATEGORY",
        actions: [someAction],
        context: "default"
      });
    });

    describe("register push notifications", () => {
      it("should call native request permissions with array of categories", () => {
        NotificationsIOS.requestPermissions([someCategory]);

        expect(nativeRequestPermissionsWithCategories).to.have.been.calledWith([{
          identifier: "SOME_CATEGORY",
          actions: [actionOpts],
          context: "default"
        }]);
      });

      it("should call native request permissions with empty array if no categories specified", () => {
        NotificationsIOS.requestPermissions();

        expect(nativeRequestPermissionsWithCategories).to.have.been.calledWith([]);
      });

      it("should subscribe to 'notificationActionReceived' event once, with a single event handler", () => {
        NotificationsIOS.requestPermissions([someCategory]);

        expect(nativeAppAddEventListener).to.have.been.calledOnce;
        expect(nativeAppAddEventListener).to.have.been.calledWith("notificationActionReceived", sinon.match.func);
      });
    });

    describe("reset categories", () => {
      it("should remove 'notificationActionReceived' event handler", () => {
        NotificationsIOS.resetCategories();

        expect(nativeAppRemoveEventListener).to.have.been.calledOnce;
      });
    });
  });

  describe("register push kit for background notifications", function () {
    it("should call native register push kit method", function () {
      NotificationsIOS.registerPushKit();

      expect(nativeRegisterPushKit).to.have.been.called;
    });
  });

  describe("Abandon push notifications permissions", () => {
    it("should call native abandon permissions method", () => {
      NotificationsIOS.abandonPermissions();

      expect(nativeAbandonPermissions).to.have.been.called;
    });
  });

  describe("Get background remaining time", () => {
    it("should call native background remaining time method", () => {
      NotificationsIOS.backgroundTimeRemaining(time => { });

      expect(nativeBackgroundTimeRemaining).to.have.been.called;
    });
  });
});
<commit_msg>fix background remaining time test<commit_after>"use strict";
let expect = require("chai").use(require("sinon-chai")).expect;
import proxyquire from "proxyquire";
import sinon from "sinon";

/* eslint-disable no-unused-vars */

describe("NotificationsIOS", () => {
  let deviceEvents = [
    "pushKitRegistered",
    "remoteNotificationsRegistered",
    "notificationReceivedForeground",
    "notificationReceivedBackground",
    "notificationOpened"
  ];

  /*eslint-disable indent*/
  let deviceAddEventListener,
      deviceRemoveEventListener,
      nativeAppAddEventListener,
      nativeAppRemoveEventListener,
      nativeRequestPermissionsWithCategories,
      nativeAbandonPermissions,
      nativeRegisterPushKit,
      nativeBackgroundTimeRemaining;
  let NotificationsIOS, NotificationAction, NotificationCategory;
  let someHandler = () => {};
  /*eslint-enable indent*/

  before(() => {
    deviceAddEventListener = sinon.spy();
    deviceRemoveEventListener = sinon.spy();
    nativeAppAddEventListener = sinon.spy();
    nativeAppRemoveEventListener = sinon.spy();
    nativeRequestPermissionsWithCategories = sinon.spy();
    nativeAbandonPermissions = sinon.spy();
    nativeRegisterPushKit = sinon.spy();
    nativeBackgroundTimeRemaining = sinon.spy();

    let libUnderTest = proxyquire("../index.ios", {
      "react-native": {
        NativeModules: {
          RNNotifications: {
            requestPermissionsWithCategories: nativeRequestPermissionsWithCategories,
            abandonPermissions: nativeAbandonPermissions,
            registerPushKit: nativeRegisterPushKit,
            backgroundTimeRemaining: nativeBackgroundTimeRemaining
          }
        },
        NativeAppEventEmitter: {
          addListener: (...args) => {
            nativeAppAddEventListener(...args);

            return { remove: nativeAppRemoveEventListener };
          }
        },
        DeviceEventEmitter: {
          addListener: (...args) => {
            deviceAddEventListener(...args);

            return { remove: deviceRemoveEventListener };
          }
        },
        "@noCallThru": true
      }
    });

    NotificationsIOS = libUnderTest.default;
    NotificationAction = libUnderTest.NotificationAction;
    NotificationCategory = libUnderTest.NotificationCategory;
  });

  afterEach(() => {
    deviceAddEventListener.reset();
    deviceRemoveEventListener.reset();
    nativeAppAddEventListener.reset();
    nativeAppRemoveEventListener.reset();
    nativeRequestPermissionsWithCategories.reset();
    nativeAbandonPermissions.reset();
    nativeRegisterPushKit.reset();
    nativeBackgroundTimeRemaining.reset();
  });

  after(() => {
    deviceAddEventListener = null;
    deviceRemoveEventListener = null;
    nativeAppAddEventListener = null;
    nativeAppRemoveEventListener = null;
    nativeRequestPermissionsWithCategories = null;
    nativeAbandonPermissions = null;
    nativeRegisterPushKit = null;
    nativeBackgroundTimeRemaining = null;

    NotificationsIOS = null;
    NotificationAction = null;
    NotificationCategory = null;
  });

  describe("Add Event Listener", () => {
    deviceEvents.forEach(event => {
      it(`should subscribe the given handler to device event: ${event}`, () => {
        NotificationsIOS.addEventListener(event, someHandler);

        expect(deviceAddEventListener).to.have.been.calledWith(event, sinon.match.func);
      });
    });

    it("should not subscribe to unknown device events", () => {
      NotificationsIOS.addEventListener("someUnsupportedEvent", someHandler);

      expect(deviceAddEventListener).to.not.have.been.called;
    });
  });

  describe("Remove Event Listener", () => {
    deviceEvents.forEach(event => {
      it(`should unsubscribe the given handler from device event: ${event}`, () => {
        NotificationsIOS.addEventListener(event, someHandler);
        NotificationsIOS.removeEventListener(event, someHandler);

        expect(deviceRemoveEventListener).to.have.been.calledOnce;
      });
    });

    it("should not unsubscribe to unknown device events", () => {
      let someUnsupportedEvent = "someUnsupportedEvent";
      NotificationsIOS.addEventListener(someUnsupportedEvent, someHandler);
      NotificationsIOS.removeEventListener(someUnsupportedEvent, someHandler);

      expect(deviceRemoveEventListener).to.not.have.been.called;
    });
  });

  describe("Notification actions handling", () => {
    let someAction, someCategory;

    let actionOpts = {
      activationMode: "foreground",
      title: "someAction",
      behavior: "default",
      identifier: "SOME_ACTION"
    };

    beforeEach(() => {
      someAction = new NotificationAction(actionOpts, () => {});

      someCategory = new NotificationCategory({
        identifier: "SOME_CATEGORY",
        actions: [someAction],
        context: "default"
      });
    });

    describe("register push notifications", () => {
      it("should call native request permissions with array of categories", () => {
        NotificationsIOS.requestPermissions([someCategory]);

        expect(nativeRequestPermissionsWithCategories).to.have.been.calledWith([{
          identifier: "SOME_CATEGORY",
          actions: [actionOpts],
          context: "default"
        }]);
      });

      it("should call native request permissions with empty array if no categories specified", () => {
        NotificationsIOS.requestPermissions();

        expect(nativeRequestPermissionsWithCategories).to.have.been.calledWith([]);
      });

      it("should subscribe to 'notificationActionReceived' event once, with a single event handler", () => {
        NotificationsIOS.requestPermissions([someCategory]);

        expect(nativeAppAddEventListener).to.have.been.calledOnce;
        expect(nativeAppAddEventListener).to.have.been.calledWith("notificationActionReceived", sinon.match.func);
      });
    });

    describe("reset categories", () => {
      it("should remove 'notificationActionReceived' event handler", () => {
        NotificationsIOS.resetCategories();

        expect(nativeAppRemoveEventListener).to.have.been.calledOnce;
      });
    });
  });

  describe("register push kit for background notifications", function () {
    it("should call native register push kit method", function () {
      NotificationsIOS.registerPushKit();

      expect(nativeRegisterPushKit).to.have.been.called;
    });
  });

  describe("Abandon push notifications permissions", () => {
    it("should call native abandon permissions method", () => {
      NotificationsIOS.abandonPermissions();

      expect(nativeAbandonPermissions).to.have.been.called;
    });
  });

  describe("Get background remaining time", () => {
    it("should call native background remaining time method", () => {
      let someCallback = (time) => { };

      NotificationsIOS.backgroundTimeRemaining(someCallback);

      expect(nativeBackgroundTimeRemaining).to.have.been.calledWith(someCallback);
    });
  });
});
<|endoftext|>


<commit_before>var http = require('http'),
    assert = require('assert'),
    cb = require('assert-called'),
    jsonquest = require('../');

var server = http.createServer(cb(function (req, res) {
  var data = '';

  assert.equal(req.method, 'PUT');
  assert.equal(req.url, '/hello');
  assert.equal(req.headers['content-type'], 'application/json');

  req.on('readable', function () {
    var chunk = req.read();
    if (chunk) {
      data += chunk;
    }
  });

  req.on('end', function () {
    assert.deepEqual(JSON.parse(data), { hello: 'world' });

    res.writeHead(201, { 'content-type': 'application/json' });
    res.write(JSON.stringify({ world: 'hello' }));
    res.end();
  });
})).listen(9999, cb(function () {
  jsonquest({
    host: 'localhost',
    port: 9999,
    path: '/hello',
    body: { hello: 'world' },
    method: 'PUT',
    protocol: 'http'
  }, cb(function (err, res, body) {
    assert.equal(res.statusCode, 201);
    assert.deepEqual(body, { world: 'hello' });
    assert.equal(res.headers['content-type'], 'application/json');

    server.close();
  }));
}));
<commit_msg>[test] Fix tests under node 0.8<commit_after>var http = require('http'),
    assert = require('assert'),
    cb = require('assert-called'),
    jsonquest = require('../');

var server = http.createServer(cb(function (req, res) {
  var data = '';

  assert.equal(req.method, 'PUT');
  assert.equal(req.url, '/hello');
  assert.equal(req.headers['content-type'], 'application/json');

  req.on('data', function (chunk) {
    data += chunk;
  });

  req.on('end', function () {
    assert.deepEqual(JSON.parse(data), { hello: 'world' });

    res.writeHead(201, { 'content-type': 'application/json' });
    res.write(JSON.stringify({ world: 'hello' }));
    res.end();
  });
})).listen(9999, cb(function () {
  jsonquest({
    host: 'localhost',
    port: 9999,
    path: '/hello',
    body: { hello: 'world' },
    method: 'PUT',
    protocol: 'http'
  }, cb(function (err, res, body) {
    assert.equal(res.statusCode, 201);
    assert.deepEqual(body, { world: 'hello' });
    assert.equal(res.headers['content-type'], 'application/json');

    server.close();
  }));
}));
<|endoftext|>


<commit_before>const chai = require('chai');
const assert = chai.assert;
const stub = require('./support/stub');
const JunkFood = require('../lib/junk-food')
const Overlord = require('../lib/overlord')
const World = require('../lib/world')

describe('junkFood', function(){
  context('with default attributes', function(){
    var junkFood = new JunkFood();

    it('should be instantiated', function(){
      assert.isObject(junkFood);
    });

    it('should have an x-coordinate', function(){
      var world = new World(600, 600, 'context');
      var overlordX = world.overlord.x + world.overlord.height;
      var junkfoodX = world.junkFood.x;
      assert.equal(junkfoodX, overlordX);
    });

    it('should have an y-coordinate', function(){
      var world = new World(600, 600, 'context');
      var overlordY = world.overlord.y;
      var junkfoodY = world.junkFood.y;
      assert.equal(junkfoodY, overlordY);
    });

    it('should have a height', function(){
      assert.equal(junkFood.height, 20);
    });

    it('should have a width', function(){
      assert.equal(junkFood.width, 20);
    });

    it('should have a speed', function(){
      assert.equal(junkFood.speed, 0.5);
    });
  });

  context('moveJunkFood', function(){
    var context = stub().of('beginPath').of('fillRect').of('closePath').of('fill');
    var junkFood = new JunkFood({context: context});
    junkFood.moveJunkFood();

    it('should calls correct functions on context', function(){
      assert.equal(context.beginPath.calls.length, 1);
      assert.equal(context.fillRect.calls.length, 1);
      assert.equal(context.closePath.calls.length, 1);
      assert.equal(context.fill.calls.length, 1);
    });
  });

  // context('dropRandomFood', function(){
  //   var junkFood = new JunkFood();
  //
  //   it('should assign a random healthy food type', function(){
  //     var newFoodHash = junkFood.dropRandomFood();
  //     var newFood = new JunkFood(newFoodHash);
  //     assert.notEqual(newFood['type'], 'carrot');
  //   });
  //
  //   it('should assign a random healthy food color', function(){
  //     var newFoodHash = junkFood.dropRandomFood();
  //     var newFood = new JunkFood(newFoodHash);
  //     assert.notEqual(newFood['color'], 'orange');
  //   });
  //
  //   it('should assign a random healthy food score', function(){
  //     var newFoodHash = junkFood.dropRandomFood();
  //     var newFood = new JunkFood(newFoodHash);
  //     assert.notEqual(newFood['score'], 100);
  //   });
  //
  //   it('should assign a random healthy x coordinate', function(){
  //     var newFoodHash = junkFood.dropRandomFood();
  //     var newFood = new JunkFood(newFoodHash);
  //     assert.notEqual(newFood['x'], 500);
  //   });
  //
  //   it('should assign a random healthy y coordinate', function(){
  //     var newFoodHash = junkFood.dropRandomFood();
  //     var newFood = new JunkFood(newFoodHash);
  //     assert.equal(newFood['y'], 0);
  //   });
  // });
});
<commit_msg>add dropJunkFood prototype function add dropJunkFood test context<commit_after>const chai = require('chai');
const assert = chai.assert;
const stub = require('./support/stub');
const JunkFood = require('../lib/junk-food')
const Overlord = require('../lib/overlord')
const World = require('../lib/world')

describe('junkFood', function(){
  context('with default attributes', function(){
    var junkFood = new JunkFood();

    it('should be instantiated', function(){
      assert.isObject(junkFood);
    });

    it('should have an x-coordinate', function(){
      var world = new World(600, 600, 'context');
      var overlordX = world.overlord.x + world.overlord.height;
      var junkfoodX = world.junkFood.x;
      assert.equal(junkfoodX, overlordX);
    });

    it('should have an y-coordinate', function(){
      var world = new World(600, 600, 'context');
      var overlordY = world.overlord.y;
      var junkfoodY = world.junkFood.y;
      assert.equal(junkfoodY, overlordY);
    });

    it('should have a height', function(){
      assert.equal(junkFood.height, 20);
    });

    it('should have a width', function(){
      assert.equal(junkFood.width, 20);
    });

    it('should have a speed', function(){
      assert.equal(junkFood.speed, 0.5);
    });
  });

  context('moveJunkFood', function(){
    var context = stub().of('beginPath').of('fillRect').of('closePath').of('fill');
    var junkFood = new JunkFood({context: context});
    junkFood.moveJunkFood();

    it('should calls correct functions on context', function(){
      assert.equal(context.beginPath.calls.length, 1);
      assert.equal(context.fillRect.calls.length, 1);
      assert.equal(context.closePath.calls.length, 1);
      assert.equal(context.fill.calls.length, 1);
    });
  });

  context('dropRandomFood', function(){
    var junkFood = new JunkFood();

    it('should assign a random healthy food type', function(){
      var newFoodHash = junkFood.dropJunkFood();
      var newFood = new JunkFood(newFoodHash);
      assert.notEqual(newFood['type'], 'cheeto');
    });

  //   it('should assign a random healthy food color', function(){
  //     var newFoodHash = junkFood.dropRandomFood();
  //     var newFood = new JunkFood(newFoodHash);
  //     assert.notEqual(newFood['color'], 'orange');
  //   });
  //
  //   it('should assign a random healthy food score', function(){
  //     var newFoodHash = junkFood.dropRandomFood();
  //     var newFood = new JunkFood(newFoodHash);
  //     assert.notEqual(newFood['score'], 100);
  //   });
  //
  //   it('should assign a random healthy x coordinate', function(){
  //     var newFoodHash = junkFood.dropRandomFood();
  //     var newFood = new JunkFood(newFoodHash);
  //     assert.notEqual(newFood['x'], 500);
  //   });
  //
  //   it('should assign a random healthy y coordinate', function(){
  //     var newFoodHash = junkFood.dropRandomFood();
  //     var newFood = new JunkFood(newFoodHash);
  //     assert.equal(newFood['y'], 0);
  //   });
  });
});
<|endoftext|>


<commit_before>const chai = require('chai');
const assert = chai.assert;
const stub = require('./support/stub');
const JunkFood = require('../lib/junk-food')
const Overlord = require('../lib/overlord')
const World = require('../lib/world')

describe('junkFood', function(){
  context('with default attributes', function(){
    var junkFood = new JunkFood();

    it('should be instantiated', function(){
      assert.isObject(junkFood);
    });

    it('should have an x-coordinate', function(){
      var world = new World(600, 600, 'context');
      var overlordX = world.overlord.x + world.overlord.height;
      var junkfoodX = world.junkFood.x;
      assert.equal(junkfoodX, overlordX);
    });

    it('should have an y-coordinate', function(){
      var world = new World(600, 600, 'context');
      var overlordY = world.overlord.y;
      var junkfoodY = world.junkFood.y;
      assert.equal(junkfoodY, overlordY);
    });

    it('should have a height', function(){
      assert.equal(junkFood.height, 20);
    });

    it('should have a width', function(){
      assert.equal(junkFood.width, 20);
    });

    it('should have a speed', function(){
      assert.equal(junkFood.speed, 0.5);
    });
  });

  context('moveJunkFood', function(){
    var context = stub().of('beginPath').of('fillRect').of('closePath').of('fill');
    var junkFood = new JunkFood({context: context});
    junkFood.moveJunkFood();

    it('should calls correct functions on context', function(){
      assert.equal(context.beginPath.calls.length, 1);
      assert.equal(context.fillRect.calls.length, 1);
      assert.equal(context.closePath.calls.length, 1);
      assert.equal(context.fill.calls.length, 1);
    });
  });

  context('dropRandomFood', function(){
    var junkFood = new JunkFood();

    it('should assign a random healthy food type', function(){
      var newFoodHash = junkFood.dropJunkFood();
      var newFood = new JunkFood(newFoodHash);
      assert.notEqual(newFood['type'], 'cheeto');
    });

  //   it('should assign a random healthy food color', function(){
  //     var newFoodHash = junkFood.dropRandomFood();
  //     var newFood = new JunkFood(newFoodHash);
  //     assert.notEqual(newFood['color'], 'orange');
  //   });
  //
  //   it('should assign a random healthy food score', function(){
  //     var newFoodHash = junkFood.dropRandomFood();
  //     var newFood = new JunkFood(newFoodHash);
  //     assert.notEqual(newFood['score'], 100);
  //   });
  //
  //   it('should assign a random healthy x coordinate', function(){
  //     var newFoodHash = junkFood.dropRandomFood();
  //     var newFood = new JunkFood(newFoodHash);
  //     assert.notEqual(newFood['x'], 500);
  //   });
  //
  //   it('should assign a random healthy y coordinate', function(){
  //     var newFoodHash = junkFood.dropRandomFood();
  //     var newFood = new JunkFood(newFoodHash);
  //     assert.equal(newFood['y'], 0);
  //   });
  });
});
<commit_msg>add tests for junk-food functions<commit_after>const chai = require('chai');
const assert = chai.assert;
const stub = require('./support/stub');
const JunkFood = require('../lib/junk-food')
const Overlord = require('../lib/overlord')
const World = require('../lib/world')

describe('junkFood', function(){
  context('with default attributes', function(){
    var junkFood = new JunkFood();

    it('should be instantiated', function(){
      assert.isObject(junkFood);
    });

    it('should have an x-coordinate', function(){
      var world = new World(600, 600, 'context');
      var overlordX = world.overlord.x + world.overlord.height;
      var junkfoodX = world.junkFood.x;
      assert.equal(junkfoodX, overlordX);
    });

    it('should have an y-coordinate', function(){
      var world = new World(600, 600, 'context');
      var overlordY = world.overlord.y;
      var junkfoodY = world.junkFood.y;
      assert.equal(junkfoodY, overlordY);
    });

    it('should have a height', function(){
      assert.equal(junkFood.height, 20);
    });

    it('should have a width', function(){
      assert.equal(junkFood.width, 20);
    });

    it('should have a speed', function(){
      assert.equal(junkFood.speed, 0.5);
    });
  });

  context('moveJunkFood', function(){
    var context = stub().of('beginPath').of('fillRect').of('closePath').of('fill');
    var junkFood = new JunkFood({context: context});
    junkFood.moveJunkFood();

    it('should calls correct functions on context', function(){
      assert.equal(context.beginPath.calls.length, 1);
      assert.equal(context.fillRect.calls.length, 1);
      assert.equal(context.closePath.calls.length, 1);
      assert.equal(context.fill.calls.length, 1);
    });
  });

  context('dropJunkFood', function(){
    var junkFood = new JunkFood();

    it('should assign a random healthy food type', function(){
      var newFoodHash = junkFood.dropJunkFood();
      var newFood = new JunkFood(newFoodHash);
      assert.notEqual(newFood['type'], 'cheeto');
    });

    it('should assign a random junk food color', function(){
      var newFoodHash = junkFood.dropJunkFood();
      var newFood = new JunkFood(newFoodHash);
      assert.notEqual(newFood['color'], 'yellow');
    });
  });
});
<|endoftext|>


<commit_before>exports.config = {

  specs: ['e2e/responsiveSpec.js','e2e/scenariosSpec.js'],

  capabilities: {
    browserName: 'chrome',
    shardTestFiles: true,
    maxInstances: 2
  },

	onPrepare: function() {
		// implicit and page load timeouts
		browser.manage().timeouts().pageLoadTimeout(40000);
		browser.manage().timeouts().implicitlyWait(25000);
 	},

  	chromeDriver: '../node_modules/protractor/selenium/chromedriver',

  	baseUrl: 'http://localhost:8080/',

  	framework: 'jasmine',

};<commit_msg>Grunt && CircleCi && Heroku: Angular is not found...Deletng the 2 instances of webdriver.<commit_after>exports.config = {

  specs: ['e2e/responsiveSpec.js','e2e/scenariosSpec.js'],

  capabilities: {
    browserName: 'chrome',
    shardTestFiles: true,
    maxInstances: 1
  },

	onPrepare: function() {
		// implicit and page load timeouts
		browser.manage().timeouts().pageLoadTimeout(40000);
		browser.manage().timeouts().implicitlyWait(25000);
 	},

  	chromeDriver: '../node_modules/protractor/selenium/chromedriver',

  	baseUrl: 'http://localhost:8080/',

  	framework: 'jasmine',

};<|endoftext|>


<commit_before>/* @flow */

import { CompositeDisposable } from "atom";
import {
  observable,
  computed,
  action,
  isObservableMap,
  keys,
  values
} from "mobx";
import { isMultilanguageGrammar, getEmbeddedScope } from "./../utils";
import _ from "lodash";

import Config from "./../config";
import * as codeManager from "./../code-manager";
import MarkerStore from "./markers";
import kernelManager from "./../kernel-manager";
import Kernel from "./../kernel";

const commutable = require("@nteract/commutable");

export class Store {
  subscriptions = new CompositeDisposable();
  markers = new MarkerStore();
  @observable
  runningKernels: Array<Kernel> = [];
  @observable
  kernelMapping: KernelMapping = new Map();
  @observable
  startingKernels: Map<string, boolean> = new Map();
  @observable
  editor = atom.workspace.getActiveTextEditor();
  @observable
  grammar: ?atom$Grammar;
  @observable
  configMapping: Map<string, ?mixed> = new Map();
  globalMode: boolean = Boolean(atom.config.get("Hydrogen.globalMode"));

  @computed
  get kernel(): ?Kernel {
    if (this.globalMode) {
      if (!this.grammar) return null;
      const currentScopeName = this.grammar.scopeName;
      return this.runningKernels.filter(
        k => k.grammar.scopeName === currentScopeName
      )[0];
    }

    if (!this.filePath) return null;
    const kernelOrMap = this.kernelMapping.get(this.filePath);
    if (!kernelOrMap || kernelOrMap instanceof Kernel) return kernelOrMap;
    if (this.grammar) return kernelOrMap.get(this.grammar.name);
  }

  @computed
  get filePath(): ?string {
    return this.editor ? this.editor.getPath() : null;
  }

  @computed
  get filePaths(): Array<?string> {
    return keys(this.kernelMapping);
  }

  @computed
  get notebook() {
    const editor = this.editor;
    if (!editor) {
      return null;
    }
    let notebook = commutable.emptyNotebook;
    if (this.kernel) {
      notebook = notebook.setIn(
        ["metadata", "kernelspec"],
        this.kernel.transport.kernelSpec
      );
    }
    const cellRanges = codeManager.getCells(editor);
    _.forEach(cellRanges, cell => {
      const { start, end } = cell;
      let source = codeManager.getTextInRange(editor, start, end);
      source = source ? source : "";
      const cellType = codeManager.getMetadataForRow(editor, start);
      let newCell;
      if (cellType === "code") {
        newCell = commutable.emptyCodeCell.set("source", source);
      } else if (cellType === "markdown") {
        source = codeManager.removeCommentsMarkdownCell(editor, source);
        newCell = commutable.emptyMarkdownCell.set("source", source);
      }
      notebook = commutable.appendCellToNotebook(notebook, newCell);
    });
    return commutable.toJS(notebook);
  }

  @action
  startKernel(kernelDisplayName: string) {
    this.startingKernels.set(kernelDisplayName, true);
  }

  @action
  newKernel(
    kernel: Kernel,
    filePath: string,
    editor: atom$TextEditor,
    grammar: atom$Grammar
  ) {
    if (isMultilanguageGrammar(editor.getGrammar())) {
      if (!this.kernelMapping.has(filePath)) {
        this.kernelMapping.set(filePath, new Map());
      }
      const multiLanguageMap = this.kernelMapping.get(filePath);
      multiLanguageMap.set(grammar.name, kernel);
    } else {
      this.kernelMapping.set(filePath, kernel);
    }
    const index = this.runningKernels.findIndex(k => k === kernel);
    if (index === -1) {
      this.runningKernels.push(kernel);
    }
    // delete startingKernel since store.kernel now in place to prevent duplicate kernel
    this.startingKernels.delete(kernel.kernelSpec.display_name);
  }

  @action
  deleteKernel(kernel: Kernel) {
    const grammar = kernel.grammar.name;
    const files = this.getFilesForKernel(kernel);

    files.forEach(file => {
      const kernelOrMap = this.kernelMapping.get(file);
      if (!kernelOrMap) return;
      if (kernelOrMap instanceof Kernel) {
        this.kernelMapping.delete(file);
      } else {
        kernelOrMap.delete(grammar);
      }
    });

    this.runningKernels = this.runningKernels.filter(k => k !== kernel);
  }

  getFilesForKernel(kernel: Kernel): Array<?string> {
    const grammar = kernel.grammar.name;
    return this.filePaths.filter(file => {
      const kernelOrMap = this.kernelMapping.get(file);
      return kernelOrMap instanceof Kernel
        ? kernelOrMap === kernel
        : kernelOrMap.get(grammar) === kernel;
    });
  }

  @action
  dispose() {
    this.subscriptions.dispose();
    this.markers.clear();
    this.runningKernels.forEach(kernel => kernel.destroy());
    this.runningKernels = [];
    this.kernelMapping.clear();
  }

  @action
  updateEditor(editor: ?atom$TextEditor) {
    this.editor = editor;
    this.setGrammar(editor);

    if (this.globalMode && this.kernel && editor) {
      const fileName = editor.getPath();
      if (!fileName) return;
      this.kernelMapping.set(fileName, this.kernel);
    }
  }

  @action
  setGrammar(editor: ?atom$TextEditor) {
    if (!editor) {
      this.grammar = null;
      return;
    }

    let grammar = editor.getGrammar();

    if (isMultilanguageGrammar(grammar)) {
      const embeddedScope = getEmbeddedScope(
        editor,
        editor.getCursorBufferPosition()
      );

      if (embeddedScope) {
        const scope = embeddedScope.replace(".embedded", "");
        grammar = atom.grammars.grammarForScopeName(scope);
      }
    }

    this.grammar = grammar;
  }

  @action
  setConfigValue(keyPath: string, newValue: ?mixed) {
    if (!newValue) {
      newValue = atom.config.get(keyPath);
    }
    this.configMapping.set(keyPath, newValue);
  }

  forceEditorUpdate() {
    // Force mobx to recalculate filePath (which depends on editor observable)

    const currentEditor = this.editor;
    this.updateEditor(null);
    this.updateEditor(currentEditor);
  }
}

const store = new Store();
export default store;

// For debugging
window.hydrogen_store = store;
<commit_msg>Remove trailing newline for notebook export if it exists. See #1512<commit_after>/* @flow */

import { CompositeDisposable } from "atom";
import {
  observable,
  computed,
  action,
  isObservableMap,
  keys,
  values
} from "mobx";
import { isMultilanguageGrammar, getEmbeddedScope } from "./../utils";
import _ from "lodash";

import Config from "./../config";
import * as codeManager from "./../code-manager";
import MarkerStore from "./markers";
import kernelManager from "./../kernel-manager";
import Kernel from "./../kernel";

const commutable = require("@nteract/commutable");

export class Store {
  subscriptions = new CompositeDisposable();
  markers = new MarkerStore();
  @observable
  runningKernels: Array<Kernel> = [];
  @observable
  kernelMapping: KernelMapping = new Map();
  @observable
  startingKernels: Map<string, boolean> = new Map();
  @observable
  editor = atom.workspace.getActiveTextEditor();
  @observable
  grammar: ?atom$Grammar;
  @observable
  configMapping: Map<string, ?mixed> = new Map();
  globalMode: boolean = Boolean(atom.config.get("Hydrogen.globalMode"));

  @computed
  get kernel(): ?Kernel {
    if (this.globalMode) {
      if (!this.grammar) return null;
      const currentScopeName = this.grammar.scopeName;
      return this.runningKernels.filter(
        k => k.grammar.scopeName === currentScopeName
      )[0];
    }

    if (!this.filePath) return null;
    const kernelOrMap = this.kernelMapping.get(this.filePath);
    if (!kernelOrMap || kernelOrMap instanceof Kernel) return kernelOrMap;
    if (this.grammar) return kernelOrMap.get(this.grammar.name);
  }

  @computed
  get filePath(): ?string {
    return this.editor ? this.editor.getPath() : null;
  }

  @computed
  get filePaths(): Array<?string> {
    return keys(this.kernelMapping);
  }

  @computed
  get notebook() {
    const editor = this.editor;
    if (!editor) return null;
    let notebook = commutable.emptyNotebook;
    if (this.kernel) {
      notebook = notebook.setIn(
        ["metadata", "kernelspec"],
        this.kernel.transport.kernelSpec
      );
    }
    const cellRanges = codeManager.getCells(editor);
    _.forEach(cellRanges, cell => {
      const { start, end } = cell;
      let source = codeManager.getTextInRange(editor, start, end);
      source = source ? source : "";
      if (source.slice(-1) === "\n") source = source.slice(0, -1);
      const cellType = codeManager.getMetadataForRow(editor, start);
      let newCell;
      if (cellType === "code") {
        newCell = commutable.emptyCodeCell.set("source", source);
      } else if (cellType === "markdown") {
        source = codeManager.removeCommentsMarkdownCell(editor, source);
        newCell = commutable.emptyMarkdownCell.set("source", source);
      }
      notebook = commutable.appendCellToNotebook(notebook, newCell);
    });
    return commutable.toJS(notebook);
  }

  @action
  startKernel(kernelDisplayName: string) {
    this.startingKernels.set(kernelDisplayName, true);
  }

  @action
  newKernel(
    kernel: Kernel,
    filePath: string,
    editor: atom$TextEditor,
    grammar: atom$Grammar
  ) {
    if (isMultilanguageGrammar(editor.getGrammar())) {
      if (!this.kernelMapping.has(filePath)) {
        this.kernelMapping.set(filePath, new Map());
      }
      const multiLanguageMap = this.kernelMapping.get(filePath);
      multiLanguageMap.set(grammar.name, kernel);
    } else {
      this.kernelMapping.set(filePath, kernel);
    }
    const index = this.runningKernels.findIndex(k => k === kernel);
    if (index === -1) {
      this.runningKernels.push(kernel);
    }
    // delete startingKernel since store.kernel now in place to prevent duplicate kernel
    this.startingKernels.delete(kernel.kernelSpec.display_name);
  }

  @action
  deleteKernel(kernel: Kernel) {
    const grammar = kernel.grammar.name;
    const files = this.getFilesForKernel(kernel);

    files.forEach(file => {
      const kernelOrMap = this.kernelMapping.get(file);
      if (!kernelOrMap) return;
      if (kernelOrMap instanceof Kernel) {
        this.kernelMapping.delete(file);
      } else {
        kernelOrMap.delete(grammar);
      }
    });

    this.runningKernels = this.runningKernels.filter(k => k !== kernel);
  }

  getFilesForKernel(kernel: Kernel): Array<?string> {
    const grammar = kernel.grammar.name;
    return this.filePaths.filter(file => {
      const kernelOrMap = this.kernelMapping.get(file);
      return kernelOrMap instanceof Kernel
        ? kernelOrMap === kernel
        : kernelOrMap.get(grammar) === kernel;
    });
  }

  @action
  dispose() {
    this.subscriptions.dispose();
    this.markers.clear();
    this.runningKernels.forEach(kernel => kernel.destroy());
    this.runningKernels = [];
    this.kernelMapping.clear();
  }

  @action
  updateEditor(editor: ?atom$TextEditor) {
    this.editor = editor;
    this.setGrammar(editor);

    if (this.globalMode && this.kernel && editor) {
      const fileName = editor.getPath();
      if (!fileName) return;
      this.kernelMapping.set(fileName, this.kernel);
    }
  }

  @action
  setGrammar(editor: ?atom$TextEditor) {
    if (!editor) {
      this.grammar = null;
      return;
    }

    let grammar = editor.getGrammar();

    if (isMultilanguageGrammar(grammar)) {
      const embeddedScope = getEmbeddedScope(
        editor,
        editor.getCursorBufferPosition()
      );

      if (embeddedScope) {
        const scope = embeddedScope.replace(".embedded", "");
        grammar = atom.grammars.grammarForScopeName(scope);
      }
    }

    this.grammar = grammar;
  }

  @action
  setConfigValue(keyPath: string, newValue: ?mixed) {
    if (!newValue) {
      newValue = atom.config.get(keyPath);
    }
    this.configMapping.set(keyPath, newValue);
  }

  forceEditorUpdate() {
    // Force mobx to recalculate filePath (which depends on editor observable)

    const currentEditor = this.editor;
    this.updateEditor(null);
    this.updateEditor(currentEditor);
  }
}

const store = new Store();
export default store;

// For debugging
window.hydrogen_store = store;
<|endoftext|>


<commit_before>"use strict";

var proto = require("./state/proto");
var clone = require("clone");

/**
 * Creates a state proxy, managing the internal values using getters/setters
 *
 * @param {object} props        - Object of key => propObjects
 * @param {function} observer   - function to call when change occurs
 * @param {bool} strict         - if strict, state will not update on bad types
 */
function createStoreState(props, observer, strict) {
    var state = Object.create(proto, Object.keys(props).reduce(function(state, key) {
        var _value;

        state[key] = {
            enumerable: true,
            get: function() {
                if (!(_value && this.__dirty[key]))
                    return this.__default(props[key].default);

                return clone(_value);
            },

            set: function(val) {
                if (this.__check(props[key].type, strict, key, val)) {
                    var prevValue = _value;
                    _value = val;
                    observer(key, val, prevValue);
                    this.__dirty[key] = true;
                }
            }
        };

        return state;
    }, {}));

    var dirty = Object.keys(props).reduce(function(dirty, key) {
        dirty[key] = false;
        return dirty;
    }, {});

    Object.defineProperty(state, "__dirty", {
        value: dirty,
    });

    return Object.freeze(state);
}

module.exports = createStoreState;<commit_msg>fix dirty check: set dirty before observer<commit_after>"use strict";

var proto = require("./state/proto");
var clone = require("clone");

/**
 * Creates a state proxy, managing the internal values using getters/setters
 *
 * @param {object} props        - Object of key => propObjects
 * @param {function} observer   - function to call when change occurs
 * @param {bool} strict         - if strict, state will not update on bad types
 */
function createStoreState(props, observer, strict) {
    var state = Object.create(proto, Object.keys(props).reduce(function(state, key) {
        var _value;

        state[key] = {
            enumerable: true,
            get: function() {
                if (!(_value && this.__dirty[key]))
                    return this.__default(props[key].default);

                return clone(_value);
            },

            set: function(val) {
                if (this.__check(props[key].type, strict, key, val)) {
                    this.__dirty[key] = true;
                    var prevValue = _value;
                    _value = val;
                    observer(key, val, prevValue);
                }
            }
        };

        return state;
    }, {}));

    var dirty = Object.keys(props).reduce(function(dirty, key) {
        dirty[key] = false;
        return dirty;
    }, {});

    Object.defineProperty(state, "__dirty", {
        value: dirty,
    });

    return Object.freeze(state);
}

module.exports = createStoreState;<|endoftext|>


<commit_before>export default [
  {
    type: 'select',
    input: true,
    key: 'displayInTimezone',
    label: 'Display in Timezone',
    tooltip: 'This will display the captured date time in the select timezone.',
    weight: 30,
    defaultValue: 'viewer',
    dataSrc: 'values',
    data: {
      values: [
        { label: 'of Viewer', value: 'viewer' },
        { label: 'of Submission', value: 'submission' },
        { label: 'of Location', value: 'location' },
        { label: 'of GMT', value: 'gmt' }
      ]
    }
  },
  {
    type: 'select',
    input: true,
    key: 'timezoneOffset',
    label: 'Select Timezone',
    tooltip: 'Select the timezone you wish to display this Date',
    weight: 31,
    defaultValue: '',
    lazyLoad: true,
    dataSrc: 'url',
    data: {
      url: 'https://cdn.rawgit.com/travist/1072389661176f3efcd20f71b245e8aa/raw/timezones.json'
    },
    template: '{{ item.name }}',
    conditional: {
      json: { '===': [{ var: 'data.displayInTimezone' }, 'select'] }
    }
  },
  {
    type: 'checkbox',
    input: true,
    key: 'useLocaleSettings',
    label: 'Use Locale Settings',
    tooltip: 'Use locale settings to display date and time.',
    weight: 51
  },
  {
    type: 'checkbox',
    input: true,
    key: 'allowInput',
    label: 'Allow Manual Input',
    tooltip: 'Check this if you would like to allow the user to manually enter in the date.',
    weight: 51
  },
  {
    type: 'textfield',
    input: true,
    key: 'format',
    label: 'Format',
    placeholder: 'Format',
    tooltip: 'The moment.js format for saving the value of this field.',
    weight: 52
  }
];
<commit_msg>Fixed issue with the timezone selection where it was not showing up.<commit_after>export default [
  {
    type: 'select',
    input: true,
    key: 'displayInTimezone',
    label: 'Display in Timezone',
    tooltip: 'This will display the captured date time in the select timezone.',
    weight: 30,
    defaultValue: 'viewer',
    dataSrc: 'values',
    data: {
      values: [
        { label: 'of Viewer', value: 'viewer' },
        { label: 'of Submission', value: 'submission' },
        { label: 'of Location', value: 'location' },
        { label: 'of GMT', value: 'gmt' }
      ]
    }
  },
  {
    type: 'select',
    input: true,
    key: 'timezoneOffset',
    label: 'Select Timezone',
    tooltip: 'Select the timezone you wish to display this Date',
    weight: 31,
    defaultValue: '',
    lazyLoad: true,
    dataSrc: 'url',
    data: {
      url: 'https://cdn.rawgit.com/travist/1072389661176f3efcd20f71b245e8aa/raw/timezones.json'
    },
    template: '{{ item.name }}',
    conditional: {
      json: { '===': [{ var: 'data.displayInTimezone' }, 'location'] }
    }
  },
  {
    type: 'checkbox',
    input: true,
    key: 'useLocaleSettings',
    label: 'Use Locale Settings',
    tooltip: 'Use locale settings to display date and time.',
    weight: 51
  },
  {
    type: 'checkbox',
    input: true,
    key: 'allowInput',
    label: 'Allow Manual Input',
    tooltip: 'Check this if you would like to allow the user to manually enter in the date.',
    weight: 51
  },
  {
    type: 'textfield',
    input: true,
    key: 'format',
    label: 'Format',
    placeholder: 'Format',
    tooltip: 'The moment.js format for saving the value of this field.',
    weight: 52
  }
];
<|endoftext|>


<commit_before>var Email = require('../../lib/email');
var fs = require('fs');

var default_payload = {
  to        : 'david.tomberlin@sendgrid.com',
  from      : 'kyle.partridge@sendgrid.com',
  subject   : 'Subject',
  text      : 'This is an email.'
};

var files = [
  __dirname + '/../assets/logo.png',
  __dirname + '/../assets/sendgrid.txt'
]

describe('Email', function () {
  it('should allow attributes to be set in the constructor', function() {
    var payload     = Object.create(default_payload);
    var email       = new Email(payload);
    for (var key in payload) {
      expect(payload[key]).to.eql(email[key]);
    }
  });

  describe("#toWebFormat", function() {
    it('should return a Web Api format as expected', function() {
      var payload     = Object.create(default_payload);
      var email       = new Email(payload);
      var format      = email.toWebFormat();

      expect(format.to).to.equal(payload.to);
      expect(format.from).to.equal(payload.from);
      expect(format.subject).to.equal(payload.subject);
      expect(format.text).to.equal(payload.text);
      expect(format.fromname).to.be.empty;
      expect(format.toname).to.be.empty;
    });

    it('should have multiple TOs if as an array', function() {
      var payload     = Object.create(default_payload);
      payload.to      = ['david.tomberlin@sendgrid.com', 'otherguy@sendgrid.com'];
      var email       = new Email(payload);
      var format      = email.toWebFormat();

      expect(format.to).to.equal(payload.to);
    });

    it('should not have multiple TOs if as an array but also set on smtpapi via addTo', function() {
      var payload     = Object.create(default_payload);
      payload.to      = ['david.tomberlin@sendgrid.com', 'otherguy@sendgrid.com'];
      var email       = new Email(payload);
      email.addTo(payload.to[0]);
      email.addTo(payload.to[1]);

      var format      = email.toWebFormat();

      console.log(format);
      expect(format.to).to.equal(payload.from);
    });

    it('should have multiple BCCs if as an array', function() {
      var payload     = Object.create(default_payload);
      payload.bcc     = ['david.tomberlin@sendgrid.com', 'otherguy@sendgrid.com'];
      var email       = new Email(payload);
      var format      = email.toWebFormat();

      expect(format.bcc).to.equal(payload.bcc);
    });

    it('should not have a field for undefined file', function() {
      var payload     = Object.create(default_payload);
      var email       = new Email(payload);
      var format      = email.toWebFormat();

      expect(format.to).to.equal(payload.to);
      expect(format.from).to.equal(payload.from);
      expect(format.subject).to.equal(payload.subject);
      expect(format.text).to.equal(payload.text);
      expect(format.fromname).to.be.empty;
      expect(format.toname).to.be.empty;
      expect(format['files[undefined]']).to.be.undefined;
    });

    it('should not have a field for undefined file even with Array prototype overridden', function() {

      Array.prototype['testMethod'] = function() {
        return 'testMethod';
      };

      var payload     = Object.create(default_payload);
      var email       = new Email(payload);
      var format      = email.toWebFormat();

      expect(format.to).to.equal(payload.to);
      expect(format.from).to.equal(payload.from);
      expect(format.subject).to.equal(payload.subject);
      expect(format.text).to.equal(payload.text);
      expect(format.fromname).to.be.empty;
      expect(format.toname).to.be.empty;
      expect(format['files[undefined]']).to.be.undefined;
    });

    it('should not have a to address if there is no to or no smtpapi.', function() {
      var payload     = Object.create(default_payload);
      var email       = new Email({from: 'test@test.com', subject: 'testing', text: 'testing'});
      var format = email.toWebFormat();
      expect(format.to).to.be.empty;
    });

    it('should have a to address if there is no to but there is an smtpapi to', function() {
      var payload     = Object.create(default_payload);
      payload.to      = "";
      var email       = new Email(payload);
      email.addTo("test@test.com");
      var format = email.toWebFormat();

      expect(JSON.parse(format['x-smtpapi']).to).to.not.be.empty;
      expect(format.to).to.not.be.empty;
    });

    it("should set a fromname if one is provided", function() {
      var payload     = Object.create(default_payload);
      var email       = new Email({from: 'test@test.com', fromname:'Tester T. Testerson', subject: 'testing', text: 'testing'});
      var format = email.toWebFormat();

      expect(format.fromname).to.equal('Tester T. Testerson');
    });

    it("should set a toname if one is provided", function() {
      var payload     = Object.create(default_payload);
      var email       = new Email({from: 'test@test.com', to:'test@test.com', toname:'Tester T. Testerson', subject: 'testing', text: 'testing'});
      var format = email.toWebFormat();

      expect(format.toname).to.equal('Tester T. Testerson');
    });

    it("should set multiple tonames if several are provided", function() {
      var payload     = Object.create(default_payload);
      var email       = new Email({from: 'test@test.com', to: ['test@test.com', 'test2@test.com'], toname:['Tester T. Testerson', 'Test2 M. Testerson'], subject: 'testing', text: 'testing'});
      var format = email.toWebFormat();

      expect(format.toname[0]).to.equal('Tester T. Testerson');
      expect(format.toname[1]).to.equal('Test2 M. Testerson');
    });
  });

  it('should be possible to setFrom', function() {
    var email = new Email();
    expect(email.from).to.be.empty;
    email.setFrom('kyle.partridge@sendgrid.com');
    expect(email.from).to.eql('kyle.partridge@sendgrid.com');
  });

  it('should be possible to setSubject', function() {
    var email = new Email();
    expect(email.subject).to.be.empty;
    email.setSubject('A subject');
    expect(email.subject).to.eql('A subject');
  });

  it('should be possible to setText', function() {
    var email = new Email();
    expect(email.text).to.be.empty;
    email.setText('Some text');
    expect(email.text).to.eql('Some text');
  });

  it('should be possible to setHtml', function() {
    var email = new Email();
    expect(email.html).to.be.empty;
    email.setHtml('
Some html
');
    expect(email.html).to.eql('
Some html
');
  });

  describe('files', function() {
    it('should support adding attachments via path', function() {
      var email = new Email();
      email.addFile({filename: 'path-image.png', path: files[0]});
      expect(email.files[0].filename).to.equal('path-image.png');
      expect(email.files[0].contentType).to.equal('image/png');
    });

    it('should support attachments via url', function() {
      var email = new Email();
      email.addFile({filename: 'url-image.jpg', url: 'http://i.imgur.com/2fDh8.jpg'});
      expect(email.files[0].filename).to.equal('url-image.jpg');
      expect(email.files[0].contentType).to.equal('image/jpeg');
    });

    it('should support attachments via content', function() {
      var email = new Email();
      fs.readFile(files[0], function(err, data) {
        expect(err).to.not.be.ok;
        email.addFile({filename: 'content-image.png', content: data, contentType: 'image/png'});
        expect(email.files[0].filename).to.equal('content-image.png');
        expect(email.files[0].contentType).to.equal('image/png');
      });
    });

    it('should support inline content', function() {
      var email = new Email();
      fs.readFile(files[0], function(err, data) {
        expect(err).to.not.be.ok;
        email.addFile({filename: 'content-image.png', content: data, contentType: 'image/png', cid: 'testcid'});
        expect(email.files[0].cid).to.equal('testcid');
        expect(email.files[0].filename).to.equal('content-image.png');
        expect(email.files[0].contentType).to.equal('image/png');
      });
    });
  });

  describe('custom headers', function() {
    var mail;
    var custom_headers = {cow: 'moo', panda: 'brawr'};
    beforeEach(function() {
      mail = new Email();
    });

    it('should allow setting custom headers via setHeaders', function() {
      mail.setHeaders(custom_headers);
      expect(mail.headers).to.eql(custom_headers);
    });

    it('should allow setting custom headers with key, value approach', function() {
      mail.addHeader('fox', 'hound');
      expect(mail.headers.fox).to.eql('hound');
    });

    it('should overwrite headers when calling addHeader with the same value', function() {
      mail.addHeader(custom_headers);
      expect(mail.headers).to.eql(custom_headers);
      mail.addHeader('cow', 'in my mind');
      expect(mail.headers).not.to.eql(custom_headers);
      expect(mail.headers.cow).to.eql('in my mind');
    });

    it('should allow setting custom headers one at a time with addHeader as a hash (temporary. deprecate this ability for key, value approach instead)', function() {
      for(var key in custom_headers) {
        var args = {};
        args[key] = custom_headers[key];
        mail.addHeader(args);
      }

      expect(mail.headers).to.eql(custom_headers);
      mail.addHeader({fox: 'hound'});
      expect(mail.headers.fox).to.eql('hound');
    });

  });

  describe('file handling the constructor', function() {
    it('should be able to add content files easily', function(done) {
      var file = {
        filename: 'hello_snowman.txt',
        content: new Buffer("Hello ☃, I hope you don't melt", 'utf-8')
      };
      var email = new Email({
        files: [
          file
        ]
      });

      email.files[0].loadContent(function(error, message) {
        expect(error).to.not.be.true;
        expect(email.files[0].content).to.eql(file.content);
        done();
      });
    });

    it('should be able to add url files easily', function(done) {
      var file = {
        filename: 'icon.jpg',
        url: 'http://i.imgur.com/2fDh8.jpg'
      };
      var email = new Email({
        files: [
          file
        ]
      });

      expect(email.files[0].filename).to.equal(file.filename);
      expect(email.files[0].content).to.eql(file.content);
      expect(email.files[0].contentType).to.equal('image/jpeg');

      email.files[0].loadContent(function(error, message) {
        expect(error).to.not.be.true;
        expect(email.files[0].content).to.not.be.undefined;
        done();
      });
    });

    it('should be able to add path files easily', function(done) {
      var file = {
        path: __dirname + '/../assets/secret.txt'
      };
      var email = new Email({
        files: [
          file
        ]
      });

      email.files[0].loadContent(function(error, message) {
        expect(error).to.not.be.true;
        expect(email.files[0].content).to.not.be.undefined;
        done();
      });
    });

    it('should be able to add filters', function(done) {
      var email = new Email();

      email.addFilter('subscriptiontrack', 'enable', 1)
      email.addFilter('subscriptiontrack', "text/plain", "If you would like to unsubscribe and stop receiving these emails click here: <% %>.")

      expect(email.smtpapi.jsonString()).to.eql("{\"filters\":{\"subscriptiontrack\":{\"settings\":{\"enable\":1,\"text/plain\":\"If you would like to unsubscribe and stop receiving these emails click here: <% %>.\"}}}}");

      done();
    });
  });
});
<commit_msg>remove console.log<commit_after>var Email = require('../../lib/email');
var fs = require('fs');

var default_payload = {
  to        : 'david.tomberlin@sendgrid.com',
  from      : 'kyle.partridge@sendgrid.com',
  subject   : 'Subject',
  text      : 'This is an email.'
};

var files = [
  __dirname + '/../assets/logo.png',
  __dirname + '/../assets/sendgrid.txt'
]

describe('Email', function () {
  it('should allow attributes to be set in the constructor', function() {
    var payload     = Object.create(default_payload);
    var email       = new Email(payload);
    for (var key in payload) {
      expect(payload[key]).to.eql(email[key]);
    }
  });

  describe("#toWebFormat", function() {
    it('should return a Web Api format as expected', function() {
      var payload     = Object.create(default_payload);
      var email       = new Email(payload);
      var format      = email.toWebFormat();

      expect(format.to).to.equal(payload.to);
      expect(format.from).to.equal(payload.from);
      expect(format.subject).to.equal(payload.subject);
      expect(format.text).to.equal(payload.text);
      expect(format.fromname).to.be.empty;
      expect(format.toname).to.be.empty;
    });

    it('should have multiple TOs if as an array', function() {
      var payload     = Object.create(default_payload);
      payload.to      = ['david.tomberlin@sendgrid.com', 'otherguy@sendgrid.com'];
      var email       = new Email(payload);
      var format      = email.toWebFormat();

      expect(format.to).to.equal(payload.to);
    });

    it('should not have multiple TOs if as an array but also set on smtpapi via addTo', function() {
      var payload     = Object.create(default_payload);
      payload.to      = ['david.tomberlin@sendgrid.com', 'otherguy@sendgrid.com'];
      var email       = new Email(payload);
      email.addTo(payload.to[0]);
      email.addTo(payload.to[1]);

      var format      = email.toWebFormat();

      expect(format.to).to.equal(payload.from);
    });

    it('should have multiple BCCs if as an array', function() {
      var payload     = Object.create(default_payload);
      payload.bcc     = ['david.tomberlin@sendgrid.com', 'otherguy@sendgrid.com'];
      var email       = new Email(payload);
      var format      = email.toWebFormat();

      expect(format.bcc).to.equal(payload.bcc);
    });

    it('should not have a field for undefined file', function() {
      var payload     = Object.create(default_payload);
      var email       = new Email(payload);
      var format      = email.toWebFormat();

      expect(format.to).to.equal(payload.to);
      expect(format.from).to.equal(payload.from);
      expect(format.subject).to.equal(payload.subject);
      expect(format.text).to.equal(payload.text);
      expect(format.fromname).to.be.empty;
      expect(format.toname).to.be.empty;
      expect(format['files[undefined]']).to.be.undefined;
    });

    it('should not have a field for undefined file even with Array prototype overridden', function() {

      Array.prototype['testMethod'] = function() {
        return 'testMethod';
      };

      var payload     = Object.create(default_payload);
      var email       = new Email(payload);
      var format      = email.toWebFormat();

      expect(format.to).to.equal(payload.to);
      expect(format.from).to.equal(payload.from);
      expect(format.subject).to.equal(payload.subject);
      expect(format.text).to.equal(payload.text);
      expect(format.fromname).to.be.empty;
      expect(format.toname).to.be.empty;
      expect(format['files[undefined]']).to.be.undefined;
    });

    it('should not have a to address if there is no to or no smtpapi.', function() {
      var payload     = Object.create(default_payload);
      var email       = new Email({from: 'test@test.com', subject: 'testing', text: 'testing'});
      var format = email.toWebFormat();
      expect(format.to).to.be.empty;
    });

    it('should have a to address if there is no to but there is an smtpapi to', function() {
      var payload     = Object.create(default_payload);
      payload.to      = "";
      var email       = new Email(payload);
      email.addTo("test@test.com");
      var format = email.toWebFormat();

      expect(JSON.parse(format['x-smtpapi']).to).to.not.be.empty;
      expect(format.to).to.not.be.empty;
    });

    it("should set a fromname if one is provided", function() {
      var payload     = Object.create(default_payload);
      var email       = new Email({from: 'test@test.com', fromname:'Tester T. Testerson', subject: 'testing', text: 'testing'});
      var format = email.toWebFormat();

      expect(format.fromname).to.equal('Tester T. Testerson');
    });

    it("should set a toname if one is provided", function() {
      var payload     = Object.create(default_payload);
      var email       = new Email({from: 'test@test.com', to:'test@test.com', toname:'Tester T. Testerson', subject: 'testing', text: 'testing'});
      var format = email.toWebFormat();

      expect(format.toname).to.equal('Tester T. Testerson');
    });

    it("should set multiple tonames if several are provided", function() {
      var payload     = Object.create(default_payload);
      var email       = new Email({from: 'test@test.com', to: ['test@test.com', 'test2@test.com'], toname:['Tester T. Testerson', 'Test2 M. Testerson'], subject: 'testing', text: 'testing'});
      var format = email.toWebFormat();

      expect(format.toname[0]).to.equal('Tester T. Testerson');
      expect(format.toname[1]).to.equal('Test2 M. Testerson');
    });
  });

  it('should be possible to setFrom', function() {
    var email = new Email();
    expect(email.from).to.be.empty;
    email.setFrom('kyle.partridge@sendgrid.com');
    expect(email.from).to.eql('kyle.partridge@sendgrid.com');
  });

  it('should be possible to setSubject', function() {
    var email = new Email();
    expect(email.subject).to.be.empty;
    email.setSubject('A subject');
    expect(email.subject).to.eql('A subject');
  });

  it('should be possible to setText', function() {
    var email = new Email();
    expect(email.text).to.be.empty;
    email.setText('Some text');
    expect(email.text).to.eql('Some text');
  });

  it('should be possible to setHtml', function() {
    var email = new Email();
    expect(email.html).to.be.empty;
    email.setHtml('
Some html
');
    expect(email.html).to.eql('
Some html
');
  });

  describe('files', function() {
    it('should support adding attachments via path', function() {
      var email = new Email();
      email.addFile({filename: 'path-image.png', path: files[0]});
      expect(email.files[0].filename).to.equal('path-image.png');
      expect(email.files[0].contentType).to.equal('image/png');
    });

    it('should support attachments via url', function() {
      var email = new Email();
      email.addFile({filename: 'url-image.jpg', url: 'http://i.imgur.com/2fDh8.jpg'});
      expect(email.files[0].filename).to.equal('url-image.jpg');
      expect(email.files[0].contentType).to.equal('image/jpeg');
    });

    it('should support attachments via content', function() {
      var email = new Email();
      fs.readFile(files[0], function(err, data) {
        expect(err).to.not.be.ok;
        email.addFile({filename: 'content-image.png', content: data, contentType: 'image/png'});
        expect(email.files[0].filename).to.equal('content-image.png');
        expect(email.files[0].contentType).to.equal('image/png');
      });
    });

    it('should support inline content', function() {
      var email = new Email();
      fs.readFile(files[0], function(err, data) {
        expect(err).to.not.be.ok;
        email.addFile({filename: 'content-image.png', content: data, contentType: 'image/png', cid: 'testcid'});
        expect(email.files[0].cid).to.equal('testcid');
        expect(email.files[0].filename).to.equal('content-image.png');
        expect(email.files[0].contentType).to.equal('image/png');
      });
    });
  });

  describe('custom headers', function() {
    var mail;
    var custom_headers = {cow: 'moo', panda: 'brawr'};
    beforeEach(function() {
      mail = new Email();
    });

    it('should allow setting custom headers via setHeaders', function() {
      mail.setHeaders(custom_headers);
      expect(mail.headers).to.eql(custom_headers);
    });

    it('should allow setting custom headers with key, value approach', function() {
      mail.addHeader('fox', 'hound');
      expect(mail.headers.fox).to.eql('hound');
    });

    it('should overwrite headers when calling addHeader with the same value', function() {
      mail.addHeader(custom_headers);
      expect(mail.headers).to.eql(custom_headers);
      mail.addHeader('cow', 'in my mind');
      expect(mail.headers).not.to.eql(custom_headers);
      expect(mail.headers.cow).to.eql('in my mind');
    });

    it('should allow setting custom headers one at a time with addHeader as a hash (temporary. deprecate this ability for key, value approach instead)', function() {
      for(var key in custom_headers) {
        var args = {};
        args[key] = custom_headers[key];
        mail.addHeader(args);
      }

      expect(mail.headers).to.eql(custom_headers);
      mail.addHeader({fox: 'hound'});
      expect(mail.headers.fox).to.eql('hound');
    });

  });

  describe('file handling the constructor', function() {
    it('should be able to add content files easily', function(done) {
      var file = {
        filename: 'hello_snowman.txt',
        content: new Buffer("Hello ☃, I hope you don't melt", 'utf-8')
      };
      var email = new Email({
        files: [
          file
        ]
      });

      email.files[0].loadContent(function(error, message) {
        expect(error).to.not.be.true;
        expect(email.files[0].content).to.eql(file.content);
        done();
      });
    });

    it('should be able to add url files easily', function(done) {
      var file = {
        filename: 'icon.jpg',
        url: 'http://i.imgur.com/2fDh8.jpg'
      };
      var email = new Email({
        files: [
          file
        ]
      });

      expect(email.files[0].filename).to.equal(file.filename);
      expect(email.files[0].content).to.eql(file.content);
      expect(email.files[0].contentType).to.equal('image/jpeg');

      email.files[0].loadContent(function(error, message) {
        expect(error).to.not.be.true;
        expect(email.files[0].content).to.not.be.undefined;
        done();
      });
    });

    it('should be able to add path files easily', function(done) {
      var file = {
        path: __dirname + '/../assets/secret.txt'
      };
      var email = new Email({
        files: [
          file
        ]
      });

      email.files[0].loadContent(function(error, message) {
        expect(error).to.not.be.true;
        expect(email.files[0].content).to.not.be.undefined;
        done();
      });
    });

    it('should be able to add filters', function(done) {
      var email = new Email();

      email.addFilter('subscriptiontrack', 'enable', 1)
      email.addFilter('subscriptiontrack', "text/plain", "If you would like to unsubscribe and stop receiving these emails click here: <% %>.")

      expect(email.smtpapi.jsonString()).to.eql("{\"filters\":{\"subscriptiontrack\":{\"settings\":{\"enable\":1,\"text/plain\":\"If you would like to unsubscribe and stop receiving these emails click here: <% %>.\"}}}}");

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


<commit_before>import db from 'src/pouchdb'
import { pageDocsSelector } from 'src/page-storage'
import { checkWithBlacklist } from 'src/blacklist'
import { isLoggable } from 'src/activity-logger'
import { IMPORT_TYPE, OLD_EXT_KEYS } from 'src/options/imports/constants'
import importsConnectionHandler from './imports-connection-handler'

// Constants
export const importStateStorageKey = 'import_items'
export const installTimeStorageKey = 'extension_install_time'

// Imports local storage state interface
export const getImportItems = async () => {
    const data = (await browser.storage.local.get(importStateStorageKey))[
        importStateStorageKey
    ]
    return !data ? [] : JSON.parse(data)
}

export const setImportItems = items =>
    browser.storage.local.set({
        [importStateStorageKey]: JSON.stringify(items),
    })

export const clearImportItems = () =>
    browser.storage.local.remove(importStateStorageKey)

/**
 * @param url The URL to match against all items in import state. Item with matching URL will be removed.
 *  Assumes that input state is unique on URL to work properly.
 */
export const removeImportItem = async url => {
    const importItems = await getImportItems()
    const i = importItems.findIndex(item => item.url === url)
    if (i !== -1) {
        await setImportItems([
            ...importItems.slice(0, i),
            ...importItems.slice(i + 1),
        ])
    }
}

/**
 * @returns A function affording checking of a URL against the URLs of existing page docs.
 */
async function checkWithExistingDocs() {
    const { docs: existingPageDocs } = await db.find({
        selector: pageDocsSelector,
        fields: ['url'],
    })
    const existingUrls = existingPageDocs.map(({ url }) => url)

    return ({ url }) => !existingUrls.includes(url)
}

/**
 * Handles performing blacklist and pending import filtering logic on any type
 * of items containing a `url` field.
 *
 * @param {Iterable<any>} items Some Iterable of items of any shape, as long as they contain `url` field.
 * @returns {Iterable<any>} Filtered version of the items arg.
 */
async function filterItemsByUrl(items, type) {
    const isNotBlacklisted = await checkWithBlacklist()
    const doesNotExist = await checkWithExistingDocs()

    const isWorthRemembering = item =>
        isLoggable(item) && isNotBlacklisted(item) && doesNotExist(item)
    return items.filter(isWorthRemembering)
}

export async function getOldExtItems() {
    let importItems = []
    let bookmarkUrls = new Set()
    const {
        [OLD_EXT_KEYS.INDEX]: index,
        [OLD_EXT_KEYS.BOOKMARKS]: bookmarks,
    } = await browser.storage.local.get({
        [OLD_EXT_KEYS.INDEX]: { index: [] },
        [OLD_EXT_KEYS.BOOKMARKS]: '[]',
    })

    if (typeof bookmarks === 'string') {
        try {
            bookmarkUrls = new Set(JSON.parse(bookmarks))
        } catch (error) {}
    }

    // Only attempt page data conversion if index + bookmark storage values are correct types
    if (index && index.index instanceof Array) {
        importItems = index.index.map(data => ({
            type: IMPORT_TYPE.OLD,
            url: data.url,
            timestamp: data.time,
            hasBookmark: bookmarkUrls.has(data.url),
        }))
    }

    return importItems
}

/**
 * @param {number} [maxResults=9999999] The max amount of items to grab from browser.
 * @param {number} [startTime=0] The time to start search from for browser history.
 * @returns {Array<browser.history.HistoryItem>} All history items in browser filtered by URL.
 */
export async function getURLFilteredHistoryItems(
    maxResults = 9999999,
    startTime = 0,
) {
    const historyItems = await browser.history.search({
        text: '',
        maxResults,
        startTime,
    })
    return filterItemsByUrl(historyItems, IMPORT_TYPE.HISTORY)
}

/**
 * @param {number} [maxResults=100000] The max amount of items to grab from browser.
 * @returns {Array<browser.bookmarks.BookmarkTreeNode>} All bookmark items in browser filtered by URL.
 */
export async function getURLFilteredBookmarkItems(maxResults = 100000) {
    const bookmarkItems = await browser.bookmarks.getRecent(maxResults)
    return filterItemsByUrl(bookmarkItems, IMPORT_TYPE.BOOKMARK)
}

// Allow content-script or UI to connect and communicate control of imports
browser.runtime.onConnect.addListener(importsConnectionHandler)
<commit_msg>Update old ext page->import item logic<commit_after>import db from 'src/pouchdb'
import { pageDocsSelector } from 'src/page-storage'
import { checkWithBlacklist } from 'src/blacklist'
import { isLoggable } from 'src/activity-logger'
import { IMPORT_TYPE, OLD_EXT_KEYS } from 'src/options/imports/constants'
import importsConnectionHandler from './imports-connection-handler'

// Constants
export const importStateStorageKey = 'import_items'
export const installTimeStorageKey = 'extension_install_time'

// Imports local storage state interface
export const getImportItems = async () => {
    const data = (await browser.storage.local.get(importStateStorageKey))[
        importStateStorageKey
    ]
    return !data ? [] : JSON.parse(data)
}

export const setImportItems = items =>
    browser.storage.local.set({
        [importStateStorageKey]: JSON.stringify(items),
    })

export const clearImportItems = () =>
    browser.storage.local.remove(importStateStorageKey)

/**
 * @param url The URL to match against all items in import state. Item with matching URL will be removed.
 *  Assumes that input state is unique on URL to work properly.
 */
export const removeImportItem = async url => {
    const importItems = await getImportItems()
    const i = importItems.findIndex(item => item.url === url)
    if (i !== -1) {
        await setImportItems([
            ...importItems.slice(0, i),
            ...importItems.slice(i + 1),
        ])
    }
}

/**
 * @returns A function affording checking of a URL against the URLs of existing page docs.
 */
async function checkWithExistingDocs() {
    const { docs: existingPageDocs } = await db.find({
        selector: pageDocsSelector,
        fields: ['url'],
    })
    const existingUrls = existingPageDocs.map(({ url }) => url)

    return ({ url }) => !existingUrls.includes(url)
}

/**
 * Handles performing blacklist and pending import filtering logic on any type
 * of items containing a `url` field.
 *
 * @param {Iterable<any>} items Some Iterable of items of any shape, as long as they contain `url` field.
 * @returns {Iterable<any>} Filtered version of the items arg.
 */
async function filterItemsByUrl(items, type) {
    const isNotBlacklisted = await checkWithBlacklist()
    const doesNotExist = await checkWithExistingDocs()

    const isWorthRemembering = item =>
        isLoggable(item) && isNotBlacklisted(item) && doesNotExist(item)
    return items.filter(isWorthRemembering)
}

export async function getOldExtItems() {
    let importItems = []
    let bookmarkUrls = new Set()
    const {
        [OLD_EXT_KEYS.INDEX]: index,
        [OLD_EXT_KEYS.BOOKMARKS]: bookmarks,
    } = await browser.storage.local.get({
        [OLD_EXT_KEYS.INDEX]: { index: [] },
        [OLD_EXT_KEYS.BOOKMARKS]: '[]',
    })

    if (typeof bookmarks === 'string') {
        try {
            bookmarkUrls = new Set(JSON.parse(bookmarks))
        } catch (error) {}
    }

    // Only attempt page data conversion if index + bookmark storage values are correct types
    if (index && index.index instanceof Array) {
        // Map all old ext data to import items, ignoring text
        importItems = Object.values(
            await browser.storage.local.get(index.index),
        ).map(data => ({
            type: IMPORT_TYPE.OLD,
            url: data.url,
            timestamp: data.time,
            hasBookmark: bookmarkUrls.has(data.url),
        }))
    }

    return importItems
}

/**
 * @param {number} [maxResults=9999999] The max amount of items to grab from browser.
 * @param {number} [startTime=0] The time to start search from for browser history.
 * @returns {Array<browser.history.HistoryItem>} All history items in browser filtered by URL.
 */
export async function getURLFilteredHistoryItems(
    maxResults = 9999999,
    startTime = 0,
) {
    const historyItems = await browser.history.search({
        text: '',
        maxResults,
        startTime,
    })
    return filterItemsByUrl(historyItems, IMPORT_TYPE.HISTORY)
}

/**
 * @param {number} [maxResults=100000] The max amount of items to grab from browser.
 * @returns {Array<browser.bookmarks.BookmarkTreeNode>} All bookmark items in browser filtered by URL.
 */
export async function getURLFilteredBookmarkItems(maxResults = 100000) {
    const bookmarkItems = await browser.bookmarks.getRecent(maxResults)
    return filterItemsByUrl(bookmarkItems, IMPORT_TYPE.BOOKMARK)
}

// Allow content-script or UI to connect and communicate control of imports
browser.runtime.onConnect.addListener(importsConnectionHandler)
<|endoftext|>


<commit_before>describe("lib/utils", () => {
  jest.useFakeTimers();

  let utils = require("./../../src/lib/utils");
  let ldClient = require("ldclient-js").default;

  const mockLdClient = (() => {
    ldClient.identify = jest.fn();
    ldClient.initialize = jest.fn().mockImplementation(() => ({
      on: (event, callback) => {
        setTimeout(() => {
          callback();
        }, 1000);
      }
    }));
  });
  mockLdClient();

  it("exports functions", () => {
    expect(utils["ldClientWrapper"]).toBeDefined();
    expect(utils["ldOverrideFlag"]).toBeDefined();
    expect(utils["getAllFeatureFlags"]).toBeDefined();
  });

  describe("ldClientWrapper", () => {
    const key = "my key";
    const user = { key: "my user" };
    const options = { baseUrl: "http://test" };

    describe("proxies to ldClient", () => {
      beforeEach(() => {
        // `ldClientWrapper` is a singleton, we need to reset the module cache with each test
        // to be able to properly assert each instance of `ldClientWrapper`
        jest.resetModules();
        utils = require("./../../src/lib/utils");
        ldClient = require("ldclient-js").default;
        mockLdClient();
      });

      it("initializes with key, user and default options parameter", () => {
        utils.ldClientWrapper(key, user);
        expect(ldClient.initialize).toBeCalledWith(key, user, {});
      });

      it("initializes with key, user and options", () => {
        utils.ldClientWrapper(key, user, options);
        expect(ldClient.initialize).toBeCalledWith(key, user, options);
      });
    });

    it("does not instantiate ldclient-js more than once", () => {
      utils.ldClientWrapper(key, user);
      utils.ldClientWrapper(key, user);
      utils.ldClientWrapper(key, user);
      expect(ldClient.initialize).toHaveBeenCalledTimes(1);
    });

    it("onReady calls wait for ready event to fire", () => {
      const callbackMock = jest.fn();
      utils.ldClientWrapper(key, user).onReady(callbackMock);
      utils.ldClientWrapper(key, user).onReady(callbackMock);
      utils.ldClientWrapper(key, user).onReady(callbackMock);
      expect(callbackMock.mock.instances.length).toBe(0);
    });

    it("executes all onReady calls after ldClient is ready", () => {
      const callbackMock = jest.fn();
      utils.ldClientWrapper(key, user).onReady(callbackMock);
      utils.ldClientWrapper(key, user).onReady(callbackMock);
      utils.ldClientWrapper(key, user).onReady(callbackMock);
      jest.runAllTimers();
      expect(callbackMock.mock.instances.length).toBe(3);
    });
  });

  describe("getAllFeatureFlags", () => {

  });

  describe("identify", () => {
    it("ldclient-js identify is called", () => {
      utils.identify(1234, {}).then( () => {
        expect(ldClient.identify).toHaveBeenCalled();
      });
    });
  });

  describe("track", () => {
    it("ldclient-js track is called", () => {
      utils.track(1234, {}).then( () => {
        expect(ldClient.track).toHaveBeenCalled();
      });
    });
  });

  describe("ldOverrideFlag", () => {

  });

  describe("feature", () => {
    it("ldclient-js feature is called", () => {
      utils.feature("home-test", {}).then( () => {
        expect(ldClient.feature).toHaveBeenCalled();
      });
    });
  });

});
<commit_msg>change test to expect variation<commit_after>describe("lib/utils", () => {
  jest.useFakeTimers();

  let utils = require("./../../src/lib/utils");
  let ldClient = require("ldclient-js").default;

  const mockLdClient = (() => {
    ldClient.identify = jest.fn();
    ldClient.initialize = jest.fn().mockImplementation(() => ({
      on: (event, callback) => {
        setTimeout(() => {
          callback();
        }, 1000);
      }
    }));
  });
  mockLdClient();

  it("exports functions", () => {
    expect(utils["ldClientWrapper"]).toBeDefined();
    expect(utils["ldOverrideFlag"]).toBeDefined();
    expect(utils["getAllFeatureFlags"]).toBeDefined();
  });

  describe("ldClientWrapper", () => {
    const key = "my key";
    const user = { key: "my user" };
    const options = { baseUrl: "http://test" };

    describe("proxies to ldClient", () => {
      beforeEach(() => {
        // `ldClientWrapper` is a singleton, we need to reset the module cache with each test
        // to be able to properly assert each instance of `ldClientWrapper`
        jest.resetModules();
        utils = require("./../../src/lib/utils");
        ldClient = require("ldclient-js").default;
        mockLdClient();
      });

      it("initializes with key, user and default options parameter", () => {
        utils.ldClientWrapper(key, user);
        expect(ldClient.initialize).toBeCalledWith(key, user, {});
      });

      it("initializes with key, user and options", () => {
        utils.ldClientWrapper(key, user, options);
        expect(ldClient.initialize).toBeCalledWith(key, user, options);
      });
    });

    it("does not instantiate ldclient-js more than once", () => {
      utils.ldClientWrapper(key, user);
      utils.ldClientWrapper(key, user);
      utils.ldClientWrapper(key, user);
      expect(ldClient.initialize).toHaveBeenCalledTimes(1);
    });

    it("onReady calls wait for ready event to fire", () => {
      const callbackMock = jest.fn();
      utils.ldClientWrapper(key, user).onReady(callbackMock);
      utils.ldClientWrapper(key, user).onReady(callbackMock);
      utils.ldClientWrapper(key, user).onReady(callbackMock);
      expect(callbackMock.mock.instances.length).toBe(0);
    });

    it("executes all onReady calls after ldClient is ready", () => {
      const callbackMock = jest.fn();
      utils.ldClientWrapper(key, user).onReady(callbackMock);
      utils.ldClientWrapper(key, user).onReady(callbackMock);
      utils.ldClientWrapper(key, user).onReady(callbackMock);
      jest.runAllTimers();
      expect(callbackMock.mock.instances.length).toBe(3);
    });
  });

  describe("getAllFeatureFlags", () => {

  });

  describe("identify", () => {
    it("ldclient-js identify is called", () => {
      utils.identify(1234, {}).then( () => {
        expect(ldClient.identify).toHaveBeenCalled();
      });
    });
  });

  describe("track", () => {
    it("ldclient-js track is called", () => {
      utils.track(1234, {}).then( () => {
        expect(ldClient.track).toHaveBeenCalled();
      });
    });
  });

  describe("ldOverrideFlag", () => {

  });

  describe("feature", () => {
    it("ldclient-js feature is called", () => {
      utils.feature("home-test", {}).then( () => {
        expect(ldClient.variation).toHaveBeenCalled();
      });
    });
  });

});
<|endoftext|>


<commit_before>/* global require, describe, it */

var assert = require('assert');
var katasUrl = 'http://katas.tddbin.com/katas/es6/language/__grouped__.json';

describe('load ES6 kata data', function() {
  it('loaded data are as expected', function(done) {
    function onSuccess(groupedKatas) {
      assert.equal('groups' in groupedKatas, true);
      done();
    }

    loadGroupedKata(katasUrl, function() {}, onSuccess);
  });
  describe('on error, call error callback and the error passed', function() {
    it('invalid JSON', function(done) {
      function onError(err) {
        assert.ok(err);
        done();
      }

      var invalidUrl = 'http://katas.tddbin.com/katas/es6/language';
      loadGroupedKata(invalidUrl, onError);
    });
  });
});

function loadGroupedKata(katasUrl, onError, onSuccess) {
  function onLoaded(err, data) {
    var parsed;
    try {
      parsed = JSON.parse(data);
    } catch (jsonParseError) {
      onError(jsonParseError);
    }
    if (err) {
      onError(err);
    } else {
      onSuccess(parsed);
    }
  }

  loadFileOnServer(katasUrl, onLoaded);
}

var http = require('http');
var url = require('url');

function loadFileOnServer(fileUrl, onLoaded) {
  var data = '';
  var options = url.parse(fileUrl);
  options.headers = {'User-Agent': ''}; // github wants a user agent header
  var request = http.request(options, function(res) {
    res.on('data', function(chunk) {data += chunk;});
    res.on('end', function() {
      onLoaded(null, data);
    });
  });
  request.on('error', function(e) { onLoaded(e); });
  request.end();
}
<commit_msg>Ensure that the right data are loaded, they have to have `groups` as the first key.<commit_after>/* global require, describe, it */

var assert = require('assert');
var urlPrefix = 'http://katas.tddbin.com/katas/es6/language/';
var katasUrl = urlPrefix + '__grouped__.json';

describe('load ES6 kata data', function() {
  it('loaded data are as expected', function(done) {
    function onSuccess(groupedKatas) {
      assert.ok(groupedKatas);
      done();
    }

    loadGroupedKata(katasUrl, function() {}, onSuccess);
  });
  describe('on error, call error callback and the error passed', function() {
    it('invalid JSON', function(done) {
      function onError(err) {
        assert.ok(err);
        done();
      }

      var invalidUrl = urlPrefix;
      loadGroupedKata(invalidUrl, onError);
    });
    it('for invalid data', function(done) {
      function onError(err) {
        assert.ok(err);
        done();
      }

      var invalidData = urlPrefix + '__all__.json';
      loadGroupedKata(invalidData, onError);
    });
  });
});

function loadGroupedKata(katasUrl, onError, onSuccess) {
  function onLoaded(err, data) {
    var parsed;
    try {
      parsed = JSON.parse(data);
    } catch (jsonParseError) {
      onError(jsonParseError);
    }
    if (err) {
      onError(err);
    } else if (!('groups' in parsed)) {
      onError(new Error('No groups found in the data'));
    } else {
      onSuccess(parsed.groups);
    }
  }

  loadFileOnServer(katasUrl, onLoaded);
}

var http = require('http');
var url = require('url');

function loadFileOnServer(fileUrl, onLoaded) {
  var data = '';
  var options = url.parse(fileUrl);
  options.headers = {'User-Agent': ''}; // github wants a user agent header
  var request = http.request(options, function(res) {
    res.on('data', function(chunk) {data += chunk;});
    res.on('end', function() {
      onLoaded(null, data);
    });
  });
  request.on('error', function(e) { onLoaded(e); });
  request.end();
}
<|endoftext|>