<commit_before>'use strict';

const fs = require('fs-extra');
const path = require('path');
const { describe, it } = require('../helpers/mocha');
const { expect } = require('../helpers/chai');
const {
  buildTmp,
  processBin,
  fixtureCompare: _fixtureCompare
} = require('git-fixtures');
const {
  assertNormalUpdate,
  assertNoUnstaged,
  assertNoStaged,
  assertCodemodRan
} = require('../helpers/assertions');
const { initBlueprint } = require('../helpers/blueprint');
const run = require('../../src/run');

describe(function() {
  this.timeout(30 * 1000);

  let tmpPath;

  async function merge({
    fixturesPath,
    from,
    to = '3.2.0-beta.1',
    runCodemods,
    subDir = '',
    commitMessage,
    init,
    reset,
    blueprint,
    install,
    addon,
    bootstrap,
    save,
    beforeMerge = () => Promise.resolve()
  }) {
    tmpPath = await buildTmp({
      fixturesPath,
      subDir
    });

    await beforeMerge();

    let args = [
      `--to=${to}`,
      '--resolve-conflicts'
    ];
    if (runCodemods) {
      args = [
        '--run-codemods'
      ];
    }
    if (init) {
      args = [
        'init',
        `--to=${to}`
      ];
      if (reset) {
        args.push('--reset');
      }
    }
    if (install) {
      args = [
        'install',
        addon
      ];
    }
    if (bootstrap) {
      args = [
        'bootstrap'
      ];
    }
    if (save) {
      args = [
        'save',
        `-b=${blueprint}`,
        `--from=${from}`
      ];
    }

    return processBin({
      binFile: 'ember-cli-update',
      args,
      cwd: tmpPath,
      commitMessage,
      expect
    });
  }

  function fixtureCompare({
    mergeFixtures
  }) {
    let actual = tmpPath;
    let expected = mergeFixtures;

    _fixtureCompare({
      expect,
      actual,
      expected
    });
  }

  it('updates app', async function() {
    let {
      status
    } = await (await merge({
      fixturesPath: 'test/fixtures/app/local',
      commitMessage: 'my-app'
    })).promise;

    fixtureCompare({
      mergeFixtures: 'test/fixtures/app/merge/my-app'
    });

    assertNormalUpdate(status);
    assertNoUnstaged(status);
  });

  it('updates addon', async function() {
    let {
      status
    } = await (await merge({
      fixturesPath: 'test/fixtures/addon/local',
      commitMessage: 'my-addon'
    })).promise;

    fixtureCompare({
      mergeFixtures: 'test/fixtures/addon/merge/my-addon'
    });

    assertNormalUpdate(status);
    assertNoUnstaged(status);
  });

  it('runs codemods', async function() {
    this.timeout(5 * 60 * 1000);

    let {
      ps,
      promise
    } = await merge({
      fixturesPath: 'test/fixtures/codemod/local',
      commitMessage: 'my-app',
      runCodemods: true
    });

    ps.stdout.pipe(process.stdout);

    ps.stdout.on('data', data => {
      let str = data.toString();
      if (str.includes('These codemods apply to your project.')) {
        ps.stdin.write(' \n');
      }
    });

    let {
      status
    } = await promise;

    // file is indeterminent between OS's, so ignore
    await fs.remove(path.join(tmpPath, 'MODULE_REPORT.md'));

    let mergeFixtures = 'test/fixtures/codemod/latest-node/my-app';
    if (process.env.NODE_LTS) {
      mergeFixtures = 'test/fixtures/codemod/min-node/my-app';
    }

    fixtureCompare({
      mergeFixtures
    });

    assertNoUnstaged(status);
    assertCodemodRan(status);
  });

  it('scopes to sub dir if run from there', async function() {
    let {
      status
    } = await (await merge({
      fixturesPath: 'test/fixtures/app/local',
      commitMessage: 'my-app',
      subDir: 'foo/bar'
    })).promise;

    fixtureCompare({
      mergeFixtures: 'test/fixtures/app/merge/my-app'
    });

    assertNormalUpdate(status);
    assertNoUnstaged(status);
  });

  it('can pick from multiple blueprints', async function() {
    this.timeout(15 * 60 * 1000);

    let {
      location,
      version: to
    } = require('../fixtures/blueprint/app/local-app/merge/my-app/config/ember-cli-update').blueprints[1];

    let {
      ps,
      promise
    } = await merge({
      fixturesPath: 'test/fixtures/blueprint/app/local-app/local',
      commitMessage: 'my-app',
      to,
      async beforeMerge() {
        await initBlueprint('test/fixtures/blueprint/app/local', location);
      }
    });

    ps.stdout.on('data', data => {
      let str = data.toString();
      if (str.includes('Blueprint updates have been found.')) {
        let down = '\u001b[B';
        let enter = '\n';
        ps.stdin.write(`${down}${enter}`);
      }
    });

    let {
      status
    } = await promise;

    fixtureCompare({
      mergeFixtures: 'test/fixtures/blueprint/app/local-app/merge/my-app'
    });

    expect(status).to.match(/^M {2}.*ember-cli-update\.json$/m);

    assertNoUnstaged(status);
  });

  it('can init the default blueprint', async function() {
    this.timeout(5 * 60 * 1000);

    let {
      status
    } = await (await merge({
      fixturesPath: 'test/fixtures/app/local',
      commitMessage: 'my-app',
      init: true,
      reset: true
    })).promise;

    expect(path.join(tmpPath, 'config/ember-cli-update.json')).to.be.a.file()
      .and.equal('test/fixtures/ember-cli-update-json/default/config/ember-cli-update.json');

    await fs.remove(path.join(tmpPath, 'config/ember-cli-update.json'));

    fixtureCompare({
      mergeFixtures: 'test/fixtures/app/reset/my-app'
    });

    expect(status).to.match(/^ D app\/controllers\/application\.js$/m);

    assertNoStaged(status);
  });

  it('can install an addon with a default blueprint and no state file', async function() {
    this.timeout(3 * 60 * 1000);

    let {
      location
    } = require('../fixtures/blueprint/addon/legacy-app/merge/ideal/my-app/config/ember-cli-update').blueprints[0];

    let {
      status
    } = await (await merge({
      fixturesPath: 'test/fixtures/blueprint/addon/legacy-app/local/no-addon',
      commitMessage: 'my-app',
      install: true,
      addon: location,
      async beforeMerge() {
        await initBlueprint('test/fixtures/blueprint/addon/legacy', location);

        await run('npm install', { cwd: tmpPath });
      }
    })).promise;

    await fs.remove(path.join(tmpPath, 'package-lock.json'));

    fixtureCompare({
      mergeFixtures: 'test/fixtures/blueprint/addon/legacy-app/merge/no-state-file/my-app'
    });

    assertNoStaged(status);
  });

  it('can bootstrap the default blueprint', async function() {
    let {
      status
    } = await (await merge({
      fixturesPath: 'test/fixtures/app/merge',
      commitMessage: 'my-app',
      bootstrap: true
    })).promise;

    assertNoUnstaged(status);

    expect(path.join(tmpPath, 'config/ember-cli-update.json')).to.be.a.file()
      .and.equal('test/fixtures/ember-cli-update-json/default/config/ember-cli-update.json');

    await fs.remove(path.join(tmpPath, 'config/ember-cli-update.json'));

    fixtureCompare({
      mergeFixtures: 'test/fixtures/app/merge/my-app'
    });
  });

  it('can save an old blueprint\'s state', async function() {
    let {
      name,
      version: from
    } = require('../fixtures/blueprint/app/npm-app/local/my-app/config/ember-cli-update').blueprints[0];

    let {
      status
    } = await (await merge({
      fixturesPath: 'test/fixtures/blueprint/app/npm-app/local',
      commitMessage: 'my-app',
      save: true,
      blueprint: name,
      from,
      async beforeMerge() {
        await fs.remove(path.join(tmpPath, 'config/ember-cli-update.json'));
      }
    })).promise;

    assertNoUnstaged(status);

    fixtureCompare({
      mergeFixtures: 'test/fixtures/blueprint/app/npm-app/local/my-app'
    });
  });
});
<commit_msg>check status before fixtures<commit_after>'use strict';

const fs = require('fs-extra');
const path = require('path');
const { describe, it } = require('../helpers/mocha');
const { expect } = require('../helpers/chai');
const {
  buildTmp,
  processBin,
  fixtureCompare: _fixtureCompare
} = require('git-fixtures');
const {
  assertNormalUpdate,
  assertNoUnstaged,
  assertNoStaged,
  assertCodemodRan
} = require('../helpers/assertions');
const { initBlueprint } = require('../helpers/blueprint');
const run = require('../../src/run');

