<commit_before>/**
 * AUTO TRACKER LIKE JS
 *
 * @objectives
 * - Track forms
 * - Use Session storage
 * - Send data
 *
 *
 *
 * @type {{init: Function}}
 */

var AutoTracker = {
  init: function(options){
    var default_options = {
      visitExpire: 4*60*60*1000,
      visitorExpire: 365*24*60*60*1000
    };

    /* Set default option if option not available */
    for(var i in default_options){
      if(default_options.hasOwnProperty(i)){
        if(!options[i]){
          options[i] = default_options[i]
        }
      }
    }
    new AutoTrackerClass(options)
  }
};

function AutoTrackerClass(options){

  var _this         = this;
  this.visitId      = "";
  this.visitorsId   = "";
  this.pageUrl      = "http://job_search.dev/auto-tracker-image.gif";
  this.formUrl      = "http://job_search.dev/auto-tracker-form.gif";
  this.queueFormData = [];
  this.ajaxOnProcess = false;

  /**
   * Generate secrets key
   * @returns {string}
   */
  this.generateSecretKey = function(){
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
      var r = Math.random() * 16 | 0,
        v = c == 'x' ? r : (r & 0x3 | 0x8);
      return v.toString(16);
    });
  };

  /* Initial Stages */
  /* Create VisitID and VisitorsID and store it in cookies */

  var allDataObject =  {
    form_submit_data:[],
    view_change_data:[],
    event_change_data:[]
  };

  /* Set Session if not exists */

  this.setStorageIfNotExist = function(key_a,allDataObject){
    if(sessionStorage.getItem(key_a)){
      allDataObject[key_a] = JSON.parse(sessionStorage.getItem(key_a))
    }else{
      sessionStorage.setItem(key_a,JSON.stringify(allDataObject[key_a]));
    }
  };

  /* Check existence and set default values */
  for(var key_a in allDataObject){
    if(allDataObject.hasOwnProperty(key_a)){
      _this.setStorageIfNotExist(key_a,allDataObject)
    }
  }
  this.getSessionData = function(key){
    allDataObject[key] = JSON.parse(sessionStorage.getItem(key))|| [];
  }
  this.removeSessionData = function(key){
    sessionStorage.removeItem(key);
  }
  /* Set session data */
  this.setSessionData = function(key,data,clear){
    if(typeof clear=="undefined") clear=false;
    if(clear){
      console.log("Remove")
     _this.removeSessionData(key);
    }
    _this.getSessionData(key);
    if(allDataObject[key].length < 5){
      if(Array.isArray(data)){
        for(var ai=0; ai<data.length; ai++){
          allDataObject[key].push(data[ai]);
        }
      }else{
        allDataObject[key].push(data);
      }
      sessionStorage.setItem(key,JSON.stringify(allDataObject[key]))
    }else{
      _this.removeSessionData(key)
    }
  };

  /* end session data */

  /**
   *
   * @param cname
   * @returns {*}
   */
  this.getCookies = function(cname){
    var name = cname + "=";
    var ca = document.cookie.split(';');
    for(var i = 0; i <ca.length; i++) {
      var c = ca[i];
      while (c.charAt(0)==' ') {
        c = c.substring(1);
      }
      if (c.indexOf(name) == 0) {
        return c.substring(name.length,c.length);
      }
    }
    return "";
  };

  /**
   *
   * @param cookieName
   * @param value
   * @param cookiesExpire
   */
  this.setCookies = function(cookieName,value,cookiesExpire){
    var d = new Date();
    d.setTime(d.getTime() + cookiesExpire);
    var expireTime = d.toUTCString();
    document.cookie= cookieName+"="+value+";expires="+expireTime+";path=/";
  };

  this.setVisitIds = function(variableId,variableName,value,expireTime,clear){
    // Check cookies or create one
    if(_this.getCookies(variableName)==""){
      _this[variableId] = _this.generateSecretKey();
      _this.setCookies(variableName,value,expireTime);
    }else{
      _this[variableId] = _this.getCookies(variableName);
    }
  };

  /** VISITORS ID **/
  this.setVisitIds('visitorsId',"visitorsId",this.generateSecretKey(),options.visitorExpire);
  /** END VISITORS ID */

this.sendPageViewData = function(url){
  if(allDataObject['view_change_data'] && Array.isArray(allDataObject['view_change_data']) && ['view_change_data'].length > 0){
    var sendViewData = new XMLHttpRequest();
    var sendData = (JSON.stringify(allDataObject['view_change_data']));
    sendViewData.open('GET',url+'?data='+sendData,false);
    sendViewData.send();
  }
};
  /* Track Url Changes */
 window.onbeforeunload  = function(){
   _this.getSessionData('view_change_data');
   _this.sendPageViewData(_this.pageUrl)
 };
  /* end Track Url changes */

this.sendFormDataToQueue = function(formData,form){

  _this.queueFormData = [{
    formData: formData,
    time: (new Date()).getTime(),
    queued: true,
    formId: (form && form.id) ? form.id : null,
  }];
  _this.setSessionData('form_submit_data',_this.queueFormData)
};

  /**
   *
   * @param currentFormData { FORM DATA }
   * @param form {CurrentForm}
   */
this.sendFormDataToServer = function(currentFormData,form){
  try{
    _this.ajaxOnProcess = true;
    var sendFormData = new XMLHttpRequest();
    sendFormData.open('POST',_this.formUrl,true);
    sendFormData.send(JSON.stringify({data:(JSON.stringify(currentFormData))}))
    sendFormData.onreadystatechange= function(){
      if(sendFormData.readyState == XMLHttpRequest.DONE && sendFormData.status== 200){
        var serverResponse = JSON.parse(sendFormData.response);
        _this.ajaxOnProcess = false;
        if(serverResponse.status == 200){
          if(typeof form !="undefined"){
            form.submit();
          }
          return true;
        }else{
          _this.sendFormDataToQueue(currentFormData,form);
          if(typeof form !="undefined"){
            form.submit();
          }
        }
      }
    }
  }catch(e){
    _this.sendFormDataToQueue(currentFormData)
  }
};
this.formDataSubmission = function(){
  if(1==1){// no selected forms, go for all forms
    var allForms = document.querySelectorAll('form');

    for(var form of allForms){

      try{
        form.addEventListener('submit', function(event){
          var currentFormData = [];
          event.preventDefault();
          var elements = this.elements;
          try{
            var shouldNotInclude = ['submit','button'];
            for(var element of elements){
              try{
                if(shouldNotInclude.indexOf(element.type) == - 1){
                  if(element.value!=""){
                    var shouldSave = {
                      name: element.name || '',
                      value: element.value || '',
                      type: element.type,
                      time: (new Date()).getTime()
                    };
                    if(element.type =="checkbox" || element.type == "radio"){
                      shouldSave['checked'] = typeof element.checked!="undefined" ? element.checked:false
                    }
                    currentFormData.push(shouldSave)

                  }
                }
              }catch(e){
                console.log(e)
                // Save currentFormData if ajax failed
              }
            }
            if(Array.isArray(currentFormData) && currentFormData.length > 0){
              _this.sendFormDataToServer(currentFormData,form)
            }
          }catch(e){
            console.log(e)
          }
          return true;
        })
      }catch(er){
        console.log(er)
      }
    }
  }
}

  /* FORM SUBMISSION SECTION */

  // Support form on submit

  /* END FORM SUBMISSION */
  /* For the first page */

  window.addEventListener('load', function(event){
    try{
      // Create visit id in every browser load
      _this.setVisitIds('visitId',"visitId",_this.generateSecretKey(),options.visitExpire);
      _this.getSessionData('view_change_data');
      var currentPageDetails = {
        url: encodeURIComponent(window.location.href),
        time: (new Date()).getTime(),
        title: document.title,
        screenWidth: window.screen.width,
        screenHeight: window.screen.height,
        platform: (navigator.platform || null),
        referrer: document.referrer || "",
        visitorId: _this.visitorsId,
        visitId: _this.visitId
      };
      allDataObject['view_change_data'] =[(currentPageDetails)];
      _this.setSessionData('view_change_data',allDataObject['view_change_data'],true);
    }catch(e){
      console.log(e)

    }

    _this.formDataSubmission();
    // visit cookie
  });

  /* INTERVAL TO SEND QUEUED */
  setInterval(function(){
    console.log("Hello")
    if(!_this.ajaxOnProcess){//If ajax not running
      _this.getSessionData('form_submit_data');
      if(Array.isArray(allDataObject['form_submit_data']) && allDataObject['form_submit_data'].length > 0){
        allDataObject['form_submit_data'] = _removeDuplicates(allDataObject['form_submit_data'],'time')
        for(formDataQueue of allDataObject['form_submit_data']){
          _this.sendFormDataToServer(formDataQueue.formData);
          allDataObject['form_submit_data'].pop();
        }
        _this.setSessionData('form_submit_data',allDataObject['form_submit_data'],true)
      }
    }
  },10 * 1000);

  /* END INTERVAL */
}

function _removeDuplicates(originalArray, prop) {
  console.log(originalArray,prop)
  var newArray = [];
  var lookupObject  = {};
  for(var i in originalArray) {
    lookupObject[originalArray[i][prop]] = originalArray[i];
  }
  for(i in lookupObject) {
    newArray.push(lookupObject[i]);
  }
  console.log(newArray)
  return newArray;
}<commit_msg>form and url<commit_after>/**
 * AUTO TRACKER LIKE JS
 *
 * @objectives
 * - Track forms
 * - Use Session storage
 * - Send data
 *
 *
 *
 * @type {{init: Function}}
 */

var AutoTracker = {
  init: function(options){
    var default_options = {
      visitExpire: 4*60*60*1000,
      visitorExpire: 365*24*60*60*1000
    };

    /* Set default option if option not available */
    for(var i in default_options){
      if(default_options.hasOwnProperty(i)){
        if(!options[i]){
          options[i] = default_options[i]
        }
      }
    }
    new AutoTrackerClass(options)
  }
};

