<commit_before>/**
 * Pimcore
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://www.pimcore.org/license
 *
 * @copyright  Copyright (c) 2009-2010 elements.at New Media Solutions GmbH (http://www.elements.at)
 * @license    http://www.pimcore.org/license     New BSD License
 */

// debug
if (!console) {
    if (!parent.console) {
        var console = {
            log: function (v) {
            }
        };
    }
    else {
        console = parent.console;
    }
}

// some globals
var pimcore_system_i18n;
var dndZones = []; // contains elements which are able to get data per dnd
var editables = [];
var editableNames = [];
var dndManager;

Ext.onReady(function () {

    Ext.QuickTips.init();

    // i18n
    pimcore_system_i18n = parent.pimcore_system_i18n;

    if (typeof pimcore == "object") {
        //editWindow.protectLocation();
        pimcore.registerNS("pimcore.globalmanager");
        pimcore.registerNS("pimcore.helpers");

        pimcore.globalmanager = parent.pimcore.globalmanager;
        pimcore.helpers = parent.pimcore.helpers;
    }

    if (pimcore_document_id) {
        editWindow = pimcore.globalmanager.get("document_" + pimcore_document_id).edit;
        editWindow.reloadInProgress = false;
        editWindow.frame = window;
    }

    function getEditable(config) {
        var id = config.id;
        var type = config.type;
        var name = config.name;
        var options = config.options;
        var data = config.data;

        if(in_array(name,editableNames)) {
            Ext.MessageBox.alert("ERROR","Dublicate editable name: " + name);
        }
        editableNames.push(name);

        return new pimcore.document.tags[type](id, name, options, data);
    }

    if (typeof Ext == "object" && typeof pimcore == "object") {

        for (var i = 0; i < editableConfigurations.length; i++) {
            try {
                editables.push(getEditable(editableConfigurations[i]));
            } catch (e) {
                console.log(e);
            }
        }

        if (editWindow.lastScrollposition) {
            if (editWindow.lastScrollposition.top > 100) {
                window.scrollTo(editWindow.lastScrollposition.left, editWindow.lastScrollposition.top);
            }
        }

        /* Drag an Drop from Tree panel */
        // IE HACK because the body is not 100% at height
        var bodyHeight = parent.Ext.get('document_iframe_' + window.editWindow.document.id).getHeight() + "px";
        Ext.getBody().applyStyles("min-height:" + bodyHeight);
        // set handler
        dndManager = new pimcore.document.edit.dnd(parent.Ext, Ext.getBody(), parent.Ext.get('document_iframe_' + window.editWindow.document.id), dndZones);

        // handler for Esc
        var mapEsc = new Ext.KeyMap(document, {
            key: [27],
            fn: function () {
                closeCKeditors();
            },
            stopEvent: true
        });

        // handler for STRG+S
        var mapCtrlS = new Ext.KeyMap(document, {
            key: "s",
            fn: parent.pimcore.helpers.handleCtrlS,
            ctrl:true,
            stopEvent: true
        });

        // handler for F5
        var mapF5 = new Ext.KeyMap(document, {
            key: [116],
            fn: parent.pimcore.helpers.handleF5,
            stopEvent: true
        });

        // add contextmenu note in help tool-tips
        var editablesForTooltip = Ext.query(".pimcore_editable");
        var tmpEl;
        for (var e=0; e<editablesForTooltip.length; e++) {
            tmpEl = Ext.get(editablesForTooltip[e]);
            if(tmpEl) {
                if(tmpEl.hasClass("pimcore_tag_inc") || tmpEl.hasClass("pimcore_tag_href") || tmpEl.hasClass("pimcore_tag_image") || tmpEl.hasClass("pimcore_tag_renderlet") || tmpEl.hasClass("pimcore_tag_snippet")) {
                    new Ext.ToolTip({
                        target: tmpEl,
                        showDelay: 100,
                        title: t("click_right_for_more_options"),
                        trackMouse:true
                    });
                }

                if(!tmpEl.hasClass("pimcore_tag_block") && !tmpEl.hasClass("pimcore_tag_areablock")) {
                    tmpEl.on("mouseenter", function (e) {
                        pimcore.edithelpers.frameElement(this, Ext.getBody());
                    });

                    tmpEl.on("mouseleave", function () {
                        pimcore.edithelpers.unFrameElement();
                    });
                }

            }
        }

        // add contextmenu menu to elements included by $this->inc();
        var incElements = Ext.query(".pimcore_tag_inc");
        var tmpIncEl;
        for (var q=0; q<incElements.length; q++) {
            tmpIncEl = Ext.get(incElements[q]);
            if(tmpIncEl) {
                if(tmpIncEl.getAttribute("pimcore_id") && tmpIncEl.getAttribute("pimcore_type")) {
                    tmpIncEl.on("contextmenu", function (e) {

                        var menu = new Ext.menu.Menu();
                        menu.add(new Ext.menu.Item({
                            text: t('open'),
                            iconCls: "pimcore_icon_open",
                            handler: function (item) {
                                item.parentMenu.destroy();
                                pimcore.helpers.openDocument(this.getAttribute("pimcore_id"), this.getAttribute("pimcore_type"));
                            }.bind(this)
                        }));

                        menu.showAt(e.getXY());

                        e.stopEvent();
                    });
                }
            }
        }

    }
});

<commit_msg>no mouse tracking anymore for tooltips over editables<commit_after>/**
 * Pimcore
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://www.pimcore.org/license
 *
 * @copyright  Copyright (c) 2009-2010 elements.at New Media Solutions GmbH (http://www.elements.at)
 * @license    http://www.pimcore.org/license     New BSD License
 */

// debug
if (!console) {
    if (!parent.console) {
        var console = {
            log: function (v) {
            }
        };
    }
    else {
        console = parent.console;
    }
}

// some globals
var pimcore_system_i18n;
var dndZones = []; // contains elements which are able to get data per dnd
var editables = [];
var editableNames = [];
var dndManager;

Ext.onReady(function () {

    Ext.QuickTips.init();

    // i18n
    pimcore_system_i18n = parent.pimcore_system_i18n;

    if (typeof pimcore == "object") {
        //editWindow.protectLocation();
        pimcore.registerNS("pimcore.globalmanager");
        pimcore.registerNS("pimcore.helpers");

        pimcore.globalmanager = parent.pimcore.globalmanager;
        pimcore.helpers = parent.pimcore.helpers;
    }

    if (pimcore_document_id) {
        editWindow = pimcore.globalmanager.get("document_" + pimcore_document_id).edit;
        editWindow.reloadInProgress = false;
        editWindow.frame = window;
    }

    function getEditable(config) {
        var id = config.id;
        var type = config.type;
        var name = config.name;
        var options = config.options;
        var data = config.data;

        if(in_array(name,editableNames)) {
            Ext.MessageBox.alert("ERROR","Dublicate editable name: " + name);
        }
        editableNames.push(name);

        return new pimcore.document.tags[type](id, name, options, data);
    }

    if (typeof Ext == "object" && typeof pimcore == "object") {

        for (var i = 0; i < editableConfigurations.length; i++) {
            try {
                editables.push(getEditable(editableConfigurations[i]));
            } catch (e) {
                console.log(e);
            }
        }

        if (editWindow.lastScrollposition) {
            if (editWindow.lastScrollposition.top > 100) {
                window.scrollTo(editWindow.lastScrollposition.left, editWindow.lastScrollposition.top);
            }
        }

        /* Drag an Drop from Tree panel */
        // IE HACK because the body is not 100% at height
        var bodyHeight = parent.Ext.get('document_iframe_' + window.editWindow.document.id).getHeight() + "px";
        Ext.getBody().applyStyles("min-height:" + bodyHeight);
        // set handler
        dndManager = new pimcore.document.edit.dnd(parent.Ext, Ext.getBody(), parent.Ext.get('document_iframe_' + window.editWindow.document.id), dndZones);

        // handler for Esc
        var mapEsc = new Ext.KeyMap(document, {
            key: [27],
            fn: function () {
                closeCKeditors();
            },
            stopEvent: true
        });

        // handler for STRG+S
        var mapCtrlS = new Ext.KeyMap(document, {
            key: "s",
            fn: parent.pimcore.helpers.handleCtrlS,
            ctrl:true,
            stopEvent: true
        });

        // handler for F5
        var mapF5 = new Ext.KeyMap(document, {
            key: [116],
            fn: parent.pimcore.helpers.handleF5,
            stopEvent: true
        });

        // add contextmenu note in help tool-tips
        var editablesForTooltip = Ext.query(".pimcore_editable");
        var tmpEl;
        for (var e=0; e<editablesForTooltip.length; e++) {
            tmpEl = Ext.get(editablesForTooltip[e]);
            if(tmpEl) {
                if(tmpEl.hasClass("pimcore_tag_inc") || tmpEl.hasClass("pimcore_tag_href") || tmpEl.hasClass("pimcore_tag_image") || tmpEl.hasClass("pimcore_tag_renderlet") || tmpEl.hasClass("pimcore_tag_snippet")) {
                    new Ext.ToolTip({
                        target: tmpEl,
                        showDelay: 100,
                        anchor: "left",
                        title: t("click_right_for_more_options")
                    });
                }

                if(!tmpEl.hasClass("pimcore_tag_block") && !tmpEl.hasClass("pimcore_tag_areablock")) {
                    tmpEl.on("mouseenter", function (e) {
                        pimcore.edithelpers.frameElement(this, Ext.getBody());
                    });

                    tmpEl.on("mouseleave", function () {
                        pimcore.edithelpers.unFrameElement();
                    });
                }

            }
        }

        // add contextmenu menu to elements included by $this->inc();
        var incElements = Ext.query(".pimcore_tag_inc");
        var tmpIncEl;
        for (var q=0; q<incElements.length; q++) {
            tmpIncEl = Ext.get(incElements[q]);
            if(tmpIncEl) {
                if(tmpIncEl.getAttribute("pimcore_id") && tmpIncEl.getAttribute("pimcore_type")) {
                    tmpIncEl.on("contextmenu", function (e) {

                        var menu = new Ext.menu.Menu();
                        menu.add(new Ext.menu.Item({
                            text: t('open'),
                            iconCls: "pimcore_icon_open",
                            handler: function (item) {
                                item.parentMenu.destroy();
                                pimcore.helpers.openDocument(this.getAttribute("pimcore_id"), this.getAttribute("pimcore_type"));
                            }.bind(this)
                        }));

                        menu.showAt(e.getXY());

                        e.stopEvent();
                    });
                }
            }
        }

    }
});

<|endoftext|>


<commit_before>import React from 'react'
import Globalize from 'globalize'
import { mount, shallow } from 'enzyme'

import DateTimePicker from '../src/DateTimePicker'
import TimeList from '../src/TimeList'
import Calendar from '../src/Calendar'

