<commit_before>const libxmljs = require('libxmljs');
const fetch = require('node-fetch');
const E2eHelpers = require('../util/e2e-helpers');
const Timeouts = require('../util/timeouts.js');

const SITEMAP_URL = `${E2eHelpers.baseUrl}/sitemap.xml`;
const SITEMAP_LOC_NS = 'http://www.sitemaps.org/schemas/sitemap/0.9';
const BUILD_BASE_URL = 'http://www.vets.gov';

let sitemapURLs = [];

module.exports = {
  before: (client, done) => {
    // Load sitemap urls by loading and parsing the sitemap
    fetch(SITEMAP_URL)
      .then((res) => {
        return res.text();
      }).then((body) => {
        const doc = libxmljs.parseXml(body);

        sitemapURLs = doc.find('//xmlns:loc', SITEMAP_LOC_NS)
          .map(n => n.text().replace(BUILD_BASE_URL, E2eHelpers.baseUrl));

        done();
      }).catch(done);
  },

  'test accesssibility': (client) => {
    // Iterate through each of the sitemap urls run the axe checks
    if (!sitemapURLs.length) {
      this.verify.fail('No URLs found in sitemap');
    }

    sitemapURLs.forEach(url => {
      client
        .url(url)
        .waitForElementVisible('body', Timeouts.normal)
        .axeCheck('document', { scope: url });
    });

    client.end();
  }
};
<commit_msg>do not check old facility locator<commit_after>const libxmljs = require('libxmljs');
const fetch = require('node-fetch');
const E2eHelpers = require('../util/e2e-helpers');
const Timeouts = require('../util/timeouts.js');

const SITEMAP_URL = `${E2eHelpers.baseUrl}/sitemap.xml`;
const SITEMAP_LOC_NS = 'http://www.sitemaps.org/schemas/sitemap/0.9';
const BUILD_BASE_URL = 'http://www.vets.gov';

let sitemapURLs = [];

module.exports = {
  before: (client, done) => {
    // Load sitemap urls by loading and parsing the sitemap
    fetch(SITEMAP_URL)
      .then((res) => {
        return res.text();
      }).then((body) => {
        const doc = libxmljs.parseXml(body);

        sitemapURLs = doc.find('//xmlns:loc', SITEMAP_LOC_NS)
          .map(n => n.text().replace(BUILD_BASE_URL, E2eHelpers.baseUrl));

        done();
      }).catch(done);
  },

  'test accesssibility': (client) => {
    // Iterate through each of the sitemap urls run the axe checks
    if (!sitemapURLs.length) {
      this.verify.fail('No URLs found in sitemap');
    }

    // do not check old facility locator
    sitemapURLs.forEach(url => {
      if (url.endsWith('facility-locator')) {
        return;
      }

      client
        .url(url)
        .waitForElementVisible('body', Timeouts.normal)
        .axeCheck('document', { scope: url });
    });

    client.end();
  }
};
<|endoftext|>


<commit_before>'use strict';
var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var ExamsSchema = new Schema({
  subject: String,
  examDate: Date,
  score: Number,
  result: {type: String, enum: ['distinction', 'merit', 'pass', 'fail']},
  grader: { type: Schema.Types.ObjectId, ref: 'b_using_options', form: {select2: {fngAjax: true}}},
  retakeDate: {type: Date, form: {showWhen: {lhs: '$exams.result', comp: 'eq', rhs: 'fail'}}}
}, {_id: false});

var FSchema = new Schema({
  surname: {type: String, index: true, list: {}},
  forename: {type: String, index: true, list: true},
  aTest: { type: Schema.Types.ObjectId, ref: 'b_using_options'},

//  exams: [ExamsSchema]    // defaults to horizontal compact form
  // or
  exams: {type: [ExamsSchema], form: {formStyle: 'inline'}}
});

var F;
try {
  F = mongoose.model('F');
} catch (e) {
  F = mongoose.model('F', FSchema);
}

F.prototype.searchResultFormat = function () {

  // You can set up a function to modify search result display and the
  // ordering within a collection
  var weighting;

  weighting = this.forename === 'John' ? 2 : 3;

  return {
    resource: 'f_nested_schema',
    resourceText: 'Exams',
    id: this._id,
    weighting: weighting,
    text: this.surname + ', ' + this.forename
  };
};

FSchema.statics.form = function (layout) {
  var formSchema = '';
  switch (layout) {
    case 'English' :
      // Just the English exam from the array
      formSchema = {
        surname: {},
        forename: {},
        exams: {subkey: {keyList: {subject: 'English'}, containerType: 'well', title: 'English Exam'}}
      };
      break;
    case 'EnglishAndMaths' :
      // English and Maths exams from the array
      formSchema = {
        surname: {},
        forename: {},
        exams: {subkey: [
          {keyList: {subject: 'English'}, containerType: 'well', title: 'English Exam'},
          {keyList: {subject: 'Maths'}, containerType: 'well', title: 'Maths Exam'}
        ]}
      };
      break;
  }
  return formSchema;
};

module.exports = {
  model: F,
  searchResultFormat: F.prototype.searchResultFormat
};

<commit_msg>Correct comment<commit_after>'use strict';
var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var ExamsSchema = new Schema({
  subject: String,
  examDate: Date,
  score: Number,
  result: {type: String, enum: ['distinction', 'merit', 'pass', 'fail']},
  grader: { type: Schema.Types.ObjectId, ref: 'b_using_options', form: {select2: {fngAjax: true}}},
  retakeDate: {type: Date, form: {showWhen: {lhs: '$exams.result', comp: 'eq', rhs: 'fail'}}}
}, {_id: false});

var FSchema = new Schema({
  surname: {type: String, index: true, list: {}},
  forename: {type: String, index: true, list: true},
  aTest: { type: Schema.Types.ObjectId, ref: 'b_using_options'},

//  exams: [ExamsSchema]    // defaults to horizontal compact form
  // or
  exams: {type: [ExamsSchema], form: {formStyle: 'inline'}}
});

var F;
try {
  F = mongoose.model('F');
} catch (e) {
  F = mongoose.model('F', FSchema);
}

F.prototype.searchResultFormat = function () {

  // You can set up a function to modify search result display and the
  // ordering within a collection
  var weighting;

  weighting = this.forename === 'John' ? 2 : 3;

  return {
    resource: 'f_nested_schema',
    resourceText: 'Exams',
    id: this._id,
    weighting: weighting,
    text: this.surname + ', ' + this.forename
  };
};

FSchema.statics.form = function (layout) {
  var formSchema = '';
  switch (layout) {
    case 'English' :
      // Just the English exam from the array
      formSchema = {
        surname: {},
        forename: {},
        exams: {subkey: {keyList: {subject: 'English'}, containerType: 'well', title: 'English Exam'}}
      };
      break;
    case 'EnglishAndMaths' :
      // English and Maths exams from the array
      formSchema = {
        surname: {},
        forename: {},
        exams: {subkey: [
          {keyList: {subject: 'English'}, containerType: 'well', title: 'English Exam'},
          {keyList: {subject: 'Maths'}, containerType: 'well', title: 'Maths Exam'}
        ]}
      };
      break;
    case 'ResultsOnly' :
      // Demonstration of specifying fields within sub schemas in a form schema
      formSchema = {
        surname: {},
        forename: {},
        exams: {schema: {
          subject: {},
          result: {}
        }}
      };
      break;
  }
  return formSchema;
};

module.exports = {
  model: F,
  searchResultFormat: F.prototype.searchResultFormat
};

<|endoftext|>


