<commit_before>describe("customSelect", function () {
  var select,
      customSelect;

  beforeEach(function () {
    resetSingle();
  });

  afterEach(function () {
    destroy();
  });

  describe("interaction", function () {
    it("it should open and close upon mouse click", function () {
      clickWindow();
      expect(isOpen()).toBeTruthy();
      $('body').click();
      expect(isOpen()).toBeFalsy();
    });
    it("should not close when the click event is on the dropdown", function () {
      clickWindow();
      expect(isOpen()).toBeTruthy();
      customSelect.find('ul>li:first-child').click();
      expect(isOpen()).toBeTruthy();
    });
    it("should respect the enable and disable methods", function () {
      var blurCallback = jasmine.createSpy();

      select.bind('customselectblur', blurCallback);
      clickWindow();
      expect(isOpen()).toBeTruthy();
      select.customSelect("disable");
      expect(isOpen()).toBeFalsy(); // disabling should close the dropdown
      expect(blurCallback).toHaveBeenCalled(); // and it should fire a blur event since the dropdown was open

      clickWindow();
      expect(isOpen()).toBeFalsy(); // and a click shouldn't open it

      select.customSelect("enable");
      clickWindow();
      expect(isOpen()).toBeTruthy(); // can open now that it's enabled
    });
    it("should not fire a blur event if disabled when the dropdown is closed", function () {
      var blurCallback = jasmine.createSpy();

      select.bind('customselectblur', blurCallback);
      expect(isOpen()).toBeFalsy();
      select.customSelect("disable");
      expect(blurCallback).not.toHaveBeenCalled(); // and it should fire a blur event since the dropdown was open
    })
  });

  describe("events", function () {
    it("should fire a change event on the native select and customSelect", function () {
      var changeCallback = jasmine.createSpy();

      select.bind('change', changeCallback);
      select.bind('customselectchange', changeCallback);

      clickWindow();
      customSelect.find('ul>li:first-child input').attr('checked', true).change();

      expect(changeCallback.callCount).toBe(2);
    });
    it("should fire a focus and blur event", function () {
      var blurCallback = jasmine.createSpy(),
          focusCallback = jasmine.createSpy();

      select.bind('customselectblur', blurCallback);
      select.bind('customselectfocus', focusCallback);

      clickWindow();
      expect(focusCallback).toHaveBeenCalled();
      clickWindow();
      expect(blurCallback).toHaveBeenCalled();
    });
    it("should fire a blur event when the dropdown is open and something else is clicked", function () {
      var blurCallback = jasmine.createSpy();

      clickWindow();
      select.bind('customselectblur', blurCallback);
      $('body').click();
      expect(isOpen()).toBeFalsy();
      expect(blurCallback).toHaveBeenCalled();
    });
  });

  describe("single select mode", function () {
    describe("creation", function () {
      it("should create a series of radio buttons for a select element", function () {
        var selectOptions = select.children('option').map(function () {
              return this.value;
            }).toArray(),
            customSelectOptions = customSelect.find('input[type=radio]').map(function () {
              return this.value;
            }).toArray();

        expect(customSelectOptions).toEqual(selectOptions);
      });
      it("should select whatever was initially selected in the native select", function () {
        expect(select.val()).toEqual(select.customSelect("getVal"));
      });
      it("should put the default item text in the window", function () {
        expect(windowText()).toBe(select.children().eq(1).html());
      });
    });
    describe("interaction", function () {
      it("should place the selected value in the window", function () {
        var selectedItem = customSelect.find('li:nth-child(3)>input').attr('checked', true).change();
        expect(windowText()).toBe(selectedItem.next().html());
      });
    });
    describe("value", function () {
      it("the value can be retrieved in an array by calling val/getVal on the native or custom select", function () {
        expect(select.val()).toEqual('1p');
        expect(select.customSelect("getVal")).toEqual('1p');

        customSelect.find('li>input').eq(2).attr('checked', true).change();
        expect(select.val()).toEqual('2p');
        expect(select.customSelect("getVal")).toEqual('2p');
      });
    });

    it("should be possible to remove options from the list", function () {
      select.children().eq(1).remove();
      select.customSelect("reload");

      var selectOptions = select.children('option').map(function () {
            return this.value;
          }).toArray(),
          customSelectOptions = customSelect.find('input[type=radio]').map(function () {
            return this.value;
          }).toArray();

      expect(customSelectOptions).toEqual(selectOptions);
    });

    it("should be possible to add options to the list", function () {
      select.append('<option name="10p">10+</option');
      select.customSelect("reload");

      var selectOptions = select.children('option').map(function () {
            return this.value;
          }).toArray(),
          customSelectOptions = customSelect.find('input[type=radio]').map(function () {
            return this.value;
          }).toArray();

      expect(customSelectOptions).toEqual(selectOptions);
    });
  });

  describe("multi select mode", function () {
    beforeEach(function () {
      destroy();
      resetMultipleSelected(); // make a multiple select
    });

    describe("creation", function () {
      it("should create a series of checkboxes for a select=multiple element", function () {
        var selectOptions = select.children('option').map(function () {
              return this.value;
            }).toArray(),
            customSelectOptions = customSelect.find('input[type=checkbox]').map(function () {
              return this.value;
            }).toArray();

        expect(customSelectOptions).toEqual(selectOptions);
      });
      it("should select whatever was initially selected in the native select", function () {
        expect(select.val()).toEqual(select.customSelect("getVal"));
      });
      it("should display the placeholder text if no items were selected at creation", function () {
        destroy();
        resetMultipleNoneSelected();
        expect(windowText()).toBe('Please select some items');
      });
      it("should display the default item if no items were selected at creation", function () {
        destroy();
        resetMultipleNoneSelected({
          defaultValue: '2p'
        });
        expect(windowText()).toBe('2+');
        expect(select.val()).toEqual(['2p']);
      });
    });
    describe("interaction", function () {
      it("should display placeholder text if all items were unchecked", function () {
        customSelect.find('li>input:checked').attr('checked', false).change();
        expect(windowText()).toBe('Please select some items');
      });
      it("should default to a certain value if all items were unchecked", function () {
        destroy();
        resetMultipleSelected({
          defaultValue: '2p'
        });

        customSelect.find('li>input:checked').attr('checked', false).change();
        expect(select.val()).toEqual(['2p']);
        expect(select.customSelect("getVal")).toEqual(['2p']);
      });
      it("should place a comma separated list of selected items in the window", function () {
        expect(windowText()).toBe('1+, 3+');
        customSelect.find('li>input:checked').eq(1).attr('checked', false).change();
        expect(windowText()).toBe('1+');
      });
    });
    describe("value", function () {
      it("the value can be retrieved in an array by calling val/getVal on the native or custom select", function () {
        var expectedValue = ['1p', '3p'];

        expect(select.val()).toEqual(expectedValue);
        expect(select.customSelect("getVal")).toEqual(expectedValue);

        customSelect.find('li>input:checked').eq(1).attr('checked', false).change();
        expect(select.val()).toEqual(['1p']);
        expect(select.customSelect("getVal")).toEqual(['1p']);
      });
    });

    it("should be possible to remove options from the list", function () {
      select.children().eq(1).remove();
      select.customSelect("reload");

      var selectOptions = select.children('option').map(function () {
            return this.value;
          }).toArray(),
          customSelectOptions = customSelect.find('input[type=checkbox]').map(function () {
            return this.value;
          }).toArray();

      expect(customSelectOptions).toEqual(selectOptions);
    });

    it("should be possible to add options to the list", function () {
      select.append('<option name="10p">10+</option');
      select.customSelect("reload");

      var selectOptions = select.children('option').map(function () {
            return this.value;
          }).toArray(),
          customSelectOptions = customSelect.find('input[type=checkbox]').map(function () {
            return this.value;
          }).toArray();

      expect(customSelectOptions).toEqual(selectOptions);
    });
  });

  describe("custom range", function () {
    beforeEach(function () {
      destroy();
      resetSingle({
        customRange: true
      });
    });
    describe("creation", function () {
      it("should create a custom mix/max inputs when the option is specified", function () {
        expect(customSelect).toContain('.ui-customSelect-rangeContainer');
      });
      it("should not create mix/max inputs for a multiple select", function () {
        destroy();
        resetMultipleSelected({
          customRange: true
        });
        expect(customSelect).not.toContain('.ui-customSelect-rangeContainer');
      });
      it("should load the starting custom values if they are provided and display them in the window", function () {
        destroy();
        resetSingle({
          customRange: true,
          customRanges: {
            min: 1,
            max: 10
          }
        });

        expect(windowText()).toBe('1 to 10');
        expect(select.val()).toBe('1-10');
      });
    });
    describe("events", function () {
      it("should fire data validation callbacks", function () {
        var callback = jasmine.createSpy();

        select.bind('customselectrangechange', callback);

        fillValues(1, 10);
        rangeSubmit();

        expect(callback).toHaveBeenCalledWith(jasmine.any(Object), { min: '1', max: '10', widget: jasmine.any(Object)});
      });
      it("should fire change events on the native select", function () {
        var callback = jasmine.createSpy();

        select.bind('change', callback);

        fillValues(1, 10);
        rangeSubmit();

        expect(callback).toHaveBeenCalled()
      });
    });
    describe("interaction", function () {
      it("should submit the custom values upon pressing enter", function () {
        fillValues(1, 10);
        rangeSubmit();
        expect(select.val()).toBe('1-10');
      });
      it("should pass the selected range through helper, returning the value and display value", function () {
        destroy();
        resetSingle({
          customRange: true,
          customRangeHelper: function(){
            return ['dataValue', 'displayValue'];
          }
        });
        fillValues(1, 10);
        rangeSubmit();
        expect(select.val()).toBe('dataValue');
        expect(windowText()).toBe('displayValue');
      });
      it("should place the range in the window", function () {
        fillValues(1, 10);
        rangeSubmit();
        expect(windowText()).toBe('1 to 10');
      });
      it("should uncheck all the radio boxes", function () {
        var selectedItem = customSelect.find('li:nth-child(3)>input').attr('checked', true).change();

        expect(selectedItem).toBeChecked();
        fillValues(1, 10);
        rangeSubmit();
        expect(selectedItem).not.toBeChecked();
        expect(customSelect.find('input:checked')).not.toExist();
      });
      it("should not allow min to be bigger than max", function () {
        expect(select.val()).toBe('1p');
        fillValues(10, 1);
        rangeSubmit();
        expect(select.val()).toBe('1p');
        expect(customSelect.find('.ui-customSelect-error')).toBeVisible();
      });
      it("should hide error messages after a successful range", function () {
        expect(select.val()).toBe('1p');
        fillValues(10, 1);
        rangeSubmit();
        expect(select.val()).toBe('1p');
        expect(customSelect.find('.ui-customSelect-error')).toBeVisible();
        fillValues(1, 10);
        rangeSubmit();
        expect(select.val()).toBe('1-10');
        expect(customSelect.find('.ui-customSelect-error')).not.toBeVisible();
      });
      it("should show error messages from the data validation handlers", function () {
        select.bind('customselectrangechange', function (event, data) {
          data.widget.setCustomRangeError("LOLWUT");
          return false;
        });

        fillValues(1, 10);
        rangeSubmit();

        expect(customSelect.find('.ui-customSelect-error')).toBeVisible();
      });
      it("should have sane data and display values for various use cases", function () {
        // min and max set
        fillValues(1, 10);
        rangeSubmit();
        expect(select.val()).toBe('1-10');
        expect(windowText()).toBe('1 to 10');

        // min set, max not
        fillValues(100, '');
        rangeSubmit();
        expect(select.val()).toBe('100p');
        expect(windowText()).toBe('100+');

        // max set, min not,
        fillValues('', 100);
        rangeSubmit();
        expect(select.val()).toBe('0-100');
        expect(windowText()).toBe('0 to 100');

        // min == max
        fillValues(100, 100);
        rangeSubmit();
        expect(select.val()).toBe('100-100');
        expect(windowText()).toBe('100');
      });
    });
    describe("value", function () {
      it("should create an option in the native select with the custom data attribute and select it", function () {
        fillValues(1, 10);
        rangeSubmit();

        var newOption = select.find('option[data-custom]:last-child');
        expect(newOption).toExist();
        expect(newOption).toHaveValue("1-10");
      });
      it("calling val() on the native select should retrieve our custom value", function () {
        fillValues(1, 10);
        rangeSubmit();
        expect(select.val()).toBe("1-10");
      });
      it("calling getVal on the custom select should retrieve our custom value", function () {
        fillValues(1, 10);
        rangeSubmit();
        expect(select.customSelect("getVal")).toBe("1-10");
      });
    });

    /**
     * Custom range test helpers
     */
    function fillValues(min, max) {
      $('.ui-customSelect-min').val(min);
      $('.ui-customSelect-max').val(max);
    }

    function rangeSubmit() {
      var event = $.Event('keydown');
      event.which = 13;
      $('.ui-customSelect-min').trigger(event);
    };
  });

  it("should hide the native select upon creation", function () {
    expect($('#select').is(':visible')).toBeFalsy();
  });

  it("should show the native select upon destruction", function () {
    destroy();
    expect($('#select').is(':visible')).toBeTruthy();
  });

  /**
   * Test helpers
   */

  function resetSingle(options) {
    setFixtures('<select id="select"><option value="">Any</option><option selected value="1p">1+</option><option value="2p">2+</option><option value="3p">3+</option></select>');
    select = $('#select').customSelect(options || {});
    customSelect = $('#select_customSelect');
  }

  function resetMultipleSelected(options) {
    setFixtures('<select multiple id="select"><option value="">Any</option><option selected value="1p">1+</option><option value="2p">2+</option><option selected value="3p">3+</option></select>');
    select = $('#select').customSelect(options || {});
    customSelect = $('#select_customSelect');
  }

  function resetMultipleNoneSelected(options) {
    setFixtures('<select multiple id="select"><option value="">Any</option><option value="1p">1+</option><option value="2p">2+</option><option value="3p">3+</option></select>');
    select = $('#select').customSelect(options || {});
    customSelect = $('#select_customSelect');
  }

  function destroy() {
    $('select').customSelect('destroy');
  }

  function clickWindow() {
    customSelect.find('.ui-customSelect-window').click();
  }

  function isOpen() {
    return customSelect.hasClass('ui-customSelect-open');
  }

  function windowText() {
    return customSelect.find('.ui-customSelect-window span').html()
  }
});<commit_msg>Add test coverage for windowFormatter<commit_after>describe("customSelect", function () {
  var select,
      customSelect;

  beforeEach(function () {
    resetSingle();
  });

  afterEach(function () {
    destroy();
  });

  describe("interaction", function () {
    it("it should open and close upon mouse click", function () {
      clickWindow();
      expect(isOpen()).toBeTruthy();
      $('body').click();
      expect(isOpen()).toBeFalsy();
    });
    it("should not close when the click event is on the dropdown", function () {
      clickWindow();
      expect(isOpen()).toBeTruthy();
      customSelect.find('ul>li:first-child').click();
      expect(isOpen()).toBeTruthy();
    });
    it("should respect the enable and disable methods", function () {
      var blurCallback = jasmine.createSpy();

      select.bind('customselectblur', blurCallback);
      clickWindow();
      expect(isOpen()).toBeTruthy();
      select.customSelect("disable");
      expect(isOpen()).toBeFalsy(); // disabling should close the dropdown
      expect(blurCallback).toHaveBeenCalled(); // and it should fire a blur event since the dropdown was open

      clickWindow();
      expect(isOpen()).toBeFalsy(); // and a click shouldn't open it

      select.customSelect("enable");
      clickWindow();
      expect(isOpen()).toBeTruthy(); // can open now that it's enabled
    });
    it("should not fire a blur event if disabled when the dropdown is closed", function () {
      var blurCallback = jasmine.createSpy();

      select.bind('customselectblur', blurCallback);
      expect(isOpen()).toBeFalsy();
      select.customSelect("disable");
      expect(blurCallback).not.toHaveBeenCalled(); // and it should fire a blur event since the dropdown was open
    })
  });

  describe("events", function () {
    it("should fire a change event on the native select and customSelect", function () {
      var changeCallback = jasmine.createSpy();

      select.bind('change', changeCallback);
      select.bind('customselectchange', changeCallback);

      clickWindow();
      customSelect.find('ul>li:first-child input').attr('checked', true).change();

      expect(changeCallback.callCount).toBe(2);
    });
    it("should fire a focus and blur event", function () {
      var blurCallback = jasmine.createSpy(),
          focusCallback = jasmine.createSpy();

      select.bind('customselectblur', blurCallback);
      select.bind('customselectfocus', focusCallback);

      clickWindow();
      expect(focusCallback).toHaveBeenCalled();
      clickWindow();
      expect(blurCallback).toHaveBeenCalled();
    });
    it("should fire a blur event when the dropdown is open and something else is clicked", function () {
      var blurCallback = jasmine.createSpy();

      clickWindow();
      select.bind('customselectblur', blurCallback);
      $('body').click();
      expect(isOpen()).toBeFalsy();
      expect(blurCallback).toHaveBeenCalled();
    });
  });

  describe("single select mode", function () {
    describe("creation", function () {
      it("should create a series of radio buttons for a select element", function () {
        var selectOptions = select.children('option').map(function () {
              return this.value;
            }).toArray(),
            customSelectOptions = customSelect.find('input[type=radio]').map(function () {
              return this.value;
            }).toArray();

        expect(customSelectOptions).toEqual(selectOptions);
      });
      it("should select whatever was initially selected in the native select", function () {
        expect(select.val()).toEqual(select.customSelect("getVal"));
      });
      it("should put the default item text in the window", function () {
        expect(windowText()).toBe(select.children().eq(1).html());
      });
    });
    describe("interaction", function () {
      it("should place the selected value in the window", function () {
        var selectedItem = customSelect.find('li:nth-child(3)>input').attr('checked', true).change();
        expect(windowText()).toBe(selectedItem.next().html());
      });
      it("should run the window value through the formatter", function () {
        destroy();
        resetSingle({
          windowFormatter: function (value) {
            return 'LOLBUTTS-' + value;
          }
        });

        expect(select.val()).toBe('1p');
        expect(windowText()).toBe('LOLBUTTS-1+');
      });
    });
    describe("value", function () {
      it("the value can be retrieved in an array by calling val/getVal on the native or custom select", function () {
        expect(select.val()).toEqual('1p');
        expect(select.customSelect("getVal")).toEqual('1p');

        customSelect.find('li>input').eq(2).attr('checked', true).change();
        expect(select.val()).toEqual('2p');
        expect(select.customSelect("getVal")).toEqual('2p');
      });
    });

    it("should be possible to remove options from the list", function () {
      select.children().eq(1).remove();
      select.customSelect("reload");

      var selectOptions = select.children('option').map(function () {
            return this.value;
          }).toArray(),
          customSelectOptions = customSelect.find('input[type=radio]').map(function () {
            return this.value;
          }).toArray();

      expect(customSelectOptions).toEqual(selectOptions);
    });

    it("should be possible to add options to the list", function () {
      select.append('<option name="10p">10+</option');
      select.customSelect("reload");

      var selectOptions = select.children('option').map(function () {
            return this.value;
          }).toArray(),
          customSelectOptions = customSelect.find('input[type=radio]').map(function () {
            return this.value;
          }).toArray();

      expect(customSelectOptions).toEqual(selectOptions);
    });
  });

  describe("multi select mode", function () {
    beforeEach(function () {
      destroy();
      resetMultipleSelected(); // make a multiple select
    });

    describe("creation", function () {
      it("should create a series of checkboxes for a select=multiple element", function () {
        var selectOptions = select.children('option').map(function () {
              return this.value;
            }).toArray(),
            customSelectOptions = customSelect.find('input[type=checkbox]').map(function () {
              return this.value;
            }).toArray();

        expect(customSelectOptions).toEqual(selectOptions);
      });
      it("should select whatever was initially selected in the native select", function () {
        expect(select.val()).toEqual(select.customSelect("getVal"));
      });
      it("should display the placeholder text if no items were selected at creation", function () {
        destroy();
        resetMultipleNoneSelected();
        expect(windowText()).toBe('Please select some items');
      });
      it("should display the default item if no items were selected at creation", function () {
        destroy();
        resetMultipleNoneSelected({
          defaultValue: '2p'
        });
        expect(windowText()).toBe('2+');
        expect(select.val()).toEqual(['2p']);
      });
    });
    describe("interaction", function () {
      it("should display placeholder text if all items were unchecked", function () {
        customSelect.find('li>input:checked').attr('checked', false).change();
        expect(windowText()).toBe('Please select some items');
      });
      it("should default to a certain value if all items were unchecked", function () {
        destroy();
        resetMultipleSelected({
          defaultValue: '2p'
        });

        customSelect.find('li>input:checked').attr('checked', false).change();
        expect(select.val()).toEqual(['2p']);
        expect(select.customSelect("getVal")).toEqual(['2p']);
      });
      it("should place a comma separated list of selected items in the window", function () {
        expect(windowText()).toBe('1+, 3+');
        customSelect.find('li>input:checked').eq(1).attr('checked', false).change();
        expect(windowText()).toBe('1+');
      });
    });
    describe("value", function () {
      it("the value can be retrieved in an array by calling val/getVal on the native or custom select", function () {
        var expectedValue = ['1p', '3p'];

        expect(select.val()).toEqual(expectedValue);
        expect(select.customSelect("getVal")).toEqual(expectedValue);

        customSelect.find('li>input:checked').eq(1).attr('checked', false).change();
        expect(select.val()).toEqual(['1p']);
        expect(select.customSelect("getVal")).toEqual(['1p']);
      });
    });

    it("should be possible to remove options from the list", function () {
      select.children().eq(1).remove();
      select.customSelect("reload");

      var selectOptions = select.children('option').map(function () {
            return this.value;
          }).toArray(),
          customSelectOptions = customSelect.find('input[type=checkbox]').map(function () {
            return this.value;
          }).toArray();

      expect(customSelectOptions).toEqual(selectOptions);
    });

    it("should be possible to add options to the list", function () {
      select.append('<option name="10p">10+</option');
      select.customSelect("reload");

      var selectOptions = select.children('option').map(function () {
            return this.value;
          }).toArray(),
          customSelectOptions = customSelect.find('input[type=checkbox]').map(function () {
            return this.value;
          }).toArray();

      expect(customSelectOptions).toEqual(selectOptions);
    });
  });

  describe("custom range", function () {
    beforeEach(function () {
      destroy();
      resetSingle({
        customRange: true
      });
    });
    describe("creation", function () {
      it("should create a custom mix/max inputs when the option is specified", function () {
        expect(customSelect).toContain('.ui-customSelect-rangeContainer');
      });
      it("should not create mix/max inputs for a multiple select", function () {
        destroy();
        resetMultipleSelected({
          customRange: true
        });
        expect(customSelect).not.toContain('.ui-customSelect-rangeContainer');
      });
      it("should load the starting custom values if they are provided and display them in the window", function () {
        destroy();
        resetSingle({
          customRange: true,
          customRanges: {
            min: 1,
            max: 10
          }
        });

        expect(windowText()).toBe('1 to 10');
        expect(select.val()).toBe('1-10');
      });
    });
    describe("events", function () {
      it("should fire data validation callbacks", function () {
        var callback = jasmine.createSpy();

        select.bind('customselectrangechange', callback);

        fillValues(1, 10);
        rangeSubmit();

        expect(callback).toHaveBeenCalledWith(jasmine.any(Object), { min: '1', max: '10', widget: jasmine.any(Object)});
      });
      it("should fire change events on the native select", function () {
        var callback = jasmine.createSpy();

        select.bind('change', callback);

        fillValues(1, 10);
        rangeSubmit();

        expect(callback).toHaveBeenCalled()
      });
    });
    describe("interaction", function () {
      it("should submit the custom values upon pressing enter", function () {
        fillValues(1, 10);
        rangeSubmit();
        expect(select.val()).toBe('1-10');
      });
      it("should pass the selected range through helper, returning the value and display value", function () {
        destroy();
        resetSingle({
          customRange: true,
          customRangeHelper: function(){
            return ['dataValue', 'displayValue'];
          }
        });
        fillValues(1, 10);
        rangeSubmit();
        expect(select.val()).toBe('dataValue');
        expect(windowText()).toBe('displayValue');
      });
      it("should place the range in the window", function () {
        fillValues(1, 10);
        rangeSubmit();
        expect(windowText()).toBe('1 to 10');
      });
      it("should uncheck all the radio boxes", function () {
        var selectedItem = customSelect.find('li:nth-child(3)>input').attr('checked', true).change();

        expect(selectedItem).toBeChecked();
        fillValues(1, 10);
        rangeSubmit();
        expect(selectedItem).not.toBeChecked();
        expect(customSelect.find('input:checked')).not.toExist();
      });
      it("should not allow min to be bigger than max", function () {
        expect(select.val()).toBe('1p');
        fillValues(10, 1);
        rangeSubmit();
        expect(select.val()).toBe('1p');
        expect(customSelect.find('.ui-customSelect-error')).toBeVisible();
      });
      it("should hide error messages after a successful range", function () {
        expect(select.val()).toBe('1p');
        fillValues(10, 1);
        rangeSubmit();
        expect(select.val()).toBe('1p');
        expect(customSelect.find('.ui-customSelect-error')).toBeVisible();
        fillValues(1, 10);
        rangeSubmit();
        expect(select.val()).toBe('1-10');
        expect(customSelect.find('.ui-customSelect-error')).not.toBeVisible();
      });
      it("should show error messages from the data validation handlers", function () {
        select.bind('customselectrangechange', function (event, data) {
          data.widget.setCustomRangeError("LOLWUT");
          return false;
        });

        fillValues(1, 10);
        rangeSubmit();

        expect(customSelect.find('.ui-customSelect-error')).toBeVisible();
      });
      it("should have sane data and display values for various use cases", function () {
        // min and max set
        fillValues(1, 10);
        rangeSubmit();
        expect(select.val()).toBe('1-10');
        expect(windowText()).toBe('1 to 10');

        // min set, max not
        fillValues(100, '');
        rangeSubmit();
        expect(select.val()).toBe('100p');
        expect(windowText()).toBe('100+');

        // max set, min not,
        fillValues('', 100);
        rangeSubmit();
        expect(select.val()).toBe('0-100');
        expect(windowText()).toBe('0 to 100');

        // min == max
        fillValues(100, 100);
        rangeSubmit();
        expect(select.val()).toBe('100-100');
        expect(windowText()).toBe('100');
      });
    });
    describe("value", function () {
      it("should create an option in the native select with the custom data attribute and select it", function () {
        fillValues(1, 10);
        rangeSubmit();

        var newOption = select.find('option[data-custom]:last-child');
        expect(newOption).toExist();
        expect(newOption).toHaveValue("1-10");
      });
      it("calling val() on the native select should retrieve our custom value", function () {
        fillValues(1, 10);
        rangeSubmit();
        expect(select.val()).toBe("1-10");
      });
      it("calling getVal on the custom select should retrieve our custom value", function () {
        fillValues(1, 10);
        rangeSubmit();
        expect(select.customSelect("getVal")).toBe("1-10");
      });
    });

    /**
     * Custom range test helpers
     */
    function fillValues(min, max) {
      $('.ui-customSelect-min').val(min);
      $('.ui-customSelect-max').val(max);
    }

    function rangeSubmit() {
      var event = $.Event('keydown');
      event.which = 13;
      $('.ui-customSelect-min').trigger(event);
    };
  });

  it("should hide the native select upon creation", function () {
    expect($('#select').is(':visible')).toBeFalsy();
  });

  it("should show the native select upon destruction", function () {
    destroy();
    expect($('#select').is(':visible')).toBeTruthy();
  });

  /**
   * Test helpers
   */

  function resetSingle(options) {
    setFixtures('<select id="select"><option value="">Any</option><option selected value="1p">1+</option><option value="2p">2+</option><option value="3p">3+</option></select>');
    select = $('#select').customSelect(options || {});
    customSelect = $('#select_customSelect');
  }

  function resetMultipleSelected(options) {
    setFixtures('<select multiple id="select"><option value="">Any</option><option selected value="1p">1+</option><option value="2p">2+</option><option selected value="3p">3+</option></select>');
    select = $('#select').customSelect(options || {});
    customSelect = $('#select_customSelect');
  }

  function resetMultipleNoneSelected(options) {
    setFixtures('<select multiple id="select"><option value="">Any</option><option value="1p">1+</option><option value="2p">2+</option><option value="3p">3+</option></select>');
    select = $('#select').customSelect(options || {});
    customSelect = $('#select_customSelect');
  }

  function destroy() {
    $('select').customSelect('destroy');
  }

  function clickWindow() {
    customSelect.find('.ui-customSelect-window').click();
  }

  function isOpen() {
    return customSelect.hasClass('ui-customSelect-open');
  }

  function windowText() {
    return customSelect.find('.ui-customSelect-window span').html()
  }
});<|endoftext|>