function AutoTrackerClass(options){

  var _this         = this;
  this.visitId      = "";
  this.visitorsId   = "";
  this.pageUrl      = "http://job_search.dev/auto-tracker-image.gif";
  this.formUrl      = "http://job_search.dev/auto-tracker-form.gif";
  this.queueFormData = [];
  this.ajaxOnProcess = false;

  /**
   * Generate secrets key
   * @returns {string}
   */
  this.generateSecretKey = function(){
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
      var r = Math.random() * 16 | 0,
        v = c == 'x' ? r : (r & 0x3 | 0x8);
      return v.toString(16);
    });
  };

  /* Initial Stages */
  /* Create VisitID and VisitorsID and store it in cookies */

  var allDataObject =  {
    form_submit_data:[],
    view_change_data:[],
    event_change_data:[]
  };

  /* Set Session if not exists */

  this.setStorageIfNotExist = function(key_a,allDataObject){
    if(sessionStorage.getItem(key_a)){
      allDataObject[key_a] = JSON.parse(sessionStorage.getItem(key_a))
    }else{
      sessionStorage.setItem(key_a,JSON.stringify(allDataObject[key_a]));
    }
  };

  /* Check existence and set default values */
  for(var key_a in allDataObject){
    if(allDataObject.hasOwnProperty(key_a)){
      _this.setStorageIfNotExist(key_a,allDataObject)
    }
  }
  this.getSessionData = function(key){
    allDataObject[key] = JSON.parse(sessionStorage.getItem(key))|| [];
  }
  this.removeSessionData = function(key){
    sessionStorage.removeItem(key);
  }
  /* Set session data */
  this.setSessionData = function(key,data,clear){
    if(typeof clear=="undefined") clear=false;
    if(clear){
      console.log("Remove")
     _this.removeSessionData(key);
    }
    _this.getSessionData(key);
    if(allDataObject[key].length < 5){
      if(Array.isArray(data)){
        for(var ai=0; ai<data.length; ai++){
          allDataObject[key].push(data[ai]);
        }
      }else{
        allDataObject[key].push(data);
      }
      sessionStorage.setItem(key,JSON.stringify(allDataObject[key]))
    }else{
      _this.removeSessionData(key)
    }
  };

  /* end session data */

  /**
   *
   * @param cname
   * @returns {*}
   */
  this.getCookies = function(cname){
    var name = cname + "=";
    var ca = document.cookie.split(';');
    for(var i = 0; i <ca.length; i++) {
      var c = ca[i];
      while (c.charAt(0)==' ') {
        c = c.substring(1);
      }
      if (c.indexOf(name) == 0) {
        return c.substring(name.length,c.length);
      }
    }
    return "";
  };

  /**
   *
   * @param cookieName
   * @param value
   * @param cookiesExpire
   */
  this.setCookies = function(cookieName,value,cookiesExpire){
    var d = new Date();
    d.setTime(d.getTime() + cookiesExpire);
    var expireTime = d.toUTCString();
    document.cookie= cookieName+"="+value+";expires="+expireTime+";path=/";
  };

  this.setVisitIds = function(variableId,variableName,value,expireTime,clear){
    // Check cookies or create one
    if(_this.getCookies(variableName)==""){
      _this[variableId] = _this.generateSecretKey();
      _this.setCookies(variableName,value,expireTime);
    }else{
      _this[variableId] = _this.getCookies(variableName);
    }
  };

  /** VISITORS ID **/
  this.setVisitIds('visitorsId',"visitorsId",this.generateSecretKey(),options.visitorExpire);
  /** END VISITORS ID */

this.sendPageViewData = function(url){
  if(allDataObject['view_change_data'] && Array.isArray(allDataObject['view_change_data']) && ['view_change_data'].length > 0){
    var sendViewData = new XMLHttpRequest();
    var sendData = (JSON.stringify(allDataObject['view_change_data']));
    sendViewData.open('GET',url+'?data='+sendData,false);
    sendViewData.send();
  }
};
  /* Track Url Changes */
 window.onbeforeunload  = function(){
   _this.getSessionData('view_change_data');
   _this.sendPageViewData(_this.pageUrl)
 };
  /* end Track Url changes */

this.sendFormDataToQueue = function(formData,form){

  _this.queueFormData = [{
    formData: formData,
    time: (new Date()).getTime(),
    queued: true,
    formId: (form && form.id) ? form.id : null,
  }];
  _this.setSessionData('form_submit_data',_this.queueFormData)
};

  /**
   *
   * @param currentFormData { FORM DATA }
   * @param form {CurrentForm}
   */
this.sendFormDataToServer = function(currentFormData,form){
  try{
    _this.ajaxOnProcess = true;
    var sendFormData = new XMLHttpRequest();
    sendFormData.open('POST',_this.formUrl,true);
    sendFormData.send(JSON.stringify({data:(JSON.stringify(currentFormData))}))
    sendFormData.onreadystatechange= function(){
      if(sendFormData.readyState == XMLHttpRequest.DONE && sendFormData.status== 200){
        var serverResponse = JSON.parse(sendFormData.response);
        _this.ajaxOnProcess = false;
        if(serverResponse.status == 200){
          if(typeof form !="undefined"){
            form.submit();
          }
          return true;
        }else{
          _this.sendFormDataToQueue(currentFormData,form);
          if(typeof form !="undefined"){
            form.submit();
          }
        }
      }
    }
  }catch(e){
    _this.sendFormDataToQueue(currentFormData)
  }
};
this.formDataSubmission = function(){
  if(1==1){// no selected forms, go for all forms
    var allForms = document.querySelectorAll('form');

    for(var form of allForms){

      try{
        form.addEventListener('submit', function(event){
          var currentFormData = [];
          event.preventDefault();
          var elements = this.elements;
          try{
            var shouldNotInclude = ['submit','button'];
            for(var element of elements){
              try{
                if(shouldNotInclude.indexOf(element.type) == - 1){
                  if(element.value!=""){
                    var shouldSave = {
                      name: element.name || '',
                      value: element.value || '',
                      type: element.type,
                      time: (new Date()).getTime()
                    };
                    if(element.type =="checkbox" || element.type == "radio"){
                      shouldSave['checked'] = typeof element.checked!="undefined" ? element.checked:false
                    }
                    currentFormData.push(shouldSave)

                  }
                }
              }catch(e){
                console.log(e)
                // Save currentFormData if ajax failed
              }
            }
            if(Array.isArray(currentFormData) && currentFormData.length > 0){
              _this.sendFormDataToServer(currentFormData,form)
            }
          }catch(e){
            console.log(e)
          }
          return true;
        })
      }catch(er){
        console.log(er)
      }
    }
  }
}

  /* FORM SUBMISSION SECTION */

  // Support form on submit

  /* END FORM SUBMISSION */
  /* For the first page */

  window.addEventListener('load', function(event){
    try{
      // Create visit id in every browser load
      _this.setVisitIds('visitId',"visitId",_this.generateSecretKey(),options.visitExpire);
      _this.getSessionData('view_change_data');
      var currentPageDetails = {
        url: encodeURIComponent(location.host+location.pathname),
        time: (new Date()).getTime(),
        title: document.title,
        screenWidth: window.screen.width,
        screenHeight: window.screen.height,
        platform: (navigator.platform || null),
        referrer: document.referrer || "",
        visitorId: _this.visitorsId,
        visitId: _this.visitId
      };
      allDataObject['view_change_data'] =[(currentPageDetails)];
      _this.setSessionData('view_change_data',allDataObject['view_change_data'],true);
    }catch(e){
      console.log(e)

    }

    _this.formDataSubmission();
    // visit cookie
  });

  /* INTERVAL TO SEND QUEUED */
  setInterval(function(){
    console.log("Hello")
    if(!_this.ajaxOnProcess){//If ajax not running
      _this.getSessionData('form_submit_data');
      if(Array.isArray(allDataObject['form_submit_data']) && allDataObject['form_submit_data'].length > 0){
        allDataObject['form_submit_data'] = _removeDuplicates(allDataObject['form_submit_data'],'time')
        for(formDataQueue of allDataObject['form_submit_data']){
          _this.sendFormDataToServer(formDataQueue.formData);
          allDataObject['form_submit_data'].pop();
        }
        _this.setSessionData('form_submit_data',allDataObject['form_submit_data'],true)
      }
    }
  },10 * 1000);

  /* END INTERVAL */
}

function _removeDuplicates(originalArray, prop) {
  console.log(originalArray,prop)
  var newArray = [];
  var lookupObject  = {};
  for(var i in originalArray) {
    lookupObject[originalArray[i][prop]] = originalArray[i];
  }
  for(i in lookupObject) {
    newArray.push(lookupObject[i]);
  }
  console.log(newArray)
  return newArray;
}<|endoftext|>


<commit_before>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';

var format = require('util').format;
var inherits = require('util').inherits;

var errors = require('./errors');

module.exports.StateOptions = StateOptions;
module.exports.HealthyState = HealthyState;
module.exports.UnhealthyState = UnhealthyState;
module.exports.LockedHealthyState = LockedHealthyState;
module.exports.LockedUnhealthyState = LockedUnhealthyState;

function StateOptions(stateMachine, options) {
    options = options || {};
    this.stateMachine = stateMachine;
    this.nextHandler = options.nextHandler;
    this.timers = options.timers;
    this.random = options.random;
    this.period = options.period;
    this.maxErrorRate = options.maxErrorRate;
    this.minimumRequests = options.minimumRequests;
    this.probation = options.probation;
}

/*
 * Collectively, the health states receive additional options through the peer
 * options:
 * - maxErrorRate (error rate to go from healthy to unhealthy)
 * - minResponseCount (response count to go from unhealthy to healthy)
 * - TODO
 *
 * They also inherit:
 * - channel.timers
 * - channel.random
 */

function State() {
}

State.prototype.onRequest = function onRequest(/* req */) {
};

State.prototype.onRequestHealthy = function onRequestHealthy(/* req */) {
};

State.prototype.onRequestError = function onRequestError(err) {
};

State.prototype.onRequestUnhealthy = function onRequestUnhealthy() {
};

State.prototype.close = function close(callback) {
    callback(null);
};

function HealthyState(options) {
    var self = this;
    self.stateMachine = options.stateMachine;
    self.nextHandler = options.nextHandler;
    self.timers = options.timers;
    self.random = options.random;
    self.period = options.period || 1000; // ms
    self.start = self.timers.now();
    self.maxErrorRate = options.maxErrorRate || 0.5;
    self.healthyCount = 0;
    self.unhealthyCount = 0;
    self.totalRequests = 0;
    self.minRequests = typeof options.minRequests === 'number' ?
        options.minRequests : 5;
}

inherits(HealthyState, State);

HealthyState.prototype.type = 'tchannel.healthy';

HealthyState.prototype.toString = function healthyToString() {
    var self = this;
    return format('[Healthy %s healthy %s unhealthy]', self.healthyCount, self.unhealthyCount);
};

