<commit_before>angular.module('cesium.es.subscription.controllers', ['cesium.es.services'])

  .config(function($stateProvider) {

    $stateProvider
      .state('app.edit_subscriptions', {
        cache: false,
        url: "/wallet/subscriptions",
        views: {
          'menuContent': {
            templateUrl: "plugins/es/templates/subscription/edit_subscriptions.html",
            controller: 'ViewSubscriptionsCtrl'
          }
        },
        data: {
          auth: true,
          minData: true
        }
      })

      .state('app.edit_subscriptions_by_id', {
        cache: false,
        url: "/wallets/:id/subscriptions",
        views: {
          'menuContent': {
            templateUrl: "plugins/es/templates/subscription/edit_subscriptions.html",
            controller: 'ViewSubscriptionsCtrl'
          }
        },
        data: {
          login: true,
          minData: true
        }
      });

  })

 .controller('ViewSubscriptionsCtrl', ViewSubscriptionsController)

 .controller('ModalEmailSubscriptionsCtrl', ModalEmailSubscriptionsController)

;

function ViewSubscriptionsController($scope, $q, $ionicHistory, csWot, csWallet, UIUtils, ModalUtils, esSubscription) {
  'ngInject';

  $scope.loading = true;
  $scope.popupData = {}; // need for the node popup
  $scope.search = {
    results: [],
    loading: true
  };
  $scope.emailFrequencies = [
    {id: "daily", label: "daily"},
    {id: "weekly", label: "weekly"}
  ];

  var wallet;

  $scope.enter = function(e, state) {

    // First load
    if ($scope.loading) {

      wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet;
      if (!wallet) {
        UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID');
        return $scope.showHome();
      }

      $scope.loadWallet({
        wallet: wallet,
        auth: true,
        minData: true
      })
        .then(function() {
          UIUtils.loading.hide();
          return $scope.load();
        })
        .catch(function(err){
          if (err == 'CANCELLED') {
            UIUtils.loading.hide(10);
            $ionicHistory.goBack();
            return;
          }
          UIUtils.onError('SUBSCRIPTION.ERROR.LOAD_SUBSCRIPTIONS_FAILED')(err);
        });
    }

  };
  $scope.$on('$ionicView.enter', $scope.enter);

  $scope.load = function() {
    $scope.loading = true; // to avoid the call of doSave()
    return esSubscription.record.load(wallet.data.pubkey, wallet.data.keypair)
      .then(function(results) {
        // Group by type
        var groups = _.groupBy((results || []), function (record) {
          return [record.type, record.recipient].join('|');
        });
        return _.keys(groups).reduce(function (res, key) {
          var parts = key.split('|');
          return res.concat({
            type: parts[0],
            recipient: parts[1],
            items: groups[key]
          });
        }, []);
      })
      .then(function(results) {
        return csWot.extendAll(results, 'recipient');
      })
      // Display result
      .then($scope.updateView)
      .catch(function(err){
        UIUtils.loading.hide(10);
        if (err && err.ucode == 404) {
          $scope.updateView([]);
          $scope.existing = false;
        }
        else {
          UIUtils.onError('PROFILE.ERROR.LOAD_PROFILE_FAILED')(err);
        }
      });
  };

  $scope.updateView = function(results) {
    if (results) {
      $scope.search.results = results;
    }

    if ($scope.search.results && $scope.search.results.length) {
      $scope.motion.show();
    }
    $scope.search.loading = false;
  };

  $scope.addSubscription = function() {
    var type;
    $scope.showCategoryModal()
      .then(function(cat) {
        if (!cat) return;
        type = cat.id;
        // get subscription parameters
        if (type == 'email') {
          return $scope.showEmailModal();
        }
        else {
          UIUtils.alert.notImplemented();
        }
      })
      .then(function(record) {
        if (!record) return;
        UIUtils.loading.show();
        esSubscription.record.add(record, wallet)
          .then($scope.addToUI)
          .then(function() {
            $scope.wallet.data.subscriptions = $scope.wallet.data.subscriptions || {count: 0};
            $scope.wallet.data.subscriptions.count++;
            UIUtils.loading.hide();
            $scope.updateView();
          })
          .catch(UIUtils.onError('SUBSCRIPTION.ERROR.ADD_SUBSCRIPTION_FAILED'));
      });
  };

  $scope.editSubscription = function(record) {

    // get subscription parameters
    var promise;
    var oldRecord = angular.copy(record);
    if (record.type == 'email') {
      promise = $scope.showEmailModal(record);
    }
    if (!promise) return;
    return promise
      .then(function(res) {
        if (!res) return;
        UIUtils.loading.show();
        record.id = oldRecord.id;
        return esSubscription.record.update(record, wallet)
          .then(function() {
            // If recipient change, update in results
            if (oldRecord.type != record.type ||
              oldRecord.recipient != record.recipient) {
              $scope.removeFromUI(oldRecord);
              return $scope.addToUI(record);
            }
          })
          .then(function() {
            UIUtils.loading.hide();
            $scope.updateView();
          })
          .catch(UIUtils.onError('SUBSCRIPTION.ERROR.UPDATE_SUBSCRIPTION_FAILED'));
      });
  };

  $scope.deleteSubscription = function(record, confirm) {
    if (!record || !record.id) return;

    if (!confirm) {
      return UIUtils.alert.confirm('SUBSCRIPTION.CONFIRM.DELETE_SUBSCRIPTION')
        .then(function(confirm) {
          if (confirm) return $scope.deleteSubscription(record, confirm);
        });
    }

    UIUtils.loading.show();
    esSubscription.record.remove(record.id)
      .then(function() {
        $scope.wallet.data.subscriptions = $scope.wallet.data.subscriptions || {count: 1};
        $scope.wallet.data.subscriptions.count--;
        $scope.removeFromUI(record);
        UIUtils.loading.hide();
      })
      .catch(UIUtils.onError('SUBSCRIPTION.ERROR.DELETE_SUBSCRIPTION_FAILED'));
  };

  $scope.removeFromUI = function(record) {
    var subscriptions = _.findWhere($scope.search.results, {type: record.type, recipient: record.recipient});
    var index = _.findIndex(subscriptions.items, record);
    if (index >= 0) {
      subscriptions.items.splice(index, 1);
    }
    if (!subscriptions.items.length) {
      index = _.findIndex($scope.search.results, subscriptions);
      $scope.search.results.splice(index, 1);
    }
  };

  $scope.addToUI = function(record) {
    $scope.search.results = $scope.search.results || [];
    var subscriptions = _.findWhere($scope.search.results,
      {type: record.type, recipient: record.recipient});

    if (!subscriptions) {
      subscriptions = {type: record.type, recipient: record.recipient, items: []};
      return csWot.extendAll([subscriptions], 'recipient')
        .then(function(){
          subscriptions.items.push(record);
          $scope.search.results.push(subscriptions);
          return record;
        });
    }

    subscriptions.items.push(record);
    return $q.when(record);
  };

  /* -- modals -- */

  $scope.showCategoryModal = function() {
    // load categories
    return esSubscription.category.all()
      .then(function(categories){
        return ModalUtils.show('plugins/es/templates/common/modal_category.html', 'ESCategoryModalCtrl as ctrl',
          {categories : categories},
          {focusFirstInput: true}
        );
      })
      .then(function(cat){
        if (cat && cat.parent) {
           return cat;
        }
      });
  };

  $scope.showEmailModal = function(parameters) {
    return ModalUtils.show('plugins/es/templates/subscription/modal_email.html','ModalEmailSubscriptionsCtrl',
      parameters, {focusFirstInput: true});
  };
}

function ModalEmailSubscriptionsController($scope, Modals, csSettings, esHttp, csWot, parameters) {
  'ngInject';

  $scope.frequencies = [
    {id: "daily", label: "daily"},
    {id: "weekly", label: "weekly"}
  ];
  $scope.formData = parameters || {};
  $scope.formData.content = $scope.formData.content || {};
  $scope.formData.content.frequency = $scope.formData.content.frequency || $scope.frequencies[0].id; // set to first value
  $scope.recipient = {};

  $scope.$on('modal.shown', function() {
    // Load recipient (uid, name, avatar...)
    if ($scope.formData.recipient) {
      $scope.recipient = {pubkey: $scope.formData.recipient};
      return csWot.extendAll([$scope.recipient]);
    }
  });

  // Submit
  $scope.doSubmit = function() {
    $scope.form.$submitted = true;
    if (!$scope.form.$valid || !$scope.formData.content.email || !$scope.formData.content.frequency) return;

    var record = {
      type: 'email',
      recipient: $scope.formData.recipient,
      content: {
        email: $scope.formData.content.email,
        locale: csSettings.data.locale.id,
        frequency: $scope.formData.content.frequency
      }
    };
    $scope.closeModal(record);
  };

  $scope.cancel = function() {
    $scope.closeModal();
  };

  if (!!$scope.subscriptionForm) {
    $scope.subscriptionForm.$setPristine();
  }

  $scope.showNetworkLookup = function() {
    return Modals.showNetworkLookup({
      enableFilter: true,
      endpointFilter: esHttp.constants.ES_USER_API_ENDPOINT
    })
      .then(function (peer) {
        if (peer) {
          $scope.recipient = peer;
          $scope.formData.recipient = peer.pubkey;
        }
      });

  };
}
<commit_msg>[fix] Subscripton: Fix add/remove actions on secondary wallets<commit_after>angular.module('cesium.es.subscription.controllers', ['cesium.es.services'])

  .config(function($stateProvider) {

    $stateProvider
      .state('app.edit_subscriptions', {
        cache: false,
        url: "/wallet/subscriptions",
        views: {
          'menuContent': {
            templateUrl: "plugins/es/templates/subscription/edit_subscriptions.html",
            controller: 'ViewSubscriptionsCtrl'
          }
        },
        data: {
          auth: true,
          minData: true
        }
      })

      .state('app.edit_subscriptions_by_id', {
        cache: false,
        url: "/wallets/:id/subscriptions",
        views: {
          'menuContent': {
            templateUrl: "plugins/es/templates/subscription/edit_subscriptions.html",
            controller: 'ViewSubscriptionsCtrl'
          }
        },
        data: {
          login: true,
          minData: true
        }
      });

  })

 .controller('ViewSubscriptionsCtrl', ViewSubscriptionsController)

 .controller('ModalEmailSubscriptionsCtrl', ModalEmailSubscriptionsController)

;

