<commit_before>'use strict';

describe('datepicker', function () {
  var scope, $sandbox, $compile, $timeout;

  beforeEach(module('$strap.directives'));

  beforeEach(inject(function ($injector, $rootScope, _$compile_, _$timeout_) {
    scope = $rootScope.$new();
    $compile = _$compile_;
    $timeout = _$timeout_;

    $sandbox = $('

').appendTo($('body'));
  }));

  afterEach(function() {
    $sandbox.remove();
    scope.$destroy();
    $('.datepicker').remove();
  });

  var fixtures = {
    'default': {
      element: '<input type="text" ng-model="foo.date" bs-datepicker>',
      scope: {foo: {date: new Date('2012-09-01T00:00:00.000Z')}}
    },
    'string': {
      element: '<input type="text" ng-model="foo.date" data-date-format="yyyy/mm/dd" data-date-type="string" bs-datepicker>',
      scope: {foo: {date: '2012/09/01'}}
    },
    'addon': {
      element: '<input type="text" ng-model="foo.date" bs-datepicker>'
    },
    'language': {
      element: '<input type="text" ng-model="foo.date" data-language="fr" bs-datepicker>'
    }
  };

  function compileDirective(template) {
    template = template ? fixtures[template] : fixtures['default'];
    angular.extend(scope, template.scope || fixtures['default'].scope);
    $(template.element).appendTo($sandbox);
    var $element = $(template.element).appendTo($sandbox);
    $element = $compile($element)(scope);
    scope.$digest();
    return $element;
  }

  // Tests

  it('should add "data-toggle" attr for you', function () {
    var elm = compileDirective();
    expect(elm.attr('data-toggle') === 'datepicker').toBe(true);
  });

  it('should correctly call $.fn.datepicker', function () {
    var old = $.fn.datepicker;
    var spy = angular.extend(spyOn($.fn, 'datepicker'), old).andCallThrough();
    var elm = compileDirective();
    expect(spy).toHaveBeenCalled();
  });

  it('should handle "data-language" attr', function () {
    (function($){$.fn.datepicker.dates["fr"]={days:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi","Dimanche"],daysShort:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam","Dim"],daysMin:["D","L","Ma","Me","J","V","S","D"],months:["Janvier","Février","Mars","Avril","Mai","Juin","Juillet","Août","Septembre","Octobre","Novembre","Décembre"],monthsShort:["Jan","Fev","Mar","Avr","Mai","Jui","Jul","Aou","Sep","Oct","Nov","Dec"],today:"Aujourd'hui",weekStart:1,format:"dd/mm/yyyy"}})(jQuery);
    var elm = compileDirective('language');
    expect(elm.data('datepicker').language).toBe('fr');
  });

  it('should show/hide the datepicker', function() {
    var elm = compileDirective();
    elm.datepicker('show');
    expect(elm.data('datepicker').picker.is(':visible')).toBe(true);
    elm.datepicker('hide');
    expect(elm.data('datepicker').picker.is(':visible')).toBe(false);
  });

  it('should show the datepicker on focus', function() {
    var elm = compileDirective();
    elm.trigger('focus');
    expect(elm.data('datepicker').picker.is(':visible')).toBe(true);
  });

  it('should show the datepicker on [data-toggle="datepicker"] click', function() {
    var elm = compileDirective('addon');
    elm.next('[data-toggle="datepicker"]').trigger('click');
    expect(elm.data('datepicker').picker.is(':visible')).toBe(true);
  });

  describe("data-binding", function() {

    it('should support date as a string', function() {
      var elm = compileDirective('string');
      expect(+elm.data('datepicker').date).toBe(+new Date('2012-09-01T00:00:00.000Z'));
      expect(elm.prop('value')).toBe('2012/09/01');
    });

  });

  describe("data-binding", function() {

    it('should correctly apply model defaults to the view', function() {
      var elm = compileDirective();
      expect(elm.data('datepicker').date).toBe(scope.foo.date);
      expect(elm.val()).toBe('2012-09-01');
    });

    it('should correctly apply model changes to the view', function() {
      var elm = compileDirective();
      scope.foo.date = new Date('2000-01-01T00:00:00.000Z');
      scope.$digest();
      expect(elm.data('datepicker').date).toBe(scope.foo.date);
      expect(elm.val()).toBe('2000-01-01');
    });

    it('should correctly apply view changes to the model', function() {
      var elm = compileDirective();
      elm.trigger('focus');
      elm.data('datepicker').picker.find('td').trigger('click');
      expect(elm.val() !== '').toBe(true);
      expect(scope.foo.date).toBe(elm.data('datepicker').date);
    });

  });

});
<commit_msg>chore(tests): support mobile-ios testing for datepicker<commit_after>'use strict';

describe('datepicker', function () {
  var scope, $sandbox, $compile, $timeout;

  beforeEach(module('$strap.directives'));

  beforeEach(inject(function ($injector, $rootScope, _$compile_, _$timeout_) {
    scope = $rootScope.$new();
    $compile = _$compile_;
    $timeout = _$timeout_;

    $sandbox = $('

').appendTo($('body'));
  }));

  afterEach(function() {
    $sandbox.remove();
    scope.$destroy();
    $('.datepicker').remove();
  });

  var fixtures = {
    'default': {
      element: '<input type="text" ng-model="foo.date" bs-datepicker>',
      scope: {foo: {date: new Date('2012-09-01T00:00:00.000Z')}}
    },
    'string': {
      element: '<input type="text" ng-model="foo.date" data-date-format="yyyy/mm/dd" data-date-type="string" bs-datepicker>',
      scope: {foo: {date: '2012/09/01'}}
    },
    'addon': {
      element: '<input type="text" ng-model="foo.date" bs-datepicker>'
    },
    'language': {
      element: '<input type="text" ng-model="foo.date" data-language="fr" bs-datepicker>'
    }
  };

  function compileDirective(template) {
    template = template ? fixtures[template] : fixtures['default'];
    angular.extend(scope, template.scope || fixtures['default'].scope);
    $(template.element).appendTo($sandbox);
    var $element = $(template.element).appendTo($sandbox);
    $element = $compile($element)(scope);
    scope.$digest();
    return $element;
  }

  // Tests
  describe('desktop', function () {
    var isAppleTouch = /(iPad|iPho(ne|d))/g.test(navigator.userAgent);
    if(isAppleTouch) return;

    it('should add "data-toggle" attr for you', function () {
      var elm = compileDirective();
      expect(elm.attr('data-toggle') === 'datepicker').toBe(true);
    });

    it('should correctly call $.fn.datepicker', function () {
      var old = $.fn.datepicker;
      var spy = angular.extend(spyOn($.fn, 'datepicker'), old).andCallThrough();
      var elm = compileDirective();
      expect(spy).toHaveBeenCalled();
    });

    it('should handle "data-language" attr', function () {
      (function($){$.fn.datepicker.dates["fr"]={days:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi","Dimanche"],daysShort:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam","Dim"],daysMin:["D","L","Ma","Me","J","V","S","D"],months:["Janvier","Février","Mars","Avril","Mai","Juin","Juillet","Août","Septembre","Octobre","Novembre","Décembre"],monthsShort:["Jan","Fev","Mar","Avr","Mai","Jui","Jul","Aou","Sep","Oct","Nov","Dec"],today:"Aujourd'hui",weekStart:1,format:"dd/mm/yyyy"}})(jQuery);
      var elm = compileDirective('language');
      expect(elm.data('datepicker').language).toBe('fr');
    });

    it('should show/hide the datepicker', function() {
      var elm = compileDirective();
      elm.datepicker('show');
      expect(elm.data('datepicker').picker.is(':visible')).toBe(true);
      elm.datepicker('hide');
      expect(elm.data('datepicker').picker.is(':visible')).toBe(false);
    });

    it('should show the datepicker on focus', function() {
      var elm = compileDirective();
      elm.trigger('focus');
      expect(elm.data('datepicker').picker.is(':visible')).toBe(true);
    });

    it('should show the datepicker on [data-toggle="datepicker"] click', function() {
      var elm = compileDirective('addon');
      elm.next('[data-toggle="datepicker"]').trigger('click');
      expect(elm.data('datepicker').picker.is(':visible')).toBe(true);
    });

    describe("data-binding", function() {

      it('should support date as a string', function() {
        var elm = compileDirective('string');
        expect(+elm.data('datepicker').date).toBe(+new Date('2012-09-01T00:00:00.000Z'));
        expect(elm.prop('value')).toBe('2012/09/01');
      });

    });

    describe("data-binding", function() {

      it('should correctly apply model defaults to the view', function() {
        var elm = compileDirective();
        expect(elm.data('datepicker').date).toBe(scope.foo.date);
        expect(elm.val()).toBe('2012-09-01');
      });

      it('should correctly apply model changes to the view', function() {
        var elm = compileDirective();
        scope.foo.date = new Date('2000-01-01T00:00:00.000Z');
        scope.$digest();
        expect(elm.data('datepicker').date).toBe(scope.foo.date);
        expect(elm.val()).toBe('2000-01-01');
      });

      it('should correctly apply view changes to the model', function() {
        var elm = compileDirective();
        elm.trigger('focus');
        elm.data('datepicker').picker.find('td').trigger('click');
        expect(elm.val() !== '').toBe(true);
        expect(scope.foo.date).toBe(elm.data('datepicker').date);
      });

    });

  });

});
<|endoftext|>


<commit_before>var assert = require('assert'),
    manyToManyFixture = require('../../support/fixtures/model/context.manyToMany.fixture'),
    Model = require('../../../lib/waterline/model');