HealthyState.prototype.shouldRequest = function shouldRequest(req, options) {
    var self = this;
    var now = self.timers.now();
    // At the conclusion of a period
    if (now - self.start >= self.period) {
        var totalCount = self.healthyCount + self.unhealthyCount;

        // Transition to unhealthy state if the healthy request rate dips below
        // the acceptable threshold.
        if (self.unhealthyCount / totalCount > self.maxErrorRate &&
            self.totalRequests > self.minRequests
        ) {
            self.stateMachine.setState(UnhealthyState);
            return 0;
        }
        // Alternatley, start a new monitoring period.
        self.start = self.timers.now();
        self.healthyCount = 0;
        self.unhealthyCount = 0;
    }
    return self.nextHandler.shouldRequest(req, options);
};

HealthyState.prototype.onRequestHealthy = function onRequestHealthy(/* req */) {
    var self = this;
    self.healthyCount++;
    self.totalRequests++;
};

HealthyState.prototype.onRequestError = function onRequestError(err) {
    var self = this;

    self.totalRequests++;
    var codeString = errors.classify(err);
    if (errors.isUnhealthy(codeString)) {
        self.unhealthyCount++;
    } else {
        self.healthyCount++;
    }
};

HealthyState.prototype.onRequestUnhealthy = function onRequestUnhealthy() {
    var self = this;
    self.totalRequests++;
    self.unhealthyCount++;
};

function UnhealthyState(options) {
    var self = this;
    self.stateMachine = options.stateMachine;
    self.nextHandler = options.nextHandler;
    self.timers = options.timers;
    self.random = options.random;
    self.minResponseCount = options.probation || 5;
    self.period = options.period || 1000;
    self.start = self.timers.now();
    self.healthyCount = 0;
    self.triedThisPeriod = true;
}

inherits(UnhealthyState, State);

UnhealthyState.prototype.type = 'tchannel.unhealthy';

UnhealthyState.prototype.toString = function healthyToString() {
    var self = this;
    return format('[Unhealthy %s consecutive healthy requests]', self.healthyCount);
};

UnhealthyState.prototype.shouldRequest = function shouldRequest(req, options) {
    var self = this;

    // Start a new period if the previous has concluded
    var now = self.timers.now();
    if (now - self.start >= self.period) {
        self.start = self.timers.now();
        self.triedThisPeriod = false;
    }

    // Allow one trial per period
    if (self.triedThisPeriod) {
        return 0;
    }

    return self.nextHandler.shouldRequest(req, options);
};

UnhealthyState.prototype.onRequest = function onRequest(/* req */) {
    var self = this;
    self.triedThisPeriod = true;
};

UnhealthyState.prototype.onRequestHealthy = function onRequestHealthy(/* req */) {
    var self = this;
    self.healthyCount++;
    if (self.healthyCount > self.minResponseCount) {
        self.stateMachine.setState(HealthyState);
    }
};

UnhealthyState.prototype.onRequestError = function onRequestError(err) {
    var self = this;
    var codeString = errors.classify(err);
    if (errors.isUnhealthy(codeString)) {
        self.healthyCount = 0;
    } else {
        self.onRequestHealthy();
    }
};

UnhealthyState.prototype.onRequestUnhealthy = function onRequestUnhealthy() {
    var self = this;
    self.healthyCount = 0;
};

function LockedHealthyState(options) {
    var self = this;
    self.nextHandler = options.nextHandler;
}

inherits(LockedHealthyState, State);

LockedHealthyState.prototype.type = 'tchannel.healthy-locked';

LockedHealthyState.prototype.toString = function lockedHealthyToString() {
    return '[Healthy state (locked)]';
};

LockedHealthyState.prototype.shouldRequest = function shouldRequest(req, options) {
    var self = this;
    return self.nextHandler.shouldRequest(req, options);
};

function LockedUnhealthyState(options) {
    var self = this;
    self.nextHandler = options.nextHandler;
}

inherits(LockedUnhealthyState, State);

LockedUnhealthyState.prototype.type = 'tchannel.unhealthy-locked';

LockedUnhealthyState.prototype.toString = function lockedUnhealthyToString() {
    return '[Unhealthy state (locked)]';
};

LockedUnhealthyState.prototype.shouldRequest = function shouldRequest(req, options) {
    return 0;
};
<commit_msg>Document state options<commit_after>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';

var format = require('util').format;
var inherits = require('util').inherits;

var errors = require('./errors');

module.exports.StateOptions = StateOptions;
module.exports.HealthyState = HealthyState;
module.exports.UnhealthyState = UnhealthyState;
module.exports.LockedHealthyState = LockedHealthyState;
module.exports.LockedUnhealthyState = LockedUnhealthyState;

function StateOptions(stateMachine, options) {
    options = options || {};
    // for setState changes
    this.stateMachine = stateMachine;
    // for downstream shouldRequest, used differently in Peer and Circuit.
    this.nextHandler = options.nextHandler;
    // for mocking tests
    this.timers = options.timers;
    this.random = options.random;
    // the number of miliseconds that healthy and unhealthy requests are
    // tracked between state reevaluation.
    this.period = options.period;
    // when healthy, the minimum number of requests during a period to trigger
    // state reevaluation.
    this.minimumRequests = options.minimumRequests;
    // when healthy, the failure rate for a period that will trigger a
    // transition to unhealthy.
    this.maxErrorRate = options.maxErrorRate;
    // when unhealthy, allow one request per period. this is the number of
    // consecutive periods that must have 100% healthy responses to trigger a
    // switch back to healthy.
    this.probation = options.probation;
}

/*
 * Collectively, the health states receive additional options through the peer
 * options:
 * - maxErrorRate (error rate to go from healthy to unhealthy)
 * - minResponseCount (response count to go from unhealthy to healthy)
 * - TODO
 *
 * They also inherit:
 * - channel.timers
 * - channel.random
 */

function State() {
}

State.prototype.onRequest = function onRequest(/* req */) {
};

State.prototype.onRequestHealthy = function onRequestHealthy(/* req */) {
};

State.prototype.onRequestError = function onRequestError(err) {
};

State.prototype.onRequestUnhealthy = function onRequestUnhealthy() {
};

State.prototype.close = function close(callback) {
    callback(null);
};

function HealthyState(options) {
    var self = this;
    self.stateMachine = options.stateMachine;
    self.nextHandler = options.nextHandler;
    self.timers = options.timers;
    self.random = options.random;
    self.period = options.period || 1000; // ms
    self.start = self.timers.now();
    self.maxErrorRate = options.maxErrorRate || 0.5;
    self.healthyCount = 0;
    self.unhealthyCount = 0;
    self.totalRequests = 0;
    self.minRequests = typeof options.minRequests === 'number' ?
        options.minRequests : 5;
}

inherits(HealthyState, State);

HealthyState.prototype.type = 'tchannel.healthy';

HealthyState.prototype.toString = function healthyToString() {
    var self = this;
    return format('[Healthy %s healthy %s unhealthy]', self.healthyCount, self.unhealthyCount);
};

HealthyState.prototype.shouldRequest = function shouldRequest(req, options) {
    var self = this;
    var now = self.timers.now();
    // At the conclusion of a period
    if (now - self.start >= self.period) {
        var totalCount = self.healthyCount + self.unhealthyCount;

        // Transition to unhealthy state if the healthy request rate dips below
        // the acceptable threshold.
        if (self.unhealthyCount / totalCount > self.maxErrorRate &&
            self.totalRequests > self.minRequests
        ) {
            self.stateMachine.setState(UnhealthyState);
            return 0;
        }
        // Alternatley, start a new monitoring period.
        self.start = self.timers.now();
        self.healthyCount = 0;
        self.unhealthyCount = 0;
    }
    return self.nextHandler.shouldRequest(req, options);
};

HealthyState.prototype.onRequestHealthy = function onRequestHealthy(/* req */) {
    var self = this;
    self.healthyCount++;
    self.totalRequests++;
};

HealthyState.prototype.onRequestError = function onRequestError(err) {
    var self = this;

    self.totalRequests++;
    var codeString = errors.classify(err);
    if (errors.isUnhealthy(codeString)) {
        self.unhealthyCount++;
    } else {
        self.healthyCount++;
    }
};

HealthyState.prototype.onRequestUnhealthy = function onRequestUnhealthy() {
    var self = this;
    self.totalRequests++;
    self.unhealthyCount++;
};

function UnhealthyState(options) {
    var self = this;
    self.stateMachine = options.stateMachine;
    self.nextHandler = options.nextHandler;
    self.timers = options.timers;
    self.random = options.random;
    self.minResponseCount = options.probation || 5;
    self.period = options.period || 1000;
    self.start = self.timers.now();
    self.healthyCount = 0;
    self.triedThisPeriod = true;
}

inherits(UnhealthyState, State);

UnhealthyState.prototype.type = 'tchannel.unhealthy';

UnhealthyState.prototype.toString = function healthyToString() {
    var self = this;
    return format('[Unhealthy %s consecutive healthy requests]', self.healthyCount);
};

UnhealthyState.prototype.shouldRequest = function shouldRequest(req, options) {
    var self = this;

    // Start a new period if the previous has concluded
    var now = self.timers.now();
    if (now - self.start >= self.period) {
        self.start = self.timers.now();
        self.triedThisPeriod = false;
    }

    // Allow one trial per period
    if (self.triedThisPeriod) {
        return 0;
    }

    return self.nextHandler.shouldRequest(req, options);
};

UnhealthyState.prototype.onRequest = function onRequest(/* req */) {
    var self = this;
    self.triedThisPeriod = true;
};

UnhealthyState.prototype.onRequestHealthy = function onRequestHealthy(/* req */) {
    var self = this;
    self.healthyCount++;
    if (self.healthyCount > self.minResponseCount) {
        self.stateMachine.setState(HealthyState);
    }
};

UnhealthyState.prototype.onRequestError = function onRequestError(err) {
    var self = this;
    var codeString = errors.classify(err);
    if (errors.isUnhealthy(codeString)) {
        self.healthyCount = 0;
    } else {
        self.onRequestHealthy();
    }
};

UnhealthyState.prototype.onRequestUnhealthy = function onRequestUnhealthy() {
    var self = this;
    self.healthyCount = 0;
};

function LockedHealthyState(options) {
    var self = this;
    self.nextHandler = options.nextHandler;
}

inherits(LockedHealthyState, State);

LockedHealthyState.prototype.type = 'tchannel.healthy-locked';

LockedHealthyState.prototype.toString = function lockedHealthyToString() {
    return '[Healthy state (locked)]';
};

LockedHealthyState.prototype.shouldRequest = function shouldRequest(req, options) {
    var self = this;
    return self.nextHandler.shouldRequest(req, options);
};

