<commit_before>/* eslint vars-on-top: 0 */
/* globals $ */
var popoverLocalInit = function() {
  var options = {
    html: true,
    placement: function(context, source) {
      var position = $(source).offset();
      $(context).addClass($(source).attr('data-popover-class'));
      if ($(source).hasClass('a-js-popoverBig')) {
        return 'bottom';
      }
      if (position.left < 125) {
        return 'right';
      }
      if (position.left > ($(document).width() - $(source).width() - 125)) {
        return 'left';
      }
      return 'bottom';
    },
    content: function() {
      if ($(this).attr('data-popover-content')) {
        return $('#' + $(this).data('popover-content')).html();
      }
      return false;
    },
    template: '

'
  };

  $('[data-toggle="popover"]').popover(options);

  $('.a-js-togglePopoverIcons').each(function() {
    // $(this).find('i').eq(1).hide();
    $(this).find('.a-js-popoverIconExpanded').hide();
  });

  $('.a-js-popoverIconExpanded').on('click', function() {
    $('.a-js-popoverIconExpanded').hide();
    $('.a-js-popoverIconInitial').show();
    // $(this).hide();
    // $('.a-js-popoverIconInitial').show();
  });
  $('.a-js-popoverIconInitial').on('click', function() {
    $(this).hide();
    $(this).parent().find('.a-js-popoverIconExpanded').show();
  });
};

var forceFocusTriggerElement;
var popoverGlobalInit = function() {
  $('[data-toggle="dropdown"]').on('click', function(e) {
    if (window.innerWidth < 992) {
      $('.a-dropdown-overflow-menu-right').removeClass('dropdown-menu-right');
    } else {
      $('.a-dropdown-overflow-menu-right').addClass('dropdown-menu-right');
    }
  });

  $('body').on('show.bs.popover', '[data-toggle="popover"].a-js-tabable-popover', function(e) {
    var triggerElement = this;
    $(triggerElement).closest('.a-modal').scrollTop(0);
  });

  $('body').on('shown.bs.popover', '[data-toggle="popover"].a-js-tabable-popover', function(e) {
    var triggerElement = this;
    setTimeout(function() {
      $(triggerElement).after($($(triggerElement).data('bs.popover').tip));
      $(triggerElement).closest('.a-modal').one('scroll', function() {
        $('[data-toggle="popover"]').popover('hide');
      });
    }, 0);
  });

  $('body').on('shown.bs.popover', '[data-toggle="popover"].a-js-popover-forceFocus', function(e) {
    $('body').append($('<button class="sr-only a-js-popoverTrick">ignoreme</button>'));
    forceFocusTriggerElement = this;
    console.log('triggered by', forceFocusTriggerElement);

    /* Keyboard trap start */

    // Find popover-warning
    var popoverWarning = $('.popover-warning');
    console.log('popover', popoverWarning);

    // Find all focusable children
    var focusableElementsString = 'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex="0"], [contenteditable]';
    // var focusableElements = popover.querySelectorAll(focusableElementsString);
    var focusableElements = $(popoverWarning).find(focusableElementsString);
    console.log('focusable', focusableElements);

    // If there are focusable elements, make keyboardtrap
    if (focusableElements.length) {
      // Convert NodeList to Array
      focusableElements = Array.prototype.slice.call(focusableElements);

      var firstTabStop = focusableElements[0];
      var lastTabStop = focusableElements[focusableElements.length - 1];

      // Focus first child
      firstTabStop.focus();

      $(popoverWarning).keydown(function(key) {
        console.log('keydown', key.keyCode);
        if (key.keyCode === 9) {
          // Shift + Tab
          if (key.shiftKey) {
            if (document.activeElement === firstTabStop) {
              key.preventDefault();
              lastTabStop.focus();
            }
          // TAB
          } else {
            if (document.activeElement === lastTabStop) { // eslint-disable-line
              key.preventDefault();
              firstTabStop.focus();
            }
          }
        } else if (key.keyCode === 13) {
          // Enter
          $('[data-toggle="popover"]').popover('hide');
        } else if (key.keyCode === 27) {
          // Escape
          $('[data-toggle="popover"]').popover('hide');
        }
      });
    }

    /* Keyboard trap end */

    $(forceFocusTriggerElement).one('blur', function() {
      var that = this;
      if (forceFocusTriggerElement) {
        console.log('focus thingy', $($(this).data('bs.popover').tip).find('button,input,a,textarea').filter(':visible:first'));
        $($(this).data('bs.popover').tip).find('button,input,a,textarea').filter(':visible:first').focus();
      }
    });
  });

  $('body').on('hidden.bs.popover', '[data-toggle="popover"].a-js-popover-forceFocus', function(e) {
    $('body').find('.a-js-popoverTrick').remove();
  });

  // hides popover when the cehckbutton is checked
  $('body').on('focus', '[data-toggle="popover"].sr-only', function(e) {
    if ($(this).is(':checked')) {
      $(this).popover('hide');
    } else {
      $(this).popover('show');
    }
  });

  // show/hide popover on checkbutton change
  $('body').on('change', 'a-switch[data-toggle=popover]', function() {
    if ($(this).is(':checked')) {
      $(this).popover('hide');
    } else {
      $(this).popover('show');
    }
  });

  // Hide all existing popovers when opening a new popover
  $('body').on('click', '[data-toggle="popover"]', function(e) {
    $('[data-toggle="popover"]').not(this).popover('hide');
  });

  // Hide all existing popovers when focusing a new element
  // which is not the open popover or any of its content
  $('body').on('blur', '[data-toggle="popover"], .popover *', function(e) {
    setTimeout(function() {
      var $focused = $(':focus');
      if ((($focused.length !== 0 || forceFocusTriggerElement)
        && !$focused.hasClass('popover')
        && !$focused.parents('.popover').length >= 1) || $focused.hasClass('a-js-popoverTrick')) {
        if (forceFocusTriggerElement) {
          $(forceFocusTriggerElement).focus();
          forceFocusTriggerElement = false;
        }
        // disable blur when in modal to allow use of non-original scrollbar
        if ($('.modal.show').length > 0) {
          $('.popover-big[data-toggle="popover"]').popover('hide');
        }
      }
    }, 0);
  });

  // Hide popovers when clicking on something else than the trigger element
  // and the popover itself
  $('body').on('click', function(e) {
    if ($(e.target).data('toggle') !== 'popover' && $(e.target).parents('[data-toggle="popover"]').length === 0 && $(e.target).parents('.popover.show').length === 0) {
      $('[data-toggle="popover"]').popover('hide');
      forceFocusTriggerElement = false;
      $(this).parent().find('.a-js-popoverIconInitial').show();
      $(this).parent().find('.a-js-popoverIconExpanded').hide();
    }
  });

  function resetTranslate() {
    $('.popover-big').attr('style', $('.popover-big').attr('style').replace(/translateX\(.*?\)/, 'translateX(0px)'));
  }

  function adjustBig() {
    var modalHeight;
    var padding;
    if ($('.popover-big').length > 0) {
      if ($('.modal.show').length > 0) {
        // Add padding to make sure modal is big enough to contain popover
        modalHeight = $('.modal-dialog').height() + $('.modalPage').height();
        padding = ($('.popover').offset().top + $('.modal').scrollTop() + $('.popover').height() + 5) - modalHeight;
        $('.modalPage').css('padding-bottom', padding + 'px');
        // tranlate is somehow added by Bootstrap later when in modal??
        setTimeout(resetTranslate, 0);
      } else {
        resetTranslate();
      }
    }
  }

  $('body').on('shown.bs.popover', '.a-js-persistPopover', function() {
    $('.arrow').html('');
    $('html, body').animate({
      scrollTop: $('.a-js-persistPopover').offset().top - 50
    }, 250);

    adjustBig();
  });

  // clean up modal page fix
  $('body').on('hidden.bs.popover', 'a-js-persistPopover', function(e) {
    $('.modalPage').css('padding-bottom', '0px');
  });

  $(window).scroll(adjustBig);
  $('.modal').scroll(adjustBig);
  $(window).resize(adjustBig);
};
<commit_msg>Implemented keyboard trap on popovers with focusable elements and a-js-popover-forceFocus class.<commit_after>/* eslint vars-on-top: 0 */
/* globals $ */
var popoverLocalInit = function() {
  var options = {
    html: true,
    placement: function(context, source) {
      var position = $(source).offset();
      $(context).addClass($(source).attr('data-popover-class'));
      if ($(source).hasClass('a-js-popoverBig')) {
        return 'bottom';
      }
      if (position.left < 125) {
        return 'right';
      }
      if (position.left > ($(document).width() - $(source).width() - 125)) {
        return 'left';
      }
      return 'bottom';
    },
    content: function() {
      if ($(this).attr('data-popover-content')) {
        return $('#' + $(this).data('popover-content')).html();
      }
      return false;
    },
    template: '

'
  };

  $('[data-toggle="popover"]').popover(options);

  $('.a-js-togglePopoverIcons').each(function() {
    // $(this).find('i').eq(1).hide();
    $(this).find('.a-js-popoverIconExpanded').hide();
  });

  $('.a-js-popoverIconExpanded').on('click', function() {
    $('.a-js-popoverIconExpanded').hide();
    $('.a-js-popoverIconInitial').show();
    // $(this).hide();
    // $('.a-js-popoverIconInitial').show();
  });
  $('.a-js-popoverIconInitial').on('click', function() {
    $(this).hide();
    $(this).parent().find('.a-js-popoverIconExpanded').show();
  });
};