describe('instance methods', function() {
  describe('association setters', function() {

    /////////////////////////////////////////////////////
    // TEST SETUP
    ////////////////////////////////////////////////////

    var model;

    before(function() {
      model = new Model(manyToManyFixture(), {});
    });

    /////////////////////////////////////////////////////
    // TEST METHODS
    ////////////////////////////////////////////////////

    it('should allow new associations to be added using the add function', function() {
      var person = new model({ name: 'foobar' });

      person.bars.add(1);
      assert(person.associations.bars.addModels.length === 1);
    });

    it('should allow new associations to be removed using the remove function', function() {
      var person = new model({ name: 'foobar' });

      person.bars.remove(1);
      assert(person.associations.bars.removeModels.length === 1);
    });

  });
});
<commit_msg>Add unit tests on .add() and .remove()<commit_after>var assert = require('assert'),
    manyToManyFixture = require('../../support/fixtures/model/context.manyToMany.fixture'),
    Model = require('../../../lib/waterline/model');

describe('instance methods', function() {
  describe('association setters', function() {

    /////////////////////////////////////////////////////
    // TEST SETUP
    ////////////////////////////////////////////////////

    var model;

    before(function() {
      model = new Model(manyToManyFixture(), {});
    });

    /////////////////////////////////////////////////////
    // TEST METHODS
    ////////////////////////////////////////////////////

    it('should allow new associations to be added using the add function', function() {
      var person = new model({ name: 'foobar' });

      person.bars.add(1);
      assert(person.associations.bars.addModels.length === 1);
    });

    it('should allow new associations to be added using the add function and an array', function() {
      var person = new model({ name: 'foobar' });

      person.bars.add( [ 1, 2, 3 ] );
      assert(person.associations.bars.addModels.length === 3);
    });

    it('should allow new associations to be removed using the remove function', function() {
      var person = new model({ name: 'foobar' });

      person.bars.remove(1);
      assert(person.associations.bars.removeModels.length === 1);
    });

    it('should allow new associations to be removed using the remove function and an array', function() {
      var person = new model({ name: 'foobar' });

      person.bars.remove( [ 1, 2, 3 ] );
      assert(person.associations.bars.removeModels.length === 3);
    });
  });
});
<|endoftext|>


<commit_before>//es6 ecmascript 2015
//a promise is a returned object to which you attach callbacks, instead of passing callbacks into a function.
//Promise.resolve() and Promise.reject() are shortcuts to manually create an already resolved or rejected promise respectively.
let callAPIAsync = new Promise((resolve, reject) => {
    // make API call
    //if success call resolve
    setTimeout( function() {
      resolve("Success!")  // Yay! Everything went well!
    }, 250)
    //else call reject
  })

let successCallback = (successMessage) => {
    console.log("Yay! " + successMessage)
  }

let failureCallback = (failureMessage) => {
    console.log("Error " + failureMessage)
  }

//Callbacks will never be called before the completion of the current run of the JavaScript event loop.
callAPIAsync.then(successCallback, failureCallback);

console.log("Finish Setup")
//promises can be chained
//also use catch to handle errors/default case
//https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

//https://developers.google.com/web/fundamentals/primers/promises#error_handling
//error handling
//With then(func1, func2), func1 or func2 will be called, never both.
//i.e if error occurs in successCallback, failureCallback will not be called
//Promise rejections skip forward to the next then() with a rejection callback (or catch(), since it's equivalent).
//with then(successCallback).catch(failureCallback) successCallback will be executed and if error, skip next then(), and will call failureCallback

let problemSuccessCallback = (successMessage) => {
  throw Error('problem in callback')
}
callAPIAsync.then(problemSuccessCallback).catch(failureCallback);
console.log("Finish Setup2")
<commit_msg>Update promises example<commit_after>//es6 ecmascript 2015
//a promise is a returned object to which you attach callbacks, instead of passing callbacks into a function.
//Promise.resolve() and Promise.reject() are shortcuts to manually create an already resolved or rejected promise respectively.
let callAPIAsync = new Promise((resolve, reject) => {
    // make API call
    let success = true //false
    setTimeout( function() {
      //if success call resolve
      if (success) {
        resolve("Success!")  // Yay! Everything went well!
      }//else call reject
      else {
        reject("Failure")
      }
    }, 250)
  })

let successCallback = (successMessage) => {
    console.log("successCallback " + successMessage)
  }

let failureCallback = (failureMessage) => {
    console.log("failureCallback " + failureMessage)
  }

//Callbacks will never be called before the completion of the current run of the JavaScript event loop.
callAPIAsync.then(successCallback, failureCallback);

console.log("Finish Setup")
//promises can be chained
//also use catch to handle errors/default case
//https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

//https://developers.google.com/web/fundamentals/primers/promises#error_handling
//error handling
//With then(func1, func2), func1 or func2 will be called, never both.
//i.e if error occurs in successCallback, failureCallback will not be called
//Promise rejections skip forward to the next then() with a rejection callback (or catch(), since it's equivalent).
//with then(successCallback).catch(failureCallback) successCallback will be executed and if error, skip next then(), and will call failureCallback

let problemSuccessCallback = (successMessage) => {
  throw Error('problem in successcallback')
}
callAPIAsync.then(problemSuccessCallback).catch(failureCallback);
console.log("Finish Setup2")
<|endoftext|>


<commit_before>// 每日推荐歌曲

module.exports = (query, request) => {
  const data = {
    limit: 20,
    offset: 0,
    total: true
  }
  return request(
    'POST', `https://music.163.com/weapi/v1/discovery/recommend/songs`, data,
    {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy}
  )
}<commit_msg>移除无效参数<commit_after>// 每日推荐歌曲

module.exports = (query, request) => {
  const data = {
    total: true
  }
  return request(
    'POST', `https://music.163.com/weapi/v1/discovery/recommend/songs`, data,
    {crypto: 'weapi', cookie: query.cookie, proxy: query.proxy}
  )
}<|endoftext|>


<commit_before>/* See license.txt for terms of usage */

/**
 * This file defines Watch Panel APIs for test drivers.
 */

(function() {

// ********************************************************************************************* //
// Constants

// ********************************************************************************************* //
// Watch Panel API

/**
 * Appends a new expression into the Watch panel (the side panel for the Script panel).
 * @param {Object} chrome The current Firebug's chrome (can be null).
 * @param {Object} expression The expression to be evaluated.
 * @param {Object} callback Called after the result is displayed.
 */
this.addWatchExpression = function(chrome, expression, callback)
{
    if (!chrome)
        chrome = FW.Firebug.chrome;

    var watchPanel = FBTest.getPanel("watches", true);
    FBTest.ok(watchPanel, "The watch panel must be there; " + expression);

    // Create new watch expression (should be done by events).
    var panelNode = watchPanel.panelNode;
    var watchNewRow = panelNode.querySelector(".watchEditBox");
    FBTest.ok(watchNewRow, "The watch edit box must be there; " + expression);

    // Click to open a text editor.
    FBTest.mouseDown(watchNewRow);

    var editor = panelNode.querySelector(".completionInput");
    FBTest.ok(editor, "The editor must be there; " + expression);

    // Wait till the result is evaluated and displayed.
    var doc = FBTest.getSidePanelDocument();
    var recognizer = new MutationRecognizer(doc.defaultView, "tr",
        {"class": "memberRow watchRow"}, expression);

    recognizer.onRecognizeAsync((row) =>
    {
        var value = FW.FBL.getChildByClass(row, "memberValueCell");
        if (callback)
            callback(value);
    });

    // Set expression and press enter.
    FBTest.sendString(expression, editor);
    FBTest.sendKey("RETURN", editor);
};

/**
 * Sets new value for specified expression in the Watch side panel.
 *
 * @param {Object} chrome The current Firebug's chrome (can be null).
 * @param {Object} varName Name of the variable in the Watch panel.
 * @param {Object} expression New expression/value
 * @param {Object} callback Called after the result is displayed.
 */
this.setWatchExpressionValue = function(chrome, varName, expression, callback)
{
    if (!chrome)
        chrome = FW.Firebug.chrome;

    if (!callback)
    {
        FBTest.sysout("setWatchExpressionValue; ERROR missing callback");
        return;
    }

    var watchPanel = FBTest.getPanel("watches", true);
    var row = this.getWatchExpressionRow(chrome, varName);
    if (!row)
        return null;

    // Click to open a text editor.
    FBTest.dblclick(row);

    var panelNode = watchPanel.panelNode;
    var editor = panelNode.querySelector(".completionInput");
    FBTest.ok(editor, "The editor must be there; " + varName);

    // Wait till the tree-row (with given variable name) is refreshed
    var doc = FBTest.getSidePanelDocument();
    var recognizer = new MutationRecognizer(doc.defaultView, "Text",
        {"class": "memberLabelBox"}, varName);

    recognizer.onRecognizeAsync(function(element)
    {
        FBTest.sysout("setWatchExpressionValue; row refreshed: " + varName);

        var row = FW.FBL.getAncestorByClass(element, "memberRow");
        callback(row);
    });

    // Set expression and press enter.
    FBTest.sendString(expression, editor);
    FBTest.sendKey("RETURN", editor);
}

/**
 * Toggles boolean value in the Watch side panel.
 *
 * @param {Object} chrome The current Firebug's chrome (can be null).
 * @param {Object} varName Variable name
 * @param {Object} callback Called after the result is displayed.
 */
this.toggleWatchExpressionBooleanValue = function(chrome, varName, callback)
{
    if (!chrome)
        chrome = FW.Firebug.chrome;

    if (!callback)
    {
        FBTest.sysout("setWatchExpressionValue; ERROR missing callback");
        return;
    }

    var watchPanel = FBTest.getPanel("watches", true);
    var row = this.getWatchExpressionRow(chrome, varName);
    if (!row)
        return null;

    // Click to open a text editor.
    FBTest.dblclick(row);

    // Wait till the tree-row (with given variable name) is refreshed
    var doc = FBTest.getSidePanelDocument();
    var recognizer = new MutationRecognizer(doc.defaultView, "Text",
        {"class": "memberLabelBox"}, varName);

    recognizer.onRecognizeAsync(function(element)
    {
        FBTest.sysout("toggleWatchExpressionBooleanValue; row refreshed: " + varName);

        var row = FW.FBL.getAncestorByClass(element, "memberRow");
        callback(row);
    });
}

/**
 * Returns value for specified expression displayed in the Watch panel.
 *
 * @param {Object} chrome The current Firebug's chrome (optional)
 * @param {Object} expression The expression we are looking for.
 */
this.getWatchExpressionValue = function(chrome, expression)
{
    var row = this.getWatchExpressionRow(chrome, expression);
    if (!row)
        return null;

    var cell = row.querySelector(".memberValueCell");
    return cell.textContent;
};

/**
 * Returns the row element "<tr>" from the 'watches' side-panel for specified expression.
 *
 * @param {Object} chrome The current Firebug's chrome (optional)
 * @param {Object} expression The expression we are looking for.
 */
this.getWatchExpressionRow = function(chrome, expression)
{
    if (!chrome)
        chrome = FW.Firebug.chrome;

    var watchPanel = FBTest.getPanel("watches", true);
    FBTest.ok(watchPanel, "The watch panel must be there; " + expression);

    return getDOMMemberRow(watchPanel, expression);
};

// ********************************************************************************************* //
// Local Helpers

function getDOMMemberRow(panel, name)
{
    var panelNode = panel.panelNode;
    var rows = panelNode.querySelectorAll(".memberRow");

    // Iterate over all rows and pick the one that fits the name.
    for (var i=0; i<rows.length; i++)
    {
        var row = rows[i];
        var labelCell = row.querySelector(".memberLabelCell");
        if (labelCell.textContent == name)
            return row;
    }
}

// ********************************************************************************************* //
}).apply(FBTest);
<commit_msg>One more fix related to FBTest.addWatchExpression(), which crops the expression (fixes script/watch/7300/issue7300.js)<commit_after>/* See license.txt for terms of usage */