function LockedUnhealthyState(options) {
    var self = this;
    self.nextHandler = options.nextHandler;
}

inherits(LockedUnhealthyState, State);

LockedUnhealthyState.prototype.type = 'tchannel.unhealthy-locked';

LockedUnhealthyState.prototype.toString = function lockedUnhealthyToString() {
    return '[Unhealthy state (locked)]';
};

LockedUnhealthyState.prototype.shouldRequest = function shouldRequest(req, options) {
    return 0;
};
<|endoftext|>


<commit_before>// Event
////////

// Open select when click on dropdown link
$vic(document).on('focus', '.v-slot select', function(event) {
    $vic(this).parent('.v-slot').addClass('v-slot--open');
});
$vic(document).on('blur', '.v-slot select', function(event) {
    $vic(event.target).parent('.v-slot').removeClass('v-slot--open');
    $vic(event.target).prop('selectedIndex', 0);
});

// Eval width of the slots to add or not a class
function evalSlotWidth(slot) {
    var smallClass = 'v-slot--sm';

    if (slot.offsetWidth > 250 && slot.classList.contains(smallClass)) {
        slot.classList.remove(smallClass);
    } else if (slot.offsetWidth <= 250 && slot.offsetWidth > 0) {
        slot.classList.add(smallClass);
    }

    return;
}

$vic(document).ready(function() {
    $('.v-slot').each(function(index, el) {
        return evalSlotWidth(el);
    });
});

$vic(window).resize(function() {
    $('.v-slot').each(function(index, el) {
        return evalSlotWidth(el);
    });
});

// Create modal for new widget
$vic(document).on('change', '.v-slot select', function(event) {
    event.preventDefault();
    var url = generateNewWidgetUrl(event.target);
    $vic(this).blur();
    openModal(url);
    $vic(this).parents('.v-slot').first().addClass('vic-creating');
});

$vic(document).on('click', '.v-modal--widget a[data-modal="update"], .v-modal--widget a[data-modal="create"]', function(event) {
    event.preventDefault();

    var forms = [];
    $vic('[data-group="tab-widget-quantum"]').each(function() {

        var quantumLetter = $(this).data('quantum');

        // matches widget edit form with more than one mode available
        var activeForm = $(this).find('[data-group="picker-' + quantumLetter + '"][data-state="visible"] [data-flag="v-collapse"][data-state="visible"] > form');

        // matches widget edit form with only static mode available
        if (activeForm.length == 0) {
            activeForm = $(this).find('[data-group="picker-' + quantumLetter + '"][data-state="visible"] form');
        }

        // matches widget stylize form
        if (activeForm.length == 0 && $(this).attr('data-state') == 'visible') {
            activeForm = $(this).find('form[name="widget_style"]');
        }

        forms = $vic.merge(forms, [activeForm]);
    });

    loading(true);
    var calls = [];
    $vic(forms).each(function (key, form) {
        $vic(form).trigger("victoire_widget_form_update_presubmit");
        formData = $vic(form).serialize();
        var contentType = 'application/x-www-form-urlencoded; charset=UTF-8';
        if ($vic(form).attr('enctype') == 'multipart/form-data') {
            var formData = new FormData($vic(form)[0]);
            var contentType = false;
        }
        calls.push($vic.ajax({
            type: $vic(form).attr('method'),
            url : $vic(form).attr('action'),
            data        : formData,
            processData : false,
            contentType : contentType
        }).done(function(response) {
            $vic(form).trigger("victoire_widget_form_update_postsubmit");
        }).fail(function() {
            loading(false);
        })
        );
    });

    $vic.when.apply($vic, calls).then(function() {
        var errors = false;
        //arguments is a magic var that contains all callback arguments
        $vic(arguments).each(function(index, response) {
            if (response.length) {
                response = response[0];
            }
            if (false === response.success) {
                $vic('ul.vic-modal-nav-tabs a[href="#widget-'+response.widgetId+'-tab-pane"]').css('color', 'red');
                errors = true;
                //inform user there have been an error
                warn(response.message, 10000);

                if (response.html) {
                    $vic('#widget-'+response.widgetId+'-tab-pane div.vic-tab-mode.vic-tab-pane.vic-active div.vic-tab-pane.vic-active').html(response.html)

                }
            } else {
                $vic('ul.vic-modal-nav-tabs a[href="#widget-'+response.widgetId+'-tab-pane"]').css('color', '');
            }
        });
        if (errors === false) {
            window.location.reload();
        }
        loading(false);
    });
});

// Delete a widget after submit
$vic(document).on('click', 'a#widget-new-tab', function(event) {
    event.preventDefault();
    loading(true);
    var url = Routing.generate('victoire_core_widget_new', {
        type: $vic(this).data('type'),
        viewReference: $vic(this).data('viewreference'),
        slot: $vic(this).data('slot'),
        position: $vic(this).data('position'),
        parentWidgetMap: $vic(this).data('parentwidgetmap'),
        quantum: $vic("#v-quantum-tab > .v-flex-col").length - 1,
        _locale: locale
    });
    $vic.ajax({
        type: "GET",
        url : url
    }).done(function(response) {
        if (true === response.success) {
            $vic('[data-group="tab-widget-quantum"][data-state="visible"]').attr('data-state', 'hidden');
            $vic('.v-btn--quantum-active').removeClass('v-btn--quantum-active');
            var form = $vic(response.html).find('[data-group="tab-widget-quantum"]').first();
            var tab = $vic(response.html).find('.v-btn--quantum').last().addClass('v-btn--quantum-active').parent();
            $vic('#widget-new-tab').parent('.v-flex-col').before(tab);
            $vic('#v-modal-tab-content-container').append(form);

            loading(false);
        }
    }).fail(function() {
        loading(false);
    });
    $vic(document).trigger("victoire_widget_delete_postsubmit");
});

// Delete a widget after submit
$vic(document).on('click', '.v-modal--widget a.vic-confirmed, .vic-hover-widget-unlink', function(event) {
    event.preventDefault();
    $vic(document).trigger("victoire_widget_delete_presubmit");

        loading(true);
        $vic.ajax({
            type: "GET",
            url : $vic(this).attr('href')
        }).done(function(response) {
            if (true === response.success) {
                if (response.hasOwnProperty("redirect")) {
                    window.location.replace(response.redirect);
                } else {
                    window.location.reload();
                }
                loading(false);
            } else {
                //log the error
                console.info('An error occured during the deletion of the widget.');
                console.log(response.message);
            }
        }).fail(function() {
            loading(false);
        });
        $vic(document).trigger("victoire_widget_delete_postsubmit");
});

function generateNewWidgetUrl(select){
    var slotId = $vic(select).parents('.vic-slot').first().data('name');
    var container = $vic(select).parents('new-widget-button');

    var position = $vic(container).attr('position');
    var parentWidgetMap = $vic(container).attr('widget-map');

    var params = {
        'viewReference'    : viewReferenceId,
        'type'             : $vic(select).val(),
        'slot'             : slotId,
        '_locale'          : locale
    };

    if (position) {
        params['position'] = position;
    }
    if (parentWidgetMap) {
        params['parentWidgetMap'] = parentWidgetMap;

    }
    return Routing.generate(
        'victoire_core_widget_new',
        params
    );
}

// update on left bar, the quantum name when modifying it
$vic(document).on('keyup', '[data-flag="v-quantum-name"]', function(event) {
    var activeQuantumTab = $vic('#v-quantum-tab > .v-flex-col .v-btn--quantum-active');

    if (!activeQuantumTab.find('span[data-flag="old-name"]').length) {
        var originalShortName = $vic('#v-quantum-tab > .v-flex-col .v-btn--quantum-active span:not([data-flag="old-name"])').text();
        activeQuantumTab.append('' + originalShortName + '');
    }

    var quantumShortName = event.target.value.length ? event.target.value.substr(0, 2) : activeQuantumTab.find('span[data-flag="old-name"]').text();

    activeQuantumTab.find('span:not([data-flag="old-name"])').text(quantumShortName);
});
<commit_msg>Use $vic instead of $<commit_after>// Event
////////

// Open select when click on dropdown link
$vic(document).on('focus', '.v-slot select', function(event) {
    $vic(this).parent('.v-slot').addClass('v-slot--open');
});
$vic(document).on('blur', '.v-slot select', function(event) {
    $vic(event.target).parent('.v-slot').removeClass('v-slot--open');
    $vic(event.target).prop('selectedIndex', 0);
});

// Eval width of the slots to add or not a class
function evalSlotWidth(slot) {
    var smallClass = 'v-slot--sm';

    if (slot.offsetWidth > 250 && slot.classList.contains(smallClass)) {
        slot.classList.remove(smallClass);
    } else if (slot.offsetWidth <= 250 && slot.offsetWidth > 0) {
        slot.classList.add(smallClass);
    }

    return;
}

$vic(document).ready(function() {
    $('.v-slot').each(function(index, el) {
        return evalSlotWidth(el);
    });
});

$vic(window).resize(function() {
    $('.v-slot').each(function(index, el) {
        return evalSlotWidth(el);
    });
});

// Create modal for new widget
$vic(document).on('change', '.v-slot select', function(event) {
    event.preventDefault();
    var url = generateNewWidgetUrl(event.target);
    $vic(this).blur();
    openModal(url);
    $vic(this).parents('.v-slot').first().addClass('vic-creating');
});