function ViewSubscriptionsController($scope, $q, $ionicHistory, csWot, csWallet, UIUtils, ModalUtils, esSubscription) {
  'ngInject';

  $scope.loading = true;
  $scope.popupData = {}; // need for the node popup
  $scope.search = {
    results: [],
    loading: true
  };
  $scope.emailFrequencies = [
    {id: "daily", label: "daily"},
    {id: "weekly", label: "weekly"}
  ];

  var wallet;

  $scope.enter = function(e, state) {

    // First load
    if ($scope.loading) {

      wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet;
      if (!wallet) {
        UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID');
        return $scope.showHome();
      }

      $scope.loadWallet({
        wallet: wallet,
        auth: true,
        minData: true
      })
        .then(function() {
          UIUtils.loading.hide();
          return $scope.load();
        })
        .catch(function(err){
          if (err == 'CANCELLED') {
            UIUtils.loading.hide(10);
            $ionicHistory.goBack();
            return;
          }
          UIUtils.onError('SUBSCRIPTION.ERROR.LOAD_SUBSCRIPTIONS_FAILED')(err);
        });
    }

  };
  $scope.$on('$ionicView.enter', $scope.enter);

  $scope.load = function() {
    $scope.loading = true; // to avoid the call of doSave()
    return esSubscription.record.load(wallet.data.pubkey, wallet.data.keypair)
      .then(function(results) {
        // Group by type
        var groups = _.groupBy((results || []), function (record) {
          return [record.type, record.recipient].join('|');
        });
        return _.keys(groups).reduce(function (res, key) {
          var parts = key.split('|');
          return res.concat({
            type: parts[0],
            recipient: parts[1],
            items: groups[key]
          });
        }, []);
      })
      .then(function(results) {
        return csWot.extendAll(results, 'recipient');
      })
      // Display result
      .then($scope.updateView)
      .catch(function(err){
        UIUtils.loading.hide(10);
        if (err && err.ucode == 404) {
          $scope.updateView([]);
          $scope.existing = false;
        }
        else {
          UIUtils.onError('PROFILE.ERROR.LOAD_PROFILE_FAILED')(err);
        }
      });
  };

  $scope.updateView = function(results) {
    if (results) {
      $scope.search.results = results;
    }

    if ($scope.search.results && $scope.search.results.length) {
      $scope.motion.show();
    }
    $scope.search.loading = false;
  };

  $scope.addSubscription = function() {
    var type;
    $scope.showCategoryModal()
      .then(function(cat) {
        if (!cat) return;
        type = cat.id;
        // get subscription parameters
        if (type == 'email') {
          return $scope.showEmailModal();
        }
        else {
          UIUtils.alert.notImplemented();
        }
      })
      .then(function(record) {
        if (!record) return;
        UIUtils.loading.show();
        esSubscription.record.add(record, wallet)
          .then($scope.addToUI)
          .then(function() {
            wallet.data.subscriptions = wallet.data.subscriptions || {count: 0};
            wallet.data.subscriptions.count++;
            UIUtils.loading.hide();
            $scope.updateView();
          })
          .catch(UIUtils.onError('SUBSCRIPTION.ERROR.ADD_SUBSCRIPTION_FAILED'));
      });
  };

  $scope.editSubscription = function(record) {

    // get subscription parameters
    var promise;
    var oldRecord = angular.copy(record);
    if (record.type == 'email') {
      promise = $scope.showEmailModal(record);
    }
    if (!promise) return;
    return promise
      .then(function(res) {
        if (!res) return;
        UIUtils.loading.show();
        record.id = oldRecord.id;
        return esSubscription.record.update(record, wallet)
          .then(function() {
            // If recipient change, update in results
            if (oldRecord.type != record.type ||
              oldRecord.recipient != record.recipient) {
              $scope.removeFromUI(oldRecord);
              return $scope.addToUI(record);
            }
          })
          .then(function() {
            UIUtils.loading.hide();
            $scope.updateView();
          })
          .catch(UIUtils.onError('SUBSCRIPTION.ERROR.UPDATE_SUBSCRIPTION_FAILED'));
      });
  };

  $scope.deleteSubscription = function(record, confirm) {
    if (!record || !record.id) return;

    if (!confirm) {
      return UIUtils.alert.confirm('SUBSCRIPTION.CONFIRM.DELETE_SUBSCRIPTION')
        .then(function(confirm) {
          if (confirm) return $scope.deleteSubscription(record, confirm);
        });
    }

    UIUtils.loading.show();
    esSubscription.record.remove(record.id, {wallet: wallet})
      .then(function() {
        wallet.data.subscriptions = wallet.data.subscriptions || {count: 1};
        wallet.data.subscriptions.count--;
        $scope.removeFromUI(record);
        UIUtils.loading.hide();
      })
      .catch(UIUtils.onError('SUBSCRIPTION.ERROR.DELETE_SUBSCRIPTION_FAILED'));
  };

  $scope.removeFromUI = function(record) {
    var subscriptions = _.findWhere($scope.search.results, {type: record.type, recipient: record.recipient});
    var index = _.findIndex(subscriptions.items, record);
    if (index >= 0) {
      subscriptions.items.splice(index, 1);
    }
    if (!subscriptions.items.length) {
      index = _.findIndex($scope.search.results, subscriptions);
      $scope.search.results.splice(index, 1);
    }
  };

  $scope.addToUI = function(record) {
    $scope.search.results = $scope.search.results || [];
    var subscriptions = _.findWhere($scope.search.results,
      {type: record.type, recipient: record.recipient});

    if (!subscriptions) {
      subscriptions = {type: record.type, recipient: record.recipient, items: []};
      return csWot.extendAll([subscriptions], 'recipient')
        .then(function(){
          subscriptions.items.push(record);
          $scope.search.results.push(subscriptions);
          return record;
        });
    }

    subscriptions.items.push(record);
    return $q.when(record);
  };

  /* -- modals -- */

  $scope.showCategoryModal = function() {
    // load categories
    return esSubscription.category.all()
      .then(function(categories){
        return ModalUtils.show('plugins/es/templates/common/modal_category.html', 'ESCategoryModalCtrl as ctrl',
          {categories : categories},
          {focusFirstInput: true}
        );
      })
      .then(function(cat){
        if (cat && cat.parent) {
           return cat;
        }
      });
  };

  $scope.showEmailModal = function(parameters) {
    return ModalUtils.show('plugins/es/templates/subscription/modal_email.html','ModalEmailSubscriptionsCtrl',
      parameters, {focusFirstInput: true});
  };
}

function ModalEmailSubscriptionsController($scope, Modals, csSettings, esHttp, csWot, parameters) {
  'ngInject';

  $scope.frequencies = [
    {id: "daily", label: "daily"},
    {id: "weekly", label: "weekly"}
  ];
  $scope.formData = parameters || {};
  $scope.formData.content = $scope.formData.content || {};
  $scope.formData.content.frequency = $scope.formData.content.frequency || $scope.frequencies[0].id; // set to first value
  $scope.recipient = {};

  $scope.$on('modal.shown', function() {
    // Load recipient (uid, name, avatar...)
    if ($scope.formData.recipient) {
      $scope.recipient = {pubkey: $scope.formData.recipient};
      return csWot.extendAll([$scope.recipient]);
    }
  });

  // Submit
  $scope.doSubmit = function() {
    $scope.form.$submitted = true;
    if (!$scope.form.$valid || !$scope.formData.content.email || !$scope.formData.content.frequency) return;

    var record = {
      type: 'email',
      recipient: $scope.formData.recipient,
      content: {
        email: $scope.formData.content.email,
        locale: csSettings.data.locale.id,
        frequency: $scope.formData.content.frequency
      }
    };
    $scope.closeModal(record);
  };

  $scope.cancel = function() {
    $scope.closeModal();
  };

  if (!!$scope.subscriptionForm) {
    $scope.subscriptionForm.$setPristine();
  }

  $scope.showNetworkLookup = function() {
    return Modals.showNetworkLookup({
      enableFilter: true,
      endpointFilter: esHttp.constants.ES_USER_API_ENDPOINT
    })
      .then(function (peer) {
        if (peer) {
          $scope.recipient = peer;
          $scope.formData.recipient = peer.pubkey;
        }
      });

  };
}
<|endoftext|>


<commit_before>import React from 'react'
import styles from './our-styles.less'
import BackButton from './back-button'

class About extends React.Component {
	render() {
		return (

This is where the about text will go!

					<BackButton link_to='/'/>

		)
	}
}

export default About<commit_msg>Changed back button to a main menu button.<commit_after>import React from 'react'
import styles from './our-styles.less'
import MainMenuButton from './main-menu-button'

class About extends React.Component {
	render() {
		return (

About

					This web application was designed and built in the Computer Science Capstone course
					in fall 2015. It was designed and built by Elinor Holm '16 and Kayla Bonnstetter '16.
					This application builds upon previous Capstone work, especially work done on the tile
					server in fall 2014. The designers would also like to thank our classmates for their design
					input and Professor Hall-Holt for his guidance. The designers hope that the application is
					fun and easy to use.

					<MainMenuButton link_to='/'/>

		)
	}
}

export default About<|endoftext|>