<commit_before>exports.handlers = {
    beforeParse : function(e) {
        var classMatch = e.source.match(/\/\*\*[\s\S]*@class\s+(.*?)\s*$[\s\S]*?\*\//m);
        var className = classMatch ? classMatch[1] : null;

        if (className) {
            e.source = e.source.replace(/(.*?\s?=\s?.*?\.\$extend\(\X*?)(\{)/, "$1/** @lends sticky.StickyStructure */$2");
            e.source = e.source.replace(/@(member|event|fires|emits)\s+([a-zA-Z\._-]*?)\s*$/gm, "@$1 " + className + "#$2");
        }
    },
};
<commit_msg>Fix comment insertion bug<commit_after>exports.handlers = {
    beforeParse : function(e) {
        var classMatch = e.source.match(/\/\*\*[\s\S]*@class\s+(.*?)\s*$[\s\S]*?\*\//m);
        var className = classMatch ? classMatch[1] : null;

        if (className) {
            e.source = e.source.replace(/(.*?\s?=\s?.*?\.\$extend\(\X*?)(\{)/, "$1/** @lends " + className + " */$2");
            e.source = e.source.replace(/@(member|event|fires|emits)\s+([a-zA-Z\._-]*?)\s*$/gm, "@$1 " + className + "#$2");
        }

        console.log(e.source);
    },
};
<|endoftext|>


<commit_before>var _ = require('lodash')
var async = require('async')
var exec = require('child_process').exec
var gutil = require('gulp-util')
var path = require('path')
var through = require('through2')

var PLUGIN_NAME = 'gulp-shell'

function shell(commands, options) {
  if (typeof commands === 'string') {
    commands = [commands]
  }

  if (!Array.isArray(commands)) {
    throw new gutil.PluginError(PLUGIN_NAME, 'Missing commands')
  }

  options = _.extend({
    ignoreErrors: false,
    errorMessage: 'Command `<%= command %>` failed with exit code <%= error.code %>',
    quiet: false,
    cwd: process.cwd(),
    maxBuffer: 16 * 1024 * 1024
  }, options)

  var pathToBin = path.join(process.cwd(), 'node_modules/.bin')
  var PATH = pathToBin + path.delimiter + process.env.PATH
  options.env = _.extend({}, process.env, {PATH: PATH}, options.env)

  var stream = through.obj(function (file, unused, done) {
    var self = this

    async.eachSeries(commands, function (command, done) {
      var context = _.extend({file: file}, options.templateData)
      command = gutil.template(command, context)

      var child = exec(command, {
        env: options.env,
        cwd: options.cwd,
        maxBuffer: options.maxBuffer,
        timeout: options.timeout
      }, function (error, stdout, stderr) {
        process.stdin.unpipe(child.stdin)
        process.stdin.resume()
        process.stdin.pause()

        if (error && !options.ignoreErrors) {
          error.stdout = stdout
          error.stderr = stderr

          var errorContext = _.extend({
            command: command,
            file: file,
            error: error
          }, options.templateData)

          error.message = gutil.template(options.errorMessage, errorContext)
        }

        done(options.ignoreErrors ? null : error)
      })

      process.stdin.resume()
      process.stdin.setEncoding('utf8')
      process.stdin.pipe(child.stdin)

      if (!options.quiet) {
        child.stdout.pipe(process.stdout)
        child.stderr.pipe(process.stderr)
      }
    }, function (error) {
      if (error) {
        self.emit('error', new gutil.PluginError({
          plugin: PLUGIN_NAME,
          message: error.message
        }))
      } else {
        self.push(file)
      }
      done()
    })
  })

  stream.resume()

  return stream
}

shell.task = function (commands, options) {
  return function () {
    var stream = shell(commands, options)

    stream.write(new gutil.File())
    stream.end()

    return stream
  }
}

module.exports = shell
<commit_msg>Replace environment variable named Path instead of PATH on Windows<commit_after>var _ = require('lodash')
var async = require('async')
var exec = require('child_process').exec
var gutil = require('gulp-util')
var path = require('path')
var through = require('through2')

var PLUGIN_NAME = 'gulp-shell'

function shell(commands, options) {
  if (typeof commands === 'string') {
    commands = [commands]
  }

  if (!Array.isArray(commands)) {
    throw new gutil.PluginError(PLUGIN_NAME, 'Missing commands')
  }

  options = _.extend({
    ignoreErrors: false,
    errorMessage: 'Command `<%= command %>` failed with exit code <%= error.code %>',
    quiet: false,
    cwd: process.cwd(),
    maxBuffer: 16 * 1024 * 1024
  }, options)

  var pathToBin = path.join(process.cwd(), 'node_modules/.bin')
  var pathName = /^win/.test(process.platform) ? 'Path' : 'PATH'
  var newPath = pathToBin + path.delimiter + process.env[pathName]
  options.env = _.extend(process.env, _.object([[pathName, newPath]]), options.env)

  var stream = through.obj(function (file, unused, done) {
    var self = this

    async.eachSeries(commands, function (command, done) {
      var context = _.extend({file: file}, options.templateData)
      command = gutil.template(command, context)

      var child = exec(command, {
        env: options.env,
        cwd: options.cwd,
        maxBuffer: options.maxBuffer,
        timeout: options.timeout
      }, function (error, stdout, stderr) {
        process.stdin.unpipe(child.stdin)
        process.stdin.resume()
        process.stdin.pause()

        if (error && !options.ignoreErrors) {
          error.stdout = stdout
          error.stderr = stderr

          var errorContext = _.extend({
            command: command,
            file: file,
            error: error
          }, options.templateData)

          error.message = gutil.template(options.errorMessage, errorContext)
        }

        done(options.ignoreErrors ? null : error)
      })

      process.stdin.resume()
      process.stdin.setEncoding('utf8')
      process.stdin.pipe(child.stdin)

      if (!options.quiet) {
        child.stdout.pipe(process.stdout)
        child.stderr.pipe(process.stderr)
      }
    }, function (error) {
      if (error) {
        self.emit('error', new gutil.PluginError({
          plugin: PLUGIN_NAME,
          message: error.message
        }))
      } else {
        self.push(file)
      }
      done()
    })
  })

  stream.resume()

  return stream
}

shell.task = function (commands, options) {
  return function () {
    var stream = shell(commands, options)

    stream.write(new gutil.File())
    stream.end()

    return stream
  }
}

module.exports = shell
<|endoftext|>


<commit_before>/*!
 * jQuery Json Plugin (with Transition Definitions)
 * Examples and documentation at: http://json.cn/
 * Copyright (c) 2012-2013  China.Ren.
 * Version: 1.0.2 (19-OCT-2013)
 * Dual licensed under the MIT and GPL licenses.
 * http://jquery.malsup.com/license.html
 * Requires: jQuery v1.3.1 or later
 */
var JSONFormat = (function(){
    var _toString = Object.prototype.toString;
    var _bigNums = [];
    function format(object, indent_count){
        var html_fragment = '';
        switch(_typeof(object)){
            case 'Null' :0
                html_fragment = _format_null(object);
                break;
            case 'Boolean' :
                html_fragment = _format_boolean(object);
                break;
            case 'Number' :
                html_fragment = _format_number(object);
                break;
            case 'String' :
                html_fragment = _format_string(object);
                break;
            case 'Array' :
                html_fragment = _format_array(object, indent_count);
                break;
            case 'Object' :
                html_fragment = _format_object(object, indent_count);
                break;
        }
        return html_fragment;
    };

    function _format_null(object){
        return 'null';
    }

    function _format_boolean(object){
        return '' + object + '';
    }

    function _format_number(object){
        return '' + object + '';
    }

    function _format_string(object){
        if(!isNaN(object) && object.length>=15 && $.inArray(object, _bigNums)>-1){
            return _format_number(object);
        }
        object = object.replace(/\</g,"<");
        object = object.replace(/\>/g,">");
        if(0 <= object.search(/^http/)){
            object = '' + object + ''
        }
        return '"' + object + '"';
    }

    function _format_array(object, indent_count){
        var tmp_array = [];
        for(var i = 0, size = object.length; i < size; ++i){
            tmp_array.push(indent_tab(indent_count) + format(object[i], indent_count + 1));
        }
        return '[
'
            + tmp_array.join(',
')
            + '
' + indent_tab(indent_count - 1) + ']';
    }

    function _format_object(object, indent_count){
        var tmp_array = [];
        for(var key in object){
            tmp_array.push( indent_tab(indent_count) + '"' + key + '":' +  format(object[key], indent_count + 1));
        }
        return '{
'
            + tmp_array.join(',
')
            + '
' + indent_tab(indent_count - 1) + '}';
    }

    function indent_tab(indent_count){
        return (new Array(indent_count + 1)).join('    ');
    }

    function _typeof(object){
        var tf = typeof object,
            ts = _toString.call(object);
        return null === object ? 'Null' :
            'undefined' == tf ? 'Undefined'   :
                'boolean' == tf ? 'Boolean'   :
                    'number' == tf ? 'Number'   :
                        'string' == tf ? 'String'   :
                            '[object Function]' == ts ? 'Function' :
                                '[object Array]' == ts ? 'Array' :
                                    '[object Date]' == ts ? 'Date' : 'Object';
    };

    function loadCssString(){
        var style = document.createElement('style');
        style.type = 'text/css';
        var code = Array.prototype.slice.apply(arguments).join('');
        try{
            style.appendChild(document.createTextNode(code));
        }catch(ex){
            style.styleSheet.cssText = code;
        }
        document.getElementsByTagName('head')[0].appendChild(style);
    }

    loadCssString(
        '.json_key{ color: #92278f;font-weight:bold;}',
        '.json_null{color: #f1592a;font-weight:bold;}',
        '.json_string{ color: #3ab54a;font-weight:bold;}',
        '.json_number{ color: #25aae2;font-weight:bold;}',
        '.json_boolean{ color: #f98280;font-weight:bold;}',
        '.json_link{ color: #61D2D6;font-weight:bold;}',
        '.json_array_brackets{}');

    var _JSONFormat = function(origin_data){
        //this.data = origin_data ? origin_data :
            //JSON && JSON.parse ? JSON.parse(origin_data) : eval('(' + origin_data + ')');
        _bigNums = [];
        var check_data = origin_data.replace(/\s/g,'');
        var bigNum_regex = /[^\\][\"]([\[:]){1}(\d{16,})([,\}\]])/g;
        //var tmp_bigNums = check_data.match(bigNum_regex);
        var m;
        do {
            m = bigNum_regex.exec(check_data);
            if (m) {
              _bigNums.push(m[2]);
              origin_data=origin_data.replace(/([\[:])?(\d{16,})\s*([,\}\]])/, "$1\"$2\"$3");
            }
        } while (m);
        this.data = JSON.parse(origin_data);
    };

    _JSONFormat.prototype = {
        constructor : JSONFormat,
        toString : function(){
            return format(this.data, 1);
        }
    }

    return _JSONFormat;

})();
var last_html = '';
function hide(obj){
    var data_type = obj.parentNode.getAttribute('data-type');
    var data_size = obj.parentNode.getAttribute('data-size');
    obj.parentNode.setAttribute('data-inner',obj.parentNode.innerHTML);
    if (data_type === 'array') {
        obj.parentNode.innerHTML = 'Array[' + data_size + ']';
    }else{
        obj.parentNode.innerHTML = 'Object{...}';
    }

}

function show(obj){
    var innerHtml = obj.parentNode.getAttribute('data-inner');
    obj.parentNode.innerHTML = innerHtml;
}
<commit_msg>fix bug<commit_after>/*!
 * jQuery Json Plugin (with Transition Definitions)
 * Examples and documentation at: http://json.cn/
 * Copyright (c) 2012-2013  China.Ren.
 * Version: 1.0.2 (19-OCT-2013)
 * Dual licensed under the MIT and GPL licenses.
 * http://jquery.malsup.com/license.html
 * Requires: jQuery v1.3.1 or later
 */
var JSONFormat = (function(){
    var _toString = Object.prototype.toString;
    var _bigNums = [];
    function format(object, indent_count){
        var html_fragment = '';
        switch(_typeof(object)){
            case 'Null' :0
                html_fragment = _format_null(object);
                break;
            case 'Boolean' :
                html_fragment = _format_boolean(object);
                break;
            case 'Number' :
                html_fragment = _format_number(object);
                break;
            case 'String' :
                html_fragment = _format_string(object);
                break;
            case 'Array' :
                html_fragment = _format_array(object, indent_count);
                break;
            case 'Object' :
                html_fragment = _format_object(object, indent_count);
                break;
        }
        return html_fragment;
    };

    function _format_null(object){
        return 'null';
    }

    function _format_boolean(object){
        return '' + object + '';
    }

    function _format_number(object){
        return '' + object + '';
    }

    function _format_string(object){
        if(!isNaN(object) && object.length>=15 && $.inArray(object, _bigNums)>-1){
            return _format_number(object);
        }
        object = object.replace(/\</g,"<");
        object = object.replace(/\>/g,">");
        if(0 <= object.search(/^http/)){
            object = '' + object + ''
        }
        return '"' + object + '"';
    }

    function _format_array(object, indent_count){
        var tmp_array = [];
        for(var i = 0, size = object.length; i < size; ++i){
            tmp_array.push(indent_tab(indent_count) + format(object[i], indent_count + 1));
        }
        return '[
'
            + tmp_array.join(',
')
            + '
' + indent_tab(indent_count - 1) + ']';
    }

    function _format_object(object, indent_count){
        var tmp_array = [];
        for(var key in object){
            tmp_array.push( indent_tab(indent_count) + '"' + key + '":' +  format(object[key], indent_count + 1));
        }
        return '{
'
            + tmp_array.join(',
')
            + '
' + indent_tab(indent_count - 1) + '}';
    }

    function indent_tab(indent_count){
        return (new Array(indent_count + 1)).join('    ');
    }

    function _typeof(object){
        var tf = typeof object,
            ts = _toString.call(object);
        return null === object ? 'Null' :
            'undefined' == tf ? 'Undefined'   :
                'boolean' == tf ? 'Boolean'   :
                    'number' == tf ? 'Number'   :
                        'string' == tf ? 'String'   :
                            '[object Function]' == ts ? 'Function' :
                                '[object Array]' == ts ? 'Array' :
                                    '[object Date]' == ts ? 'Date' : 'Object';
    };

    function loadCssString(){
        var style = document.createElement('style');
        style.type = 'text/css';
        var code = Array.prototype.slice.apply(arguments).join('');
        try{
            style.appendChild(document.createTextNode(code));
        }catch(ex){
            style.styleSheet.cssText = code;
        }
        document.getElementsByTagName('head')[0].appendChild(style);
    }

    loadCssString(
        '.json_key{ color: #92278f;font-weight:bold;}',
        '.json_null{color: #f1592a;font-weight:bold;}',
        '.json_string{ color: #3ab54a;font-weight:bold;}',
        '.json_number{ color: #25aae2;font-weight:bold;}',
        '.json_boolean{ color: #f98280;font-weight:bold;}',
        '.json_link{ color: #61D2D6;font-weight:bold;}',
        '.json_array_brackets{}');

    var _JSONFormat = function(origin_data){
        //this.data = origin_data ? origin_data :
            //JSON && JSON.parse ? JSON.parse(origin_data) : eval('(' + origin_data + ')');
        _bigNums = [];
        var check_data = origin_data.replace(/\s/g,'');
        var bigNum_regex = /([\[:]){1}([-\.\d]{16,})([,\}\]])/g;
        //var tmp_bigNums = check_data.match(bigNum_regex);
        var m;
        do {
            m = bigNum_regex.exec(check_data);
            if (m) {
              _bigNums.push(m[2]);
              origin_data=origin_data.replace(/([\[:])?([-\.\d]{16,})\s*([,\}\]])/, "$1\"$2\"$3");
            }
        } while (m);
        this.data = JSON.parse(origin_data);
    };

    _JSONFormat.prototype = {
        constructor : JSONFormat,
        toString : function(){
            return format(this.data, 1);
        }
    }

    return _JSONFormat;

})();
var last_html = '';
function hide(obj){
    var data_type = obj.parentNode.getAttribute('data-type');
    var data_size = obj.parentNode.getAttribute('data-size');
    obj.parentNode.setAttribute('data-inner',obj.parentNode.innerHTML);
    if (data_type === 'array') {
        obj.parentNode.innerHTML = 'Array[' + data_size + ']';
    }else{
        obj.parentNode.innerHTML = 'Object{...}';
    }

}

function show(obj){
    var innerHtml = obj.parentNode.getAttribute('data-inner');
    obj.parentNode.innerHTML = innerHtml;
}
<|endoftext|>


<commit_before>describe('my app', function() {

  beforeEach(function() {
    browser().navigateTo('/');
  });

  it('should automatically redirect to /signin when location hash/fragment is empty', function() {
    expect(browser().location().path()).toBe("/dashboard");
  });

});<commit_msg>Fix e2e tests<commit_after>describe('my app', function() {

  beforeEach(function() {
    browser().navigateTo('/');
  });

  it('publicly accessible and default route to be /projectsinfo', function() {
    expect(browser().location().path()).toBe("/projectsinfo");
  });
});<|endoftext|>


<commit_before>var express, mongoose, nconf, bodyParser,
app, auth;

express = require('express');
mongoose = require('mongoose');
nconf = require('nconf');
bodyParser = require('body-parser');

nconf.argv();
nconf.env();
nconf.defaults(require('./config'));

auth = require('./auth');
mongoose.connect(nconf.get('MONGOHQ_URL'));

app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({'extended' : true}));
app.use(auth.session());
app.use(function (request, response, next) {
  'use strict';

  response.header('Content-Type', 'application/json');
  response.header('Content-Encoding', 'UTF-8');
  response.header('Content-Language', 'en');
  response.header('Cache-Control', 'no-cache, no-store, must-revalidate');
  response.header('Pragma', 'no-cache');
  response.header('Expires', '0');
  response.header('Access-Control-Allow-Origin', '*');
  response.header('Access-Control-Allow-Methods', request.get('Access-Control-Request-Method'));
  response.header('Access-Control-Allow-Headers', request.get('Access-Control-Request-Headers'));
  next();
});
app.use(require('./controllers/user'));
app.use(require('./controllers/profile'));
app.use(function handleErrors(error, request, response, next) {
  'use strict';

  var errors, prop;
  if (error && error.cause && error.cause()) {
    if (error.cause().code === 11000) {
      return response.status(409).end();
    }
    if (error.cause().errors) {
      errors = {};
      for (prop in error.cause().errors) {
        if (error.cause().errors.hasOwnProperty(prop)) {
          errors[prop] = error.cause().errors[prop].type;
        }
      }
      return response.status(400).send(errors);
    }
  }
  console.error(error);
  response.status(500).end();
  return process.exit();
});

app.get('/', function pingSuccess(request, response) {
  'use strict';

  response.status(200).send({'ola' : 'mundo'});
});

app.listen(nconf.get('PORT'));

module.exports = app;
<commit_msg>platform test<commit_after>var express, mongoose, nconf, bodyParser,
app, auth;

express = require('express');
mongoose = require('mongoose');
nconf = require('nconf');
bodyParser = require('body-parser');

nconf.argv();
nconf.env();
nconf.defaults(require('./config'));

auth = require('./auth');
mongoose.connect(nconf.get('MONGOHQ_URL'));

app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({'extended' : true}));
app.use(auth.session());
app.use(function (request, response, next) {
  'use strict';

  response.header('Content-Type', 'application/json');
  response.header('Content-Encoding', 'UTF-8');
  response.header('Content-Language', 'en');
  response.header('Cache-Control', 'no-cache, no-store, must-revalidate');
  response.header('Pragma', 'no-cache');
  response.header('Expires', '0');
  response.header('Access-Control-Allow-Origin', '*');
  response.header('Access-Control-Allow-Methods', request.get('Access-Control-Request-Method'));
  response.header('Access-Control-Allow-Headers', request.get('Access-Control-Request-Headers'));
  next();
});
app.use(require('./controllers/user'));
app.use(require('./controllers/profile'));
app.use(function handleErrors(error, request, response, next) {
  'use strict';

  var errors, prop;
  if (error && error.cause && error.cause()) {
    if (error.cause().code === 11000) {
      return response.status(409).end();
    }
    if (error.cause().errors) {
      errors = {};
      for (prop in error.cause().errors) {
        if (error.cause().errors.hasOwnProperty(prop)) {
          errors[prop] = error.cause().errors[prop].type;
        }
      }
      return response.status(400).send(errors);
    }
  }
  console.error(error);
  response.status(500).end();
  return process.exit();
});

app.get('/', function pingSuccess(request, response) {
  'use strict';

  response.status(200).send({});
});

app.listen(nconf.get('PORT'));

module.exports = app;
<|endoftext|>


<commit_before>//Karyoviewer object
jviz.modules.karyoviewer = function(opt)
{
  //Check the options
  if(typeof opt !== 'object'){ var opt = {}; }

  //Save the ideogram ID
  this._id = (typeof opt.id === 'undefined') ? jviz.misc.getID({ prefix: 'karyoviewer', length: 5 }) : opt.id;

  //Save the ideogram class
  this._class = (typeof opt.class === 'undefined') ? 'jviz-modules-karyoviewer' : opt.class;

  //Parent element
  this._parent = opt.parent;

  //Default size
  this._width = 0; //Default width
  this._height = 0; //Default height

  //Margins
  this._margin = { top: 30, bottom: 30, left: 40, right: 40 };

  //Orientation
  this._orientation = {};
  this._orientation.actual = 'portrait'; //Actual orientation name
  this._orientation.values = [ 'portrait', 'landscape' ]; //Orientation values

  //Panel object
  this._panel = {};
  this._panel.el = null; //Panel element
  this._panel.id = this._id + '-panel'; //Panel id
  this._panel.parent = this._id; //Panel parent
  this._panel.title = (typeof opt.title === 'string') ? opt.title : 'Karyotype viewer'; //Panel title
  this._panel.detail = (typeof opt.detail === 'string') ? opt.detail : ''; //Panel detail
  this._panel.detail = ''; //Panel detail
  this._panel.visible = (typeof opt.panel === 'boolean') ? opt.panel : true; //Panel is visible

  //Canvas object
  this._canvas = {};
  this._canvas.id = this._id + '-canvas'; //Canvas ID
  this._canvas.parent = this._id; //Parent canvas ID
  this._canvas.width = '100%'; //Canvas width
  this._canvas.height = 0; //Canvas height
  this._canvas.layers = 3; //Number of layers
  this._canvas.el = null; //Canvas element

  //Chromosome info
  this._chromosome = {};
  this._chromosome.width = 15; //Chromosome default width
  this._chromosome.height = 50; //Chromosome default height
  this._chromosome.layer = 1; //Chromosome layer
  this._chromosome.list = []; //Chromosomes list
  this._chromosome.names = {}; //Chromosome names
  this._chromosome.max = 0; //Chromosome max length
  this._chromosome.margin = 0; //Chromosome margin
  this._chromosome.num = 0; //Number of chromosomes
  this._chromosome.color = jviz.colors.blue2.hex; //Chromosome color
  this._chromosome.opacity = 0.6; //Chromosome opacity
  this._chromosome.resized = false; //Chromosome data is resized

  //Chromosome radius
  this._chromosome.radius = {};
  this._chromosome.radius.portrait = 6; //Chromosome radius for portrait
  this._chromosome.radius.landscape = 20; //Chromosome radius for landscape

  //Chromosome text info
  this._chromosome.text = {};
  this._chromosome.text.list = []; //Chromosomes text
  this._chromosome.text.font = jviz.font.default; //Text font
  this._chromosome.text.size = '11px'; //Text size
  this._chromosome.text.align = 'center'; //Chromosomes text align
  this._chromosome.text.margin = 5; //Chromosomes text margin top

  //Centromere
  this._chromosome.centromere = {};
  this._chromosome.centromere.list = []; //List of centromere positions
  this._chromosome.centromere.opacity = 0.9; //Centromere opacity

  //Check the features object
  if(typeof opt.features === 'undefined'){ opt.features = {}; }

  //Features object
  this._features = {};
  this._features.list = []; //List of features
  this._features.layer = 2; //Features layer
  this._features.color = (typeof opt.features.color === 'string') ? opt.features.color : jviz.colors.red.hex; //Features default color
  this._features.opacity = 0.8; //Features opacity
  this._features.resized = false; //Features data is resized

  //Features triangle
  this._features.triangle = {};
  this._features.triangle.width = 6; //Features triangle width
  this._features.triangle.height = 4; //Features triangle height
  this._features.triangle.margin = 1; //Features triangle mrgin
  this._features.triangle.opacity = 0.6; //Features triangle opacity
  this._features.triangle.visible = (typeof opt.features.triangle === 'boolean') ? opt.features.triangle : true; //Triangle visible

  //Features label
  this._features.label = {};
  this._features.label.opacity = 1.0; //Features label opacity
  this._features.label.visible = (typeof opt.features.label === 'boolean') ? opt.features.label : true; //Label visible

  //Features label rectangle
  this._features.label.rectangle = {};
  this._features.label.rectangle.width = 0; //Features label rectangle width
  this._features.label.rectangle.height = 0; //Features label rectangle height
  this._features.label.rectangle.radius = 5; //Features label rectangle radius

  //Chromosomes hover
  this._hover = {};
  this._hover.index = -1; //Hover chromosome index
  this._hover.margin = { top: 10, bottom: 20, left: 10, right: 10 }; //Hover margin
  this._hover.color = jviz.colors.white.hex; //Hover background color
  this._hover.opacity = 1.0; //Hover background color opacity
  this._hover.radius = 10; //Hover radius
  this._hover.layer = 0; //Hover layer

  //Check for undefined orientation
  if(typeof opt.orientation !== 'string'){ opt.orientation = 'portrait'; }

  //Parse the orientation
  this.orientation(opt.orientation);

  //Build the karyotype element
  this.build();

  //Register the events
  this.events();

  //Resize the canvas
  this.resize();

  //Return this
  return this;
};
<commit_msg>js/karyoviewer.js: added default orientation value<commit_after>//Karyoviewer object
jviz.modules.karyoviewer = function(opt)
{
  //Check the options
  if(typeof opt !== 'object'){ var opt = {}; }

  //Save the ideogram ID
  this._id = (typeof opt.id === 'undefined') ? jviz.misc.getID({ prefix: 'karyoviewer', length: 5 }) : opt.id;

  //Save the ideogram class
  this._class = (typeof opt.class === 'undefined') ? 'jviz-modules-karyoviewer' : opt.class;

  //Parent element
  this._parent = opt.parent;

  //Default size
  this._width = 0; //Default width
  this._height = 0; //Default height

  //Margins
  this._margin = { top: 30, bottom: 30, left: 40, right: 40 };

  //Orientation
  this._orientation = {};
  this._orientation.actual = ''; //Actual orientation name
  this._orientation.default = 'portrait'; //Default orientation
  this._orientation.values = [ 'portrait', 'landscape' ]; //Orientation values

  //Panel object
  this._panel = {};
  this._panel.el = null; //Panel element
  this._panel.id = this._id + '-panel'; //Panel id
  this._panel.parent = this._id; //Panel parent
  this._panel.title = (typeof opt.title === 'string') ? opt.title : 'Karyotype viewer'; //Panel title
  this._panel.detail = (typeof opt.detail === 'string') ? opt.detail : ''; //Panel detail
  this._panel.detail = ''; //Panel detail
  this._panel.visible = (typeof opt.panel === 'boolean') ? opt.panel : true; //Panel is visible

  //Canvas object
  this._canvas = {};
  this._canvas.id = this._id + '-canvas'; //Canvas ID
  this._canvas.parent = this._id; //Parent canvas ID
  this._canvas.width = '100%'; //Canvas width
  this._canvas.height = 0; //Canvas height
  this._canvas.layers = 3; //Number of layers
  this._canvas.el = null; //Canvas element

  //Chromosome info
  this._chromosome = {};
  this._chromosome.width = 15; //Chromosome default width
  this._chromosome.height = 50; //Chromosome default height
  this._chromosome.layer = 1; //Chromosome layer
  this._chromosome.list = []; //Chromosomes list
  this._chromosome.names = {}; //Chromosome names
  this._chromosome.max = 0; //Chromosome max length
  this._chromosome.margin = 0; //Chromosome margin
  this._chromosome.num = 0; //Number of chromosomes
  this._chromosome.color = jviz.colors.blue2.hex; //Chromosome color
  this._chromosome.opacity = 0.6; //Chromosome opacity
  this._chromosome.resized = false; //Chromosome data is resized

  //Chromosome radius
  this._chromosome.radius = {};
  this._chromosome.radius.portrait = 6; //Chromosome radius for portrait
  this._chromosome.radius.landscape = 20; //Chromosome radius for landscape

  //Chromosome text info
  this._chromosome.text = {};
  this._chromosome.text.list = []; //Chromosomes text
  this._chromosome.text.font = jviz.font.default; //Text font
  this._chromosome.text.size = '11px'; //Text size
  this._chromosome.text.align = 'center'; //Chromosomes text align
  this._chromosome.text.margin = 5; //Chromosomes text margin top

  //Centromere
  this._chromosome.centromere = {};
  this._chromosome.centromere.list = []; //List of centromere positions
  this._chromosome.centromere.opacity = 0.9; //Centromere opacity

  //Check the features object
  if(typeof opt.features === 'undefined'){ opt.features = {}; }

  //Features object
  this._features = {};
  this._features.list = []; //List of features
  this._features.layer = 2; //Features layer
  this._features.color = (typeof opt.features.color === 'string') ? opt.features.color : jviz.colors.red.hex; //Features default color
  this._features.opacity = 0.8; //Features opacity
  this._features.resized = false; //Features data is resized

  //Features triangle
  this._features.triangle = {};
  this._features.triangle.width = 6; //Features triangle width
  this._features.triangle.height = 4; //Features triangle height
  this._features.triangle.margin = 1; //Features triangle mrgin
  this._features.triangle.opacity = 0.6; //Features triangle opacity
  this._features.triangle.visible = (typeof opt.features.triangle === 'boolean') ? opt.features.triangle : true; //Triangle visible

  //Features label
  this._features.label = {};
  this._features.label.opacity = 1.0; //Features label opacity
  this._features.label.visible = (typeof opt.features.label === 'boolean') ? opt.features.label : true; //Label visible

  //Features label rectangle
  this._features.label.rectangle = {};
  this._features.label.rectangle.width = 0; //Features label rectangle width
  this._features.label.rectangle.height = 0; //Features label rectangle height
  this._features.label.rectangle.radius = 5; //Features label rectangle radius

  //Chromosomes hover
  this._hover = {};
  this._hover.index = -1; //Hover chromosome index
  this._hover.margin = { top: 10, bottom: 20, left: 10, right: 10 }; //Hover margin
  this._hover.color = jviz.colors.white.hex; //Hover background color
  this._hover.opacity = 1.0; //Hover background color opacity
  this._hover.radius = 10; //Hover radius
  this._hover.layer = 0; //Hover layer

  //Check for undefined orientation
  if(typeof opt.orientation !== 'string'){ opt.orientation = 'portrait'; }

  //Parse the orientation
  this.orientation(opt.orientation);

  //Build the karyotype element
  this.build();

  //Register the events
  this.events();

  //Resize the canvas
  this.resize();

  //Return this
  return this;
};
<|endoftext|>


<commit_before>var path = require('path');

describe(path.basename(__filename), function (done) {

  this.timeout(120000);

  require('benchmarket').start();
  after(require('benchmarket').store());

  var libFolder = path.join(__dirname, 'lib');
  var Mesh = require('../');
  var async = require('async');
  require('chai').should();
  var test_id = Date.now() + '_' + require('shortid').generate();
  var dbFileName = './temp/' + test_id + '.nedb';
  var mesh;

  var exchangeIterations = (process.arch == 'arm') ? 100 : 1000;
  var allowedOverhead = 100; // this is just value. Based on the best we can get this to, this can change. At least then we have a baseline.
  var callbackTimeout = (process.arch == 'arm') ? 0 : 0;

  var config = {
    name: "testComponent2Component",
    datalayer: {
      secure: true,
      persist: true,
      defaultRoute: "mem",
      filename: dbFileName
    },
    modules: {
      "e7Module": {
        path: path.join(libFolder, "e7-module"),
        constructor: {
          type: "sync",
          parameters: []
        }
      }
    },
    components: {
      "e7Component": {
        moduleName: "e7Module",
        startMethod: 'start',
        // scope:"component",//either component(mesh aware) or module - default is module
        schema: {
          "exclusive": false,//means we dont dynamically share anything else
          "methods": {
            start: {
              type: 'sync',
              parameters: [
                {type: 'object', name: 'options', value: {callbackTimeout: callbackTimeout}}
              ]
            }
          }
        }
      }
    }
  };

  before(function () {
    return Mesh.create(config)
      .then(function (createdMesh) {
        mesh = createdMesh;
      });
  });

  after(function () {
    return mesh.stop({reconnect: false});
  });

  it('does not add more than ' + allowedOverhead + '% overhead on local exchange functions', function (done) {
    var startTime = process.hrtime();
    var diffTimeExchange;
    var diffTimeDirect;
    var overheadTimeExchange;
    var overheadTimeDirect;
    var object = {
      someProperty: 'This is the value',
      someNumberProperty: 0
    };
    async.timesSeries(exchangeIterations,
      function (iteration, cb) {
        mesh.exchange.e7Component.exchangeFunction(object, cb);
      },
      function () {
        var diffTimeExchangeArray = process.hrtime(startTime);
        diffTimeExchange = diffTimeExchangeArray[0] + diffTimeExchangeArray[1] / 1000000000;
        overheadTimeExchange = diffTimeExchange - (callbackTimeout / 1000 * exchangeIterations);
        mesh.log.info(exchangeIterations + " exchange calls took %d seconds, added %d seconds overhead per call", diffTimeExchange, overheadTimeExchange / exchangeIterations);
        runDirectly();
      });

    function runDirectly() {
      var e7module = require(path.join(libFolder, 'e7-module'))();
      e7module.start({callbackTimeout: callbackTimeout});
      startTime = process.hrtime();
      async.timesSeries(exchangeIterations,
        function (iterations, callback) {
          var forceAsync = true;

          e7module.exchangeFunction(object, function () {
            if (forceAsync) {
              return setImmediate(callback);
            }
            callback();
          });
          forceAsync = false;
        },
        function () {
          var diffTimeDirectArray = process.hrtime(startTime);
          diffTimeDirect = diffTimeDirectArray[0] + diffTimeDirectArray[1] / 1000000000;
          overheadTimeDirect = diffTimeDirect - (callbackTimeout / 1000 * exchangeIterations);
          mesh.log.info(exchangeIterations + " exchange calls took %d seconds, added %d seconds overhead per call", diffTimeDirect, overheadTimeDirect / exchangeIterations);
          var difference = ((overheadTimeExchange - overheadTimeDirect) / overheadTimeDirect) * 100;
          mesh.log.info("Exchange is %d\% slower than direct", difference);
          (difference).should.be.lt(allowedOverhead + 100);
          done();
        });
    }

  });

  require('benchmarket').stop();
});

<commit_msg>issue/#196 - Fix print out<commit_after>var path = require('path');

describe(path.basename(__filename), function (done) {

  this.timeout(120000);

  require('benchmarket').start();
  after(require('benchmarket').store());

  var libFolder = path.join(__dirname, 'lib');
  var Mesh = require('../');
  var async = require('async');
  require('chai').should();
  var test_id = Date.now() + '_' + require('shortid').generate();
  var dbFileName = './temp/' + test_id + '.nedb';
  var mesh;

  var exchangeIterations = (process.arch == 'arm') ? 100 : 1000;
  var allowedOverhead = 100; // this is just value. Based on the best we can get this to, this can change. At least then we have a baseline.
  var callbackTimeout = (process.arch == 'arm') ? 0 : 0;

  var config = {
    name: "testComponent2Component",
    datalayer: {
      secure: true,
      persist: true,
      defaultRoute: "mem",
      filename: dbFileName
    },
    modules: {
      "e7Module": {
        path: path.join(libFolder, "e7-module"),
        constructor: {
          type: "sync",
          parameters: []
        }
      }
    },
    components: {
      "e7Component": {
        moduleName: "e7Module",
        startMethod: 'start',
        // scope:"component",//either component(mesh aware) or module - default is module
        schema: {
          "exclusive": false,//means we dont dynamically share anything else
          "methods": {
            start: {
              type: 'sync',
              parameters: [
                {type: 'object', name: 'options', value: {callbackTimeout: callbackTimeout}}
              ]
            }
          }
        }
      }
    }
  };

  before(function () {
    return Mesh.create(config)
      .then(function (createdMesh) {
        mesh = createdMesh;
      });
  });

  after(function () {
    return mesh.stop({reconnect: false});
  });

  it('does not add more than ' + allowedOverhead + '% overhead on local exchange functions', function (done) {
    var startTime = process.hrtime();
    var diffTimeExchange;
    var diffTimeDirect;
    var overheadTimeExchange;
    var overheadTimeDirect;
    var object = {
      someProperty: 'This is the value',
      someNumberProperty: 0
    };
    async.timesSeries(exchangeIterations,
      function (iteration, cb) {
        mesh.exchange.e7Component.exchangeFunction(object, cb);
      },
      function () {
        var diffTimeExchangeArray = process.hrtime(startTime);
        diffTimeExchange = diffTimeExchangeArray[0] + diffTimeExchangeArray[1] / 1000000000;
        overheadTimeExchange = diffTimeExchange - (callbackTimeout / 1000 * exchangeIterations);
        mesh.log.info(exchangeIterations + " exchange calls took %d seconds, added %d seconds overhead per call", diffTimeExchange, overheadTimeExchange / exchangeIterations);
        runDirectly();
      });

    function runDirectly() {
      var e7module = require(path.join(libFolder, 'e7-module'))();
      e7module.start({callbackTimeout: callbackTimeout});
      startTime = process.hrtime();
      async.timesSeries(exchangeIterations,
        function (iterations, callback) {
          var forceAsync = true;

          e7module.exchangeFunction(object, function () {
            if (forceAsync) {
              return setImmediate(callback);
            }
            callback();
          });
          forceAsync = false;
        },
        function () {
          var diffTimeDirectArray = process.hrtime(startTime);
          diffTimeDirect = diffTimeDirectArray[0] + diffTimeDirectArray[1] / 1000000000;
          overheadTimeDirect = diffTimeDirect - (callbackTimeout / 1000 * exchangeIterations);
          mesh.log.info(exchangeIterations + " direct calls took %d seconds, added %d seconds overhead per call", diffTimeDirect, overheadTimeDirect / exchangeIterations);
          var difference = ((overheadTimeExchange - overheadTimeDirect) / overheadTimeDirect) * 100;
          mesh.log.info("Exchange is %d\% slower than direct", difference);
          (difference).should.be.lt(allowedOverhead + 100);
          done();
        });
    }

  });

  require('benchmarket').stop();
});

<|endoftext|>


<commit_before>#!/usr/bin/env node
require('dotenv').config();
const argv = require('yargs').argv;

const log = require(process.env.PROJECT_ROOT+'/libs/log');

const SpeedTask = require(process.env.PROJECT_ROOT+'/libs/speedTest');
const EmailTask = require(process.env.PROJECT_ROOT+'/libs/email');

log('Cron executing');
if (argv.email) {
	new EmailTask();
} else {
	new SpeedTask();
}<commit_msg>fix cli reference<commit_after>#!/usr/bin/env node
require('dotenv').config();
#!/usr/bin/env /usr/local/bin/node
const argv = require('yargs').argv;

const log = require(process.env.PROJECT_ROOT+'/libs/log');

const SpeedTask = require(process.env.PROJECT_ROOT+'/libs/speedTest');
const EmailTask = require(process.env.PROJECT_ROOT+'/libs/email');

log('Cron executing');
if (argv.email) {
	new EmailTask();
} else {
	new SpeedTask();
}<|endoftext|>


<commit_before>var Dialog = require('./../index');
var _ = require('lodash');

Dialog.prototype._show = function(e) {
  if (e) {
    this.model.setEach('origin', { x: e.pageX, y: e.pageY });
  }

  var self = this;
  this._maybeShowOverlay();
  this.model.set('animating', true);
  _.delay(function () {
    self.model.set('show', true)
  }, 100);
};

Dialog.prototype._maybeHide = function(action) {
  var cancelled = this.emitCancellable('hide', action);
  if (cancelled) return;

  this._hide()
};

Dialog.prototype._hide = function() {
  var self = this;

  this._maybeHideOverlay();
  this.model.set('show', false);
  _.delay(function () {
    self.model.set('animating', false);
  }, 300);
};

Dialog.prototype._maybeHideByOverlay = function () {
  var opts = this.getAttribute('options');
  if (opts && opts.overlay && opts.overlay.clickToHide) {
    this._maybeHide(opts.overlay.closeAction || 'overlay');
  }
};

Dialog.prototype._maybeShowOverlay = function () {
  var opts = this.getAttribute('options');
  if (opts && opts.overlay) {
    this.overlay.show();
  }
};

Dialog.prototype._maybeHideOverlay = function () {
  var opts = this.getAttribute('options');
  if (opts && opts.overlay) {
    this.overlay.hide();
  }
};
<commit_msg>Add returning of any params passed to dialog show.<commit_after>var Dialog = require('./../index');
var _ = require('lodash');

Dialog.prototype._show = function(e) {
  // Animate from click if event is passed
  if (e && typeof e.pageX === 'number') {
    this.model.setEach('origin', { x: e.pageX, y: e.pageY });
  }

  // Save params so we can return them in emit.
  this.params = arguments;

  var self = this;
  this._maybeShowOverlay();
  this.model.set('animating', true);
  _.delay(function () {
    self.model.set('show', true)
  }, 100);
};

Dialog.prototype._maybeHide = function(action) {
  var cancelled = this.emitCancellable('hide', action, this.params);
  if (cancelled) return;

  this._hide()
};

Dialog.prototype._hide = function() {
  var self = this;

  this._maybeHideOverlay();
  this.model.set('show', false);
  _.delay(function () {
    self.model.set('animating', false);
  }, 300);
};

Dialog.prototype._maybeHideByOverlay = function () {
  var opts = this.getAttribute('options');
  if (opts && opts.overlay && opts.overlay.clickToHide) {
    this._maybeHide(opts.overlay.closeAction || 'overlay');
  }
};

Dialog.prototype._maybeShowOverlay = function () {
  var opts = this.getAttribute('options');
  if (opts && opts.overlay) {
    this.overlay.show();
  }
};

Dialog.prototype._maybeHideOverlay = function () {
  var opts = this.getAttribute('options');
  if (opts && opts.overlay) {
    this.overlay.hide();
  }
};
<|endoftext|>


<commit_before>/**
 * Module dependencies
 */

var superagent = require('superagent-defaults');
var parseLinks = require('links-parser');
var LRU = require('lru-cache');
var immutableParse = require('hyper-json-immutable-parse');
var inherits = require('util').inherits;
var Emitter = require('events').EventEmitter;
var qs = require('qs').stringify;

/**
 * Expose the Client constructor
 */

module.exports = Client;

/**
 * Create a client
 */

function Client(API_URL, opts) {
  if (!(this instanceof Client)) return new Client(API_URL, opts);

  Emitter.call(this);
  var self = this;
  opts = opts || {};
  self.cache = new LRU(opts.maxSize || 500);
  self.pending = {};

  self.root = get.bind(self, API_URL);
  self.get = get.bind(self);

  var context = self.context = superagent();

  // TODO only set the parser for the context
  var parsers = context.request.parse;
  parsers['application/json'] = parsers['application/hyper+json'] = parseHyperJson;

  patchCrappySuperagent(context.request.Response, context.request.parse);
}
inherits(Client, Emitter);

Client.prototype.auth = function(user, pass) {
  this.context.auth(user, pass);
  return this;
};

Client.prototype.use = function(fn) {
  this.context.on('request', fn);
  return this;
};

Client.prototype.header = function(key, value) {
  this.context.set(key, value);
  return this;
};

Client.prototype.format = function(method, action, values, cb) {
  if (method === 'GET') {
    action = action.split('?')[0];
    cb(null, action + '?' + qs(values));
  } else {
    cb(null, action, values);
  }
  return this;
};

Client.prototype.submit = function(method, action, body, fn) {
  var self = this;
  method = method.toLowerCase();
  var req = self._init(method, action);

  if (body) {
    method === 'get' ?
      req.query(body) :
      req.send(body);
  }

  return req.end(function(err, res) {
    if (err) return fn(err);
    if (!res.ok) return fn(new HyperError(res));
    var location = res.get('location');
    var contentLocation = res.get('content-location');
    var href = contentLocation || location;
    var body = res.body;
    fn(null, res.body, res.links, href, false);
    if (method !== 'get') self._scheduleUpdates(action, res, location, contentLocation);
  });
};

Client.prototype._scheduleUpdates = function(action, res, location, contentLocation) {
  var body = res.body;
  var updates = {};
  var links = parseLinks(res.headers.link || '') || {};

  if (action) updates[action] = [action];
  if (body) updates[body.href] = [body.href, body, links];
  if (contentLocation) updates[contentLocation] = [contentLocation, body, links];
  if (location) updates[location] = updates[location] || [location];

  // add support for http://tools.ietf.org/html/draft-nottingham-linked-cache-inv-03#section-3
  var invalidates = typeof links.invalidates === 'string' ? [links.invalidates] : links.invalidates;
  for (var i = 0; i < (invalidates || []).length; i++) {
    updates[invalidates[i]] = [invalidates[i]];
  }

  for (var href in updates) {
    this.refresh.apply(this, updates[href]);
  }
};

Client.prototype.refresh = function(href, body, links) {
  if (body) this._save(href, body, links);
  this._bustCache(href);
};

Client.prototype.subscribe = function(href, cb) {
  var self = this;
  var sub = function() {
    cb.apply(self, arguments);
  };
  self.on(href, sub);
  return function() {
    self.removeListener(href, sub);
  };
};

Client.prototype._save = function(href, body, links) {
  var self = this;
  self.cache.set(href, {b: body, l: links});
  self.emit(href, null, body, links, null, false);
};

Client.prototype._bustCache = function(href) {
  var req = this._fetch(href);
  req.set({
    'cache-control': 'max-age=0, no-store, no-cache',
    pragma: 'no-cache'
  });
  req.end();
};

Client.prototype._init = function(method, href) {
  if (!!process.env.CHAOS) {
    var weight = parseFloat(process.env.CHAOS);
    if (isNaN(weight)) weight = 0.1;
    if (Math.random() < weight) return chaos(href);
  }
  return this.context[method](href);
};

Client.prototype._fetch = function(href, cb) {
  var self = this;
  var pending = self.pending;
  var req = pending[href] = self._init('get', href);

  self._wait(href, function(err, body, links) {
    delete pending[href];

    if (err) return self.emit(href, err);

    self._save(href, body, links);

    setTimeout(function() {
      req.removeAllListeners();
    }, 0);
  }, false);

  if (!cb) return req;

  var sub = self._wait(href, cb);

  req.end();

  return sub;
};

Client.prototype._wait = function(href, cb, shouldSubscribe) {
  var self = this;

  var req = self.pending[href];
  if (!req) return false;

  req.on('error', cb);

  if (shouldSubscribe !== false) return self.subscribe(href, cb);

  req.on('response', function(res) {
    if (res.error) return cb(res.error);
    return cb(null, res.body, res.links, null, false);
  });
  return req;
};

function get(href, cb) {
  var self = this;
  var cache = self.cache;
  var res = cache.get(href);
  if (res) {
    cb(null, res.b, res.l, null, false);
    return self.subscribe(href, cb);
  }

  return self._wait(href, cb) || self._fetch(href, cb);
}

function parseHyperJson(res, fn) {
  // browser
  if (typeof res === 'string') return parseJSON(res, this.xhr.responseURL || this.headers['content-location'] || this.headers.location || this.req.url);

  // node
  res.text = '';
  res.setEncoding('utf8');
  res.on('data', function(chunk){ res.text += chunk; });
  res.on('end', function(){
    var href = res.headers['content-location'] || res.headers.location || res.req.url;
    var out;
    try {
      out = parseJSON(res.text.replace(/^\s*|\s*$/g, ''), href);
    } catch (err) {
      return fn(err);
    }
    return fn(null, out);
  });
}

function parseJSON(body, href) {
  return JSON.parse(body, immutableParse(href));
}

if (!!process.env.CHAOS) {

  function chaos(path) {
    var req = new Emitter();
    if (Math.random() > 0.5) {
      setTimeout(function() {
        req.emit('error', new Error('Internal server error'));
      }, Math.random() * 500);
    } else {
      setTimeout(function() {
        req.emit('error', new Error('Connection timeout'));
      }, 5000);
    }
    req.end = function() {};
    return req;
  }
}

/**
 * Create a hyper error given a superagent response
 *
 * @param {Response} res
 */

function HyperError(res) {
  Error.call(this);
  Error.captureStackTrace(this, arguments.callee);
  this.name = 'HyperError';
  this.status = res.status;
  if (res.body && res.body.error) this.message = res.body.error.message;
  else this.message = res.text;
}

function patchCrappySuperagent(Response, parsers) {
  if (!Response || !Response.prototype.parseBody) return;
  Response.prototype.parseBody = function(str) {
    var parse = parsers[this.type];
    return parse && str && str.length ?
      parse.call(this, str) :
      null;
  };
}
<commit_msg>add clear function for clearing the cache<commit_after>/**
 * Module dependencies
 */

var superagent = require('superagent-defaults');
var parseLinks = require('links-parser');
var LRU = require('lru-cache');
var immutableParse = require('hyper-json-immutable-parse');
var inherits = require('util').inherits;
var Emitter = require('events').EventEmitter;
var qs = require('qs').stringify;

/**
 * Expose the Client constructor
 */

module.exports = Client;

/**
 * Create a client
 */

function Client(API_URL, opts) {
  if (!(this instanceof Client)) return new Client(API_URL, opts);

  Emitter.call(this);
  var self = this;
  opts = opts || {};
  self.cache = new LRU(opts.maxSize || 500);
  self.pending = {};

  self.root = get.bind(self, API_URL);
  self.get = get.bind(self);

  var context = self.context = superagent();

  // TODO only set the parser for the context
  var parsers = context.request.parse;
  parsers['application/json'] = parsers['application/hyper+json'] = parseHyperJson;

  patchCrappySuperagent(context.request.Response, context.request.parse);
}
inherits(Client, Emitter);

Client.prototype.auth = function(user, pass) {
  this.context.auth(user, pass);
  return this;
};

Client.prototype.use = function(fn) {
  this.context.on('request', fn);
  return this;
};

Client.prototype.header = function(key, value) {
  this.context.set(key, value);
  return this;
};

Client.prototype.format = function(method, action, values, cb) {
  if (method === 'GET') {
    action = action.split('?')[0];
    cb(null, action + '?' + qs(values));
  } else {
    cb(null, action, values);
  }
  return this;
};

Client.prototype.submit = function(method, action, body, fn) {
  var self = this;
  method = method.toLowerCase();
  var req = self._init(method, action);

  if (body) {
    method === 'get' ?
      req.query(body) :
      req.send(body);
  }

  return req.end(function(err, res) {
    if (err) return fn(err);
    if (!res.ok) return fn(new HyperError(res));
    var location = res.get('location');
    var contentLocation = res.get('content-location');
    var href = contentLocation || location;
    var body = res.body;
    fn(null, res.body, res.links, href, false);
    if (method !== 'get') self._scheduleUpdates(action, res, location, contentLocation);
  });
};

Client.prototype._scheduleUpdates = function(action, res, location, contentLocation) {
  var body = res.body;
  var updates = {};
  var links = parseLinks(res.headers.link || '') || {};

  if (action) updates[action] = [action];
  if (body) updates[body.href] = [body.href, body, links];
  if (contentLocation) updates[contentLocation] = [contentLocation, body, links];
  if (location) updates[location] = updates[location] || [location];

  // add support for http://tools.ietf.org/html/draft-nottingham-linked-cache-inv-03#section-3
  var invalidates = typeof links.invalidates === 'string' ? [links.invalidates] : links.invalidates;
  for (var i = 0; i < (invalidates || []).length; i++) {
    updates[invalidates[i]] = [invalidates[i]];
  }

  for (var href in updates) {
    this.refresh.apply(this, updates[href]);
  }
};

Client.prototype.clear = function(href, cb) {
  this.cache.del(href);
  cb();
};

Client.prototype.refresh = function(href, body, links) {
  if (body) this._save(href, body, links);
  this._bustCache(href);
};

Client.prototype.subscribe = function(href, cb) {
  var self = this;
  var sub = function() {
    cb.apply(self, arguments);
  };
  self.on(href, sub);
  return function() {
    self.removeListener(href, sub);
  };
};

Client.prototype._save = function(href, body, links) {
  var self = this;
  self.cache.set(href, {b: body, l: links});
  self.emit(href, null, body, links, null, false);
};

Client.prototype._bustCache = function(href) {
  var req = this._fetch(href);
  req.set({
    'cache-control': 'max-age=0, no-store, no-cache',
    pragma: 'no-cache'
  });
  req.end();
};

Client.prototype._init = function(method, href) {
  if (!!process.env.CHAOS) {
    var weight = parseFloat(process.env.CHAOS);
    if (isNaN(weight)) weight = 0.1;
    if (Math.random() < weight) return chaos(href);
  }
  return this.context[method](href);
};

Client.prototype._fetch = function(href, cb) {
  var self = this;
  var pending = self.pending;
  var req = pending[href] = self._init('get', href);

  self._wait(href, function(err, body, links) {
    delete pending[href];

    if (err) return self.emit(href, err);

    self._save(href, body, links);

    setTimeout(function() {
      req.removeAllListeners();
    }, 0);
  }, false);

  if (!cb) return req;

  var sub = self._wait(href, cb);

  req.end();

  return sub;
};

Client.prototype._wait = function(href, cb, shouldSubscribe) {
  var self = this;

  var req = self.pending[href];
  if (!req) return false;

  req.on('error', cb);

  if (shouldSubscribe !== false) return self.subscribe(href, cb);

  req.on('response', function(res) {
    if (res.error) return cb(res.error);
    return cb(null, res.body, res.links, null, false);
  });
  return req;
};

function get(href, cb) {
  var self = this;
  var cache = self.cache;
  var res = cache.get(href);
  if (res) {
    cb(null, res.b, res.l, null, false);
    return self.subscribe(href, cb);
  }

  return self._wait(href, cb) || self._fetch(href, cb);
}

function parseHyperJson(res, fn) {
  // browser
  if (typeof res === 'string') return parseJSON(res, this.xhr.responseURL || this.headers['content-location'] || this.headers.location || this.req.url);

  // node
  res.text = '';
  res.setEncoding('utf8');
  res.on('data', function(chunk){ res.text += chunk; });
  res.on('end', function(){
    var href = res.headers['content-location'] || res.headers.location || res.req.url;
    var out;
    try {
      out = parseJSON(res.text.replace(/^\s*|\s*$/g, ''), href);
    } catch (err) {
      return fn(err);
    }
    return fn(null, out);
  });
}

function parseJSON(body, href) {
  return JSON.parse(body, immutableParse(href));
}

if (!!process.env.CHAOS) {

  function chaos(path) {
    var req = new Emitter();
    if (Math.random() > 0.5) {
      setTimeout(function() {
        req.emit('error', new Error('Internal server error'));
      }, Math.random() * 500);
    } else {
      setTimeout(function() {
        req.emit('error', new Error('Connection timeout'));
      }, 5000);
    }
    req.end = function() {};
    return req;
  }
}

/**
 * Create a hyper error given a superagent response
 *
 * @param {Response} res
 */

function HyperError(res) {
  Error.call(this);
  Error.captureStackTrace(this, arguments.callee);
  this.name = 'HyperError';
  this.status = res.status;
  if (res.body && res.body.error) this.message = res.body.error.message;
  else this.message = res.text;
}

function patchCrappySuperagent(Response, parsers) {
  if (!Response || !Response.prototype.parseBody) return;
  Response.prototype.parseBody = function(str) {
    var parse = parsers[this.type];
    return parse && str && str.length ?
      parse.call(this, str) :
      null;
  };
}
<|endoftext|>


<commit_before>import { expect } from 'chai'
import { stub } from 'sinon'
import { SEP } from '../src/paramHelpers'
import expandConfig from '../src/expandConfig'

describe('expandConfig.js', () => {
  it(`dies if any task key has a "${SEP}" character in it`, () => {
    expect(expandConfig.bind(expandConfig, {
      build: 'thing',
      'test:watch': 'thing'
    })).to.throw(Error)
  })
})
<commit_msg>add more tests for expandConfig<commit_after>import { expect } from 'chai'
import {
  COMMAND_KEY,
  ENV_KEY,
  DEPENDENCIES_KEY,
  BEFORE_KEY,
  OPTIONAL_BEFORE_KEY,
  AFTER_KEY,
  OPTIONAL_AFTER_KEY,
  ANYTIME_KEY
} from '../src/configKeys'
import { SEP } from '../src/paramHelpers'
import expandConfig, { __RewireAPI__ as rewireAPI } from '../src/expandConfig'

describe('expandConfig.js', () => {
  it(`dies if any task key has a "${SEP}" character in it`, () => {
    expect(expandConfig.bind(expandConfig, {
      build: 'thing',
      'test:watch': 'thing'
    })).to.throw(Error)
  })
  describe('expandTask()', () => {
    let expandTask
    before(() => expandTask = rewireAPI.__get__('expandTask'))

    it('expands to sane defaults', () => {
      const task = expandTask({})
      expect(task).to.have.property(COMMAND_KEY).that.is.instanceof(Array)
      expect(task).to.have.property(ENV_KEY).that.is.instanceof(Object)
      expect(task).to.have.property(DEPENDENCIES_KEY).that.is.instanceof(Object)
      expect(task).to.have.property(DEPENDENCIES_KEY).that.has.property(BEFORE_KEY).that.is.instanceof(Array)
      expect(task).to.have.property(DEPENDENCIES_KEY).that.has.property(OPTIONAL_BEFORE_KEY).that.is.instanceof(Array)
      expect(task).to.have.property(DEPENDENCIES_KEY).that.has.property(AFTER_KEY).that.is.instanceof(Array)
      expect(task).to.have.property(DEPENDENCIES_KEY).that.has.property(OPTIONAL_AFTER_KEY).that.is.instanceof(Array)
      expect(task).to.have.property(DEPENDENCIES_KEY).that.has.property(ANYTIME_KEY).that.is.instanceof(Array)
    })
    it('expands a task that is a string', () => {
      const task = 'test'
      expect(expandTask(task)).to.have.property(COMMAND_KEY).that.equals(task)
    })
    it('expands a task that is a function', () => {
      const task = () => null
      expect(expandTask(task)).to.have.property(COMMAND_KEY).that.equals(task)
    })
    it('expands a task that is an array', () => {
      const task = ['test1', 'test2']
      expect(expandTask(task)).to.have.property(COMMAND_KEY).that.equals(task)
    })
  })
})
<|endoftext|>