$vic(document).on('click', '.v-modal--widget a[data-modal="update"], .v-modal--widget a[data-modal="create"]', function(event) {
    event.preventDefault();

    var forms = [];
    $vic('[data-group="tab-widget-quantum"]').each(function() {

        var quantumLetter = $vic(this).data('quantum');

        // matches widget edit form with more than one mode available
        var activeForm = $vic(this).find('[data-group="picker-' + quantumLetter + '"][data-state="visible"] [data-flag="v-collapse"][data-state="visible"] > form');

        // matches widget edit form with only static mode available
        if (activeForm.length == 0) {
            activeForm = $vic(this).find('[data-group="picker-' + quantumLetter + '"][data-state="visible"] form');
        }

        // matches widget stylize form
        if (activeForm.length == 0 && $vic(this).attr('data-state') == 'visible') {
            activeForm = $vic(this).find('form[name="widget_style"]');
        }

        forms = $vic.merge(forms, [activeForm]);
    });

    loading(true);
    var calls = [];
    $vic(forms).each(function (key, form) {
        $vic(form).trigger("victoire_widget_form_update_presubmit");
        formData = $vic(form).serialize();
        var contentType = 'application/x-www-form-urlencoded; charset=UTF-8';
        if ($vic(form).attr('enctype') == 'multipart/form-data') {
            var formData = new FormData($vic(form)[0]);
            var contentType = false;
        }
        calls.push($vic.ajax({
            type: $vic(form).attr('method'),
            url : $vic(form).attr('action'),
            data        : formData,
            processData : false,
            contentType : contentType
        }).done(function(response) {
            $vic(form).trigger("victoire_widget_form_update_postsubmit");
        }).fail(function() {
            loading(false);
        })
        );
    });

    $vic.when.apply($vic, calls).then(function() {
        var errors = false;
        //arguments is a magic var that contains all callback arguments
        $vic(arguments).each(function(index, response) {
            if (response.length) {
                response = response[0];
            }
            if (false === response.success) {
                $vic('ul.vic-modal-nav-tabs a[href="#widget-'+response.widgetId+'-tab-pane"]').css('color', 'red');
                errors = true;
                //inform user there have been an error
                warn(response.message, 10000);

                if (response.html) {
                    $vic('#widget-'+response.widgetId+'-tab-pane div.vic-tab-mode.vic-tab-pane.vic-active div.vic-tab-pane.vic-active').html(response.html)

                }
            } else {
                $vic('ul.vic-modal-nav-tabs a[href="#widget-'+response.widgetId+'-tab-pane"]').css('color', '');
            }
        });
        if (errors === false) {
            window.location.reload();
        }
        loading(false);
    });
});

// Delete a widget after submit
$vic(document).on('click', 'a#widget-new-tab', function(event) {
    event.preventDefault();
    loading(true);
    var url = Routing.generate('victoire_core_widget_new', {
        type: $vic(this).data('type'),
        viewReference: $vic(this).data('viewreference'),
        slot: $vic(this).data('slot'),
        position: $vic(this).data('position'),
        parentWidgetMap: $vic(this).data('parentwidgetmap'),
        quantum: $vic("#v-quantum-tab > .v-flex-col").length - 1,
        _locale: locale
    });
    $vic.ajax({
        type: "GET",
        url : url
    }).done(function(response) {
        if (true === response.success) {
            $vic('[data-group="tab-widget-quantum"][data-state="visible"]').attr('data-state', 'hidden');
            $vic('.v-btn--quantum-active').removeClass('v-btn--quantum-active');
            var form = $vic(response.html).find('[data-group="tab-widget-quantum"]').first();
            var tab = $vic(response.html).find('.v-btn--quantum').last().addClass('v-btn--quantum-active').parent();
            $vic('#widget-new-tab').parent('.v-flex-col').before(tab);
            $vic('#v-modal-tab-content-container').append(form);

            loading(false);
        }
    }).fail(function() {
        loading(false);
    });
    $vic(document).trigger("victoire_widget_delete_postsubmit");
});

// Delete a widget after submit
$vic(document).on('click', '.v-modal--widget a.vic-confirmed, .vic-hover-widget-unlink', function(event) {
    event.preventDefault();
    $vic(document).trigger("victoire_widget_delete_presubmit");

        loading(true);
        $vic.ajax({
            type: "GET",
            url : $vic(this).attr('href')
        }).done(function(response) {
            if (true === response.success) {
                if (response.hasOwnProperty("redirect")) {
                    window.location.replace(response.redirect);
                } else {
                    window.location.reload();
                }
                loading(false);
            } else {
                //log the error
                console.info('An error occured during the deletion of the widget.');
                console.log(response.message);
            }
        }).fail(function() {
            loading(false);
        });
        $vic(document).trigger("victoire_widget_delete_postsubmit");
});

function generateNewWidgetUrl(select){
    var slotId = $vic(select).parents('.vic-slot').first().data('name');
    var container = $vic(select).parents('new-widget-button');

    var position = $vic(container).attr('position');
    var parentWidgetMap = $vic(container).attr('widget-map');

    var params = {
        'viewReference'    : viewReferenceId,
        'type'             : $vic(select).val(),
        'slot'             : slotId,
        '_locale'          : locale
    };

    if (position) {
        params['position'] = position;
    }
    if (parentWidgetMap) {
        params['parentWidgetMap'] = parentWidgetMap;

    }
    return Routing.generate(
        'victoire_core_widget_new',
        params
    );
}

// update on left bar, the quantum name when modifying it
$vic(document).on('keyup', '[data-flag="v-quantum-name"]', function(event) {
    var activeQuantumTab = $vic('#v-quantum-tab > .v-flex-col .v-btn--quantum-active');

    if (!activeQuantumTab.find('span[data-flag="old-name"]').length) {
        var originalShortName = $vic('#v-quantum-tab > .v-flex-col .v-btn--quantum-active span:not([data-flag="old-name"])').text();
        activeQuantumTab.append('' + originalShortName + '');
    }

    var quantumShortName = event.target.value.length ? event.target.value.substr(0, 2) : activeQuantumTab.find('span[data-flag="old-name"]').text();

    activeQuantumTab.find('span:not([data-flag="old-name"])').text(quantumShortName);
});
<|endoftext|>


<commit_before>'use strict';