describe(function() {
  this.timeout(30 * 1000);

  let tmpPath;

  async function merge({
    fixturesPath,
    from,
    to = '3.2.0-beta.1',
    runCodemods,
    subDir = '',
    commitMessage,
    init,
    reset,
    blueprint,
    install,
    addon,
    bootstrap,
    save,
    beforeMerge = () => Promise.resolve()
  }) {
    tmpPath = await buildTmp({
      fixturesPath,
      subDir
    });

    await beforeMerge();

    let args = [
      `--to=${to}`,
      '--resolve-conflicts'
    ];
    if (runCodemods) {
      args = [
        '--run-codemods'
      ];
    }
    if (init) {
      args = [
        'init',
        `--to=${to}`
      ];
      if (reset) {
        args.push('--reset');
      }
    }
    if (install) {
      args = [
        'install',
        addon
      ];
    }
    if (bootstrap) {
      args = [
        'bootstrap'
      ];
    }
    if (save) {
      args = [
        'save',
        `-b=${blueprint}`,
        `--from=${from}`
      ];
    }

    return processBin({
      binFile: 'ember-cli-update',
      args,
      cwd: tmpPath,
      commitMessage,
      expect
    });
  }

  function fixtureCompare({
    mergeFixtures
  }) {
    let actual = tmpPath;
    let expected = mergeFixtures;

    _fixtureCompare({
      expect,
      actual,
      expected
    });
  }

  it('updates app', async function() {
    let {
      status
    } = await (await merge({
      fixturesPath: 'test/fixtures/app/local',
      commitMessage: 'my-app'
    })).promise;

    fixtureCompare({
      mergeFixtures: 'test/fixtures/app/merge/my-app'
    });

    assertNormalUpdate(status);
    assertNoUnstaged(status);
  });

  it('updates addon', async function() {
    let {
      status
    } = await (await merge({
      fixturesPath: 'test/fixtures/addon/local',
      commitMessage: 'my-addon'
    })).promise;

    fixtureCompare({
      mergeFixtures: 'test/fixtures/addon/merge/my-addon'
    });

    assertNormalUpdate(status);
    assertNoUnstaged(status);
  });

  it('runs codemods', async function() {
    this.timeout(5 * 60 * 1000);

    let {
      ps,
      promise
    } = await merge({
      fixturesPath: 'test/fixtures/codemod/local',
      commitMessage: 'my-app',
      runCodemods: true
    });

    ps.stdout.pipe(process.stdout);

    ps.stdout.on('data', data => {
      let str = data.toString();
      if (str.includes('These codemods apply to your project.')) {
        ps.stdin.write(' \n');
      }
    });

    let {
      status
    } = await promise;

    assertNoUnstaged(status);
    assertCodemodRan(status);

    // file is indeterminent between OS's, so ignore
    await fs.remove(path.join(tmpPath, 'MODULE_REPORT.md'));

    let mergeFixtures = 'test/fixtures/codemod/latest-node/my-app';
    if (process.env.NODE_LTS) {
      mergeFixtures = 'test/fixtures/codemod/min-node/my-app';
    }

    fixtureCompare({
      mergeFixtures
    });
  });

  it('scopes to sub dir if run from there', async function() {
    let {
      status
    } = await (await merge({
      fixturesPath: 'test/fixtures/app/local',
      commitMessage: 'my-app',
      subDir: 'foo/bar'
    })).promise;

    fixtureCompare({
      mergeFixtures: 'test/fixtures/app/merge/my-app'
    });

    assertNormalUpdate(status);
    assertNoUnstaged(status);
  });

  it('can pick from multiple blueprints', async function() {
    this.timeout(15 * 60 * 1000);

    let {
      location,
      version: to
    } = require('../fixtures/blueprint/app/local-app/merge/my-app/config/ember-cli-update').blueprints[1];

    let {
      ps,
      promise
    } = await merge({
      fixturesPath: 'test/fixtures/blueprint/app/local-app/local',
      commitMessage: 'my-app',
      to,
      async beforeMerge() {
        await initBlueprint('test/fixtures/blueprint/app/local', location);
      }
    });

    ps.stdout.on('data', data => {
      let str = data.toString();
      if (str.includes('Blueprint updates have been found.')) {
        let down = '\u001b[B';
        let enter = '\n';
        ps.stdin.write(`${down}${enter}`);
      }
    });

    let {
      status
    } = await promise;

    fixtureCompare({
      mergeFixtures: 'test/fixtures/blueprint/app/local-app/merge/my-app'
    });

    expect(status).to.match(/^M {2}.*ember-cli-update\.json$/m);

    assertNoUnstaged(status);
  });

  it('can init the default blueprint', async function() {
    this.timeout(5 * 60 * 1000);

    let {
      status
    } = await (await merge({
      fixturesPath: 'test/fixtures/app/local',
      commitMessage: 'my-app',
      init: true,
      reset: true
    })).promise;

    expect(path.join(tmpPath, 'config/ember-cli-update.json')).to.be.a.file()
      .and.equal('test/fixtures/ember-cli-update-json/default/config/ember-cli-update.json');

    await fs.remove(path.join(tmpPath, 'config/ember-cli-update.json'));

    fixtureCompare({
      mergeFixtures: 'test/fixtures/app/reset/my-app'
    });

    expect(status).to.match(/^ D app\/controllers\/application\.js$/m);

    assertNoStaged(status);
  });

  it('can install an addon with a default blueprint and no state file', async function() {
    this.timeout(3 * 60 * 1000);

    let {
      location
    } = require('../fixtures/blueprint/addon/legacy-app/merge/ideal/my-app/config/ember-cli-update').blueprints[0];

    let {
      status
    } = await (await merge({
      fixturesPath: 'test/fixtures/blueprint/addon/legacy-app/local/no-addon',
      commitMessage: 'my-app',
      install: true,
      addon: location,
      async beforeMerge() {
        await initBlueprint('test/fixtures/blueprint/addon/legacy', location);

        await run('npm install', { cwd: tmpPath });
      }
    })).promise;

    await fs.remove(path.join(tmpPath, 'package-lock.json'));

    fixtureCompare({
      mergeFixtures: 'test/fixtures/blueprint/addon/legacy-app/merge/no-state-file/my-app'
    });

    assertNoStaged(status);
  });

  it('can bootstrap the default blueprint', async function() {
    let {
      status
    } = await (await merge({
      fixturesPath: 'test/fixtures/app/merge',
      commitMessage: 'my-app',
      bootstrap: true
    })).promise;

    assertNoUnstaged(status);

    expect(path.join(tmpPath, 'config/ember-cli-update.json')).to.be.a.file()
      .and.equal('test/fixtures/ember-cli-update-json/default/config/ember-cli-update.json');

    await fs.remove(path.join(tmpPath, 'config/ember-cli-update.json'));

    fixtureCompare({
      mergeFixtures: 'test/fixtures/app/merge/my-app'
    });
  });

  it('can save an old blueprint\'s state', async function() {
    let {
      name,
      version: from
    } = require('../fixtures/blueprint/app/npm-app/local/my-app/config/ember-cli-update').blueprints[0];

    let {
      status
    } = await (await merge({
      fixturesPath: 'test/fixtures/blueprint/app/npm-app/local',
      commitMessage: 'my-app',
      save: true,
      blueprint: name,
      from,
      async beforeMerge() {
        await fs.remove(path.join(tmpPath, 'config/ember-cli-update.json'));
      }
    })).promise;

    assertNoUnstaged(status);

    fixtureCompare({
      mergeFixtures: 'test/fixtures/blueprint/app/npm-app/local/my-app'
    });
  });
});
<|endoftext|>


<commit_before>import Parchment from 'parchment';
import clone from 'clone';
import equal from 'deep-equal';
import Emitter from './emitter';
import logger from './logger';

let debug = logger('quill:selection');

class Range {
  constructor(index, length = 0) {
    this.index = index;
    this.length = length;
  }
}

class Selection {
  constructor(scroll, emitter) {
    this.emitter = emitter;
    this.scroll = scroll;
    this.composing = false;
    this.mouseDown = false;
    this.root = this.scroll.domNode;
    this.cursor = Parchment.create('cursor', this);
    // savedRange is last non-null range
    this.lastRange = this.savedRange = new Range(0, 0);

    this.root.addEventListener('click', (e) => {
      const blot = Parchment.find(e.target, true);
      const selectedNode = document.querySelector('.ql-embed-selected');
      if (selectedNode) {
        selectedNode.classList.remove('ql-embed-selected');
      }
      if (blot instanceof Parchment.Embed) {
        blot.domNode.classList.add('ql-embed-selected');
        const range = new Range(blot.offset(scroll), blot.length());
        this.setRange(range, Emitter.sources.USER);
        e.stopPropagation();
      }
    });
    let mouseCount = 0;
    this.emitter.listenDOM('mousedown', document.body, () => {
      mouseCount += 1;
    });
    this.emitter.listenDOM('mouseup', document.body, () => {
      mouseCount -= 1;
      if (mouseCount === 0) {
        this.update(Emitter.sources.USER);
      }
    });

    this.handleComposition();
    this.handleDragging();

    this.emitter.listenDOM('selectionchange', document, () => {
      if (!this.mouseDown) {
        setTimeout(this.update.bind(this, Emitter.sources.USER), 1);
      }
    });
    this.emitter.on(Emitter.events.EDITOR_CHANGE, (type, delta) => {
      if (type === Emitter.events.TEXT_CHANGE && delta.length() > 0) {
        this.update(Emitter.sources.SILENT);
      }
    });
    this.emitter.on(Emitter.events.SCROLL_BEFORE_UPDATE, () => {
      if (!this.hasFocus()) return;
      let native = this.getNativeRange();
      if (native == null) return;
      if (native.start.node === this.cursor.textNode) return;  // cursor.restore() will handle
      // TODO unclear if this has negative side effects
      this.emitter.once(Emitter.events.SCROLL_UPDATE, () => {
        try {
          this.setNativeRange(native.start.node, native.start.offset, native.end.node, native.end.offset);
        } catch (ignored) {}
      });
    });
    this.emitter.on(Emitter.events.SCROLL_OPTIMIZE, (mutations, context) => {
      if (context.range) {
        const { startNode, startOffset, endNode, endOffset } = context.range;
        this.setNativeRange(startNode, startOffset, endNode, endOffset);
      }
    });
    this.update(Emitter.sources.SILENT);
  }

  handleComposition() {
    this.root.addEventListener('compositionstart', () => {
      this.composing = true;
    });
    this.root.addEventListener('compositionend', () => {
      this.composing = false;
      if (this.cursor.parent) {
        const range = this.cursor.restore();
        if (!range) return;
        setTimeout(() => {
          this.setNativeRange(range.startNode, range.startOffset, range.endNode, range.endOffset);
        }, 1);
      }
    });
  }

  handleDragging() {
    this.emitter.listenDOM('mousedown', document.body, () => {
      this.mouseDown = true;
    });
    this.emitter.listenDOM('mouseup', document.body, () => {
      this.mouseDown = false;
      this.update(Emitter.sources.USER);
    });
  }

  focus() {
    if (this.hasFocus()) return;
    this.root.focus();
    this.setRange(this.savedRange);
  }

  format(format, value) {
    if (this.scroll.whitelist != null && !this.scroll.whitelist[format]) return;
    this.scroll.update();
    let nativeRange = this.getNativeRange();
    if (nativeRange == null || !nativeRange.native.collapsed || Parchment.query(format, Parchment.Scope.BLOCK)) return;
    if (nativeRange.start.node !== this.cursor.textNode) {
      let blot = Parchment.find(nativeRange.start.node, false);
      if (blot == null) return;
      // TODO Give blot ability to not split
      if (blot instanceof Parchment.Leaf) {
        let after = blot.split(nativeRange.start.offset);
        blot.parent.insertBefore(this.cursor, after);
      } else {
        blot.insertBefore(this.cursor, nativeRange.start.node);  // Should never happen
      }
      this.cursor.attach();
    }
    this.cursor.format(format, value);
    this.scroll.optimize();
    this.setNativeRange(this.cursor.textNode, this.cursor.textNode.data.length);
    this.update();
  }

  getBounds(index, length = 0) {
    let scrollLength = this.scroll.length();
    index = Math.min(index, scrollLength - 1);
    length = Math.min(index + length, scrollLength - 1) - index;
    let node, [leaf, offset] = this.scroll.leaf(index);
    if (leaf == null) return null;
    [node, offset] = leaf.position(offset, true);
    let range = document.createRange();
    if (length > 0) {
      range.setStart(node, offset);
      [leaf, offset] = this.scroll.leaf(index + length);
      if (leaf == null) return null;
      [node, offset] = leaf.position(offset, true);
      range.setEnd(node, offset);
      return range.getBoundingClientRect();
    } else {
      let side = 'left';
      let rect;
      if (node instanceof Text) {
        if (offset < node.data.length) {
          range.setStart(node, offset);
          range.setEnd(node, offset + 1);
        } else {
          range.setStart(node, offset - 1);
          range.setEnd(node, offset);
          side = 'right';
        }
        rect = range.getBoundingClientRect();
      } else {
        rect = leaf.domNode.getBoundingClientRect();
        if (offset > 0) side = 'right';
      }
      return {
        bottom: rect.top + rect.height,
        height: rect.height,
        left: rect[side],
        right: rect[side],
        top: rect.top,
        width: 0
      };
    }
  }

  getNativeRange() {
    let selection = document.getSelection();
    if (selection == null || selection.rangeCount <= 0) return null;
    let nativeRange = selection.getRangeAt(0);
    if (nativeRange == null) return null;
    let range = this.normalizeNative(nativeRange);
    debug.info('getNativeRange', range);
    return range;
  }

  getRange() {
    let normalized = this.getNativeRange();
    if (normalized == null) return [null, null];
    let range = this.normalizedToRange(normalized);
    return [range, normalized];
  }

  hasFocus() {
    return document.activeElement === this.root;
  }

  normalizedToRange(range) {
    let positions = [[range.start.node, range.start.offset]];
    if (!range.native.collapsed) {
      positions.push([range.end.node, range.end.offset]);
    }
    let indexes = positions.map((position) => {
      let [node, offset] = position;
      let blot = Parchment.find(node, true);
      let index = blot.offset(this.scroll);
      if (offset === 0) {
        return index;
      } else if (blot instanceof Parchment.Container) {
        return index + blot.length();
      } else {
        return index + blot.index(node, offset);
      }
    });
    let end = Math.min(Math.max(...indexes), this.scroll.length() - 1);
    let start = Math.min(end, ...indexes);
    return new Range(start, end-start);
  }

  normalizeNative(nativeRange) {
    if (!contains(this.root, nativeRange.startContainer) ||
        (!nativeRange.collapsed && !contains(this.root, nativeRange.endContainer))) {
      return null;
    }
    let range = {
      start: { node: nativeRange.startContainer, offset: nativeRange.startOffset },
      end: { node: nativeRange.endContainer, offset: nativeRange.endOffset },
      native: nativeRange
    };
    [range.start, range.end].forEach(function(position) {
      let node = position.node, offset = position.offset;
      while (!(node instanceof Text) && node.childNodes.length > 0) {
        if (node.childNodes.length > offset) {
          node = node.childNodes[offset];
          offset = 0;
        } else if (node.childNodes.length === offset) {
          node = node.lastChild;
          offset = node instanceof Text ? node.data.length : node.childNodes.length + 1;
        } else {
          break;
        }
      }
      position.node = node, position.offset = offset;
    });
    return range;
  }