var forceFocusTriggerElement;
var popoverGlobalInit = function() {
  $('[data-toggle="dropdown"]').on('click', function(e) {
    if (window.innerWidth < 992) {
      $('.a-dropdown-overflow-menu-right').removeClass('dropdown-menu-right');
    } else {
      $('.a-dropdown-overflow-menu-right').addClass('dropdown-menu-right');
    }
  });

  $('body').on('show.bs.popover', '[data-toggle="popover"].a-js-tabable-popover', function(e) {
    var triggerElement = this;
    $(triggerElement).closest('.a-modal').scrollTop(0);
  });

  $('body').on('shown.bs.popover', '[data-toggle="popover"].a-js-tabable-popover', function(e) {
    var triggerElement = this;
    setTimeout(function() {
      $(triggerElement).after($($(triggerElement).data('bs.popover').tip));
      $(triggerElement).closest('.a-modal').one('scroll', function() {
        $('[data-toggle="popover"]').popover('hide');
      });
    }, 0);
  });

  $('body').on('shown.bs.popover', '[data-toggle="popover"].a-js-popover-forceFocus', function(e) {
    $('body').append($('<button class="sr-only a-js-popoverTrick">ignoreme</button>'));
    forceFocusTriggerElement = this;

    /*
      This is a keyboard trap code
      which prevents the user from exiting the "popover" dialog with tabbing.
      ESC will close the "popover" dialog.
    */

    // Find popover-warning
    var popoverWarning = $('.popover-warning');

    // Find all focusable children
    var focusableElementsString = 'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex="0"], [contenteditable]';
    // var focusableElements = popover.querySelectorAll(focusableElementsString);
    var focusableElements = $(popoverWarning).find(focusableElementsString);

    // If there are focusable elements, make keyboardtrap
    if (focusableElements.length) {
      // Convert NodeList to Array
      focusableElements = Array.prototype.slice.call(focusableElements);

      var firstTabStop = focusableElements[0];
      var lastTabStop = focusableElements[focusableElements.length - 1];

      // Focus first child
      // and scroll to current position for preventscroll unsupported browsers.
      var position = $(window).scrollTop();
      firstTabStop.focus({ preventScroll: true });
      $(window).scrollTop(position);

      $(popoverWarning).keydown(function(key) {
        if (key.keyCode === 9) {
          // Shift + Tab
          if (key.shiftKey) {
            if (document.activeElement === firstTabStop) {
              key.preventDefault();
              lastTabStop.focus();
            }
          // TAB
          } else {
            if (document.activeElement === lastTabStop) { // eslint-disable-line
              key.preventDefault();
              firstTabStop.focus();
            }
          }
        } else if (key.keyCode === 27) {
          // Escape
          $('[data-toggle="popover"]').popover('hide');
          key.preventDefault();
          $(forceFocusTriggerElement).focus();
        }
      });
    }
  });

  $('body').on('hidden.bs.popover', '[data-toggle="popover"].a-js-popover-forceFocus', function(e) {
    $('body').find('.a-js-popoverTrick').remove();
  });

  // hides popover when the checkbutton is checked
  $('body').on('focus', '[data-toggle="popover"].sr-only', function(e) {
    if ($(this).is(':checked')) {
      $(this).popover('hide');
    } else {
      $(this).popover('show');
    }
  });

  // show/hide popover on checkbutton change
  $('body').on('change', 'a-switch[data-toggle=popover]', function() {
    if ($(this).is(':checked')) {
      $(this).popover('hide');
    } else {
      $(this).popover('show');
    }
  });

  // Hide all existing popovers when opening a new popover
  $('body').on('click', '[data-toggle="popover"]', function(e) {
    $('[data-toggle="popover"]').not(this).popover('hide');
  });

  // Hide all existing popovers when focusing a new element
  // which is not the open popover or any of its content
  $('body').on('blur', '[data-toggle="popover"], .popover *', function(e) {
    setTimeout(function() {
      var $focused = $(':focus');
      if ((($focused.length !== 0 || forceFocusTriggerElement) && !$focused.hasClass('popover') && $focused.parents('.popover').length === 0) || $focused.hasClass('a-js-popoverTrick')) {
        // disable blur when in modal to allow use of non-original scrollbar
        if ($('.modal.show').length > 0) {
          $('.popover-big[data-toggle="popover"]').popover('hide');
        }
      }
    }, 0);
  });

  // Hide popovers when clicking on something else than the trigger element
  // and the popover itself
  $('body').on('click', function(e) {
    if ($(e.target).data('toggle') !== 'popover' && $(e.target).parents('[data-toggle="popover"]').length === 0 && $(e.target).parents('.popover.show').length === 0) {
      $('[data-toggle="popover"]').popover('hide');
      forceFocusTriggerElement = false;
      $(this).parent().find('.a-js-popoverIconInitial').show();
      $(this).parent().find('.a-js-popoverIconExpanded').hide();
    }
  });

  function resetTranslate() {
    $('.popover-big').attr('style', $('.popover-big').attr('style').replace(/translateX\(.*?\)/, 'translateX(0px)'));
  }

  function adjustBig() {
    var modalHeight;
    var padding;
    if ($('.popover-big').length > 0) {
      if ($('.modal.show').length > 0) {
        // Add padding to make sure modal is big enough to contain popover
        modalHeight = $('.modal-dialog').height() + $('.modalPage').height();
        padding = ($('.popover').offset().top + $('.modal').scrollTop() + $('.popover').height() + 5) - modalHeight;
        $('.modalPage').css('padding-bottom', padding + 'px');
        // tranlate is somehow added by Bootstrap later when in modal??
        setTimeout(resetTranslate, 0);
      } else {
        resetTranslate();
      }
    }
  }

  $('body').on('shown.bs.popover', '.a-js-persistPopover', function() {
    $('.arrow').html('');
    $('html, body').animate({
      scrollTop: $('.a-js-persistPopover').offset().top - 50
    }, 250);

    adjustBig();
  });

  // clean up modal page fix
  $('body').on('hidden.bs.popover', 'a-js-persistPopover', function(e) {
    $('.modalPage').css('padding-bottom', '0px');
  });

  $(window).scroll(adjustBig);
  $('.modal').scroll(adjustBig);
  $(window).resize(adjustBig);
};
<|endoftext|>


<commit_before>'use strict';

const expect = require('chai').expect;
const reporter = require('./stock-table');

let resultFixture = [
  {
    buCode: 123,
    stock: {
      availableStock: 999,
      inStockProbabilityCode: 'HIGH',
    },
  },
];

describe('stock reporter table', function() {
  it('shows the output as a table', function() {
    let data = {
      countryCode: 'de',
      productId: 'S49903093',
      results: resultFixture,
    };
    reporter.show(data);
  });
});
<commit_msg>test: stock-table reporter test actually tests something<commit_after>'use strict';

const expect = require('chai').expect;
const reporter = require('./stock-table');

let resultFixture = [
  {
    buCode: 123,
    stock: {
      availableStock: 999,
      inStockProbabilityCode: 'HIGH',
    },
  },
];

describe('stock reporter table', function() {
  it('shows the output as a table', function() {
    let data = {
      countryCode: 'de',
      productId: 'S49903093',
      results: resultFixture,
    };
    let report = reporter.show(data);
    expect(report).to.match(/S49903093/);
    expect(report).to.match(/999/);
    expect(report).to.match(/123/);
  });
});
<|endoftext|>


<commit_before>//= require jquery
//= require support/sinon
//= require support/chai
//= require chai-jquery
//= require magic_lamp

//= require support/helper_functions

// require support/sinon-chai
// require_self

jQuery.fx.off = true;

MagicLamp.preload();

// var spies;
// var stubs;
// window.spyOn = function(object, method) {
//   var spy = sinon.spy(object, method);
//   spies.push(spy);
//   return spy;
// };

// window.stub = function(object, method, retVal) {
//   var stub = sinon.stub(object, method).returns(retVal);
//   stubs.push(stub);
//   return stub;
// };

// beforeEach(function() {
//   spies = [];
//   stubs = [];
// });

// afterEach(function() {
//   MagicLamp.clean();

//   _(spies).each(function(spy) {
//     spy.restore();
//   });

//   _(stubs).each(function(stub) {
//     stub.restore();
//   });
// });

window.expect = chai.expect;
<commit_msg>change js spec helper order (CCI experiment)<commit_after>//= require jquery
//= require support/sinon
//= require support/chai
//= require chai-jquery
//= require magic_lamp

//= require support/helper_functions

// require support/sinon-chai
// require_self

jQuery.fx.off = true;
window.expect = chai.expect;

MagicLamp.preload();

// var spies;
// var stubs;
// window.spyOn = function(object, method) {
//   var spy = sinon.spy(object, method);
//   spies.push(spy);
//   return spy;
// };

// window.stub = function(object, method, retVal) {
//   var stub = sinon.stub(object, method).returns(retVal);
//   stubs.push(stub);
//   return stub;
// };

// beforeEach(function() {
//   spies = [];
//   stubs = [];
// });

// afterEach(function() {
//   MagicLamp.clean();

//   _(spies).each(function(spy) {
//     spy.restore();
//   });

//   _(stubs).each(function(stub) {
//     stub.restore();
//   });
// });

<|endoftext|>


<commit_before>// Copyright 2015, EMC, Inc.
/* jshint node:true */

"use strict";

var uuid = require("node-uuid");