describe('E2E testing: New Lex Project wizard app', function() {
  var constants = require('../../../testConstants.json'),
      loginPage = require('../../../bellows/pages/loginPage.js'),
      body      = require('../../../bellows/pages/pageBody.js'),
      util      = require('../../../bellows/pages/util.js'),
      dbePage   = require('../../pages/dbePage.js'),
      page      = require('../../pages/newLexProjectPage.js');

  afterEach(function() {
    expect(body.phpError.isPresent()).toBe(false);
  });

  it('admin can get to wizard', function() {
    loginPage.loginAsAdmin();
    page.get();
    expect(page.newLexProjectForm).toBeDefined();
    expect(page.namePage.projectNameInput.isPresent()).toBe(true);
  });

  it('manager can get wizard', function() {
    loginPage.loginAsManager();
    page.get();
    expect(page.newLexProjectForm).toBeDefined();
    expect(page.namePage.projectNameInput.isPresent()).toBe(true);
  });

  it('setup: user login and page contains a form', function() {
    loginPage.loginAsUser();
    page.get();
    expect(page.newLexProjectForm).toBeDefined();
    expect(page.namePage.projectNameInput.isPresent()).toBe(true);
  });

  describe('Project Name page', function() {

    it('cannot see back button', function() {
      expect(page.backButton.isDisplayed()).toBe(false);
      page.formStatus.expectHasNoError();
    });

    it('cannot move on if name is invalid', function() {
      expect(page.nextButton.isEnabled()).toBe(true);
      page.nextButton.click();
      expect(page.namePage.projectNameInput.isPresent()).toBe(true);
      page.formStatus.expectContainsError('Project Name cannot be empty.');
    });

    it('finds the test project already exists', function() {
      page.namePage.projectNameInput.sendKeys(constants.testProjectName + protractor.Key.TAB);
      expect(page.namePage.projectCodeExists.isDisplayed()).toBe(true);
      expect(page.namePage.projectCodeAlphanumeric.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeOk.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeInput.getAttribute('value')).toEqual(constants.testProjectCode);
      page.formStatus.expectContainsError("Another project with code '" + constants.testProjectCode + "' already exists.");
      page.namePage.projectNameInput.clear();
    });

    it('with a cleared name does not show an error but is still invalid', function() {

      // added the following two lines so the test will work (previous error wasn't clearing)
      // as I couldn't re-produce the problem manually,
      // however is likely symptomatic of some funkiness with promises. IJH 2014-12
      page.namePage.projectNameInput.sendKeys('a' + protractor.Key.TAB);
      page.namePage.projectNameInput.clear();
      page.namePage.projectNameInput.sendKeys(protractor.Key.TAB);
      expect(page.namePage.projectCodeExists.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeAlphanumeric.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeOk.isDisplayed()).toBe(false);
      page.formStatus.expectHasNoError();
      expect(page.nextButton.isEnabled()).toBe(true);
      page.nextButton.click();
      expect(page.namePage.projectNameInput.isPresent()).toBe(true);
      page.formStatus.expectContainsError('Project Name cannot be empty.');
    });

    it('can verify that an unused project name is available', function() {
      page.namePage.projectNameInput.sendKeys(constants.newProjectName + protractor.Key.TAB);
      expect(page.namePage.projectCodeExists.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeAlphanumeric.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeOk.isDisplayed()).toBe(true);
      expect(page.namePage.projectCodeInput.getAttribute('value')).toEqual(constants.newProjectCode);
      page.formStatus.expectHasNoError();
    });

    it('can not edit project code by default', function() {
      expect(page.namePage.projectCodeInput.isDisplayed()).toBe(false);
    });

    it('can edit project code when enabled', function() {
      expect(page.namePage.editProjectCodeCheckbox.isDisplayed()).toBe(true);
      util.setCheckbox(page.namePage.editProjectCodeCheckbox, true);
      expect(page.namePage.projectCodeInput.isDisplayed()).toBe(true);
      page.namePage.projectCodeInput.clear();
      page.namePage.projectCodeInput.sendKeys('changed_new_project' + protractor.Key.TAB);
      expect(page.namePage.projectCodeInput.getAttribute('value')).toEqual('changed_new_project');
      page.formStatus.expectHasNoError();
    });

    it('project code cannot be empty; does not show an error but is still invalid', function() {
      page.namePage.projectCodeInput.clear();
      page.namePage.projectNameInput.sendKeys(protractor.Key.TAB);     // trigger project code check
      expect(page.namePage.projectCodeExists.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeAlphanumeric.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeOk.isDisplayed()).toBe(false);
      page.formStatus.expectHasNoError();
      expect(page.nextButton.isEnabled()).toBe(true);
      page.nextButton.click();
      expect(page.namePage.projectNameInput.isPresent()).toBe(true);
      page.formStatus.expectContainsError('Project Code cannot be empty.');
    });

    it('project code can be one character', function() {
      page.namePage.projectCodeInput.clear();
      page.namePage.projectCodeInput.sendKeys('a' + protractor.Key.TAB);
      expect(page.namePage.projectCodeExists.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeAlphanumeric.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeOk.isDisplayed()).toBe(true);
      page.formStatus.expectHasNoError();
    });

    it('project code cannot be uppercase', function() {
      page.namePage.projectCodeInput.clear();
      page.namePage.projectCodeInput.sendKeys('A' + protractor.Key.TAB);
      expect(page.namePage.projectCodeExists.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeAlphanumeric.isDisplayed()).toBe(true);
      expect(page.namePage.projectCodeOk.isDisplayed()).toBe(false);
      page.formStatus.expectHasNoError();
      page.nextButton.click();
      page.formStatus.expectContainsError('Project Code must begin with a letter');
      page.namePage.projectCodeInput.clear();
      page.namePage.projectCodeInput.sendKeys('aB' + protractor.Key.TAB);
      expect(page.namePage.projectCodeExists.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeAlphanumeric.isDisplayed()).toBe(true);
      expect(page.namePage.projectCodeOk.isDisplayed()).toBe(false);
      page.formStatus.expectHasNoError();
      page.nextButton.click();
      page.formStatus.expectContainsError('Project Code must begin with a letter');
    });

    it('project code cannot start with a number', function() {
      page.namePage.projectCodeInput.clear();
      page.namePage.projectCodeInput.sendKeys('1' + protractor.Key.TAB);
      expect(page.namePage.projectCodeExists.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeAlphanumeric.isDisplayed()).toBe(true);
      expect(page.namePage.projectCodeOk.isDisplayed()).toBe(false);
      page.formStatus.expectHasNoError();
      page.nextButton.click();
      page.formStatus.expectContainsError('Project Code must begin with a letter');
    });

    it('project code cannot use non-alphanumeric', function() {
      page.namePage.projectCodeInput.clear();
      page.namePage.projectCodeInput.sendKeys('a?' + protractor.Key.TAB);
      expect(page.namePage.projectCodeExists.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeAlphanumeric.isDisplayed()).toBe(true);
      expect(page.namePage.projectCodeOk.isDisplayed()).toBe(false);
      page.formStatus.expectHasNoError();
      page.nextButton.click();
      page.formStatus.expectContainsError('Project Code must begin with a letter');
    });

    it('project code reverts to default when Edit-project-code is disabled', function() {
      expect(page.namePage.editProjectCodeCheckbox.isDisplayed()).toBe(true);
      util.setCheckbox(page.namePage.editProjectCodeCheckbox, false);
      expect(page.namePage.projectCodeInput.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeInput.getAttribute('value')).toEqual(constants.newProjectCode);
      page.formStatus.expectHasNoError();
    });

    it('can create project', function() {
      expect(page.nextButton.isEnabled()).toBe(true);
      page.nextButton.expectFormIsValid();
      page.nextButton.click();
      expect(page.namePage.projectNameInput.isPresent()).toBe(false);
      expect(page.initialDataPage.browseButton.isPresent()).toBe(true);
      page.formStatus.expectHasNoError();
    });

  });

  describe('Initial Data page with upload', function() {

    it('cannot see back button and defaults to uploading data', function() {
      expect(page.backButton.isDisplayed()).toBe(false);
      expect(page.initialDataPage.browseButton.isDisplayed()).toBe(true);
      expect(page.progressIndicatorStep3Label.getText()).toEqual('Verify');
      page.nextButton.expectFormIsNotValid();
      page.formStatus.expectHasNoError();
    });

    describe('Mock file upload', function() {

      it('cannot upload large file', function() {
        page.initialDataPage.mockUpload.enableButton.click();
        expect(page.initialDataPage.mockUpload.fileNameInput.isPresent()).toBe(true);
        expect(page.initialDataPage.mockUpload.fileNameInput.isDisplayed()).toBe(true);
        page.initialDataPage.mockUpload.fileNameInput.sendKeys(constants.testMockZipImportFile.name);
        page.initialDataPage.mockUpload.fileSizeInput.sendKeys(134217728);
        expect(page.noticeList.count()).toBe(0);
        page.initialDataPage.mockUpload.uploadButton.click();
        expect(page.initialDataPage.browseButton.isDisplayed()).toBe(true);
        expect(page.verifyDataPage.entriesImported.isPresent()).toBe(false);
        expect(page.noticeList.count()).toBe(1);
        expect(page.noticeList.get(0).getText()).toContain('is too large. It must be smaller than');
        page.formStatus.expectHasNoError();
        page.initialDataPage.mockUpload.fileNameInput.clear();
        page.initialDataPage.mockUpload.fileSizeInput.clear();
      });

      it('cannot upload jpg', function() {
        page.initialDataPage.mockUpload.fileNameInput.sendKeys(constants.testMockJpgImportFile.name);
        page.initialDataPage.mockUpload.fileSizeInput.sendKeys(constants.testMockJpgImportFile.size);
        expect(page.noticeList.count()).toBe(1);
        page.initialDataPage.mockUpload.uploadButton.click();
        expect(page.initialDataPage.browseButton.isDisplayed()).toBe(true);
        expect(page.verifyDataPage.entriesImported.isPresent()).toBe(false);
        expect(page.noticeList.count()).toBe(2);
        expect(page.noticeList.get(1).getText()).toContain(constants.testMockJpgImportFile.name + ' is not an allowed compressed file. Ensure the file is');
        page.formStatus.expectHasNoError();
        page.initialDataPage.mockUpload.fileNameInput.clear();
        page.initialDataPage.mockUpload.fileSizeInput.clear();
      });

      it('can upload zip file', function() {
        page.initialDataPage.mockUpload.fileNameInput.sendKeys(constants.testMockZipImportFile.name);
        page.initialDataPage.mockUpload.fileSizeInput.sendKeys(constants.testMockZipImportFile.size);
        expect(page.noticeList.count()).toBe(2);
        page.initialDataPage.mockUpload.uploadButton.click();
        expect(page.verifyDataPage.entriesImported.isDisplayed()).toBe(true);
        expect(page.noticeList.count()).toBe(3);
        expect(page.noticeList.get(2).getText()).toContain('Successfully imported ' + constants.testMockZipImportFile.name);
        page.formStatus.expectHasNoError();
      });

    });

  });

  describe('Verify Data page', function() {

    it('displays stats', function() {
      expect(page.verifyDataPage.entriesImported.getText()).toEqual('2 entries were found in the initial data.');
      page.formStatus.expectHasNoError();
    });

    it('can go to lexicon', function() {

      // wait for animation to finish
      browser.sleep(2000);
      expect(page.nextButton.isDisplayed()).toBe(true);
      expect(page.nextButton.isEnabled()).toBe(true);
      page.nextButton.expectFormIsValid();
      page.nextButton.click();
      expect(dbePage.browse.getEntryCount()).toBe(2);
    });

  });

  describe('Project Name page', function() {

    it('create: new empty project', function() {
      page.get();
      page.namePage.projectNameInput.sendKeys(constants.emptyProjectName + protractor.Key.TAB);
      expect(page.namePage.projectCodeExists.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeAlphanumeric.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeOk.isDisplayed()).toBe(true);
      expect(page.nextButton.isEnabled()).toBe(true);
      page.nextButton.click();
      expect(page.namePage.projectNameInput.isPresent()).toBe(false);
      expect(page.initialDataPage.browseButton.isPresent()).toBe(true);
    });

  });

  describe('Initial Data page skipping upload', function() {

    it('can skip uploading data', function() {
      expect(page.nextButton.isEnabled()).toBe(true);
      page.nextButton.expectFormIsNotValid();
      page.nextButton.click();
      expect(page.primaryLanguagePage.selectButton.isPresent()).toBe(true);
    });

  });

  describe('Primary Language page', function() {

    it('can go back to initial data page (then forward again)', function() {
      expect(page.backButton.isDisplayed()).toBe(true);
      expect(page.backButton.isEnabled()).toBe(true);
      page.backButton.click();
      expect(page.initialDataPage.browseButton.isDisplayed()).toBe(true);
      expect(page.nextButton.isEnabled()).toBe(true);
      page.nextButton.expectFormIsNotValid();
      page.nextButton.click();
      expect(page.primaryLanguagePage.selectButton.isPresent()).toBe(true);
      expect(page.backButton.isDisplayed()).toBe(true);
    });

    it('cannot move on if language is not selected', function() {
      expect(page.nextButton.isEnabled()).toBe(true);
      page.nextButton.expectFormIsNotValid();
      page.nextButton.click();
      expect(page.primaryLanguagePage.selectButton.isPresent()).toBe(true);
      page.formStatus.expectContainsError('Please select a primary language for the project.');
    });

    it('can select language', function() {
      expect(page.primaryLanguagePage.selectButton.isEnabled()).toBe(true);
      page.primaryLanguagePage.selectButton.click();
      expect(page.modal.selectLanguage.searchLanguageInput.isPresent()).toBe(true);
    });

    describe('Select Language modal', function() {

      it('can search, select and add language', function() {
        var language = 'French';

        page.modal.selectLanguage.searchLanguageInput.sendKeys(language + protractor.Key.ENTER);
        expect(page.modal.selectLanguage.firstLanguageRow.isPresent()).toBe(true);

        expect(page.modal.selectLanguage.addButton.isPresent()).toBe(true);
        expect(page.modal.selectLanguage.addButton.isEnabled()).toBe(false);
        page.modal.selectLanguage.firstLanguageRow.click();
        expect(page.modal.selectLanguage.addButton.isEnabled()).toBe(true);
        expect(page.modal.selectLanguage.addButton.getText()).toEqual('Add ' + language);

        page.modal.selectLanguage.addButton.click();
        expect(page.modal.selectLanguage.searchLanguageInput.isPresent()).toBe(false);
      });

    });

    it('can go to lexicon and primary language has changed', function() {
      page.formStatus.expectHasNoError();
      expect(page.nextButton.isEnabled()).toBe(true);
      page.nextButton.expectFormIsValid();
      page.nextButton.click();
      expect(dbePage.browse.getEntryCount()).toBe(0);
      dbePage.browse.newWordBtn.click();
      expect(dbePage.edit.getEntryCount()).toBe(1);
      expect(dbePage.edit.getLexemesAsObject()).toEqual({'fr': ''});
    });

  });

});
<commit_msg>attempt to fix dev box E2E timing error<commit_after>'use strict';