  rangeToNative(range) {
    let indexes = range.collapsed ? [range.index] : [range.index, range.index + range.length];
    let args = [];
    let scrollLength = this.scroll.length();
    indexes.forEach((index, i) => {
      index = Math.min(scrollLength - 1, index);
      let node, [leaf, offset] = this.scroll.leaf(index);
      [node, offset] = leaf.position(offset, i !== 0);
      args.push(node, offset);
    });
    if (args.length < 2) {
      args = args.concat(args);
    }
    return args;
  }

  scrollIntoView(scrollingContainer) {
    let range = this.lastRange;
    if (range == null) return;
    let bounds = this.getBounds(range.index, range.length);
    if (bounds == null) return;
    let limit = this.scroll.length()-1;
    let [first, ] = this.scroll.line(Math.min(range.index, limit));
    let last = first;
    if (range.length > 0) {
      [last, ] = this.scroll.line(Math.min(range.index + range.length, limit));
    }
    if (first == null || last == null) return;
    let scroller = this.scroll.scrollingContainer;
    // let scrollBounds = scroller.getBoundingClientRect();
    let headerHeight = 65;
    let windowHeight = window.innerHeight - 20;
    if (!!bounds.top && !!bounds.bottom && !!scroller) {
      if (bounds.top < headerHeight) {
        scroller.scrollTop -= (headerHeight - bounds.top);
      } else if (bounds.bottom > windowHeight) {
        scroller.scrollTop += (bounds.bottom - windowHeight);
      }
    }
  }

  setNativeRange(startNode, startOffset, endNode = startNode, endOffset = startOffset, force = false) {
    debug.info('setNativeRange', startNode, startOffset, endNode, endOffset);
    if (startNode != null && (this.root.parentNode == null || startNode.parentNode == null || endNode.parentNode == null)) {
      return;
    }
    let selection = document.getSelection();
    if (selection == null) return;
    if (startNode != null) {
      if (!this.hasFocus()) this.root.focus();
      let native = (this.getNativeRange() || {}).native;
      if (native == null || force ||
          startNode !== native.startContainer ||
          startOffset !== native.startOffset ||
          endNode !== native.endContainer ||
          endOffset !== native.endOffset) {

        if (startNode.tagName == "BR") {
          startOffset = [].indexOf.call(startNode.parentNode.childNodes, startNode);
          startNode = startNode.parentNode;
        }
        if (endNode.tagName == "BR") {
          endOffset = [].indexOf.call(endNode.parentNode.childNodes, endNode);
          endNode = endNode.parentNode;
        }
        let range = document.createRange();
        range.setStart(startNode, startOffset);
        range.setEnd(endNode, endOffset);
        selection.removeAllRanges();
        selection.addRange(range);
      }
    } else {
      selection.removeAllRanges();
      this.root.blur();
      document.body.focus();  // root.blur() not enough on IE11+Travis+SauceLabs (but not local VMs)
    }
  }

  setRange(range, force = false, source = Emitter.sources.API) {
    if (typeof force === 'string') {
      source = force;
      force = false;
    }
    debug.info('setRange', range);
    if (range != null) {
      let args = this.rangeToNative(range);
      this.setNativeRange(...args, force);
    } else {
      this.setNativeRange(null);
    }
    this.update(source);
  }

  update(source = Emitter.sources.USER) {
    let oldRange = this.lastRange;
    let [lastRange, nativeRange] = this.getRange();
    this.lastRange = lastRange;
    if (this.lastRange != null) {
      this.savedRange = this.lastRange;
    }
    if (!equal(oldRange, this.lastRange)) {
      if (!this.composing && nativeRange != null && nativeRange.native.collapsed && nativeRange.start.node !== this.cursor.textNode) {
        this.cursor.restore();
      }
      let args = [Emitter.events.SELECTION_CHANGE, clone(this.lastRange), clone(oldRange), source];
      this.emitter.emit(Emitter.events.EDITOR_CHANGE, ...args);
      if (source !== Emitter.sources.SILENT) {
        this.emitter.emit(...args);
      }
    }
  }
}

function contains(parent, descendant) {
  try {
    // Firefox inserts inaccessible nodes around video elements
    descendant.parentNode;
  } catch (e) {
    return false;
  }
  // IE11 has bug with Text nodes
  // https://connect.microsoft.com/IE/feedback/details/780874/node-contains-is-incorrect
  if (descendant instanceof Text) {
    descendant = descendant.parentNode;
  }
  return parent.contains(descendant);
}

export { Range, Selection as default };
<commit_msg>remove stop propagation<commit_after>import Parchment from 'parchment';
import clone from 'clone';
import equal from 'deep-equal';
import Emitter from './emitter';
import logger from './logger';

let debug = logger('quill:selection');

class Range {
  constructor(index, length = 0) {
    this.index = index;
    this.length = length;
  }
}

class Selection {
  constructor(scroll, emitter) {
    this.emitter = emitter;
    this.scroll = scroll;
    this.composing = false;
    this.mouseDown = false;
    this.root = this.scroll.domNode;
    this.cursor = Parchment.create('cursor', this);
    // savedRange is last non-null range
    this.lastRange = this.savedRange = new Range(0, 0);

    this.root.addEventListener('click', (e) => {
      const blot = Parchment.find(e.target, true);
      const selectedNode = document.querySelector('.ql-embed-selected');
      if (selectedNode) {
        selectedNode.classList.remove('ql-embed-selected');
      }
      if (blot instanceof Parchment.Embed) {
        blot.domNode.classList.add('ql-embed-selected');
        const range = new Range(blot.offset(scroll), blot.length());
        this.setRange(range, Emitter.sources.USER);
        //e.stopPropagation();
      }
    });
    let mouseCount = 0;
    this.emitter.listenDOM('mousedown', document.body, () => {
      mouseCount += 1;
    });
    this.emitter.listenDOM('mouseup', document.body, () => {
      mouseCount -= 1;
      if (mouseCount === 0) {
        this.update(Emitter.sources.USER);
      }
    });

    this.handleComposition();
    this.handleDragging();

    this.emitter.listenDOM('selectionchange', document, () => {
      if (!this.mouseDown) {
        setTimeout(this.update.bind(this, Emitter.sources.USER), 1);
      }
    });
    this.emitter.on(Emitter.events.EDITOR_CHANGE, (type, delta) => {
      if (type === Emitter.events.TEXT_CHANGE && delta.length() > 0) {
        this.update(Emitter.sources.SILENT);
      }
    });
    this.emitter.on(Emitter.events.SCROLL_BEFORE_UPDATE, () => {
      if (!this.hasFocus()) return;
      let native = this.getNativeRange();
      if (native == null) return;
      if (native.start.node === this.cursor.textNode) return;  // cursor.restore() will handle
      // TODO unclear if this has negative side effects
      this.emitter.once(Emitter.events.SCROLL_UPDATE, () => {
        try {
          this.setNativeRange(native.start.node, native.start.offset, native.end.node, native.end.offset);
        } catch (ignored) {}
      });
    });
    this.emitter.on(Emitter.events.SCROLL_OPTIMIZE, (mutations, context) => {
      if (context.range) {
        const { startNode, startOffset, endNode, endOffset } = context.range;
        this.setNativeRange(startNode, startOffset, endNode, endOffset);
      }
    });
    this.update(Emitter.sources.SILENT);
  }

  handleComposition() {
    this.root.addEventListener('compositionstart', () => {
      this.composing = true;
    });
    this.root.addEventListener('compositionend', () => {
      this.composing = false;
      if (this.cursor.parent) {
        const range = this.cursor.restore();
        if (!range) return;
        setTimeout(() => {
          this.setNativeRange(range.startNode, range.startOffset, range.endNode, range.endOffset);
        }, 1);
      }
    });
  }

  handleDragging() {
    this.emitter.listenDOM('mousedown', document.body, () => {
      this.mouseDown = true;
    });
    this.emitter.listenDOM('mouseup', document.body, () => {
      this.mouseDown = false;
      this.update(Emitter.sources.USER);
    });
  }

  focus() {
    if (this.hasFocus()) return;
    this.root.focus();
    this.setRange(this.savedRange);
  }

  format(format, value) {
    if (this.scroll.whitelist != null && !this.scroll.whitelist[format]) return;
    this.scroll.update();
    let nativeRange = this.getNativeRange();
    if (nativeRange == null || !nativeRange.native.collapsed || Parchment.query(format, Parchment.Scope.BLOCK)) return;
    if (nativeRange.start.node !== this.cursor.textNode) {
      let blot = Parchment.find(nativeRange.start.node, false);
      if (blot == null) return;
      // TODO Give blot ability to not split
      if (blot instanceof Parchment.Leaf) {
        let after = blot.split(nativeRange.start.offset);
        blot.parent.insertBefore(this.cursor, after);
      } else {
        blot.insertBefore(this.cursor, nativeRange.start.node);  // Should never happen
      }
      this.cursor.attach();
    }
    this.cursor.format(format, value);
    this.scroll.optimize();
    this.setNativeRange(this.cursor.textNode, this.cursor.textNode.data.length);
    this.update();
  }

  getBounds(index, length = 0) {
    let scrollLength = this.scroll.length();
    index = Math.min(index, scrollLength - 1);
    length = Math.min(index + length, scrollLength - 1) - index;
    let node, [leaf, offset] = this.scroll.leaf(index);
    if (leaf == null) return null;
    [node, offset] = leaf.position(offset, true);
    let range = document.createRange();
    if (length > 0) {
      range.setStart(node, offset);
      [leaf, offset] = this.scroll.leaf(index + length);
      if (leaf == null) return null;
      [node, offset] = leaf.position(offset, true);
      range.setEnd(node, offset);
      return range.getBoundingClientRect();
    } else {
      let side = 'left';
      let rect;
      if (node instanceof Text) {
        if (offset < node.data.length) {
          range.setStart(node, offset);
          range.setEnd(node, offset + 1);
        } else {
          range.setStart(node, offset - 1);
          range.setEnd(node, offset);
          side = 'right';
        }
        rect = range.getBoundingClientRect();
      } else {
        rect = leaf.domNode.getBoundingClientRect();
        if (offset > 0) side = 'right';
      }
      return {
        bottom: rect.top + rect.height,
        height: rect.height,
        left: rect[side],
        right: rect[side],
        top: rect.top,
        width: 0
      };
    }
  }

  getNativeRange() {
    let selection = document.getSelection();
    if (selection == null || selection.rangeCount <= 0) return null;
    let nativeRange = selection.getRangeAt(0);
    if (nativeRange == null) return null;
    let range = this.normalizeNative(nativeRange);
    debug.info('getNativeRange', range);
    return range;
  }

  getRange() {
    let normalized = this.getNativeRange();
    if (normalized == null) return [null, null];
    let range = this.normalizedToRange(normalized);
    return [range, normalized];
  }

  hasFocus() {
    return document.activeElement === this.root;
  }

  normalizedToRange(range) {
    let positions = [[range.start.node, range.start.offset]];
    if (!range.native.collapsed) {
      positions.push([range.end.node, range.end.offset]);
    }
    let indexes = positions.map((position) => {
      let [node, offset] = position;
      let blot = Parchment.find(node, true);
      let index = blot.offset(this.scroll);
      if (offset === 0) {
        return index;
      } else if (blot instanceof Parchment.Container) {
        return index + blot.length();
      } else {
        return index + blot.index(node, offset);
      }
    });
    let end = Math.min(Math.max(...indexes), this.scroll.length() - 1);
    let start = Math.min(end, ...indexes);
    return new Range(start, end-start);
  }