<commit_before>
describe("Privacy selector", function() {
  var privacy_selector, vis;

  beforeEach(function() {
    vis = new cdb.admin.Visualization({
      map_id:           96,
      active_layer_id:  null,
      name:             "test_table",
      description:      "Visualization description",
      tags:             ["jamon","probando","test"],
      privacy:          "PUBLIC",
      updated_at:       "2013-03-04T18:09:34+01:00",
      type:             "table"
    });

    privacy_selector = new cdb.admin.PrivacySelector({
      model: vis,
      limitation: true,
      direction: 'down',
      upgrade_url: window.location.protocol + "//test.localhost.lan/account/development/upgrade"
    });
  });

  it("should render properly when you can't change to private tables", function() {
    privacy_selector.render();
    expect(privacy_selector.$('span.radio').length).toEqual(0);
    expect(privacy_selector.$('p:contains("Free users")').length).toEqual(1);
  });

  it("should render properly when you can change to private tables", function() {
    var new_privacy = new cdb.admin.PrivacySelector({
      model: vis,
      limitation: false,
      direction: 'down',
      upgrade_url: window.location.protocol + "//test.localhost.lan/account/development/upgrade"
    });

    new_privacy.render();
    expect(new_privacy.$('span.radio').length).toEqual(2);
    expect(new_privacy.$('li a:contains("Make this table public")').length).toEqual(1);
    expect(new_privacy.$('li a:contains("Make this table private")').length).toEqual(1);
  });

  it("should render properly when you can't change to private vis", function() {
    vis.set('type', 'derived');
    privacy_selector.render();
    expect(privacy_selector.$('span.radio').length).toEqual(0);
    expect(privacy_selector.$('p:contains("Free users")').length).toEqual(1);
  });

  it("should render properly when you can change to private visualizations", function() {
    vis.set('type', 'derived');
    var new_privacy = new cdb.admin.PrivacySelector({
      model: vis,
      limitation: false,
      direction: 'down',
      upgrade_url: window.location.protocol + "//test.localhost.lan/account/development/upgrade"
    });

    new_privacy.render();
    expect(new_privacy.$('span.radio').length).toEqual(2);
    expect(new_privacy.$('li a:contains("Make this vis private")').length).toEqual(1);
    expect(new_privacy.$('li a:contains("Make this vis public")').length).toEqual(1);
  });

  it("shouldn't change the model if it selects the same privacy", function() {
    var new_privacy = new cdb.admin.PrivacySelector({
      model: vis,
      limitation: false,
      direction: 'down',
      upgrade_url: window.location.protocol + "//test.localhost.lan/account/development/upgrade"
    });

    spyOn(new_privacy.model, 'set');
    new_privacy.render();
    new_privacy.$('li a:eq(0)').click();

    expect(new_privacy.model.set).not.toHaveBeenCalled();
  });

  it("should change the model when user clicks in private tables", function() {
    var new_privacy = new cdb.admin.PrivacySelector({
      model: vis,
      limitation: false,
      direction: 'down',
      upgrade_url: window.location.protocol + "//test.localhost.lan/account/development/upgrade"
    });

    new_privacy.render();
    new_privacy.$('li a:eq(1)').click();

    expect(new_privacy.warning).toBeDefined();
    expect(new_privacy.warning.$('h3').text()).toBe('Change table privacy');

    new_privacy.warning.$('a.ok').click();
    expect(new_privacy.model.get('privacy')).toBe('PRIVATE');

    new_privacy.warning.clean();
  });

  it("should change the model when user clicks in private visualizations", function() {
    vis.set('type', 'derived', {silent:true})
    var new_privacy = new cdb.admin.PrivacySelector({
      model: vis,
      limitation: false,
      direction: 'down',
      upgrade_url: window.location.protocol + "//test.localhost.lan/account/development/upgrade"
    });

    new_privacy.render();
    new_privacy.$('li a:eq(1)').click();

    expect(new_privacy.warning).toBeDefined();
    expect(new_privacy.warning.$('h3').text()).toBe('Change visualization privacy');

    new_privacy.warning.$('a.ok').click();
    expect(new_privacy.model.get('privacy')).toBe('PRIVATE');

    new_privacy.warning.clean();
  });

  it("should show the 'related private tables' dialog properly when you change to private vis", function() {
    var new_vis = new cdb.admin.Visualization({
      map_id:           96,
      active_layer_id:  null,
      name:             "test_table",
      description:      "Visualization description",
      tags:             ["jamon","probando","test"],
      privacy:          "PRIVATE",
      updated_at:       "2013-03-04T18:09:34+01:00",
      type:             "derived",
      related_tables:   [{ id: "23423432", "table_name": "jamon", "privacy": "PRIVATE" }]
    });

    expect(new_vis.get('related_tables')).toBeTruthy();

    var new_privacy = new cdb.admin.PrivacySelector({
      model: new_vis,
      limitation: false,
      direction: 'down',
      upgrade_url: window.location.protocol + "//test.localhost.lan/account/development/upgrade"
    });

    new_privacy.render();

    new_privacy.$('li a.public').click();

    expect(new_privacy.warning).toBeDefined();
    expect(new_privacy.warning.options.title).toBe('Cannot make this visualization public')
    new_privacy.warning.clean();
  });

  it("should get 'related tables' when starts privacy dialog if visualization is derived type", function() {
    vis.set({
      'type': 'derived',
      'privacy': 'PRIVATE',
      'id': 5
    });

    var server = sinon.fakeServer.create();
    expect(vis.get('related_tables')).toBeFalsy();

    var new_privacy = new cdb.admin.PrivacySelector({
      model: vis,
      limitation: false,
      direction: 'down',
      upgrade_url: window.location.protocol + "//test.localhost.lan/account/development/upgrade"
    });

    server.respondWith('/api/v1/viz/5', [200, { "Content-Type": "application/json" }, '{ "related_tables": [{ "table_name": "jamon", "privacy": "PRIVATE" }] }']);
    server.respond();

    expect(vis.get('related_tables').length == 1).toBeTruthy();
  });

});
<commit_msg>Comments private selector tests<commit_after>
describe("Privacy selector", function() {
  var privacy_selector, vis;

  beforeEach(function() {
    vis = new cdb.admin.Visualization({
      map_id:           96,
      active_layer_id:  null,
      name:             "test_table",
      description:      "Visualization description",
      tags:             ["jamon","probando","test"],
      privacy:          "PUBLIC",
      updated_at:       "2013-03-04T18:09:34+01:00",
      type:             "table"
    });

    privacy_selector = new cdb.admin.PrivacySelector({
      model: vis,
      limitation: true,
      direction: 'down',
      upgrade_url: window.location.protocol + "//test.localhost.lan/account/development/upgrade"
    });
  });

  it("should render properly when you can't change to private tables", function() {
    privacy_selector.render();
    expect(privacy_selector.$('span.radio').length).toEqual(0);
    expect(privacy_selector.$('p:contains("Free users")').length).toEqual(1);
  });

  it("should render properly when you can change to private tables", function() {
    var new_privacy = new cdb.admin.PrivacySelector({
      model: vis,
      limitation: false,
      direction: 'down',
      upgrade_url: window.location.protocol + "//test.localhost.lan/account/development/upgrade"
    });

    new_privacy.render();
    expect(new_privacy.$('span.radio').length).toEqual(2);
    expect(new_privacy.$('li a:contains("Make this table public")').length).toEqual(1);
    expect(new_privacy.$('li a:contains("Make this table private")').length).toEqual(1);
  });

  it("should render properly when you can't change to private vis", function() {
    vis.set('type', 'derived');
    privacy_selector.render();
    expect(privacy_selector.$('span.radio').length).toEqual(0);
    expect(privacy_selector.$('p:contains("Free users")').length).toEqual(1);
  });

  it("should render properly when you can change to private visualizations", function() {
    vis.set('type', 'derived');
    var new_privacy = new cdb.admin.PrivacySelector({
      model: vis,
      limitation: false,
      direction: 'down',
      upgrade_url: window.location.protocol + "//test.localhost.lan/account/development/upgrade"
    });

    new_privacy.render();
    expect(new_privacy.$('span.radio').length).toEqual(2);
    expect(new_privacy.$('li a:contains("Make this vis private")').length).toEqual(1);
    expect(new_privacy.$('li a:contains("Make this vis public")').length).toEqual(1);
  });

  xit("shouldn't change the model if it selects the same privacy", function() {
    var new_privacy = new cdb.admin.PrivacySelector({
      model: vis,
      limitation: false,
      direction: 'down',
      upgrade_url: window.location.protocol + "//test.localhost.lan/account/development/upgrade"
    });

    spyOn(new_privacy.model, 'set');
    new_privacy.render();
    new_privacy.$('li a:eq(0)').click();

    expect(new_privacy.model.set).not.toHaveBeenCalled();
  });

  xit("should change the model when user clicks in private tables", function() {
    var new_privacy = new cdb.admin.PrivacySelector({
      model: vis,
      limitation: false,
      direction: 'down',
      upgrade_url: window.location.protocol + "//test.localhost.lan/account/development/upgrade"
    });

    new_privacy.render();
    new_privacy.$('li a:eq(1)').click();

    expect(new_privacy.warning).toBeDefined();
    expect(new_privacy.warning.$('h3').text()).toBe('Change table privacy');

    new_privacy.warning.$('a.ok').click();
    expect(new_privacy.model.get('privacy')).toBe('PRIVATE');

    new_privacy.warning.clean();
  });

  xit("should change the model when user clicks in private visualizations", function() {
    vis.set('type', 'derived', {silent:true})
    var new_privacy = new cdb.admin.PrivacySelector({
      model: vis,
      limitation: false,
      direction: 'down',
      upgrade_url: window.location.protocol + "//test.localhost.lan/account/development/upgrade"
    });

    new_privacy.render();
    new_privacy.$('li a:eq(1)').click();

    expect(new_privacy.warning).toBeDefined();
    expect(new_privacy.warning.$('h3').text()).toBe('Change visualization privacy');

    new_privacy.warning.$('a.ok').click();
    expect(new_privacy.model.get('privacy')).toBe('PRIVATE');

    new_privacy.warning.clean();
  });

  it("should show the 'related private tables' dialog properly when you change to private vis", function() {
    var new_vis = new cdb.admin.Visualization({
      map_id:           96,
      active_layer_id:  null,
      name:             "test_table",
      description:      "Visualization description",
      tags:             ["jamon","probando","test"],
      privacy:          "PRIVATE",
      updated_at:       "2013-03-04T18:09:34+01:00",
      type:             "derived",
      related_tables:   [{ id: "23423432", "table_name": "jamon", "privacy": "PRIVATE" }]
    });

    expect(new_vis.get('related_tables')).toBeTruthy();

    var new_privacy = new cdb.admin.PrivacySelector({
      model: new_vis,
      limitation: false,
      direction: 'down',
      upgrade_url: window.location.protocol + "//test.localhost.lan/account/development/upgrade"
    });

    new_privacy.render();

    new_privacy.$('li a.public').click();

    expect(new_privacy.warning).toBeDefined();
    expect(new_privacy.warning.options.title).toBe('Cannot make this visualization public')
    new_privacy.warning.clean();
  });

  it("should get 'related tables' when starts privacy dialog if visualization is derived type", function() {
    vis.set({
      'type': 'derived',
      'privacy': 'PRIVATE',
      'id': 5
    });

    var server = sinon.fakeServer.create();
    expect(vis.get('related_tables')).toBeFalsy();

    var new_privacy = new cdb.admin.PrivacySelector({
      model: vis,
      limitation: false,
      direction: 'down',
      upgrade_url: window.location.protocol + "//test.localhost.lan/account/development/upgrade"
    });

    server.respondWith('/api/v1/viz/5', [200, { "Content-Type": "application/json" }, '{ "related_tables": [{ "table_name": "jamon", "privacy": "PRIVATE" }] }']);
    server.respond();

    expect(vis.get('related_tables').length == 1).toBeTruthy();
  });

});
<|endoftext|>


<commit_before>
// eslint-disable-next-line
import Inferno from 'inferno';
import Component from 'inferno-component';

import assign from 'lodash/assign';

import Ids from 'ids';

const ids = new Ids();

export default class ContextMenuComponent extends Component {

  constructor(props) {
    super(props);

    this.state = {
      isOpen: false,
      position: {
        x: 0,
        y: 0
      }
    };

    this.open = this.open.bind(this);
    this.close = this.close.bind(this);
    this.onClick = this.onClick.bind(this);
  }

  /**
   *
   * @param {Object} position - Position of context menu. Can either be point or box.
   * Context Menu will figure out best position.
   * @param {number} position.x - X coordinate of position.
   * @param {number} position.y - Y coordinate of position.
   * @param {number} position.width - Width of position box.
   * @param {number} position.height - Height of position box.
   * @param {Object} [context] - Context.
   */
  open({ position, context }) {

    if (!position) {
      position = { x: 0, y: 0 };
    }

    if (!context) {
      context = {};
    }

    const id = ids.next();

    this.setState({
      id,
      isOpen: true,
      position,
      context
    }, () => {

      // prevent listener being called immediately due to event bubbling
      setTimeout(() => {
        window.addEventListener('click', this.onClick(id));
      });
    });
  }