<commit_before>/*
 * Copyright 2010 ITA Software, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// Base for data manipulation
// TODO: A global variable? I hate you.
base = 0;

function chooseBase(max) {
    // Memoizes results!
    if (this.chooseBase.result != undefined &&
        this.chooseBase.result.max == max) {
        return result;
    }
    bases = ['', 'K', 'M', 'G', 'T'];
    for(interval = 0; interval < bases.length; interval++) {
        if(max / (Math.pow(base, interval)) <= base) {
            break;
        }
    }
    var result = new Array();
    result.interval = interval;
    result.bases = bases;
    result.max = max;
    return result;
}

// Generate ticks, passed as an option to Flot
function tickGenerator(range) {
    result = chooseBase(range.max);
    interval = result.interval

    final_base = Math.pow(base, interval);

    var noTicks = 0.3 * Math.sqrt($(".graph").height());

    var delta = ((range.max - range.min) / final_base) / noTicks,
        size, generator, unit, formatter, i, magn, norm;

    // pretty rounding of base-10 numbers
    var dec = -Math.floor(Math.log(delta) / Math.LN10);

    magn = Math.pow(10, -dec);
    norm = delta / magn; // norm is between 1.0 and 10.0

    if (norm < 1.5)
        size = 1;
    else if (norm < 3) {
        size = 2;
        // special case for 2.5, requires an extra decimal
        if (norm > 2.25) {
            size = 2.5;
            ++dec;
        }
    }
    else if (norm < 7.5)
        size = 5;
    else
        size = 10;

    size *= magn;
    size *= final_base;

    var ticks = [];
    x = 0;
    for(tick = range.min; tick < range.max+size; tick+=size) {
        ticks[x++] = tick;
    }
    return ticks;
}

// Format ticks for displayed, passed as option to Flot
function tickFormatter(val, axis) {
    result = chooseBase(axis.max);
    interval = result.interval;
    bases = result.bases;

    final_base = (Math.pow(base, interval));

    // flot computes tickDecimals before dividing by final_base, so we update
    // tickDecimals accordingly
    if (final_base != 1) {
        tickDecimals = axis.tickDecimals;
        while (tickDecimals <= 3 &&
			(val / final_base).toFixed(tickDecimals) != val / final_base)
            tickDecimals++;

		if (tickDecimals <= 3)
			axis.tickDecimals = tickDecimals;
    }

    return (val / final_base).toFixed(axis.tickDecimals) + bases[interval];
}

// Format a label, passed to Flot
function labelFormatter(label, series) {
    return label.replace(/_/g, ' ');
}

// Takes the raw data and sets up required Flot formatting options
function formatGraph(element, data) {
    base = data.base;

    data.options.yaxis.ticks = tickGenerator;
    data.options.yaxis.tickFormatter = tickFormatter;

    // TODO: Cleanup legend and axis label creation
    data.options.legend = {}
    data.options.legend.container = $(element).next('.legend');
    data.options.legend.labelFormatter = labelFormatter;
    return data;
}

// Creates a graph
function createGraph(element, path, callback, zoom) {
    $(element).append('

');
    $(element).remove('.empty');
    $.ajax({
        url: '/railroad/parserrd/' + path,
        dataType: 'json',
        success: function(data) {
            // If we are zooming and there's no data, just bail with an error
            if(zoom && data.empty) {
                plot = $(element).data('plot');
                plot.clearSelection();
                $(element).append('
no data to zoom
');
                // Nice fadeOut won't let us remove the element, so use a callback
                $(element).find('.error')
                          .delay(500)
                          .fadeOut(500,
                                   function() {
                                       $(this).remove();
                                   });
            } else {
                data = formatGraph(element, data);
                $(element).data('plot', $.plot($(element), data.data, data.options));
                if(data.options.yaxis.label) {
                    $(element).before('
' +
                                      data.options.yaxis.label +
                                      '
');
                }
                if(data.empty == true) {
                    $(element).append('
no data
');
                }

                update = $(element).closest('.graph_container')
                                   .find('.update');
                update.html('updated: ' + data.current_time);

                if(callback != null) {
                    callback(data);
                }
            }
            $(element).find('.throbber').remove();
        },
        // If there's an error, toss out a warning about it
        error: function(request, status, error) {
            plot = $(element).data('plot');
            if(zoom) {
                plot.clearSelection();
            }
            $(element).find('.throbber').remove();
            $(element).append('
error
');
            if(zoom) {
                // Nice fadeOut won't let us remove the element, so use a callback
                $(element).find('.error')
                          .delay(500)
                          .fadeOut(500,
                                   function() {
                                       $(this).remove();
                                   });
            }
        }
    });
}

// Update an AJAX timestamp
function updateTimestamp(element) {
    // TODO: Format time cleaner?
    time = new Date();
    element.html('updated: ' + time.toString());
}

// Execute setup code when page loads
$(document).ready(function() {
    // Bind the graph time range selection buttons
    $('.options ul li').click(function() {
        button = $(this)
        graph = button.closest('.graph_container')
                      .find('.graph');
        time = new Date();
        end = parseInt(time.getTime() / 1000);

        // Depending on which button is hit, change the behavior
        // TODO: Look at possibilities at cleaning this up

        if(button.hasClass('zoom')) {
            return;
        }

        button.closest('.graph_container')
              .find('.zoom')
              .css('visibility', 'hidden');

        if(button.hasClass('reset')) {
            graph.addClass('ajax');
        } else {
            graph.removeClass('ajax');
        }

        if(button.hasClass('day') || button.hasClass('reset')) {
            start = parseInt(end - 60 * 60 * 24);
        } else if(button.hasClass('week')) {
            start = parseInt(end - 60 * 60 * 24 * 7);
        } else if(button.hasClass('month')) {
            start = parseInt(end - 60 * 60 * 24 * 30);
        } else if(button.hasClass('year')) {
            start = parseInt(end - 60 * 60 * 24 * 365);
        }

        serviceData = $(graph).data();

        path = [serviceData.host,
                serviceData.service,
                start,
                end,
                serviceData.res].join('/');

        createGraph(graph,
                    path,
                    function() {
                        button.closest('.graph_container')
                              .find('.options .selected')
                              .removeClass('selected');
                        button.addClass('selected');
                    });

    });

    // Loop over the things to be graphed and produce graphs for each
    $(".graph").each(function(index, element) {

        // Store the graph data for usage later
        path = $(element).find('a').attr('href');
        splitPath = path.split('/');
        $(element).data('host', splitPath[0]);
        $(element).data('service', splitPath[1]);
        $(element).data('res', splitPath[4]);

        createGraph(element, path);

        // Allow for zooming
        $(element).bind('plotselected', function (event, ranges) {
            serviceData = $(element).data();

            path = [serviceData.host,
                    serviceData.service,
                    parseInt(ranges.xaxis.from / 1000),
                    parseInt(ranges.xaxis.to / 1000),
                    serviceData.res].join('/');

            createGraph(element,
                        path,
                        function() {
                            $(element).removeClass('ajax');
                            zoom = $(element).closest('.graph_container')
                                             .find('.zoom');
                            selected = $(element).closest('.graph_container')
                                                 .find('.selected');
                            selected.removeClass('selected');
                            zoom.css('visibility', 'visible');
                            zoom.addClass('selected');
                        },
                        true);

        });

    });

    function autoFetchData() {
        $('.graph.ajax').each(function(index, element) {
            serviceData = $(element).data();
            time = new Date();
            end = parseInt(time.getTime() / 1000);
            start = parseInt(end - 60 * 60 * 24);

            path = [serviceData.host,
                    serviceData.service,
                    start,
                    end,
                    serviceData.res].join('/');

            createGraph(element, path);
        });
        setTimeout(autoFetchData, 60 * 1000);
    }
    setTimeout(autoFetchData, 60 * 1000);
});

<commit_msg>Added check to prevent graphs from ajax loading while you are selecting<commit_after>/*
 * Copyright 2010 ITA Software, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// Base for data manipulation
// TODO: A global variable? I hate you.
base = 0;

function chooseBase(max) {
    // Memoizes results!
    if (this.chooseBase.result != undefined &&
        this.chooseBase.result.max == max) {
        return result;
    }
    bases = ['', 'K', 'M', 'G', 'T'];
    for(interval = 0; interval < bases.length; interval++) {
        if(max / (Math.pow(base, interval)) <= base) {
            break;
        }
    }
    var result = new Array();
    result.interval = interval;
    result.bases = bases;
    result.max = max;
    return result;
}

// Generate ticks, passed as an option to Flot
function tickGenerator(range) {
    result = chooseBase(range.max);
    interval = result.interval

    final_base = Math.pow(base, interval);

    var noTicks = 0.3 * Math.sqrt($(".graph").height());

    var delta = ((range.max - range.min) / final_base) / noTicks,
        size, generator, unit, formatter, i, magn, norm;

    // pretty rounding of base-10 numbers
    var dec = -Math.floor(Math.log(delta) / Math.LN10);

    magn = Math.pow(10, -dec);
    norm = delta / magn; // norm is between 1.0 and 10.0

    if (norm < 1.5)
        size = 1;
    else if (norm < 3) {
        size = 2;
        // special case for 2.5, requires an extra decimal
        if (norm > 2.25) {
            size = 2.5;
            ++dec;
        }
    }
    else if (norm < 7.5)
        size = 5;
    else
        size = 10;

    size *= magn;
    size *= final_base;

    var ticks = [];
    x = 0;
    for(tick = range.min; tick < range.max+size; tick+=size) {
        ticks[x++] = tick;
    }
    return ticks;
}

// Format ticks for displayed, passed as option to Flot
function tickFormatter(val, axis) {
    result = chooseBase(axis.max);
    interval = result.interval;
    bases = result.bases;

    final_base = (Math.pow(base, interval));

    // flot computes tickDecimals before dividing by final_base, so we update
    // tickDecimals accordingly
    if (final_base != 1) {
        tickDecimals = axis.tickDecimals;
        while (tickDecimals <= 3 &&
			(val / final_base).toFixed(tickDecimals) != val / final_base)
            tickDecimals++;

		if (tickDecimals <= 3)
			axis.tickDecimals = tickDecimals;
    }

    return (val / final_base).toFixed(axis.tickDecimals) + bases[interval];
}

// Format a label, passed to Flot
function labelFormatter(label, series) {
    return label.replace(/_/g, ' ');
}

// Takes the raw data and sets up required Flot formatting options
function formatGraph(element, data) {
    base = data.base;

    data.options.yaxis.ticks = tickGenerator;
    data.options.yaxis.tickFormatter = tickFormatter;

    // TODO: Cleanup legend and axis label creation
    data.options.legend = {}
    data.options.legend.container = $(element).next('.legend');
    data.options.legend.labelFormatter = labelFormatter;
    return data;
}

// Creates a graph
function createGraph(element, path, callback, zoom) {
    // If the graph isn't busy
    if(!$(element).data('busy')) {
        $(element).data('busy', true);
        $(element).append('

');
        $(element).remove('.empty');
        $.ajax({
            url: '/railroad/parserrd/' + path,
            dataType: 'json',
            success: function(data) {
                // If we are zooming and there's no data, just bail with an error
                if(zoom && data.empty) {
                    plot = $(element).data('plot');
                    plot.clearSelection();
                    $(element).append('
no data to zoom
');
                    // Nice fadeOut won't let us remove the element, so use a callback
                    $(element).find('.error')
                              .delay(500)
                              .fadeOut(500,
                                       function() {
                                           $(this).remove();
                                       });
                } else {
                    data = formatGraph(element, data);
                    $(element).data('plot', $.plot($(element), data.data, data.options));
                    if(data.options.yaxis.label) {
                        $(element).before('
' +
                                          data.options.yaxis.label +
                                          '
');
                    }
                    if(data.empty == true) {
                        $(element).append('
no data
');
                    }

                    update = $(element).closest('.graph_container')
                                       .find('.update');
                    update.html('updated: ' + data.current_time);

                    if(callback != null) {
                        callback(data);
                    }
                }
                $(element).find('.throbber').remove();
            },
            // If there's an error, toss out a warning about it
            error: function(request, status, error) {
                plot = $(element).data('plot');
                if(zoom) {
                    plot.clearSelection();
                }
                $(element).find('.throbber').remove();
                $(element).append('
error
');
                if(zoom) {
                    // Nice fadeOut won't let us remove the element, so use a callback
                    $(element).find('.error')
                              .delay(500)
                              .fadeOut(500,
                                       function() {
                                           $(this).remove();
                                       });
                }
            }
        });
    // Release the graph
    $(element).data('busy', null);
    }
}

// Update an AJAX timestamp
function updateTimestamp(element) {
    // TODO: Format time cleaner?
    time = new Date();
    element.html('updated: ' + time.toString());
}

// Execute setup code when page loads
$(document).ready(function() {
    // Bind the graph time range selection buttons
    $('.options ul li').click(function() {
        button = $(this)
        graph = button.closest('.graph_container')
                      .find('.graph');
        time = new Date();
        end = parseInt(time.getTime() / 1000);

        // Depending on which button is hit, change the behavior
        // TODO: Look at possibilities at cleaning this up

        if(button.hasClass('zoom')) {
            return;
        }

        button.closest('.graph_container')
              .find('.zoom')
              .css('visibility', 'hidden');

        if(button.hasClass('reset')) {
            graph.addClass('ajax');
        } else {
            graph.removeClass('ajax');
        }

        if(button.hasClass('day') || button.hasClass('reset')) {
            start = parseInt(end - 60 * 60 * 24);
        } else if(button.hasClass('week')) {
            start = parseInt(end - 60 * 60 * 24 * 7);
        } else if(button.hasClass('month')) {
            start = parseInt(end - 60 * 60 * 24 * 30);
        } else if(button.hasClass('year')) {
            start = parseInt(end - 60 * 60 * 24 * 365);
        }

        serviceData = $(graph).data();

        path = [serviceData.host,
                serviceData.service,
                start,
                end,
                serviceData.res].join('/');

        createGraph(graph,
                    path,
                    function() {
                        button.closest('.graph_container')
                              .find('.options .selected')
                              .removeClass('selected');
                        button.addClass('selected');
                    });

    });

    // Loop over the things to be graphed and produce graphs for each
    $(".graph").each(function(index, element) {

        // Store the graph data for usage later
        path = $(element).find('a').attr('href');
        splitPath = path.split('/');
        $(element).data('host', splitPath[0]);
        $(element).data('service', splitPath[1]);
        $(element).data('res', splitPath[4]);

        createGraph(element, path);

        // Allow for zooming
        $(element).bind('plotselected', function (event, ranges) {
            serviceData = $(element).data();

            path = [serviceData.host,
                    serviceData.service,
                    parseInt(ranges.xaxis.from / 1000),
                    parseInt(ranges.xaxis.to / 1000),
                    serviceData.res].join('/');

            // The graph isn't busy anymore, allow updates
            $(element).data('busy', null);

            createGraph(element,
                        path,
                        function() {
                            $(element).removeClass('ajax');
                            zoom = $(element).closest('.graph_container')
                                             .find('.zoom');
                            selected = $(element).closest('.graph_container')
                                                 .find('.selected');
                            selected.removeClass('selected');
                            zoom.css('visibility', 'visible');
                            zoom.addClass('selected');
                        },
                        true);
        });
        $(element).bind('plotselecting', function() {
            // If we are selecting, mark the graph as busy so no AJAX fires
            $(element).data('busy', true);
        });

    });

    function autoFetchData() {
        $('.graph.ajax').each(function(index, element) {
            serviceData = $(element).data();
            time = new Date();
            end = parseInt(time.getTime() / 1000);
            start = parseInt(end - 60 * 60 * 24);

            path = [serviceData.host,
                    serviceData.service,
                    start,
                    end,
                    serviceData.res].join('/');

            createGraph(element, path);
        });
        setTimeout(autoFetchData, 60 * 1000);
    }
    setTimeout(autoFetchData, 60 * 1000);
});

<|endoftext|>


<commit_before>'use strict'

const t = require('../lib/translator')
const Logger = require('../lib/logger')
const languages = require('../lib/lang')
const mixpanel = require('../lib/mixpanel')
const db = require('../db/redis')
const _ = require('lodash')

const responseType = {
  getStarted: '!getstarted',
  change: '!change'
};

class MessageHandler {

  static handleMessage(bot, payload, reply) {

    const { sender, message, postback } = payload
    bot.setTyping(sender.id, true)
    bot.getProfile(sender.id, (err, profile) => {

      if (err) return Logger.log(err)

      db.getAsync(sender.id).then((context) => {
        if (postback && postback.payload === responseType.getStarted) {
          return MessageHandler.handleGetStarted(sender, profile, reply)
        }
        if (_.includes(message.text, responseType.change)) {
          return MessageHandler.handleChange(sender, reply)
        }
        if (context === null) {
          return MessageHandler.handleNoContext(sender, message, reply)
        }
        // we made it! translate the message
        MessageHandler.handleTranslation(context, sender, message, reply)
      })
    })
  }

  static handleGetStarted(sender, profile, reply) {
    reply({
      text: `OK ${profile.first_name}, let's get started! I speak lots of languages, so go ahead and tell me what to translate for you.\n\nFor example, type "english to spanish" or "german to french"`
    }, () => {
      mixpanel.setPerson(sender, profile)
      mixpanel.track('I click to get started', sender)
    })
  }

  static handleChange(sender, reply) {
    db.delAsync(sender.id).then((err, resp) => {
      return reply({
        text: `Sure thing! What language you would like me to translate for you now? For example, type "english to spanish" or "german to french"`
      }, () => {
        mixpanel.track('I change context', sender)
      })
    })
  }

  static handleNoContext(sender, message, reply) {
    const context = MessageHandler.getContext(message.text)
    if (!context.has) {
      return reply({
        text: `I didn't quite catch that. Type, for example: "english to spanish" or "german to french"`
      }, () => {
        mixpanel.track('I incorrectly set context', sender, message)
      })
    }
    return MessageHandler.handleIncomingContext(context, sender, message, reply)
  }

  static handleIncomingContext(context, sender, message, reply) {
    // we have context, store it and reply
    const contextValue = `${context.matches[0].code}:${context.matches[1].code}`
    db.setAsync(sender.id, contextValue).then((err, resp) => {
      return reply({
        text: `${_.capitalize(context.matches[0].name)} to ${_.capitalize(context.matches[1].name)}. Got it! Now go ahead and tell me what to translate. Type "${responseType.change}" at anytime to switch languages`
      }, () => {
        mixpanel.track('I set context', sender, message)
      })
    })
  }

  static handleTranslation(context, sender, message, reply) {
    t.translate(message.text, context).
      then((result) => {
        reply({ text: result }, (err) => {
          if (err) Logger.log(err)
          mixpanel.track('I send a message to be translated', sender, message)
        })
      }).
      catch((err) => {
        reply({ text: `Oh no, something has gone wrong. Please try that again` })
      })
  }

  static getContext(message) {
    let matches = []
    const words = message.split(' ')
    words.forEach((word) => {
      languages.filter(item => item.name === _.lowerCase(word)).map((lang) => {
        if (matches.length === 2) return
        matches.push(lang)
      })
    })
    return {
      has: matches.length === 2,
      matches: matches
    }
  }
}

module.exports = MessageHandler<commit_msg>debug<commit_after>'use strict'

const t = require('../lib/translator')
const Logger = require('../lib/logger')
const languages = require('../lib/lang')
const mixpanel = require('../lib/mixpanel')
const db = require('../db/redis')
const _ = require('lodash')

const responseType = {
  getStarted: '!getstarted',
  change: '!change'
};

class MessageHandler {

  static handleMessage(bot, payload, reply) {
    console.log('PAYLOAD: ' + payload)
    const { sender, message, postback } = payload
    bot.setTyping(sender.id, true)
    bot.getProfile(sender.id, (err, profile) => {

      if (err) return Logger.log(err)

      db.getAsync(sender.id).then((context) => {
        if (postback && postback.payload === responseType.getStarted) {
          return MessageHandler.handleGetStarted(sender, profile, reply)
        }
        if (_.includes(message.text, responseType.change)) {
          return MessageHandler.handleChange(sender, reply)
        }
        if (context === null) {
          return MessageHandler.handleNoContext(sender, message, reply)
        }
        // we made it! translate the message
        MessageHandler.handleTranslation(context, sender, message, reply)
      })
    })
  }

  static handleGetStarted(sender, profile, reply) {
    reply({
      text: `OK ${profile.first_name}, let's get started! I speak lots of languages, so go ahead and tell me what to translate for you.\n\nFor example, type "english to spanish" or "german to french"`
    }, () => {
      mixpanel.setPerson(sender, profile)
      mixpanel.track('I click to get started', sender)
    })
  }

  static handleChange(sender, reply) {
    db.delAsync(sender.id).then((err, resp) => {
      return reply({
        text: `Sure thing! What language you would like me to translate for you now? For example, type "english to spanish" or "german to french"`
      }, () => {
        mixpanel.track('I change context', sender)
      })
    })
  }

  static handleNoContext(sender, message, reply) {
    const context = MessageHandler.getContext(message.text)
    if (!context.has) {
      return reply({
        text: `I didn't quite catch that. Type, for example: "english to spanish" or "german to french"`
      }, () => {
        mixpanel.track('I incorrectly set context', sender, message)
      })
    }
    return MessageHandler.handleIncomingContext(context, sender, message, reply)
  }

  static handleIncomingContext(context, sender, message, reply) {
    // we have context, store it and reply
    const contextValue = `${context.matches[0].code}:${context.matches[1].code}`
    db.setAsync(sender.id, contextValue).then((err, resp) => {
      return reply({
        text: `${_.capitalize(context.matches[0].name)} to ${_.capitalize(context.matches[1].name)}. Got it! Now go ahead and tell me what to translate. Type "${responseType.change}" at anytime to switch languages`
      }, () => {
        mixpanel.track('I set context', sender, message)
      })
    })
  }

  static handleTranslation(context, sender, message, reply) {
    t.translate(message.text, context).
      then((result) => {
        reply({ text: result }, (err) => {
          if (err) Logger.log(err)
          mixpanel.track('I send a message to be translated', sender, message)
        })
      }).
      catch((err) => {
        reply({ text: `Oh no, something has gone wrong. Please try that again` })
      })
  }

  static getContext(message) {
    let matches = []
    const words = message.split(' ')
    words.forEach((word) => {
      languages.filter(item => item.name === _.lowerCase(word)).map((lang) => {
        if (matches.length === 2) return
        matches.push(lang)
      })
    })
    return {
      has: matches.length === 2,
      matches: matches
    }
  }
}

module.exports = MessageHandler<|endoftext|>


<commit_before>/*
#
# i2mx.js - v0.1-Alpha
# Apache v2 License
#
*/