  normalizeNative(nativeRange) {
    if (!contains(this.root, nativeRange.startContainer) ||
        (!nativeRange.collapsed && !contains(this.root, nativeRange.endContainer))) {
      return null;
    }
    let range = {
      start: { node: nativeRange.startContainer, offset: nativeRange.startOffset },
      end: { node: nativeRange.endContainer, offset: nativeRange.endOffset },
      native: nativeRange
    };
    [range.start, range.end].forEach(function(position) {
      let node = position.node, offset = position.offset;
      while (!(node instanceof Text) && node.childNodes.length > 0) {
        if (node.childNodes.length > offset) {
          node = node.childNodes[offset];
          offset = 0;
        } else if (node.childNodes.length === offset) {
          node = node.lastChild;
          offset = node instanceof Text ? node.data.length : node.childNodes.length + 1;
        } else {
          break;
        }
      }
      position.node = node, position.offset = offset;
    });
    return range;
  }

  rangeToNative(range) {
    let indexes = range.collapsed ? [range.index] : [range.index, range.index + range.length];
    let args = [];
    let scrollLength = this.scroll.length();
    indexes.forEach((index, i) => {
      index = Math.min(scrollLength - 1, index);
      let node, [leaf, offset] = this.scroll.leaf(index);
      [node, offset] = leaf.position(offset, i !== 0);
      args.push(node, offset);
    });
    if (args.length < 2) {
      args = args.concat(args);
    }
    return args;
  }

  scrollIntoView(scrollingContainer) {
    let range = this.lastRange;
    if (range == null) return;
    let bounds = this.getBounds(range.index, range.length);
    if (bounds == null) return;
    let limit = this.scroll.length()-1;
    let [first, ] = this.scroll.line(Math.min(range.index, limit));
    let last = first;
    if (range.length > 0) {
      [last, ] = this.scroll.line(Math.min(range.index + range.length, limit));
    }
    if (first == null || last == null) return;
    let scroller = this.scroll.scrollingContainer;
    // let scrollBounds = scroller.getBoundingClientRect();
    let headerHeight = 65;
    let windowHeight = window.innerHeight - 20;
    if (!!bounds.top && !!bounds.bottom && !!scroller) {
      if (bounds.top < headerHeight) {
        scroller.scrollTop -= (headerHeight - bounds.top);
      } else if (bounds.bottom > windowHeight) {
        scroller.scrollTop += (bounds.bottom - windowHeight);
      }
    }
  }

  setNativeRange(startNode, startOffset, endNode = startNode, endOffset = startOffset, force = false) {
    debug.info('setNativeRange', startNode, startOffset, endNode, endOffset);
    if (startNode != null && (this.root.parentNode == null || startNode.parentNode == null || endNode.parentNode == null)) {
      return;
    }
    let selection = document.getSelection();
    if (selection == null) return;
    if (startNode != null) {
      if (!this.hasFocus()) this.root.focus();
      let native = (this.getNativeRange() || {}).native;
      if (native == null || force ||
          startNode !== native.startContainer ||
          startOffset !== native.startOffset ||
          endNode !== native.endContainer ||
          endOffset !== native.endOffset) {

        if (startNode.tagName == "BR") {
          startOffset = [].indexOf.call(startNode.parentNode.childNodes, startNode);
          startNode = startNode.parentNode;
        }
        if (endNode.tagName == "BR") {
          endOffset = [].indexOf.call(endNode.parentNode.childNodes, endNode);
          endNode = endNode.parentNode;
        }
        let range = document.createRange();
        range.setStart(startNode, startOffset);
        range.setEnd(endNode, endOffset);
        selection.removeAllRanges();
        selection.addRange(range);
      }
    } else {
      selection.removeAllRanges();
      this.root.blur();
      document.body.focus();  // root.blur() not enough on IE11+Travis+SauceLabs (but not local VMs)
    }
  }

  setRange(range, force = false, source = Emitter.sources.API) {
    if (typeof force === 'string') {
      source = force;
      force = false;
    }
    debug.info('setRange', range);
    if (range != null) {
      let args = this.rangeToNative(range);
      this.setNativeRange(...args, force);
    } else {
      this.setNativeRange(null);
    }
    this.update(source);
  }

  update(source = Emitter.sources.USER) {
    let oldRange = this.lastRange;
    let [lastRange, nativeRange] = this.getRange();
    this.lastRange = lastRange;
    if (this.lastRange != null) {
      this.savedRange = this.lastRange;
    }
    if (!equal(oldRange, this.lastRange)) {
      if (!this.composing && nativeRange != null && nativeRange.native.collapsed && nativeRange.start.node !== this.cursor.textNode) {
        this.cursor.restore();
      }
      let args = [Emitter.events.SELECTION_CHANGE, clone(this.lastRange), clone(oldRange), source];
      this.emitter.emit(Emitter.events.EDITOR_CHANGE, ...args);
      if (source !== Emitter.sources.SILENT) {
        this.emitter.emit(...args);
      }
    }
  }
}

function contains(parent, descendant) {
  try {
    // Firefox inserts inaccessible nodes around video elements
    descendant.parentNode;
  } catch (e) {
    return false;
  }
  // IE11 has bug with Text nodes
  // https://connect.microsoft.com/IE/feedback/details/780874/node-contains-is-incorrect
  if (descendant instanceof Text) {
    descendant = descendant.parentNode;
  }
  return parent.contains(descendant);
}

export { Range, Selection as default };
<|endoftext|>


<commit_before>var net = require('net');
var fork = require(__dirname + '/../build/default/fork.node');

var sockpath = 'socket';
// create a server
var server = net.createServer(function (c) {
  c.write('hello\r\n', 'utf8');
  c.pipe(c);
  console.log("exit parent");
  server.close();
  process.exit(0);
});

var pid = fork.fork();

if (pid > 0) {
  console.log("parent:" + fork.getpid());
  server.listen(sockpath);
}
else {
  delete server;
  console.log("child:"  + fork.getpid());
  setTimeout(function() {
    // create a client to connect to parent server
    var client = new net.Socket({type:'unix'});
    client.connect(sockpath, function() { console.log("connected"); });
    client.on("data", function(d) { console.log(d.toString('utf8')); });
  }, 100);
}
<commit_msg>holy crap IPC works in node.js<commit_after>var fork = require(__dirname + '/../build/default/fork.node');
var net = require("net");
var netBinding = process.binding('net');

var pipeFDs = netBinding.pipe();
var pid = fork.fork();

if (pid == 0) {
  netBinding.close(pipeFDs[1]); // close the write fd
  console.log("child:"  + fork.getpid());
  var pipeReadStream = new net.Stream();
  pipeReadStream.addListener('data', function(data) {
    console.log(data.toString('utf8'));
  });
  pipeReadStream.addListener('data', function(data) {
    console.log("parent closed the write pipe\r\n");
  });
  pipeReadStream.open(pipeFDs[0]);
  pipeReadStream.resume();
}
else {
  netBinding.close(pipeFDs[0]); // close the read fd
  console.log("parent:" + fork.getpid());
  var pipeWriteStream = new net.Stream();
  pipeWriteStream.open(pipeFDs[1]);
  pipeWriteStream.write("\nhello unix\r\n");
  netBinding.close(pipeFDs[1]); // close the read fd
}
<|endoftext|>