let ControlledDateTimePicker = DateTimePicker.ControlledComponent

describe('DateTimePicker', () => {
  it('should set initial values', () => {
    var date = new Date()

    expect(
      mount(<DateTimePicker defaultValue={date} format="MM-dd-yyyy" />)
        .find('.rw-input')
        .getDOMNode().value
    ).to.equal(Globalize.format(date, 'MM-dd-yyyy'))
  })

  it('should start closed', () => {
    let inst = shallow(<ControlledDateTimePicker />)

    expect(inst.prop('open')).to.not.equal(true)

    expect(
      inst
        .find('Popup')
        .first()
        .prop('open')
    ).to.not.equal(true)

    inst.assertNone('.rw-open')
    inst.assertSingle('DateTimePickerInput[aria-expanded=false]')
  })

  it('should open when clicked', () => {
    var onOpen = sinon.spy()

    let wrapper = shallow(<ControlledDateTimePicker onToggle={onOpen} />)

    wrapper
      .find('Button')
      .first()
      .simulate('click')

    wrapper
      .find('Button')
      .last()
      .simulate('click')

    expect(onOpen.calledTwice).to.equal(true)
  })

  it('passes default props to calendar', () => {
    let wrapper = mount(
      <ControlledDateTimePicker open="date" defaultView="year" />
    )

    expect(wrapper.find(Calendar.ControlledComponent).props().view).to.equal(
      'year'
    )
  })

  it('sets aria-owns relationship for Calendar', () => {
    const inst = shallow(<ControlledDateTimePicker open="date" time={false} />)
    const dateId = inst.find(Calendar).props().id
    inst.assertSingle(`[aria-owns='${dateId}']`)
  })

  it('sets aria-owns relationship for TimePicker', () => {
    const inst = shallow(<ControlledDateTimePicker open="time" date={false} time={true} />)
    const listId = inst.find(TimeList).props().id
    console.log(inst.find(TimeList).debug())
    console.log(inst.find('DateTimePickerInput').debug())
    inst.assertSingle(`[aria-owns='${listId}']`)
  })

  it('should change when selecting a date', () => {
    let change = sinon.spy()

    shallow(
      <ControlledDateTimePicker
        open="date"
        onChange={change}
        onToggle={() => {}}
      />
    )
      .assertSingle(Calendar)
      .simulate('change', new Date())

    expect(change.calledOnce).to.equal(true)
  })

  it('should change when selecting a time', () => {
    let change = sinon.spy(),
      select = sinon.spy()

    shallow(
      <ControlledDateTimePicker
        open="date"
        onChange={change}
        onSelect={select}
        onToggle={() => {}}
      />
    )
      .assertSingle(TimeList)
      .simulate('select', { date: new Date() })

    expect(select.calledOnce).to.equal(true)
    expect(change.calledAfter(select)).to.equal(true)
    expect(change.calledOnce).to.equal(true)
  })

  it('should change when selecting a time', () => {
    let change = sinon.spy(),
      select = sinon.spy()

    shallow(
      <ControlledDateTimePicker
        open="date"
        onChange={change}
        onSelect={select}
        onToggle={() => {}}
      />
    )
      .assertSingle(TimeList)
      .simulate('select', { date: new Date() })

    expect(select.calledOnce).to.equal(true)
    expect(change.calledAfter(select)).to.equal(true)
    expect(change.calledOnce).to.equal(true)
  })

  it('should set id on list', () => {
    expect(
      mount(<DateTimePicker />)
        .find('ul')
        .getDOMNode()
        .hasAttribute('id')
    ).to.equal(true)
  })

  it('should not show time button when not selected', () => {
    var spy = sinon.spy()

    mount(<DateTimePicker time={false} date={false} onToggle={spy} />)
      .tap(_ => _.assertNone('.rw-btn-time'))
      .tap(_ => _.assertNone('.rw-btn-calendar'))
      .simulate('keyDown', { altKey: true })
      .simulate('keyDown', { altKey: true })

    expect(spy.callCount).to.equal(0)
  })

  it('should simulate focus/blur events', done => {
    let blur = sinon.spy()
    let focus = sinon.spy()

    let inst = mount(<DateTimePicker onBlur={blur} onFocus={focus} />)

    expect(focus.calledOnce).to.equal(false)
    expect(blur.calledOnce).to.equal(false)

    inst.simulate('focus')

    setTimeout(() => {
      expect(focus.calledOnce).to.equal(true)
      inst.simulate('blur')

      setTimeout(() => {
        expect(blur.calledOnce).to.equal(true)
        done()
      })
    })
  })

  it('should simulate key events', () => {
    let kp = sinon.spy(),
      kd = sinon.spy(),
      ku = sinon.spy()

    mount(<DateTimePicker onKeyPress={kp} onKeyUp={ku} onKeyDown={kd} />)
      .find('.rw-input')
      .simulate('keyPress')
      .simulate('keyDown')
      .simulate('keyUp')

    expect(kp.calledOnce).to.equal(true)
    expect(kd.calledOnce).to.equal(true)
    expect(ku.calledOnce).to.equal(true)
  })

  it('should do nothing when disabled', done => {
    let wrapper = mount(<DateTimePicker defaultValue={new Date()} disabled />)

    let input = wrapper.find('.rw-input').getDOMNode()

    expect(input.hasAttribute('disabled')).to.equal(true)
    expect(input.getAttribute('aria-owns')).to.equal('')

    wrapper.find('.rw-i-calendar').simulate('click')

    setTimeout(() => {
      expect(wrapper.instance()._values.open).to.not.equal(true)
      done()
    }, 0)
  })

  it('should do nothing when readonly', done => {
    let wrapper = mount(<DateTimePicker defaultValue={new Date()} readOnly />)

    let input = wrapper.find('.rw-input').getDOMNode()

    expect(input.hasAttribute('readonly')).to.equal(true)
    expect(input.getAttribute('aria-owns')).to.equal('')

    wrapper.find('.rw-i-calendar').simulate('click')

    setTimeout(() => {
      expect(wrapper.instance()._values.open).to.not.equal(true)
      done()
    })
  })

  it('should change values on key down', () => {
    let change = sinon.spy()

    let wrapper = mount(<DateTimePicker onChange={change} />)

    let options = wrapper.find('li').map(n => n.getDOMNode())

    wrapper.simulate('keyDown', { key: 'ArrowDown', altKey: true })

    expect(wrapper.instance()._values.open).to.equal('date')

    wrapper.simulate('keyDown', { key: 'ArrowDown', altKey: true })

    expect(wrapper.instance()._values.open).to.equal('time')

    wrapper.simulate('keyDown', { key: 'Home' })

    expect(options[0].className).to.match(/\brw-state-focus\b/)

    wrapper.simulate('keyDown', { key: 'End' })

    expect(options[options.length - 1].className).to.match(/\brw-state-focus\b/)

    wrapper.simulate('keyDown', { key: 'ArrowUp' })

    expect(options[options.length - 2].className).to.match(/\brw-state-focus\b/)

    wrapper.simulate('keyDown', { key: 'ArrowDown' })

    expect(options[options.length - 1].className).to.match(/\brw-state-focus\b/)
  })

  describe('TimeList', () => {
    it('should render max correctly', () => {
      let date = new Date(2014, 0, 16, 9, 30)
      let inst = mount(
        <TimeList value={new Date(2014, 0, 16, 8)} max={date} preserveDate />
      )

      let dates = inst.state('data')
      let time = dates[dates.length - 1]

      expect(time.date.getHours()).to.eql(9)
      expect(time.date.getMinutes()).to.eql(30)
      expect(time.date.getSeconds()).to.eql(0)

      inst.setProps({ value: new Date(2014, 0, 15, 8) })

      dates = inst.state('data')
      time = dates[dates.length - 1]

      expect(time.date.getHours()).to.eql(23)
      expect(time.date.getMinutes()).to.eql(30)
      expect(time.date.getSeconds()).to.eql(0)
    })

    it('should render min correctly', () => {
      let date = new Date(2014, 0, 16, 9, 30)

      let inst = mount(
        <TimeList value={new Date(2014, 0, 16, 12)} min={date} preserveDate />
      )

      let time = inst.state('data')[0]

      expect(time.date.getHours()).to.eql(9)
      expect(time.date.getMinutes()).to.eql(30)
      expect(time.date.getSeconds()).to.eql(0)

      inst = mount(
        <TimeList value={new Date(2014, 0, 18, 8)} min={date} preserveDate />
      )
      time = inst.state('data')[0]

      expect(time.date.getHours()).to.eql(0)
      expect(time.date.getMinutes()).to.eql(0)
      expect(time.date.getSeconds()).to.eql(0)
    })

    it('should set the step property', () => {
      let dates = mount(<DateTimePicker step={60} />)
        .find(TimeList)
        .instance().state.data

      expect(dates[0].date.getHours()).to.equal(0)
      expect(dates[1].date.getHours()).to.equal(1)
      expect(dates[2].date.getHours()).to.equal(2)

      dates = mount(<DateTimePicker step={120} />)
        .find(TimeList)
        .instance().state.data

      expect(dates[0].date.getHours()).to.equal(0)
      expect(dates[1].date.getHours()).to.equal(2)
      expect(dates[2].date.getHours()).to.equal(4)
    })
  })
})
<commit_msg>chore: remove unintended console (#903)<commit_after>import React from 'react'
import Globalize from 'globalize'
import { mount, shallow } from 'enzyme'

import DateTimePicker from '../src/DateTimePicker'
import TimeList from '../src/TimeList'
import Calendar from '../src/Calendar'

let ControlledDateTimePicker = DateTimePicker.ControlledComponent

describe('DateTimePicker', () => {
  it('should set initial values', () => {
    var date = new Date()

    expect(
      mount(<DateTimePicker defaultValue={date} format="MM-dd-yyyy" />)
        .find('.rw-input')
        .getDOMNode().value
    ).to.equal(Globalize.format(date, 'MM-dd-yyyy'))
  })

  it('should start closed', () => {
    let inst = shallow(<ControlledDateTimePicker />)

    expect(inst.prop('open')).to.not.equal(true)

    expect(
      inst
        .find('Popup')
        .first()
        .prop('open')
    ).to.not.equal(true)

    inst.assertNone('.rw-open')
    inst.assertSingle('DateTimePickerInput[aria-expanded=false]')
  })

  it('should open when clicked', () => {
    var onOpen = sinon.spy()

    let wrapper = shallow(<ControlledDateTimePicker onToggle={onOpen} />)

    wrapper
      .find('Button')
      .first()
      .simulate('click')

    wrapper
      .find('Button')
      .last()
      .simulate('click')

    expect(onOpen.calledTwice).to.equal(true)
  })

  it('passes default props to calendar', () => {
    let wrapper = mount(
      <ControlledDateTimePicker open="date" defaultView="year" />
    )

    expect(wrapper.find(Calendar.ControlledComponent).props().view).to.equal(
      'year'
    )
  })

  it('sets aria-owns relationship for Calendar', () => {
    const inst = shallow(<ControlledDateTimePicker open="date" time={false} />)
    const dateId = inst.find(Calendar).props().id
    inst.assertSingle(`[aria-owns='${dateId}']`)
  })

  it('sets aria-owns relationship for TimePicker', () => {
    const inst = shallow(<ControlledDateTimePicker open="time" date={false} time={true} />)
    const listId = inst.find(TimeList).props().id
    inst.assertSingle(`[aria-owns='${listId}']`)
  })

  it('should change when selecting a date', () => {
    let change = sinon.spy()

    shallow(
      <ControlledDateTimePicker
        open="date"
        onChange={change}
        onToggle={() => {}}
      />
    )
      .assertSingle(Calendar)
      .simulate('change', new Date())

    expect(change.calledOnce).to.equal(true)
  })

  it('should change when selecting a time', () => {
    let change = sinon.spy(),
      select = sinon.spy()

    shallow(
      <ControlledDateTimePicker
        open="date"
        onChange={change}
        onSelect={select}
        onToggle={() => {}}
      />
    )
      .assertSingle(TimeList)
      .simulate('select', { date: new Date() })

    expect(select.calledOnce).to.equal(true)
    expect(change.calledAfter(select)).to.equal(true)
    expect(change.calledOnce).to.equal(true)
  })

  it('should change when selecting a time', () => {
    let change = sinon.spy(),
      select = sinon.spy()

    shallow(
      <ControlledDateTimePicker
        open="date"
        onChange={change}
        onSelect={select}
        onToggle={() => {}}
      />
    )
      .assertSingle(TimeList)
      .simulate('select', { date: new Date() })

    expect(select.calledOnce).to.equal(true)
    expect(change.calledAfter(select)).to.equal(true)
    expect(change.calledOnce).to.equal(true)
  })

  it('should set id on list', () => {
    expect(
      mount(<DateTimePicker />)
        .find('ul')
        .getDOMNode()
        .hasAttribute('id')
    ).to.equal(true)
  })

  it('should not show time button when not selected', () => {
    var spy = sinon.spy()

    mount(<DateTimePicker time={false} date={false} onToggle={spy} />)
      .tap(_ => _.assertNone('.rw-btn-time'))
      .tap(_ => _.assertNone('.rw-btn-calendar'))
      .simulate('keyDown', { altKey: true })
      .simulate('keyDown', { altKey: true })

    expect(spy.callCount).to.equal(0)
  })

  it('should simulate focus/blur events', done => {
    let blur = sinon.spy()
    let focus = sinon.spy()

    let inst = mount(<DateTimePicker onBlur={blur} onFocus={focus} />)

    expect(focus.calledOnce).to.equal(false)
    expect(blur.calledOnce).to.equal(false)

    inst.simulate('focus')

    setTimeout(() => {
      expect(focus.calledOnce).to.equal(true)
      inst.simulate('blur')

      setTimeout(() => {
        expect(blur.calledOnce).to.equal(true)
        done()
      })
    })
  })

  it('should simulate key events', () => {
    let kp = sinon.spy(),
      kd = sinon.spy(),
      ku = sinon.spy()

    mount(<DateTimePicker onKeyPress={kp} onKeyUp={ku} onKeyDown={kd} />)
      .find('.rw-input')
      .simulate('keyPress')
      .simulate('keyDown')
      .simulate('keyUp')

    expect(kp.calledOnce).to.equal(true)
    expect(kd.calledOnce).to.equal(true)
    expect(ku.calledOnce).to.equal(true)
  })

  it('should do nothing when disabled', done => {
    let wrapper = mount(<DateTimePicker defaultValue={new Date()} disabled />)

    let input = wrapper.find('.rw-input').getDOMNode()

    expect(input.hasAttribute('disabled')).to.equal(true)
    expect(input.getAttribute('aria-owns')).to.equal('')

    wrapper.find('.rw-i-calendar').simulate('click')

    setTimeout(() => {
      expect(wrapper.instance()._values.open).to.not.equal(true)
      done()
    }, 0)
  })

  it('should do nothing when readonly', done => {
    let wrapper = mount(<DateTimePicker defaultValue={new Date()} readOnly />)

    let input = wrapper.find('.rw-input').getDOMNode()

    expect(input.hasAttribute('readonly')).to.equal(true)
    expect(input.getAttribute('aria-owns')).to.equal('')

    wrapper.find('.rw-i-calendar').simulate('click')

    setTimeout(() => {
      expect(wrapper.instance()._values.open).to.not.equal(true)
      done()
    })
  })

  it('should change values on key down', () => {
    let change = sinon.spy()

    let wrapper = mount(<DateTimePicker onChange={change} />)

    let options = wrapper.find('li').map(n => n.getDOMNode())

    wrapper.simulate('keyDown', { key: 'ArrowDown', altKey: true })

    expect(wrapper.instance()._values.open).to.equal('date')

    wrapper.simulate('keyDown', { key: 'ArrowDown', altKey: true })

    expect(wrapper.instance()._values.open).to.equal('time')

    wrapper.simulate('keyDown', { key: 'Home' })

    expect(options[0].className).to.match(/\brw-state-focus\b/)

    wrapper.simulate('keyDown', { key: 'End' })

    expect(options[options.length - 1].className).to.match(/\brw-state-focus\b/)

    wrapper.simulate('keyDown', { key: 'ArrowUp' })

    expect(options[options.length - 2].className).to.match(/\brw-state-focus\b/)

    wrapper.simulate('keyDown', { key: 'ArrowDown' })

    expect(options[options.length - 1].className).to.match(/\brw-state-focus\b/)
  })

  describe('TimeList', () => {
    it('should render max correctly', () => {
      let date = new Date(2014, 0, 16, 9, 30)
      let inst = mount(
        <TimeList value={new Date(2014, 0, 16, 8)} max={date} preserveDate />
      )

      let dates = inst.state('data')
      let time = dates[dates.length - 1]

      expect(time.date.getHours()).to.eql(9)
      expect(time.date.getMinutes()).to.eql(30)
      expect(time.date.getSeconds()).to.eql(0)

      inst.setProps({ value: new Date(2014, 0, 15, 8) })

      dates = inst.state('data')
      time = dates[dates.length - 1]

      expect(time.date.getHours()).to.eql(23)
      expect(time.date.getMinutes()).to.eql(30)
      expect(time.date.getSeconds()).to.eql(0)
    })

    it('should render min correctly', () => {
      let date = new Date(2014, 0, 16, 9, 30)

      let inst = mount(
        <TimeList value={new Date(2014, 0, 16, 12)} min={date} preserveDate />
      )

      let time = inst.state('data')[0]

      expect(time.date.getHours()).to.eql(9)
      expect(time.date.getMinutes()).to.eql(30)
      expect(time.date.getSeconds()).to.eql(0)

      inst = mount(
        <TimeList value={new Date(2014, 0, 18, 8)} min={date} preserveDate />
      )
      time = inst.state('data')[0]

      expect(time.date.getHours()).to.eql(0)
      expect(time.date.getMinutes()).to.eql(0)
      expect(time.date.getSeconds()).to.eql(0)
    })

    it('should set the step property', () => {
      let dates = mount(<DateTimePicker step={60} />)
        .find(TimeList)
        .instance().state.data

      expect(dates[0].date.getHours()).to.equal(0)
      expect(dates[1].date.getHours()).to.equal(1)
      expect(dates[2].date.getHours()).to.equal(2)

      dates = mount(<DateTimePicker step={120} />)
        .find(TimeList)
        .instance().state.data

      expect(dates[0].date.getHours()).to.equal(0)
      expect(dates[1].date.getHours()).to.equal(2)
      expect(dates[2].date.getHours()).to.equal(4)
    })
  })
})
<|endoftext|>


<commit_before>/* jshint mocha: true */

var assert = require('assert');
var fs = require('fs');
var path = require('path');

var pkg = require('./../package.json');
var dirs = pkg.configs.directories;

var expectedFilesInArchiveDir = [
    pkg.name + '_v' + pkg.version + '.zip'
];

var expectedFilesInDistDir = [

    '.editorconfig',
    '.gitattributes',
    '.gitignore',
    '.htaccess',
    '404.html',
    'browserconfig.xml',
    'crossdomain.xml',

    'css/', // for directories, a `/` character
            // should be included at the end
        'css/main.css',
        'css/normalize.css',
        'css/materialize.min.css',

    'doc/',
        'doc/TOC.md',
        'doc/css.md',
        'doc/extend.md',
        'doc/faq.md',
        'doc/html.md',
        'doc/js.md',
        'doc/misc.md',
        'doc/usage.md',

    'humans.txt',

    'img/',
        'img/.gitignore',
        'img/adcade.png',
        'img/allhdd.png',
        'img/amplify.png',
        'img/comix.png',
        'img/logo.png',
        'img/face.png',
        'img/withpulp.png',
        'img/background_320.jpg',
        'img/background_1024.jpg',
        'img/background_2880.jpg',

    'fonts/',
    'fonts/material-design-icons/',
    'fonts/roboto/',
        'fonts/material-design-icons/LICENSE.txt',
        'fonts/material-design-icons/Material-Design-Icons.eot',
        'fonts/material-design-icons/Material-Design-Icons.svg',
        'fonts/material-design-icons/Material-Design-Icons.ttf',
        'fonts/material-design-icons/Material-Design-Icons.woff',
        'fonts/material-design-icons/Material-Design-Icons.woff2',
        'fonts/roboto/Roboto-Bold.ttf',
        'fonts/roboto/Roboto-Bold.woff2',
        'fonts/roboto/Roboto-Light.woff',
        'fonts/roboto/Roboto-Medium.ttf',
        'fonts/roboto/Roboto-Medium.woff2',
        'fonts/roboto/Roboto-Regular.woff',
        'fonts/roboto/Roboto-Thin.ttf',
        'fonts/roboto/Roboto-Thin.woff2',
        'fonts/roboto/Roboto-Bold.woff',
        'fonts/roboto/Roboto-Light.ttf',
        'fonts/roboto/Roboto-Light.woff2',
        'fonts/roboto/Roboto-Medium.woff',
        'fonts/roboto/Roboto-Regular.ttf',
        'fonts/roboto/Roboto-Regular.woff2',
        'fonts/roboto/Roboto-Thin.woff',

    'index.html',
    'stage.index.html',

    'js/',
        'js/main.js',
        'js/plugins.js',
        'js/vendor/',
            'js/vendor/jquery-' + pkg.devDependencies.jquery + '.min.js',
            'js/vendor/modernizr-2.8.3.min.js',
            'js/vendor/init.js',
            'js/vendor/materialize.min.js',

    'LICENSE.txt',
    'robots.txt'

];

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

function checkFiles(directory, expectedFiles) {

    // Get the list of files from the specified directory
    var files = require('glob').sync('**/*', {
        'cwd': directory,
        'dot': true,      // include hidden files
        'mark': true      // add a `/` character to directory matches
    });

    // Check if all expected files are present in the
    // specified directory, and are of the expected type
    expectedFiles.forEach(function (file) {

        var ok = false;
        var expectedFileType = (file.slice(-1) !== '/' ? 'regular file' : 'directory');

        // If file exists
        if (files.indexOf(file) !== -1) {

            // Check if the file is of the correct type
            if (file.slice(-1) !== '/') {
                // Check if the file is really a regular file
                ok = fs.statSync(path.resolve(directory, file)).isFile();
            } else {
                // Check if the file is a directory
                // (Since glob adds the `/` character to directory matches,
                // we can simply check if the `/` character is present)
                ok = (files[files.indexOf(file)].slice(-1) === '/');
            }

        }

        it('"' + file + '" should be present and it should be a ' + expectedFileType, function () {
            assert.equal(true, ok);
        });

    });

    // List all files that should be NOT
    // be present in the specified directory
    (files.filter(function (file) {
        return expectedFiles.indexOf(file) === -1;
    })).forEach(function (file) {
        it('"' + file + '" should NOT be present', function () {
            assert(false);
        });
    });

}

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

function runTests() {

    describe('Test if all the expected files, and only them, are present in the build directories', function () {

        describe(dirs.archive, function () {
            checkFiles(dirs.archive, expectedFilesInArchiveDir);
        });

        describe(dirs.dist, function () {
            checkFiles(dirs.dist, expectedFilesInDistDir);
        });

    });

}

runTests();
<commit_msg>final before branch<commit_after>/* jshint mocha: true */

var assert = require('assert');
var fs = require('fs');
var path = require('path');

var pkg = require('./../package.json');
var dirs = pkg.configs.directories;

var expectedFilesInArchiveDir = [
    pkg.name + '_v' + pkg.version + '.zip'
];

var expectedFilesInDistDir = [

    '.editorconfig',
    '.gitattributes',
    '.gitignore',
    '.htaccess',
    '404.html',
    'browserconfig.xml',
    'crossdomain.xml',

    'css/', // for directories, a `/` character
            // should be included at the end
        'css/main.css',
        'css/normalize.css',
        'css/materialize.min.css',

    'doc/',
        'doc/README.md',
        'doc/TOC.md',
        'doc/css.md',
        'doc/extend.md',
        'doc/faq.md',
        'doc/html.md',
        'doc/js.md',
        'doc/misc.md',
        'doc/usage.md',

    'humans.txt',

    'img/',
        'img/.gitignore',
        'img/adcade.png',
        'img/allhdd.png',
        'img/amplify.png',
        'img/comix.png',
        'img/logo.png',
        'img/face.png',
        'img/withpulp.png',
        'img/background_320.jpg',
        'img/background_1024.jpg',
        'img/background_2880.jpg',

    'fonts/',
    'fonts/material-design-icons/',
    'fonts/roboto/',
        'fonts/material-design-icons/LICENSE.txt',
        'fonts/material-design-icons/Material-Design-Icons.eot',
        'fonts/material-design-icons/Material-Design-Icons.svg',
        'fonts/material-design-icons/Material-Design-Icons.ttf',
        'fonts/material-design-icons/Material-Design-Icons.woff',
        'fonts/material-design-icons/Material-Design-Icons.woff2',
        'fonts/roboto/Roboto-Bold.ttf',
        'fonts/roboto/Roboto-Bold.woff2',
        'fonts/roboto/Roboto-Light.woff',
        'fonts/roboto/Roboto-Medium.ttf',
        'fonts/roboto/Roboto-Medium.woff2',
        'fonts/roboto/Roboto-Regular.woff',
        'fonts/roboto/Roboto-Thin.ttf',
        'fonts/roboto/Roboto-Thin.woff2',
        'fonts/roboto/Roboto-Bold.woff',
        'fonts/roboto/Roboto-Light.ttf',
        'fonts/roboto/Roboto-Light.woff2',
        'fonts/roboto/Roboto-Medium.woff',
        'fonts/roboto/Roboto-Regular.ttf',
        'fonts/roboto/Roboto-Regular.woff2',
        'fonts/roboto/Roboto-Thin.woff',

    'index.html',
    'stage.index.html',

    'js/',
        'js/main.js',
        'js/plugins.js',
        'js/vendor/',
            'js/vendor/jquery-' + pkg.devDependencies.jquery + '.min.js',
            'js/vendor/modernizr-2.8.3.min.js',
            'js/vendor/init.js',
            'js/vendor/materialize.min.js',

    'LICENSE.txt',
    'robots.txt'

];

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

function checkFiles(directory, expectedFiles) {

    // Get the list of files from the specified directory
    var files = require('glob').sync('**/*', {
        'cwd': directory,
        'dot': true,      // include hidden files
        'mark': true      // add a `/` character to directory matches
    });

    // Check if all expected files are present in the
    // specified directory, and are of the expected type
    expectedFiles.forEach(function (file) {

        var ok = false;
        var expectedFileType = (file.slice(-1) !== '/' ? 'regular file' : 'directory');

        // If file exists
        if (files.indexOf(file) !== -1) {

            // Check if the file is of the correct type
            if (file.slice(-1) !== '/') {
                // Check if the file is really a regular file
                ok = fs.statSync(path.resolve(directory, file)).isFile();
            } else {
                // Check if the file is a directory
                // (Since glob adds the `/` character to directory matches,
                // we can simply check if the `/` character is present)
                ok = (files[files.indexOf(file)].slice(-1) === '/');
            }

        }

        it('"' + file + '" should be present and it should be a ' + expectedFileType, function () {
            assert.equal(true, ok);
        });

    });

    // List all files that should be NOT
    // be present in the specified directory
    (files.filter(function (file) {
        return expectedFiles.indexOf(file) === -1;
    })).forEach(function (file) {
        it('"' + file + '" should NOT be present', function () {
            assert(false);
        });
    });

}

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

function runTests() {

    describe('Test if all the expected files, and only them, are present in the build directories', function () {

        describe(dirs.archive, function () {
            checkFiles(dirs.archive, expectedFilesInArchiveDir);
        });

        describe(dirs.dist, function () {
            checkFiles(dirs.dist, expectedFilesInDistDir);
        });

    });

}

runTests();
<|endoftext|>


<commit_before>var columnDefs = [
    {headerName: "Athlete", field: "athlete", enableRowGroup: true, rowGroupIndex: 1},
    {headerName: "Age", field: "age", enableRowGroup: true},
    {headerName: "Country", field: "country", enableRowGroup: true},
    {headerName: "Year", field: "year", enableRowGroup: true},
    {headerName: "Sport", field: "sport", enableRowGroup: true},
    {headerName: "Gold", field: "gold", aggFunc: 'sum'},
    {headerName: "Silver", field: "silver", aggFunc: 'sum'},
    {headerName: "Bronze", field: "bronze", aggFunc: 'sum'}
];

var gridOptions = {
    defaultColDef: {
        suppressFilter: true,
        width: 100
    },
    rowBuffer: 0,
    columnDefs: columnDefs,
    enableColResize: true,
    rowModelType: 'enterprise',
    rowGroupPanelShow: 'always',
    animateRows: true,
    debug: true,
    showToolPanel: true,
    // restrict to 2 server side calls concurrently
    maxConcurrentDatasourceRequests: 2,
    infiniteBlockSize: 100,
    maxPagesInCache: 2,
    onGridReady: function(params) {
        params.api.sizeColumnsToFit();
    }
};

function EnterpriseDatasource(fakeServer) {
    this.fakeServer = fakeServer;
}

EnterpriseDatasource.prototype.getRows = function(params) {
    // console.log('EnterpriseDatasource.getRows: params = ', params);
    this.fakeServer.getData(params.request,
        function successCallback(resultForGrid, lastRow) {
            params.successCallback(resultForGrid, lastRow);
        });
};

function FakeServer(allData) {
    this.allData = allData;
}

FakeServer.prototype.getData = function(request, callback) {

    // the row group cols, ie teh cols that the user has dragged into the
    // 'group by' zone, eg 'Country' and 'Year'
    var rowGroupCols = request.rowGroupCols;
    // the keys we are looking at. will be empty if looking at top level (either
    // no groups, or looking at top level groups). eg ['United States','2002']
    var groupKeys = request.groupKeys;
    // if going aggregation, contains the value columns, eg ['gold','silver','bronze']
    var valueCols = request.valueCols;

    // we are not doing sorting and filtering in this example, but if you did
    // want to sort or filter using your implementation, you would do it here.
    var filterModel = request.filterModel;
    var sortModel = request.sortModel;

    var result;

    // if not grouping, just return the full set
    if (rowGroupCols.length===0) {
        result = this.allData;
    } else {
        // otherwise if grouping, a few steps...

        // first, if not the top level, take out everything that is not under the group
        // we are looking at.
        var filteredData = this.filterOutOtherGroups(this.allData, groupKeys, rowGroupCols);

        // if grouping, return the group
        var showingGroups = rowGroupCols.length > groupKeys.length;

        if (showingGroups) {
            result = this.buildGroupsFromData(filteredData, rowGroupCols, groupKeys, valueCols);
        } else {
            // show all remaining leaf level rows
            result = filteredData;
        }
    }

    // we mimic finding the last row. if the request exceeds the length of the
    // list, then we assume the last row is found. this would be similar to hitting
    // a database, where we have gone past the last row.
    var lastRowFound = (result.length <= request.endRow);
    var lastRow = lastRowFound ? result.length : null;

    // if using blocks, only return back the subset
    var result = result.slice(request.startRow, request.endRow);

    // so that the example behaves like a server side call, we put
    // it in a timeout to a) give a delay and b) make it asynchronous
    setTimeout( function() {
        callback(result, lastRow);
    }, 200);
};

FakeServer.prototype.buildGroupsFromData = function(filteredData, rowGroupCols, groupKeys, valueCols) {
    var rowGroupCol = rowGroupCols[groupKeys.length];
    var field = rowGroupCol.field;
    var mappedValues = this.groupBy(filteredData, field);
    var listOfKeys = Object.keys(mappedValues);
    var groups = [];
    listOfKeys.forEach(function(key) {
        var groupItem = {};
        groupItem[field] = key;

        valueCols.forEach(function(valueCol) {
            var field = valueCol.field;
            var sum = 0;
            mappedValues[key].forEach( function(childItem) {
                sum += childItem[field];
            });
            groupItem[field] = sum;
        });

        groups.push(groupItem)
    });
    return groups;
};

// if user is down some group levels, we take everything else out. eg
// if user has opened the two groups United States and 2002, we filter
// out everything that is not equal to United States and 2002.
FakeServer.prototype.filterOutOtherGroups = function(originalData, groupKeys, rowGroupCols) {
    var filteredData = originalData;
    var that = this;

    // if we are inside a group, then filter out everything that is not
    // part of this group
    groupKeys.forEach(function(groupKey, index) {
        var rowGroupCol = rowGroupCols[index];
        var field = rowGroupCol.field;

        filteredData = that.filter(filteredData, function(item) {
            return item[field] == groupKey;
        });
    });

    return filteredData;
};

// simple implementation of lodash groupBy
FakeServer.prototype.groupBy = function(data, field) {
    var result = {};
    data.forEach( function(item) {
        var key = item[field];
        var listForThisKey = result[key];
        if (!listForThisKey) {
            listForThisKey = [];
            result[key] = listForThisKey;
        }
        listForThisKey.push(item);
    });
    return result;
};

// simple implementation of lodash filter
FakeServer.prototype.filter = function(data, callback) {
    var result = [];
    data.forEach( function(item) {
        if (callback(item)) {
            result.push(item);
        }
    });
    return result;
};

// setup the grid after the page has finished loading
document.addEventListener('DOMContentLoaded', function() {
    var gridDiv = document.querySelector('#myGrid');
    new agGrid.Grid(gridDiv, gridOptions);

    // do http request to get our sample data - not using any framework to keep the example self contained.
    // you will probably use a framework like JQuery, Angular or something else to do your HTTP calls.
    agGrid.simpleHttpRequest({url: '../olympicWinners.json'})
        .then( function(rows) {
            var fakeServer = new FakeServer(rows);
            var datasource = new EnterpriseDatasource(fakeServer);
            gridOptions.api.setEnterpriseDatasource(datasource);
        }
    );
});
<commit_msg>iteration of enterprise row model<commit_after>var columnDefs = [
    {headerName: "Athlete", field: "athlete", enableRowGroup: true, rowGroupIndex: 1},
    {headerName: "Age", field: "age", enableRowGroup: true},
    {headerName: "Country", field: "country", enableRowGroup: true},
    {headerName: "Year", field: "year", enableRowGroup: true},
    {headerName: "Sport", field: "sport", enableRowGroup: true},
    {headerName: "Gold", field: "gold", aggFunc: 'sum'},
    {headerName: "Silver", field: "silver", aggFunc: 'sum'},
    {headerName: "Bronze", field: "bronze", aggFunc: 'sum'}
];

var gridOptions = {
    defaultColDef: {
        suppressFilter: true,
        width: 100
    },
    rowBuffer: 0,
    columnDefs: columnDefs,
    enableColResize: true,
    rowModelType: 'enterprise',
    rowGroupPanelShow: 'always',
    animateRows: true,
    debug: true,
    showToolPanel: true,
    // restrict to 2 server side calls concurrently
    maxConcurrentDatasourceRequests: 2,
    infiniteBlockSize: 100,
    maxPagesInCache: 2,
    purgeClosedRowNodes: true,
    onGridReady: function(params) {
        params.api.sizeColumnsToFit();
    }
};

function EnterpriseDatasource(fakeServer) {
    this.fakeServer = fakeServer;
}

EnterpriseDatasource.prototype.getRows = function(params) {
    // console.log('EnterpriseDatasource.getRows: params = ', params);
    this.fakeServer.getData(params.request,
        function successCallback(resultForGrid, lastRow) {
            params.successCallback(resultForGrid, lastRow);
        });
};

function FakeServer(allData) {
    this.allData = allData;
}

FakeServer.prototype.getData = function(request, callback) {

    // the row group cols, ie teh cols that the user has dragged into the
    // 'group by' zone, eg 'Country' and 'Year'
    var rowGroupCols = request.rowGroupCols;
    // the keys we are looking at. will be empty if looking at top level (either
    // no groups, or looking at top level groups). eg ['United States','2002']
    var groupKeys = request.groupKeys;
    // if going aggregation, contains the value columns, eg ['gold','silver','bronze']
    var valueCols = request.valueCols;

    // we are not doing sorting and filtering in this example, but if you did
    // want to sort or filter using your implementation, you would do it here.
    var filterModel = request.filterModel;
    var sortModel = request.sortModel;

    var result;

    // if not grouping, just return the full set
    if (rowGroupCols.length===0) {
        result = this.allData;
    } else {
        // otherwise if grouping, a few steps...

        // first, if not the top level, take out everything that is not under the group
        // we are looking at.
        var filteredData = this.filterOutOtherGroups(this.allData, groupKeys, rowGroupCols);

        // if grouping, return the group
        var showingGroups = rowGroupCols.length > groupKeys.length;

        if (showingGroups) {
            result = this.buildGroupsFromData(filteredData, rowGroupCols, groupKeys, valueCols);
        } else {
            // show all remaining leaf level rows
            result = filteredData;
        }
    }

    // we mimic finding the last row. if the request exceeds the length of the
    // list, then we assume the last row is found. this would be similar to hitting
    // a database, where we have gone past the last row.
    var lastRowFound = (result.length <= request.endRow);
    var lastRow = lastRowFound ? result.length : null;

    // if using blocks, only return back the subset
    var result = result.slice(request.startRow, request.endRow);

    // so that the example behaves like a server side call, we put
    // it in a timeout to a) give a delay and b) make it asynchronous
    setTimeout( function() {
        callback(result, lastRow);
    }, 200);
};

FakeServer.prototype.buildGroupsFromData = function(filteredData, rowGroupCols, groupKeys, valueCols) {
    var rowGroupCol = rowGroupCols[groupKeys.length];
    var field = rowGroupCol.field;
    var mappedValues = this.groupBy(filteredData, field);
    var listOfKeys = Object.keys(mappedValues);
    var groups = [];
    listOfKeys.forEach(function(key) {
        var groupItem = {};
        groupItem[field] = key;

        valueCols.forEach(function(valueCol) {
            var field = valueCol.field;
            var sum = 0;
            mappedValues[key].forEach( function(childItem) {
                sum += childItem[field];
            });
            groupItem[field] = sum;
        });

        groups.push(groupItem)
    });
    return groups;
};

// if user is down some group levels, we take everything else out. eg
// if user has opened the two groups United States and 2002, we filter
// out everything that is not equal to United States and 2002.
FakeServer.prototype.filterOutOtherGroups = function(originalData, groupKeys, rowGroupCols) {
    var filteredData = originalData;
    var that = this;

    // if we are inside a group, then filter out everything that is not
    // part of this group
    groupKeys.forEach(function(groupKey, index) {
        var rowGroupCol = rowGroupCols[index];
        var field = rowGroupCol.field;

        filteredData = that.filter(filteredData, function(item) {
            return item[field] == groupKey;
        });
    });

    return filteredData;
};

// simple implementation of lodash groupBy
FakeServer.prototype.groupBy = function(data, field) {
    var result = {};
    data.forEach( function(item) {
        var key = item[field];
        var listForThisKey = result[key];
        if (!listForThisKey) {
            listForThisKey = [];
            result[key] = listForThisKey;
        }
        listForThisKey.push(item);
    });
    return result;
};

// simple implementation of lodash filter
FakeServer.prototype.filter = function(data, callback) {
    var result = [];
    data.forEach( function(item) {
        if (callback(item)) {
            result.push(item);
        }
    });
    return result;
};

// setup the grid after the page has finished loading
document.addEventListener('DOMContentLoaded', function() {
    var gridDiv = document.querySelector('#myGrid');
    new agGrid.Grid(gridDiv, gridOptions);

    // do http request to get our sample data - not using any framework to keep the example self contained.
    // you will probably use a framework like JQuery, Angular or something else to do your HTTP calls.
    agGrid.simpleHttpRequest({url: '../olympicWinners.json'})
        .then( function(rows) {
            var fakeServer = new FakeServer(rows);
            var datasource = new EnterpriseDatasource(fakeServer);
            gridOptions.api.setEnterpriseDatasource(datasource);
        }
    );
});
<|endoftext|>


<commit_before>/**
 * The configuration object's layout version.
 */
const CURRENT_VERSION =
{
	major: 1,
	minor: 0,
	patch: 0
};
/**
 * Determines whether the specified object represents a valid version
 * object.
 *
 * @param obj
 *        The object to test.
 * @returns
 *        True iff the object is a valid version object.
 */
function is_valid_version_object(obj)
{
	/**
	 * Determines whether the specified object is a (non-strict) positive
	 * integer.
	 *
	 * @param obj
	 *        The object to test.
	 * @returns
	 *        True iff the object is a (non-strict) positive integer.
	 */
	function is_positive_integer(obj)
	{
		return Number.isInteger(obj) && obj >= 0;
	}
	return (
		is_positive_integer(obj.major) &&
		is_positive_integer(obj.minor) &&
		is_positive_integer(obj.patch)
	);
}
/**
 * Determines whether one version is greater, lesser, or equal than/to
 * another.
 *
 * @param first
 * 		The first version object.
 * @param second
 * 		The second version object.
 * @returns
 * 		A positive integer if first > second,
 *      a negative integer if first < second,
 *      and zero if first == second.
 */
function compare_versions(first, second)
{
	const
		GREATER = 1,
		LESSER = -1,
		EQUAL = 0;

	const
		parts_of_first = [first.major, first.minor, first.patch],
		parts_of_second = [second.major, second.minor, second.patch];

	for (let i = 0; i < 3; ++i)
	{
		const
			first_part = parts_of_first[i],
			second_part = parts_of_second[i];

		if (first_part > second_part)
		{
			return GREATER;
		}
		else if (first_part < second_part)
		{
			return LESSER;
		}
	}
	return EQUAL;
}

const module_interface =
{
	CURRENT_VERSION: CURRENT_VERSION,

	is_valid_version_object: is_valid_version_object,
	compare_versions: compare_versions
};
if (module !== 'undefined' &&
	module.exports !== 'undefined')  // support Node.js
{
	module.exports = exports = module_interface;
}
if (window !== 'undefined')  // support browser
{
	if (window.CustomNewTab === 'undefined')
	{
		window.CustomNewTab = {};
	}
	window.CustomNewTab.VersionInfo = module_interface;
}
<commit_msg>remove symbol export to window<commit_after>/**
 * The configuration object's layout version.
 */
const CURRENT_VERSION =
{
	major: 1,
	minor: 0,
	patch: 0
};
/**
 * Determines whether the specified object represents a valid version
 * object.
 *
 * @param obj
 *        The object to test.
 * @returns
 *        True iff the object is a valid version object.
 */
function is_valid_version_object(obj)
{
	/**
	 * Determines whether the specified object is a (non-strict) positive
	 * integer.
	 *
	 * @param obj
	 *        The object to test.
	 * @returns
	 *        True iff the object is a (non-strict) positive integer.
	 */
	function is_positive_integer(obj)
	{
		return Number.isInteger(obj) && obj >= 0;
	}
	return (
		is_positive_integer(obj.major) &&
		is_positive_integer(obj.minor) &&
		is_positive_integer(obj.patch)
	);
}
/**
 * Determines whether one version is greater, lesser, or equal than/to
 * another.
 *
 * @param first
 * 		The first version object.
 * @param second
 * 		The second version object.
 * @returns
 * 		A positive integer if first > second,
 *      a negative integer if first < second,
 *      and zero if first == second.
 */
function compare_versions(first, second)
{
	const
		GREATER = 1,
		LESSER = -1,
		EQUAL = 0;

	const
		parts_of_first = [first.major, first.minor, first.patch],
		parts_of_second = [second.major, second.minor, second.patch];

	for (let i = 0; i < 3; ++i)
	{
		const
			first_part = parts_of_first[i],
			second_part = parts_of_second[i];

		if (first_part > second_part)
		{
			return GREATER;
		}
		else if (first_part < second_part)
		{
			return LESSER;
		}
	}
	return EQUAL;
}

if (module !== 'undefined' &&
	module.exports !== 'undefined')  // support Node.js for testing purposes
{
	module.exports = exports =
	{
		CURRENT_VERSION: CURRENT_VERSION,

		is_valid_version_object: is_valid_version_object,
		compare_versions: compare_versions
	};
}<|endoftext|>


<commit_before>/**
 * Copyright (c) 2013-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule RelayFileWriter
 * @flow
 * @format
 */

'use strict';

const ASTConvert = require('ASTConvert');
const CodegenDirectory = require('CodegenDirectory');
const RelayCompiler = require('RelayCompiler');
const RelayCompilerContext = require('RelayCompilerContext');
const RelayFlowGenerator = require('RelayFlowGenerator');
const RelayValidator = require('RelayValidator');

const invariant = require('invariant');
const path = require('path');
const printFlowTypes = require('printFlowTypes');
const writeLegacyFlowFile = require('./writeLegacyFlowFile');
const writeRelayGeneratedFile = require('./writeRelayGeneratedFile');

const {isOperationDefinitionAST} = require('GraphQLSchemaUtils');
const {generate} = require('RelayCodeGenerator');
const {Map: ImmutableMap} = require('immutable');

import type {RelayGeneratedNode} from 'RelayCodeGenerator';
import type {FileWriterInterface} from 'RelayCodegenTypes';
import type {CompiledNode, CompiledDocumentMap} from 'RelayCompiler';
import type {CompilerTransforms} from 'RelayCompiler';
import type {GeneratedNode} from 'RelayConcreteNode';
import type {ScalarTypeMapping} from 'RelayFlowGenerator';
import type {DocumentNode, GraphQLSchema} from 'graphql';
import type {FormatModule} from 'writeRelayGeneratedFile';

export type GenerateExtraFiles = (
  getOutputDirectory: (path?: string) => CodegenDirectory,
  compilerContext: RelayCompilerContext,
) => void;

export type WriterConfig = {
  baseDir: string,
  formatModule: FormatModule,
  compilerTransforms: CompilerTransforms,
  customScalars?: ScalarTypeMapping,
  generateExtraFiles?: GenerateExtraFiles,
  outputDir?: string,
  persistQuery?: (text: string) => Promise<string>,
  platform?: string,
  fragmentsWithLegacyFlowTypes?: Set<string>,
  schemaExtensions: Array<string>,
  relayRuntimeModule?: string,
  inputFieldWhiteListForFlow?: Array<string>,
};

/* eslint-disable no-console-disallow */

class RelayFileWriter implements FileWriterInterface {
  _onlyValidate: boolean;
  _config: WriterConfig;
  _baseSchema: GraphQLSchema;
  _baseDocuments: ImmutableMap<string, DocumentNode>;
  _documents: ImmutableMap<string, DocumentNode>;

  constructor(options: {
    config: WriterConfig,
    onlyValidate: boolean,
    baseDocuments: ImmutableMap<string, DocumentNode>,
    documents: ImmutableMap<string, DocumentNode>,
    schema: GraphQLSchema,
  }) {
    const {config, onlyValidate, baseDocuments, documents, schema} = options;
    this._baseDocuments = baseDocuments || ImmutableMap();
    this._baseSchema = schema;
    this._config = config;
    this._documents = documents;
    this._onlyValidate = onlyValidate;

    validateConfig(this._config);
  }

  async writeAll(): Promise<Map<string, CodegenDirectory>> {
    const tStart = Date.now();

    // Can't convert to IR unless the schema already has Relay-local extensions
    const transformedSchema = ASTConvert.transformASTSchema(
      this._baseSchema,
      this._config.schemaExtensions,
    );
    const extendedSchema = ASTConvert.extendASTSchema(
      transformedSchema,
      this._baseDocuments.merge(this._documents).valueSeq().toArray(),
    );

    // Build a context from all the documents
    const baseDefinitionNames = new Set();
    this._baseDocuments.forEach(doc => {
      doc.definitions.forEach(def => {
        if (isOperationDefinitionAST(def) && def.name) {
          baseDefinitionNames.add(def.name.value);
        }
      });
    });
    const definitionDirectories = new Map();
    const allOutputDirectories: Map<string, CodegenDirectory> = new Map();
    const addCodegenDir = dirPath => {
      const codegenDir = new CodegenDirectory(dirPath, {
        onlyValidate: this._onlyValidate,
      });
      allOutputDirectories.set(dirPath, codegenDir);
      return codegenDir;
    };

    let configOutputDirectory;
    if (this._config.outputDir) {
      configOutputDirectory = addCodegenDir(this._config.outputDir);
    } else {
      this._documents.forEach((doc, filePath) => {
        doc.definitions.forEach(def => {
          if (isOperationDefinitionAST(def) && def.name) {
            definitionDirectories.set(
              def.name.value,
              path.join(this._config.baseDir, path.dirname(filePath)),
            );
          }
        });
      });
    }

    const definitions = ASTConvert.convertASTDocumentsWithBase(
      extendedSchema,
      this._baseDocuments.valueSeq().toArray(),
      this._documents.valueSeq().toArray(),
      // Verify using local and global rules, can run global verifications here
      // because all files are processed together
      [...RelayValidator.LOCAL_RULES, ...RelayValidator.GLOBAL_RULES],
    );

    const compilerContext = new RelayCompilerContext(extendedSchema);
    const compiler = new RelayCompiler(
      this._baseSchema,
      compilerContext,
      this._config.compilerTransforms,
      generate,
    );

    const getGeneratedDirectory = definitionName => {
      if (configOutputDirectory) {
        return configOutputDirectory;
      }
      const definitionDir = definitionDirectories.get(definitionName);
      invariant(
        definitionDir,
        'RelayFileWriter: Could not determine source directory for definition: %s',
        definitionName,
      );
      const generatedPath = path.join(definitionDir, '__generated__');
      let cachedDir = allOutputDirectories.get(generatedPath);
      if (!cachedDir) {
        cachedDir = addCodegenDir(generatedPath);
      }
      return cachedDir;
    };

    compiler.addDefinitions(definitions);

    const transformedFlowContext = RelayFlowGenerator.flowTransforms.reduce(
      (ctx, transform) => transform(ctx, extendedSchema),
      compiler.context(),
    );
    const transformedQueryContext = compiler.transformedQueryContext();
    const compiledDocumentMap: CompiledDocumentMap<
      RelayGeneratedNode,
    > = compiler.compile();

    const tCompiled = Date.now();

    let tGenerated;
    try {
      await Promise.all(
        transformedFlowContext.documents().map(async node => {
          if (baseDefinitionNames.has(node.name)) {
            // don't add definitions that were part of base context
            return;
          }
          if (
            this._config.fragmentsWithLegacyFlowTypes &&
            this._config.fragmentsWithLegacyFlowTypes.has(node.name)
          ) {
            const legacyFlowTypes = printFlowTypes(node);
            if (legacyFlowTypes) {
              writeLegacyFlowFile(
                getGeneratedDirectory(node.name),
                node.name,
                legacyFlowTypes,
                this._config.platform,
              );
            }
          }

          const flowTypes = RelayFlowGenerator.generate(
            node,
            this._config.customScalars,
            this._config.inputFieldWhiteListForFlow,
          );

          const compiledNode = compiledDocumentMap.get(node.name);
          invariant(
            compiledNode,
            'RelayCompiler: did not compile definition: %s',
            node.name,
          );
          await writeRelayGeneratedFile(
            getGeneratedDirectory(compiledNode.name),
            getGeneratedNode(compiledNode),
            this._config.formatModule,
            flowTypes,
            this._config.persistQuery,
            this._config.platform,
            this._config.relayRuntimeModule || 'relay-runtime',
          );
        }),
      );
      tGenerated = Date.now();

      if (this._config.generateExtraFiles) {
        const configDirectory = this._config.outputDir;
        invariant(
          configDirectory,
          'RelayFileWriter: cannot generate extra files without specifying ' +
            ' an outputDir in the config.',
        );

        this._config.generateExtraFiles(dir => {
          const outputDirectory = dir || configDirectory;
          let outputDir = allOutputDirectories.get(outputDirectory);
          if (!outputDir) {
            outputDir = addCodegenDir(outputDirectory);
          }
          return outputDir;
        }, transformedQueryContext);
      }

      // clean output directories
      allOutputDirectories.forEach(dir => {
        dir.deleteExtraFiles();
      });
    } catch (error) {
      tGenerated = Date.now();
      let details;
      try {
        details = JSON.parse(error.message);
      } catch (_) {}
      if (details && details.name === 'GraphQL2Exception' && details.message) {
        console.log('ERROR writing modules:\n' + details.message);
      } else {
        console.log('Error writing modules:\n' + error.toString());
      }
      return allOutputDirectories;
    }

    const tExtra = Date.now();
    console.log(
      'Writer time: %s [%s compiling, %s generating, %s extra]',
      toSeconds(tStart, tExtra),
      toSeconds(tStart, tCompiled),
      toSeconds(tCompiled, tGenerated),
      toSeconds(tGenerated, tExtra),
    );
    return allOutputDirectories;
  }
}

function getGeneratedNode(
  compiledNode: CompiledNode<RelayGeneratedNode>,
): GeneratedNode {
  invariant(
    typeof compiledNode === 'object' &&
      compiledNode !== null &&
      (compiledNode.kind === 'Fragment' || compiledNode.kind === 'Batch'),
    'getGeneratedNode: Expected a GeneratedNode, got `%s`.',
    JSON.stringify(compiledNode),
  );
  return (compiledNode: any);
}

function toSeconds(t0, t1) {
  return ((t1 - t0) / 1000).toFixed(2) + 's';
}

function validateConfig(config: Object): void {
  if (config.buildCommand) {
    process.stderr.write(
      'WARNING: RelayFileWriter: For RelayFileWriter to work you must ' +
        'replace config.buildCommand with config.formatModule.\n',
    );
  }
}

module.exports = RelayFileWriter;
<commit_msg>change invariant for generateExtraFiles<commit_after>/**
 * Copyright (c) 2013-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule RelayFileWriter
 * @flow
 * @format
 */

'use strict';

const ASTConvert = require('ASTConvert');
const CodegenDirectory = require('CodegenDirectory');
const RelayCompiler = require('RelayCompiler');
const RelayCompilerContext = require('RelayCompilerContext');
const RelayFlowGenerator = require('RelayFlowGenerator');
const RelayValidator = require('RelayValidator');

const invariant = require('invariant');
const path = require('path');
const printFlowTypes = require('printFlowTypes');
const writeLegacyFlowFile = require('./writeLegacyFlowFile');
const writeRelayGeneratedFile = require('./writeRelayGeneratedFile');

const {isOperationDefinitionAST} = require('GraphQLSchemaUtils');
const {generate} = require('RelayCodeGenerator');
const {Map: ImmutableMap} = require('immutable');

import type {RelayGeneratedNode} from 'RelayCodeGenerator';
import type {FileWriterInterface} from 'RelayCodegenTypes';
import type {CompiledNode, CompiledDocumentMap} from 'RelayCompiler';
import type {CompilerTransforms} from 'RelayCompiler';
import type {GeneratedNode} from 'RelayConcreteNode';
import type {ScalarTypeMapping} from 'RelayFlowGenerator';
import type {DocumentNode, GraphQLSchema} from 'graphql';
import type {FormatModule} from 'writeRelayGeneratedFile';

export type GenerateExtraFiles = (
  getOutputDirectory: (path?: string) => CodegenDirectory,
  compilerContext: RelayCompilerContext,
) => void;

export type WriterConfig = {
  baseDir: string,
  formatModule: FormatModule,
  compilerTransforms: CompilerTransforms,
  customScalars?: ScalarTypeMapping,
  generateExtraFiles?: GenerateExtraFiles,
  outputDir?: string,
  persistQuery?: (text: string) => Promise<string>,
  platform?: string,
  fragmentsWithLegacyFlowTypes?: Set<string>,
  schemaExtensions: Array<string>,
  relayRuntimeModule?: string,
  inputFieldWhiteListForFlow?: Array<string>,
};

/* eslint-disable no-console-disallow */

class RelayFileWriter implements FileWriterInterface {
  _onlyValidate: boolean;
  _config: WriterConfig;
  _baseSchema: GraphQLSchema;
  _baseDocuments: ImmutableMap<string, DocumentNode>;
  _documents: ImmutableMap<string, DocumentNode>;

  constructor(options: {
    config: WriterConfig,
    onlyValidate: boolean,
    baseDocuments: ImmutableMap<string, DocumentNode>,
    documents: ImmutableMap<string, DocumentNode>,
    schema: GraphQLSchema,
  }) {
    const {config, onlyValidate, baseDocuments, documents, schema} = options;
    this._baseDocuments = baseDocuments || ImmutableMap();
    this._baseSchema = schema;
    this._config = config;
    this._documents = documents;
    this._onlyValidate = onlyValidate;

    validateConfig(this._config);
  }

  async writeAll(): Promise<Map<string, CodegenDirectory>> {
    const tStart = Date.now();

    // Can't convert to IR unless the schema already has Relay-local extensions
    const transformedSchema = ASTConvert.transformASTSchema(
      this._baseSchema,
      this._config.schemaExtensions,
    );
    const extendedSchema = ASTConvert.extendASTSchema(
      transformedSchema,
      this._baseDocuments.merge(this._documents).valueSeq().toArray(),
    );

    // Build a context from all the documents
    const baseDefinitionNames = new Set();
    this._baseDocuments.forEach(doc => {
      doc.definitions.forEach(def => {
        if (isOperationDefinitionAST(def) && def.name) {
          baseDefinitionNames.add(def.name.value);
        }
      });
    });
    const definitionDirectories = new Map();
    const allOutputDirectories: Map<string, CodegenDirectory> = new Map();
    const addCodegenDir = dirPath => {
      const codegenDir = new CodegenDirectory(dirPath, {
        onlyValidate: this._onlyValidate,
      });
      allOutputDirectories.set(dirPath, codegenDir);
      return codegenDir;
    };

    let configOutputDirectory;
    if (this._config.outputDir) {
      configOutputDirectory = addCodegenDir(this._config.outputDir);
    } else {
      this._documents.forEach((doc, filePath) => {
        doc.definitions.forEach(def => {
          if (isOperationDefinitionAST(def) && def.name) {
            definitionDirectories.set(
              def.name.value,
              path.join(this._config.baseDir, path.dirname(filePath)),
            );
          }
        });
      });
    }

    const definitions = ASTConvert.convertASTDocumentsWithBase(
      extendedSchema,
      this._baseDocuments.valueSeq().toArray(),
      this._documents.valueSeq().toArray(),
      // Verify using local and global rules, can run global verifications here
      // because all files are processed together
      [...RelayValidator.LOCAL_RULES, ...RelayValidator.GLOBAL_RULES],
    );

    const compilerContext = new RelayCompilerContext(extendedSchema);
    const compiler = new RelayCompiler(
      this._baseSchema,
      compilerContext,
      this._config.compilerTransforms,
      generate,
    );

    const getGeneratedDirectory = definitionName => {
      if (configOutputDirectory) {
        return configOutputDirectory;
      }
      const definitionDir = definitionDirectories.get(definitionName);
      invariant(
        definitionDir,
        'RelayFileWriter: Could not determine source directory for definition: %s',
        definitionName,
      );
      const generatedPath = path.join(definitionDir, '__generated__');
      let cachedDir = allOutputDirectories.get(generatedPath);
      if (!cachedDir) {
        cachedDir = addCodegenDir(generatedPath);
      }
      return cachedDir;
    };

    compiler.addDefinitions(definitions);

    const transformedFlowContext = RelayFlowGenerator.flowTransforms.reduce(
      (ctx, transform) => transform(ctx, extendedSchema),
      compiler.context(),
    );
    const transformedQueryContext = compiler.transformedQueryContext();
    const compiledDocumentMap: CompiledDocumentMap<
      RelayGeneratedNode,
    > = compiler.compile();

    const tCompiled = Date.now();

    let tGenerated;
    try {
      await Promise.all(
        transformedFlowContext.documents().map(async node => {
          if (baseDefinitionNames.has(node.name)) {
            // don't add definitions that were part of base context
            return;
          }
          if (
            this._config.fragmentsWithLegacyFlowTypes &&
            this._config.fragmentsWithLegacyFlowTypes.has(node.name)
          ) {
            const legacyFlowTypes = printFlowTypes(node);
            if (legacyFlowTypes) {
              writeLegacyFlowFile(
                getGeneratedDirectory(node.name),
                node.name,
                legacyFlowTypes,
                this._config.platform,
              );
            }
          }

          const flowTypes = RelayFlowGenerator.generate(
            node,
            this._config.customScalars,
            this._config.inputFieldWhiteListForFlow,
          );

          const compiledNode = compiledDocumentMap.get(node.name);
          invariant(
            compiledNode,
            'RelayCompiler: did not compile definition: %s',
            node.name,
          );
          await writeRelayGeneratedFile(
            getGeneratedDirectory(compiledNode.name),
            getGeneratedNode(compiledNode),
            this._config.formatModule,
            flowTypes,
            this._config.persistQuery,
            this._config.platform,
            this._config.relayRuntimeModule || 'relay-runtime',
          );
        }),
      );
      tGenerated = Date.now();

      if (this._config.generateExtraFiles) {
        const configDirectory = this._config.outputDir;
        this._config.generateExtraFiles(dir => {
          const outputDirectory = dir || configDirectory;
          invariant(
            outputDirectory,
            'RelayFileWriter: cannot generate extra files without specifying ' +
              'an outputDir in the config or passing it in.',
          );
          let outputDir = allOutputDirectories.get(outputDirectory);
          if (!outputDir) {
            outputDir = addCodegenDir(outputDirectory);
          }
          return outputDir;
        }, transformedQueryContext);
      }

      // clean output directories
      allOutputDirectories.forEach(dir => {
        dir.deleteExtraFiles();
      });
    } catch (error) {
      tGenerated = Date.now();
      let details;
      try {
        details = JSON.parse(error.message);
      } catch (_) {}
      if (details && details.name === 'GraphQL2Exception' && details.message) {
        console.log('ERROR writing modules:\n' + details.message);
      } else {
        console.log('Error writing modules:\n' + error.toString());
      }
      return allOutputDirectories;
    }

    const tExtra = Date.now();
    console.log(
      'Writer time: %s [%s compiling, %s generating, %s extra]',
      toSeconds(tStart, tExtra),
      toSeconds(tStart, tCompiled),
      toSeconds(tCompiled, tGenerated),
      toSeconds(tGenerated, tExtra),
    );
    return allOutputDirectories;
  }
}

function getGeneratedNode(
  compiledNode: CompiledNode<RelayGeneratedNode>,
): GeneratedNode {
  invariant(
    typeof compiledNode === 'object' &&
      compiledNode !== null &&
      (compiledNode.kind === 'Fragment' || compiledNode.kind === 'Batch'),
    'getGeneratedNode: Expected a GeneratedNode, got `%s`.',
    JSON.stringify(compiledNode),
  );
  return (compiledNode: any);
}

function toSeconds(t0, t1) {
  return ((t1 - t0) / 1000).toFixed(2) + 's';
}

function validateConfig(config: Object): void {
  if (config.buildCommand) {
    process.stderr.write(
      'WARNING: RelayFileWriter: For RelayFileWriter to work you must ' +
        'replace config.buildCommand with config.formatModule.\n',
    );
  }
}

module.exports = RelayFileWriter;
<|endoftext|>


<commit_before>var util = require('util'),
    assert = require('assert'),
    vows = require('vows'),
    functions = require('../');

var N = 1024; // this is a bit silly

var OurError = function () {};
util.inherits(OurError, Error);

vows.describe('functions').addBatch({
  '`returns` function result': {
    topic: function () {
      return functions.returns(42);
      //
      // This is cause by a bug/feature in vows. When vows is given a function
      // as a topic, it executes it. Since our functions return functions, this
      // behavior results in unexpected results and has to be prevented.
      //
    },
    'should be a function': function (topic) {
      assert.isFunction(topic);
    },
    'should always return given value': function (topic) {
      for (var i = 0; i < N; i++) {
        assert.equal(topic(), 42);
      }
    }
  },
  '`throws` function result': {
    topic: function () {
      return functions.throws(new OurError('Expected error'));
    },
    'should be a function': function (topic) {
      assert.isFunction(topic);
    },
    'should always throw given error': function (topic) {
      for (var i = 0; i < N; i++) {
        assert.throws(topic, OurError);
      }
    }
  },
  '`throwsIfError` function result': {
    'without `exception` parameter': {
      topic: function () {
        return functions.throwsIfError();
      },
      'should be a function': function (topic) {
        assert.isFunction(topic);
      },
      "should always throw first parameter if it's truthy": function (topic) {
        for (var i = 0; i < N; i++) {
          assert.throws(topic.bind(topic, new OurError('Expected error')),
                        OurError);
        }
      },
      'should never throw if first parameter is falsy': function (topic) {
        for (var i = 0; i < N; i++) {
          assert.doesNotThrow(topic.bind(topic, false));
        }
      }
    },
    'with `exception` parameter': {
      topic: function () {
        return functions.throwsIfError(new OurError('Expected error'));
      },
      'should be a function': function (topic) {
        assert.isFunction(topic);
      },
      'should always throw provided error if first parameter is truthy': function (topic) {
        for (var i = 0; i < N; i++) {
          assert.throws(topic.bind(topic, true), OurError);
        }
      },
      'should never throw if first parameter is falsy': function (topic) {
        for (var i = 0; i < N; i++) {
          assert.doesNotThrow(topic.bind(topic, false), Error);
        }
      }
    }
  },
  '`noop` function': {
    topic: function () {
      return functions.noop;
    },
    'should be a function': function (topic) {
      assert.isFunction(topic);
    },
    'when called': {
      'should never return anything': function (result) {
        for (var i = 0; i < N; i++) {
          assert.isUndefined(result());
        }
      }
    }
  },
  '`eq` function': {
    topic: function () {
      return functions.eq;
    },
    'should be a function': function (topic) {
      assert.isFunction(topic);
    },
    'when called': {
      'with equal values': {
        topic: functions.eq(42, 42),
        'should return true': function (result) {
          assert.isTrue(result);
        }
      },
      'with equalish values': {
        topic: functions.eq('42', 42),
        'should return true': function (result) {
          assert.isTrue(result);
        }
      }
    }
  },
  '`strictEq` function': {
    topic: function () {
      return functions.strictEq;
    },
    'should be a function': function (topic) {
      assert.isFunction(topic);
    },
    'when called': {
      'with equal values': {
        topic: functions.strictEq(42, 42),
        'should return true': function (result) {
          assert.isTrue(result);
        }
      },
      'with equalish values': {
        topic: functions.strictEq('42', 42),
        'should return false': function (result) {
          assert.isFalse(result);
        }
      }
    }
  }
}).export(module);

<commit_msg>[test] Test `gt` function<commit_after>var util = require('util'),
    assert = require('assert'),
    vows = require('vows'),
    functions = require('../');

var N = 1024; // this is a bit silly

var OurError = function () {};
util.inherits(OurError, Error);

vows.describe('functions').addBatch({
  '`returns` function result': {
    topic: function () {
      return functions.returns(42);
      //
      // This is cause by a bug/feature in vows. When vows is given a function
      // as a topic, it executes it. Since our functions return functions, this
      // behavior results in unexpected results and has to be prevented.
      //
    },
    'should be a function': function (topic) {
      assert.isFunction(topic);
    },
    'should always return given value': function (topic) {
      for (var i = 0; i < N; i++) {
        assert.equal(topic(), 42);
      }
    }
  },
  '`throws` function result': {
    topic: function () {
      return functions.throws(new OurError('Expected error'));
    },
    'should be a function': function (topic) {
      assert.isFunction(topic);
    },
    'should always throw given error': function (topic) {
      for (var i = 0; i < N; i++) {
        assert.throws(topic, OurError);
      }
    }
  },
  '`throwsIfError` function result': {
    'without `exception` parameter': {
      topic: function () {
        return functions.throwsIfError();
      },
      'should be a function': function (topic) {
        assert.isFunction(topic);
      },
      "should always throw first parameter if it's truthy": function (topic) {
        for (var i = 0; i < N; i++) {
          assert.throws(topic.bind(topic, new OurError('Expected error')),
                        OurError);
        }
      },
      'should never throw if first parameter is falsy': function (topic) {
        for (var i = 0; i < N; i++) {
          assert.doesNotThrow(topic.bind(topic, false));
        }
      }
    },
    'with `exception` parameter': {
      topic: function () {
        return functions.throwsIfError(new OurError('Expected error'));
      },
      'should be a function': function (topic) {
        assert.isFunction(topic);
      },
      'should always throw provided error if first parameter is truthy': function (topic) {
        for (var i = 0; i < N; i++) {
          assert.throws(topic.bind(topic, true), OurError);
        }
      },
      'should never throw if first parameter is falsy': function (topic) {
        for (var i = 0; i < N; i++) {
          assert.doesNotThrow(topic.bind(topic, false), Error);
        }
      }
    }
  },
  '`noop` function': {
    topic: function () {
      return functions.noop;
    },
    'should be a function': function (topic) {
      assert.isFunction(topic);
    },
    'when called': {
      'should never return anything': function (result) {
        for (var i = 0; i < N; i++) {
          assert.isUndefined(result());
        }
      }
    }
  },
  '`eq` function': {
    topic: function () {
      return functions.eq;
    },
    'should be a function': function (topic) {
      assert.isFunction(topic);
    },
    'when called': {
      'with equal values': {
        topic: functions.eq(42, 42),
        'should return true': function (result) {
          assert.isTrue(result);
        }
      },
      'with equalish values': {
        topic: functions.eq('42', 42),
        'should return true': function (result) {
          assert.isTrue(result);
        }
      }
    }
  },
  '`strictEq` function': {
    topic: function () {
      return functions.strictEq;
    },
    'should be a function': function (topic) {
      assert.isFunction(topic);
    },
    'when called': {
      'with equal values': {
        topic: functions.strictEq(42, 42),
        'should return true': function (result) {
          assert.isTrue(result);
        }
      },
      'with equalish values': {
        topic: functions.strictEq('42', 42),
        'should return false': function (result) {
          assert.isFalse(result);
        }
      }
    }
  },
  '`gt` function': {
    topic: function () {
      return functions.gt;
    },
    'should be a function': function (topic) {
      assert.isFunction(topic);
    },
    'when called': {
      'with first argument greater than second': {
        topic: functions.gt(42, -42),
        'should return true': function (result) {
          assert.isTrue(result);
        }
      },
      'with first argument less than second': {
        topic: functions.gt(42, 84),
        'should return false': function (result) {
          assert.isFalse(result);
        }
      },
      'with equal arguments': {
        topic: functions.gt(42, 42),
        'should return false': function (result) {
          assert.isFalse(result);
        }
      }
    }
  }
}).export(module);

<|endoftext|>


<commit_before>/* @flow */
import ConnectionBase from './base';

class ConnectionSubscriber extends ConnectionBase {
  connect() {
    this.role = 'downstream';
    if (this.options && this.options.multistream) {
      return this._multiStream();
    }
    else {
      return this._singleStream();
    }
  }
  _singleStream() {
    return this.disconnect()
      .then(this._createOffer)
      .then(this._signaling.bind(this))
      .then(this._connectPeerConnection.bind(this))
      .then(message => {
        if (typeof this._pc.ontrack === 'undefined') {
          this._pc.onaddstream = function(event) {
            this.stream = event.stream;
          }.bind(this);
        }
        else {
          this._pc.ontrack = function(event) {
            this.stream = event.streams[0];
          }.bind(this);
        }
        return this._setRemoteDescription(message);
      })
      .then(this._createAnswer.bind(this))
      .then(this._sendAnswer.bind(this))
      .then(this._onIceCandidate.bind(this))
      .then(() => {
        return this.stream;
      });
  }

  _multiStream() {
    return this.disconnect()
      .then(this._createOffer)
      .then(this._signaling.bind(this))
      .then(this._connectPeerConnection.bind(this))
      .then(message => {
        if (typeof this._pc.ontrack === 'undefined') {
          this._pc.onaddstream = event => {
            this._callbacks.addstream(event);
          };
        } else {
          this._pc.ontrack = event => {
            const stream = event.streams[0];
            if (stream.id === 'default') return;
            if (stream.id === this.clientId) return;
            if (event.track.kind === 'video') {
              event.stream = stream;
              this._callbacks.addstream(event);
            }
          };
        }
        this._pc.onremovestream = event => {
          this._callbacks.removestream(event);
        };
        return this._setRemoteDescription(message);
      })
      .then(this._createAnswer.bind(this))
      .then(this._sendAnswer.bind(this))
      .then(this._onIceCandidate.bind(this));
  }
}

module.exports = ConnectionSubscriber;
<commit_msg>video のみではなく audio でも ontrack が発火する仕組みに修正する<commit_after>/* @flow */
import ConnectionBase from './base';

class ConnectionSubscriber extends ConnectionBase {
  connect() {
    this.role = 'downstream';
    if (this.options && this.options.multistream) {
      return this._multiStream();
    }
    else {
      return this._singleStream();
    }
  }
  _singleStream() {
    return this.disconnect()
      .then(this._createOffer)
      .then(this._signaling.bind(this))
      .then(this._connectPeerConnection.bind(this))
      .then(message => {
        if (typeof this._pc.ontrack === 'undefined') {
          this._pc.onaddstream = function(event) {
            this.stream = event.stream;
          }.bind(this);
        }
        else {
          this._pc.ontrack = function(event) {
            this.stream = event.streams[0];
          }.bind(this);
        }
        return this._setRemoteDescription(message);
      })
      .then(this._createAnswer.bind(this))
      .then(this._sendAnswer.bind(this))
      .then(this._onIceCandidate.bind(this))
      .then(() => {
        return this.stream;
      });
  }

  _multiStream() {
    return this.disconnect()
      .then(this._createOffer)
      .then(this._signaling.bind(this))
      .then(this._connectPeerConnection.bind(this))
      .then(message => {
        if (typeof this._pc.ontrack === 'undefined') {
          this._pc.onaddstream = event => {
            this._callbacks.addstream(event);
          };
        } else {
          this._pc.ontrack = event => {
            const stream = event.streams[0];
            if (stream.id === 'default') return;
            if (stream.id === this.clientId) return;
            if (-1 < this.remoteClientIds.indexOf(stream.id)) return;
            event.stream = stream;
            this.remoteClientIds.push(stream.id);
            this._callbacks.addstream(event);
          };
        }
        this._pc.onremovestream = event => {
          this._callbacks.removestream(event);
        };
        return this._setRemoteDescription(message);
      })
      .then(this._createAnswer.bind(this))
      .then(this._sendAnswer.bind(this))
      .then(this._onIceCandidate.bind(this));
  }
}

module.exports = ConnectionSubscriber;
<|endoftext|>