/**
 * This file defines Watch Panel APIs for test drivers.
 */

(function() {

// ********************************************************************************************* //
// Constants

// ********************************************************************************************* //
// Watch Panel API

/**
 * Appends a new expression into the Watch panel (the side panel for the Script panel).
 * @param {Object} chrome The current Firebug's chrome (can be null).
 * @param {Object} expression The expression to be evaluated.
 * @param {Object} callback Called after the result is displayed.
 */
this.addWatchExpression = function(chrome, expression, callback)
{
    if (!chrome)
        chrome = FW.Firebug.chrome;

    var watchPanel = FBTest.getPanel("watches", true);
    FBTest.ok(watchPanel, "The watch panel must be there; " + expression);

    // Create new watch expression (should be done by events).
    var panelNode = watchPanel.panelNode;
    var watchNewRow = panelNode.querySelector(".watchEditBox");
    FBTest.ok(watchNewRow, "The watch edit box must be there; " + expression);

    // Click to open a text editor.
    FBTest.mouseDown(watchNewRow);

    var editor = panelNode.querySelector(".completionInput");
    FBTest.ok(editor, "The editor must be there; " + expression);

    // Wait till the result is evaluated and displayed.
    var doc = FBTest.getSidePanelDocument();
    var recognizer = new MutationRecognizer(doc.defaultView, "tr",
        {"class": "memberRow watchRow"}, FW.FBL.cropString(expression, 25));

    recognizer.onRecognizeAsync((row) =>
    {
        var value = FW.FBL.getChildByClass(row, "memberValueCell");
        if (callback)
            callback(value);
    });

    // Set expression and press enter.
    FBTest.sendString(expression, editor);
    FBTest.sendKey("RETURN", editor);
};

/**
 * Sets new value for specified expression in the Watch side panel.
 *
 * @param {Object} chrome The current Firebug's chrome (can be null).
 * @param {Object} varName Name of the variable in the Watch panel.
 * @param {Object} expression New expression/value
 * @param {Object} callback Called after the result is displayed.
 */
this.setWatchExpressionValue = function(chrome, varName, expression, callback)
{
    if (!chrome)
        chrome = FW.Firebug.chrome;

    if (!callback)
    {
        FBTest.sysout("setWatchExpressionValue; ERROR missing callback");
        return;
    }

    var watchPanel = FBTest.getPanel("watches", true);
    var row = this.getWatchExpressionRow(chrome, varName);
    if (!row)
        return null;

    // Click to open a text editor.
    FBTest.dblclick(row);

    var panelNode = watchPanel.panelNode;
    var editor = panelNode.querySelector(".completionInput");
    FBTest.ok(editor, "The editor must be there; " + varName);

    // Wait till the tree-row (with given variable name) is refreshed
    var doc = FBTest.getSidePanelDocument();
    var recognizer = new MutationRecognizer(doc.defaultView, "Text",
        {"class": "memberLabelBox"}, varName);

    recognizer.onRecognizeAsync(function(element)
    {
        FBTest.sysout("setWatchExpressionValue; row refreshed: " + varName);

        var row = FW.FBL.getAncestorByClass(element, "memberRow");
        callback(row);
    });

    // Set expression and press enter.
    FBTest.sendString(expression, editor);
    FBTest.sendKey("RETURN", editor);
}

/**
 * Toggles boolean value in the Watch side panel.
 *
 * @param {Object} chrome The current Firebug's chrome (can be null).
 * @param {Object} varName Variable name
 * @param {Object} callback Called after the result is displayed.
 */
this.toggleWatchExpressionBooleanValue = function(chrome, varName, callback)
{
    if (!chrome)
        chrome = FW.Firebug.chrome;

    if (!callback)
    {
        FBTest.sysout("setWatchExpressionValue; ERROR missing callback");
        return;
    }

    var watchPanel = FBTest.getPanel("watches", true);
    var row = this.getWatchExpressionRow(chrome, varName);
    if (!row)
        return null;

    // Click to open a text editor.
    FBTest.dblclick(row);

    // Wait till the tree-row (with given variable name) is refreshed
    var doc = FBTest.getSidePanelDocument();
    var recognizer = new MutationRecognizer(doc.defaultView, "Text",
        {"class": "memberLabelBox"}, varName);

    recognizer.onRecognizeAsync(function(element)
    {
        FBTest.sysout("toggleWatchExpressionBooleanValue; row refreshed: " + varName);

        var row = FW.FBL.getAncestorByClass(element, "memberRow");
        callback(row);
    });
}

/**
 * Returns value for specified expression displayed in the Watch panel.
 *
 * @param {Object} chrome The current Firebug's chrome (optional)
 * @param {Object} expression The expression we are looking for.
 */
this.getWatchExpressionValue = function(chrome, expression)
{
    var row = this.getWatchExpressionRow(chrome, expression);
    if (!row)
        return null;

    var cell = row.querySelector(".memberValueCell");
    return cell.textContent;
};

/**
 * Returns the row element "<tr>" from the 'watches' side-panel for specified expression.
 *
 * @param {Object} chrome The current Firebug's chrome (optional)
 * @param {Object} expression The expression we are looking for.
 */
this.getWatchExpressionRow = function(chrome, expression)
{
    if (!chrome)
        chrome = FW.Firebug.chrome;

    var watchPanel = FBTest.getPanel("watches", true);
    FBTest.ok(watchPanel, "The watch panel must be there; " + expression);

    return getDOMMemberRow(watchPanel, expression);
};

// ********************************************************************************************* //
// Local Helpers

function getDOMMemberRow(panel, name)
{
    var panelNode = panel.panelNode;
    var rows = panelNode.querySelectorAll(".memberRow");

    // Iterate over all rows and pick the one that fits the name.
    for (var i=0; i<rows.length; i++)
    {
        var row = rows[i];
        var labelCell = row.querySelector(".memberLabelCell");
        if (labelCell.textContent == name)
            return row;
    }
}

// ********************************************************************************************* //
}).apply(FBTest);
<|endoftext|>


<commit_before> /* global Event, assert, process, setup, suite, test */

var CANVAS_GRAB_CLASS = 'a-grab-cursor';
var GRABBING_CLASS = 'a-grabbing';