  /**
   * Closes context menu and resets state.
   */
  close() {
    this.setState({
      id: undefined,
      context: undefined,
      isOpen: false,
      position: {
        x: 0,
        y: 0
      }
    });
  }

  /**
   * Returns event listener that closes context menu with specified ID if
   * event target was not context menu itself and removes itself afterwards.
   *
   * @param {string} id - ID of context menu that will be closed by this listener.
   */
  onClick(id) {

    const listener = ({ target }) => {

      if (this.state.id === id) {

        if (!this.node) {

          // TODO(philippfromme): listener should be removed on componentWillUnmount
          window.removeEventListener('click', listener);

          return;
        }

        if (!this.node.contains(target)) {
          this._eventBus.fire('contextMenu.close');

          window.removeEventListener('click', listener);
        }

      } else {

        // context menu with ID was closed
        window.removeEventListener('click', listener);
      }

    };

    return listener;
  }

  componentWillMount() {
    const { injector } = this.context;

    this._components = injector.get('components');

    const eventBus = this._eventBus = injector.get('eventBus');
    this._renderer = injector.get('renderer');

    eventBus.on('contextMenu.open', this.open);
    eventBus.on('contextMenu.close', this.close);
  }

  componentWillUnmount() {
    this._eventBus.off('contextMenu.open', this.open);
    this._eventBus.off('contextMenu.close', this.close);
  }

  // get best position and layout
  componentDidUpdate() {
    if (!this.state.isOpen) {
      return;
    }

    const { position } = this.state;

    if (!this.node) {
      return;
    }

    const bounds = this.node.getBoundingClientRect();

    if (!position.width) {
      position.width = 0;
    }

    if (!position.height) {
      position.height = 0;
    }

    const container = this._renderer.getContainer();

    const containerBounds = container.getBoundingClientRect();

    if (containerBounds.width > containerBounds.height) {
      this.node.classList.add('horizontal');
      this.node.classList.remove('vertical');
    } else {
      this.node.classList.add('vertical');
      this.node.classList.remove('horizontal');
    }

    const { scrollLeft, scrollTop } = container;

    const contextMenuPosition = {};

    if (position.x + (position.width / 2) > containerBounds.width / 2) {
      contextMenuPosition.left =
        (position.x
        - containerBounds.left
        - bounds.width
        + scrollLeft)
        + 'px';
    } else {
      contextMenuPosition.left =
        (window.scrollX
        - containerBounds.left
        + position.x
        + position.width
        + scrollLeft)
        + 'px';
    }

    if (position.y + (position.height / 2) > containerBounds.height / 2) {
      contextMenuPosition.top =
        (position.y
        - containerBounds.top
        - bounds.height
        + scrollTop)
        + 'px';
    } else {
      contextMenuPosition.top =
        (window.scrollY
        - containerBounds.top
        + position.y
        + scrollTop)
        + 'px';
    }

    assign(this.node.style, contextMenuPosition);
  }

  render() {
    const { context, isOpen } = this.state;

    const contextMenuComponents = this._components.getComponents('context-menu', context);

    if (!contextMenuComponents || !contextMenuComponents.length) {
      return null;
    }

    return (
      isOpen &&
        <div
          ref={ node => this.node = node }
          onContextMenu={ e => e.preventDefault() }
          className="context-menu">
          {
            contextMenuComponents &&
            contextMenuComponents.map((Component, index) => <Component key={ index } context={ context } />)
          }
        </div>
    );
  }
}<commit_msg>fix(context-menu): always close before opening<commit_after>
// eslint-disable-next-line
import Inferno from 'inferno';
import Component from 'inferno-component';

import assign from 'lodash/assign';

import Ids from 'ids';

const ids = new Ids();

export default class ContextMenuComponent extends Component {

  constructor(props) {
    super(props);

    this.state = {
      isOpen: false,
      position: {
        x: 0,
        y: 0
      }
    };

    this.open = this.open.bind(this);
    this.close = this.close.bind(this);
    this.onClick = this.onClick.bind(this);
  }

  /**
   *
   * @param {Object} position - Position of context menu. Can either be point or box.
   * Context Menu will figure out best position.
   * @param {number} position.x - X coordinate of position.
   * @param {number} position.y - Y coordinate of position.
   * @param {number} position.width - Width of position box.
   * @param {number} position.height - Height of position box.
   * @param {Object} [context] - Context.
   */
  open({ position, context }) {

    // always close first
    this.close();

    if (!position) {
      position = { x: 0, y: 0 };
    }

    if (!context) {
      context = {};
    }

    const id = ids.next();

    this.setState({
      id,
      isOpen: true,
      position,
      context
    }, () => {

      // prevent listener being called immediately due to event bubbling
      setTimeout(() => {
        window.addEventListener('click', this.onClick(id));
      });
    });
  }

  /**
   * Closes context menu and resets state.
   */
  close() {
    this.setState({
      id: undefined,
      context: undefined,
      isOpen: false,
      position: {
        x: 0,
        y: 0
      }
    });
  }

  /**
   * Returns event listener that closes context menu with specified ID if
   * event target was not context menu itself and removes itself afterwards.
   *
   * @param {string} id - ID of context menu that will be closed by this listener.
   */
  onClick(id) {

    const listener = ({ target }) => {

      if (this.state.id === id) {

        if (!this.node) {

          // TODO(philippfromme): listener should be removed on componentWillUnmount
          window.removeEventListener('click', listener);

          return;
        }

        if (!this.node.contains(target)) {
          this._eventBus.fire('contextMenu.close');

          window.removeEventListener('click', listener);
        }

      } else {

        // context menu with ID was closed
        window.removeEventListener('click', listener);
      }

    };

    return listener;
  }

  componentWillMount() {
    const { injector } = this.context;

    this._components = injector.get('components');

    const eventBus = this._eventBus = injector.get('eventBus');
    this._renderer = injector.get('renderer');

    eventBus.on('contextMenu.open', this.open);
    eventBus.on('contextMenu.close', this.close);
  }

  componentWillUnmount() {
    this._eventBus.off('contextMenu.open', this.open);
    this._eventBus.off('contextMenu.close', this.close);
  }

  // get best position and layout
  componentDidUpdate() {
    if (!this.state.isOpen) {
      return;
    }

    const { position } = this.state;

    if (!this.node) {
      return;
    }

    const bounds = this.node.getBoundingClientRect();

    if (!position.width) {
      position.width = 0;
    }

    if (!position.height) {
      position.height = 0;
    }

    const container = this._renderer.getContainer();

    const containerBounds = container.getBoundingClientRect();

    if (containerBounds.width > containerBounds.height) {
      this.node.classList.add('horizontal');
      this.node.classList.remove('vertical');
    } else {
      this.node.classList.add('vertical');
      this.node.classList.remove('horizontal');
    }

    const { scrollLeft, scrollTop } = container;

    const contextMenuPosition = {};

    if (position.x + (position.width / 2) > containerBounds.width / 2) {
      contextMenuPosition.left =
        (position.x
        - containerBounds.left
        - bounds.width
        + scrollLeft)
        + 'px';
    } else {
      contextMenuPosition.left =
        (window.scrollX
        - containerBounds.left
        + position.x
        + position.width
        + scrollLeft)
        + 'px';
    }

    if (position.y + (position.height / 2) > containerBounds.height / 2) {
      contextMenuPosition.top =
        (position.y
        - containerBounds.top
        - bounds.height
        + scrollTop)
        + 'px';
    } else {
      contextMenuPosition.top =
        (window.scrollY
        - containerBounds.top
        + position.y
        + scrollTop)
        + 'px';
    }

    assign(this.node.style, contextMenuPosition);
  }

  render() {
    const { context, isOpen } = this.state;

    const contextMenuComponents = this._components.getComponents('context-menu', context);

    if (!contextMenuComponents || !contextMenuComponents.length) {
      return null;
    }

    return (
      isOpen &&
        <div
          ref={ node => this.node = node }
          onContextMenu={ e => e.preventDefault() }
          className="context-menu">
          {
            contextMenuComponents &&
            contextMenuComponents.map((Component, index) => <Component key={ index } context={ context } />)
          }
        </div>
    );
  }
}<|endoftext|>


<commit_before>// Fallback exports for node and phantomjs
var exports = exports || {};

// Code to run inside of mocha
exports.mocha = function () {
  before(function (done) {
    var exec = require('child_process').exec;
    var that = this;
    exec('phantomjs ' + this.filepath, function (err, stdout, stderr) {
      that.stdout = stdout;
      if (stderr) {
        console.error(stderr);
      }
      if (err) {
        done(err);
      }
    });
  });

  it('process.exit exits with given code', function () {
    var assert = require('assert');
    assert.strictEqual(this.stdout, 'Hello World');
  });
};

// Executed in the context of PhantomJS after shimming
exports.phantomjs = function () {
  process.stdout.write('Hello World');
  phantom.exit();
};
if (typeof phantom !== 'undefined') {
  exports.phantomjs();
}<commit_msg>Moved off of exec and to spawn, things work now. yey.<commit_after>// Fallback exports for node and phantomjs
var exports = exports || {};

// Code to run inside of mocha
exports.mocha = function () {
  before(function (done) {
    var spawn = require('child_process').spawn;
    var child = spawn('phantomjs', [this.filepath], {stdio: [0, 'pipe', 2]});
    var that = this;
    this.stdout = '';
    child.stdout.on('data', function (buff) {
      that.stdout += buff;
    });
    child.on('exit', function (code, signal) {
      done();
    });
  });

  it('process.exit exits with given code', function () {
    var assert = require('assert');
    assert.strictEqual(this.stdout, 'Hello World');
  });
};

// Executed in the context of PhantomJS after shimming
exports.phantomjs = function () {
  process.stdout.write('Hello World');
  phantom.exit();
};
if (typeof phantom !== 'undefined') {
  exports.phantomjs();
}<|endoftext|>


<commit_before>'use strict';

// MODULES //