// Create img2musicXML (abbreviated as i2mx) namespace
var i2mx = i2mx || { };

// Create JsCheckup class (@TODO: Move to inside namespace)
var JsCheckup = function() {
	this.divId = "i2mx-checkup";

	this.activate = function() {
		var div = document.getElementId(this.divId);

		div.innerHTML = "No checklist for now, but img2musicXML loaded successfully!"; // @TODO: Multi-line
	}
}

var jsCheckup = new JsCheckup();

// @TODO: Use event listener instead of onload
window.onload = function() {
	jsCheckup.activate();
}
<commit_msg>Fix wrong function name. Again.<commit_after>/*
#
# i2mx.js - v0.1-Alpha
# Apache v2 License
#
*/

// Create img2musicXML (abbreviated as i2mx) namespace
var i2mx = i2mx || { };

// Create JsCheckup class (@TODO: Move to inside namespace)
var JsCheckup = function() {
	this.divId = "i2mx-checkup";

	this.activate = function() {
		var div = document.getElementById(this.divId);

		div.innerHTML = "No checklist for now, but img2musicXML loaded successfully!"; // @TODO: Multi-line
	}
}

var jsCheckup = new JsCheckup();

// @TODO: Use event listener instead of onload
window.onload = function() {
	jsCheckup.activate();
}
<|endoftext|>


<commit_before>import { base } from '../config/constants'

export var push = (resolve, reject, data, collection) => {
    base.push(collection, {
        data: data
    }).then(snapshot => {
        resolve(snapshot)
    }).catch(err => {
        //handle error
        console.log(err)
    });
}

export var update = (resolve, reject, data, collection) => {
    base.update(collection, {
        data: data
    }).then(snapshot => {
        resolve(snapshot)
    }).catch(err => {
        //handle error
        console.log(err)
    });
}

export var post = (resolve, reject, data, collection) => {
    base.post(collection, {
        data: data
    }).then(snapshot => {
        resolve(snapshot)
    }).catch(err => {
        //handle error
        console.log(err)
    });
}

export var fetch = (resolve, reject, collection, query, asArray) => {
    if(asArray === undefined){
        asArray = true
    }
    query = query || {};
    base.fetch(collection, {
    context: {},
    asArray: asArray,
    queries: query
    }).then(snapshot => {
        resolve(snapshot);
    }).catch(err => {
        //handle error
        console.log(err)
    });
}<commit_msg>added remove<commit_after>import { base } from '../config/constants'

export var push = (resolve, reject, data, collection) => {
    base.push(collection, {
        data: data
    }).then(snapshot => {
        resolve(snapshot)
    }).catch(err => {
        //handle error
        console.log(err)
    });
}

export var update = (resolve, reject, data, collection) => {
    base.update(collection, {
        data: data
    }).then(snapshot => {
        resolve(snapshot)
    }).catch(err => {
        //handle error
        console.log(err)
    });
}

export var post = (resolve, reject, data, collection) => {
    base.post(collection, {
        data: data
    }).then(snapshot => {
        resolve(snapshot)
    }).catch(err => {
        //handle error
        console.log(err)
    });
}

export var fetch = (resolve, reject, collection, query, asArray) => {
    if(asArray === undefined){
        asArray = true
    }
    query = query || {};
    base.fetch(collection, {
    context: {},
    asArray: asArray,
    queries: query
    }).then(snapshot => {
        resolve(snapshot);
    }).catch(err => {
        //handle error
        console.log(err)
    });
}

export var remove = (resolve, reject, collection) => {
    base.remove(collection)
    .then(() => {
        resolve("done")
    }).catch(err => {
        //handle error
        console.log(err)
    });
}
<|endoftext|>


<commit_before>import Ember from 'ember';
import { moduleForComponent } from 'ember-qunit';
import test from '../../ember-sinon-qunit/test';
import GMapComponent from 'ember-g-map/components/g-map';
import sinon from 'sinon';

const { run } = Ember;

let fakeMarkerObject;
let component;

moduleForComponent('g-map-marker', 'Unit | Component | g map marker', {
  // Specify the other units that are required for this test
  // needs: ['component:foo', 'helper:bar'],
  unit: true,

  beforeEach() {
    fakeMarkerObject = {
      setPosition: sinon.stub(),
      setIcon: sinon.stub(),
      setLabel: sinon.stub(),
      setTitle: sinon.stub(),
      setMap: sinon.stub(),
      addListener: sinon.stub()
    };
    sinon.stub(google.maps, 'Marker').returns(fakeMarkerObject);
    component = this.subject({
      mapContext: new GMapComponent()
    });
  },

  afterEach() {
    google.maps.Marker.restore();
  }
});

test('it constructs new `Marker` object on `didInsertElement` event', function(assert) {
  component.trigger('didInsertElement');
  sinon.assert.calledOnce(google.maps.Marker);
  assert.equal(component.get('marker'), fakeMarkerObject);
});