describe("Message Cache Job", function () {
    var base = require('./base-spec');
    var Errors;
    var job;

    base.before(function (context) {
        helper.setupInjector([
            helper.require('/spec/mocks/logger.js'),
            helper.requireGlob('/lib/services/*.js'),
            helper.require('/lib/jobs/base-job.js'),
            helper.require('/lib/jobs/message-cache-job.js')
        ]);

        var configuration = helper.injector.get('Services.Configuration');
        sinon.stub(configuration, 'get').withArgs('pollerCacheSize').returns(10);

        Errors = helper.injector.get('Errors');
        context.Jobclass = helper.injector.get('Job.Message.Cache');
    });

    beforeEach("Message Cache Job beforeEach", function() {
        this.sandbox = sinon.sandbox.create();
        job = new this.Jobclass({}, { graphId: uuid.v4() }, uuid.v4());
    });

    afterEach("Message Cache Job afterEach", function() {
        this.sandbox.restore();
    });

    describe("Base", function () {
        base.examples();
    });

    describe("cache", function() {
        it("should return false if an id is not in the cache", function() {
            job.cache = {};
            expect(job.cacheHas('testid')).to.equal(false);
        });

        it("should return true if an id is in the cache", function() {
            job.cache = { testid: [] };
            expect(job.cacheHas('testid')).to.equal(true);
        });

        it("should get cache entries by id", function() {
            var cache = { 'testid': [{}, {}] };
            job.cache = cache;
            expect(job.cacheGet('testid')).to.equal(cache.testid);
        });

        it("should set a cache entry", function() {
            job.cacheSet('testid', { testkey: 'testvalue' });
            expect(job.cacheGet('testid')[0]).to.have.property('testkey').equals('testvalue');
        });

        it("should not set a cache entry for empty data", function() {
            job.cacheSet('testid', null);
            expect(job.cacheGet('testid')).to.be.empty;
        });

        it("should limit the cache size", function() {
            job.maxCacheSize = 1;
            job.cacheSet('testid', { k: 1 });
            expect(job.cacheGet('testid')).to.have.length(1);
            expect(job.cacheGet('testid')[0]).to.have.property('k').that.equals(1);
            job.cacheSet('testid', { k: 2 });
            expect(job.cacheGet('testid')).to.have.length(1);
            expect(job.cacheGet('testid')[0]).to.have.property('k').that.equals(2);
        });

        it("should add timestamps to cache entries", function() {
            job.cacheSet('testid', { testkey: 'testvalue' });
            expect(job.cacheGet('testid')[0]).to.have.property('timestamp');
            expect(new Date(job.cacheGet('testid')[0].timestamp)).to.be.a('date');
        });
    });

    describe("subscription callbacks", function() {
        var baseJob;

        before("Message Cache subscription callbacks before", function() {
            baseJob = helper.injector.get('Job.Base');
            sinon.stub(baseJob.prototype, '_subscribeIpmiCommandResult');
            sinon.stub(baseJob.prototype, '_subscribeSnmpCommandResult');
            sinon.stub(baseJob.prototype, '_subscribeRequestPollerCache');
            sinon.stub(baseJob.prototype, '_subscribeRedfishCommandResult');
            sinon.stub(baseJob.prototype, '_subscribeMetricResult');
        });

        beforeEach("Message Cache subscription callbacks beforeEach", function() {
            baseJob.prototype._subscribeIpmiCommandResult.reset();
            baseJob.prototype._subscribeSnmpCommandResult.reset();
            baseJob.prototype._subscribeRequestPollerCache.reset();
        });

        after("Message Cache subscription callbacks after", function() {
            baseJob.prototype._subscribeIpmiCommandResult.restore();
            baseJob.prototype._subscribeSnmpCommandResult.restore();
            baseJob.prototype._subscribeRequestPollerCache.restore();
        });

        it("should set subscription callbacks for ipmi results", function() {
            this.sandbox.stub(job, 'createSetIpmiCommandResultCallback').returns('fn return stub');
            job._run();
            expect(job._subscribeIpmiCommandResult.callCount).to.equal(5);
            _.forEach(['sdr', 'selInformation', 'sel', 'chassis', 'driveHealth'],
            function(command) {
                expect(job._subscribeIpmiCommandResult).to.have.been.calledWith(
                    job.routingKey,
                    command,
                    'fn return stub'
                );
            });
        });

        it("should set subscription callbacks for snmp results", function() {
            job._run();
            expect(job._subscribeSnmpCommandResult).to.have.been.calledOnce;
            expect(job._subscribeSnmpCommandResult)
                .to.have.been.calledWith(job.routingKey, job.setSnmpCommandResultCallback);
        });

        it("should set subscription callbacks for poller cache requests", function() {
            job._run();
            expect(job._subscribeRequestPollerCache).to.have.been.calledOnce;
            expect(job._subscribeRequestPollerCache)
                .to.have.been.calledWith(job.requestPollerCacheCallback);
        });

        it("should work for setting cache data on ipmi results", function() {
            _.forEach(['sdr', 'selInformation', 'sel', 'chassis'], function(command) {
                var testdata = { test: 'data' };
                var cb = job.createSetIpmiCommandResultCallback(command);
                cb.call(job, testdata);
                expect(job.cacheGet('unknown.ipmi.' + command)).to.have.length(1);
                expect(job.cacheGet('unknown.ipmi.' + command)[0])
                    .to.have.property('test').that.equals('data');
                testdata.workItemId = 'testid.' + command;
                cb.call(job, testdata);
                expect(job.cacheGet('testid.' + command)).to.have.length(1);
                expect(job.cacheGet('testid.' + command)[0])
                    .to.have.property('test').that.equals('data');
            });
        });

        it("should work for setting cache data on snmp results", function() {
            var testdata = { test: 'data' };
            job.setSnmpCommandResultCallback(testdata);
            expect(job.cacheGet('unknown.snmp')).to.have.length(1);
            expect(job.cacheGet('unknown.snmp')[0])
                .to.have.property('test').that.equals('data');

            testdata.workItemId = 'testid';
            job.setSnmpCommandResultCallback(testdata);
            expect(job.cacheGet(testdata.workItemId)).to.have.length(1);
            expect(job.cacheGet(testdata.workItemId)[0])
                .to.have.property('test').that.equals('data');
        });

        it("should work for setting cache data on metric results", function() {
            _.forEach(['test-metric-1', 'test-metric-2', 'test-metric-3'], function(metric) {
                var testdata = { test: 'data' };
                job.setMetricResultCallback(testdata, metric);
                expect(job.cacheGet('unknown.metric.' + metric)).to.have.length(1);
                expect(job.cacheGet('unknown.metric.' + metric)[0])
                    .to.have.property('test').that.equals('data');

                testdata.workItemId = 'testid.' + metric;
                job.setMetricResultCallback(testdata, metric);
                expect(job.cacheGet(testdata.workItemId)).to.have.length(1);
                expect(job.cacheGet(testdata.workItemId)[0])
                    .to.have.property('test').that.equals('data');
            });
        });

        it("should work for poller cache requests", function() {
            job.cacheSet('testid', { test: 'data' });
            return job.requestPollerCacheCallback('testid')
            .then(function(data) {
                expect(data).to.have.length(1);
                expect(data[0]).to.have.property('test').that.equals('data');
            });
        });

        it("should work for poller cache requests for the latest entry", function() {
            job.cacheSet('testid', { test: 'data' });
            job.cacheSet('testid', { test: 'data latest' });
            return job.requestPollerCacheCallback('testid', { latestOnly: true })
            .then(function(data) {
                expect(data).to.have.length(1);
                expect(data[0]).to.have.property('test').that.equals('data latest');
            });
        });

        it("should reject for poller cache requests on non-existant workItems", function() {
            return expect(job.requestPollerCacheCallback('badid'))
                .to.be.rejectedWith(Errors.NotFoundError, /There is no cache record/);
        });
    });
});
<commit_msg>restore stub after MessageCacheJob unit-test finishes<commit_after>// Copyright 2015, EMC, Inc.
/* jshint node:true */

"use strict";

var uuid = require("node-uuid");

describe("Message Cache Job", function () {
    var base = require('./base-spec');
    var Errors;
    var job;
    var sandbox = sinon.sandbox.create();

    base.before(function (context) {
        helper.setupInjector([
            helper.require('/spec/mocks/logger.js'),
            helper.requireGlob('/lib/services/*.js'),
            helper.require('/lib/jobs/base-job.js'),
            helper.require('/lib/jobs/message-cache-job.js')
        ]);

        var configuration = helper.injector.get('Services.Configuration');
        sandbox.stub(configuration, 'get').withArgs('pollerCacheSize').returns(10);

        Errors = helper.injector.get('Errors');
        context.Jobclass = helper.injector.get('Job.Message.Cache');
    });

    before("Message Cache Job before", function() {
        var baseJob = helper.injector.get('Job.Base');
        sandbox.stub(baseJob.prototype, '_subscribeIpmiCommandResult');
        sandbox.stub(baseJob.prototype, '_subscribeSnmpCommandResult');
        sandbox.stub(baseJob.prototype, '_subscribeRequestPollerCache');
        sandbox.stub(baseJob.prototype, '_subscribeRedfishCommandResult');
        sandbox.stub(baseJob.prototype, '_subscribeMetricResult');
    });

    after("Message Cache Job after", function() {
        sandbox.restore();
    });

    beforeEach("Message Cache Job beforeEach", function() {
        job = new this.Jobclass({}, { graphId: uuid.v4() }, uuid.v4());
    });

    afterEach("Message Cache Job afterEach", function() {
        sandbox.reset();
    });

    describe("Base", function () {
        base.examples();
    });

    describe("cache", function() {
        it("should return false if an id is not in the cache", function() {
            job.cache = {};
            expect(job.cacheHas('testid')).to.equal(false);
        });

        it("should return true if an id is in the cache", function() {
            job.cache = { testid: [] };
            expect(job.cacheHas('testid')).to.equal(true);
        });

        it("should get cache entries by id", function() {
            var cache = { 'testid': [{}, {}] };
            job.cache = cache;
            expect(job.cacheGet('testid')).to.equal(cache.testid);
        });

        it("should set a cache entry", function() {
            job.cacheSet('testid', { testkey: 'testvalue' });
            expect(job.cacheGet('testid')[0]).to.have.property('testkey').equals('testvalue');
        });

        it("should not set a cache entry for empty data", function() {
            job.cacheSet('testid', null);
            expect(job.cacheGet('testid')).to.be.empty;
        });

        it("should limit the cache size", function() {
            job.maxCacheSize = 1;
            job.cacheSet('testid', { k: 1 });
            expect(job.cacheGet('testid')).to.have.length(1);
            expect(job.cacheGet('testid')[0]).to.have.property('k').that.equals(1);
            job.cacheSet('testid', { k: 2 });
            expect(job.cacheGet('testid')).to.have.length(1);
            expect(job.cacheGet('testid')[0]).to.have.property('k').that.equals(2);
        });

        it("should add timestamps to cache entries", function() {
            job.cacheSet('testid', { testkey: 'testvalue' });
            expect(job.cacheGet('testid')[0]).to.have.property('timestamp');
            expect(new Date(job.cacheGet('testid')[0].timestamp)).to.be.a('date');
        });
    });

    describe("subscription callbacks", function() {
        it("should set subscription callbacks for ipmi results", function() {
            sandbox.stub(job, 'createSetIpmiCommandResultCallback').returns('fn return stub');
            job._run();
            expect(job._subscribeIpmiCommandResult.callCount).to.equal(5);
            _.forEach(['sdr', 'selInformation', 'sel', 'chassis', 'driveHealth'],
            function(command) {
                expect(job._subscribeIpmiCommandResult).to.have.been.calledWith(
                    job.routingKey,
                    command,
                    'fn return stub'
                );
            });
        });

        it("should set subscription callbacks for snmp results", function() {
            job._run();
            expect(job._subscribeSnmpCommandResult).to.have.been.calledOnce;
            expect(job._subscribeSnmpCommandResult)
                .to.have.been.calledWith(job.routingKey, job.setSnmpCommandResultCallback);
        });

        it("should set subscription callbacks for poller cache requests", function() {
            job._run();
            expect(job._subscribeRequestPollerCache).to.have.been.calledOnce;
            expect(job._subscribeRequestPollerCache)
                .to.have.been.calledWith(job.requestPollerCacheCallback);
        });

        it("should work for setting cache data on ipmi results", function() {
            _.forEach(['sdr', 'selInformation', 'sel', 'chassis'], function(command) {
                var testdata = { test: 'data' };
                var cb = job.createSetIpmiCommandResultCallback(command);
                cb.call(job, testdata);
                expect(job.cacheGet('unknown.ipmi.' + command)).to.have.length(1);
                expect(job.cacheGet('unknown.ipmi.' + command)[0])
                    .to.have.property('test').that.equals('data');
                testdata.workItemId = 'testid.' + command;
                cb.call(job, testdata);
                expect(job.cacheGet('testid.' + command)).to.have.length(1);
                expect(job.cacheGet('testid.' + command)[0])
                    .to.have.property('test').that.equals('data');
            });
        });

        it("should work for setting cache data on snmp results", function() {
            var testdata = { test: 'data' };
            job.setSnmpCommandResultCallback(testdata);
            expect(job.cacheGet('unknown.snmp')).to.have.length(1);
            expect(job.cacheGet('unknown.snmp')[0])
                .to.have.property('test').that.equals('data');

            testdata.workItemId = 'testid';
            job.setSnmpCommandResultCallback(testdata);
            expect(job.cacheGet(testdata.workItemId)).to.have.length(1);
            expect(job.cacheGet(testdata.workItemId)[0])
                .to.have.property('test').that.equals('data');
        });

        it("should work for setting cache data on metric results", function() {
            _.forEach(['test-metric-1', 'test-metric-2', 'test-metric-3'], function(metric) {
                var testdata = { test: 'data' };
                job.setMetricResultCallback(testdata, metric);
                expect(job.cacheGet('unknown.metric.' + metric)).to.have.length(1);
                expect(job.cacheGet('unknown.metric.' + metric)[0])
                    .to.have.property('test').that.equals('data');

                testdata.workItemId = 'testid.' + metric;
                job.setMetricResultCallback(testdata, metric);
                expect(job.cacheGet(testdata.workItemId)).to.have.length(1);
                expect(job.cacheGet(testdata.workItemId)[0])
                    .to.have.property('test').that.equals('data');
            });
        });

        it("should work for poller cache requests", function() {
            job.cacheSet('testid', { test: 'data' });
            return job.requestPollerCacheCallback('testid')
            .then(function(data) {
                expect(data).to.have.length(1);
                expect(data[0]).to.have.property('test').that.equals('data');
            });
        });

        it("should work for poller cache requests for the latest entry", function() {
            job.cacheSet('testid', { test: 'data' });
            job.cacheSet('testid', { test: 'data latest' });
            return job.requestPollerCacheCallback('testid', { latestOnly: true })
            .then(function(data) {
                expect(data).to.have.length(1);
                expect(data[0]).to.have.property('test').that.equals('data latest');
            });
        });

        it("should reject for poller cache requests on non-existant workItems", function() {
            return expect(job.requestPollerCacheCallback('badid'))
                .to.be.rejectedWith(Errors.NotFoundError, /There is no cache record/);
        });
    });
});
<|endoftext|>