suite('look-controls', function () {
  setup(function (done) {
    var el = this.sceneEl = document.createElement('a-scene');
    document.body.appendChild(el);
    el.addEventListener('camera-ready', function () {
      done();
    });
  });

  suite('exit-vr', function () {
    test('reset previous HMD position upon exit-vr event', function (done) {
      var el = this.sceneEl;
      var lookControls = el.camera.el.components['look-controls'];
      lookControls.hasPositionalTracking = false;
      lookControls.previousHMDPosition.set(1, 2, 3);
      process.nextTick(function () {
        assert.ok(lookControls.previousHMDPosition.length() === 0);
        done();
      });
      el.dispatchEvent(new Event('exit-vr'));
    });
  });

  suite('grabbing', function () {
    test('enables grab cursor on canvas', function () {
      this.sceneEl.canvas.classList.contains(CANVAS_GRAB_CLASS);
    });

    test('adds grabbing class to document body on mousedown', function (done) {
      var el = this.sceneEl;
      process.nextTick(function () {
        assert.ok(document.body.classList.contains(GRABBING_CLASS));
        document.body.classList.remove(GRABBING_CLASS);
        done();
      });
      var event = new Event('mousedown');
      event.button = 0;
      el.canvas.dispatchEvent(event);
    });

    test('removes grabbing class from document body on document body mouseup', function (done) {
      document.body.classList.add(GRABBING_CLASS);
      process.nextTick(function () {
        assert.notOk(document.body.classList.contains(GRABBING_CLASS));
        done();
      });
      window.dispatchEvent(new Event('mouseup'));
    });

    test('requests pointer lock on mousedown', function (done) {
      var canvasEl = this.sceneEl.canvas;

      var requestPointerLock = this.sinon.spy(canvasEl, 'requestPointerLock');

      process.nextTick(function () {
        assert.ok(requestPointerLock.called);
        document.body.classList.remove(GRABBING_CLASS);
        done();
      });

      var event = new Event('mousedown');
      event.button = 0;
      canvasEl.dispatchEvent(event);
    });

    test('does not request pointer lock when option is disabled', function (done) {
      var sceneEl = this.sceneEl;
      var canvasEl = sceneEl.canvas;
      var cameraEl = sceneEl.camera.el;

      var requestPointerLock = this.sinon.spy(canvasEl, 'requestPointerLock');

      cameraEl.setAttribute('look-controls', {pointerLockEnabled: false});

      process.nextTick(function () {
        assert.notOk(requestPointerLock.called);
        document.body.classList.remove(GRABBING_CLASS);
        done();
      });

      var event = new Event('mousedown');
      event.button = 0;
      canvasEl.dispatchEvent(event);
    });
  });

  suite('saveCameraPose', function () {
    test('saves camera pose when entering VR w/ positional tracking', function () {
      var sceneEl = this.sceneEl;
      var cameraEl = sceneEl.camera.el;
      var lookControlsComponent = cameraEl.components['look-controls'];
      lookControlsComponent.hasPositionalTracking = true;
      cameraEl.setAttribute('look-controls', {userHeight: 0});
      cameraEl.setAttribute('position', '3 3 3');
      sceneEl.emit('enter-vr');
      assert.shallowDeepEqual(lookControlsComponent.savedPose.position,
                              {x: 3.0, y: 3.0, z: 3.0});
    });

    test('does not save camera pose when entering VR w/o positional tracking', function () {
      var sceneEl = this.sceneEl;
      var cameraEl = sceneEl.camera.el;
      var lookControlsComponent = cameraEl.components['look-controls'];
      lookControlsComponent.hasPositionalTracking = false;
      sceneEl.emit('enter-vr');
      assert.notOk(lookControlsComponent.savedPose);
    });
  });

  suite('restoreCameraPose (exit VR)', function () {
    test('restores camera pose with headset', function () {
      var sceneEl = this.sceneEl;
      var cameraEl = sceneEl.camera.el;
      cameraEl.components['look-controls'].hasPositionalTracking = true;
      cameraEl.setAttribute('position', {x: 6, y: 6, z: 6});
      sceneEl.emit('enter-vr');
      cameraEl.setAttribute('position', {x: 9, y: 9, z: 9});
      assert.shallowDeepEqual(cameraEl.getAttribute('position'), {x: 9, y: 9, z: 9});
      sceneEl.emit('exit-vr');
      assert.shallowDeepEqual(cameraEl.getAttribute('position'), {x: 6, y: 6, z: 6});
    });

    test('does not restore camera pose without headset', function () {
      var sceneEl = this.sceneEl;
      var cameraEl = sceneEl.camera.el;
      cameraEl.components['look-controls'].hasPositionalTracking = false;
      sceneEl.emit('enter-vr');
      cameraEl.setAttribute('position', {x: 6, y: 6, z: 6});
      sceneEl.emit('exit-vr');
      assert.shallowDeepEqual(cameraEl.getAttribute('position'), {x: 6, y: 6, z: 6});
    });
  });
});
<commit_msg>fix look-controls test<commit_after> /* global Event, assert, process, setup, suite, test */

var CANVAS_GRAB_CLASS = 'a-grab-cursor';
var GRABBING_CLASS = 'a-grabbing';

suite('look-controls', function () {
  setup(function (done) {
    var el = this.sceneEl = document.createElement('a-scene');
    document.body.appendChild(el);
    el.addEventListener('camera-ready', function () {
      done();
    });
  });

  suite('exit-vr', function () {
    test('reset previous HMD position upon exit-vr event', function (done) {
      var el = this.sceneEl;
      var lookControls = el.camera.el.components['look-controls'];
      lookControls.hasPositionalTracking = false;
      lookControls.previousHMDPosition.set(1, 2, 3);
      process.nextTick(function () {
        assert.ok(lookControls.previousHMDPosition.length() === 0);
        done();
      });
      el.dispatchEvent(new Event('exit-vr'));
    });
  });

  suite('grabbing', function () {
    test('enables grab cursor on canvas', function () {
      this.sceneEl.canvas.classList.contains(CANVAS_GRAB_CLASS);
    });

    test('adds grabbing class to document body on mousedown', function (done) {
      var el = this.sceneEl;
      process.nextTick(function () {
        assert.ok(document.body.classList.contains(GRABBING_CLASS));
        document.body.classList.remove(GRABBING_CLASS);
        done();
      });
      var event = new Event('mousedown');
      event.button = 0;
      el.canvas.dispatchEvent(event);
    });

    test('removes grabbing class from document body on document body mouseup', function (done) {
      document.body.classList.add(GRABBING_CLASS);
      process.nextTick(function () {
        assert.notOk(document.body.classList.contains(GRABBING_CLASS));
        done();
      });
      window.dispatchEvent(new Event('mouseup'));
    });

    test('requests pointer lock on mousedown', function (done) {
      var cameraEl = this.sceneEl.camera.el;
      var canvasEl = this.sceneEl.canvas;

      var requestPointerLock = this.sinon.spy(canvasEl, 'requestPointerLock');
      cameraEl.setAttribute('look-controls', {pointerLockEnabled: true});

      process.nextTick(function () {
        assert.ok(requestPointerLock.called);
        document.body.classList.remove(GRABBING_CLASS);
        done();
      });

      var event = new Event('mousedown');
      event.button = 0;
      canvasEl.dispatchEvent(event);
    });

    test('does not request pointer lock when option is disabled', function (done) {
      var sceneEl = this.sceneEl;
      var canvasEl = sceneEl.canvas;
      var cameraEl = sceneEl.camera.el;

      var requestPointerLock = this.sinon.spy(canvasEl, 'requestPointerLock');

      cameraEl.setAttribute('look-controls', {pointerLockEnabled: false});

      process.nextTick(function () {
        assert.notOk(requestPointerLock.called);
        document.body.classList.remove(GRABBING_CLASS);
        done();
      });

      var event = new Event('mousedown');
      event.button = 0;
      canvasEl.dispatchEvent(event);
    });
  });

  suite('saveCameraPose', function () {
    test('saves camera pose when entering VR w/ positional tracking', function () {
      var sceneEl = this.sceneEl;
      var cameraEl = sceneEl.camera.el;
      var lookControlsComponent = cameraEl.components['look-controls'];
      lookControlsComponent.hasPositionalTracking = true;
      cameraEl.setAttribute('look-controls', {userHeight: 0});
      cameraEl.setAttribute('position', '3 3 3');
      sceneEl.emit('enter-vr');
      assert.shallowDeepEqual(lookControlsComponent.savedPose.position,
                              {x: 3.0, y: 3.0, z: 3.0});
    });

    test('does not save camera pose when entering VR w/o positional tracking', function () {
      var sceneEl = this.sceneEl;
      var cameraEl = sceneEl.camera.el;
      var lookControlsComponent = cameraEl.components['look-controls'];
      lookControlsComponent.hasPositionalTracking = false;
      sceneEl.emit('enter-vr');
      assert.notOk(lookControlsComponent.savedPose);
    });
  });

  suite('restoreCameraPose (exit VR)', function () {
    test('restores camera pose with headset', function () {
      var sceneEl = this.sceneEl;
      var cameraEl = sceneEl.camera.el;
      cameraEl.components['look-controls'].hasPositionalTracking = true;
      cameraEl.setAttribute('position', {x: 6, y: 6, z: 6});
      sceneEl.emit('enter-vr');
      cameraEl.setAttribute('position', {x: 9, y: 9, z: 9});
      assert.shallowDeepEqual(cameraEl.getAttribute('position'), {x: 9, y: 9, z: 9});
      sceneEl.emit('exit-vr');
      assert.shallowDeepEqual(cameraEl.getAttribute('position'), {x: 6, y: 6, z: 6});
    });

    test('does not restore camera pose without headset', function () {
      var sceneEl = this.sceneEl;
      var cameraEl = sceneEl.camera.el;
      cameraEl.components['look-controls'].hasPositionalTracking = false;
      sceneEl.emit('enter-vr');
      cameraEl.setAttribute('position', {x: 6, y: 6, z: 6});
      sceneEl.emit('exit-vr');
      assert.shallowDeepEqual(cameraEl.getAttribute('position'), {x: 6, y: 6, z: 6});
    });
  });
});
<|endoftext|>