describe('E2E testing: New Lex Project wizard app', function() {
  var constants = require('../../../testConstants.json'),
      loginPage = require('../../../bellows/pages/loginPage.js'),
      body      = require('../../../bellows/pages/pageBody.js'),
      util      = require('../../../bellows/pages/util.js'),
      dbePage   = require('../../pages/dbePage.js'),
      page      = require('../../pages/newLexProjectPage.js');

  afterEach(function() {
    expect(body.phpError.isPresent()).toBe(false);
  });

  it('admin can get to wizard', function() {
    loginPage.loginAsAdmin();
    page.get();
    expect(page.newLexProjectForm).toBeDefined();
    expect(page.namePage.projectNameInput.isPresent()).toBe(true);
  });

  it('manager can get wizard', function() {
    loginPage.loginAsManager();
    page.get();
    expect(page.newLexProjectForm).toBeDefined();
    expect(page.namePage.projectNameInput.isPresent()).toBe(true);
  });

  it('setup: user login and page contains a form', function() {
    loginPage.loginAsUser();
    page.get();
    expect(page.newLexProjectForm).toBeDefined();
    expect(page.namePage.projectNameInput.isPresent()).toBe(true);
  });

  describe('Project Name page', function() {

    it('cannot see back button', function() {
      expect(page.backButton.isDisplayed()).toBe(false);
      page.formStatus.expectHasNoError();
    });

    it('cannot move on if name is invalid', function() {
      expect(page.nextButton.isEnabled()).toBe(true);
      page.nextButton.click();
      expect(page.namePage.projectNameInput.isPresent()).toBe(true);
      page.formStatus.expectContainsError('Project Name cannot be empty.');
    });

    it('finds the test project already exists', function() {
      page.namePage.projectNameInput.sendKeys(constants.testProjectName + protractor.Key.TAB);
      expect(page.namePage.projectCodeExists.isDisplayed()).toBe(true);
      expect(page.namePage.projectCodeAlphanumeric.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeOk.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeInput.getAttribute('value')).toEqual(constants.testProjectCode);
      page.formStatus.expectContainsError("Another project with code '" + constants.testProjectCode + "' already exists.");
      page.namePage.projectNameInput.clear();
    });

    it('with a cleared name does not show an error but is still invalid', function() {

      // added the following two lines so the test will work (previous error wasn't clearing)
      // as I couldn't re-produce the problem manually,
      // however is likely symptomatic of some funkiness with promises. IJH 2014-12
      page.namePage.projectNameInput.sendKeys('a' + protractor.Key.TAB);
      page.namePage.projectNameInput.clear();
      page.namePage.projectNameInput.sendKeys(protractor.Key.TAB);
      expect(page.namePage.projectCodeExists.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeAlphanumeric.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeOk.isDisplayed()).toBe(false);
      page.formStatus.expectHasNoError();
      expect(page.nextButton.isEnabled()).toBe(true);
      page.nextButton.click();
      expect(page.namePage.projectNameInput.isPresent()).toBe(true);
      page.formStatus.expectContainsError('Project Name cannot be empty.');
    });

    it('can verify that an unused project name is available', function() {
      page.namePage.projectNameInput.sendKeys(constants.newProjectName + protractor.Key.TAB);
      expect(page.namePage.projectCodeExists.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeAlphanumeric.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeOk.isDisplayed()).toBe(true);
      expect(page.namePage.projectCodeInput.getAttribute('value')).toEqual(constants.newProjectCode);
      page.formStatus.expectHasNoError();
    });

    it('can not edit project code by default', function() {
      expect(page.namePage.projectCodeInput.isDisplayed()).toBe(false);
    });

    it('can edit project code when enabled', function() {
      expect(page.namePage.editProjectCodeCheckbox.isDisplayed()).toBe(true);
      util.setCheckbox(page.namePage.editProjectCodeCheckbox, true);
      expect(page.namePage.projectCodeInput.isDisplayed()).toBe(true);
      page.namePage.projectCodeInput.clear();
      page.namePage.projectCodeInput.sendKeys('changed_new_project' + protractor.Key.TAB);
      expect(page.namePage.projectCodeInput.getAttribute('value')).toEqual('changed_new_project');
      page.formStatus.expectHasNoError();
    });

    it('project code cannot be empty; does not show an error but is still invalid', function() {
      page.namePage.projectCodeInput.clear();
      page.namePage.projectNameInput.sendKeys(protractor.Key.TAB);     // trigger project code check
      expect(page.namePage.projectCodeExists.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeAlphanumeric.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeOk.isDisplayed()).toBe(false);
      page.formStatus.expectHasNoError();
      expect(page.nextButton.isEnabled()).toBe(true);
      page.nextButton.click();
      expect(page.namePage.projectNameInput.isPresent()).toBe(true);
      page.formStatus.expectContainsError('Project Code cannot be empty.');
    });

    it('project code can be one character', function() {
      page.namePage.projectCodeInput.clear();
      page.namePage.projectCodeInput.sendKeys('a' + protractor.Key.TAB);
      expect(page.namePage.projectCodeExists.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeAlphanumeric.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeOk.isDisplayed()).toBe(true);
      page.formStatus.expectHasNoError();
    });

    it('project code cannot be uppercase', function() {
      page.namePage.projectCodeInput.clear();
      page.namePage.projectCodeInput.sendKeys('A' + protractor.Key.TAB);
      expect(page.namePage.projectCodeExists.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeAlphanumeric.isDisplayed()).toBe(true);
      expect(page.namePage.projectCodeOk.isDisplayed()).toBe(false);
      page.formStatus.expectHasNoError();
      page.nextButton.click();
      page.formStatus.expectContainsError('Project Code must begin with a letter');
      page.namePage.projectCodeInput.clear();
      page.namePage.projectCodeInput.sendKeys('aB' + protractor.Key.TAB);
      expect(page.namePage.projectCodeExists.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeAlphanumeric.isDisplayed()).toBe(true);
      expect(page.namePage.projectCodeOk.isDisplayed()).toBe(false);
      page.formStatus.expectHasNoError();
      page.nextButton.click();
      page.formStatus.expectContainsError('Project Code must begin with a letter');
    });

    it('project code cannot start with a number', function() {
      page.namePage.projectCodeInput.clear();
      page.namePage.projectCodeInput.sendKeys('1' + protractor.Key.TAB);
      expect(page.namePage.projectCodeExists.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeAlphanumeric.isDisplayed()).toBe(true);
      expect(page.namePage.projectCodeOk.isDisplayed()).toBe(false);
      page.formStatus.expectHasNoError();
      page.nextButton.click();
      page.formStatus.expectContainsError('Project Code must begin with a letter');
    });

    it('project code cannot use non-alphanumeric', function() {
      page.namePage.projectCodeInput.clear();
      page.namePage.projectCodeInput.sendKeys('a?' + protractor.Key.TAB);
      expect(page.namePage.projectCodeExists.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeAlphanumeric.isDisplayed()).toBe(true);
      expect(page.namePage.projectCodeOk.isDisplayed()).toBe(false);
      page.formStatus.expectHasNoError();
      page.nextButton.click();
      page.formStatus.expectContainsError('Project Code must begin with a letter');
    });

    it('project code reverts to default when Edit-project-code is disabled', function() {
      expect(page.namePage.editProjectCodeCheckbox.isDisplayed()).toBe(true);
      util.setCheckbox(page.namePage.editProjectCodeCheckbox, false);
      expect(page.namePage.projectCodeInput.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeInput.getAttribute('value')).toEqual(constants.newProjectCode);
      page.formStatus.expectHasNoError();
    });

    it('can create project', function() {
      expect(page.nextButton.isEnabled()).toBe(true);
      page.nextButton.expectFormIsValid();
      page.nextButton.click();
      expect(page.namePage.projectNameInput.isPresent()).toBe(false);
      expect(page.initialDataPage.browseButton.isPresent()).toBe(true);
      page.formStatus.expectHasNoError();
    });

  });

  describe('Initial Data page with upload', function() {

    it('cannot see back button and defaults to uploading data', function() {
      expect(page.backButton.isDisplayed()).toBe(false);
      expect(page.initialDataPage.browseButton.isDisplayed()).toBe(true);
      expect(page.progressIndicatorStep3Label.getText()).toEqual('Verify');
      page.nextButton.expectFormIsNotValid();
      page.formStatus.expectHasNoError();
    });

    describe('Mock file upload', function() {

      it('cannot upload large file', function() {
        page.initialDataPage.mockUpload.enableButton.click();
        expect(page.initialDataPage.mockUpload.fileNameInput.isPresent()).toBe(true);
        expect(page.initialDataPage.mockUpload.fileNameInput.isDisplayed()).toBe(true);
        page.initialDataPage.mockUpload.fileNameInput.sendKeys(constants.testMockZipImportFile.name);
        page.initialDataPage.mockUpload.fileSizeInput.sendKeys(134217728);
        expect(page.noticeList.count()).toBe(0);
        page.initialDataPage.mockUpload.uploadButton.click();
        expect(page.initialDataPage.browseButton.isDisplayed()).toBe(true);
        expect(page.verifyDataPage.entriesImported.isPresent()).toBe(false);
        expect(page.noticeList.count()).toBe(1);
        expect(page.noticeList.get(0).getText()).toContain('is too large. It must be smaller than');
        page.formStatus.expectHasNoError();
        page.initialDataPage.mockUpload.fileNameInput.clear();
        page.initialDataPage.mockUpload.fileSizeInput.clear();
      });

      it('cannot upload jpg', function() {
        page.initialDataPage.mockUpload.fileNameInput.sendKeys(constants.testMockJpgImportFile.name);
        page.initialDataPage.mockUpload.fileSizeInput.sendKeys(constants.testMockJpgImportFile.size);
        expect(page.noticeList.count()).toBe(1);
        page.initialDataPage.mockUpload.uploadButton.click();
        expect(page.initialDataPage.browseButton.isDisplayed()).toBe(true);
        expect(page.verifyDataPage.entriesImported.isPresent()).toBe(false);
        expect(page.noticeList.count()).toBe(2);
        expect(page.noticeList.get(1).getText()).toContain(constants.testMockJpgImportFile.name + ' is not an allowed compressed file. Ensure the file is');
        page.formStatus.expectHasNoError();
        page.initialDataPage.mockUpload.fileNameInput.clear();
        page.initialDataPage.mockUpload.fileSizeInput.clear();
      });

      it('can upload zip file', function() {
        page.initialDataPage.mockUpload.fileNameInput.sendKeys(constants.testMockZipImportFile.name);
        page.initialDataPage.mockUpload.fileSizeInput.sendKeys(constants.testMockZipImportFile.size);
        expect(page.noticeList.count()).toBe(2);
        page.initialDataPage.mockUpload.uploadButton.click();
        expect(page.verifyDataPage.entriesImported.isDisplayed()).toBe(true);
        expect(page.noticeList.count()).toBe(3);
        expect(page.noticeList.get(2).getText()).toContain('Successfully imported ' + constants.testMockZipImportFile.name);
        page.formStatus.expectHasNoError();
      });

    });

  });

  describe('Verify Data page', function() {

    it('displays stats', function() {
      expect(page.verifyDataPage.entriesImported.getText()).toEqual('2 entries were found in the initial data.');
      page.formStatus.expectHasNoError();
    });

    it('can go to lexicon', function() {

      // wait for animation to finish
      browser.sleep(3000);
      expect(page.nextButton.isDisplayed()).toBe(true);
      expect(page.nextButton.isEnabled()).toBe(true);
      page.nextButton.expectFormIsValid();
      page.nextButton.click();
      expect(dbePage.browse.getEntryCount()).toBe(2);
    });

  });

  describe('Project Name page', function() {

    it('create: new empty project', function() {
      page.get();
      page.namePage.projectNameInput.sendKeys(constants.emptyProjectName + protractor.Key.TAB);
      expect(page.namePage.projectCodeExists.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeAlphanumeric.isDisplayed()).toBe(false);
      expect(page.namePage.projectCodeOk.isDisplayed()).toBe(true);
      expect(page.nextButton.isEnabled()).toBe(true);
      page.nextButton.click();
      expect(page.namePage.projectNameInput.isPresent()).toBe(false);
      expect(page.initialDataPage.browseButton.isPresent()).toBe(true);
    });

  });

  describe('Initial Data page skipping upload', function() {

    it('can skip uploading data', function() {
      expect(page.nextButton.isEnabled()).toBe(true);
      page.nextButton.expectFormIsNotValid();
      page.nextButton.click();
      expect(page.primaryLanguagePage.selectButton.isPresent()).toBe(true);
    });

  });

  describe('Primary Language page', function() {

    it('can go back to initial data page (then forward again)', function() {
      expect(page.backButton.isDisplayed()).toBe(true);
      expect(page.backButton.isEnabled()).toBe(true);
      page.backButton.click();
      expect(page.initialDataPage.browseButton.isDisplayed()).toBe(true);
      expect(page.nextButton.isEnabled()).toBe(true);
      page.nextButton.expectFormIsNotValid();
      page.nextButton.click();
      expect(page.primaryLanguagePage.selectButton.isPresent()).toBe(true);
      expect(page.backButton.isDisplayed()).toBe(true);
    });

    it('cannot move on if language is not selected', function() {
      expect(page.nextButton.isEnabled()).toBe(true);
      page.nextButton.expectFormIsNotValid();
      page.nextButton.click();
      expect(page.primaryLanguagePage.selectButton.isPresent()).toBe(true);
      page.formStatus.expectContainsError('Please select a primary language for the project.');
    });

    it('can select language', function() {
      expect(page.primaryLanguagePage.selectButton.isEnabled()).toBe(true);
      page.primaryLanguagePage.selectButton.click();
      expect(page.modal.selectLanguage.searchLanguageInput.isPresent()).toBe(true);
    });

    describe('Select Language modal', function() {

      it('can search, select and add language', function() {
        var language = 'French';

        page.modal.selectLanguage.searchLanguageInput.sendKeys(language + protractor.Key.ENTER);
        expect(page.modal.selectLanguage.firstLanguageRow.isPresent()).toBe(true);

        expect(page.modal.selectLanguage.addButton.isPresent()).toBe(true);
        expect(page.modal.selectLanguage.addButton.isEnabled()).toBe(false);
        page.modal.selectLanguage.firstLanguageRow.click();
        expect(page.modal.selectLanguage.addButton.isEnabled()).toBe(true);
        expect(page.modal.selectLanguage.addButton.getText()).toEqual('Add ' + language);

        page.modal.selectLanguage.addButton.click();
        expect(page.modal.selectLanguage.searchLanguageInput.isPresent()).toBe(false);
      });

    });

    it('can go to lexicon and primary language has changed', function() {
      page.formStatus.expectHasNoError();
      expect(page.nextButton.isEnabled()).toBe(true);
      page.nextButton.expectFormIsValid();
      page.nextButton.click();
      expect(dbePage.browse.getEntryCount()).toBe(0);
      dbePage.browse.newWordBtn.click();
      expect(dbePage.edit.getEntryCount()).toBe(1);
      expect(dbePage.edit.getLexemesAsObject()).toEqual({'fr': ''});
    });

  });

});
<|endoftext|>