<commit_before>'use strict';

/**
 * The main menu
 *
 * @memberof HashBrown.Client.Views.Navigation
 */
class MainMenu extends Crisp.View {
    constructor(params) {
        super(params);

        $('.page--environment__space--menu').html(this.$element);

        this.fetch();
    }

    /**
     * Event: On change language
     *
     * @param {String} newLanguage
     */
    async onChangeLanguage(newLanguage) {
        localStorage.setItem('language', newLanguage);
        HashBrown.Context.language = newLanguage;

        await HashBrown.Helpers.ResourceHelper.reloadResource('content');

        let contentEditor = Crisp.View.get('ContentEditor');

        if(contentEditor) {
            contentEditor.model = null;
            await contentEditor.fetch();
        }

        this.fetch();
    }

    /**
     * Event: Click question
     *
     * @param {String} topic
     */
    onClickQuestion(topic) {
        switch(topic) {
            case 'content':
                HashBrown.Helpers.ContentHelper.startTour();
                break;

            case 'media':
                UI.messageModal('Media', [
                    _.p('This is a gallery of your statically hosted files, such as images, videos and PDFs.'),
                    _.p('The contents of this gallery depends on which Connection has been set up as the Media provider')
                ]);
                break;

            case'forms':
                HashBrown.Helpers.FormHelper.startTour();
                break;

            case 'connections':
                HashBrown.Helpers.ConnectionHelper.startTour();
                break;

            case 'schemas':
                UI.messageModal('Schemas', 'This is a library of content structures. Here you define how your editable content looks and behaves. You can define schemas for both content nodes and property fields.');
                break;
        }
    }

    /**
     * Gets the help options
     *
     * @return {Object} Options
     */
    getHelpOptions() {
        let helpOptions = {
            'Connections': () => { this.onClickQuestion('connections'); },
            'Content': () => { this.onClickQuestion('content'); },
            'Forms': () => { this.onClickQuestion('forms'); },
            'Media': () => { this.onClickQuestion('media'); },
            'Schemas': () => { this.onClickQuestion('schemas'); }
        };

        if(!currentUserHasScope('connections')) { delete helpOptions['Connections']; }
        if(!currentUserHasScope('schemas')) { delete helpOptions['Schemas']; }

        return helpOptions;
    }

    /**
     * Post render
     */
    postrender() {
        if(this.languageDropdown) {
            this.languageDropdown.notify(HashBrown.Context.language);
        }
    }

    /**
     * Renders this menu
     */
    template() {
        return _.div({class: 'main-menu widget-group'},
            _.if(HashBrown.Context.projectSettings.languages.length > 1,
                // Language picker
                this.languageDropdown = new HashBrown.Views.Widgets.Dropdown({
                    tooltip: 'Language',
                    icon: 'flag',
                    value: HashBrown.Context.language,
                    options: HashBrown.Context.projectSettings.languages,
                    onChange: (newValue) => {
                        this.onChangeLanguage(newValue);
                    }
                })
            ),

            // User dropdown
            this.userDropdown = new HashBrown.Views.Widgets.Dropdown({
                tooltip: 'Logged in as "' + (HashBrown.Context.user.fullName || HashBrown.Context.user.username) + '"',
                icon: 'user',
                reverseKeys: true,
                options: {
                    'User settings': () => { new HashBrown.Views.Editors.UserEditor({ hidePermissions: true, model: HashBrown.Context.user }); },
                    'Log out': () => {
                        HashBrown.Helpers.RequestHelper.customRequest('post', '/api/user/logout')
                        .then(() => {
                            location = '/';
                        });
                    }
                }
            }),

            // Help
            this.helpDropdown = new HashBrown.Views.Widgets.Dropdown({
                tooltip: 'Get help',
                icon: 'question-circle',
                reverseKeys: true,
                options: this.getHelpOptions(),
            })
        );
    }
}

module.exports = MainMenu;
<commit_msg>Added trailing slash to media guide modal<commit_after>'use strict';

/**
 * The main menu
 *
 * @memberof HashBrown.Client.Views.Navigation
 */
class MainMenu extends Crisp.View {
    constructor(params) {
        super(params);

        $('.page--environment__space--menu').html(this.$element);

        this.fetch();
    }

    /**
     * Event: On change language
     *
     * @param {String} newLanguage
     */
    async onChangeLanguage(newLanguage) {
        localStorage.setItem('language', newLanguage);
        HashBrown.Context.language = newLanguage;

        await HashBrown.Helpers.ResourceHelper.reloadResource('content');

        let contentEditor = Crisp.View.get('ContentEditor');

        if(contentEditor) {
            contentEditor.model = null;
            await contentEditor.fetch();
        }

        this.fetch();
    }

    /**
     * Event: Click question
     *
     * @param {String} topic
     */
    onClickQuestion(topic) {
        switch(topic) {
            case 'content':
                HashBrown.Helpers.ContentHelper.startTour();
                break;

            case 'media':
                UI.messageModal('Media', [
                    _.p('This is a gallery of your statically hosted files, such as images, videos and PDFs.'),
                    _.p('The contents of this gallery depends on which Connection has been set up as the Media provider')
                ]);
                break;

            case'forms':
                HashBrown.Helpers.FormHelper.startTour();
                break;

            case 'connections':
                HashBrown.Helpers.ConnectionHelper.startTour();
                break;

            case 'schemas':
                UI.messageModal('Schemas', 'This is a library of content structures. Here you define how your editable content looks and behaves. You can define schemas for both content nodes and property fields.');
                break;
        }
    }

    /**
     * Gets the help options
     *
     * @return {Object} Options
     */
    getHelpOptions() {
        let helpOptions = {
            'Connections': () => { this.onClickQuestion('connections'); },
            'Content': () => { this.onClickQuestion('content'); },
            'Forms': () => { this.onClickQuestion('forms'); },
            'Media': () => { this.onClickQuestion('media'); },
            'Schemas': () => { this.onClickQuestion('schemas'); }
        };

        if(!currentUserHasScope('connections')) { delete helpOptions['Connections']; }
        if(!currentUserHasScope('schemas')) { delete helpOptions['Schemas']; }

        return helpOptions;
    }

    /**
     * Post render
     */
    postrender() {
        if(this.languageDropdown) {
            this.languageDropdown.notify(HashBrown.Context.language);
        }
    }

    /**
     * Renders this menu
     */
    template() {
        return _.div({class: 'main-menu widget-group'},
            _.if(HashBrown.Context.projectSettings.languages.length > 1,
                // Language picker
                this.languageDropdown = new HashBrown.Views.Widgets.Dropdown({
                    tooltip: 'Language',
                    icon: 'flag',
                    value: HashBrown.Context.language,
                    options: HashBrown.Context.projectSettings.languages,
                    onChange: (newValue) => {
                        this.onChangeLanguage(newValue);
                    }
                })
            ),

            // User dropdown
            this.userDropdown = new HashBrown.Views.Widgets.Dropdown({
                tooltip: 'Logged in as "' + (HashBrown.Context.user.fullName || HashBrown.Context.user.username) + '"',
                icon: 'user',
                reverseKeys: true,
                options: {
                    'User settings': () => { new HashBrown.Views.Editors.UserEditor({ hidePermissions: true, model: HashBrown.Context.user }); },
                    'Log out': () => {
                        HashBrown.Helpers.RequestHelper.customRequest('post', '/api/user/logout')
                        .then(() => {
                            location = '/';
                        });
                    }
                }
            }),

            // Help
            this.helpDropdown = new HashBrown.Views.Widgets.Dropdown({
                tooltip: 'Get help',
                icon: 'question-circle',
                reverseKeys: true,
                options: this.getHelpOptions(),
            })
        );
    }
}

module.exports = MainMenu;
<|endoftext|>


<commit_before>var URL = "http://localhost:4242/web/index.html"

casper.test.begin("current user shown correctly", 2, function(test) {
    casper.start(URL).
        then(function () {
            test.assertExists("#username");
            test.assertSelectorHasText("#username", "John Doe");
        }).
        run(function() {
            test.done();
    });
});

function get_number_of_rows(table_selector) {
    var result = casper.evaluate(function (selector) {
        return $(selector).find("tr").length;
    }, table_selector);
    return result;
}

function get_cell_from_last_row(table_selector, cell_index) {
    return casper.evaluate(function(selector, index) {
        return $(selector).find("tr").last().find("td")[index].innerHTML;
    }, table_selector, cell_index);
}