<commit_before>const fs = require( 'fs' );
const spawnSync = require( 'child_process' ).spawnSync;

/**
   Get the number of letters inside the text

   @param text : string - Text where count the number of letters
   @return {number} - Number of letters
*/
function letters( text ) {
    return text.match( /\w/g ).length;
}

/**
   Get the number of sentences inside the text

   @param text : string - Text where count the number of sentences
   @return {number} - Number of sentences
*/
function sentences( text ) {
    var allCarriageReturn = text;

    // For each end lines or sentences add a point and carrige return.
    // Example:
    //   My mother going at home. He will go back friday. =>
    //   My mother going at home.
    //   He will go back friday.
    allCarriageReturn = allCarriageReturn.replace( /(\n|\. )/g, ".\n" );

    //Therefor the number of sentences is a number of the point preceded by
    //another symbol. The separator line will ignored because it haven't
    //nothing before. I believe that one sentence with less than three words is
    //absurde.
    return allCarriageReturn.match( /\w{3,}\s{0,}.$/gm ).length;
}

/**
   Get the number of words inside the text

   @param text : string - Text where count the number of words
   @return {number} - Number of words
*/
function words( text ) {
    return text.match( /\w+/g ).length;
}

exports.main = function ( path ) {
    // The path MUST have above struct:
    // res/section/all_file.tex
    path += "res/sections/"; // Attach the location when all sections are store

    var files = fs.readdirSync( path ); // Get all files
    var dcDetex = "";

    console.log( "Detected this files:" );

    // Apply detex every files and append content at dcDetex
    files.forEach( ( val, index, array ) => {
	console.log( val );

	var outSpawn = spawnSync( 'detex', [ path+val ] );
	dcDetex += `${outSpawn.stdout}\n`;
    });

    // Remove all matched form dcDetex
    var filter =
	"enumerate|" +
	"itemize|" +
	"center|" +
	"figure|" +
	"longtable|" +
	"description|" +
	"tabular|" +
	"table|" +
	"math|" +
	"name|" +
	"p.*cm|" + // measure
	"\s1.8\s|" +
	"\s2.*c.*0\.9\s|" +
	"\[.*\]|" +
	"(l\s?)*(l\s?c)(c\s?)*\s{0,}|" + // latex format table
	".*\.png$|" +
	"\t";

    // Convert filter string in a regex exp with global visibility
    var e = new RegExp( filter, "gm" );
    // Clean text catch
    var cleanText = dcDetex.replace( e, "" );

    console.log( `\nSentences: ${sentences( cleanText )}` );
    console.log( `Letters: ${letters( cleanText )}` );
    console.log( `Words: ${words( cleanText )}` );

    var seToLe =  300 * sentences( cleanText ) - 10 * letters( cleanText );
    var words = words( cleanText );

    return 89 + ( seToLe ) / words;
}
<commit_msg>Add start log<commit_after>const fs = require( 'fs' );
const spawnSync = require( 'child_process' ).spawnSync;

/**
   Get the number of letters inside the text

   @param text : string - Text where count the number of letters
   @return {number} - Number of letters
*/
function letters( text ) {
    return text.match( /\w/g ).length;
}

/**
   Get the number of sentences inside the text

   @param text : string - Text where count the number of sentences
   @return {number} - Number of sentences
*/
function sentences( text ) {
    var allCarriageReturn = text;

    // For each end lines or sentences add a point and carrige return.
    // Example:
    //   My mother going at home. He will go back friday. =>
    //   My mother going at home.
    //   He will go back friday.
    allCarriageReturn = allCarriageReturn.replace( /(\n|\. )/g, ".\n" );

    //Therefor the number of sentences is a number of the point preceded by
    //another symbol. The separator line will ignored because it haven't
    //nothing before. I believe that one sentence with less than three words is
    //absurde.
    return allCarriageReturn.match( /\w{3,}\s{0,}.$/gm ).length;
}

/**
   Get the number of words inside the text

   @param text : string - Text where count the number of words
   @return {number} - Number of words
*/
function words( text ) {
    return text.match( /\w+/g ).length;
}

exports.main = function ( path ) {
    console.log( "Run gulpease script..." );
    // The path MUST have above struct:
    // res/section/all_file.tex
    path += "res/sections/"; // Attach the location when all sections are store

    var files = fs.readdirSync( path ); // Get all files
    var dcDetex = "";

    console.log( "Detected this files:" );

    // Apply detex every files and append content at dcDetex
    files.forEach( ( val, index, array ) => {
	console.log( val );

	var outSpawn = spawnSync( 'detex', [ path+val ] );
	dcDetex += `${outSpawn.stdout}\n`;
    });

    // Remove all matched form dcDetex
    var filter =
	"enumerate|" +
	"itemize|" +
	"center|" +
	"figure|" +
	"longtable|" +
	"description|" +
	"tabular|" +
	"table|" +
	"math|" +
	"name|" +
	"p.*cm|" + // measure
	"\s1.8\s|" +
	"\s2.*c.*0\.9\s|" +
	"\[.*\]|" +
	"(l\s?)*(l\s?c)(c\s?)*\s{0,}|" + // latex format table
	".*\.png$|" +
	"\t";

    // Convert filter string in a regex exp with global visibility
    var e = new RegExp( filter, "gm" );
    // Clean text catch
    var cleanText = dcDetex.replace( e, "" );

    console.log( `\nSentences: ${sentences( cleanText )}` );
    console.log( `Letters: ${letters( cleanText )}` );
    console.log( `Words: ${words( cleanText )}` );

    var seToLe =  300 * sentences( cleanText ) - 10 * letters( cleanText );
    var words = words( cleanText );

    return 89 + ( seToLe ) / words;
}
<|endoftext|>


<commit_before>describe("masks", function() {

    var player,
        C = anm.C;

    var b = Builder._$,
        B = Builder;

    beforeEach(function() {
        this.addMatchers(_matchers);

        spyOn(document, 'getElementById').andReturn(_mocks.canvas);
        _fakeCallsForCanvasRelatedStuff();

        player = createPlayer('test-id');
    });

    it("should apply mask to an element", function() {

        var saveSpy = spyOn(_mocks.context2d, 'save');
        var restoreSpy = spyOn(_mocks.context2d, 'restore');

        var maskPaintSpy = jasmine.createSpy('mask-paint').andCallFake(function(ctx) {
            console.log('mask-paint');

            expect(saveSpy).toHaveBeenCalled();
            expect(elemPaintSpy).not.toHaveBeenCalled();
            expect(clipSpy).not.toHaveBeenCalled();
            expect(transformSpy).not.toHaveBeenCalled();

            saveSpy.reset();
        });

        var clipSpy = spyOn(_mocks.context2d, 'clip').andCallFake(function() {
            console.log('ctx-clip');

            expect(maskPaintSpy).toHaveBeenCalled();
            expect(elemPaintSpy).not.toHaveBeenCalled();
            expect(transformSpy).not.toHaveBeenCalled();

            maskPaintSpy.reset();
        });

        var elemPaintSpy = jasmine.createSpy('elem-paint').andCallFake(function(ctx) {
            console.log('elem-paint');

            expect(maskPaintSpy).not.toHaveBeenCalled();
            expect(clipSpy).toHaveBeenCalled();
            expect(transformSpy).toHaveBeenCalled();

            elemPaintSpy.reset();
            clipSpy.reset();
            maskPaintSpy.reset();
            saveSpy.reset();
            restoreSpy.reset();
            transformSpy.reset();
        });

        var scene = b().band([0, 1]);
        var elem = b().paint(elemPaintSpy);
        var mask = b().paint(maskPaintSpy);

        var transformSpy = spyOn(elem.v, 'transform').andCallThrough();

        scene.add(elem);

        elem.mask(mask);

        runs(function() {
            player.load(scene).play();
        });

        waitsFor(function() {
            return player.state.happens === C.STOPPED;
        }, 1200);

        runs(function() {
            expect(saveSpy).not.toHaveBeenCalled();
            expect(restoreSpy).toHaveBeenCalled();
        })
    });

});<commit_msg>removed logs from test<commit_after>describe("masks", function() {

    var player,
        C = anm.C;

    var b = Builder._$,
        B = Builder;

    beforeEach(function() {
        this.addMatchers(_matchers);

        spyOn(document, 'getElementById').andReturn(_mocks.canvas);
        _fakeCallsForCanvasRelatedStuff();

        player = createPlayer('test-id');
    });

    it("should apply mask to an element", function() {

        var saveSpy = spyOn(_mocks.context2d, 'save');
        var restoreSpy = spyOn(_mocks.context2d, 'restore');

        var maskPaintSpy = jasmine.createSpy('mask-paint').andCallFake(function(ctx) {
            expect(saveSpy).toHaveBeenCalled();
            expect(elemPaintSpy).not.toHaveBeenCalled();
            expect(clipSpy).not.toHaveBeenCalled();
            expect(transformSpy).not.toHaveBeenCalled();

            saveSpy.reset();
        });

        var clipSpy = spyOn(_mocks.context2d, 'clip').andCallFake(function() {
            expect(maskPaintSpy).toHaveBeenCalled();
            expect(elemPaintSpy).not.toHaveBeenCalled();
            expect(transformSpy).not.toHaveBeenCalled();

            maskPaintSpy.reset();
        });

        var elemPaintSpy = jasmine.createSpy('elem-paint').andCallFake(function(ctx) {
            expect(maskPaintSpy).not.toHaveBeenCalled();
            expect(clipSpy).toHaveBeenCalled();
            expect(transformSpy).toHaveBeenCalled();

            elemPaintSpy.reset();
            clipSpy.reset();
            maskPaintSpy.reset();
            saveSpy.reset();
            restoreSpy.reset();
            transformSpy.reset();
        });

        var scene = b().band([0, .5]);
        var elem = b().paint(elemPaintSpy);
        var mask = b().paint(maskPaintSpy);

        var transformSpy = spyOn(elem.v, 'transform').andCallThrough();

        scene.add(elem);

        elem.mask(mask);

        runs(function() {
            player.load(scene).play();
        });

        waitsFor(function() {
            return player.state.happens === C.STOPPED;
        }, 700);

        runs(function() {
            expect(saveSpy).not.toHaveBeenCalled();
            expect(restoreSpy).toHaveBeenCalled();
        })
    });

});<|endoftext|>