<commit_before>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @format
 * @flow
 */

'use strict';

const React = require('react');

const {Alert, Button, View} = require('react-native');

class XHRExampleAbortController extends React.Component<{...}, {...}> {
  _timeout: any;

  _submit(abortDelay) {
    clearTimeout(this._timeout);
    // eslint-disable-next-line no-undef
    const abortController = new AbortController();
    fetch('https://facebook.github.io/react-native/', {
      signal: abortController.signal,
    })
      .then(res => res.text())
      .then(res => Alert.alert(res))
      .catch(err => Alert.alert(err.message));
    this._timeout = setTimeout(() => {
      abortController.abort();
    }, abortDelay);
  }

  componentWillUnmount() {
    clearTimeout(this._timeout);
  }

  render(): React.Node {
    return (
      <View>
        <Button
          title="Abort before response"
          onPress={() => {
            this._submit(0);
          }}
        />
        <Button
          title="Abort after response"
          onPress={() => {
            this._submit(5000);
          }}
        />
      </View>
    );
  }
}

module.exports = XHRExampleAbortController;
<commit_msg>Move eslint-disable no-undef to a global comment<commit_after>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @format
 * @flow
 */

'use strict';

const React = require('react');

const {Alert, Button, View} = require('react-native');

class XHRExampleAbortController extends React.Component<{...}, {...}> {
  _timeout: any;

  _submit(abortDelay) {
    clearTimeout(this._timeout);
    const abortController = new global.AbortController();
    fetch('https://facebook.github.io/react-native/', {
      signal: abortController.signal,
    })
      .then(res => res.text())
      .then(res => Alert.alert(res))
      .catch(err => Alert.alert(err.message));
    this._timeout = setTimeout(() => {
      abortController.abort();
    }, abortDelay);
  }

  componentWillUnmount() {
    clearTimeout(this._timeout);
  }

  render(): React.Node {
    return (
      <View>
        <Button
          title="Abort before response"
          onPress={() => {
            this._submit(0);
          }}
        />
        <Button
          title="Abort after response"
          onPress={() => {
            this._submit(5000);
          }}
        />
      </View>
    );
  }
}

module.exports = XHRExampleAbortController;
<|endoftext|>


<commit_before>const sass = require('gulp-sass');
const named = require('vinyl-named');
const rename = require('gulp-rename');
const path = require('path');
const fs = require('fs');
const merge = require('merge-stream');
const gulpIf = require('gulp-if');
const sourcemaps = require('gulp-sourcemaps');
const plumber = require('gulp-plumber');

const isDevelopment = !process.env.NODE_ENV || process.env.NODE_ENV == 'development';

module.exports = {
    assign: sassTask
};

function sassTask (gulp, options) {
    /*
    var series = options.sassFiles.map(function (sassFile) {
        return function (callback) {
            return gulp.src({cwd: 'shortcode/*'}, '')
                .pipe(sass().on('error', sass.logError))
                .pipe(gulp.dest('bundle'));
        };
    });
    */

    function getFolders(dir) {
        return fs.readdirSync(dir)
            .filter(function(file) {
                return fs.statSync(path.join(dir, file)).isDirectory();
            });
    }

    var series = options.sassFiles.map(function (entry) {
        if (entry.forEachFolderIn) {
            var folders = getFolders(entry.forEachFolderIn);

            var tasks = folders.map(function (folder) {
                return function () {
                    return sassProcess(
                        path.join(entry.forEachFolderIn, folder, entry.input),
                        path.join(entry.forEachFolderIn, folder, entry.output)
                    );
                }
            });

            return gulp.series(tasks);
        }

        return function () {
            return sassProcess(entry.input, entry.output);
        }
    });

    function sassProcess (input, output) {
        return gulp.src(input)
            .pipe(plumber({
                errorHandler: notify.onError(err => ({
                    title:   'Styles',
                    message: err.message
                }))
            }))
            .pipe(gulpIf(isDevelopment, sourcemaps.init()))
            .pipe(sass({
                outputStyle: isDevelopment ? 'nested' : 'compressed',
                includePaths: [
                    'bower_components',
                    'node_modules'
                ].concat(
                    options.sassIncludePaths
                )
            }).on('error', sass.logError))
            .pipe(gulpIf(isDevelopment, sourcemaps.write()))
            .pipe(gulp.dest(output));
    }

    gulp.task('sass', gulp.series(series));
}
<commit_msg>require notify<commit_after>const sass = require('gulp-sass');
const named = require('vinyl-named');
const rename = require('gulp-rename');
const path = require('path');
const fs = require('fs');
const merge = require('merge-stream');
const gulpIf = require('gulp-if');
const sourcemaps = require('gulp-sourcemaps');
const plumber = require('gulp-plumber');
const notify = require('gulp-notify');

const isDevelopment = !process.env.NODE_ENV || process.env.NODE_ENV == 'development';

module.exports = {
    assign: sassTask
};

function sassTask (gulp, options) {
    /*
    var series = options.sassFiles.map(function (sassFile) {
        return function (callback) {
            return gulp.src({cwd: 'shortcode/*'}, '')
                .pipe(sass().on('error', sass.logError))
                .pipe(gulp.dest('bundle'));
        };
    });
    */

    function getFolders(dir) {
        return fs.readdirSync(dir)
            .filter(function(file) {
                return fs.statSync(path.join(dir, file)).isDirectory();
            });
    }

    var series = options.sassFiles.map(function (entry) {
        if (entry.forEachFolderIn) {
            var folders = getFolders(entry.forEachFolderIn);

            var tasks = folders.map(function (folder) {
                return function () {
                    return sassProcess(
                        path.join(entry.forEachFolderIn, folder, entry.input),
                        path.join(entry.forEachFolderIn, folder, entry.output)
                    );
                }
            });

            return gulp.series(tasks);
        }

        return function () {
            return sassProcess(entry.input, entry.output);
        }
    });

    function sassProcess (input, output) {
        return gulp.src(input)
            .pipe(plumber({
                errorHandler: notify.onError(err => ({
                    title:   'Styles',
                    message: err.message
                }))
            }))
            .pipe(gulpIf(isDevelopment, sourcemaps.init()))
            .pipe(sass({
                outputStyle: isDevelopment ? 'nested' : 'compressed',
                includePaths: [
                    'bower_components',
                    'node_modules'
                ].concat(
                    options.sassIncludePaths
                )
            }).on('error', sass.logError))
            .pipe(gulpIf(isDevelopment, sourcemaps.write()))
            .pipe(gulp.dest(output));
    }

    gulp.task('sass', gulp.series(series));
}
<|endoftext|>