casper.test.begin("new message appears in the sent messages list", 6, function (test) {
    var initial_sent_notes_count;
    var initial_received_notes_count;

    casper.start(URL);

    casper.then(function() {
        this.sendKeys("#recipient", "Jane Doe");

        initial_sent_notes_count = get_number_of_rows("#sent_notes_table");
        initial_received_notes_count = get_number_of_rows("#received_notes_table");

        // send note
        this.click("#thank_you_button");
    });

    casper.wait(100);

    casper.then(function() {
        var count_after = get_number_of_rows("#sent_notes_table");
        test.assertEquals(count_after, initial_sent_notes_count + 1);

        var recipient = get_cell_from_last_row("#sent_notes_table", 0);
        test.assertEquals(recipient, "Jane Doe");

        var message = get_cell_from_last_row("#sent_notes_table", 1);
        test.assertEquals(message, "Thank you, Jane Doe! Sincerely, John Doe");
    });

    casper.then(function() {
        this.click("#refresh_button");
    });

    casper.wait(100);

    casper.then(function (){
        // count the rows in the received notes table
        var count_after = get_number_of_rows("#received_notes_table");
        test.assertEquals(count_after, initial_received_notes_count + 1);

        var sender = get_cell_from_last_row("#received_notes_table", 0);
        test.assertEquals(sender, "Jane Doe");

        var message = get_cell_from_last_row("#received_notes_table", 1);
        test.assertEquals(message, "Thank you, John Doe! Sincerely, Jane Doe");
    });
    casper.run(function () {
        test.done();
    });
});

<commit_msg>integration tests can run without the WebAPI up<commit_after>var URL = "http://localhost:4242/web/index.html";

// when using fake api, we can load the file directly without build/restart of the web service
// the wait calls in the tests are not necessary in this case.
//var URL = "index.html";

casper.test.begin("current user shown correctly", 2, function(test) {
    casper.start(URL).
        then(function () {
            test.assertExists("#username");
            test.assertSelectorHasText("#username", "John Doe");
        }).
        run(function() {
            test.done();
    });
});

function get_number_of_rows(table_selector) {
    var result = casper.evaluate(function (selector) {
        return $(selector).find("tr").length;
    }, table_selector);
    return result;
}

function get_cell_from_last_row(table_selector, cell_index) {
    return casper.evaluate(function(selector, index) {
        return $(selector).find("tr").last().find("td")[index].innerHTML;
    }, table_selector, cell_index);
}

casper.test.begin("new message appears in the sent messages list", 6, function (test) {
    var initial_sent_notes_count;
    var initial_received_notes_count;

    casper.start(URL);

    casper.then(function() {
        this.sendKeys("#recipient", "Jane Doe");

        initial_sent_notes_count = get_number_of_rows("#sent_notes_table");
        initial_received_notes_count = get_number_of_rows("#received_notes_table");

        // send note
        this.click("#thank_you_button");
    });

    casper.wait(100);

    casper.then(function() {
        var count_after = get_number_of_rows("#sent_notes_table");
        test.assertEquals(count_after, initial_sent_notes_count + 1);

        var recipient = get_cell_from_last_row("#sent_notes_table", 0);
        test.assertEquals(recipient, "Jane Doe");

        var message = get_cell_from_last_row("#sent_notes_table", 1);
        test.assertEquals(message, "Thank you, Jane Doe! Sincerely, John Doe");
    });

    casper.then(function() {
        this.click("#refresh_button");
    });

    casper.wait(100);

    casper.then(function (){
        // count the rows in the received notes table
        var count_after = get_number_of_rows("#received_notes_table");
        test.assertEquals(count_after, initial_received_notes_count + 1);

        var sender = get_cell_from_last_row("#received_notes_table", 0);
        test.assertEquals(sender, "Jane Doe");

        var message = get_cell_from_last_row("#received_notes_table", 1);
        test.assertEquals(message, "Thank you, John Doe! Sincerely, Jane Doe");
    });
    casper.run(function () {
        test.done();
    });
});

<|endoftext|>


<commit_before>/*
Copyright (C) 2010, Oleg Efimov <efimovov@gmail.com>

See license text in LICENSE file
*/

// Require modules
var
  sys = require('sys'),
  mysql = require('../deps/Sannis-node-mysql-libmysqlclient/mysql-libmysqlclient'),
  conn;

/*function fetchAllAsyncBenchmark(callback, cfg) {
  var
    start_time,
    total_time,
    factor = cfg.do_not_run_sync_if_async_exists ? 1 : 2,
    res,
    rows;

  start_time = new Date();

  res = conn.querySync("SELECT * FROM " + cfg.test_table + ";");

  res.fetchAll(function (err, rows) {
    //res.freeSync();

    total_time = ((new Date()) - start_time) / 1000;
    sys.puts("**** " + (factor * cfg.insert_rows_count) + " rows async (fetchAll) selected in " + total_time + "s (" + Math.round(factor * cfg.insert_rows_count / total_time) + "/s)");

    // Finish benchmark
    conn.closeSync();
    callback.apply();
  });
}*/

function fetchObjectLoopSyncBenchmark(callback, cfg) {
  var
    start_time,
    total_time,
    factor = cfg.do_not_run_sync_if_async_exists ? 1 : 2,
    res,
    row,
    rows = [];

  start_time = new Date();

  res = conn.querySync("SELECT * FROM " + cfg.test_table + ";");

  while ((row = res.fetchObjectSync())) {
    rows.push(row);
  }

  res.freeSync();

  total_time = ((new Date()) - start_time) / 1000;
  sys.puts("**** " + (factor * cfg.insert_rows_count) + " rows sync (fetchObject in loop) selected in " + total_time + "s (" + Math.round(factor * cfg.insert_rows_count / total_time) + "/s)");

  //fetchAllAsyncBenchmark(callback, cfg);
  // Finish benchmark
  conn.closeSync();
  callback.apply();
}

function fetchAllSyncBenchmark(callback, cfg) {
  var
    start_time,
    total_time,
    factor = cfg.do_not_run_sync_if_async_exists ? 1 : 2,
    res,
    rows;

  start_time = new Date();

  res = conn.querySync("SELECT * FROM " + cfg.test_table + ";");

  rows = res.fetchAllSync();

  res.freeSync();

  total_time = ((new Date()) - start_time) / 1000;
  sys.puts("**** " + (factor * cfg.insert_rows_count) + " rows sync (fetchAll) selected in " + total_time + "s (" + Math.round(factor * cfg.insert_rows_count / total_time) + "/s)");

  fetchObjectLoopSyncBenchmark(callback, cfg);
}

function insertAsyncBenchmark(callback, cfg) {
  var
    start_time,
    total_time,
    i = 0;

  start_time = new Date();

  function insertAsync() {
    i += 1;
    if (i <= cfg.insert_rows_count) {
      conn.query(cfg.insert_query, function (res) {
        insertAsync();
      });
    } else {
      total_time = ((new Date()) - start_time) / 1000;
      sys.puts("**** " + cfg.insert_rows_count + " async insertions in " + total_time + "s (" + Math.round(cfg.insert_rows_count / total_time) + "/s)");

      setTimeout(function () {
        fetchAllSyncBenchmark(callback, cfg);
      }, cfg.delay_before_select);
    }
  }

  insertAsync();
}

function insertSyncBenchmark(callback, cfg) {
  var
    start_time,
    total_time,
    i = 0,
    res;

  start_time = new Date();

  for (i = 0; i < cfg.insert_rows_count; i += 1) {
    res = conn.querySync(cfg.insert_query);
  }

  total_time = ((new Date()) - start_time) / 1000;
  sys.puts("**** " + cfg.insert_rows_count + " sync insertions in " + total_time + "s (" + Math.round(cfg.insert_rows_count / total_time) + "/s)");

  insertAsyncBenchmark(callback, cfg);
}

function reconnectHalfAsyncBenchmark(callback, cfg) {
  var
    start_time,
    total_time,
    i = 0;

    start_time = new Date();

    function reconnectAsync() {
      i += 1;
      if (i <= cfg.reconnect_count) {
        conn.closeSync();
        conn.connect(cfg.host, cfg.user, cfg.password, cfg.database, function (err, result) {
          reconnectAsync();
        });
      } else {
        total_time = ((new Date()) - start_time) / 1000;
        sys.puts("**** " + cfg.reconnect_count + " half-async reconnects in " + total_time + "s (" + Math.round(cfg.reconnect_count / total_time) + "/s)");

        if (cfg.do_not_run_sync_if_async_exists) {
          insertAsyncBenchmark(callback, cfg);
        } else {
          insertSyncBenchmark(callback, cfg);
        }
      }
    }

    reconnectAsync();
}

function reconnectSyncBenchmark(callback, cfg) {
  var
    start_time,
    total_time,
    i = 0;

  start_time = new Date();

  for (i = 0; i < cfg.reconnect_count; i += 1) {
    conn.closeSync();
    conn.connectSync(cfg.host, cfg.user, cfg.password, cfg.database);
  }

  total_time = ((new Date()) - start_time) / 1000;
  sys.puts("**** " + cfg.reconnect_count + " sync reconnects in " + total_time + "s (" + Math.round(cfg.reconnect_count / total_time) + "/s)");

  reconnectHalfAsyncBenchmark(callback, cfg);
}

function escapeBenchmark(callback, cfg) {
  var
    start_time,
    total_time,
    i = 0,
    escaped_string;

  start_time = new Date();

  for (i = 0; i < cfg.escape_count; i += 1) {
    escaped_string = conn.escapeSync(cfg.string_to_escape);
  }

  total_time = ((new Date()) - start_time) / 1000;
  sys.puts("**** " + cfg.escape_count + " escapes in " + total_time + "s (" + Math.round(cfg.escape_count / total_time) + "/s)");

  reconnectSyncBenchmark(callback, cfg);
}

function startBenchmark(callback, cfg) {
  var
    start_time,
    total_time;

  start_time = new Date();

  conn = mysql.createConnectionSync();
  conn.connectSync(cfg.host, cfg.user, cfg.password, cfg.database);

  conn.querySync("DROP TABLE IF EXISTS " + cfg.test_table + ";");
  conn.querySync(cfg.create_table_query);

  total_time = ((new Date()) - start_time) / 1000;
  sys.puts("**** Benchmark initialization time is " + total_time + "s");

  escapeBenchmark(callback, cfg);
}

exports.run = function (callback, cfg) {
  startBenchmark(callback, cfg);
};

<commit_msg>Enable async fetchAll benchmark for Sannis/node-mysql-libmysqlclient<commit_after>/*
Copyright (C) 2010, Oleg Efimov <efimovov@gmail.com>

See license text in LICENSE file
*/

// Require modules
var
  sys = require('sys'),
  mysql = require('../deps/Sannis-node-mysql-libmysqlclient/mysql-libmysqlclient'),
  conn;

function fetchAllAsyncBenchmark(callback, cfg) {
  var
    start_time,
    total_time,
    factor = cfg.do_not_run_sync_if_async_exists ? 1 : 2,
    res,
    rows;

  start_time = new Date();

  res = conn.querySync("SELECT * FROM " + cfg.test_table + ";");

  res.fetchAll(function (err, rows) {
    res.freeSync();

    total_time = ((new Date()) - start_time) / 1000;
    sys.puts("**** " + (factor * cfg.insert_rows_count) + " rows async (fetchAll) selected in " + total_time + "s (" + Math.round(factor * cfg.insert_rows_count / total_time) + "/s)");

    // Finish benchmark
    conn.closeSync();
    callback.apply();
  });
}