<commit_before>/* @flow */
/* eslint-disable no-undef */
/* eslint-disable no-console */

import {
  STATE_IDENTIFIER,
  MODULE_CHUNK_MAPPING_IDENTIFIER,
} from './constants';
import { es6Safe } from './utils';

export default function rehydrateState() {
  return new Promise((resolve) => {
    if (
      // Has this source been bundled by webpack, making the following global
      // available?
      // $FlowFixMe
      !__webpack_require__
      // Running in the browser?
      || !window
      // Has the rehydrate state been bound to the window object?
      || !window[STATE_IDENTIFIER]
      // Has the module/chunk mapping been bound to the window object? If not
      // there is no point continuing as we won't know how to map the
      // moduleHash's to the correct webpack identifiers.
      || !window[MODULE_CHUNK_MAPPING_IDENTIFIER]
      ) {
      // Should we warn the user?  If they are using the rehydrateState
      // function perhaps they are expecting it to actually do some
      // rehydrating. :)
      resolve();
      return;
    }

    const moduleChunkMap = window[MODULE_CHUNK_MAPPING_IDENTIFIER];
    const { chunks, modules } = window[STATE_IDENTIFIER];

    const safelyFetchChunk = (chunkName : string) => {
      try {
        __webpack_require__.e(moduleChunkMap.chunks[chunkName]);
      } catch (err) {
        // We swallow the error. It's possible an active webpack plugin did
        // some "shifting around" of our chunks.
      }
    };

    const resolveModule = (moduleHash : string) => ({
      id: moduleHash,
      module: es6Safe(__webpack_require__(moduleChunkMap.modules[moduleHash])),
    });

    Promise.all(chunks.map(safelyFetchChunk))
      .then(() => modules.map(resolveModule))
      .then(resolve)
      .catch((err) => {
        console.log(
          'An error occurred whilst attempting to rehydrate code-split-component.',
          err,
          err.stack,
        );
      });
  });
}
<commit_msg>Fixes small bug, ensuring that the chunk fetching within the rehydrateState function returns the require promise.<commit_after>/* @flow */
/* eslint-disable no-undef */
/* eslint-disable no-console */

import {
  STATE_IDENTIFIER,
  MODULE_CHUNK_MAPPING_IDENTIFIER,
} from './constants';
import { es6Safe } from './utils';

export default function rehydrateState() {
  return new Promise((resolve) => {
    if (
      // Has this source been bundled by webpack, making the following global
      // available?
      // $FlowFixMe
      !__webpack_require__
      // Running in the browser?
      || !window
      // Has the rehydrate state been bound to the window object?
      || !window[STATE_IDENTIFIER]
      // Has the module/chunk mapping been bound to the window object? If not
      // there is no point continuing as we won't know how to map the
      // moduleHash's to the correct webpack identifiers.
      || !window[MODULE_CHUNK_MAPPING_IDENTIFIER]
      ) {
      // Should we warn the user?  If they are using the rehydrateState
      // function perhaps they are expecting it to actually do some
      // rehydrating. :)
      resolve();
      return;
    }

    const moduleChunkMap = window[MODULE_CHUNK_MAPPING_IDENTIFIER];
    const { chunks, modules } = window[STATE_IDENTIFIER];

    const safelyFetchChunk = (chunkName : string) => {
      try {
        return __webpack_require__.e(moduleChunkMap.chunks[chunkName]);
      } catch (err) {
        // We swallow the error. It's possible an active webpack plugin did
        // some "shifting around" of our chunks.
        return false;
      }
    };

    const resolveModule = (moduleHash : string) => ({
      id: moduleHash,
      module: es6Safe(__webpack_require__(moduleChunkMap.modules[moduleHash])),
    });

    Promise.all(chunks.map(safelyFetchChunk))
      .then(() => modules.map(resolveModule))
      .then(resolve)
      .catch((err) => {
        console.log(
          'An error occurred whilst attempting to rehydrate code-split-component.',
          err,
          err.stack,
        );
      });
  });
}
<|endoftext|>


<commit_before>var storage = require('client/applications/dashboard/cores/storage');
var fetch = require('client/applications/dashboard/cores/fetch');
var RSVP = require('rsvp');

module.exports = {
  getList: function(forced) {
    return storage.getList(['router', 'network', 'subnet', 'ipsec', 'vpnservice', 'ikepolicy', 'ipsecpolicy'], forced).then((res) => {
      var exNetworks = [];
      res.network.forEach((item) => {
        if (item['router:external']) {
          exNetworks.push(item);
          return true;
        }
        return false;
      });

      if(exNetworks.length > 1) {
        res.router.forEach(r => {
          if(r.external_gateway_info) {
            exNetworks.some(n => {
              if(r.external_gateway_info.network_id === n.id) {
                r.external_gateway_info.network_name = n.name;
                return true;
              }
              return false;
            });
          }
        });
      }

      res.router.forEach((router, index) => {
        res.router[index].vpnservices = [];
        res.router[index].ipsec_site_connections = [];
        res.router[index].ikepolicies = [];
        res.router[index].ipsecpolicies = [];
      });
      res.vpnservice.forEach((vpnService) => {
        res.router.forEach((router, index) => {
          if (vpnService.router_id === router.id) {
            res.router[index].vpnservices.push(vpnService);
          }
        });
      });

      res.vpnservice.forEach((vpnService, index) => {
        res.subnet.forEach((subnet) => {
          if (vpnService.subnet_id === subnet.id) {
            res.vpnservice[index].subnet = subnet;
          }
        });
      });

      res.router.forEach((router, index) => {
        res.router[index].ikepolicies = res.ikepolicy.ikepolicies;
        res.router[index].ipsecpolicies = res.ipsecpolicy.ipsecpolicies;
        res.router[index].vpnservices.forEach((vpnservice) => {
          res.ipsec[0] && res.ipsec[0].ipsec_site_connections.forEach((site) => {
            if (site.vpnservice_id === vpnservice.id) {
              res.router[index].ipsec_site_connections.push(site);
            }
          });
        });
      });
      return res.router;
    });
  },
  getPrices: function() {
    return fetch.get({
      url: '/proxy/gringotts/v2/products'
    });
  },
  editRouterName: function(item, newName) {
    var data = {};
    data.router = {};
    data.router.name = newName;

    return fetch.put({
      url: '/proxy/neutron/v2.0/routers/' + item.id,
      data: data
    });
  },
  deleteRouters: function(items) {
    var deferredList = [];
    items.forEach((item) => {
      deferredList.push(fetch.delete({
        url: '/proxy/neutron/v2.0/routers/' + item.id
      }));
    });
    return RSVP.all(deferredList);
  },
  createRouter: function(data) {
    return fetch.post({
      url: '/proxy/neutron/v2.0/routers',
      data: {
        router: data
      }
    });
  },
  updateRouter: function(routerId, data) {
    return fetch.put({
      url: '/proxy/neutron/v2.0/routers/' + routerId,
      data: {
        router: data
      }
    });
  },
  addInterface: function(routerId, data) {
    return fetch.put({
      url: '/proxy/neutron/v2.0/routers/' + routerId + '/add_router_interface',
      data: data
    });
  },
  changeFip: function(routerId, fipId) {
    return fetch.put({
      url: '/proxy/neutron/v2.0/floatingips/' + fipId,
      data: {
        floatingip: {
          port_id: routerId
        }
      }
    });
  },
  getGateway: function() {
    return storage.getList(['network']).then(function(data) {
      var exNetworks = [];
      data.network.forEach((item) => {
        if (item['router:external']) {
          exNetworks.push(item);
          return true;
        }
        return false;
      });
      return exNetworks;
    });
  },
  getSubnets: function(forced) {
    return storage.getList(['subnet'], forced).then(function(data) {
      return data.subnet;
    });
  },
  detachSubnet: function(item) {
    var data = {};
    data.subnet_id = item.childItem.id;

    return fetch.put({
      url: '/proxy/neutron/v2.0/routers/' + item.rawItem.id + '/remove_router_interface',
      data: data
    });
  },
  createVpnService: function(data) {
    var url = '/proxy/neutron/v2.0/vpn/vpnservices';
    return fetch.post({
      url: url,
      data: data
    }).then(res => {
      return res.vpnservice;
    });
  },
  deleteVpnService: function(id) {
    var url = '/proxy/neutron/v2.0/vpn/vpnservices/' + id;
    return fetch.delete({
      url: url
    });
  },
  createTunnel: function(data) {
    var url = '/proxy/neutron/v2.0/vpn/ipsec-site-connections';
    return fetch.post({
      url: url,
      data: data
    });
  },
  updateIpsecConnection: function(id, data) {
    var url = '/proxy/neutron/v2.0/vpn/ipsec-site-connections/' + id;
    return fetch.put({
      url: url,
      data: data
    }).then(res => {
      return res;
    });
  },
  deleteIpsecConnection: function(id) {
    var url = '/proxy/neutron/v2.0/vpn/ipsec-site-connections/' + id;
    return fetch.delete({
      url: url
    });
  }
};
<commit_msg>ipsec bugfix<commit_after>var storage = require('client/applications/dashboard/cores/storage');
var fetch = require('client/applications/dashboard/cores/fetch');
var RSVP = require('rsvp');