var tape = require( 'tape' );
var proxyquire = require( 'proxyquire' ).noPreserveCache();
var isObject = require( '@stdlib/utils/is-plain-object' );
var getFile = require( './../lib/get_file.js' );

// TESTS //

tape( 'main export is a function', function test( t ) {
	t.ok( true, __filename );
	t.equal( typeof getFile, 'function', 'main export is a function' );
	t.end();
});

tape( 'the function returns an object', function test( t ) {
	t.equal( isObject( getFile( 0 ) ), true, 'returns an object' );
	t.end();
});

tape( 'if file data does not exist in the database, the data is synchronously loaded (non-browser environment)', function test( t ) {
	var getFile;
	var data;
	var file;
	var db;

	db = new Array( 10 );
	data = { 'beep': 'boop' };

	getFile = proxyquire( './../lib/get_file.js', {
		'./db.js': db,
		'./load_json.js': load
	});
	t.equal( db[ 5 ], void 0, 'db[5] has empty value' );

	file = getFile( 5 );
	t.deepEqual( file, data, 'returns file data' );
	t.notEqual( file, data, 'returns copy' );
	t.deepEqual( file, db[ 5 ], 'caches the returned data' );

	t.end();

	function load() {
		return data;
	}
});

tape( 'if data has been previously loaded, the function returns a value from a cache', function test( t ) {
	var getFile;
	var data;
	var file;
	var db;
	var i;

	db = new Array( 10 );
	data = { 'beep': 'boop' };

	getFile = proxyquire( './../lib/get_file.js', {
		'./db.js': db,
		'./load_json.js': load
	});
	t.equal( db[ 5 ], void 0, 'db[5] has empty value' );

	for ( i = 0; i < 10; i++ ) {
		file = getFile( 5 );
		t.deepEqual( file, data, 'returns file data' );
		t.deepEqual( db[ 5 ], data, 'data stored in database cache' );
	}
	t.end();

	function load() {
		return data;
	}
});
<commit_msg>Fix lint errors<commit_after>'use strict';

// MODULES //

var tape = require( 'tape' );
var proxyquire = require( 'proxyquire' ).noPreserveCache();
var isObject = require( '@stdlib/utils/is-plain-object' );
var getFile = require( './../lib/get_file.js' );

// TESTS //

tape( 'main export is a function', function test( t ) {
	t.ok( true, __filename );
	t.equal( typeof getFile, 'function', 'main export is a function' );
	t.end();
});

tape( 'the function returns an object', function test( t ) {
	t.equal( isObject( getFile( 0 ) ), true, 'returns an object' );
	t.end();
});

tape( 'if file data does not exist in the database, the data is synchronously loaded (non-browser environment)', function test( t ) {
	var getFile;
	var data;
	var file;
	var db;

	db = new Array( 10 );
	data = {
		'beep': 'boop'
	};

	getFile = proxyquire( './../lib/get_file.js', {
		'./db.js': db,
		'./load_json.js': load
	});
	t.equal( db[ 5 ], void 0, 'db[5] has empty value' );

	file = getFile( 5 );
	t.deepEqual( file, data, 'returns file data' );
	t.notEqual( file, data, 'returns copy' );
	t.deepEqual( file, db[ 5 ], 'caches the returned data' );

	t.end();

	function load() {
		return data;
	}
});

tape( 'if data has been previously loaded, the function returns a value from a cache', function test( t ) {
	var getFile;
	var data;
	var file;
	var db;
	var i;

	db = new Array( 10 );
	data = {
		'beep': 'boop'
	};

	getFile = proxyquire( './../lib/get_file.js', {
		'./db.js': db,
		'./load_json.js': load
	});
	t.equal( db[ 5 ], void 0, 'db[5] has empty value' );

	for ( i = 0; i < 10; i++ ) {
		file = getFile( 5 );
		t.deepEqual( file, data, 'returns file data' );
		t.deepEqual( db[ 5 ], data, 'data stored in database cache' );
	}
	t.end();

	function load() {
		return data;
	}
});
<|endoftext|>


<commit_before>'use strict';

/*
* When adding modules to the namespace, ensure that they are added in alphabetical order according to module name.
*/

// MODULES //

var setReadOnly = require( '@stdlib/utils/define-read-only-property' );

// MAIN //

/**
* Top-level namespace.
*
* @namespace poisson
*/
var poisson = {};

/**
* @name cdf
* @memberof poisson
* @readonly
* @type {Function}
* @see {@link module:@stdlib/math/base/dist/poisson/cdf}
*/
setReadOnly( poisson, 'cdf', require( '@stdlib/math/base/dist/poisson/cdf' ) );

/**
* @name kurtosis
* @memberof poisson
* @readonly
* @type {Function}
* @see {@link module:@stdlib/math/base/dist/poisson/kurtosis}
*/
setReadOnly( poisson, 'kurtosis', require( '@stdlib/math/base/dist/poisson/kurtosis' ) );

/**
* @name mean
* @memberof poisson
* @readonly
* @type {Function}
* @see {@link module:@stdlib/math/base/dist/poisson/mean}
*/
setReadOnly( poisson, 'mean', require( '@stdlib/math/base/dist/poisson/mean' ) );

/**
* @name median
* @memberof poisson
* @readonly
* @type {Function}
* @see {@link module:@stdlib/math/base/dist/poisson/median}
*/
setReadOnly( poisson, 'median', require( '@stdlib/math/base/dist/poisson/median' ) );

/**
* @name mgf
* @memberof poisson
* @readonly
* @type {Function}
* @see {@link module:@stdlib/math/base/dist/poisson/mgf}
*/
setReadOnly( poisson, 'mgf', require( '@stdlib/math/base/dist/poisson/mgf' ) );

/**
* @name mode
* @memberof poisson
* @readonly
* @type {Function}
* @see {@link module:@stdlib/math/base/dist/poisson/mode}
*/
setReadOnly( poisson, 'mode', require( '@stdlib/math/base/dist/poisson/mode' ) );

/**
* @name pmf
* @memberof poisson
* @readonly
* @type {Function}
* @see {@link module:@stdlib/math/base/dist/poisson/pmf}
*/
setReadOnly( poisson, 'pmf', require( '@stdlib/math/base/dist/poisson/pmf' ) );

/**
* @name Poisson
* @memberof poisson
* @readonly
* @type {Function}
* @see {@link module:@stdlib/math/base/dist/poisson/ctor}
*/
setReadOnly( poisson, 'Poisson', require( '@stdlib/math/base/dist/poisson/ctor' ) );

/**
* @name quantile
* @memberof poisson
* @readonly
* @type {Function}
* @see {@link module:@stdlib/math/base/dist/poisson/quantile}
*/
setReadOnly( poisson, 'quantile', require( '@stdlib/math/base/dist/poisson/quantile' ) );

/**
* @name skewness
* @memberof poisson
* @readonly
* @type {Function}
* @see {@link module:@stdlib/math/base/dist/poisson/skewness}
*/
setReadOnly( poisson, 'skewness', require( '@stdlib/math/base/dist/poisson/skewness' ) );

/**
* @name stdev
* @memberof poisson
* @readonly
* @type {Function}
* @see {@link module:@stdlib/math/base/dist/poisson/stdev}
*/
setReadOnly( poisson, 'stdev', require( '@stdlib/math/base/dist/poisson/stdev' ) );

/**
* @name variance
* @memberof poisson
* @readonly
* @type {Function}
* @see {@link module:@stdlib/math/base/dist/poisson/variance}
*/
setReadOnly( poisson, 'variance', require( '@stdlib/math/base/dist/poisson/variance' ) );

// EXPORTS //

module.exports = poisson;
<commit_msg>Add logpmf to distribution namespace<commit_after>'use strict';

/*
* When adding modules to the namespace, ensure that they are added in alphabetical order according to module name.
*/

// MODULES //

var setReadOnly = require( '@stdlib/utils/define-read-only-property' );

// MAIN //

/**
* Top-level namespace.
*
* @namespace poisson
*/
var poisson = {};

/**
* @name cdf
* @memberof poisson
* @readonly
* @type {Function}
* @see {@link module:@stdlib/math/base/dist/poisson/cdf}
*/
setReadOnly( poisson, 'cdf', require( '@stdlib/math/base/dist/poisson/cdf' ) );

/**
* @name kurtosis
* @memberof poisson
* @readonly
* @type {Function}
* @see {@link module:@stdlib/math/base/dist/poisson/kurtosis}
*/
setReadOnly( poisson, 'kurtosis', require( '@stdlib/math/base/dist/poisson/kurtosis' ) );

/**
* @name logpmf
* @memberof poisson
* @readonly
* @type {Function}
* @see {@link module:@stdlib/math/base/dist/poisson/logpmf}
*/
setReadOnly( poisson, 'logpmf', require( '@stdlib/math/base/dist/poisson/logpmf' ) );

/**
* @name mean
* @memberof poisson
* @readonly
* @type {Function}
* @see {@link module:@stdlib/math/base/dist/poisson/mean}
*/
setReadOnly( poisson, 'mean', require( '@stdlib/math/base/dist/poisson/mean' ) );

/**
* @name median
* @memberof poisson
* @readonly
* @type {Function}
* @see {@link module:@stdlib/math/base/dist/poisson/median}
*/
setReadOnly( poisson, 'median', require( '@stdlib/math/base/dist/poisson/median' ) );

/**
* @name mgf
* @memberof poisson
* @readonly
* @type {Function}
* @see {@link module:@stdlib/math/base/dist/poisson/mgf}
*/
setReadOnly( poisson, 'mgf', require( '@stdlib/math/base/dist/poisson/mgf' ) );

/**
* @name mode
* @memberof poisson
* @readonly
* @type {Function}
* @see {@link module:@stdlib/math/base/dist/poisson/mode}
*/
setReadOnly( poisson, 'mode', require( '@stdlib/math/base/dist/poisson/mode' ) );

/**
* @name pmf
* @memberof poisson
* @readonly
* @type {Function}
* @see {@link module:@stdlib/math/base/dist/poisson/pmf}
*/
setReadOnly( poisson, 'pmf', require( '@stdlib/math/base/dist/poisson/pmf' ) );

/**
* @name Poisson
* @memberof poisson
* @readonly
* @type {Function}
* @see {@link module:@stdlib/math/base/dist/poisson/ctor}
*/
setReadOnly( poisson, 'Poisson', require( '@stdlib/math/base/dist/poisson/ctor' ) );