test('new `Marker` isn\'t constructed if it already present in component', function() {
  run(() => component.set('marker', fakeMarkerObject));
  component.trigger('didInsertElement');
  sinon.assert.notCalled(google.maps.Marker);
});

test('it triggers `setMap` on `didInsertElement` event', function() {
  component.setMap = sinon.stub();
  component.trigger('didInsertElement');
  sinon.assert.calledOnce(component.setMap);
});

test('it triggers `setOnClick` on `didInsertElement` event', function() {
  component.setOnClick = sinon.stub();
  component.trigger('didInsertElement');
  sinon.assert.calledOnce(component.setOnClick);
});

test('it triggers `unsetMarkerFromMap` on `willDestroyElement` event', function() {
  component.unsetMarkerFromMap = sinon.stub();
  component.trigger('willDestroyElement');
  sinon.assert.calledOnce(component.unsetMarkerFromMap);
});

test('it triggers `setMap` of marker with null during `unsetMarkerFromMap` if marker is set', function() {
  fakeMarkerObject.setMap = sinon.stub();

  run(() => component.set('marker', fakeMarkerObject));
  run(() => component.unsetMarkerFromMap());

  sinon.assert.calledOnce(fakeMarkerObject.setMap);
  sinon.assert.calledWith(fakeMarkerObject.setMap, null);
});

test('it doesn\'t trigger `setMap` of marker during `unsetMarkerFromMap` if there is no marker', function() {
  fakeMarkerObject.setMap = sinon.stub();

  run(() => component.set('marker', undefined));
  run(() => component.unsetMarkerFromMap());

  sinon.assert.notCalled(fakeMarkerObject.setMap);
});

test('it triggers `setMap` on `mapContext.map` change', function() {
  run(() => component.set('mapContext', { map: '' }));
  component.setMap = sinon.spy();
  run(() => component.set('mapContext.map', {}));
  sinon.assert.calledOnce(component.setMap);
});

test('it triggers `setPosition` on `didInsertElement` event', function() {
  component.setPosition = sinon.stub();
  component.trigger('didInsertElement');
  sinon.assert.calledOnce(component.setPosition);
});

test('it triggers `setPosition` on `lat` change', function() {
  component.setPosition = sinon.stub();
  run(() => component.set('lat', 14));
  sinon.assert.calledOnce(component.setPosition);
});

test('it triggers `setPosition` on `lng` change', function() {
  component.setPosition = sinon.stub();
  run(() => component.set('lng', 21));
  sinon.assert.calledOnce(component.setPosition);
});

test('it triggers `setPosition` only once on `lat` and `lng` change', function() {
  component.setPosition = sinon.stub();
  run(() => component.setProperties({ lng: 1, lat: 11 }));
  sinon.assert.calledOnce(component.setPosition);
});

test('it calls `setPosition` of google marker on `setPosition` with lat/lng present', function() {
  const point = {};
  sinon.stub(google.maps, 'LatLng').returns(point);

  run(() => component.setProperties({
    lat: 10,
    lng: 100,
    marker: fakeMarkerObject
  }));

  fakeMarkerObject.setPosition = sinon.stub();

  run(() => component.setPosition());

  sinon.assert.calledOnce(fakeMarkerObject.setPosition);
  sinon.assert.calledWith(fakeMarkerObject.setPosition, point);

  google.maps.LatLng.restore();
});

test('it doesn\'t call `setPosition` of google marker on `setPosition` when no lat present', function() {
  fakeMarkerObject.setPosition = sinon.stub();

  run(() => component.setProperties({
    lng: 100,
    marker: fakeMarkerObject
  }));
  run(() => component.setPosition());
  sinon.assert.notCalled(fakeMarkerObject.setPosition);
});

test('it doesn\'t call `setPosition` of google marker on `setPosition` when no lng present', function() {
  fakeMarkerObject.setPosition = sinon.stub();

  run(() => component.setProperties({
    lat: 10,
    marker: fakeMarkerObject
  }));
  run(() => component.setPosition());

  sinon.assert.notCalled(fakeMarkerObject.setPosition);
});

test('it calls `setMap` of google marker on `setMap` with `map` present', function() {
  const mapObject = {};
  run(() => component.setProperties({
    map: mapObject,
    marker: fakeMarkerObject
  }));

  fakeMarkerObject.setMap = sinon.stub();

  run(() => component.setMap());

  sinon.assert.calledOnce(fakeMarkerObject.setMap);
  sinon.assert.calledWith(fakeMarkerObject.setMap, mapObject);
});

test('it doesn\'t call `setMap` of google marker on `setMap` when no `map` present', function() {
  fakeMarkerObject.setMap = sinon.stub();
  run(() => component.setMap());
  sinon.assert.notCalled(fakeMarkerObject.setMap);
});

test('it triggers `setIcon` on `didInsertElement` event', function() {
  component.setIcon = sinon.stub();
  component.trigger('didInsertElement');
  sinon.assert.calledOnce(component.setIcon);
});

test('it triggers `setIcon` on `icon` change', function() {
  component.setIcon = sinon.stub();
  run(() => component.set('icon', 'image-src'));
  sinon.assert.calledOnce(component.setIcon);
});

test('it calls `setIcon` of google marker on `setIcon` with icon present', function() {
  run(() => component.setProperties({
    icon: 'image-src',
    marker: fakeMarkerObject
  }));

  fakeMarkerObject.setIcon = sinon.stub();

  run(() => component.setIcon());

  sinon.assert.calledOnce(fakeMarkerObject.setIcon);
  sinon.assert.calledWith(fakeMarkerObject.setIcon, 'image-src');
});

test('it doesn\'t call `setIcon` of google marker on `setIcon` when no icon present', function() {
  fakeMarkerObject.setIcon = sinon.stub();

  run(() => component.setProperties({
    icon: undefined,
    marker: fakeMarkerObject
  }));
  run(() => component.setIcon());

  sinon.assert.notCalled(fakeMarkerObject.setIcon);
});

test('it triggers `setLabel` on `didInsertElement` event', function() {
  component.setLabel = sinon.stub();
  component.trigger('didInsertElement');
  sinon.assert.calledOnce(component.setLabel);
});

test('it triggers `setLabel` on `label` change', function() {
  component.setLabel = sinon.stub();
  run(() => component.set('label', 'A'));
  sinon.assert.calledOnce(component.setLabel);
});

test('it calls `setLabel` of google marker on `setLabel` with label present', function() {
  run(() => component.setProperties({
    label: 'A',
    marker: fakeMarkerObject
  }));

  fakeMarkerObject.setLabel = sinon.stub();

  run(() => component.setLabel());

  sinon.assert.calledOnce(fakeMarkerObject.setLabel);
  sinon.assert.calledWith(fakeMarkerObject.setLabel, 'A');
});

test('it doesn\'t call `setLabel` of google marker on `setLabel` when no label present', function() {
  fakeMarkerObject.setLabel = sinon.stub();

  run(() => component.setProperties({
    label: undefined,
    marker: fakeMarkerObject
  }));
  run(() => component.setLabel());

  sinon.assert.notCalled(fakeMarkerObject.setLabel);
});

test('it triggers `setTitle` on `didInsertElement` event', function() {
  component.setTitle = sinon.stub();
  component.trigger('didInsertElement');
  sinon.assert.calledOnce(component.setTitle);
});

test('it triggers `setTitle` on `title` change', function() {
  component.setTitle = sinon.stub();
  run(() => component.set('title', 'marker-title'));
  sinon.assert.calledOnce(component.setTitle);
});

test('it registers itself in parent\'s `markers` array on `init` event', function() {
  let mapContext;
  run(() => mapContext = component.get('mapContext'));
  mapContext.registerMarker = sinon.stub();

  component.trigger('init');

  sinon.assert.calledOnce(mapContext.registerMarker);
  sinon.assert.calledWith(mapContext.registerMarker, component);
});

test('it unregisters itself in parent\'s `markers` array on `willDestroyElement` event', function() {
  let mapContext;
  run(() => mapContext = component.get('mapContext'));
  mapContext.unregisterMarker = sinon.stub();

  component.trigger('willDestroyElement');

  sinon.assert.calledOnce(mapContext.unregisterMarker);
  sinon.assert.calledWith(mapContext.unregisterMarker, component);
});

test('it calls `addListener` of google marker on `setOnClick` with `marker` present', function() {
  fakeMarkerObject.addListener = sinon.stub().callsArg(1);
  run(() => component.set('marker', fakeMarkerObject));
  component.sendOnClick = sinon.stub();

  run(() => component.setOnClick());

  sinon.assert.calledOnce(fakeMarkerObject.addListener);
  sinon.assert.calledWith(fakeMarkerObject.addListener, 'click');

  sinon.assert.calledOnce(component.sendOnClick);
});

test('it sends action `onClick` on callback for `click` event', function() {
  component.sendAction = sinon.stub();

  run(() => component.set('attrs', { onClick: 'action' }));
  run(() => component.sendOnClick());

  sinon.assert.calledOnce(component.sendAction);
  sinon.assert.calledWith(component.sendAction, 'onClick');
});

test('it runs closure action `attrs.onClick` directly on callback for `click` event', function() {
  run(() => component.set('attrs', { onClick: sinon.stub() }));
  run(() => component.sendOnClick());

  sinon.assert.calledOnce(component.attrs.onClick);
});

test('it calls `groupMarkerClicked` of map context on `sendOnClick` with `group` present', function() {
  let mapContext;
  run(() => mapContext = component.get('mapContext'));
  mapContext.groupMarkerClicked = sinon.stub();

  run(() => component.setProperties({
    group: 'cats',
    attrs: {}
  }));
  run(() => component.sendOnClick());

  sinon.assert.calledOnce(mapContext.groupMarkerClicked);
  sinon.assert.calledWith(mapContext.groupMarkerClicked, component, 'cats');
});

test('it doesn\'t call `groupMarkerClicked` of google marker on `sendOnClick` when no `group` present', function() {
  let mapContext;
  run(() => mapContext = component.get('mapContext'));
  mapContext.groupMarkerClicked = sinon.stub();

  run(() => component.set('attrs', {}));
  run(() => component.sendOnClick());
  sinon.assert.notCalled(mapContext.groupMarkerClicked);
});

test('it calls `close` of infowindow on `closeInfowindow`', function() {
  const infowindow = { close: sinon.stub() };
  run(() => component.set('infowindow', infowindow));

  run(() => component.closeInfowindow());
  sinon.assert.calledOnce(infowindow.close);
});
<commit_msg>Improve code coverage<commit_after>import Ember from 'ember';
import { moduleForComponent } from 'ember-qunit';
import test from '../../ember-sinon-qunit/test';
import GMapComponent from 'ember-g-map/components/g-map';
import sinon from 'sinon';

const { run } = Ember;

let fakeMarkerObject;
let component;

moduleForComponent('g-map-marker', 'Unit | Component | g map marker', {
  // Specify the other units that are required for this test
  // needs: ['component:foo', 'helper:bar'],
  unit: true,

  beforeEach() {
    fakeMarkerObject = {
      setPosition: sinon.stub(),
      setIcon: sinon.stub(),
      setLabel: sinon.stub(),
      setTitle: sinon.stub(),
      setMap: sinon.stub(),
      addListener: sinon.stub()
    };
    sinon.stub(google.maps, 'Marker').returns(fakeMarkerObject);
    component = this.subject({
      mapContext: new GMapComponent()
    });
  },

  afterEach() {
    google.maps.Marker.restore();
  }
});

test('it constructs new `Marker` object on `didInsertElement` event', function(assert) {
  component.trigger('didInsertElement');
  sinon.assert.calledOnce(google.maps.Marker);
  assert.equal(component.get('marker'), fakeMarkerObject);
});

test('new `Marker` isn\'t constructed if it already present in component', function() {
  run(() => component.set('marker', fakeMarkerObject));
  component.trigger('didInsertElement');
  sinon.assert.notCalled(google.maps.Marker);
});