<commit_before>// code modified from flot AJAX example
// http://www.flotcharts.org/flot/examples/ajax/index.html

	$(function() {

		// flot plot options!
		var options = {
			lines: {
				show: true
			},
			points: {
				show: false
			},
			legend: {
				show: true
			},
			grid: {
        		hoverable: true
      		}
	};

		// GLOBAL VARIABLES AND FUNCTIONS

		console.log('Initializing variables.');
		// initialize the arrays hold the data for plotting
		var data = [];
		var dataTarget = [];

		// IP address to access our UI
		// (empty for relative URLs)
		var publicIP = '';

		// building blocks of metadata table
		var tableTop = "
";
		var tableBottom = "
";
		var tableHeader = "
ID	Mean	StDev	Level	Blarg
";
		var metadataTable = tableTop + tableHeader;

		// helps with managing the uploaded time series
		var files;

		// initialize the timeseries plot (will be empty)
		console.log('Initializing flot plot (empty plot).');
		$.plot("#placeholder", data, options);

		// ACTIONS TO COMPLETE WHEN THE `SUBMIT` BUTTON IS CLICKED
		$("button#tsQuery").click(function () {

			console.log('Submit button has been clicked.');

			// show the progress bar so the user knows that stuff
			// is going on behind the scenes

			console.log('Adding in ticking progress bar.');
			$( "#progressbar" ).progressbar({
  				value: false
			});

			// reset everything in preparation for new data
			console.log('Resetting helper variables in preparation for new data.');
			document.getElementById('timeseriesMetadata').innerHTML = '';
			data = [];
			var simIDs = [];
			var idNum = {};
			var counter = 0;
			metadataTable = tableTop + tableHeader;

			$.plot("#placeholder", data, options);

			// retrieve the time series specified by the user, and the number of
			//   most similar time series
			var timeSeriesID = document.getElementById("tsID").value;
			var numSim = document.getElementById("n_closest").value;
			console.log('Retrieved timeseries ID #' + timeSeriesID + 'and will retrieve the ' + numSim + 'most similar timeseries.');

			// CONSTRUCT OUR QUERY
			// if the user has specified an ID, use that;
			//   otherwise assume there's an uploaded file.
			if (timeSeriesID != '') {

				// DECIDE WHETHER WE NEED A SIMQUERY
				// if the user hasn't provided a number of similar TS, or the
				//   number is zero, we won't bother sending off a simquery
				if (numSim == '' | numSim == 0) {

					// add on the ID number of the target TS
					simIDs.push(timeSeriesID);

					// now we loop over all the IDs and collect their data
					console.log("Collecting data of specified time series.");

					var dataurl = publicIP + "/timeseries/" + timeSeriesID;

					console.log('Retrieving data associated with TS ID#'+ timeSeriesID + '.');

					$.ajax({
						url: dataurl,
						type: "GET",
						dataType: "json",
						success: onDataReceived
					});

				} else {

					var simurl = publicIP + "/simquery?id=" + timeSeriesID + "&topn=" + numSim;
					console.log('Constructed simquery:', simurl);

					// get the IDs of the similar time series
					console.log('Retrieving the ID numbers of the similar TS (ID number supplied).');
					$.ajax({
						url: simurl,
						type: "GET",
						dataType: "json",
						success: function(data) {

									// parse the ID numbers returned from the server
									getSimIDs(data);

									// add on the ID number of the target TS
									simIDs.push(timeSeriesID);

									// now we loop over all the IDs and collect their data
									console.log("Looping over the retrieved ID numbers and collecting their data.");

									for(var i=0; i < simIDs.length; i++) {

										idNum   = simIDs[i];

										var dataurl = publicIP + "/timeseries/" + idNum;

										console.log('Retrieving data associated with TS ID#'+ idNum + '.');
										// solution from http://stackoverflow.com/questions/4201934/
										//               jquery-ajax-pass-additional-argument-to-success-callback
										$.ajax({
											url: dataurl,
											type: "GET",
											dataType: "json",
											success: onDataReceived
										});

									}
						 }
					});
				}

			} else if ( document.getElementById("fileSelect").files.length > 0  ) {

				// DECIDE WHETHER WE NEED A SIMQUERY
				// if the user hasn't provided a number of similar TS, or the
				//   number is zero, we won't bother sending off a simquery
				if (numSim == '' | numSim == 0) {

					console.log("Locally received data uploaded by user.");
					console.log( document.getElementById("fileSelect").files[0] );

					// parse the uploaded file
					// https://www.html5rocks.com/en/tutorials/file/dndfiles/
					read = new FileReader();
					read.readAsText(document.getElementById("fileSelect").files[0]);

					read.onloadend = function(){
						//console.log(read.result);
						//console.log(JSON.parse(read.result))
						//console.log(JSON.parse(read.result).ts)
						var dataTemp = JSON.parse(read.result).ts;
						dataTarget = dataTemp[0].map(function (e, i) {
												return [e, dataTemp[1][i]];});

						tsData = {label: "uploaded timeseries", data: dataTarget, lines: {lineWidth:6}};

						console.log('Appending uploaded time series to Flot data.');

						data.push(tsData);

						console.log(tsData);

						console.log('Plotting the data of the uploaded TS.');

						$.plot("#placeholder", data, options);

						console.log("Destroy the progress bar -- we don't need it anymore.");
					$("#progressbar").progressbar( "destroy" );

					}

				} else {

					console.log("Locally received data uploaded by user.");
					console.log( document.getElementById("fileSelect").files[0] );

					var simurl = publicIP + "/simquery?id=" + "&topn=" + numSim;

					console.log("Sending user-loaded data off to be processed.");
					$.ajax({
						url: simurl,
						type: 'POST',
						data: document.getElementById("fileSelect").files[0],
						cache: false,
						contentType: 'application/json; charset=utf-8',
						dataType: 'json',
						processData: false, // Don't process the files
						contentType: false, // Set content type to false as jQuery will tell the server its a query string request
						error: function(jqXHR, textStatus, errorThrown) {
					 			// Handle errors here
									console.log('ERRORS: ' + textStatus);
						}
					})
						.done(function (result) {

							simIDs = result.id;

							$.ajax({
								url: simurl,
								type: "GET",
								dataType: "json",
								success: function(data) {

										// loop over all the IDs and collect their data
										console.log("Looping over the retrieved ID numbers and collecting their data.");

										for(var i=0; i < simIDs.length; i++) {

											idNum   = simIDs[i];

											var dataurl = publicIP + "/timeseries/" + idNum;

											console.log('Retrieving data associated with TS ID#',idNum ,'.');
											// solution from http://stackoverflow.com/questions/4201934/
											//               jquery-ajax-pass-additional-argument-to-success-callback
											$.ajax({
												url: dataurl,
												type: "GET",
												dataType: "json",
												success: onDataReceived
											});

										}
							 }
						});

					// parse the uploaded file
					// https://www.html5rocks.com/en/tutorials/file/dndfiles/
					read = new FileReader();
					read.readAsText(document.getElementById("fileSelect").files[0]);

					read.onloadend = function(){
						//console.log(read.result);
						//console.log(JSON.parse(read.result))
						//console.log(JSON.parse(read.result).ts)
						var dataTemp = JSON.parse(read.result).ts;
						dataTarget = dataTemp[0].map(function (e, i) {
												return [e, dataTemp[1][i]];});

						tsData = {label: "uploaded timeseries", data: dataTarget, lines: {lineWidth:6}, colors: ['red']};

						console.log('Appending uploaded time series to Flot data.');

						data.push(tsData);

						console.log(tsData);

						console.log('Plotting the data of the uploaded TS.');

						$.plot("#placeholder", data, options);

					}
			});
				}

			} else {
				// user hasn't specified anything!
				alert("You gotta give us something valid to work with...");
			}

			function onDataReceived(series) {

				// pull the similar TS
				//

				// * solution from Stack Overflow:
				//   http://stackoverflow.com/questions/22015684/
				//             how-do-i-zip-two-arrays-in-javascript
				console.log('Zipping TS ID#' + simIDs[counter] + ' into appropriate form for Flot to plot.');
				var dataTarget = series.ts[0].map(function (e, i) {
					return [e, series.ts[1][i]];
				});

				tsData = {label: "timeseries " + simIDs[counter], data: dataTarget};

				console.log('Appending TS ID#' + simIDs[counter] +' to Flot data.');
				data.push(tsData);

				$.plot("#placeholder", data, options);

				// if we've reached the target TS ID, we're done putting together the
				//   metadata table.
				// highlight the row of the targt TS ID and show the table to the world
				if( series.metadata[0].id == timeSeriesID ) {

					var tableRow = "
" + series.metadata[0].id + "	";
					tableRow    += "" +series.metadata[0].mean  + "	";
					tableRow    += "" +series.metadata[0].std   + "	";
					tableRow    += "" +series.metadata[0].level + "	";
					tableRow    += "" +series.metadata[0].blarg + "
";

					metadataTable += tableRow;

					console.log("Put together + display the metadata table.");
					metadataTable += tableBottom;
					document.getElementById('timeseriesMetadata').innerHTML = metadataTable;
					console.log("Destroy the progress bar -- we don't need it anymore.");
					$("#progressbar").progressbar( "destroy" );
				} else {

					// put together the metadata
					var tableRow = "
" + series.metadata[0].id + "	";
					tableRow    += "" +series.metadata[0].mean  + "	";
					tableRow    += "" +series.metadata[0].std   + "	";
					tableRow    += "" +series.metadata[0].level + "	";
					tableRow    += "" +series.metadata[0].blarg + "
";

					metadataTable += tableRow;

				}

				// keeps track of where we are in the array of TS IDs to plot
				counter++;

				if (counter == simIDs.length - 1) {
					console.log("Destroy the progress bar -- we don't need it anymore.");
					$("#progressbar").progressbar( "destroy" );
				}

			}

			function getSimIDs(series) {
				for(var i=0; i < series.id.length; i++) {
					simIDs.push(series.id[i]);
				}
			}

		});

		// Add the Flot version string to the footer
		$("#footer").prepend("Flot " + $.plot.version + " + ");
	});<commit_msg>Fixing metadata table<commit_after>// code modified from flot AJAX example
// http://www.flotcharts.org/flot/examples/ajax/index.html

	$(function() {

		// flot plot options!
		var options = {
			lines: {
				show: true
			},
			points: {
				show: false
			},
			legend: {
				show: true
			},
			grid: {
        		hoverable: true
      		}
	};

		// GLOBAL VARIABLES AND FUNCTIONS

		console.log('Initializing variables.');
		// initialize the arrays hold the data for plotting
		var data = [];
		var dataTarget = [];

		// IP address to access our UI
		// (empty for relative URLs)
		var publicIP = '';

		// building blocks of metadata table
		var tableTop = "
";
		var tableBottom = "
";
		var tableHeader = "
ID	Mean	StDev	Level	Blarg
";
		var metadataTable = tableTop + tableHeader;

		// helps with managing the uploaded time series
		var files;

		// initialize the timeseries plot (will be empty)
		console.log('Initializing flot plot (empty plot).');
		$.plot("#placeholder", data, options);

		// ACTIONS TO COMPLETE WHEN THE `SUBMIT` BUTTON IS CLICKED
		$("button#tsQuery").click(function () {

			console.log('Submit button has been clicked.');

			// show the progress bar so the user knows that stuff
			// is going on behind the scenes

			console.log('Adding in ticking progress bar.');
			$( "#progressbar" ).progressbar({
  				value: false
			});

			// reset everything in preparation for new data
			console.log('Resetting helper variables in preparation for new data.');
			document.getElementById('timeseriesMetadata').innerHTML = '';
			data = [];
			var simIDs = [];
			var idNum = {};
			var counter = 0;
			metadataTable = tableTop + tableHeader;

			$.plot("#placeholder", data, options);

			// retrieve the time series specified by the user, and the number of
			//   most similar time series
			var timeSeriesID = document.getElementById("tsID").value;
			var numSim = document.getElementById("n_closest").value;
			console.log('Retrieved timeseries ID #' + timeSeriesID + 'and will retrieve the ' + numSim + 'most similar timeseries.');

			// CONSTRUCT OUR QUERY
			// if the user has specified an ID, use that;
			//   otherwise assume there's an uploaded file.
			if (timeSeriesID != '') {

				// DECIDE WHETHER WE NEED A SIMQUERY
				// if the user hasn't provided a number of similar TS, or the
				//   number is zero, we won't bother sending off a simquery
				if (numSim == '' | numSim == 0) {

					// add on the ID number of the target TS
					simIDs.push(timeSeriesID);

					// now we loop over all the IDs and collect their data
					console.log("Collecting data of specified time series.");

					var dataurl = publicIP + "/timeseries/" + timeSeriesID;

					console.log('Retrieving data associated with TS ID#'+ timeSeriesID + '.');

					$.ajax({
						url: dataurl,
						type: "GET",
						dataType: "json",
						success: onDataReceived
					});

				} else {

					var simurl = publicIP + "/simquery?id=" + timeSeriesID + "&topn=" + numSim;
					console.log('Constructed simquery:', simurl);

					// get the IDs of the similar time series
					console.log('Retrieving the ID numbers of the similar TS (ID number supplied).');
					$.ajax({
						url: simurl,
						type: "GET",
						dataType: "json",
						success: function(data) {

									// parse the ID numbers returned from the server
									getSimIDs(data);

									// add on the ID number of the target TS
									simIDs.push(timeSeriesID);

									// now we loop over all the IDs and collect their data
									console.log("Looping over the retrieved ID numbers and collecting their data.");

									for(var i=0; i < simIDs.length; i++) {

										idNum   = simIDs[i];

										var dataurl = publicIP + "/timeseries/" + idNum;

										console.log('Retrieving data associated with TS ID#'+ idNum + '.');
										// solution from http://stackoverflow.com/questions/4201934/
										//               jquery-ajax-pass-additional-argument-to-success-callback
										$.ajax({
											url: dataurl,
											type: "GET",
											dataType: "json",
											success: onDataReceived
										});

									}
						 }
					});
				}

			} else if ( document.getElementById("fileSelect").files.length > 0  ) {

				// DECIDE WHETHER WE NEED A SIMQUERY
				// if the user hasn't provided a number of similar TS, or the
				//   number is zero, we won't bother sending off a simquery
				if (numSim == '' | numSim == 0) {

					console.log("Locally received data uploaded by user.");
					console.log( document.getElementById("fileSelect").files[0] );

					// parse the uploaded file
					// https://www.html5rocks.com/en/tutorials/file/dndfiles/
					read = new FileReader();
					read.readAsText(document.getElementById("fileSelect").files[0]);

					read.onloadend = function(){
						//console.log(read.result);
						//console.log(JSON.parse(read.result))
						//console.log(JSON.parse(read.result).ts)
						var dataTemp = JSON.parse(read.result).ts;
						dataTarget = dataTemp[0].map(function (e, i) {
												return [e, dataTemp[1][i]];});

						tsData = {label: "uploaded timeseries", data: dataTarget, lines: {lineWidth:6}};

						console.log('Appending uploaded time series to Flot data.');

						data.push(tsData);

						console.log(tsData);

						console.log('Plotting the data of the uploaded TS.');

						$.plot("#placeholder", data, options);

						console.log("Destroy the progress bar -- we don't need it anymore.");
						$("#progressbar").progressbar( "destroy" );

					}

				} else {

					console.log("Locally received data uploaded by user.");
					console.log( document.getElementById("fileSelect").files[0] );

					var simurl = publicIP + "/simquery?id=" + "&topn=" + numSim;

					console.log("Sending user-loaded data off to be processed.");
					$.ajax({
						url: simurl,
						type: 'POST',
						data: document.getElementById("fileSelect").files[0],
						cache: false,
						contentType: 'application/json; charset=utf-8',
						dataType: 'json',
						processData: false, // Don't process the files
						contentType: false, // Set content type to false as jQuery will tell the server its a query string request
						error: function(jqXHR, textStatus, errorThrown) {
					 			// Handle errors here
									console.log('ERRORS: ' + textStatus);
						}
					})
						.done(function (result) {

							simIDs = result.id;

							$.ajax({
								url: simurl,
								type: "GET",
								dataType: "json",
								success: function(data) {

										// loop over all the IDs and collect their data
										console.log("Looping over the retrieved ID numbers and collecting their data.");

										for(var i=0; i < simIDs.length; i++) {

											idNum   = simIDs[i];

											var dataurl = publicIP + "/timeseries/" + idNum;

											console.log('Retrieving data associated with TS ID#' + idNum + '.');
											// solution from http://stackoverflow.com/questions/4201934/
											//               jquery-ajax-pass-additional-argument-to-success-callback
											$.ajax({
												url: dataurl,
												type: "GET",
												dataType: "json",
												success: onDataReceived
											});

										}
							 }
						});

					// parse the uploaded file
					// https://www.html5rocks.com/en/tutorials/file/dndfiles/
					read = new FileReader();
					read.readAsText(document.getElementById("fileSelect").files[0]);

					read.onloadend = function(){
						//console.log(read.result);
						//console.log(JSON.parse(read.result))
						//console.log(JSON.parse(read.result).ts)
						var dataTemp = JSON.parse(read.result).ts;
						dataTarget = dataTemp[0].map(function (e, i) {
												return [e, dataTemp[1][i]];});

						tsData = {label: "uploaded timeseries", data: dataTarget, lines: {lineWidth:6}, colors: ['red']};

						console.log('Appending uploaded time series to Flot data.');

						data.push(tsData);

						console.log(tsData);

						console.log('Plotting the data of the uploaded TS.');

						$.plot("#placeholder", data, options);

					}
			});
				}

			} else {
				// user hasn't specified anything!
				alert("You gotta give us something valid to work with...");
			}

			function onDataReceived(series) {

				// pull the similar TS
				//

				// * solution from Stack Overflow:
				//   http://stackoverflow.com/questions/22015684/
				//             how-do-i-zip-two-arrays-in-javascript
				console.log('Zipping TS ID#' + simIDs[counter] + ' into appropriate form for Flot to plot.');
				var dataTarget = series.ts[0].map(function (e, i) {
					return [e, series.ts[1][i]];
				});

				tsData = {label: "timeseries " + simIDs[counter], data: dataTarget};

				console.log('Appending TS ID#' + simIDs[counter] +' to Flot data.');
				data.push(tsData);

				$.plot("#placeholder", data, options);

				// if (1) we've reached the target TS ID, in the case of a specified TS ID
				//    (2) we've reached the end of the similar IDs, in the case of
				//        an uploaded TS,
				// we're done putting together the metadata table.
				// highlight the row of the targt TS ID and show the table to the world
				if( series.metadata[0].id == timeSeriesID | counter == simIDs.length - 1 ) {

					var tableRow = "
" + series.metadata[0].id + "	";
					tableRow    += "" +series.metadata[0].mean  + "	";
					tableRow    += "" +series.metadata[0].std   + "	";
					tableRow    += "" +series.metadata[0].level + "	";
					tableRow    += "" +series.metadata[0].blarg + "
";

					metadataTable += tableRow;

					console.log("Put together + display the metadata table.");
					metadataTable += tableBottom;
					document.getElementById('timeseriesMetadata').innerHTML = metadataTable;
					console.log("Destroy the progress bar -- we don't need it anymore.");
					$("#progressbar").progressbar( "destroy" );
				} else {

					// put together the metadata
					var tableRow = "
" + series.metadata[0].id + "	";
					tableRow    += "" +series.metadata[0].mean  + "	";
					tableRow    += "" +series.metadata[0].std   + "	";
					tableRow    += "" +series.metadata[0].level + "	";
					tableRow    += "" +series.metadata[0].blarg + "
";

					metadataTable += tableRow;

				}

				// keeps track of where we are in the array of TS IDs to plot
				counter++;

				//if (counter == simIDs.length - 1) {
				//	console.log("Destroy the progress bar -- we don't need it anymore.");
				//	$("#progressbar").progressbar( "destroy" );
				//}

			}

			function getSimIDs(series) {
				for(var i=0; i < series.id.length; i++) {
					simIDs.push(series.id[i]);
				}
			}

		});

		// Add the Flot version string to the footer
		$("#footer").prepend("Flot " + $.plot.version + " + ");
	});<|endoftext|>