function fetchObjectLoopSyncBenchmark(callback, cfg) {
  var
    start_time,
    total_time,
    factor = cfg.do_not_run_sync_if_async_exists ? 1 : 2,
    res,
    row,
    rows = [];

  start_time = new Date();

  res = conn.querySync("SELECT * FROM " + cfg.test_table + ";");

  while ((row = res.fetchObjectSync())) {
    rows.push(row);
  }

  res.freeSync();

  total_time = ((new Date()) - start_time) / 1000;
  sys.puts("**** " + (factor * cfg.insert_rows_count) + " rows sync (fetchObject in loop) selected in " + total_time + "s (" + Math.round(factor * cfg.insert_rows_count / total_time) + "/s)");

  fetchAllAsyncBenchmark(callback, cfg);
}

function fetchAllSyncBenchmark(callback, cfg) {
  var
    start_time,
    total_time,
    factor = cfg.do_not_run_sync_if_async_exists ? 1 : 2,
    res,
    rows;

  start_time = new Date();

  res = conn.querySync("SELECT * FROM " + cfg.test_table + ";");

  rows = res.fetchAllSync();

  res.freeSync();

  total_time = ((new Date()) - start_time) / 1000;
  sys.puts("**** " + (factor * cfg.insert_rows_count) + " rows sync (fetchAll) selected in " + total_time + "s (" + Math.round(factor * cfg.insert_rows_count / total_time) + "/s)");

  fetchObjectLoopSyncBenchmark(callback, cfg);
}

function insertAsyncBenchmark(callback, cfg) {
  var
    start_time,
    total_time,
    i = 0;

  start_time = new Date();

  function insertAsync() {
    i += 1;
    if (i <= cfg.insert_rows_count) {
      conn.query(cfg.insert_query, function (res) {
        insertAsync();
      });
    } else {
      total_time = ((new Date()) - start_time) / 1000;
      sys.puts("**** " + cfg.insert_rows_count + " async insertions in " + total_time + "s (" + Math.round(cfg.insert_rows_count / total_time) + "/s)");

      setTimeout(function () {
        fetchAllSyncBenchmark(callback, cfg);
      }, cfg.delay_before_select);
    }
  }

  insertAsync();
}

function insertSyncBenchmark(callback, cfg) {
  var
    start_time,
    total_time,
    i = 0,
    res;

  start_time = new Date();

  for (i = 0; i < cfg.insert_rows_count; i += 1) {
    res = conn.querySync(cfg.insert_query);
  }

  total_time = ((new Date()) - start_time) / 1000;
  sys.puts("**** " + cfg.insert_rows_count + " sync insertions in " + total_time + "s (" + Math.round(cfg.insert_rows_count / total_time) + "/s)");

  insertAsyncBenchmark(callback, cfg);
}

function reconnectHalfAsyncBenchmark(callback, cfg) {
  var
    start_time,
    total_time,
    i = 0;

    start_time = new Date();

    function reconnectAsync() {
      i += 1;
      if (i <= cfg.reconnect_count) {
        conn.closeSync();
        conn.connect(cfg.host, cfg.user, cfg.password, cfg.database, function (err, result) {
          reconnectAsync();
        });
      } else {
        total_time = ((new Date()) - start_time) / 1000;
        sys.puts("**** " + cfg.reconnect_count + " half-async reconnects in " + total_time + "s (" + Math.round(cfg.reconnect_count / total_time) + "/s)");

        if (cfg.do_not_run_sync_if_async_exists) {
          insertAsyncBenchmark(callback, cfg);
        } else {
          insertSyncBenchmark(callback, cfg);
        }
      }
    }

    reconnectAsync();
}

function reconnectSyncBenchmark(callback, cfg) {
  var
    start_time,
    total_time,
    i = 0;

  start_time = new Date();

  for (i = 0; i < cfg.reconnect_count; i += 1) {
    conn.closeSync();
    conn.connectSync(cfg.host, cfg.user, cfg.password, cfg.database);
  }

  total_time = ((new Date()) - start_time) / 1000;
  sys.puts("**** " + cfg.reconnect_count + " sync reconnects in " + total_time + "s (" + Math.round(cfg.reconnect_count / total_time) + "/s)");

  reconnectHalfAsyncBenchmark(callback, cfg);
}

function escapeBenchmark(callback, cfg) {
  var
    start_time,
    total_time,
    i = 0,
    escaped_string;

  start_time = new Date();

  for (i = 0; i < cfg.escape_count; i += 1) {
    escaped_string = conn.escapeSync(cfg.string_to_escape);
  }

  total_time = ((new Date()) - start_time) / 1000;
  sys.puts("**** " + cfg.escape_count + " escapes in " + total_time + "s (" + Math.round(cfg.escape_count / total_time) + "/s)");

  reconnectSyncBenchmark(callback, cfg);
}

function startBenchmark(callback, cfg) {
  var
    start_time,
    total_time;

  start_time = new Date();

  conn = mysql.createConnectionSync();
  conn.connectSync(cfg.host, cfg.user, cfg.password, cfg.database);

  conn.querySync("DROP TABLE IF EXISTS " + cfg.test_table + ";");
  conn.querySync(cfg.create_table_query);

  total_time = ((new Date()) - start_time) / 1000;
  sys.puts("**** Benchmark initialization time is " + total_time + "s");

  escapeBenchmark(callback, cfg);
}

exports.run = function (callback, cfg) {
  startBenchmark(callback, cfg);
};

<|endoftext|>


<commit_before>/**
 * @file TablePagination component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import Pagination from '../Pagination';
import BriefPagination from '../BriefPagination';

import SelectMode from '../_statics/SelectMode';
import SelectAllMode from '../_statics/SelectAllMode';
import SortingType from '../_statics/SortingType';

import Util from '../_vendors/Util';
import ComponentUtil from '../_vendors/ComponentUtil';

class TablePagination extends Component {

    static SelectMode = SelectMode;
    static SelectAllMode = SelectAllMode;
    static SortingType = SortingType;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.state = {
            page: props.page,
            pageSize: props.pageSize
        };

    }

    getPaginationComponent = () => {
        const {useFullPagination} = this.props;
        return useFullPagination ? Pagination : BriefPagination;
    };

    getSelectedCount = () => {

        const {selectMode, value} = this.props;

        switch (selectMode) {
            case SelectMode.MULTI_SELECT:
                return value.length;
            case SelectMode.SINGLE_SELECT:
                return value ? 1 : 0;
        }

        return 0;

    };

    handlePaginationChange = pagination => {
        this.setState(pagination, () => {
            const {onPaginationChange} = this.props;
            onPaginationChange && onPaginationChange(pagination);
        });
    };

    static getDerivedStateFromProps(props, state) {
        return {
            prevProps: props,
            page: ComponentUtil.getDerivedState(props, state, 'page'),
            pageSize: ComponentUtil.getDerivedState(props, state, 'pageSize')
        };
    }

    render() {

        const {
                className, style, data, paginationSelectionVisible, paginationSelectionRenderer,
                paginationTotalVisible, paginationTotalRenderer,
                paginationPageSizeVisible, paginationPageSizesVisible,
                paginationPrevIconCls, paginationNextIconCls, paginationFirstIconCls, paginationLastIconCls,
                ...restProps
            } = this.props,
            PaginationComponent = this.getPaginationComponent();

        return (

                <PaginationComponent {...restProps}
                                     total={data && data.length || 0}
                                     selectedCount={this.getSelectedCount()}
                                     selectionVisible={paginationSelectionVisible}
                                     totalVisible={paginationTotalVisible}
                                     pageSizeVisible={paginationPageSizeVisible}
                                     pageSizesVisible={paginationPageSizesVisible}
                                     prevIconCls={paginationPrevIconCls}
                                     nextIconCls={paginationNextIconCls}
                                     firstIconCls={paginationFirstIconCls}
                                     lastIconCls={paginationLastIconCls}
                                     selectionRenderer={paginationSelectionRenderer}
                                     totalRenderer={paginationTotalRenderer}
                                     onPaginationChange={this.handlePaginationChange}/>

        );

    }
}

TablePagination.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * The select mode of table.
     */
    selectMode: PropTypes.oneOf(Util.enumerateValue(SelectMode)),

    data: PropTypes.array,
    value: PropTypes.any,

    page: PropTypes.number,
    pageSize: PropTypes.number,
    pageSizes: PropTypes.array,
    useFullPagination: PropTypes.bool,

    paginationSelectionVisible: PropTypes.bool,
    paginationTotalVisible: PropTypes.bool,
    paginationPageSizeVisible: PropTypes.bool,
    paginationPageSizesVisible: PropTypes.bool,

    pageSizeRightIconCls: PropTypes.string,
    paginationPrevIconCls: PropTypes.string,
    paginationNextIconCls: PropTypes.string,
    paginationFirstIconCls: PropTypes.string,
    paginationLastIconCls: PropTypes.string,

    paginationSelectionRenderer: PropTypes.func,
    paginationTotalRenderer: PropTypes.func,
    onPaginationChange: PropTypes.func,
    onPageChange: PropTypes.func,
    onPageSizeChange: PropTypes.func

};

TablePagination.defaultProps = {

    selectMode: SelectMode.SINGLE_SELECT,

    page: 0,
    pageSize: 10,
    pageSizes: [5, 10, 15, 20],
    useFullPagination: false,

    paginationSelectionVisible: false,
    paginationTotalVisible: true,
    paginationPageSizeVisible: true,
    paginationPageSizesVisible: true,

    pageSizeRightIconCls: 'fas fa-angle-down',
    paginationPrevIconCls: 'fas fa-angle-left',
    paginationNextIconCls: 'fas fa-angle-right',
    paginationFirstIconCls: 'fas fa-angle-double-left',
    paginationLastIconCls: 'fas fa-angle-double-right'

};