test('it triggers `setMap` on `didInsertElement` event', function() {
  component.setMap = sinon.stub();
  component.trigger('didInsertElement');
  sinon.assert.calledOnce(component.setMap);
});

test('it triggers `setOnClick` on `didInsertElement` event', function() {
  component.setOnClick = sinon.stub();
  component.trigger('didInsertElement');
  sinon.assert.calledOnce(component.setOnClick);
});

test('it triggers `unsetMarkerFromMap` on `willDestroyElement` event', function() {
  component.unsetMarkerFromMap = sinon.stub();
  component.trigger('willDestroyElement');
  sinon.assert.calledOnce(component.unsetMarkerFromMap);
});

test('it triggers `setMap` of marker with null during `unsetMarkerFromMap` if marker is set', function() {
  fakeMarkerObject.setMap = sinon.stub();

  run(() => component.set('marker', fakeMarkerObject));
  run(() => component.unsetMarkerFromMap());

  sinon.assert.calledOnce(fakeMarkerObject.setMap);
  sinon.assert.calledWith(fakeMarkerObject.setMap, null);
});

test('it doesn\'t trigger `setMap` of marker during `unsetMarkerFromMap` if there is no marker', function() {
  fakeMarkerObject.setMap = sinon.stub();

  run(() => component.set('marker', undefined));
  run(() => component.unsetMarkerFromMap());

  sinon.assert.notCalled(fakeMarkerObject.setMap);
});

test('it triggers `setMap` on `mapContext.map` change', function() {
  run(() => component.set('mapContext', { map: '' }));
  component.setMap = sinon.spy();
  run(() => component.set('mapContext.map', {}));
  sinon.assert.calledOnce(component.setMap);
});

test('it triggers `setPosition` on `didInsertElement` event', function() {
  component.setPosition = sinon.stub();
  component.trigger('didInsertElement');
  sinon.assert.calledOnce(component.setPosition);
});

test('it triggers `setPosition` on `lat` change', function() {
  component.setPosition = sinon.stub();
  run(() => component.set('lat', 14));
  sinon.assert.calledOnce(component.setPosition);
});

test('it triggers `setPosition` on `lng` change', function() {
  component.setPosition = sinon.stub();
  run(() => component.set('lng', 21));
  sinon.assert.calledOnce(component.setPosition);
});

test('it triggers `setPosition` only once on `lat` and `lng` change', function() {
  component.setPosition = sinon.stub();
  run(() => component.setProperties({ lng: 1, lat: 11 }));
  sinon.assert.calledOnce(component.setPosition);
});

test('it calls `setPosition` of google marker on `setPosition` with lat/lng present', function() {
  const point = {};
  sinon.stub(google.maps, 'LatLng').returns(point);

  run(() => component.setProperties({
    lat: 10,
    lng: 100,
    marker: fakeMarkerObject
  }));

  fakeMarkerObject.setPosition = sinon.stub();

  run(() => component.setPosition());

  sinon.assert.calledOnce(fakeMarkerObject.setPosition);
  sinon.assert.calledWith(fakeMarkerObject.setPosition, point);

  google.maps.LatLng.restore();
});

test('it doesn\'t call `setPosition` of google marker on `setPosition` when no lat present', function() {
  fakeMarkerObject.setPosition = sinon.stub();

  run(() => component.setProperties({
    lng: 100,
    marker: fakeMarkerObject
  }));
  run(() => component.setPosition());
  sinon.assert.notCalled(fakeMarkerObject.setPosition);
});

test('it doesn\'t call `setPosition` of google marker on `setPosition` when no lng present', function() {
  fakeMarkerObject.setPosition = sinon.stub();

  run(() => component.setProperties({
    lat: 10,
    marker: fakeMarkerObject
  }));
  run(() => component.setPosition());

  sinon.assert.notCalled(fakeMarkerObject.setPosition);
});

test('it calls `setMap` of google marker on `setMap` with `map` present', function() {
  const mapObject = {};
  run(() => component.setProperties({
    map: mapObject,
    marker: fakeMarkerObject
  }));

  fakeMarkerObject.setMap = sinon.stub();

  run(() => component.setMap());

  sinon.assert.calledOnce(fakeMarkerObject.setMap);
  sinon.assert.calledWith(fakeMarkerObject.setMap, mapObject);
});

test('it doesn\'t call `setMap` of google marker on `setMap` when no `map` present', function() {
  fakeMarkerObject.setMap = sinon.stub();
  run(() => component.setMap());
  sinon.assert.notCalled(fakeMarkerObject.setMap);
});

test('it triggers `setIcon` on `didInsertElement` event', function() {
  component.setIcon = sinon.stub();
  component.trigger('didInsertElement');
  sinon.assert.calledOnce(component.setIcon);
});

test('it triggers `setIcon` on `icon` change', function() {
  component.setIcon = sinon.stub();
  run(() => component.set('icon', 'image-src'));
  sinon.assert.calledOnce(component.setIcon);
});

test('it calls `setIcon` of google marker on `setIcon` with icon present', function() {
  run(() => component.setProperties({
    icon: 'image-src',
    marker: fakeMarkerObject
  }));

  fakeMarkerObject.setIcon = sinon.stub();

  run(() => component.setIcon());

  sinon.assert.calledOnce(fakeMarkerObject.setIcon);
  sinon.assert.calledWith(fakeMarkerObject.setIcon, 'image-src');
});

test('it doesn\'t call `setIcon` of google marker on `setIcon` when no icon present', function() {
  fakeMarkerObject.setIcon = sinon.stub();

  run(() => component.setProperties({
    icon: undefined,
    marker: fakeMarkerObject
  }));
  run(() => component.setIcon());

  sinon.assert.notCalled(fakeMarkerObject.setIcon);
});

test('it triggers `setLabel` on `didInsertElement` event', function() {
  component.setLabel = sinon.stub();
  component.trigger('didInsertElement');
  sinon.assert.calledOnce(component.setLabel);
});

test('it triggers `setLabel` on `label` change', function() {
  component.setLabel = sinon.stub();
  run(() => component.set('label', 'A'));
  sinon.assert.calledOnce(component.setLabel);
});

test('it calls `setLabel` of google marker on `setLabel` with label present', function() {
  run(() => component.setProperties({
    label: 'A',
    marker: fakeMarkerObject
  }));

  fakeMarkerObject.setLabel = sinon.stub();

  run(() => component.setLabel());

  sinon.assert.calledOnce(fakeMarkerObject.setLabel);
  sinon.assert.calledWith(fakeMarkerObject.setLabel, 'A');
});

test('it doesn\'t call `setLabel` of google marker on `setLabel` when no label present', function() {
  fakeMarkerObject.setLabel = sinon.stub();

  run(() => component.setProperties({
    label: undefined,
    marker: fakeMarkerObject
  }));
  run(() => component.setLabel());

  sinon.assert.notCalled(fakeMarkerObject.setLabel);
});

test('it doesn\'t call `setLabel` of google marker on `setLabel` when no label present', function() {
  fakeMarkerObject.setLabel = sinon.stub();

  run(() => component.setProperties({
    label: undefined,
    marker: fakeMarkerObject
  }));
  run(() => component.setLabel());

  sinon.assert.notCalled(fakeMarkerObject.setLabel);
});

test('it triggers `setTitle` on `didInsertElement` event', function() {
  component.setTitle = sinon.stub();
  component.trigger('didInsertElement');
  sinon.assert.calledOnce(component.setTitle);
});

test('it triggers `setTitle` on `title` change', function() {
  component.setTitle = sinon.stub();
  run(() => component.set('title', 'marker-title'));
  sinon.assert.calledOnce(component.setTitle);
});

test('it calls `setTitle` of google marker on `setTitle` with title present', function() {
  run(() => component.setProperties({
    title: 'Marker #13',
    marker: fakeMarkerObject
  }));

  fakeMarkerObject.setTitle = sinon.stub();

  run(() => component.setTitle());

  sinon.assert.calledOnce(fakeMarkerObject.setTitle);
  sinon.assert.calledWith(fakeMarkerObject.setTitle, 'Marker #13');
});

test('it doesn\'t call `setTitle` of google marker on `setTitle` when no title present', function() {
  fakeMarkerObject.setTitle = sinon.stub();

  run(() => component.setProperties({
    title: undefined,
    marker: fakeMarkerObject
  }));
  run(() => component.setTitle());

  sinon.assert.notCalled(fakeMarkerObject.setTitle);
});

test('it registers itself in parent\'s `markers` array on `init` event', function() {
  let mapContext;
  run(() => mapContext = component.get('mapContext'));
  mapContext.registerMarker = sinon.stub();

  component.trigger('init');

  sinon.assert.calledOnce(mapContext.registerMarker);
  sinon.assert.calledWith(mapContext.registerMarker, component);
});

test('it unregisters itself in parent\'s `markers` array on `willDestroyElement` event', function() {
  let mapContext;
  run(() => mapContext = component.get('mapContext'));
  mapContext.unregisterMarker = sinon.stub();

  component.trigger('willDestroyElement');

  sinon.assert.calledOnce(mapContext.unregisterMarker);
  sinon.assert.calledWith(mapContext.unregisterMarker, component);
});

test('it calls `addListener` of google marker on `setOnClick` with `marker` present', function() {
  fakeMarkerObject.addListener = sinon.stub().callsArg(1);
  run(() => component.set('marker', fakeMarkerObject));
  component.sendOnClick = sinon.stub();

  run(() => component.setOnClick());

  sinon.assert.calledOnce(fakeMarkerObject.addListener);
  sinon.assert.calledWith(fakeMarkerObject.addListener, 'click');

  sinon.assert.calledOnce(component.sendOnClick);
});

test('it sends action `onClick` on callback for `click` event', function() {
  component.sendAction = sinon.stub();

  run(() => component.set('attrs', { onClick: 'action' }));
  run(() => component.sendOnClick());

  sinon.assert.calledOnce(component.sendAction);
  sinon.assert.calledWith(component.sendAction, 'onClick');
});

test('it runs closure action `attrs.onClick` directly on callback for `click` event', function() {
  run(() => component.set('attrs', { onClick: sinon.stub() }));
  run(() => component.sendOnClick());

  sinon.assert.calledOnce(component.attrs.onClick);
});

test('it calls `groupMarkerClicked` of map context on `sendOnClick` with `group` present', function() {
  let mapContext;
  run(() => mapContext = component.get('mapContext'));
  mapContext.groupMarkerClicked = sinon.stub();

  run(() => component.setProperties({
    group: 'cats',
    attrs: {}
  }));
  run(() => component.sendOnClick());

  sinon.assert.calledOnce(mapContext.groupMarkerClicked);
  sinon.assert.calledWith(mapContext.groupMarkerClicked, component, 'cats');
});

test('it doesn\'t call `groupMarkerClicked` of google marker on `sendOnClick` when no `group` present', function() {
  let mapContext;
  run(() => mapContext = component.get('mapContext'));
  mapContext.groupMarkerClicked = sinon.stub();

  run(() => component.set('attrs', {}));
  run(() => component.sendOnClick());
  sinon.assert.notCalled(mapContext.groupMarkerClicked);
});

test('it calls `close` of infowindow on `closeInfowindow`', function() {
  const infowindow = { close: sinon.stub() };
  run(() => component.set('infowindow', infowindow));

  run(() => component.closeInfowindow());
  sinon.assert.calledOnce(infowindow.close);
});
<|endoftext|>