<commit_before>import { expect } from 'chai';
import {
  beforeEach,
  describe,
  it,
} from '@bigtest/mocha';

import TransferInteractor from '../interactors/user-transfer';
import setupApplication from '../helpers/setup-application';

describe('Transfer fines', () => {
  setupApplication({
    scenarios: ['transfers'],
    currentUser: {
      curServicePoint: { id: 1 },
    },
  });

  describe('visit users-details: accounts', () => {
    beforeEach(async function () {
      this.visit('users/1ad737b0-d847-11e6-bf26-cec0c932ce02/accounts/all');

      await TransferInteractor.whenLoaded().timeout(5000);
      await TransferInteractor.whenVisibled();
    });

    it('renders proper amount of rows', () => {
      expect(TransferInteractor.mclAll.rowCount).to.equal(5);
    });

    describe('check the rows of open accounts', () => {
      beforeEach(async () => {
        await TransferInteractor.openAccounts();
      });

      it('renders proper amount of rows', () => {
        expect(TransferInteractor.mclOpen.rowCount).to.equal(4);
      });

      it('renders appropriate headers', () => {
        expect(TransferInteractor.mclOpen.headers().length).to.be.greaterThan(0);
      });

      describe('active the transfer button', () => {
        beforeEach(async () => {
          await TransferInteractor.selectCheckbox();
          await TransferInteractor.transferButton();
          await TransferInteractor.amount.fillInput('200.00');
          await TransferInteractor.transferAccount.selectOption('USA Bank1');
          await TransferInteractor.comment.fillTextArea('Comment UNAM');
        });

        it('displays a value in the amount field', () => {
          expect(TransferInteractor.amount.val).to.equal('200.00');
        });

        it('updates the value', () => {
          expect(TransferInteractor.comment.val).to.equal('Comment UNAM');
        });

        it('updates the select value', () => {
          expect(TransferInteractor.transferAccount.val).to.equal('USA Bank1');
        });

        describe('cancel the transfer', () => {
          beforeEach(async () => {
            await TransferInteractor.cancel.click();
          });

          it('renders proper amount of rows in the openaccounts section', () => {
            expect(TransferInteractor.mclOpen.rowCount).to.equal(4);
          });
        });
      });

      describe('add a transfer', () => {
        beforeEach(async () => {
          await TransferInteractor.selectCheckbox();
          await TransferInteractor.transferButton();
          await TransferInteractor.amount.fillInput('200.00');
          await TransferInteractor.transferAccount.selectOption('USA Bank1');
          await TransferInteractor.comment.fillTextArea('Comment UNAM');
        });

        it('displays a value in the amount field', () => {
          expect(TransferInteractor.amount.val).to.equal('200.00');
        });

        it('updates the value', () => {
          expect(TransferInteractor.comment.val).to.equal('Comment UNAM');
        });

        it('updates the select value', () => {
          expect(TransferInteractor.transferAccount.val).to.equal('USA Bank1');
        });

        describe.skip('submit and confirm the transfer', () => {
          beforeEach(async () => {
            await TransferInteractor.submit.click();
            await TransferInteractor.confirmationModal.confirmButton.click();
          });

          it('renders proper amount of rows', () => {
            expect(TransferInteractor.mclOpen.rowCount).to.equal(4);
          });
        });
      });

      describe('amount is less than zero', () => {
        beforeEach(async () => {
          await TransferInteractor.selectCheckbox();
          await TransferInteractor.transferButton();
          await TransferInteractor.amount.fillInput('-200.00');
          await TransferInteractor.transferAccount.selectOption('USA Bank1');
          await TransferInteractor.comment.fillTextArea('Comment UNAM');
        });

        it('show the amount field', () => {
          expect(TransferInteractor.amount.val).to.equal('-200.00');
        });
      });

      describe('transfer amount is greater than total amount', () => {
        beforeEach(async () => {
          await TransferInteractor.selectCheckbox();
          await TransferInteractor.transferButton();
          await TransferInteractor.amount.fillInput('700.00');
          await TransferInteractor.transferAccount.selectOption('USA Bank1');
          await TransferInteractor.notify.click();
        });

        it('show the amount field', () => {
          expect(TransferInteractor.amount.val).to.equal('700.00');
        });
      });

      describe('transfer amount is null', () => {
        beforeEach(async () => {
          await TransferInteractor.selectCheckbox();
          await TransferInteractor.transferButton();
          await TransferInteractor.amount.fillInput('');
          await TransferInteractor.transferAccount.selectOption('USA Bank1');
          await TransferInteractor.notify.click();
        });

        it('show the amount field', () => {
          expect(TransferInteractor.amount.val).to.equal('');
        });
      });

      // transfer many
      describe('go to all accounts', () => {
        beforeEach(async () => {
          await TransferInteractor.allAccounts();
        });

        describe('click on transfer button and close warning modal', () => {
          beforeEach(async () => {
            await TransferInteractor.selectCheckbox();
            await TransferInteractor.transferButton();
            await TransferInteractor.warningTransferCancel();
          });

          it('renders proper amount of rows', () => {
            expect(TransferInteractor.mclAll.rowCount).to.equal(5);
          });

          it('renders appropriate headers', () => {
            expect(TransferInteractor.mclAll.headers().length).to.be.greaterThan(0);
          });
        });

        describe.skip('make the transfer', () => {
          beforeEach(async () => {
            await TransferInteractor.selectCheckbox();
            await TransferInteractor.transferButton();
            await TransferInteractor.rows(0).cells(0).selectOneWarning();
            await TransferInteractor.warningTransferContinue();
            await TransferInteractor.amount.fillInput('400.00');
            await TransferInteractor.transferAccount.selectOption('USA Bank1');
            await TransferInteractor.comment.fillTextArea('Comment UNAM');
            await TransferInteractor.submit.click();
            await TransferInteractor.confirmationModal.confirmButton.click();
          });

          it('renders proper amount of rows', () => {
            expect(TransferInteractor.mclAll.rowCount).to.equal(5);
          });

          it('validate the correct amount on each row after the transfer', () => {
            const dataKeys = ['0.00', '10.00', '20.00', '30.00', '0.00'];

            for (let i = 0; i < 5; i++) {
              expect(TransferInteractor.mclAll.rows(i).cells(5).content).to.equal(dataKeys[i]);
            }
          });
        });
      });
      // END transfer many

      // on sort
      describe('go to all accounts', () => {
        beforeEach(async () => {
          await TransferInteractor.allAccounts();
        });

        describe('testing all headers columns', () => {
          beforeEach(async () => {
            await TransferInteractor.selectCheckbox();
            await TransferInteractor.transferButton();
            await TransferInteractor.mclWarning.headers(1).click();
            await TransferInteractor.mclWarning.headers(2).click();
            await TransferInteractor.mclWarning.headers(3).click();
            await TransferInteractor.mclWarning.headers(4).click();
            await TransferInteractor.mclWarning.headers(5).click();
          });

          it('renders appropriate headers', () => {
            expect(TransferInteractor.mclWarning.headers().length).to.be.greaterThan(0);
          });
        });
      });

      describe('Test all select transfers', () => {
        beforeEach(async () => {
          await TransferInteractor.allAccounts();
        });

        describe('select and deselect all transfers', () => {
          beforeEach(async () => {
            await TransferInteractor.selectCheckbox();
            await TransferInteractor.transferButton();
            await TransferInteractor.selectCheckboxWarning();
            await TransferInteractor.selectCheckboxWarning();
          });

          it('renders appropriate headers', () => {
            expect(TransferInteractor.mclWarning.headers().length).to.be.greaterThan(0);
          });

          describe('click on cancel button in warning modal', () => {
            beforeEach(async () => {
              await TransferInteractor.warningTransferCancel();
            });

            it('renders proper amount of rows', () => {
              expect(TransferInteractor.mclAll.rowCount).to.equal(5);
            });

            it('renders appropriate headers', () => {
              expect(TransferInteractor.mclAll.headers().length).to.be.greaterThan(0);
            });
          });
        });
      });
      // END on sort
    });
  });
});
<commit_msg>UIU-1795: Remove skip<commit_after>import { expect } from 'chai';
import {
  beforeEach,
  describe,
  it,
} from '@bigtest/mocha';