module.exports = {
  getList: function(forced) {
    var storgeList = ['router', 'network', 'subnet'];
    if (HALO.settings.enable_ipsec) {
      storgeList = storgeList.concat(['ipsec', 'vpnservice', 'ikepolicy', 'ipsecpolicy']);
    }
    return storage.getList(storgeList, forced).then((res) => {
      var exNetworks = [];
      res.network.forEach((item) => {
        if (item['router:external']) {
          exNetworks.push(item);
          return true;
        }
        return false;
      });

      if(exNetworks.length > 1) {
        res.router.forEach(r => {
          if(r.external_gateway_info) {
            exNetworks.some(n => {
              if(r.external_gateway_info.network_id === n.id) {
                r.external_gateway_info.network_name = n.name;
                return true;
              }
              return false;
            });
          }
        });
      }
      if (HALO.settings.enable_ipsec) {
        res.router.forEach((router, index) => {
          res.router[index].vpnservices = [];
          res.router[index].ipsec_site_connections = [];
          res.router[index].ikepolicies = [];
          res.router[index].ipsecpolicies = [];
        });
        res.vpnservice.forEach((vpnService) => {
          res.router.forEach((router, index) => {
            if (vpnService.router_id === router.id) {
              res.router[index].vpnservices.push(vpnService);
            }
          });
        });

        res.vpnservice.forEach((vpnService, index) => {
          res.subnet.forEach((subnet) => {
            if (vpnService.subnet_id === subnet.id) {
              res.vpnservice[index].subnet = subnet;
            }
          });
        });

        res.router.forEach((router, index) => {
          res.router[index].ikepolicies = res.ikepolicy.ikepolicies;
          res.router[index].ipsecpolicies = res.ipsecpolicy.ipsecpolicies;
          res.router[index].vpnservices.forEach((vpnservice) => {
            res.ipsec[0] && res.ipsec[0].ipsec_site_connections.forEach((site) => {
              if (site.vpnservice_id === vpnservice.id) {
                res.router[index].ipsec_site_connections.push(site);
              }
            });
          });
        });
      }
      return res.router;
    });
  },
  getPrices: function() {
    return fetch.get({
      url: '/proxy/gringotts/v2/products'
    });
  },
  editRouterName: function(item, newName) {
    var data = {};
    data.router = {};
    data.router.name = newName;

    return fetch.put({
      url: '/proxy/neutron/v2.0/routers/' + item.id,
      data: data
    });
  },
  deleteRouters: function(items) {
    var deferredList = [];
    items.forEach((item) => {
      deferredList.push(fetch.delete({
        url: '/proxy/neutron/v2.0/routers/' + item.id
      }));
    });
    return RSVP.all(deferredList);
  },
  createRouter: function(data) {
    return fetch.post({
      url: '/proxy/neutron/v2.0/routers',
      data: {
        router: data
      }
    });
  },
  updateRouter: function(routerId, data) {
    return fetch.put({
      url: '/proxy/neutron/v2.0/routers/' + routerId,
      data: {
        router: data
      }
    });
  },
  addInterface: function(routerId, data) {
    return fetch.put({
      url: '/proxy/neutron/v2.0/routers/' + routerId + '/add_router_interface',
      data: data
    });
  },
  changeFip: function(routerId, fipId) {
    return fetch.put({
      url: '/proxy/neutron/v2.0/floatingips/' + fipId,
      data: {
        floatingip: {
          port_id: routerId
        }
      }
    });
  },
  getGateway: function() {
    return storage.getList(['network']).then(function(data) {
      var exNetworks = [];
      data.network.forEach((item) => {
        if (item['router:external']) {
          exNetworks.push(item);
          return true;
        }
        return false;
      });
      return exNetworks;
    });
  },
  getSubnets: function(forced) {
    return storage.getList(['subnet'], forced).then(function(data) {
      return data.subnet;
    });
  },
  detachSubnet: function(item) {
    var data = {};
    data.subnet_id = item.childItem.id;

    return fetch.put({
      url: '/proxy/neutron/v2.0/routers/' + item.rawItem.id + '/remove_router_interface',
      data: data
    });
  },
  createVpnService: function(data) {
    var url = '/proxy/neutron/v2.0/vpn/vpnservices';
    return fetch.post({
      url: url,
      data: data
    }).then(res => {
      return res.vpnservice;
    });
  },
  deleteVpnService: function(id) {
    var url = '/proxy/neutron/v2.0/vpn/vpnservices/' + id;
    return fetch.delete({
      url: url
    });
  },
  createTunnel: function(data) {
    var url = '/proxy/neutron/v2.0/vpn/ipsec-site-connections';
    return fetch.post({
      url: url,
      data: data
    });
  },
  updateIpsecConnection: function(id, data) {
    var url = '/proxy/neutron/v2.0/vpn/ipsec-site-connections/' + id;
    return fetch.put({
      url: url,
      data: data
    }).then(res => {
      return res;
    });
  },
  deleteIpsecConnection: function(id) {
    var url = '/proxy/neutron/v2.0/vpn/ipsec-site-connections/' + id;
    return fetch.delete({
      url: url
    });
  }
};
<|endoftext|>


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

var request = require('util/request').request;
var testUtil = require('util/test');

exports.test_rate_limiting = function(test, assert) {
  var options = {'return_response': true, 'expected_status_codes': [200]}, server = null,
      reqCountPath1 = 0, reqCountPath2 = 0;

  options.headers = {'X-Tenant-Id': '7777', 'X-Auth-Token': 'dev'};
  async.waterfall([
    function startBackendServer(callback) {
      testUtil.getTestHttpServer(9001, '127.0.0.1', function(err, _server) {
        server = _server;

        server.get('/test/a', function(req, res) {
          var code;

          if (req.headers.hasOwnProperty('x-rp-error-code')) {
            code = testUtil.PROXY_ERROR_CODE_TO_HTTP_CODE_MAP[req.headers['x-rp-error-code']];
            res.writeHead(code, {});
            res.end(req.headers['x-rp-error-message']);
            return;
          }

          reqCountPath1++;
          res.writeHead(200, {});
          res.end();
        });

        server.get('/bar', function(req, res) {
          var code;

          if (req.headers.hasOwnProperty('x-rp-error-code')) {
            code = testUtil.PROXY_ERROR_CODE_TO_HTTP_CODE_MAP[req.headers['x-rp-error-code']];
            res.writeHead(code, {});
            res.end(req.headers['x-rp-error-message']);
            return;
          }

          reqCountPath2++;
          res.writeHead(200, {});
          res.end();
        });

        testUtil.setupErrorEchoHandlers(server);
        callback();
      });
    },

    function issueRequestsPath1NotRateLimited(callback) {
      async.forEach([1, 2, 3, 4], function(_, callback) {
        request('http://127.0.0.1:9000/test/a', 'GET', null, options, function(err, res) {
          assert.ok(!err);
          assert.equal(res.statusCode, 200);

          callback();
        });
      }, callback);
    },

    function testPath1IsRateLimited(callback) {
      // After 4 requests, path 1 should be rate limited
      request('http://127.0.0.1:9000/test/a', 'GET', null, options, function(err, res) {
        assert.ok(err);
        assert.ok(err.statusCode, 400);

        assert.equal(res.headers['x-ratelimit-path-regex'], '/test/.*');
        assert.equal(res.headers['x-ratelimit-limit'], 4);
        assert.equal(res.headers['x-ratelimit-used'], 4);
        assert.equal(res.headers['x-ratelimit-window'], '4 seconds');

        assert.match(res.body, /Limit of 4 requests in 4 seconds for path .*? has been reached/i);
        callback();
      });
    },

    function issueRequestsPath2NotRateLimited(callback) {
      async.forEach([6, 7, 8, 9, 10], function(_, callback) {
        request('http://127.0.0.1:9000/bar', 'GET', null, options, function(err, res) {
          assert.ok(!err);
          assert.equal(res.statusCode, 200);
          callback();
        });
      }, callback);
    },

    function testPath2IsRateLimited(callback) {
      // After 10 requests total, path 2 should be rate limited
      request('http://127.0.0.1:9000/bar', 'GET', null, options, function(err, res) {
        assert.ok(err);
        assert.ok(err.statusCode, 400);

        assert.equal(res.headers['x-ratelimit-path-regex'], '/.*');
        assert.equal(res.headers['x-ratelimit-limit'], 10);
        assert.equal(res.headers['x-ratelimit-window'], '4 seconds');

        assert.match(res.body, /Limit of 10 requests in 4 seconds for path .*? has been reached/i);
        callback();
      });
    },

    function wait(callback) {
      // Bucket size is 4 seconds, wait period + 2 seconds before checking
      // the limits again
      setTimeout(callback, (6 * 1000));
    },

    function testPath1IsNotRateLimited(callback) {
      // Limit shouldn't affect this request anymore
      request('http://127.0.0.1:9000/test/a', 'GET', null, options, function(err, res) {
        assert.ok(!err);
        assert.equal(res.statusCode, 200);

        assert.equal(res.headers['x-ratelimit-path-regex'], '/test/.*');
        assert.equal(res.headers['x-ratelimit-limit'], 4);
        assert.equal(res.headers['x-ratelimit-used'], 1);
        assert.equal(res.headers['x-ratelimit-window'], '4 seconds');
        callback();
      });
    },

    function testPath2IsNotRateLimited(callback) {
      // Limit shouldn't affect this request anymore
      request('http://127.0.0.1:9000/bar', 'GET', null, options, function(err, res) {
        assert.ok(!err);
        assert.equal(res.statusCode, 200);

        callback();
      });
    }
  ],

  function(err) {
    if (server) {
      server.close();
    }

    assert.equal(reqCountPath1, 5);
    assert.ok([5, 6].indexOf(reqCountPath2) !== -1);
    test.finish();
  });
};
<commit_msg>Add a test case for it.<commit_after>var async = require('async');