<commit_before>(function ( $ ) {

module( "selectmenu: events", {
	setup: function () {
		this.element = $( "#speed" );
	}
});

test( "change", function () {
	expect( 4 );

	this.element.selectmenu({
		change: function ( event, ui ) {
			ok( event, "change event fired on change" );
			equal( event.type, "selectmenuchange", "event type set to selectmenuchange" );
			equal( ui.item.element[ 0 ].nodeName, "OPTION", "ui.item.element[0] points to original option element" );
			equal( ui.item.value, value, "ui.item.value property updated correctly" );
		}
	});

	var button = this.element.selectmenu( "widget" ),
		menu = this.element.selectmenu( "menuWidget" ).parent(),
		value = this.element.find( "option" ).first().text();

	button.simulate( "focus" ).simulate( "click" );
	menu.find( "a" ).first().simulate( "mouseover" ).simulate( "click" );
});

test( "close", function () {
	expect( 3 );

	this.element.selectmenu({
		close: function ( event, ui ) {
			ok( event, "close event fired on close" );
			equal( event.type, "selectmenuclose", "event type set to selectmenuclose" );
			ok( ui, "ui object is passed as second argument to event handler" );
		}
	});

	this.element.selectmenu( "open" ).selectmenu( "close" );
});

test( "focus", function () {
	expect( 4 );

	var button,
		menu,
		links;

	this.element.selectmenu({
		focus: function ( event, ui ) {
			ok( event, "focus event fired on mouseover" );
			equal( event.type, "selectmenufocus", "event type set to selectmenufocus" );
			ok( ui, "ui object is passed as second argument to event handler" );
			equal( ui.item.element[0].nodeName, "OPTION", "ui points to original option element" );
		}
	});

	button = this.element.selectmenu( "widget" ),
	menu = this.element.selectmenu( "menuWidget" );

	button.simulate( "focus" );
	links = menu.find( "li.ui-menu-item a" );

	button.simulate( "click" );

	menu.find( "a" ).last().simulate( "mouseover" );

	this.element.selectmenu( "close" );
});

test( "open", function () {
	expect( 3 );

	this.element.selectmenu({
		open: function ( event, ui ) {
			ok( event, "open event fired on open" );
			equal( event.type, "selectmenuopen", "event type set to selectmenuopen" );
			ok( ui, "ui object is passed as second argument to event handler" );
		}
	});

	this.element.selectmenu( "open" );
});

test( "select", function () {
	expect( 4 );

	this.element.selectmenu({
		select: function ( event, ui ) {
			ok( event, "select event fired on item select" );
			equal( event.type, "selectmenuselect", "event type set to selectmenuselect" );
			ok( ui, "ui object is passed as second argument to event handler" );
			equal( ui.item.element[0].nodeName, "OPTION", "ui points to original option element" );
		}
	});

	var button = this.element.selectmenu( "widget" ),
		menu = this.element.selectmenu( "menuWidget" ).parent();

	button.simulate( "focus" ).simulate( "click" );
	menu.find( "a" ).first().simulate( "mouseover" ).simulate( "click" );
});

})(jQuery);
<commit_msg>Selectmenu Tests: remove unneeded test<commit_after>(function ( $ ) {

module( "selectmenu: events", {
	setup: function () {
		this.element = $( "#speed" );
	}
});

test( "change", function () {
	expect( 4 );

	this.element.selectmenu({
		change: function ( event, ui ) {
			ok( event, "change event fired on change" );
			equal( event.type, "selectmenuchange", "event type set to selectmenuchange" );
			equal( ui.item.element[ 0 ].nodeName, "OPTION", "ui.item.element[0] points to original option element" );
			equal( ui.item.value, value, "ui.item.value property updated correctly" );
		}
	});

	var button = this.element.selectmenu( "widget" ),
		menu = this.element.selectmenu( "menuWidget" ).parent(),
		value = this.element.find( "option" ).first().text();

	button.simulate( "focus" ).simulate( "click" );
	menu.find( "a" ).first().simulate( "mouseover" ).simulate( "click" );
});

test( "close", function () {
	expect( 2 );

	this.element.selectmenu({
		close: function ( event, ui ) {
			ok( event, "close event fired on close" );
			equal( event.type, "selectmenuclose", "event type set to selectmenuclose" );
		}
	});

	this.element.selectmenu( "open" ).selectmenu( "close" );
});

test( "focus", function () {
	expect( 3 );

	var button,
		menu,
		links;

	this.element.selectmenu({
		focus: function ( event, ui ) {
			ok( event, "focus event fired on mouseover" );
			equal( event.type, "selectmenufocus", "event type set to selectmenufocus" );
			equal( ui.item.element[0].nodeName, "OPTION", "ui points to original option element" );
		}
	});

	button = this.element.selectmenu( "widget" ),
	menu = this.element.selectmenu( "menuWidget" );

	button.simulate( "focus" );
	links = menu.find( "li.ui-menu-item a" );

	button.simulate( "click" );

	menu.find( "a" ).last().simulate( "mouseover" );

	this.element.selectmenu( "close" );
});

test( "open", function () {
	expect( 2 );

	this.element.selectmenu({
		open: function ( event, ui ) {
			ok( event, "open event fired on open" );
			equal( event.type, "selectmenuopen", "event type set to selectmenuopen" );
		}
	});

	this.element.selectmenu( "open" );
});

test( "select", function () {
	expect( 3 );

	this.element.selectmenu({
		select: function ( event, ui ) {
			ok( event, "select event fired on item select" );
			equal( event.type, "selectmenuselect", "event type set to selectmenuselect" );
			equal( ui.item.element[0].nodeName, "OPTION", "ui points to original option element" );
		}
	});

	var button = this.element.selectmenu( "widget" ),
		menu = this.element.selectmenu( "menuWidget" ).parent();

	button.simulate( "focus" ).simulate( "click" );
	menu.find( "a" ).first().simulate( "mouseover" ).simulate( "click" );
});

})(jQuery);
<|endoftext|>


<commit_before>"use strict";

const sharedUtil = require("../../src/common/util-shared");

test("shared util has correct structure", () => {
  expect(typeof sharedUtil.getMaxContinuousCount).toEqual("function");
  expect(typeof sharedUtil.getStringWidth).toEqual("function");
  expect(typeof sharedUtil.getAlignmentSize).toEqual("function");
  expect(typeof sharedUtil.getIndentSize).toEqual("function");
  expect(typeof sharedUtil.skip).toEqual("function");
  expect(typeof sharedUtil.skipWhitespace).toEqual("function");
  expect(typeof sharedUtil.skipSpaces).toEqual("function");
  expect(typeof sharedUtil.skipToLineEnd).toEqual("function");
  expect(typeof sharedUtil.skipEverythingButNewLine).toEqual("function");
  expect(typeof sharedUtil.skipInlineComment).toEqual("function");
  expect(typeof sharedUtil.skipTrailingComment).toEqual("function");
  expect(typeof sharedUtil.skipNewline).toEqual("function");
  expect(typeof sharedUtil.hasNewline).toEqual("function");
  expect(typeof sharedUtil.hasNewlineInRange).toEqual("function");
  expect(typeof sharedUtil.hasSpaces).toEqual("function");
  expect(typeof sharedUtil.isNextLineEmpty).toEqual("function");
  expect(typeof sharedUtil.isNextLineEmptyAfterIndex).toEqual("function");
  expect(typeof sharedUtil.isPreviousLineEmpty).toEqual("function");
  expect(typeof sharedUtil.getNextNonSpaceNonCommentCharacterIndex).toEqual(
    "function"
  );
  expect(typeof sharedUtil.makeString).toEqual("function");
});