import TransferInteractor from '../interactors/user-transfer';
import setupApplication from '../helpers/setup-application';

describe('Transfer fines', () => {
  setupApplication({
    scenarios: ['transfers'],
    currentUser: {
      curServicePoint: { id: 1 },
    },
  });

  describe('visit users-details: accounts', () => {
    beforeEach(async function () {
      this.visit('users/1ad737b0-d847-11e6-bf26-cec0c932ce02/accounts/all');

      await TransferInteractor.whenLoaded().timeout(5000);
      await TransferInteractor.whenVisibled();
    });

    it('renders proper amount of rows', () => {
      expect(TransferInteractor.mclAll.rowCount).to.equal(5);
    });

    describe('check the rows of open accounts', () => {
      beforeEach(async () => {
        await TransferInteractor.openAccounts();
      });

      it('renders proper amount of rows', () => {
        expect(TransferInteractor.mclOpen.rowCount).to.equal(4);
      });

      it('renders appropriate headers', () => {
        expect(TransferInteractor.mclOpen.headers().length).to.be.greaterThan(0);
      });

      describe('active the transfer button', () => {
        beforeEach(async () => {
          await TransferInteractor.selectCheckbox();
          await TransferInteractor.transferButton();
          await TransferInteractor.amount.fillInput('200.00');
          await TransferInteractor.transferAccount.selectOption('USA Bank1');
          await TransferInteractor.comment.fillTextArea('Comment UNAM');
        });

        it('displays a value in the amount field', () => {
          expect(TransferInteractor.amount.val).to.equal('200.00');
        });

        it('updates the value', () => {
          expect(TransferInteractor.comment.val).to.equal('Comment UNAM');
        });

        it('updates the select value', () => {
          expect(TransferInteractor.transferAccount.val).to.equal('USA Bank1');
        });

        describe('cancel the transfer', () => {
          beforeEach(async () => {
            await TransferInteractor.cancel.click();
          });

          it('renders proper amount of rows in the openaccounts section', () => {
            expect(TransferInteractor.mclOpen.rowCount).to.equal(4);
          });
        });
      });

      describe('add a transfer', () => {
        beforeEach(async () => {
          await TransferInteractor.selectCheckbox();
          await TransferInteractor.transferButton();
          await TransferInteractor.amount.fillInput('200.00');
          await TransferInteractor.transferAccount.selectOption('USA Bank1');
          await TransferInteractor.comment.fillTextArea('Comment UNAM');
        });

        it('displays a value in the amount field', () => {
          expect(TransferInteractor.amount.val).to.equal('200.00');
        });

        it('updates the value', () => {
          expect(TransferInteractor.comment.val).to.equal('Comment UNAM');
        });

        it('updates the select value', () => {
          expect(TransferInteractor.transferAccount.val).to.equal('USA Bank1');
        });

        describe('submit and confirm the transfer', () => {
          beforeEach(async () => {
            await TransferInteractor.submit.click();
            await TransferInteractor.confirmationModal.confirmButton.click();
          });

          it('renders proper amount of rows', () => {
            expect(TransferInteractor.mclOpen.rowCount).to.equal(4);
          });
        });
      });

      describe('amount is less than zero', () => {
        beforeEach(async () => {
          await TransferInteractor.selectCheckbox();
          await TransferInteractor.transferButton();
          await TransferInteractor.amount.fillInput('-200.00');
          await TransferInteractor.transferAccount.selectOption('USA Bank1');
          await TransferInteractor.comment.fillTextArea('Comment UNAM');
        });

        it('show the amount field', () => {
          expect(TransferInteractor.amount.val).to.equal('-200.00');
        });
      });

      describe('transfer amount is greater than total amount', () => {
        beforeEach(async () => {
          await TransferInteractor.selectCheckbox();
          await TransferInteractor.transferButton();
          await TransferInteractor.amount.fillInput('700.00');
          await TransferInteractor.transferAccount.selectOption('USA Bank1');
          await TransferInteractor.notify.click();
        });

        it('show the amount field', () => {
          expect(TransferInteractor.amount.val).to.equal('700.00');
        });
      });

      describe('transfer amount is null', () => {
        beforeEach(async () => {
          await TransferInteractor.selectCheckbox();
          await TransferInteractor.transferButton();
          await TransferInteractor.amount.fillInput('');
          await TransferInteractor.transferAccount.selectOption('USA Bank1');
          await TransferInteractor.notify.click();
        });

        it('show the amount field', () => {
          expect(TransferInteractor.amount.val).to.equal('');
        });
      });

      // transfer many
      describe('go to all accounts', () => {
        beforeEach(async () => {
          await TransferInteractor.allAccounts();
        });

        describe('click on transfer button and close warning modal', () => {
          beforeEach(async () => {
            await TransferInteractor.selectCheckbox();
            await TransferInteractor.transferButton();
            await TransferInteractor.warningTransferCancel();
          });

          it('renders proper amount of rows', () => {
            expect(TransferInteractor.mclAll.rowCount).to.equal(5);
          });

          it('renders appropriate headers', () => {
            expect(TransferInteractor.mclAll.headers().length).to.be.greaterThan(0);
          });
        });

        describe.skip('make the transfer', () => {
          beforeEach(async () => {
            await TransferInteractor.selectCheckbox();
            await TransferInteractor.transferButton();
            await TransferInteractor.rows(0).cells(0).selectOneWarning();
            await TransferInteractor.warningTransferContinue();
            await TransferInteractor.amount.fillInput('400.00');
            await TransferInteractor.transferAccount.selectOption('USA Bank1');
            await TransferInteractor.comment.fillTextArea('Comment UNAM');
            await TransferInteractor.submit.click();
            await TransferInteractor.confirmationModal.confirmButton.click();
          });

          it('renders proper amount of rows', () => {
            expect(TransferInteractor.mclAll.rowCount).to.equal(5);
          });

          it('validate the correct amount on each row after the transfer', () => {
            const dataKeys = ['0.00', '10.00', '20.00', '30.00', '0.00'];

            for (let i = 0; i < 5; i++) {
              expect(TransferInteractor.mclAll.rows(i).cells(5).content).to.equal(dataKeys[i]);
            }
          });
        });
      });
      // END transfer many

      // on sort
      describe('go to all accounts', () => {
        beforeEach(async () => {
          await TransferInteractor.allAccounts();
        });

        describe('testing all headers columns', () => {
          beforeEach(async () => {
            await TransferInteractor.selectCheckbox();
            await TransferInteractor.transferButton();
            await TransferInteractor.mclWarning.headers(1).click();
            await TransferInteractor.mclWarning.headers(2).click();
            await TransferInteractor.mclWarning.headers(3).click();
            await TransferInteractor.mclWarning.headers(4).click();
            await TransferInteractor.mclWarning.headers(5).click();
          });

          it('renders appropriate headers', () => {
            expect(TransferInteractor.mclWarning.headers().length).to.be.greaterThan(0);
          });
        });
      });

      describe('Test all select transfers', () => {
        beforeEach(async () => {
          await TransferInteractor.allAccounts();
        });

        describe('select and deselect all transfers', () => {
          beforeEach(async () => {
            await TransferInteractor.selectCheckbox();
            await TransferInteractor.transferButton();
            await TransferInteractor.selectCheckboxWarning();
            await TransferInteractor.selectCheckboxWarning();
          });

          it('renders appropriate headers', () => {
            expect(TransferInteractor.mclWarning.headers().length).to.be.greaterThan(0);
          });

          describe('click on cancel button in warning modal', () => {
            beforeEach(async () => {
              await TransferInteractor.warningTransferCancel();
            });

            it('renders proper amount of rows', () => {
              expect(TransferInteractor.mclAll.rowCount).to.equal(5);
            });

            it('renders appropriate headers', () => {
              expect(TransferInteractor.mclAll.headers().length).to.be.greaterThan(0);
            });
          });
        });
      });
      // END on sort
    });
  });
});
<|endoftext|>


<commit_before>var express = require('express');
var app = express();
var dom = require('../');

app.set('views', 'public');

app.get(
	/\.(css|js|woff|eot|ttf|svg|png|jpg|gif)$/,
	express.static('public', {index: false, redirect: false})
);

// disables onlyScripts
dom.plugins = [];

app.get('/', dom('http://figaro-front-test.nsocket.com/fidji/live1', {allow: 'all'}).use(function(page, next) {
	page.on('response', function(res) {
		console.log(res.uri, res.status, res.mime);
	});
	next();
}));
/*
.use(function(h, req, res, next) {
	var pt = require('stream').PassThrough();
	pt.pipe(res);
	h.page.wait('idle', function(err) {
		if (err) return next(err);
	}).png(pt);
}));
*/

var port = 7799;
app.listen(port);
console.log("http://localhost:" + port + "/");

<commit_msg>Update example<commit_after>var express = require('express');
var app = express();
var dom = require('../');

app.set('views', 'public');

app.get(
	/\.(css|js|woff|eot|ttf|svg|png|jpg|gif)$/,
	express.static('public', {index: false, redirect: false})
);

app.get('/', dom('http://figaro-front-test.nsocket.com/fidji/live1')
.edit(dom.plugins.absolutify)
);

app.use(function(err, req, res, next) {
	if (err) {
		console.error(err);
		res.sendStatus(500);
	} else {
		next();
	}
});
/*
.use(function(h, req, res, next) {
	var pt = require('stream').PassThrough();
	pt.pipe(res);
	h.page.wait('idle', function(err) {
		if (err) return next(err);
	}).png(pt);
}));
*/

var port = 7799;
app.listen(port);
console.log("http://localhost:" + port + "/");

<|endoftext|>


<commit_before>var skipRules = skipRules || {};
skipRules.subsection = "";

angular.module('questionnaireApp', [])
    .controller('SkipRuleController', ['$scope', '$http', function($scope, $http) {
        $scope.activeTab = "newRuleTab";
        $scope.setActiveTab = function(activeTabName){
            $scope.activeTab = activeTabName;
        };

        var resetSkipRule = function() {
            $scope.skipRule = {selectedQuestion: {}, rootQuestion: {}, csrfToken: window.csrfToken};
        };

        resetSkipRule();
        $scope.questions = [];
        $scope.existingRules = [];
        $scope.matchSelectedQuestion = function(question) {
            return !($scope.skipRule.rootQuestion.pk == question.pk);
        };

        var updateRules = function(subsectionId){
            $http.get( "/questionnaire/subsection/" + subsectionId + "/skiprules/").
                success(function(data, status, headers, config) {
                $scope.existingRules = data;
            });
        }

        $scope.updateSkipRuleModal = function(subsectionId) {
            updateRules(subsectionId);
            $http.get( "/questionnaire/subsection/" + subsectionId + "/questions/").
                success(function(data, status, headers, config) {
                    var questions = data.questions;
                    resetSkipRule();
                    $scope.questions = questions;
                    $scope.skipRule.subsectionId = subsectionId;
                    $scope.skipResult = {show: false};
                });
        };
        $scope.fns = {};
        $scope.fns.createRule = function() {
        };

        var getFormData = function() {
            return {
                root_question: $scope.skipRule.rootQuestion.pk,
                response: $scope.skipRule.questionResponse,
                subsection: $scope.skipRule.subsectionId,
                skip_question: $scope.skipRule.skipQuestion.pk,
                csrfmiddlewaretoken: $scope.skipRule.csrfToken
            };
        };

        $scope.submitForm = function() {
            postData = getFormData();
            $.post(window.url, postData)
                .done(function(data) {
                    resetSkipRule();
                    $scope.$apply(function() {
                        $scope.skipResult = { className: "alert-success", message: data.result, show: true};
                    });
                    $scope.skipRule.subsectionId = postData.subsection;
                    updateRules(postData.subsection);
                })
                .fail(function(data) {
                    $scope.$apply(function() {
                        $scope.skipResult = { className: "alert-danger", message: data.result, show: true};
                    });
                });
        };
    }]);