var request = require('util/request').request;
var testUtil = require('util/test');

exports.test_rate_limiting = function(test, assert) {
  var options = {'return_response': true, 'expected_status_codes': [200]}, server = null,
      reqCountPath1 = 0, reqCountPath2 = 0;

  options.headers = {'X-Tenant-Id': '7777', 'X-Auth-Token': 'dev'};
  async.waterfall([
    function startBackendServer(callback) {
      testUtil.getTestHttpServer(9001, '127.0.0.1', function(err, _server) {
        server = _server;

        server.get('/test/a', function(req, res) {
          var code;

          if (req.headers.hasOwnProperty('x-rp-error-code')) {
            code = testUtil.PROXY_ERROR_CODE_TO_HTTP_CODE_MAP[req.headers['x-rp-error-code']];
            res.writeHead(code, {});
            res.end(req.headers['x-rp-error-message']);
            return;
          }

          reqCountPath1++;
          res.writeHead(200, {});
          res.end();
        });

        server.get('/bar', function(req, res) {
          var code;

          if (req.headers.hasOwnProperty('x-rp-error-code')) {
            code = testUtil.PROXY_ERROR_CODE_TO_HTTP_CODE_MAP[req.headers['x-rp-error-code']];
            res.writeHead(code, {});
            res.end(req.headers['x-rp-error-message']);
            return;
          }

          reqCountPath2++;
          res.writeHead(200, {});
          res.end();
        });

        server.post('/rate_limits', function(req, res) {
          var buffer = '';

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

          req.on('end', function() {
            res.writeHead(200, {'content-type': 'application/json'});
            res.end(buffer);
          });
        });

        testUtil.setupErrorEchoHandlers(server);
        callback();
      });
    },

    function issueRequestsPath1NotRateLimited(callback) {
      async.forEach([1, 2, 3, 4], function(_, callback) {
        request('http://127.0.0.1:9000/test/a', 'GET', null, options, function(err, res) {
          assert.ok(!err);
          assert.equal(res.statusCode, 200);

          callback();
        });
      }, callback);
    },

    function testPath1IsRateLimited(callback) {
      // After 4 requests, path 1 should be rate limited
      request('http://127.0.0.1:9000/test/a', 'GET', null, options, function(err, res) {
        assert.ok(err);
        assert.ok(err.statusCode, 400);

        assert.equal(res.headers['x-ratelimit-path-regex'], '/test/.*');
        assert.equal(res.headers['x-ratelimit-limit'], 4);
        assert.equal(res.headers['x-ratelimit-used'], 4);
        assert.equal(res.headers['x-ratelimit-window'], '4 seconds');

        assert.match(res.body, /Limit of 4 requests in 4 seconds for path .*? has been reached/i);
        callback();
      });
    },

    function issueRequestsPath2NotRateLimited(callback) {
      async.forEach([6, 7, 8, 9, 10], function(_, callback) {
        request('http://127.0.0.1:9000/bar', 'GET', null, options, function(err, res) {
          assert.ok(!err);
          assert.equal(res.statusCode, 200);
          callback();
        });
      }, callback);
    },

    function testPath2IsRateLimited(callback) {
      // After 10 requests total, path 2 should be rate limited
      request('http://127.0.0.1:9000/bar', 'GET', null, options, function(err, res) {
        assert.ok(err);
        assert.ok(err.statusCode, 400);

        assert.equal(res.headers['x-ratelimit-path-regex'], '/.*');
        assert.equal(res.headers['x-ratelimit-limit'], 10);
        assert.equal(res.headers['x-ratelimit-window'], '4 seconds');

        assert.match(res.body, /Limit of 10 requests in 4 seconds for path .*? has been reached/i);
        callback();
      });
    },

    function wait(callback) {
      // Bucket size is 4 seconds, wait period + 2 seconds before checking
      // the limits again
      setTimeout(callback, (6 * 1000));
    },

    function testPath1IsNotRateLimited(callback) {
      // Limit shouldn't affect this request anymore
      request('http://127.0.0.1:9000/test/a', 'GET', null, options, function(err, res) {
        assert.ok(!err);
        assert.equal(res.statusCode, 200);

        assert.equal(res.headers['x-ratelimit-path-regex'], '/test/.*');
        assert.equal(res.headers['x-ratelimit-limit'], 4);
        assert.equal(res.headers['x-ratelimit-used'], 1);
        assert.equal(res.headers['x-ratelimit-window'], '4 seconds');
        callback();
      });
    },

    function testPath2IsNotRateLimited(callback) {
      // Limit shouldn't affect this request anymore
      request('http://127.0.0.1:9000/bar', 'GET', null, options, function(err, res) {
        assert.ok(!err);
        assert.equal(res.statusCode, 200);

        callback();
      });
    },

    function getLimits(callback) {
      request('http://127.0.0.1:9000/limits', 'GET', null, options, function(err, res) {
        var data = JSON.parse(res.body);

        assert.ok(!err);
        assert.equal(res.statusCode, 200);
        assert.equal(data.length, 2); // 2 rules

        assert.equal(data[0].method, 'GET');
        assert.equal(data[0].path_regex, '/.*');
        assert.equal(data[0].limit, 10);
        assert.equal(data[0].used, 2);
        assert.equal(data[0].period, 4);
        callback();
      });
    }
  ],

  function(err) {
    if (server) {
      server.close();
    }

    assert.equal(reqCountPath1, 5);
    assert.ok([5, 6].indexOf(reqCountPath2) !== -1);
    test.finish();
  });
};
<|endoftext|>


<commit_before>
// We define a tracker dependency that we invalidate every 5 seconds to
// refresh `moment.fromNow()` texts reactively.
momentDependency = new Tracker.Dependency;
setInterval(function() {
  momentDependency.changed();
}, 5000);

// Register a (reactive) Blaze helper that we can use in meteor templates
Blaze.registerHelper('moment', function(date, format) {
  var m = moment(date);

  if (_.isString(format)) {
    m = m.format(format);
  } else {
    momentDependency.depend();
    m = m.fromNow();
  }

  return m;
});

// Everytime the TAPi18n language change we change the moment locale in
// adequacy. If we haven't done it already we download the moment translation
// file using a ajax query.

// TAPi18n was loaded using a weak dependency, so we need the verify package
// presence before executing this file.
if (Package['tap:i18n']) {

  // English is the default language and we don't need to load its translation.
  var alreadyLoadedLanguages = ['en'];

  Meteor.startup(function() {
    Tracker.autorun(function() {
      var language = TAPi18n.getLanguage();
      var localePath = 'packages/mquandalle_moment/locale/' + language + '.js';
      if (alreadyLoadedLanguages.indexOf(language) === -1) {
        $.ajax({
          url: Meteor.absoluteUrl(localePath),
          dataType: 'script',
          success: function() {
            momentDependency.changed();
            moment.locale(language);
            alreadyLoadedLanguages.push(language);
          }
        });
      } else {
        moment.locale(language);
      }
    });
  });
}
<commit_msg>Bugfix, the moment locale filename is lowercase<commit_after>
// We define a tracker dependency that we invalidate every 5 seconds to
// refresh `moment.fromNow()` texts reactively.
momentDependency = new Tracker.Dependency;
setInterval(function() {
  momentDependency.changed();
}, 5000);

// Register a (reactive) Blaze helper that we can use in meteor templates
Blaze.registerHelper('moment', function(date, format) {
  var m = moment(date);

  if (_.isString(format)) {
    m = m.format(format);
  } else {
    momentDependency.depend();
    m = m.fromNow();
  }

  return m;
});

// Everytime the TAPi18n language change we change the moment locale in
// adequacy. If we haven't done it already we download the moment translation
// file using a ajax query.

// TAPi18n was loaded using a weak dependency, so we need the verify package
// presence before executing this file.
if (Package['tap:i18n']) {

  // English is the default language and we don't need to load its translation.
  var alreadyLoadedLanguages = ['en'];

  Meteor.startup(function() {
    Tracker.autorun(function() {
      var language = TAPi18n.getLanguage();
      var localePath = 'packages/mquandalle_moment/locale/' + language.toLowerCase() + '.js';
      if (alreadyLoadedLanguages.indexOf(language) === -1) {
        $.ajax({
          url: Meteor.absoluteUrl(localePath),
          dataType: 'script',
          success: function() {
            momentDependency.changed();
            moment.locale(language);
            alreadyLoadedLanguages.push(language);
          }
        });
      } else {
        moment.locale(language);
      }
    });
  });
}
<|endoftext|>