/**
* @name quantile
* @memberof poisson
* @readonly
* @type {Function}
* @see {@link module:@stdlib/math/base/dist/poisson/quantile}
*/
setReadOnly( poisson, 'quantile', require( '@stdlib/math/base/dist/poisson/quantile' ) );

/**
* @name skewness
* @memberof poisson
* @readonly
* @type {Function}
* @see {@link module:@stdlib/math/base/dist/poisson/skewness}
*/
setReadOnly( poisson, 'skewness', require( '@stdlib/math/base/dist/poisson/skewness' ) );

/**
* @name stdev
* @memberof poisson
* @readonly
* @type {Function}
* @see {@link module:@stdlib/math/base/dist/poisson/stdev}
*/
setReadOnly( poisson, 'stdev', require( '@stdlib/math/base/dist/poisson/stdev' ) );

/**
* @name variance
* @memberof poisson
* @readonly
* @type {Function}
* @see {@link module:@stdlib/math/base/dist/poisson/variance}
*/
setReadOnly( poisson, 'variance', require( '@stdlib/math/base/dist/poisson/variance' ) );

// EXPORTS //

module.exports = poisson;
<|endoftext|>


<commit_before>/*jshint node: true, -W106 */
'use strict';

/*
* Name : pageSpec.js
* Module : UnitTest
* Location : /test/businessTier/page
*
* History :
*
* Version   Date         Programmer         Description
* =========================================================
* 0.0.1     2015-05-23   Samuele Zanella    Initial code
* =========================================================
*/

var Page = require('../../../lib/businessTier/page/page.js');
var PageModel = require('../../../lib/dataTier/page/pageModel.js');
var MapChart = require('../../../lib/businessTier/graph/mapChart.js');
var LineChart = require('../../../lib/businessTier/graph/lineChart.js');
var assert = require('assert');

var Norris = require('../../../lib/businessTier/norris/norris.js');
var Page = require('../../../lib/businessTier/page/page.js');
var express = require('express');
var app = express();
var http = require('http');
var server = http.createServer(app);
var io = require('socket.io')(server);
io.listen(5000);
var ioclient = require('socket.io-client');
var nor = new Norris(app, io, '/norris');
var page1 = nor.createPage({ID: 'page1'});

function ParamMock() {
    this._app = null;
    this._io = null;
    this._networkHandler = null;
    this._pageListSocket = null;
    this._pageList = null;
}

ParamMock.prototype.createSocket = function(param) {
    param = null;
    return this;
};

ParamMock.prototype.attachObject = function(param1, param2) {
    param1 = param2;
    return null;
};

ParamMock.prototype.addPageToRouting = function(param1, param2) {
    return param1 + ' ' + param2;
};

ParamMock.prototype.sendMessage = function(param1, param2) {
    return param1 + ' ' + param2;
};

ParamMock.prototype.pageChanged = function(param1) {
    return param1;
};

describe('Page', function() {

    it('returns null when there are no params', function() {
        assert.strictEqual((new Page()).hasOwnProperty('_page'), false);
    });

    it('returns null when there is no valid ID in params', function() {
        assert.strictEqual((new Page({})).hasOwnProperty('_name'), false);
    });

    it('returns null when there is a empty ID in params', function() {
        assert.strictEqual((new Page({ID:' '})).hasOwnProperty('_name'), false);
    });

    it('set param values to properties', function() {
        var page1=new Page({ID:'page1'}, new ParamMock(), new ParamMock());
        assert.deepEqual(page1._page, new PageModel({ID:'page1'}));
        assert.deepEqual(page1._networkHandler, new ParamMock());
        assert.deepEqual(page1._norris, new ParamMock());
        assert.strictEqual(page1._pageNamespace, '/page1');
        assert.deepEqual(page1._pageSocket, new ParamMock());
        assert.strictEqual(page1._graphs.length, 0);
    });

    describe('#getConfigJSON', function() {
        it('returns the JSON to send to clients when they connect', function() {
            var page2 = nor.createPage({ID:'page2', name:'page2', description:'page two', graphsPerRow: 3, graphsPerCol: 5});
            page2.createMapChart({ID:'map1'});
            page2.createLineChart({ID:'line1'});
            var expectedJSON = {
                properties: {
                    ID: 'page2',
                    name: 'page2',
                    description: 'page two',
                    graphsPerRow: 3,
                    graphsPerCol: 5
                },
                data: [
                    {
                        ID: 'map1',
                        title: '',
                        socketURL: '/page2/map1'
                    },
                    {
                        ID: 'line1',
                        title: '',
                        socketURL: '/page2/line1'
                    }
                ]
            };
            assert.deepEqual(page2.getConfigJSON(), expectedJSON);
        });
    });

    describe('#updateProperties', function() {
        it('does nothing when passed no valid parameter', function() {
            var page1=new Page({ID:'page1'}, nor._networkHandler, nor);
            page1.updateProperties();
            assert.deepEqual(page1._page, new PageModel({ID:'page1'}));
        });
        it('updates the properties to the passed parameters', function() {
            var page1=new Page({ID:'page1'}, nor._networkHandler, nor);
            var pSocketURL = 'http://0.0.0.0:5000/page1';
            var nSocketURL = 'http://0.0.0.0:5000/norris';
            var options ={
                transports: ['websocket'],
                'force new connection': true
            };
            var params = {
                name:'p1',
                description:'ppp',
                graphsPerRow: 5,
                graphsPerCol: 7
            };
            page1.updateProperties(params);
            var client1 = ioclient.connect(pSocketURL, options);
            var client2 = ioclient.connect(nSocketURL, options);
            client1.on('updatePageProp', function(message) {
                assert.strictEqual(message, params);
            });
            client2.on('updatePage', function(message) {
                assert.strictEqual(message, params);
            });
            assert.deepEqual(page1._page._ID, 'page1');
            assert.deepEqual(page1._page._name, 'p1');
            assert.deepEqual(page1._page._description, 'ppp');
            assert.deepEqual(page1._page._graphsPerRow, 5);
            assert.deepEqual(page1._page._graphsPerCol, 7);
        });
    });

    describe('#graphChanged', function() {
        it('sends the message over the socket', function() {
            var page1=new Page({ID:'page1'}, nor._networkHandler, nor);
            var pSocketURL = 'http://0.0.0.0:5000/page1';
            var nSocketURL = 'http://0.0.0.0:5000/norris';
            var options ={
                transports: ['websocket'],
                'force new connection': true
            };
            var params = {
                eventType: 'updateGraph',
                params: {
                    name: 'newName'
                }
            };
            page1.graphChanged(params);
            var client1 = ioclient.connect(pSocketURL, options);
            var client2 = ioclient.connect(nSocketURL, options);
            client1.on('updateGraph', function(message) {
                assert.strictEqual(message, params.params);
            });
            client2.on('updateGraph', function(message) {
                assert.strictEqual(message, params.params);
            });
        });
    });

    describe('#createMapChart', function() {
        it('returns null if no parameter is passed', function() {
            assert.deepEqual(page1.createMapChart(), null);
        });

        it('returns null if the passed parameter does not contain an ID', function() {
            assert.deepEqual(page1.createMapChart({p: 'abvs'}), null);
        });

        it('returns null if the passed ID is already used', function() {
            page1.createMapChart({ID: 'm1'});
            assert.deepEqual(page1.createMapChart({ID: 'm1'}), null);
        });

        it('returns null if the mapChartModel is not created', function() {
            assert.deepEqual(page1.createMapChart({ID: ''}), null);
        });

        it('behaves correctly with the right parameters', function() {
            var nor2 = new Norris(app, io, '/norris');
            var page4 = nor2.createPage({ID: 'page4'});
            var socketURL = 'http://0.0.0.0:5000/page4';
            var options ={
                transports: ['websocket'],
                'force new connection': true
            };
            var expJSON = {
                ID: 'page4',
                graph: {
                    ID: 'map1',
                    title: '',
                    type: 'MapChart',
                    socketURL: '/page4/map1'
                }
            };
            //var stPage = new Page({ID: 'page1'}, nor._networkHandler, nor);
            assert.deepEqual(page4.createMapChart({ID: 'map1'}) instanceof MapChart, true);
            assert.strictEqual(nor2._pages[0]._graphs.length, 1);
            assert.strictEqual(nor2._pageList._pages[0]._graphs.length, 1);
            var client1 = ioclient.connect(socketURL, options);
            client1.on('insertGraph', function(message) {
                assert.strictEqual(message, expJSON);
            });
        });
    });

    describe('#createLineChart', function() {
        it('returns null if no parameter is passed', function() {
            assert.deepEqual(page1.createLineChart(), null);
        });

        it('returns null if the passed parameter does not contain an ID', function() {
            assert.deepEqual(page1.createLineChart({p: 'abvs'}), null);
        });

        it('returns null if the passed ID is already used', function() {
            page1.createMapChart({ID: 'l1'});
            assert.deepEqual(page1.createLineChart({ID: 'l1'}), null);
        });

        it('returns null if the lineChartModel is not created', function() {
            assert.deepEqual(page1.createLineChart({ID: ''}), null);
        });

        it('behaves correctly with the right parameters', function() {
            var nor3 = new Norris(app, io, '/norris');
            var page3 = nor3.createPage({ID: 'page3'});
            var socketURL = 'http://0.0.0.0:5000/page3';
            var options ={
                transports: ['websocket'],
                'force new connection': true
            };
            var expJSON = {
                ID: 'page1',
                graph: {
                    ID: 'line1',
                    title: '',
                    type: 'LineChart',
                    socketURL: '/page3/line1'
                }
            };
            //var stPage = new Page({ID: 'page1'}, nor._networkHandler, nor);
            assert.deepEqual(page3.createLineChart({ID: 'line1'}) instanceof LineChart, true);
            assert.strictEqual(nor3._pages[0]._graphs.length, 1);
            assert.strictEqual(nor3._pageList._pages[0]._graphs.length, 1);
            var client1 = ioclient.connect(socketURL, options);
            client1.on('insertGraph', function(message) {
                assert.strictEqual(message, expJSON);
            });
        });
    });

    describe('#createBarChart', function() {
        it('returns null if no parameter is passed', function() {
            assert.deepEqual(page1.createBarChart(), null);
        });

        it('returns null if the passed parameter does not contain an ID', function() {
            assert.deepEqual(page1.createBarChart({p: 'abvs'}), null);
        });

        it('returns null if the passed ID is already used', function() {
            page1.createMapChart({ID: 'l1'});
            assert.deepEqual(page1.createBarChart({ID: 'l1'}), null);
        });

        it('returns null if the barChartModel is not created', function() {
            assert.deepEqual(page1.createBarChart({ID: ''}), null);
        });

        it('behaves correctly with the right parameters', function() {
            var nor4 = new Norris(app, io, '/norris');
            var page4 = nor3.createPage({ID: 'page3'});
            var socketURL = 'http://0.0.0.0:5000/page3';
            var options ={
                transports: ['websocket'],
                'force new connection': true
            };
            var expJSON = {
                ID: 'page1',
                graph: {
                    ID: 'bar1',
                    title: '',
                    type: 'BarChart',
                    socketURL: '/page3/bar1'
                }
            };
            //var stPage = new Page({ID: 'page1'}, nor._networkHandler, nor);
            assert.deepEqual(page4.createBarChart({ID: 'bar1'}) instanceof BarChart, true);
            assert.strictEqual(nor4._pages[0]._graphs.length, 1);
            assert.strictEqual(nor4._pageList._pages[0]._graphs.length, 1);
            var client1 = ioclient.connect(socketURL, options);
            client1.on('insertGraph', function(message) {
                assert.strictEqual(message, expJSON);
            });
        });
    });
});<commit_msg>fix page test<commit_after>/*jshint node: true, -W106 */
'use strict';