export default TablePagination;
<commit_msg>update TablePagination<commit_after>/**
 * @file TablePagination component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import Pagination from '../Pagination';
import BriefPagination from '../BriefPagination';

import SelectMode from '../_statics/SelectMode';
import SelectAllMode from '../_statics/SelectAllMode';
import SortingType from '../_statics/SortingType';

import Util from '../_vendors/Util';
import ComponentUtil from '../_vendors/ComponentUtil';

class TablePagination extends Component {

    static SelectMode = SelectMode;
    static SelectAllMode = SelectAllMode;
    static SortingType = SortingType;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.state = {
            page: props.page,
            pageSize: props.pageSize
        };

    }

    getPaginationComponent = () => {
        const {useFullPagination} = this.props;
        return useFullPagination ? Pagination : BriefPagination;
    };

    getSelectedCount = () => {

        const {selectMode, value} = this.props;

        switch (selectMode) {
            case SelectMode.MULTI_SELECT:
                return value.length;
            case SelectMode.SINGLE_SELECT:
                return value ? 1 : 0;
        }

        return 0;

    };

    handlePaginationChange = pagination => {
        this.setState(pagination, () => {
            const {onPaginationChange} = this.props;
            onPaginationChange && onPaginationChange(pagination);
        });
    };

    static getDerivedStateFromProps(props, state) {
        return {
            prevProps: props,
            page: ComponentUtil.getDerivedState(props, state, 'page'),
            pageSize: ComponentUtil.getDerivedState(props, state, 'pageSize')
        };
    }

    render() {

        const {
                className, style, data, paginationSelectionVisible, paginationSelectionRenderer,
                paginationTotalVisible, paginationTotalRenderer,
                paginationPageSizeVisible, paginationPageSizesVisible,
                paginationPrevIconCls, paginationNextIconCls, paginationFirstIconCls, paginationLastIconCls,
                ...restProps
            } = this.props,
            PaginationComponent = this.getPaginationComponent();

        return (

                <PaginationComponent {...restProps}
                                     total={data && data.length || 0}
                                     selectedCount={this.getSelectedCount()}
                                     selectionVisible={paginationSelectionVisible}
                                     totalVisible={paginationTotalVisible}
                                     pageSizeVisible={paginationPageSizeVisible}
                                     pageSizesVisible={paginationPageSizesVisible}
                                     prevIconCls={paginationPrevIconCls}
                                     nextIconCls={paginationNextIconCls}
                                     firstIconCls={paginationFirstIconCls}
                                     lastIconCls={paginationLastIconCls}
                                     selectionRenderer={paginationSelectionRenderer}
                                     totalRenderer={paginationTotalRenderer}
                                     onPaginationChange={this.handlePaginationChange}/>

        );

    }
}

TablePagination.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * The select mode of table.
     */
    selectMode: PropTypes.oneOf(Util.enumerateValue(SelectMode)),

    data: PropTypes.array,
    value: PropTypes.any,

    page: PropTypes.number,
    pageSize: PropTypes.number,
    pageSizes: PropTypes.array,
    useFullPagination: PropTypes.bool,

    pageSizeValueField: PropTypes.string,
    pageSizeDisplayField: PropTypes.string,

    paginationSelectionVisible: PropTypes.bool,
    paginationTotalVisible: PropTypes.bool,
    paginationPageSizeVisible: PropTypes.bool,
    paginationPageSizesVisible: PropTypes.bool,

    pageSizeRightIconCls: PropTypes.string,
    paginationPrevIconCls: PropTypes.string,
    paginationNextIconCls: PropTypes.string,
    paginationFirstIconCls: PropTypes.string,
    paginationLastIconCls: PropTypes.string,

    paginationSelectionRenderer: PropTypes.func,
    paginationTotalRenderer: PropTypes.func,
    onPaginationChange: PropTypes.func,
    onPageChange: PropTypes.func,
    onPageSizeChange: PropTypes.func

};

TablePagination.defaultProps = {

    selectMode: SelectMode.SINGLE_SELECT,

    page: 0,
    pageSize: 10,
    pageSizes: [5, 10, 15, 20],
    useFullPagination: false,

    pageSizeValueField: 'value',
    pageSizeDisplayField: 'text',

    paginationSelectionVisible: false,
    paginationTotalVisible: true,
    paginationPageSizeVisible: true,
    paginationPageSizesVisible: true,

    pageSizeRightIconCls: 'fas fa-angle-down',
    paginationPrevIconCls: 'fas fa-angle-left',
    paginationNextIconCls: 'fas fa-angle-right',
    paginationFirstIconCls: 'fas fa-angle-double-left',
    paginationLastIconCls: 'fas fa-angle-double-right'

};

export default TablePagination;
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview State and UI for trace data collection.
 */
base.requireStylesheet('about_tracing.tracing_controller');

base.require('base.event_target');
base.require('ui.overlay');

base.exportTo('about_tracing', function() {

  /**
   * The tracing controller is responsible for talking to tracing_ui.cc in
   * chrome
   * @constructor
   * @param {function(String, opt_Array.<String>} Function to be used to send
   * data to chrome.
   */
  function TracingController(sendFn) {
    this.sendFn_ = sendFn;
    this.overlay_ = new ui.Overlay();
    this.overlay_.className = 'tracing-overlay';

    this.statusDiv_ = document.createElement('div');
    this.overlay_.appendChild(this.statusDiv_);

    this.bufferPercentDiv_ = document.createElement('div');
    this.overlay_.appendChild(this.bufferPercentDiv_);

    this.stopButton_ = document.createElement('button');
    this.stopButton_.onclick = this.endTracing.bind(this);
    this.stopButton_.textContent = 'Stop tracing';
    this.overlay_.appendChild(this.stopButton_);

    this.traceEvents_ = [];
    this.systemTraceEvents_ = [];

    this.onKeydownBoundToThis_ = this.onKeydown_.bind(this);
    this.onKeypressBoundToThis_ = this.onKeypress_.bind(this);

    this.supportsSystemTracing_ = base.isChromeOS;

    if (this.sendFn_)
      this.sendFn_('tracingControllerInitialized');
  }

  TracingController.prototype = {
    __proto__: base.EventTarget.prototype,

    gpuInfo_: undefined,
    clientInfo_: undefined,
    tracingEnabled_: false,
    tracingEnding_: false,
    systemTraceDataFilename_: undefined,

    get supportsSystemTracing() {
      return this.supportsSystemTracing_;
    },

    onRequestBufferPercentFullComplete: function(percent_full) {
      if (!this.overlay_.visible)
        return;

      window.setTimeout(this.beginRequestBufferPercentFull_.bind(this), 250);

      this.bufferPercentDiv_.textContent = 'Buffer usage: ' +
          Math.round(100 * percent_full) + '%';
    },

    /**
     * Begin requesting the buffer fullness
     */
    beginRequestBufferPercentFull_: function() {
      this.sendFn_('beginRequestBufferPercentFull');
    },

    /**
     * Called by info_view to empty the trace buffer
     *
     * |opt_trace_categories| is a comma-delimited list of category wildcards.
     * A category can have an optional '-' prefix to make it an excluded
     * category.  All the same rules apply above, so for example, having both
     * included and excluded categories in the same list would not be
     * supported.
     *
     * Example: beginTracing("test_MyTest*");
     * Example: beginTracing("test_MyTest*,test_OtherStuff");
     * Example: beginTracing("-excluded_category1,-excluded_category2");
     */
    beginTracing: function(opt_systemTracingEnabled, opt_trace_continuous,
                           opt_trace_categories) {
      if (this.tracingEnabled_)
        throw new Error('Tracing already begun.');

      this.stopButton_.hidden = false;
      this.statusDiv_.textContent = 'Tracing active.';
      this.overlay_.visible = true;
      this.overlay_.defaultClickShouldClose = false;

      this.tracingEnabled_ = true;

      console.log('Beginning to trace...');
      this.statusDiv_.textContent = 'Tracing active.';

      var trace_options = (opt_trace_continuous ? 'record-continuously' :
                                                  'record-until-full');

      this.traceEvents_ = [];
      this.systemTraceEvents_ = [];
      this.sendFn_(
          'beginTracing',
          [
           opt_systemTracingEnabled || false,
           opt_trace_categories || '-test_*',
           trace_options
          ]
      );
      this.beginRequestBufferPercentFull_();

      var e = new base.Event('traceBegun');
      e.events = this.traceEvents_;
      this.dispatchEvent(e);

      e = new base.Event('traceEventsChanged');
      e.numEvents = this.traceEvents_.length;
      this.dispatchEvent(e);

      window.addEventListener('keypress', this.onKeypressBoundToThis_);
      window.addEventListener('keydown', this.onKeydownBoundToThis_);
    },

    onKeydown_: function(e) {
      if (e.keyCode == 27) {
        this.endTracing();
      }
    },

    onKeypress_: function(e) {
      if (e.keyIdentifier == 'Enter') {
        this.endTracing();
      }
    },

    /**
     * Called from gpu c++ code when ClientInfo is updated.
     */
    onClientInfoUpdate: function(clientInfo) {
      this.clientInfo_ = clientInfo;
    },

    /**
     * Called from gpu c++ code when GPU Info is updated.
     */
    onGpuInfoUpdate: function(gpuInfo) {
      this.gpuInfo_ = gpuInfo;
    },

    /**
     * Checks whether tracing is enabled
     */
    get isTracingEnabled() {
      return this.tracingEnabled_;
    },

    /**
     * Gets the currently traced events. If tracing is active, then
     * this can change on the fly.
     */
    get traceEvents() {
      return this.traceEvents_;
    },

    /**
     * Called by tracing c++ code when new trace data arrives.
     */
    onTraceDataCollected: function(events) {
      this.statusDiv_.textContent = 'Processing trace...';
      this.traceEvents_.push.apply(this.traceEvents_, events);
    },

    /**
     * Called to finish tracing and update all views.
     */
    endTracing: function() {
      if (!this.tracingEnabled_) throw new Error('Tracing not begun.');
      if (this.tracingEnding_) return;
      this.tracingEnding_ = true;

      this.statusDiv_.textContent = 'Ending trace...';
      console.log('Finishing trace');
      this.statusDiv_.textContent = 'Downloading trace data...';
      this.stopButton_.hidden = true;
      // delay sending endTracingAsync until we get a chance to
      // update the screen...
      var that = this;
      window.setTimeout(function() {
        that.sendFn_('endTracingAsync');
      }, 100);
    },

    /**
     * Called by the browser when all processes complete tracing.
     */
    onEndTracingComplete: function() {
      window.removeEventListener('keydown', this.onKeydownBoundToThis_);
      window.removeEventListener('keypress', this.onKeypressBoundToThis_);
      this.overlay_.visible = false;
      this.tracingEnabled_ = false;
      this.tracingEnding_ = false;
      console.log('onEndTracingComplete p1 with ' +
                  this.traceEvents_.length + ' events.');
      var e = new base.Event('traceEnded');
      e.events = this.traceEvents_;
      this.dispatchEvent(e);
    },

    collectCategories: function() {
      this.sendFn_('getKnownCategories');
    },

    onKnownCategoriesCollected: function(categories) {
      var e = new base.Event('categoriesCollected');
      e.categories = categories;
      this.dispatchEvent(e);
    },

    /**
     * Called by tracing c++ code when new system trace data arrives.
     */
    onSystemTraceDataCollected: function(events) {
      console.log('onSystemTraceDataCollected with ' +
                  events.length + ' chars of data.');
      this.systemTraceEvents_ = events;
    },

    /**
     * Gets the currentl system trace events. If tracing is active, then
     * this can change on the fly.
     */
    get systemTraceEvents() {
      return this.systemTraceEvents_;
    },

    /**
     * Tells browser to put up a load dialog and load the trace file
     */
    beginLoadTraceFile: function() {
      this.sendFn_('loadTraceFile');
    },

    /**
     * Called by the browser when a trace file is loaded.
     */
    onLoadTraceFileComplete: function(data) {
      if (data.traceEvents) {
        this.traceEvents_ = data.traceEvents;
      } else { // path for loading traces saved without metadata
        if (!data.length)
          console.log('Expected an array when loading the trace file');
        else
          this.traceEvents_ = data;
      }

      if (data.systemTraceEvents)
        this.systemTraceEvents_ = data.systemTraceEvents;
      else
        this.systemTraceEvents_ = [];

      var e = new base.Event('loadTraceFileComplete');
      e.events = this.traceEvents_;
      this.dispatchEvent(e);
    },

    /**
     * Called by the browser when loading a trace file was canceled.
     */
    onLoadTraceFileCanceled: function() {
      base.dispatchSimpleEvent(this, 'loadTraceFileCanceled');
    },

    /**
     * Tells browser to put up a save dialog and save the trace file
     */
    beginSaveTraceFile: function(traceEvents, systemTraceEvents) {
      var data = {
        traceEvents: this.traceEvents_,
        systemTraceEvents: this.systemTraceEvents_,
        clientInfo: this.clientInfo_,
        gpuInfo: this.gpuInfo_
      };
      this.sendFn_('saveTraceFile', [JSON.stringify(data)]);
    },

    /**
     * Called by the browser when a trace file is saveed.
     */
    onSaveTraceFileComplete: function() {
      base.dispatchSimpleEvent(this, 'saveTraceFileComplete');
    },

    /**
     * Called by the browser when saving a trace file was canceled.
     */
    onSaveTraceFileCanceled: function() {
      base.dispatchSimpleEvent(this, 'saveTraceFileCanceled');
    }
  };
  return {
    TracingController: TracingController
  };
});
<commit_msg>Only update percentFullDiv when it changes<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview State and UI for trace data collection.
 */