skipRules.updateSubsection = function(subsectionId) {
    angular.element(document.getElementById('skip-rule-controller')).scope().updateSkipRuleModal(subsectionId);
};
<commit_msg>better error message for duplicate skip rule<commit_after>var skipRules = skipRules || {};
skipRules.subsection = "";

angular.module('questionnaireApp', [])
    .controller('SkipRuleController', ['$scope', '$http', function($scope, $http) {
        $scope.activeTab = "newRuleTab";
        $scope.setActiveTab = function(activeTabName){
            $scope.activeTab = activeTabName;
        };

        var resetSkipRule = function() {
            $scope.skipRule = {selectedQuestion: {}, rootQuestion: {}, csrfToken: window.csrfToken};
        };

        resetSkipRule();
        $scope.questions = [];
        $scope.existingRules = [];
        $scope.matchSelectedQuestion = function(question) {
            return !($scope.skipRule.rootQuestion.pk == question.pk);
        };

        var updateRules = function(subsectionId){
            $http.get( "/questionnaire/subsection/" + subsectionId + "/skiprules/").
                success(function(data, status, headers, config) {
                $scope.existingRules = data;
            });
        }

        $scope.updateSkipRuleModal = function(subsectionId) {
            updateRules(subsectionId);
            $http.get( "/questionnaire/subsection/" + subsectionId + "/questions/").
                success(function(data, status, headers, config) {
                    var questions = data.questions;
                    resetSkipRule();
                    $scope.questions = questions;
                    $scope.skipRule.subsectionId = subsectionId;
                    $scope.skipResult = {show: false};
                });
        };
        $scope.fns = {};
        $scope.fns.createRule = function() {
        };

        var getFormData = function() {
            return {
                root_question: $scope.skipRule.rootQuestion.pk,
                response: $scope.skipRule.questionResponse,
                subsection: $scope.skipRule.subsectionId,
                skip_question: $scope.skipRule.skipQuestion.pk,
                csrfmiddlewaretoken: $scope.skipRule.csrfToken
            };
        };

        $scope.submitForm = function() {
            postData = getFormData();
            $.post(window.url, postData)
                .done(function(data) {
                    resetSkipRule();
                    $scope.$apply(function() {
                        $scope.skipResult = { className: "alert-success", message: data.result, show: true};
                    });
                    $scope.skipRule.subsectionId = postData.subsection;
                    updateRules(postData.subsection);
                })
                .fail(function(data) {
                    if(data.result){
                        $scope.$apply(function() {
                            $scope.skipResult = { className: "alert-danger", message: data.result, show: true};
                        });
                    } else {
                        $scope.$apply(function() {
                            $scope.skipResult = { className: "alert-danger", message: data.responseJSON.result.join(","), show: true};
                        });
                    }
                });
        };
    }]);

skipRules.updateSubsection = function(subsectionId) {
    angular.element(document.getElementById('skip-rule-controller')).scope().updateSkipRuleModal(subsectionId);
};
<|endoftext|>


<commit_before>const { ASRouter } = ChromeUtils.import(
  "resource://activity-stream/lib/ASRouter.jsm"
);
const { OnboardingMessageProvider } = ChromeUtils.import(
  "resource://activity-stream/lib/OnboardingMessageProvider.jsm"
);
const { AttributionCode } = ChromeUtils.import(
  "resource:///modules/AttributionCode.jsm"
);

const BRANCH_PREF = "trailhead.firstrun.branches";

async function setRTAMOOnboarding() {
  await ASRouter.forceAttribution({
    campaign: "non-fx-button",
    source: "addons.mozilla.org",
    content: "iridium@particlecore.github.io",
  });
  AttributionCode._clearCache();
  const data = await AttributionCode.getAttrDataAsync();
  Assert.equal(
    data.source,
    "addons.mozilla.org",
    "Attribution data should be set"
  );

  Services.prefs.setCharPref(BRANCH_PREF, "join-supercharge");

  // Reset trailhead so it loads the new branch.
  Services.prefs.clearUserPref("trailhead.firstrun.didSeeAboutWelcome");
  await ASRouter.setState({ trailheadInitialized: false });
  await ASRouter.setupTrailhead();
  ASRouter._updateMessageProviders();
  await ASRouter.loadMessagesFromAllProviders();

  registerCleanupFunction(async () => {
    // Separate cleanup methods between mac and windows
    const { path } = Services.dirsvc.get("GreD", Ci.nsIFile).parent.parent;
    const attributionSvc = Cc["@mozilla.org/mac-attribution;1"].getService(
      Ci.nsIMacAttributionService
    );
    attributionSvc.setReferrerUrl(path, "", true);
    // Clear cache call is only possible in a testing environment
    let env = Cc["@mozilla.org/process/environment;1"].getService(
      Ci.nsIEnvironment
    );
    env.set("XPCSHELL_TEST_PROFILE_DIR", "testing");
    Services.prefs.clearUserPref(BRANCH_PREF);
    await AttributionCode.deleteFileAsync();
    AttributionCode._clearCache();
  });
}

add_task(async function setup() {
  // Store it in order to restore to the original value
  const { getAddonInfo } = OnboardingMessageProvider;
  // Prevent fetching the real addon url and making a network request
  OnboardingMessageProvider.getAddonInfo = () => ({
    name: "mochitest_name",
    iconURL: "mochitest_iconURL",
    url: "https://example.com",
  });

  registerCleanupFunction(() => {
    OnboardingMessageProvider.getAddonInfo = getAddonInfo;
  });
});

add_task(async () => {
  await setRTAMOOnboarding();

  let tab = await BrowserTestUtils.openNewForegroundTab(
    gBrowser,
    "about:welcome",
    false
  );
  let browser = tab.linkedBrowser;

  await ContentTask.spawn(browser, {}, async () => {
    // Wait for Activity Stream to load
    await ContentTaskUtils.waitForCondition(
      () => content.document.querySelector(".activity-stream"),
      `Should render Activity Stream`
    );
    await ContentTaskUtils.waitForCondition(
      () => content.document.body.classList.contains("welcome"),
      "The modal setup should be completed"
    );
    await ContentTaskUtils.waitForCondition(
      () => content.document.body.classList.contains("hide-main"),
      "You shouldn't be able to see newtabpage content"
    );
    for (let selector of [
      // ReturnToAMO elements
      ".ReturnToAMOOverlay",
      ".ReturnToAMOContainer",
      ".ReturnToAMOAddonContents",
      ".ReturnToAMOIcon",
    ]) {
      ok(content.document.querySelector(selector), `Should render ${selector}`);
    }
    // Make sure strings are properly shown
    Assert.equal(
      content.document.querySelector(".ReturnToAMOText").innerText,
      "Now let’s get you mochitest_name."
    );
  });

  BrowserTestUtils.removeTab(tab);
});
<commit_msg>Revert "Bug 1584625 - browser_aboutwelcome.js mochitest fails when run twice (#5329)"<commit_after>const { ASRouter } = ChromeUtils.import(
  "resource://activity-stream/lib/ASRouter.jsm"
);
const { OnboardingMessageProvider } = ChromeUtils.import(
  "resource://activity-stream/lib/OnboardingMessageProvider.jsm"
);
const { AttributionCode } = ChromeUtils.import(
  "resource:///modules/AttributionCode.jsm"
);

const BRANCH_PREF = "trailhead.firstrun.branches";

async function setRTAMOOnboarding() {
  await ASRouter.forceAttribution({
    campaign: "non-fx-button",
    source: "addons.mozilla.org",
    content: "iridium@particlecore.github.io",
  });
  AttributionCode._clearCache();
  const data = await AttributionCode.getAttrDataAsync();
  Assert.equal(
    data.source,
    "addons.mozilla.org",
    "Attribution data should be set"
  );

  Services.prefs.setCharPref(BRANCH_PREF, "join-supercharge");

  // Reset trailhead so it loads the new branch.
  Services.prefs.clearUserPref("trailhead.firstrun.didSeeAboutWelcome");
  await ASRouter.setState({ trailheadInitialized: false });
  await ASRouter.setupTrailhead();
  ASRouter._updateMessageProviders();
  await ASRouter.loadMessagesFromAllProviders();

  registerCleanupFunction(() => {
    Services.prefs.clearUserPref(BRANCH_PREF);
  });
}

add_task(async function setup() {
  // Store it in order to restore to the original value
  const { getAddonInfo } = OnboardingMessageProvider;
  // Prevent fetching the real addon url and making a network request
  OnboardingMessageProvider.getAddonInfo = () => ({
    name: "mochitest_name",
    iconURL: "mochitest_iconURL",
    url: "https://example.com",
  });

  registerCleanupFunction(() => {
    OnboardingMessageProvider.getAddonInfo = getAddonInfo;
  });
});

add_task(async () => {
  await setRTAMOOnboarding();

  let tab = await BrowserTestUtils.openNewForegroundTab(
    gBrowser,
    "about:welcome",
    false
  );
  let browser = tab.linkedBrowser;

  await ContentTask.spawn(browser, {}, async () => {
    // Wait for Activity Stream to load
    await ContentTaskUtils.waitForCondition(
      () => content.document.querySelector(".activity-stream"),
      `Should render Activity Stream`
    );
    await ContentTaskUtils.waitForCondition(
      () => content.document.body.classList.contains("welcome"),
      "The modal setup should be completed"
    );
    await ContentTaskUtils.waitForCondition(
      () => content.document.body.classList.contains("hide-main"),
      "You shouldn't be able to see newtabpage content"
    );
    for (let selector of [
      // ReturnToAMO elements
      ".ReturnToAMOOverlay",
      ".ReturnToAMOContainer",
      ".ReturnToAMOAddonContents",
      ".ReturnToAMOIcon",
    ]) {
      ok(content.document.querySelector(selector), `Should render ${selector}`);
    }
    // Make sure strings are properly shown
    Assert.equal(
      content.document.querySelector(".ReturnToAMOText").innerText,
      "Now let’s get you mochitest_name."
    );
  });

  BrowserTestUtils.removeTab(tab);
});
<|endoftext|>


<commit_before>var expect = require('expect.js');
var eio = require('../');

describe('Socket', function () {

  this.timeout(10000);

  describe('filterUpgrades', function () {
    it('should return only available transports', function () {
      var socket = new eio.Socket({'transports': ['polling']});
      expect(socket.filterUpgrades(['polling','websocket'])).to.eql(['polling']);
    });
  });

  describe('socketClosing', function(){
    it('should not emit close on incorrect connection', function (done) {
      var socket = new eio.Socket('ws://localhost:8080');
      var closed = false;

      socket.once('error', function(){
        setTimeout(function(){
          expect(closed).to.be(false);
          done();
        }, 20);
      });

      socket.on('close', function(){
        closed = true;
      });
    });
  });

});
<commit_msg>use invalid ip address for incorrect connection test<commit_after>var expect = require('expect.js');
var eio = require('../');

describe('Socket', function () {

  this.timeout(10000);

  describe('filterUpgrades', function () {
    it('should return only available transports', function () {
      var socket = new eio.Socket({'transports': ['polling']});
      expect(socket.filterUpgrades(['polling','websocket'])).to.eql(['polling']);
    });
  });

  describe('socketClosing', function(){
    it('should not emit close on incorrect connection', function (done) {
      var socket = new eio.Socket('ws://0.0.0.0:8080');
      var closed = false;

      socket.once('error', function(){
        setTimeout(function(){
          expect(closed).to.be(false);
          done();
        }, 20);
      });

      socket.on('close', function(){
        closed = true;
      });
    });
  });

});
<|endoftext|>