/*
* Name : pageSpec.js
* Module : UnitTest
* Location : /test/businessTier/page
*
* History :
*
* Version   Date         Programmer         Description
* =========================================================
* 0.0.1     2015-05-23   Samuele Zanella    Initial code
* =========================================================
*/

var Page = require('../../../lib/businessTier/page/page.js');
var PageModel = require('../../../lib/dataTier/page/pageModel.js');
var MapChart = require('../../../lib/businessTier/graph/mapChart.js');
var LineChart = require('../../../lib/businessTier/graph/lineChart.js');
var assert = require('assert');

var Norris = require('../../../lib/businessTier/norris/norris.js');
var Page = require('../../../lib/businessTier/page/page.js');
var express = require('express');
var app = express();
var http = require('http');
var server = http.createServer(app);
var io = require('socket.io')(server);
io.listen(5000);
var ioclient = require('socket.io-client');
var nor = new Norris(app, io, '/norris');
var page1 = nor.createPage({ID: 'page1'});

function ParamMock() {
    this._app = null;
    this._io = null;
    this._networkHandler = null;
    this._pageListSocket = null;
    this._pageList = null;
}

ParamMock.prototype.createSocket = function(param) {
    param = null;
    return this;
};

ParamMock.prototype.attachObject = function(param1, param2) {
    param1 = param2;
    return null;
};

ParamMock.prototype.addPageToRouting = function(param1, param2) {
    return param1 + ' ' + param2;
};

ParamMock.prototype.sendMessage = function(param1, param2) {
    return param1 + ' ' + param2;
};

ParamMock.prototype.pageChanged = function(param1) {
    return param1;
};

describe('Page', function() {

    it('returns null when there are no params', function() {
        assert.strictEqual((new Page()).hasOwnProperty('_page'), false);
    });

    it('returns null when there is no valid ID in params', function() {
        assert.strictEqual((new Page({})).hasOwnProperty('_name'), false);
    });

    it('returns null when there is a empty ID in params', function() {
        assert.strictEqual((new Page({ID:' '})).hasOwnProperty('_name'), false);
    });

    it('set param values to properties', function() {
        var page1=new Page({ID:'page1'}, new ParamMock(), new ParamMock());
        assert.deepEqual(page1._page, new PageModel({ID:'page1'}));
        assert.deepEqual(page1._networkHandler, new ParamMock());
        assert.deepEqual(page1._norris, new ParamMock());
        assert.strictEqual(page1._pageNamespace, '/page1');
        assert.deepEqual(page1._pageSocket, new ParamMock());
        assert.strictEqual(page1._graphs.length, 0);
    });

    describe('#getConfigJSON', function() {
        it('returns the JSON to send to clients when they connect', function() {
            var page2 = nor.createPage({ID:'page2', name:'page2', description:'page two', graphsPerRow: 3, graphsPerCol: 5});
            page2.createMapChart({ID:'map1'});
            page2.createLineChart({ID:'line1'});
            var expectedJSON = {
                properties: {
                    ID: 'page2',
                    name: 'page2',
                    description: 'page two',
                    graphsPerRow: 3,
                    graphsPerCol: 5
                },
                data: [
                    {
                        ID: 'map1',
                        title: '',
                        socketURL: '/page2/map1'
                    },
                    {
                        ID: 'line1',
                        title: '',
                        socketURL: '/page2/line1'
                    }
                ]
            };
            assert.deepEqual(page2.getConfigJSON(), expectedJSON);
        });
    });

    describe('#updateProperties', function() {
        it('does nothing when passed no valid parameter', function() {
            var page1=new Page({ID:'page1'}, nor._networkHandler, nor);
            page1.updateProperties();
            assert.deepEqual(page1._page, new PageModel({ID:'page1'}));
        });
        it('updates the properties to the passed parameters', function() {
            var page1=new Page({ID:'page1'}, nor._networkHandler, nor);
            var pSocketURL = 'http://0.0.0.0:5000/page1';
            var nSocketURL = 'http://0.0.0.0:5000/norris';
            var options ={
                transports: ['websocket'],
                'force new connection': true
            };
            var params = {
                name:'p1',
                description:'ppp',
                graphsPerRow: 5,
                graphsPerCol: 7
            };
            page1.updateProperties(params);
            var client1 = ioclient.connect(pSocketURL, options);
            var client2 = ioclient.connect(nSocketURL, options);
            client1.on('updatePageProp', function(message) {
                assert.strictEqual(message, params);
            });
            client2.on('updatePage', function(message) {
                assert.strictEqual(message, params);
            });
            assert.deepEqual(page1._page._ID, 'page1');
            assert.deepEqual(page1._page._name, 'p1');
            assert.deepEqual(page1._page._description, 'ppp');
            assert.deepEqual(page1._page._graphsPerRow, 5);
            assert.deepEqual(page1._page._graphsPerCol, 7);
        });
    });

    describe('#graphChanged', function() {
        it('sends the message over the socket', function() {
            var page1=new Page({ID:'page1'}, nor._networkHandler, nor);
            var pSocketURL = 'http://0.0.0.0:5000/page1';
            var nSocketURL = 'http://0.0.0.0:5000/norris';
            var options ={
                transports: ['websocket'],
                'force new connection': true
            };
            var params = {
                eventType: 'updateGraph',
                params: {
                    name: 'newName'
                }
            };
            page1.graphChanged(params);
            var client1 = ioclient.connect(pSocketURL, options);
            var client2 = ioclient.connect(nSocketURL, options);
            client1.on('updateGraph', function(message) {
                assert.strictEqual(message, params.params);
            });
            client2.on('updateGraph', function(message) {
                assert.strictEqual(message, params.params);
            });
        });
    });

    describe('#createMapChart', function() {
        it('returns null if no parameter is passed', function() {
            assert.deepEqual(page1.createMapChart(), null);
        });

        it('returns null if the passed parameter does not contain an ID', function() {
            assert.deepEqual(page1.createMapChart({p: 'abvs'}), null);
        });

        it('returns null if the passed ID is already used', function() {
            page1.createMapChart({ID: 'm1'});
            assert.deepEqual(page1.createMapChart({ID: 'm1'}), null);
        });

        it('returns null if the mapChartModel is not created', function() {
            assert.deepEqual(page1.createMapChart({ID: ''}), null);
        });

        it('behaves correctly with the right parameters', function() {
            var nor2 = new Norris(app, io, '/norris');
            var page4 = nor2.createPage({ID: 'page4'});
            var socketURL = 'http://0.0.0.0:5000/page4';
            var options ={
                transports: ['websocket'],
                'force new connection': true
            };
            var expJSON = {
                ID: 'page4',
                graph: {
                    ID: 'map1',
                    title: '',
                    type: 'MapChart',
                    socketURL: '/page4/map1'
                }
            };
            //var stPage = new Page({ID: 'page1'}, nor._networkHandler, nor);
            assert.deepEqual(page4.createMapChart({ID: 'map1'}) instanceof MapChart, true);
            assert.strictEqual(nor2._pages[0]._graphs.length, 1);
            assert.strictEqual(nor2._pageList._pages[0]._graphs.length, 1);
            var client1 = ioclient.connect(socketURL, options);
            client1.on('insertGraph', function(message) {
                assert.strictEqual(message, expJSON);
            });
        });
    });

    describe('#createLineChart', function() {
        it('returns null if no parameter is passed', function() {
            assert.deepEqual(page1.createLineChart(), null);
        });

        it('returns null if the passed parameter does not contain an ID', function() {
            assert.deepEqual(page1.createLineChart({p: 'abvs'}), null);
        });

        it('returns null if the passed ID is already used', function() {
            page1.createMapChart({ID: 'l1'});
            assert.deepEqual(page1.createLineChart({ID: 'l1'}), null);
        });

        it('returns null if the lineChartModel is not created', function() {
            assert.deepEqual(page1.createLineChart({ID: ''}), null);
        });

        it('behaves correctly with the right parameters', function() {
            var nor3 = new Norris(app, io, '/norris');
            var page3 = nor3.createPage({ID: 'page3'});
            var socketURL = 'http://0.0.0.0:5000/page3';
            var options ={
                transports: ['websocket'],
                'force new connection': true
            };
            var expJSON = {
                ID: 'page1',
                graph: {
                    ID: 'line1',
                    title: '',
                    type: 'LineChart',
                    socketURL: '/page3/line1'
                }
            };
            //var stPage = new Page({ID: 'page1'}, nor._networkHandler, nor);
            assert.deepEqual(page3.createLineChart({ID: 'line1'}) instanceof LineChart, true);
            assert.strictEqual(nor3._pages[0]._graphs.length, 1);
            assert.strictEqual(nor3._pageList._pages[0]._graphs.length, 1);
            var client1 = ioclient.connect(socketURL, options);
            client1.on('insertGraph', function(message) {
                assert.strictEqual(message, expJSON);
            });
        });
    });

    describe('#createBarChart', function() {
        it('returns null if no parameter is passed', function() {
            assert.deepEqual(page1.createBarChart(), null);
        });

        it('returns null if the passed parameter does not contain an ID', function() {
            assert.deepEqual(page1.createBarChart({p: 'abvs'}), null);
        });

        it('returns null if the passed ID is already used', function() {
            page1.createMapChart({ID: 'l1'});
            assert.deepEqual(page1.createBarChart({ID: 'l1'}), null);
        });

        it('returns null if the barChartModel is not created', function() {
            assert.deepEqual(page1.createBarChart({ID: ''}), null);
        });

        it('behaves correctly with the right parameters', function() {
            var nor4 = new Norris(app, io, '/norris');
            var page4 = nor4.createPage({ID: 'page4'});
            var socketURL = 'http://0.0.0.0:5000/page3';
            var options ={
                transports: ['websocket'],
                'force new connection': true
            };
            var expJSON = {
                ID: 'page1',
                graph: {
                    ID: 'bar1',
                    title: '',
                    type: 'BarChart',
                    socketURL: '/page4/bar1'
                }
            };
            //var stPage = new Page({ID: 'page1'}, nor._networkHandler, nor);
            assert.deepEqual(page4.createBarChart({ID: 'bar1'}) instanceof BarChart, true);
            assert.strictEqual(nor4._pages[0]._graphs.length, 1);
            assert.strictEqual(nor4._pageList._pages[0]._graphs.length, 1);
            var client1 = ioclient.connect(socketURL, options);
            client1.on('insertGraph', function(message) {
                assert.strictEqual(message, expJSON);
            });
        });
    });
});<|endoftext|>