base.requireStylesheet('about_tracing.tracing_controller');

base.require('base.event_target');
base.require('ui.overlay');

base.exportTo('about_tracing', function() {

  /**
   * The tracing controller is responsible for talking to tracing_ui.cc in
   * chrome
   * @constructor
   * @param {function(String, opt_Array.<String>} Function to be used to send
   * data to chrome.
   */
  function TracingController(sendFn) {
    this.sendFn_ = sendFn;
    this.overlay_ = new ui.Overlay();
    this.overlay_.className = 'tracing-overlay';

    this.statusDiv_ = document.createElement('div');
    this.overlay_.appendChild(this.statusDiv_);

    this.bufferPercentDiv_ = document.createElement('div');
    this.overlay_.appendChild(this.bufferPercentDiv_);

    this.stopButton_ = document.createElement('button');
    this.stopButton_.onclick = this.endTracing.bind(this);
    this.stopButton_.textContent = 'Stop tracing';
    this.overlay_.appendChild(this.stopButton_);

    this.traceEvents_ = [];
    this.systemTraceEvents_ = [];

    this.onKeydownBoundToThis_ = this.onKeydown_.bind(this);
    this.onKeypressBoundToThis_ = this.onKeypress_.bind(this);

    this.supportsSystemTracing_ = base.isChromeOS;

    if (this.sendFn_)
      this.sendFn_('tracingControllerInitialized');
  }

  TracingController.prototype = {
    __proto__: base.EventTarget.prototype,

    gpuInfo_: undefined,
    clientInfo_: undefined,
    tracingEnabled_: false,
    tracingEnding_: false,
    systemTraceDataFilename_: undefined,

    get supportsSystemTracing() {
      return this.supportsSystemTracing_;
    },

    onRequestBufferPercentFullComplete: function(percent_full) {
      if (!this.overlay_.visible)
        return;

      window.setTimeout(this.beginRequestBufferPercentFull_.bind(this), 500);

      var newText = 'Buffer usage: ' +
          Math.round(100 * percent_full) + '%';
      if (this.bufferPercentDiv_.textContent != newText)
        this.bufferPercentDiv_.textContent = newText;
    },

    /**
     * Begin requesting the buffer fullness
     */
    beginRequestBufferPercentFull_: function() {
      this.sendFn_('beginRequestBufferPercentFull');
    },

    /**
     * Called by info_view to empty the trace buffer
     *
     * |opt_trace_categories| is a comma-delimited list of category wildcards.
     * A category can have an optional '-' prefix to make it an excluded
     * category.  All the same rules apply above, so for example, having both
     * included and excluded categories in the same list would not be
     * supported.
     *
     * Example: beginTracing("test_MyTest*");
     * Example: beginTracing("test_MyTest*,test_OtherStuff");
     * Example: beginTracing("-excluded_category1,-excluded_category2");
     */
    beginTracing: function(opt_systemTracingEnabled, opt_trace_continuous,
                           opt_trace_categories) {
      if (this.tracingEnabled_)
        throw new Error('Tracing already begun.');

      this.stopButton_.hidden = false;
      this.statusDiv_.textContent = 'Tracing active.';
      this.overlay_.visible = true;
      this.overlay_.defaultClickShouldClose = false;

      this.tracingEnabled_ = true;

      console.log('Beginning to trace...');
      this.statusDiv_.textContent = 'Tracing active.';

      var trace_options = (opt_trace_continuous ? 'record-continuously' :
                                                  'record-until-full');

      this.traceEvents_ = [];
      this.systemTraceEvents_ = [];
      this.sendFn_(
          'beginTracing',
          [
           opt_systemTracingEnabled || false,
           opt_trace_categories || '-test_*',
           trace_options
          ]
      );
      this.beginRequestBufferPercentFull_();

      var e = new base.Event('traceBegun');
      e.events = this.traceEvents_;
      this.dispatchEvent(e);

      e = new base.Event('traceEventsChanged');
      e.numEvents = this.traceEvents_.length;
      this.dispatchEvent(e);

      window.addEventListener('keypress', this.onKeypressBoundToThis_);
      window.addEventListener('keydown', this.onKeydownBoundToThis_);
    },

    onKeydown_: function(e) {
      if (e.keyCode == 27) {
        this.endTracing();
      }
    },

    onKeypress_: function(e) {
      if (e.keyIdentifier == 'Enter') {
        this.endTracing();
      }
    },

    /**
     * Called from gpu c++ code when ClientInfo is updated.
     */
    onClientInfoUpdate: function(clientInfo) {
      this.clientInfo_ = clientInfo;
    },

    /**
     * Called from gpu c++ code when GPU Info is updated.
     */
    onGpuInfoUpdate: function(gpuInfo) {
      this.gpuInfo_ = gpuInfo;
    },

    /**
     * Checks whether tracing is enabled
     */
    get isTracingEnabled() {
      return this.tracingEnabled_;
    },

    /**
     * Gets the currently traced events. If tracing is active, then
     * this can change on the fly.
     */
    get traceEvents() {
      return this.traceEvents_;
    },

    /**
     * Called by tracing c++ code when new trace data arrives.
     */
    onTraceDataCollected: function(events) {
      this.statusDiv_.textContent = 'Processing trace...';
      this.traceEvents_.push.apply(this.traceEvents_, events);
    },

    /**
     * Called to finish tracing and update all views.
     */
    endTracing: function() {
      if (!this.tracingEnabled_) throw new Error('Tracing not begun.');
      if (this.tracingEnding_) return;
      this.tracingEnding_ = true;

      this.statusDiv_.textContent = 'Ending trace...';
      console.log('Finishing trace');
      this.statusDiv_.textContent = 'Downloading trace data...';
      this.stopButton_.hidden = true;
      // delay sending endTracingAsync until we get a chance to
      // update the screen...
      var that = this;
      window.setTimeout(function() {
        that.sendFn_('endTracingAsync');
      }, 100);
    },

    /**
     * Called by the browser when all processes complete tracing.
     */
    onEndTracingComplete: function() {
      window.removeEventListener('keydown', this.onKeydownBoundToThis_);
      window.removeEventListener('keypress', this.onKeypressBoundToThis_);
      this.overlay_.visible = false;
      this.tracingEnabled_ = false;
      this.tracingEnding_ = false;
      console.log('onEndTracingComplete p1 with ' +
                  this.traceEvents_.length + ' events.');
      var e = new base.Event('traceEnded');
      e.events = this.traceEvents_;
      this.dispatchEvent(e);
    },

    collectCategories: function() {
      this.sendFn_('getKnownCategories');
    },

    onKnownCategoriesCollected: function(categories) {
      var e = new base.Event('categoriesCollected');
      e.categories = categories;
      this.dispatchEvent(e);
    },

    /**
     * Called by tracing c++ code when new system trace data arrives.
     */
    onSystemTraceDataCollected: function(events) {
      console.log('onSystemTraceDataCollected with ' +
                  events.length + ' chars of data.');
      this.systemTraceEvents_ = events;
    },

    /**
     * Gets the currentl system trace events. If tracing is active, then
     * this can change on the fly.
     */
    get systemTraceEvents() {
      return this.systemTraceEvents_;
    },

    /**
     * Tells browser to put up a load dialog and load the trace file
     */
    beginLoadTraceFile: function() {
      this.sendFn_('loadTraceFile');
    },

    /**
     * Called by the browser when a trace file is loaded.
     */
    onLoadTraceFileComplete: function(data) {
      if (data.traceEvents) {
        this.traceEvents_ = data.traceEvents;
      } else { // path for loading traces saved without metadata
        if (!data.length)
          console.log('Expected an array when loading the trace file');
        else
          this.traceEvents_ = data;
      }

      if (data.systemTraceEvents)
        this.systemTraceEvents_ = data.systemTraceEvents;
      else
        this.systemTraceEvents_ = [];

      var e = new base.Event('loadTraceFileComplete');
      e.events = this.traceEvents_;
      this.dispatchEvent(e);
    },

    /**
     * Called by the browser when loading a trace file was canceled.
     */
    onLoadTraceFileCanceled: function() {
      base.dispatchSimpleEvent(this, 'loadTraceFileCanceled');
    },

    /**
     * Tells browser to put up a save dialog and save the trace file
     */
    beginSaveTraceFile: function(traceEvents, systemTraceEvents) {
      var data = {
        traceEvents: this.traceEvents_,
        systemTraceEvents: this.systemTraceEvents_,
        clientInfo: this.clientInfo_,
        gpuInfo: this.gpuInfo_
      };
      this.sendFn_('saveTraceFile', [JSON.stringify(data)]);
    },

    /**
     * Called by the browser when a trace file is saveed.
     */
    onSaveTraceFileComplete: function() {
      base.dispatchSimpleEvent(this, 'saveTraceFileComplete');
    },

    /**
     * Called by the browser when saving a trace file was canceled.
     */
    onSaveTraceFileCanceled: function() {
      base.dispatchSimpleEvent(this, 'saveTraceFileCanceled');
    }
  };
  return {
    TracingController: TracingController
  };
});
<|endoftext|>