test("sharedUtil.getMaxContinuousCount", () => {
  const { getMaxContinuousCount } = sharedUtil;

  expect(getMaxContinuousCount("|---|--|-|--|---|", "-")).toEqual(3);
  expect(getMaxContinuousCount("|...|", ".")).toEqual(3);

  const fixture = [
    "([a-f])([a-f])",
    "[a-f][a-f][a-f]",
    "a-fa-fa-fa-f",
    "bbbbbbbbbbbbbbbbbb", // neither `a-f` `[a-f]` `([a-f])` should matches `b`
  ].join("");
  expect(getMaxContinuousCount(fixture, "([a-f])")).toEqual(2);
  expect(getMaxContinuousCount(fixture, "[a-f]")).toEqual(3);
  expect(getMaxContinuousCount(fixture, "a-f")).toEqual(4);
  expect(getMaxContinuousCount(fixture, "([a\\-f])")).toEqual(0);
  expect(getMaxContinuousCount(fixture, "[a\\-f]")).toEqual(0);
  expect(getMaxContinuousCount(fixture, "a\\-f")).toEqual(0);
});
<commit_msg>Add some tests for `sharedUtil` (#8412)<commit_after>"use strict";

const sharedUtil = require("../../src/common/util-shared");

test("shared util has correct structure", () => {
  expect(typeof sharedUtil.getMaxContinuousCount).toEqual("function");
  expect(typeof sharedUtil.getStringWidth).toEqual("function");
  expect(typeof sharedUtil.getAlignmentSize).toEqual("function");
  expect(typeof sharedUtil.getIndentSize).toEqual("function");
  expect(typeof sharedUtil.skip).toEqual("function");
  expect(typeof sharedUtil.skipWhitespace).toEqual("function");
  expect(typeof sharedUtil.skipSpaces).toEqual("function");
  expect(typeof sharedUtil.skipToLineEnd).toEqual("function");
  expect(typeof sharedUtil.skipEverythingButNewLine).toEqual("function");
  expect(typeof sharedUtil.skipInlineComment).toEqual("function");
  expect(typeof sharedUtil.skipTrailingComment).toEqual("function");
  expect(typeof sharedUtil.skipNewline).toEqual("function");
  expect(typeof sharedUtil.hasNewline).toEqual("function");
  expect(typeof sharedUtil.hasNewlineInRange).toEqual("function");
  expect(typeof sharedUtil.hasSpaces).toEqual("function");
  expect(typeof sharedUtil.isNextLineEmpty).toEqual("function");
  expect(typeof sharedUtil.isNextLineEmptyAfterIndex).toEqual("function");
  expect(typeof sharedUtil.isPreviousLineEmpty).toEqual("function");
  expect(typeof sharedUtil.getNextNonSpaceNonCommentCharacterIndex).toEqual(
    "function"
  );
  expect(typeof sharedUtil.makeString).toEqual("function");
});

test("sharedUtil.getMaxContinuousCount", () => {
  const { getMaxContinuousCount } = sharedUtil;

  expect(getMaxContinuousCount("|---|--|-|--|---|", "-")).toEqual(3);
  expect(getMaxContinuousCount("|...|", ".")).toEqual(3);

  const fixture = [
    "([a-f])([a-f])",
    "[a-f][a-f][a-f]",
    "a-fa-fa-fa-f",
    "bbbbbbbbbbbbbbbbbb", // neither `a-f` `[a-f]` `([a-f])` should matches `b`
  ].join("");
  expect(getMaxContinuousCount(fixture, "([a-f])")).toEqual(2);
  expect(getMaxContinuousCount(fixture, "[a-f]")).toEqual(3);
  expect(getMaxContinuousCount(fixture, "a-f")).toEqual(4);
  expect(getMaxContinuousCount(fixture, "([a\\-f])")).toEqual(0);
  expect(getMaxContinuousCount(fixture, "[a\\-f]")).toEqual(0);
  expect(getMaxContinuousCount(fixture, "a\\-f")).toEqual(0);
});

test("sharedUtil.getStringWidth", () => {
  const { getStringWidth } = sharedUtil;

  // From https://github.com/sindresorhus/string-width/blob/master/test.js
  expect(getStringWidth("abcde")).toBe(5);
  expect(getStringWidth("古池や")).toBe(6);
  expect(getStringWidth("あいうabc")).toBe(9);
  expect(getStringWidth("ノード.js")).toBe(9);
  expect(getStringWidth("你好")).toBe(4);
  expect(getStringWidth("안녕하세요")).toBe(10);
  expect(getStringWidth("A\uD83C\uDE00BC")).toBe(5);
  expect(getStringWidth("\u001B[31m\u001B[39m")).toBe(0);
  expect(
    getStringWidth("\u001B]8;;https://github.com\u0007Click\u001B]8;;\u0007")
  ).toBe(5);
  expect(getStringWidth("\u{231A}")).toBe(2);
  expect(getStringWidth("\u{2194}\u{FE0F}")).toBe(2);
  expect(getStringWidth("\u{1F469}")).toBe(2);
  expect(getStringWidth("\u{1F469}\u{1F3FF}")).toBe(2);
  expect(getStringWidth(String.fromCharCode(0))).toBe(0);
  expect(getStringWidth(String.fromCharCode(31))).toBe(0);
  // expect(getStringWidth(String.fromCharCode(127))).toBe(0); // Different with `string-width`
  expect(getStringWidth(String.fromCharCode(134))).toBe(0);
  expect(getStringWidth(String.fromCharCode(159))).toBe(0);
  expect(getStringWidth("\u001B")).toBe(0);
  // expect(getStringWidth("x\u0300"), 1); // Different with `string-width`
});

test("sharedUtil.getAlignmentSize", () => {
  const { getAlignmentSize } = sharedUtil;
  expect(getAlignmentSize("   ")).toBe(3);
  expect(getAlignmentSize("   ", /* tabWidth */ 2, /* startIndex */ 2)).toBe(1);
  expect(getAlignmentSize("\t\t", /* tabWidth */ 2)).toBe(4);
  expect(getAlignmentSize("\t\t", /* tabWidth */ 3)).toBe(6);
  expect(getAlignmentSize("\t\t", /* tabWidth */ 3, /* startIndex */ 1)).toBe(
    3
  );
});

test("sharedUtil.getIndentSize", () => {
  const { getIndentSize } = sharedUtil;
  expect(getIndentSize("\n   a")).toBe(3);
  expect(getIndentSize("\n   a", /* tabWidth */ 2)).toBe(3);
  expect(getIndentSize("\n\t\ta", /* tabWidth */ 2)).toBe(4);
  expect(getIndentSize("\n\t\ta", /* tabWidth */ 3)).toBe(6);
  expect(getIndentSize("\n\t\n\t\t", /* tabWidth */ 2)).toBe(4);
  expect(getIndentSize("\n \n  ", /* tabWidth */ 2)).toBe(2);
  expect(getIndentSize("   \n\t\t\n", /* tabWidth */ 2)).toBe(0);
});

test("sharedUtil.makeString", () => {
  const { makeString } = sharedUtil;
  const DOUBLE_QUOTE = '"';
  const SINGLE_QUOTE = "'";

  expect(makeString("a", DOUBLE_QUOTE)).toBe(`${DOUBLE_QUOTE}a${DOUBLE_QUOTE}`);
  expect(makeString("a", SINGLE_QUOTE)).toBe(`${SINGLE_QUOTE}a${SINGLE_QUOTE}`);
  expect(makeString(`a${DOUBLE_QUOTE}`, DOUBLE_QUOTE)).toBe(
    `${DOUBLE_QUOTE}a\\${DOUBLE_QUOTE}${DOUBLE_QUOTE}`
  );
  expect(makeString(`a${DOUBLE_QUOTE}`, SINGLE_QUOTE)).toBe(
    `${SINGLE_QUOTE}a${DOUBLE_QUOTE}${SINGLE_QUOTE}`
  );
  expect(
    makeString("\\a", SINGLE_QUOTE, /* unescapeUnnecessaryEscapes */ true)
  ).toBe(`${SINGLE_QUOTE}a${SINGLE_QUOTE}`);
});
<|endoftext|>


<commit_before>import redis from 'redis';
import logger from '../../logger';

const DEFAULT_REDIS_TTL = 30 * 1000; // 30 seconds

function debug() {
  logger.debug.apply(logger, ['RedisCacheAdapter', ...arguments]);
}

export class RedisCacheAdapter {

  constructor(ctx) {
    this.client = redis.createClient(ctx);
    this.p = Promise.resolve();
  }

  get(key) {
    debug('get', key);
    this.p = this.p.then(() => {
      return new Promise((resolve, _) => {
        this.client.get(key, function(err, res) {
          debug('-> get', key, res);
          if(!res) {
            return resolve(null);
          }
          resolve(JSON.parse(res));
        });
      });
    });
    return this.p;
  }

  put(key, value, ttl) {
    value = JSON.stringify(value);
    debug('put', key, value, ttl);
    this.p = this.p.then(() => {
      return new Promise((resolve, _) => {
        if (ttl) {
          this.client.psetex(key, ttl, value, function(err, res) {
            resolve();
          });
        } else {
          this.client.set(key, value, function(err, res) {
            resolve();
          });
        }
      });
    });
    return this.p;
  }

  del(key) {
    debug('del', key);
    this.p = this.p.then(() => {
      return new Promise((resolve, _) => {
        this.client.del(key, function(err, res) {
          resolve();
        });
      });
    });
    return this.p;
  }

  clear() {
    debug('clear');
    this.p = this.p.then(() => {
      return new Promise((resolve, _) => {
        this.client.flushall(function(err, res) {
          resolve();
        });
      });
    });
    return this.p;
  }
}

export default RedisCacheAdapter;
<commit_msg>RedisCacheAdapter: add some additional checks and defaults (#2991)<commit_after>import redis from 'redis';
import logger from '../../logger';

const DEFAULT_REDIS_TTL = 30 * 1000; // 30 seconds in milliseconds

function debug() {
  logger.debug.apply(logger, ['RedisCacheAdapter', ...arguments]);
}

export class RedisCacheAdapter {

  constructor(ctx) {
    this.client = redis.createClient(ctx);
    this.p = Promise.resolve();
  }

  get(key) {
    debug('get', key);
    this.p = this.p.then(() => {
      return new Promise((resolve, _) => {
        this.client.get(key, function(err, res) {
          debug('-> get', key, res);
          if(!res) {
            return resolve(null);
          }
          resolve(JSON.parse(res));
        });
      });
    });
    return this.p;
  }

  put(key, value, ttl = DEFAULT_REDIS_TTL) {
    value = JSON.stringify(value);
    debug('put', key, value, ttl);
    if (ttl === 0) {
      return this.p; // ttl of zero is a logical no-op, but redis cannot set expire time of zero
    }
    if (ttl < 0 || isNaN(ttl)) {
      ttl = DEFAULT_REDIS_TTL;
    }
    this.p = this.p.then(() => {
      return new Promise((resolve, _) => {
        if (ttl === Infinity) {
          this.client.set(key, value, function(err, res) {
            resolve();
          });
        } else {
          this.client.psetex(key, ttl, value, function(err, res) {
            resolve();
          });
        }
      });
    });
    return this.p;
  }

  del(key) {
    debug('del', key);
    this.p = this.p.then(() => {
      return new Promise((resolve, _) => {
        this.client.del(key, function(err, res) {
          resolve();
        });
      });
    });
    return this.p;
  }

  clear() {
    debug('clear');
    this.p = this.p.then(() => {
      return new Promise((resolve, _) => {
        this.client.flushall(function(err, res) {
          resolve();
        });
      });
    });
    return this.p;
  }
}

export default RedisCacheAdapter;
<|endoftext|>


<commit_before>var tape = require("tape"),
    jsdom = require("./jsdom"),
    d3 = require("d3-selection"),
    d3_transition = require("d3-transition"),
    d3_graphviz = require("../");

tape("graphviz.renderDot() generates a correct SVG from graphviz DOT with graph tooltip.", function(test) {
    var window = global.window = jsdom('

');
    var document = global.document = window.document;
    var graphviz = d3_graphviz.graphviz("#graph")
        .on('initEnd', startTest);

    svgDoc = `<svg width="8pt" height="8pt" viewBox="0.00 0.00 8.00 8.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 4)">
<title>%0</title>
<g id="a_graph0">
<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-4 4,-4 4,4 -4,4"></polygon>

</g>
</g>
</svg>`;

    function startTest() {
        graphviz
            .tweenShapes(false)
            .zoom(false)
            .renderDot('digraph {graph [tooltip="G"]}');

        test.equal(d3.select('div').html(), svgDoc, "SVG after initial rendering");

        test.end();
    }
});

tape("graphviz.transition().renderDot() generates a correct SVG from graphviz DOT with graph tooltip.", function(test) {
    var window = global.window = jsdom('

');
    var document = global.document = window.document;
    var graphviz = d3_graphviz.graphviz("#graph")
        .on('initEnd', startTest);

    svgDoc = `<svg width="8pt" height="8pt" viewBox="0.00 0.00 8.00 8.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 4)">
<title>%0</title>
<g id="a_graph0">
<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-4 4,-4 4,4 -4,4"></polygon>

</g>
</g>
</svg>`;

    function startTest() {
        var transition = d3_transition.transition().duration(0);
        graphviz
            .tweenShapes(false)
            .tweenPaths(false)
            .zoom(false)
//            .fade(false)
            .renderDot('digraph {graph [tooltip="G"]}');

        test.equal(d3.select('div').html(), svgDoc, "SVG after initial rendering");

        graphviz
            .tweenShapes(false)
            .tweenPaths(false)
            .zoom(false)
//            .fade(false)
            .transition(transition)
            .renderDot('digraph {graph [tooltip="G"]}');

        transition
            .transition()
            .on("end", function() {
                test.equal(d3.select('div').html(), svgDoc, "SVG after transition");
                test.end();
            });
    }

});
<commit_msg>Adapt tooltip-test.js data to Graphviz version 2.42.2<commit_after>var tape = require("tape"),
    jsdom = require("./jsdom"),
    d3 = require("d3-selection"),
    d3_transition = require("d3-transition"),
    d3_graphviz = require("../");

tape("graphviz.renderDot() generates a correct SVG from graphviz DOT with graph tooltip.", function(test) {
    var window = global.window = jsdom('

');
    var document = global.document = window.document;
    var graphviz = d3_graphviz.graphviz("#graph")
        .on('initEnd', startTest);

    svgDoc = `<svg width="8pt" height="8pt" viewBox="0.00 0.00 8.00 8.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 4)">
<title>%200176</title>
<g id="a_graph0">
<polygon fill="white" stroke="transparent" points="-4,4 -4,-4 4,-4 4,4 -4,4"></polygon>

</g>
</g>
</svg>`;

    function startTest() {
        graphviz
            .tweenShapes(false)
            .zoom(false)
            .renderDot('digraph {graph [tooltip="G"]}');

        test.equal(d3.select('div').html(), svgDoc, "SVG after initial rendering");

        test.end();
    }
});

tape("graphviz.transition().renderDot() generates a correct SVG from graphviz DOT with graph tooltip.", function(test) {
    var window = global.window = jsdom('

');
    var document = global.document = window.document;
    var graphviz = d3_graphviz.graphviz("#graph")
        .on('initEnd', startTest);

    svgDoc = `<svg width="8pt" height="8pt" viewBox="0.00 0.00 8.00 8.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 4)">
<title>%200176</title>
<g id="a_graph0">
<polygon fill="white" stroke="transparent" points="-4,4 -4,-4 4,-4 4,4 -4,4"></polygon>

</g>
</g>
</svg>`;

    function startTest() {
        var transition = d3_transition.transition().duration(0);
        graphviz
            .tweenShapes(false)
            .tweenPaths(false)
            .zoom(false)
//            .fade(false)
            .renderDot('digraph {graph [tooltip="G"]}');

        test.equal(d3.select('div').html(), svgDoc, "SVG after initial rendering");

        graphviz
            .tweenShapes(false)
            .tweenPaths(false)
            .zoom(false)
//            .fade(false)
            .transition(transition)
            .renderDot('digraph {graph [tooltip="G"]}');

        transition
            .transition()
            .on("end", function() {
                test.equal(d3.select('div').html(), svgDoc, "SVG after transition");
                test.end();
            });
    }

});
<|endoftext|>