<commit_before>/* eslint-disable no-unused-expressions */
import { expect } from 'chai';
import { shallow, mount } from 'enzyme';
import React from 'react';
import Navigation from '../../src/js/components/Navigation';

describe('<Navigation/>', () => {
  it('renders children as nav items', () => {
    const nav = (
      <Navigation>
        First
      </Navigation>
    );
    const result = mount(nav);
    expect(result.find('.nav__item').length).to.eq(1);
  });

  it('does not render if there are no children', () => {
    const result = shallow(<Navigation />);
    expect(result.html()).to.be.null;
  });
});
<commit_msg>Fix failing test for <Navigation><commit_after>/* eslint-disable no-unused-expressions */
import { expect } from 'chai';
import { shallow, mount } from 'enzyme';
import React from 'react';
import Navigation from '../../src/js/components/Navigation';

describe('<Navigation/>', () => {
  it('renders children as nav items', () => {
    const nav = (
      <Navigation>
        First
      </Navigation>
    );
    const result = mount(nav);
    expect(result.find('.nav__item').length).to.eq(1);
  });

  it('does not render if there are no children', () => {
    const result = shallow(<Navigation />);
    expect(result.html()).to.eq('');
  });
});
<|endoftext|>


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

const Brave = require('../lib/brave')
const {urlInput} = require('../lib/selectors')

describe('ContextMenu', function () {
  function * setup (client) {
    yield client
      .waitForUrl(Brave.newTabUrl)
      .waitForBrowserWindow()
      .waitForEnabled(urlInput)
  }

  describe('navigation', function () {
    Brave.beforeAll(this)

    before(function *() {
      yield setup(this.app.client)
      this.formfill = Brave.server.url('formfill.html')
      this.input = '[name="01___title"]'
      this.values = ['Value 1', 'Value 2', 'Value 3', 'Value 4']

      yield this.app.client
        .tabByIndex(0)
        .loadUrl(this.formfill)
        .waitForVisible('<form>')

      for (let i = 0; i < this.values.length; i++) {
        yield this.app.client
          .click(this.input)
          .keys(this.values[i])
          .click('#submit')
          .waitForVisible('<form>')
      }
    })

    it('check if context menu exists', function *() {
      yield this.app.client
        .tabByIndex(0)
        .loadUrl(this.formfill)
        .waitForVisible('<form>')
        .click(this.input)
        .click(this.input)
        .windowByUrl(Brave.browserWindowUrl)
        .waitForVisible('.contextMenuItemText')
    })

    it('check if enter is prevented', function *() {
      yield this.app.client
        .tabByIndex(0)
        .loadUrl(this.formfill)
        .waitForVisible('<form>')
        .click('[name="02frstname"]')
        .keys('Test value')
        .click(this.input)
        .click(this.input)
        .windowByUrl(Brave.browserWindowUrl)
        .waitForVisible('.contextMenu')
        .keys('\uE015')
        .pause(10)
        .keys('\uE015')
        .pause(10)
        .keys('\uE007')
        .pause(10)
        .tabByUrl(this.formfill)
        .getValue('[name="02frstname"]').should.eventually.be.equal('Test value')
        .getValue(this.input).should.eventually.be.equal(this.values[2])
    })

    it('click on item', function *() {
      yield this.app.client
        .tabByIndex(0)
        .loadUrl(this.formfill)
        .waitForVisible('<form>')
        .click(this.input)
        .click(this.input)
        .windowByUrl(Brave.browserWindowUrl)
        .waitForVisible('.contextMenu')
        .click('.contextMenuItem')
        .tabByUrl(this.formfill)
        .getValue(this.input).should.eventually.be.equal(this.values[0])
    })

    it('select item via click and keys', function *() {
      yield this.app.client
        .tabByIndex(0)
        .loadUrl(this.formfill)
        .waitForVisible('<form>')
        .click(this.input)
        .click(this.input)
        .windowByUrl(Brave.browserWindowUrl)
        .waitForVisible('.contextMenu')
        .keys('\uE015')
        .pause(10)
        .keys('\uE015')
        .pause(10)
        .keys('\uE007')
        .pause(10)
        .tabByUrl(this.formfill)
        .getValue(this.input).should.eventually.be.equal(this.values[2])
    })

    it('select item via keys only', function *() {
      yield this.app.client
        .tabByIndex(0)
        .loadUrl(this.formfill)
        .waitForVisible('<form>')
        .click(this.input)
        .windowByUrl(Brave.browserWindowUrl)
        .keys('\uE015')
        .waitForVisible('.contextMenu')
        .keys('\uE015')
        .pause(10)
        .keys('\uE015')
        .pause(10)
        .keys('\uE015')
        .pause(10)
        .keys('\uE015')
        .pause(10)
        .keys('\uE013')
        .pause(10)
        .keys('\uE007')
        .pause(10)
        .tabByUrl(this.formfill)
        .getValue(this.input).should.eventually.be.equal(this.values[3])
    })
  })
})
<commit_msg>Test for left/right on non sub menu item<commit_after>/* global describe, it, before */

const Brave = require('../lib/brave')
const {urlInput} = require('../lib/selectors')

describe('ContextMenu', function () {
  function * setup (client) {
    yield client
      .waitForUrl(Brave.newTabUrl)
      .waitForBrowserWindow()
      .waitForEnabled(urlInput)
  }

  describe('navigation', function () {
    Brave.beforeAll(this)

    before(function *() {
      yield setup(this.app.client)
      this.formfill = Brave.server.url('formfill.html')
      this.input = '[name="01___title"]'
      this.values = ['Value 1', 'Value 2', 'Value 3', 'Value 4']

      yield this.app.client
        .tabByIndex(0)
        .loadUrl(this.formfill)
        .waitForVisible('<form>')

      for (let i = 0; i < this.values.length; i++) {
        yield this.app.client
          .click(this.input)
          .keys(this.values[i])
          .click('#submit')
          .waitForVisible('<form>')
      }
    })

    it('check if context menu exists', function *() {
      yield this.app.client
        .tabByIndex(0)
        .loadUrl(this.formfill)
        .waitForVisible('<form>')
        .click(this.input)
        .click(this.input)
        .windowByUrl(Brave.browserWindowUrl)
        .waitForVisible('.contextMenuItemText')
    })

    it('check if enter is prevented', function *() {
      yield this.app.client
        .tabByIndex(0)
        .loadUrl(this.formfill)
        .waitForVisible('<form>')
        .click('[name="02frstname"]')
        .keys('Test value')
        .click(this.input)
        .click(this.input)
        .windowByUrl(Brave.browserWindowUrl)
        .waitForVisible('.contextMenu')
        .keys('\uE015')
        .pause(10)
        .keys('\uE015')
        .pause(10)
        .keys('\uE007')
        .pause(10)
        .tabByUrl(this.formfill)
        .getValue('[name="02frstname"]').should.eventually.be.equal('Test value')
        .getValue(this.input).should.eventually.be.equal(this.values[2])
    })

    it('click on item', function *() {
      yield this.app.client
        .tabByIndex(0)
        .loadUrl(this.formfill)
        .waitForVisible('<form>')
        .click(this.input)
        .click(this.input)
        .windowByUrl(Brave.browserWindowUrl)
        .waitForVisible('.contextMenu')
        .click('.contextMenuItem')
        .tabByUrl(this.formfill)
        .getValue(this.input).should.eventually.be.equal(this.values[0])
    })

    it('select item via click and keys', function *() {
      yield this.app.client
        .tabByIndex(0)
        .loadUrl(this.formfill)
        .waitForVisible('<form>')
        .click(this.input)
        .click(this.input)
        .windowByUrl(Brave.browserWindowUrl)
        .waitForVisible('.contextMenu')
        .keys('\uE015')
        .pause(10)
        .keys('\uE015')
        .pause(10)
        .keys('\uE007')
        .pause(10)
        .tabByUrl(this.formfill)
        .getValue(this.input).should.eventually.be.equal(this.values[2])
    })

    it('select item via keys only', function *() {
      yield this.app.client
        .tabByIndex(0)
        .loadUrl(this.formfill)
        .waitForVisible('<form>')
        .click(this.input)
        .windowByUrl(Brave.browserWindowUrl)
        .keys('\uE015')
        .waitForVisible('.contextMenu')
        .keys('\uE015')
        .pause(10)
        .keys('\uE015')
        .pause(10)
        .keys('\uE015')
        .pause(10)
        .keys('\uE015')
        .pause(10)
        .keys('\uE013')
        .pause(10)
        .keys('\uE007')
        .pause(10)
        .tabByUrl(this.formfill)
        .getValue(this.input).should.eventually.be.equal(this.values[3])
    })

    it('check left/right on non sub menu item', function *() {
      yield this.app.client
        .tabByIndex(0)
        .loadUrl(this.formfill)
        .waitForVisible('<form>')
        .click(this.input)
        .windowByUrl(Brave.browserWindowUrl)
        .keys('\uE015')
        .waitForVisible('.contextMenu')
        .keys('\uE012') // left
        .pause(10)
        .keys('\uE014') // right
        .pause(10)
        .keys('\uE014') // right
        .pause(10)
        .keys('\uE012') // left
        .pause(10)
        .keys('\uE015')
        .pause(10)
        .keys('\uE015')
        .pause(10)
        .keys('\uE007')
        .pause(10)
        .tabByUrl(this.formfill)
        .getValue(this.input).should.eventually.be.equal(this.values[2])
    })
  })
})
<|endoftext|>


<commit_before>import { List, fromJS } from 'immutable';
import { createSelector } from 'reselect';

import { getEventsAndDispatch } from '../../lib/api';

export const EVENTS_REQUEST = 'EVENTS_REQUEST';
export const eventsRequest = () => (dispatch, getState) => {
  dispatch({ type: EVENTS_REQUEST });
  return getEventsAndDispatch({
    actionError: eventsRequestError,
    actionSuccess: eventsRequestSuccess,
    dispatch
  });
};

export const EVENTS_REQUEST_SUCCESS = 'EVENTS_REQUEST_SUCCESS';
export const eventsRequestSuccess = (events) => ({
  type: EVENTS_REQUEST_SUCCESS,
  payload: events
});

export const EVENTS_REQUEST_ERROR = 'EVENTS_REQUEST_ERROR';
export const eventsRequestError = (error) => ({
  type: EVENTS_REQUEST_ERROR,
  payload: error,
  error: true
});

export const eventsReducer = (state = new List(), action) => {
  if (action.type === EVENTS_REQUEST_SUCCESS) {
    const incoming = fromJS(action.payload);
    const latest = getLatestEvent(state);
    if (!latest) {
      // no events, so seed with payload
      return incoming;
    }
    // only add events we don't have yet
    const newEvents = incoming.takeUntil((event) => event._id === latest._id);
    // use the last 120 of all the events we have now
    const allEvents = newEvents.concat(state);
    return allEvents.size > 120 ? allEvents.setSize(120) : allEvents;
  }
  if (action.type === EVENTS_REQUEST_ERROR) {
    console.log(action.type, action.payload);
  }
  return state;
};

export const getEvents = (state) => state.get('events') || new List();

export const getLatestEvent = (state) => state.first();

export const getEventsByTagsType = createSelector(
  [getEvents],
  (events) => events.groupBy((event) => event.getIn(['tags', 'type']))
);

export const getBeaconEvents = createSelector(
  [getEventsByTagsType],
  (eventGroups) => eventGroups.get('beacon') || new List()
);

export const getWifiEvents = createSelector(
  [getEventsByTagsType],
  (eventGroups) => eventGroups.get('wifi') || new List()
);

export const getRecentBeaconEvent = createSelector(
  [getBeaconEvents],
  (events) => {
    const event = events.first();
    if (event) {
      const date = new Date(event.get('date'));
      const now = new Date();
      if (date > now - 1 * 60 * 1e3) {
        return event;
      }
    }
    return null;
  }
);

export const getRecentWifiEvents = createSelector(
  [getWifiEvents],
  (events) => events.filter((event) => {
    const date = new Date(event.get('date'));
    const now = new Date();
    return date > now - 15 * 60 * 1e3;
  })
);

export const getRecentWifiEvent = createSelector(
  [getRecentWifiEvents],
  (events) => events.first() || null
);

const getEventPayload = (event) => event.getIn(['tags', 'payload']);

export const countBeacons = createSelector(
  [getRecentBeaconEvent],
  (event) => event ? getEventPayload(event).count() : 0
);

export const countWifi = createSelector(
  [getRecentWifiEvent],
  (event) => event ? getEventPayload(event).count() : 0
);

const mapPayloadToMAC = (payload) => payload.get('MAC');

export const countWifiDwellers = createSelector(
  [getRecentWifiEvents],
  (events) => {
    if (events.size < 2) {
      return 0;
    }
    const first = events.first();
    const rest = events.rest();
    const currentMACs = getEventPayload(first).map(mapPayloadToMAC);
    const olderMACs = [].concat(...rest.map((event) => {
      return getEventPayload(event).map(mapPayloadToMAC);
    }).toJS());
    return currentMACs.count((mac) => olderMACs.includes(mac));
  }
);
<commit_msg>PH-21 # (hopefully) add user IDs to events early<commit_after>import { List, fromJS } from 'immutable';
import { createSelector } from 'reselect';

import { getEventsAndDispatch } from '../../lib/api';
import { getTagsMap } from './tags';
import { store } from '../store';

export const EVENTS_REQUEST = 'EVENTS_REQUEST';
export const eventsRequest = () => (dispatch, getState) => {
  dispatch({ type: EVENTS_REQUEST });
  return getEventsAndDispatch({
    actionError: eventsRequestError,
    actionSuccess: eventsRequestSuccess,
    dispatch
  });
};

export const EVENTS_REQUEST_SUCCESS = 'EVENTS_REQUEST_SUCCESS';
export const eventsRequestSuccess = (events) => ({
  type: EVENTS_REQUEST_SUCCESS,
  payload: events
});

export const EVENTS_REQUEST_ERROR = 'EVENTS_REQUEST_ERROR';
export const eventsRequestError = (error) => ({
  type: EVENTS_REQUEST_ERROR,
  payload: error,
  error: true
});

// potentialIds (payload: { deviceid: String, data: String }) => String[]
const potentialIds = ({ deviceid = '', data = '' }) => [
  data.toLowerCase(),
  data.toUpperCase(),
  data.toLowerCase().replace(/^3000/, ''),
  data.toUpperCase().replace(/^3000/, ''),
  deviceid.toLowerCase(),
  deviceid.toUpperCase()
];

// firstMatch (map: Map, ids: String[]) => Map
const firstMatch = (map, ids) => {
  for (let id of ids) {
    let value = map.get(id);
    if (value) {
      return value;
    }
  }
  return null;
};

// ensurePayloadUser (tagsMap: Map) => (payload: Map) => Map
const ensurePayloadUser = (tagsMap) => (payload) => {
  if (payload.get('user')) {
    return payload;
  }
  const user = firstMatch(tagsMap, potentialIds(payload));
  if (user) {
    console.log(payload.toJS(), user);
  }
  return user ? payload.set('user', user) : payload;
};

// ensureEventUser (tagsMap: Map) => (event: Map) => Map
const ensureEventUser = (tagsMap) => (event) => {
  if (event.getIn(['tags', 'user'])) {
    return event;
  }
  // ensure each payload refers to a user
  const payloads = event.getIn(['tags', 'payload']);
  if (payloads && payloads.size) {
    return event.setIn(['tags', 'payload'], payloads.map(ensurePayloadUser(tagsMap)));
  }
  return event;
};

export const eventsReducer = (state = new List(), action) => {
  if (action.type === EVENTS_REQUEST_SUCCESS) {
    const incoming = fromJS(action.payload);
    const latest = getLatestEvent(state);
    const tagsMap = getTagsMap(store.getState());
    if (!latest) {
      // no events, so seed with payload
      return incoming.map(ensureEventUser(tagsMap));
    }
    // only add events we don't have yet
    let newEvents = incoming.takeUntil((event) => event._id === latest._id);
    newEvents = newEvents.map(ensureEventUser(tagsMap));
    // use the last 120 of all the events we have now
    const allEvents = newEvents.concat(state);
    return allEvents.size > 120 ? allEvents.setSize(120) : allEvents;
  }
  if (action.type === EVENTS_REQUEST_ERROR) {
    console.log(action.type, action.payload);
  }
  return state;
};

export const getEvents = (state) => state.get('events') || new List();

export const getLatestEvent = (state) => state.first();

export const getEventsByTagsType = createSelector(
  [getEvents],
  (events) => events.groupBy((event) => event.getIn(['tags', 'type']))
);

export const getBeaconEvents = createSelector(
  [getEventsByTagsType],
  (eventGroups) => eventGroups.get('beacon') || new List()
);

export const getWifiEvents = createSelector(
  [getEventsByTagsType],
  (eventGroups) => eventGroups.get('wifi') || new List()
);

export const getRecentBeaconEvent = createSelector(
  [getBeaconEvents],
  (events) => {
    const event = events.first();
    if (event) {
      const date = new Date(event.get('date'));
      const now = new Date();
      if (date > now - 1 * 60 * 1e3) {
        return event;
      }
    }
    return null;
  }
);

export const getRecentWifiEvents = createSelector(
  [getWifiEvents],
  (events) => events.filter((event) => {
    const date = new Date(event.get('date'));
    const now = new Date();
    return date > now - 15 * 60 * 1e3;
  })
);

export const getRecentWifiEvent = createSelector(
  [getRecentWifiEvents],
  (events) => events.first() || null
);

const getEventPayload = (event) => event.getIn(['tags', 'payload']);

export const countBeacons = createSelector(
  [getRecentBeaconEvent],
  (event) => event ? getEventPayload(event).count() : 0
);

export const countWifi = createSelector(
  [getRecentWifiEvent],
  (event) => event ? getEventPayload(event).count() : 0
);

const mapPayloadToMAC = (payload) => payload.get('MAC');

export const countWifiDwellers = createSelector(
  [getRecentWifiEvents],
  (events) => {
    if (events.size < 2) {
      return 0;
    }
    const first = events.first();
    const rest = events.rest();
    const currentMACs = getEventPayload(first).map(mapPayloadToMAC);
    const olderMACs = [].concat(...rest.map((event) => {
      return getEventPayload(event).map(mapPayloadToMAC);
    }).toJS());
    return currentMACs.count((mac) => olderMACs.includes(mac));
  }
);
<|endoftext|>