<commit_before>'use strict';

ddescribe('$faModifier', function() {
  var element, $compile, $scope, $famous;
  var TransformSpy, ModifierSpy;
  var compileFaModifier, getModifier, getIsolate, callGetTransform;

  // Set up spies to replace the famo.us Transform module, so we can ensure
  // that the right args are being passed to the Transform functions
  beforeEach(module('famous.angular', function($provide, _$famousProvider_) {
    // Set mockFamous as an instance of default $famous service
    var mockFamous = _$famousProvider_.$get();
    var methods = [
      'aboutOrigin',
      'perspective',
      'rotate',
      'rotateAxis',
      'rotateX',
      'rotateY',
      'rotateZ',
      'scale',
      'skew',
      'translate',
      'multiply'
    ];

    TransformSpy = mockFamous['famous/core/Transform'];

    // Spy on all the methods of Transform
    for (var i = 0; i < methods.length; i++) {
      spyOn(TransformSpy, methods[i]).and.callThrough();
    }

    ModifierSpy = jasmine.createSpy('Modifier');
    mockFamous['famous/core/Modifier'] = ModifierSpy;

    $provide.value('$famous', mockFamous);
  }));

  beforeEach(inject(function(_$compile_, _$rootScope_, _$famous_) {
    $compile = _$compile_;
    $scope = _$rootScope_.$new();
    $famous = _$famous_;

    compileFaModifier = function(attr) {
      return $compile('<fa-modifier ' + attr + '></fa-modifier>')($scope);
    };

    // faModifier must be an angular element so that .scope() can be called on it
    getModifier = function(faModifier) {
      var scope = faModifier.scope();
      var modifier = scope.isolate[scope.$id].modifier;
      return modifier;
    };

    getIsolate = function(faModifier) {
      var scope = faModifier.scope();
      return scope.isolate[scope.$id];
    };

    // getTransform is usually only called in the render loop, but invoke it
    // so that the Transform object calls its functions like rotateX, translate
    callGetTransform = function(faModifier) {
      var scope = faModifier.scope();
      var isolate = scope.isolate[scope.$id];
      isolate.getTransform();
    };
  }));

  it("should create an instance of Famo.us Modifier", function() {
    var Modifier = $famous['famous/core/Modifier'];
    var faModifier = compileFaModifier('fa-translate-x="300"');
    var modifier = getModifier(faModifier);
    expect(modifier instanceof Modifier).toBe(true);
  });

  it("should listen to 'registerChild' events from nested fa- directives, and add their data to fa-modifier's renderNode", function() {
    var RenderNode = $famous['famous/core/RenderNode'];
    var isolate;
    var modifierContent;
    $scope.$on('registerChild', function(event, data) {
      isolate = data;
    });
    var faModifier = $compile('<fa-modifier><fa-surface></fa-surface></fa-modifier>')($scope);
    //var children = faModifier[0].firstChild;
    expect(isolate.renderNode instanceof RenderNode).toBe(true);
  });

  /********************************************************************

    Test Generation
    ---------------

    generateTests() should be called before the actual execution of Jasmine,
    in order for the it() blocks to be created and ran in time.

    These tests check which values the attribute will accept.  All attributes
    will be $parse'd.

  ********************************************************************/

    function generateTests(attr, method, acceptableValues, expectedOutput) {

      // All values need to be strings that can $parse'd by Angular
      var values = {
        numbers: expectedOutput + '',
        arrays: '[' + expectedOutput + ']',
        functions: 'fn',
        expressions: 'fn()',
        transitionables: 'transitionable'
      };

      // Generate tests.  Use closures to ensure that the current loop value
      // is passed to the it() block
      for (var valueType in values) {
        // If the valueType is one of the acceptableValues to test
        if (acceptableValues.indexOf(valueType) !== -1) {
          // Generate a new spec
          it(valueType, function(type) {
            return function() {
              var value = values[type];
              var faModifier = compileFaModifier(attr + '="' + value + '"');
              callGetTransform(faModifier);
              // Check the arguments that are passed to the Transform module
              var expectation = expect(TransformSpy[method]);
              // If the expectedOutput is an array, we must convert the array
              // into individual arguments to match the expected arguments
              if (expectedOutput instanceof Array) {
                expectation.toHaveBeenCalledWith.apply(expectation, expectedOutput);
              // if the expectedOutput is a number, just check that it matches
              } else if (typeof expectedOutput === 'number') {
                expectation.toHaveBeenCalledWith(expectedOutput);
              }
            };
          // Immediately invoke the function passing in the loop's current
          // var value
          }(valueType));
        }
      }
    };

  /********************************************************************

    Transform properties

  ********************************************************************/

  describe('should accept Transform attributes', function() {

    describe('fa-rotate should accept', function() {
      beforeEach(function() {
        $scope.fn = function() {
          return [0, 0.5, -0.5];
        };
        $scope.transitionable = {
          get: function() { return [0, 0.5, -0.5]; }
        }
      });
      generateTests(
        // Attribute
        'fa-rotate',
        // Transform method expected to be called
        'rotate',
        // Acceptable values
        ['arrays', 'functions', 'expressions'],
        // Expected output
        [0, 0.5, -0.5]
      );
    });

    describe('fa-rotate-x should accept', function() {
      beforeEach(function() {
        $scope.fn = function() {
          return 0.5;
        };
        $scope.transitionable = {
          get: function() { return 0.5; }
        }
      });
      generateTests(
        // Attribute
        'fa-rotate-x',
        // Transform method expected to be called
        'rotateX',
        // Acceptable values
        ['numbers', 'functions', 'expressions'],
        // Expected output
        0.5
      );
    });

    describe('fa-rotate-y should accept', function() {
      beforeEach(function() {
        $scope.fn = function() {
          return 0.5;
        };
        $scope.transitionable = {
          get: function() { return 0.5; }
        }
      });
      generateTests(
        // Attribute
        'fa-rotate-y',
        // Transform method expected to be called
        'rotateY',
        // Acceptable values
        ['numbers', 'functions', 'expressions'],
        // Expected output
        0.5
      );
    });

    describe('fa-rotate-z should accept', function() {
      beforeEach(function() {
        $scope.fn = function() {
          return -0.785;
        };
        $scope.transitionable = {
          get: function() { return -0.785; }
        }
      });
      generateTests(
        // Attribute
        'fa-rotate-z',
        // Transform method expected to be called
        'rotateZ',
        // Acceptable values
        ['numbers', 'functions', 'expressions'],
        // Expected output
        -0.785
      );
    });

    describe('fa-scale should accept', function() {
      beforeEach(function() {
        $scope.fn = function() {
          return [0, 0.5, 1];
        };
        $scope.transitionable = {
          get: function() { return [0, 0.5, 1]; }
        }
      });
      generateTests(
        // Attribute
        'fa-rotate-z',
        // Transform method expected to be called
        'rotateZ',
        // Acceptable values
        ['arrays', 'functions', 'expressions'],
        // Expected output
        [0, 0.5, 1]
      );
    });

    describe('fa-skew should accept', function() {
      beforeEach(function() {
        $scope.fn = function() {
          return -0.2;
        };
        $scope.transitionable = {
          get: function() { return -0.2; }
        }
      });
      generateTests(
        // Attribute
        'fa-rotate-z',
        // Transform method expected to be called
        'rotateZ',
        // Acceptable values
        ['arrays', 'functions', 'expressions'],
        // Expected output
        -0.2
      );
    });

    describe('fa-transform should accept', function() {
      beforeEach(function() {
        $scope.fn = function() {
          return [0, 1, 0, 1];
        };
        $scope.transitionable = {
          get: function() { return [0, 1, 0, 1]; }
        }
      });
      generateTests(
        // Attribute
        'fa-rotate-z',
        // Transform method expected to be called
        'rotateZ',
        // Acceptable values
        ['arrays', 'functions', 'expressions'],
        // Expected output
        [0, 1, 0, 1]
      );

      it('directly set the transform matrix', function() {
        $scope.matrix = [0, 1, 2, 3];
        var faModifier = compileFaModifier('fa-transform="matrix"');
        var args = ModifierSpy.calls.mostRecent().args[0];
        expect(args.transform()).toEqual($scope.matrix);
      });

      it('override any existing transform attributes', function() {
        $scope.matrix = [0, 1, 2, 3];
        // Add additional transform attribute that should be ignored
        var faModifier = compileFaModifier('fa-transform="matrix" fa-rotate="[0.5, 0.25, 0]"');
        var args = ModifierSpy.calls.mostRecent().args[0];
        expect(args.transform()).toEqual($scope.matrix);
      });
    });

    describe('fa-transform-order', function() {

      it('to control the transformation order', function() {
        $scope.order = ['translate', 'rotateZ'];
        var faModifier = compileFaModifier('fa-transform-order="order" fa-rotate-z="0.5" fa-translate="[30, 50, 1]"');
        var args = ModifierSpy.calls.mostRecent().args[0];
        var transformResult = TransformSpy['translate'].apply(this, [30, 50, 1]);
        args.transform();

        var firstArgument = TransformSpy.multiply.calls.first().args[0];
        expect(firstArgument).toEqual(transformResult);
      });
    });

      it('if missing, will result in the transforms being in alphabetical order', function() {
        $scope.order = ['translate', 'rotateZ'];
        var faModifier = compileFaModifier('fa-rotate-z="0.5" fa-translate="[30, 50, 1]"');
        var args = ModifierSpy.calls.mostRecent().args[0];
        var transformResult = TransformSpy['translate'].apply(this, [30, 50, 1]);
        args.transform();

        var firstArgument = TransformSpy.multiply.calls.first().args[0];
        expect(firstArgument).not.toEqual(transformResult);
      });

  });

  /********************************************************************

    General modifier properties

  ********************************************************************/

  describe('should accept main Modifier attributes', function() {

    it('fa-opacity - to set the opacity of the modifier', function() {
      var faModifier = compileFaModifier('fa-opacity="0.5"');
      var args = ModifierSpy.calls.mostRecent().args[0];
      expect(args.opacity()).toEqual(0.5);
    });

    it('fa-size - to set the size of the modifier', function() {
      var faModifier = compileFaModifier('fa-size="[300,200]"');
      var args = ModifierSpy.calls.mostRecent().args[0];
      expect(args.size()).toEqual([300, 200]);
    });

    it('fa-origin - to set the origin of the modifier', function() {
      var faModifier = compileFaModifier('fa-origin="[0.5,0.5]"');
      var args = ModifierSpy.calls.mostRecent().args[0];
      expect(args.origin()).toEqual([0.5, 0.5]);
    });

    it('fa-align - to set the align of the modifier', function() {
      var faModifier = compileFaModifier('fa-align="[0.5,0.5]"');
      var args = ModifierSpy.calls.mostRecent().args[0];
      expect(args.align()).toEqual([0.5, 0.5]);
    });

  });

});

<commit_msg>Finish tests for general Modifier attributes fa-size, fa-opacity, etc<commit_after>'use strict';

ddescribe('$faModifier', function() {
  var element, $compile, $scope, $famous;
  var TransformSpy, ModifierSpy;
  var compileFaModifier, getModifier, getIsolate, callGetTransform;

  // Set up spies to replace the famo.us Transform module, so we can ensure
  // that the right args are being passed to the Transform functions
  beforeEach(module('famous.angular', function($provide, _$famousProvider_) {
    // Set mockFamous as an instance of default $famous service
    var mockFamous = _$famousProvider_.$get();
    var methods = [
      'aboutOrigin',
      'perspective',
      'rotate',
      'rotateAxis',
      'rotateX',
      'rotateY',
      'rotateZ',
      'scale',
      'skew',
      'translate',
      'multiply'
    ];

    TransformSpy = mockFamous['famous/core/Transform'];

    // Spy on all the methods of Transform
    for (var i = 0; i < methods.length; i++) {
      spyOn(TransformSpy, methods[i]).and.callThrough();
    }

    ModifierSpy = jasmine.createSpy('Modifier');
    mockFamous['famous/core/Modifier'] = ModifierSpy;

    $provide.value('$famous', mockFamous);
  }));

  beforeEach(inject(function(_$compile_, _$rootScope_, _$famous_) {
    $compile = _$compile_;
    $scope = _$rootScope_.$new();
    $famous = _$famous_;

    compileFaModifier = function(attr) {
      return $compile('<fa-modifier ' + attr + '></fa-modifier>')($scope);
    };

    // faModifier must be an angular element so that .scope() can be called on it
    getModifier = function(faModifier) {
      var scope = faModifier.scope();
      var modifier = scope.isolate[scope.$id].modifier;
      return modifier;
    };

    getIsolate = function(faModifier) {
      var scope = faModifier.scope();
      return scope.isolate[scope.$id];
    };

    // getTransform is usually only called in the render loop, but invoke it
    // so that the Transform object calls its functions like rotateX, translate
    callGetTransform = function(faModifier) {
      var scope = faModifier.scope();
      var isolate = scope.isolate[scope.$id];
      isolate.getTransform();
    };
  }));

  it("should create an instance of Famo.us Modifier", function() {
    var Modifier = $famous['famous/core/Modifier'];
    var faModifier = compileFaModifier('fa-translate-x="300"');
    var modifier = getModifier(faModifier);
    expect(modifier instanceof Modifier).toBe(true);
  });

  it("should listen to 'registerChild' events from nested fa- directives, and add their data to fa-modifier's renderNode", function() {
    var RenderNode = $famous['famous/core/RenderNode'];
    var isolate;
    var modifierContent;
    $scope.$on('registerChild', function(event, data) {
      isolate = data;
    });
    var faModifier = $compile('<fa-modifier><fa-surface></fa-surface></fa-modifier>')($scope);
    //var children = faModifier[0].firstChild;
    expect(isolate.renderNode instanceof RenderNode).toBe(true);
  });

  /********************************************************************

    Transform attributes

  ********************************************************************/

  describe('should accept Transform attributes', function() {

    // generateTransformTests() should be called before the actual execution of
    // Jasmine, in order for the it() blocks to be created and ran in time.
    //
    // Ensure that the Famo.us Transform methods are called with the arguments
    // we expect.
    function generateTransformTests(attr, method, acceptableValues, expectedOutput) {

      // All values need to be strings that can $parse'd by Angular
      var values = {
        numbers: expectedOutput + '',
        arrays: '[' + expectedOutput + ']',
        functions: 'fn',
        expressions: 'fn()',
        transitionables: 'transitionable'
      };

      for (var valueType in values) {
        // If the valueType is one of the acceptableValues to test
        if (acceptableValues.indexOf(valueType) !== -1) {
          // Generate new psec.  Use closures to ensure that the current loop value
          // is passed to the it() block
          it(valueType, function(type) {
            return function() {
              var value = values[type];
              var faModifier = compileFaModifier(attr + '="' + value + '"');
              callGetTransform(faModifier);
              // Check the arguments that are passed to the Transform module
              var expectation = expect(TransformSpy[method]);
              // If the expectedOutput is an array, we must convert the array
              // into individual arguments to match the expected arguments
              if (expectedOutput instanceof Array) {
                expectation.toHaveBeenCalledWith.apply(expectation, expectedOutput);
              // if the expectedOutput is a number, just check that it matches
              } else if (typeof expectedOutput === 'number') {
                expectation.toHaveBeenCalledWith(expectedOutput);
              }
            };
          }(valueType));
        }
      }
    };

    describe('fa-rotate should accept', function() {
      beforeEach(function() {
        $scope.fn = function() {
          return [0, 0.5, -0.5];
        };
        $scope.transitionable = {
          get: function() { return [0, 0.5, -0.5]; }
        }
      });
      generateTransformTests(
        // Attribute
        'fa-rotate',
        // Transform method expected to be called
        'rotate',
        // Acceptable values
        ['arrays', 'functions', 'expressions'],
        // Expected output
        [0, 0.5, -0.5]
      );
    });

    describe('fa-rotate-x should accept', function() {
      beforeEach(function() {
        $scope.fn = function() {
          return 0.5;
        };
        $scope.transitionable = {
          get: function() { return 0.5; }
        }
      });
      generateTransformTests(
        // Attribute
        'fa-rotate-x',
        // Transform method expected to be called
        'rotateX',
        // Acceptable values
        ['numbers', 'functions', 'expressions'],
        // Expected output
        0.5
      );
    });

    describe('fa-rotate-y should accept', function() {
      beforeEach(function() {
        $scope.fn = function() {
          return 0.5;
        };
        $scope.transitionable = {
          get: function() { return 0.5; }
        }
      });
      generateTransformTests(
        // Attribute
        'fa-rotate-y',
        // Transform method expected to be called
        'rotateY',
        // Acceptable values
        ['numbers', 'functions', 'expressions'],
        // Expected output
        0.5
      );
    });

    describe('fa-rotate-z should accept', function() {
      beforeEach(function() {
        $scope.fn = function() {
          return -0.785;
        };
        $scope.transitionable = {
          get: function() { return -0.785; }
        }
      });
      generateTransformTests(
        // Attribute
        'fa-rotate-z',
        // Transform method expected to be called
        'rotateZ',
        // Acceptable values
        ['numbers', 'functions', 'expressions'],
        // Expected output
        -0.785
      );
    });

    describe('fa-scale should accept', function() {
      beforeEach(function() {
        $scope.fn = function() {
          return [0, 0.5, 1];
        };
        $scope.transitionable = {
          get: function() { return [0, 0.5, 1]; }
        }
      });
      generateTransformTests(
        // Attribute
        'fa-rotate-z',
        // Transform method expected to be called
        'rotateZ',
        // Acceptable values
        ['arrays', 'functions', 'expressions'],
        // Expected output
        [0, 0.5, 1]
      );
    });

    describe('fa-skew should accept', function() {
      beforeEach(function() {
        $scope.fn = function() {
          return -0.2;
        };
        $scope.transitionable = {
          get: function() { return -0.2; }
        }
      });
      generateTransformTests(
        // Attribute
        'fa-rotate-z',
        // Transform method expected to be called
        'rotateZ',
        // Acceptable values
        ['arrays', 'functions', 'expressions'],
        // Expected output
        -0.2
      );
    });

    describe('fa-transform should accept', function() {
      beforeEach(function() {
        $scope.fn = function() {
          return [0, 1, 0, 1];
        };
        $scope.transitionable = {
          get: function() { return [0, 1, 0, 1]; }
        }
      });
      generateTransformTests(
        // Attribute
        'fa-rotate-z',
        // Transform method expected to be called
        'rotateZ',
        // Acceptable values
        ['arrays', 'functions', 'expressions'],
        // Expected output
        [0, 1, 0, 1]
      );

      it('directly set the transform matrix', function() {
        $scope.matrix = [0, 1, 2, 3];
        var faModifier = compileFaModifier('fa-transform="matrix"');
        var args = ModifierSpy.calls.mostRecent().args[0];
        expect(args.transform()).toEqual($scope.matrix);
      });

      it('override any existing transform attributes', function() {
        $scope.matrix = [0, 1, 2, 3];
        // Add additional transform attribute that should be ignored
        var faModifier = compileFaModifier('fa-transform="matrix" fa-rotate="[0.5, 0.25, 0]"');
        var args = ModifierSpy.calls.mostRecent().args[0];
        expect(args.transform()).toEqual($scope.matrix);
      });
    });

    describe('fa-transform-order', function() {
      it('to control the transformation order', function() {
        $scope.order = ['translate', 'rotateZ'];
        var faModifier = compileFaModifier('fa-transform-order="order" fa-rotate-z="0.5" fa-translate="[30, 50, 1]"');
        var args = ModifierSpy.calls.mostRecent().args[0];
        var transformResult = TransformSpy['translate'].apply(this, [30, 50, 1]);
        args.transform();

        var firstArgument = TransformSpy.multiply.calls.first().args[0];
        expect(firstArgument).toEqual(transformResult);
      });

      it('if missing, will result in the transforms being in alphabetical order', function() {
        $scope.order = ['translate', 'rotateZ'];
        var faModifier = compileFaModifier('fa-rotate-z="0.5" fa-translate="[30, 50, 1]"');
        var args = ModifierSpy.calls.mostRecent().args[0];
        var transformResult = TransformSpy['translate'].apply(this, [30, 50, 1]);
        args.transform();

        var firstArgument = TransformSpy.multiply.calls.first().args[0];
        expect(firstArgument).not.toEqual(transformResult);
      });
    });

  });

  /********************************************************************

    General modifier attributes

  ********************************************************************/

  describe('should accept main Modifier attributes', function() {

    // Generate tests that ensure that the Modifier constructor is called with
    // the arguments we expect.
    function generateModifierTests(attr, method, acceptableValues, expectedOutput) {

      // All values need to be strings that can $parse'd by Angular
      var values = {
        numbers: expectedOutput + '',
        arrays: '[' + expectedOutput + ']',
        functions: 'fn',
        expressions: 'fn()',
        transitionables: 'transitionable'
      };

      // Generate tests.  Use closures to ensure that the current loop value
      // is passed to the it() block
      for (var valueType in values) {
        // If the valueType is one of the acceptableValues to test
        if (acceptableValues.indexOf(valueType) !== -1) {
          // Generate a new spec
          it(valueType, function(type) {
            return function() {
              var value = values[type];
              var faModifier = compileFaModifier(attr + '="' + value + '"');
              var args = ModifierSpy.calls.mostRecent().args[0];
              expect(args[method]()).toEqual(expectedOutput);
            };
          }(valueType));
        }
      }
    };

    describe('fa-size should accept', function() {
      beforeEach(function() {
        $scope.fn = function() {
          return [300, 200];
        };
        $scope.transitionable = {
          get: function() { return [300, 200]; }
        }
      });
      generateModifierTests(
        // Attribute
        'fa-size',
        // Transform method expected to be called
        'size',
        // Acceptable values
        ['arrays', 'functions', 'expressions', 'transitionables'],
        // Expected output
        [300, 200]
      );
    });

    describe('fa-opacity should accept', function() {
      beforeEach(function() {
        $scope.fn = function() {
          return [300, 200];
        };
        $scope.transitionable = {
          get: function() { return [300, 200]; }
        }
      });
      generateModifierTests(
        // Attribute
        'fa-opacity',
        // Transform method expected to be called
        'opacity',
        // Acceptable values
        ['arrays', 'functions', 'expressions', 'transitionables'],
        // Expected output
        [300, 200]
      );
    });

    describe('fa-origin should accept', function() {
      beforeEach(function() {
        $scope.fn = function() {
          return [0.5, 0.3];
        };
        $scope.transitionable = {
          get: function() { return [0.5, 0.3]; }
        }
      });
      generateModifierTests(
        // Attribute
        'fa-origin',
        // Transform method expected to be called
        'origin',
        // Acceptable values
        ['arrays', 'functions', 'expressions', 'transitionables'],
        // Expected output
        [0.5, 0.3]
      );
    });

    describe('fa-align should accept', function() {
      beforeEach(function() {
        $scope.fn = function() {
          return [0.5, 0.5];
        };
        $scope.transitionable = {
          get: function() { return [0.5, 0.5]; }
        }
      });
      generateModifierTests(
        // Attribute
        'fa-align',
        // Transform method expected to be called
        'align',
        // Acceptable values
        ['arrays', 'functions', 'expressions', 'transitionables'],
        // Expected output
        [0.5, 0.5]
      );
    });

  });

});

<|endoftext|>


<commit_before>import { expect } from "chai";
import { createVueField } from "../util";

import Vue from "vue";
import fieldVueMultiSelect from "src/fields/fieldVueMultiSelect.vue";

Vue.component("fieldVueMultiSelect", fieldVueMultiSelect);

// eslint-disable-next-line
let el, vm, field;

function createField(schema = {}, model = null, disabled = false, options) {
	[ el, vm, field ] = createVueField("fieldVueMultiSelect", schema, model, disabled, options);
}

describe("fieldVueMultiSelect.vue", () => {

	describe("check template", () => {
		let schema = {
			type: "vueMultiSelect",
			label: "Cities",
			model: "city",
			multiSelect: false,
			required: false,
			values: [
				"London",
				"Paris",
				"Rome",
				"Berlin"
			],
			selectOptions: {}
		};
		let model = { city: "Paris" };
		let input;

		before( () => {
			createField(schema, model, false);
			input = el.getElementsByTagName("select")[0];
		});

		it("should contain a select element", () => {
			expect(field).to.be.exist;
			expect(field.$el).to.be.exist;

			expect(input).to.be.defined;
			// expect(input.classList.contains("form-control")).to.be.false;
			// expect(input.disabled).to.be.false;
		});
	});
});<commit_msg>test: improve unit testing of vueMultiSelect<commit_after>import { expect } from "chai";
import { createVueField, trigger } from "../util";

import Vue from "vue";
import fieldVueMultiSelect from "src/fields/fieldVueMultiSelect.vue";

Vue.component("fieldVueMultiSelect", fieldVueMultiSelect);

// eslint-disable-next-line
let el, vm, field;

function createField(schema = {}, model = null, disabled = false, options) {
	[ el, vm, field ] = createVueField("fieldVueMultiSelect", schema, model, disabled, options);
}

describe("fieldVueMultiSelect.vue", () => {

	describe("check template", () => {
		let schema = {
			type: "vueMultiSelect",
			label: "Cities",
			model: "city",
			multiSelect: true,
			required: false,
			values: [
				"London",
				"Paris",
				"Rome",
				"Berlin"
			],
			selectOptions: {}
		};
		let model = { city: "Paris" };
		let input;

		before( () => {
			createField(schema, model, false);
			vm.$appendTo(document.body);
			input = el.querySelector(".multiselect");
		});

		it("should contain a select element", () => {
			expect(field).to.be.exist;
			expect(field.$el).to.be.exist;

			expect(input).to.be.defined;
			expect(input.classList.contains("form-control")).to.be.false;
			expect(input.classList.contains("multiselect--disabled")).to.be.false;
		});

		it("should contain option elements", () => {
			let options = input.querySelectorAll("li.multiselect__option");
			console.log(options);
			expect(options.length).to.be.equal(schema.values.length);
			expect(options[1].querySelector("span").textContent).to.be.equal("Paris");
			expect(options[1].classList.contains("multiselect__option--selected")).to.be.true;
		});

		it("should set disabled", (done) => {
			field.disabled = true;
			vm.$nextTick( () => {
				expect(input.classList.contains("multiselect--disabled")).to.be.true;
				field.disabled = false;
				done();
			});
		});

		it("input value should be the model value after changed", (done) => {
			model.city = "Rome";
			vm.$nextTick( () => {
				let options = input.querySelectorAll("li.multiselect__option");
				expect(options[2].querySelector("span").textContent).to.be.equal("Rome");
				expect(options[2].classList.contains("multiselect__option--selected")).to.be.true;
				done();
			});
		});

		it("input value should be the model value after changed (multiselection)", (done) => {
			model.city = ["Paris","Rome"];
			vm.$nextTick( () => {
				let options = input.querySelectorAll("li.multiselect__option");
				expect(options[1].querySelector("span").textContent).to.be.equal("Paris");
				expect(options[1].classList.contains("multiselect__option--selected")).to.be.true;
				expect(options[2].querySelector("span").textContent).to.be.equal("Rome");
				expect(options[2].classList.contains("multiselect__option--selected")).to.be.true;
				done();
			});
		});

		it("model value should be the input value if changed", (done) => {
			let options = input.querySelectorAll("li.multiselect__option");
			trigger(options[2], "mousedown");

			vm.$nextTick( () => {
				expect(model.city[0]).to.be.equal("Paris");
				done();
			});

		});
	});
});<|endoftext|>


<commit_before>/* global browser, expect, capabilities, $ */
const path = require('path')
const { selectFakeFile, supportsChooseFile } = require('../utils')

const testURL = 'http://localhost:4567/transloadit'

function unhideTheInput () {
  var input = document.querySelector('#uppy-transloadit .uppy-Dashboard-input')
  input.removeAttribute('hidden')
  input.removeAttribute('aria-hidden')
  input.removeAttribute('tabindex')
}

function setTransloaditKeyAndInit (transloaditKey) {
  window.initUppyTransloadit(transloaditKey)
}

describe('Transloadit file processing', () => {
  beforeEach(() => {
    browser.url(testURL)
    browser.execute(setTransloaditKeyAndInit, process.env.TRANSLOADIT_KEY)
  })

  it('should upload a file to Transloadit and crop it', () => {
    const inputPath = '#uppy-transloadit .uppy-Dashboard-input'
    const resultPath = '#uppy-result'

    $(inputPath).waitForExist()

    if (supportsChooseFile(capabilities)) {
      browser.execute(unhideTheInput)
      browser.chooseFile(inputPath, path.join(__dirname, '../../resources/image.jpg'))
    } else {
      browser.execute(selectFakeFile, 'uppyTransloadit')
    }
    browser.pause(15000)
    // $('.uppy-StatusBar-actionBtn--upload').click()
    // $(resultPath).waitForExist()
    const text = browser.getText(resultPath)
    expect(text).to.be.equal('ok')
  })
})
<commit_msg>skip test if TRANSLOADIT_KEY is not set, use waitForExist<commit_after>/* global browser, expect, capabilities, $ */
const path = require('path')
const { selectFakeFile, supportsChooseFile } = require('../utils')

const testURL = 'http://localhost:4567/transloadit'

function unhideTheInput () {
  var input = document.querySelector('#uppy-transloadit .uppy-Dashboard-input')
  input.removeAttribute('hidden')
  input.removeAttribute('aria-hidden')
  input.removeAttribute('tabindex')
}

function setTransloaditKeyAndInit (transloaditKey) {
  window.initUppyTransloadit(transloaditKey)
}

describe('Transloadit file processing', () => {
  beforeEach(() => {
    browser.url(testURL)
  })

  it('should upload a file to Transloadit and crop it', () => {
    const transloaditKey = process.env.TRANSLOADIT_KEY
    if (transloaditKey === undefined) {
      console.log('skipping Transloadit integration test')
      return this.skip()
    }
    browser.execute(setTransloaditKeyAndInit, transloaditKey)

    const inputPath = '#uppy-transloadit .uppy-Dashboard-input'
    const resultPath = '#uppy-result'

    $(inputPath).waitForExist()

    if (supportsChooseFile(capabilities)) {
      browser.execute(unhideTheInput)
      browser.chooseFile(inputPath, path.join(__dirname, '../../resources/image.jpg'))
    } else {
      browser.execute(selectFakeFile, 'uppyTransloadit')
    }
    // browser.pause(15000)
    // $('.uppy-StatusBar-actionBtn--upload').click()
    $(resultPath).waitForExist(15000)
    const text = browser.getText(resultPath)
    expect(text).to.be.equal('ok')
  })
})
<|endoftext|>


<commit_before>var path = require("path");
var webpack = require("webpack");
var Config = require("webpack-config").Config;
var CompressionPlugin = require("compression-webpack-plugin");
var CommonsChunkPlugin = require("webpack").optimize.CommonsChunkPlugin;

module.exports = new Config().extend("conf/webpack.prod.config.js").merge({
    entry: {
        "browser-es5-commonjs": "./src/browser/index-commonjs",
        "example": "./example/browser-example.ts",
        "performance-measurement": "./example/performance-measurement.ts"
    },
    output: {
        path: path.resolve(__dirname, "../gh-pages-out/artifacts")
    },
    devtool: "#source-map",
    plugins: [
        new CommonsChunkPlugin("browser")
    ]
});<commit_msg>Fix gh-pages build<commit_after>var path = require("path");
var webpack = require("webpack");
var Config = require("webpack-config").Config;
var CompressionPlugin = require("compression-webpack-plugin");
var CommonsChunkPlugin = require("webpack").optimize.CommonsChunkPlugin;

module.exports = new Config().extend("conf/webpack.prod.config.js").merge({
    entry: {
        "browser-es5-commonjs": "./src/api/browser-commonjs",
        "example": "./example/browser-example.ts",
        "performance-measurement": "./example/performance-measurement.ts"
    },
    output: {
        path: path.resolve(__dirname, "../gh-pages-out/artifacts")
    },
    module: {
        noParse: [ /benchmark\/benchmark\.js/ ]
    },
    devtool: "#source-map",
    plugins: [
        new CommonsChunkPlugin("browser")
    ]
});<|endoftext|>


<commit_before>/*global define*/
define(['fx-m-c/config/config', 'fx-m-c/config/config-default'],function (C,DC) {

    'use strict';

    return {

        fenix_ui_map: {

            plugins: {
                disclaimerfao: true,
                geosearch: true,
                mouseposition: false,
                controlloading : true,
                zoomcontrol: 'bottomright'
            },
            guiController: {
                overlay: false,
                baselayer: true,
                wmsLoader: false
            },
            gui: {
                disclaimerfao: true
            }
        },
        leaflet: {
            zoomControl: false,
            attributionControl: false,
            minZoom: 1
        },
        layers: {
            boundary: {
                layers: 'fenix:gaul0_line_3857',
                layertitle: 'Country Boundaries',
                // TODO: remove the url to wms
                urlWMS: ( C.SERVER || DC.SERVER ) + '/geoserver-demo',
                opacity: '0.9',
                lang: 'en'
            },
            gaul0: {
                layers: 'fenix:gaul0_faostat_3857',
                // TODO: remove the url to wms
                urlWMS: ( C.SERVER || DC.SERVER ) + '/geoserver-demo',
                opacity: '0.9',
                joincolumn: 'adm0_code',
                joincolumnlabel: 'areanamee',
                layertype: 'JOIN',
                jointype: 'shaded',
                openlegend: true,
                defaultgfi: true,
                colorramp: 'YlGn',
                lang: 'en'
            }
        },
        url: {
            wms: C.WMS_URL | DC.WMS_URL
        },
        geoSubject: 'geo',
        valueSubject: 'value',
        // measurement unit
        muSubject: null,

        // Mapping with the
        join: {

            layerMapping: {
                gaul0: {
                    layers: 'fenix:gaul0_3857',
                    joincolumn: 'adm0_code',
                    joincolumnlabel: 'adm0_name'
                },
                gaul1: {
                    layers: 'fenix:gaul1_3857',
                    joincolumn: 'adm1_code',
                    joincolumnlabel: 'adm1_name'
                },

                gaul_adm1: {
                    layers: 'fenix:gaul1_3857',
                    joincolumn: 'adm1_code',
                    joincolumnlabel: 'adm1_name'
                },

                faostat_countrycodes: {
                    layers: 'fenix:gaul0_faostat_3857',
                    joincolumn: 'faost_code',
                    joincolumnlabel: 'areanamee',
                },
                faostat_countries: {
                    layers: 'fenix:gaul0_faostat_3857',
                    joincolumn: 'faost_code',
                    joincolumnlabel: 'areanamee',
                },
                gaul: {
                    layers: 'fenix:gaul1_3857',
                    joincolumn: 'adm1_code',
                    joincolumnlabel: 'adm1_name'
                },

                gaul1_afg: {
                    layers: 'fenix:gaul1_3857',
                    joincolumn: 'adm1_code',
                    joincolumnlabel: 'adm1_name'
                },
                iso3: {
                    layers: 'fenix:gaul0_faostat3_3857',
                    joincolumn: 'iso3',
                    joincolumnlabel: 'areanamee'
                }
            },
            style: {
                layertype: 'JOIN',
                jointype: 'shaded',
                defaultgfi: true,
                openlegend: true,
                lang: 'EN',
                opacity: '0.7',
                colorramp: 'Greens',
                decimalvalues: 2
            }
        }
        // TODO: add boundaries option
    };
});<commit_msg>mappatura uae_gaul Chart<commit_after>/*global define*/
define(['fx-m-c/config/config', 'fx-m-c/config/config-default'],function (C,DC) {

    'use strict';

    return {

        fenix_ui_map: {

            plugins: {
                disclaimerfao: true,
                geosearch: true,
                mouseposition: false,
                controlloading : true,
                zoomcontrol: 'bottomright'
            },
            guiController: {
                overlay: false,
                baselayer: true,
                wmsLoader: false
            },
            gui: {
                disclaimerfao: true
            }
        },
        leaflet: {
            zoomControl: false,
            attributionControl: false,
            minZoom: 1
        },
        layers: {
            boundary: {
                layers: 'fenix:gaul0_line_3857',
                layertitle: 'Country Boundaries',
                // TODO: remove the url to wms
                urlWMS: ( C.SERVER || DC.SERVER ) + '/geoserver-demo',
                opacity: '0.9',
                lang: 'en'
            },
            gaul0: {
                layers: 'fenix:gaul0_faostat_3857',
                // TODO: remove the url to wms
                urlWMS: ( C.SERVER || DC.SERVER ) + '/geoserver-demo',
                opacity: '0.9',
                joincolumn: 'adm0_code',
                joincolumnlabel: 'areanamee',
                layertype: 'JOIN',
                jointype: 'shaded',
                openlegend: true,
                defaultgfi: true,
                colorramp: 'YlGn',
                lang: 'en'
            }
        },
        url: {
            wms: C.WMS_URL ||  DC.WMS_URL
        },
        geoSubject: 'geo',
        valueSubject: 'value',
        // measurement unit
        muSubject: null,

        // Mapping with the
        join: {

            layerMapping: {
                gaul0: {
                    layers: 'fenix:gaul0_3857',
                    joincolumn: 'adm0_code',
                    joincolumnlabel: 'adm0_name'
                },
                gaul1: {
                    layers: 'fenix:gaul1_3857',
                    joincolumn: 'adm1_code',
                    joincolumnlabel: 'adm1_name'
                },
                uae_gaul: {
                    layers: 'fenix:gaul1_3857',
                    joincolumn: 'adm1_code',
                    joincolumnlabel: 'adm1_name'
                },

                gaul_adm1: {
                    layers: 'fenix:gaul1_3857',
                    joincolumn: 'adm1_code',
                    joincolumnlabel: 'adm1_name'
                },

                faostat_countrycodes: {
                    layers: 'fenix:gaul0_faostat_3857',
                    joincolumn: 'faost_code',
                    joincolumnlabel: 'areanamee',
                },
                faostat_countries: {
                    layers: 'fenix:gaul0_faostat_3857',
                    joincolumn: 'faost_code',
                    joincolumnlabel: 'areanamee',
                },
                gaul: {
                    layers: 'fenix:gaul1_3857',
                    joincolumn: 'adm1_code',
                    joincolumnlabel: 'adm1_name'
                },

                gaul1_afg: {
                    layers: 'fenix:gaul1_3857',
                    joincolumn: 'adm1_code',
                    joincolumnlabel: 'adm1_name'
                },
                iso3: {
                    layers: 'fenix:gaul0_faostat3_3857',
                    joincolumn: 'iso3',
                    joincolumnlabel: 'areanamee'
                }
            },
            style: {
                layertype: 'JOIN',
                jointype: 'shaded',
                defaultgfi: true,
                openlegend: true,
                lang: 'EN',
                opacity: '0.7',
                colorramp: 'Greens',
                decimalvalues: 2
            }
        }
        // TODO: add boundaries option
    };
});<|endoftext|>


<commit_before>define([
    "jquery",
    "../core/logger",
    "../registry",
    "../utils",
    "./inject",
    "pagedown",
    "pagedown-extra"
], function($, logger, registry, utils, inject) {
    var log = logger.getLogger("pat.markdown");

    var converter = Markdown.getSanitizingConverter();
    Markdown.Extra.init(converter, {extensions: "all"});

    var _ = {
        name: "markdown",
        trigger: ".pat-markdown",
        url_re: /\.md$/,

        init: function($el) {
            return $el.each(function() {
                var $this = $(this),
                    source = $this.is(":input") ? this.value : $this.text(),
                    $rendering = _._render(source);
                $rendering.replaceAll($this);
            });
        },

        _render: function(text) {
            var $rendering = $("<div/>");
            $rendering.html(converter.makeHtml(text));
            return $rendering;
        }
    };

    // XXX: Hack
    $("a.pat-inject").on("patterns-inject-triggered.pat-markdown", function() {
        var $this = $(this), cfgs = $this.data("patterns.inject");

        if (_.url_re.test(cfgs[0].url)) {
            cfgs.forEach(function(cfg) {
                cfg.dataType = "markdown";
            });
        }
    });

    inject.registerTypeHandler("markdown", {
        sources: function(cfgs, data) {
            var $rendering, source, header;
            return cfgs.map(function(cfg) {
                source = data;
                if (cfg.source && (header=/^(#+)\s+(.*)/.exec(cfg.source)) !== null) {
                    var level = header[1].length,
                        text = utils.escapeRegExp(header[2]),
                        matcher = "^#{@LEVEL@}\\s+@TEXT@(.|\\n)*?^(?=#{1,@LEVEL@})";
                    matcher = matcher.replace(/@LEVEL@/g, level).replace(/@TEXT@/g, text);
                    matcher = new RegExp(matcher, "m");
                    source = matcher.exec(source);
                    if (source === null) {
                        log.warn("Could not find section \"" + cfg.source + "\" in " + cfg.url);
                        return $("<div/>").attr("data-src", cfg.url);
                    }
                    source = source[0]+"\n";  // Needed for some markdown syntax
                }
                $rendering = _._render(source);
                $rendering.attr("data-src", cfg.url);
                return $rendering;
            });
        }
    });

    registry.register(_);
    return _;
});
<commit_msg>markdown extraction needs a following heading with same level<commit_after>define([
    "jquery",
    "../core/logger",
    "../registry",
    "../utils",
    "./inject",
    "pagedown",
    "pagedown-extra"
], function($, logger, registry, utils, inject) {
    var log = logger.getLogger("pat.markdown");

    var converter = Markdown.getSanitizingConverter();
    Markdown.Extra.init(converter, {extensions: "all"});

    var _ = {
        name: "markdown",
        trigger: ".pat-markdown",
        url_re: /\.md$/,

        init: function($el) {
            return $el.each(function() {
                var $this = $(this),
                    source = $this.is(":input") ? this.value : $this.text(),
                    $rendering = _._render(source);
                $rendering.replaceAll($this);
            });
        },

        _render: function(text) {
            var $rendering = $("<div/>");
            $rendering.html(converter.makeHtml(text));
            return $rendering;
        }
    };

    // XXX: Hack
    $("a.pat-inject").on("patterns-inject-triggered.pat-markdown", function() {
        var $this = $(this), cfgs = $this.data("patterns.inject");

        if (_.url_re.test(cfgs[0].url)) {
            cfgs.forEach(function(cfg) {
                cfg.dataType = "markdown";
            });
        }
    });

    inject.registerTypeHandler("markdown", {
        sources: function(cfgs, data) {
            var $rendering, source, header;
            return cfgs.map(function(cfg) {
                source = data;
                if (cfg.source && (header=/^(#+)\s+(.*)/.exec(cfg.source)) !== null) {
                    var level = header[1].length,
                        text = utils.escapeRegExp(header[2]),
                        matcher = "^#{@LEVEL@}\\s+@TEXT@(.|\\n)*?^(?=#{1,@LEVEL@})";
                    matcher = matcher.replace(/@LEVEL@/g, level).replace(/@TEXT@/g, text);
                    matcher = new RegExp(matcher, "m");
                    source = source + "\n\n" + Array(level+1).join("#") + ' Hail Eris.';
                    source = matcher.exec(source);
                    if (source === null) {
                        log.warn("Could not find section \"" + cfg.source + "\" in " + cfg.url);
                        return $("<div/>").attr("data-src", cfg.url);
                    }
                    source = source[0]+"\n";  // Needed for some markdown syntax
                }
                $rendering = _._render(source);
                $rendering.attr("data-src", cfg.url);
                return $rendering;
            });
        }
    });

    registry.register(_);
    return _;
});
<|endoftext|>


<commit_before>var config = require('./config.json');
process.env.NODE_ENV = config['server']['mode'];

var logger = require('./../../Common/sources/logger'),
	express = require('express'),
	http = require('http'),
	https = require('https'),
	fs = require("fs"),
	docsCoServer = require('./DocsCoServer'),
	app = express(),
	server = null;

if (config['ssl']) {
	var privateKey = fs.readFileSync(config['ssl']['key']).toString(),
		certificate = fs.readFileSync(config['ssl']['cert']).toString(),
		options = {key: privateKey, cert:certificate};

	server = https.createServer(options, app);
} else {
	server = http.createServer(app);
}

app.configure('development', function() {
    app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

app.configure('production', function() {
    app.use(express.errorHandler());
});

docsCoServer.install(server, function() {
	server.listen(config['server']['port'], function() {
		logger.info("Express server listening on port %d in %s mode", config['server']['port'], app.settings.env);
	});

	app.get('/index.html', function(req, res) {
		res.send('Server is functioning normally');
	});

	app.post('/RemoveChanges.ashx', function(req, res) {
		docsCoServer.removeChanges(req.query.id);
		res.send('Remove success');
	});

	app.get('/CommandService.ashx', function(req, res) {
		var result = docsCoServer.commandFromServer(req.query);

		res.send(JSON.stringify({'key': req.query.key, 'error': result}));
	});
});
<commit_msg>CommandService.ashx response type + length<commit_after>var config = require('./config.json');
process.env.NODE_ENV = config['server']['mode'];

var logger = require('./../../Common/sources/logger'),
	express = require('express'),
	http = require('http'),
	https = require('https'),
	fs = require("fs"),
	docsCoServer = require('./DocsCoServer'),
	app = express(),
	server = null;

if (config['ssl']) {
	var privateKey = fs.readFileSync(config['ssl']['key']).toString(),
		certificate = fs.readFileSync(config['ssl']['cert']).toString(),
		options = {key: privateKey, cert:certificate};

	server = https.createServer(options, app);
} else {
	server = http.createServer(app);
}

app.configure('development', function() {
    app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

app.configure('production', function() {
    app.use(express.errorHandler());
});

docsCoServer.install(server, function() {
	server.listen(config['server']['port'], function() {
		logger.info("Express server listening on port %d in %s mode", config['server']['port'], app.settings.env);
	});

	app.get('/index.html', function(req, res) {
		res.send('Server is functioning normally');
	});

	app.post('/RemoveChanges.ashx', function(req, res) {
		docsCoServer.removeChanges(req.query.id);
		res.send('Remove success');
	});

	app.get('/CommandService.ashx', function(req, res) {
		var result = docsCoServer.commandFromServer(req.query);
		result = JSON.stringify({'key': req.query.key, 'error': result});

		res.setHeader('Content-Type', 'application/json');
		res.setHeader('Content-Length', result.length);
		res.send(result);
	});
});
<|endoftext|>


<commit_before>/* Copyright (c) 2012 HyeonJe Jun (http://github.com/noraesae)
 * Licensed under the MIT License
 */
((function($) {
    $.fn.perfectScrollbar = function(option) {
        if(option === 'update') {
            if($(this).data('perfect_scrollbar_update')) {
                $(this).data('perfect_scrollbar_update')();
            }
            return $(this);
        }
        else if(option === 'destroy') {
            if($(this).data('perfect_scrollbar_destroy')) {
                $(this).data('perfect_scrollbar_destroy')();
            }
            return $(this);
        }

        if($(this).data('perfect_scrollbar')) {
            // if there's already perfect_scrollbar
            return $(this).data('perfect_scrollbar');
        }

        var $this = $(this).addClass('ps-container'),
            $content = $(this).children(),
            $scrollbar_x = $("

").appendTo($this),
            $scrollbar_y = $("

").appendTo($this),
            container_width,
            container_height,
            content_width,
            content_height,
            scrollbar_x_width,
            scrollbar_x_left,
            scrollbar_x_bottom = parseInt($scrollbar_x.css('bottom')),
            scrollbar_y_height,
            scrollbar_y_top,
            scrollbar_y_right = parseInt($scrollbar_y.css('right'));

        var updateContentScrollTop = function() {
            var scroll_top = parseInt(scrollbar_y_top * content_height / container_height);
            $this.scrollTop(scroll_top);
            $scrollbar_x.css({bottom: scrollbar_x_bottom - scroll_top});
        };

        var updateContentScrollLeft = function() {
            var scroll_left = parseInt(scrollbar_x_left * content_width / container_width);
            $this.scrollLeft(scroll_left);
            $scrollbar_y.css({right: scrollbar_y_right - scroll_left});
        };

        var updateBarSizeAndPosition = function() {
            container_width = $this.width();
            container_height = $this.height();
            content_width = $content.width();
            content_height = $content.height();
            if(container_width < content_width) {
                scrollbar_x_width = parseInt(container_width * container_width / content_width);
                scrollbar_x_left = parseInt($this.scrollLeft() * container_width / content_width);
            }
            else {
                scrollbar_x_width = 0;
                scrollbar_x_left = 0;
                $this.scrollLeft(0);
            }
            if(container_height < content_height) {
                scrollbar_y_height = parseInt(container_height * container_height / content_height);
                scrollbar_y_top = parseInt($this.scrollTop() * container_height / content_height);
            }
            else {
                scrollbar_y_height = 0;
                scrollbar_y_left = 0;
                $this.scrollTop(0);
            }

            $scrollbar_x.css({left: scrollbar_x_left + $this.scrollLeft(), bottom: scrollbar_x_bottom - $this.scrollTop(), width: scrollbar_x_width});
            $scrollbar_y.css({top: scrollbar_y_top + $this.scrollTop(), right: scrollbar_y_right - $this.scrollLeft(), height: scrollbar_y_height});
        };

        var moveBarX = function(current_left, delta_x) {
            var new_left = current_left + delta_x,
                max_left = container_width - scrollbar_x_width;

            if(new_left < 0) {
                scrollbar_x_left = 0;
            }
            else if(new_left > max_left) {
                scrollbar_x_left = max_left;
            }
            else {
                scrollbar_x_left = new_left;
            }
            $scrollbar_x.css({left: scrollbar_x_left + $this.scrollLeft()});
        }

        var moveBarY = function(current_top, delta_y) {
            var new_top = current_top + delta_y,
                max_top = container_height - scrollbar_y_height;

            if(new_top < 0) {
                scrollbar_y_top = 0;
            }
            else if(new_top > max_top) {
                scrollbar_y_top = max_top;
            }
            else {
                scrollbar_y_top = new_top;
            }
            $scrollbar_y.css({top: scrollbar_y_top + $this.scrollTop()});
        };

        var bindMouseScrollXHandler = function() {
            var current_left,
                current_page_x;

            $scrollbar_x.bind('mousedown.perfect-scroll', function(e) {
                current_page_x = e.pageX;
                current_left = $scrollbar_x.position().left;
                $scrollbar_x.addClass('in-scrolling');
                e.stopPropagation();
                e.preventDefault();
            });

            $(document).bind('mousemove.perfect-scroll', function(e) {
                if($scrollbar_x.hasClass('in-scrolling')) {
                    moveBarX(current_left, e.pageX - current_page_x);
                    updateContentScrollLeft();
                    e.stopPropagation();
                    e.preventDefault();
                }
            });

            $(document).bind('mouseup.perfect-scroll', function(e) {
                if($scrollbar_x.hasClass('in-scrolling')) {
                    $scrollbar_x.removeClass('in-scrolling');
                }
            });
        };

        var bindMouseScrollYHandler = function() {
            var current_top,
                current_page_y;

            $scrollbar_y.bind('mousedown.perfect-scroll', function(e) {
                current_page_y = e.pageY;
                current_top = $scrollbar_y.position().top;
                $scrollbar_y.addClass('in-scrolling');
                e.stopPropagation();
                e.preventDefault();
            });

            $(document).bind('mousemove.perfect-scroll', function(e) {
                if($scrollbar_y.hasClass('in-scrolling')) {
                    moveBarY(current_top, e.pageY - current_page_y);
                    updateContentScrollTop();
                    e.stopPropagation();
                    e.preventDefault();
                }
            });

            $(document).bind('mouseup.perfect-scroll', function(e) {
                if($scrollbar_y.hasClass('in-scrolling')) {
                    $scrollbar_y.removeClass('in-scrolling');
                }
            });
        };

        // bind handlers
        var bindMouseWheelHandler = function() {
            $this.mousewheel(function(e, delta, deltaX, deltaY) {
                $this.scrollTop($this.scrollTop() - (deltaY * 10));
                $this.scrollLeft($this.scrollLeft() + (deltaX * 10));

                // update bar position
                updateBarSizeAndPosition();

                if(content_height > container_height || content_width > container_width) {
                    e.preventDefault();
                }
            });
        };

        // bind mobile touch handler
        var bindMobileTouchHandler = function() {
            var applyTouchMove = function(difference_x, difference_y) {
                $this.scrollTop($this.scrollTop() - difference_y);
                $this.scrollLeft($this.scrollLeft() - difference_x);

                // update bar position
                updateBarSizeAndPosition();
            };

            var start_coords = {},
                start_time = 0,
                speed = {},
                breaking_process = null;

            $this.bind("touchstart.perfect-scroll", function(e) {
                var touch = e.originalEvent.targetTouches[0];

                start_coords.pageX = touch.pageX;
                start_coords.pageY = touch.pageY;

                start_time = (new Date()).getTime();

                if (breaking_process !== null) {
                    clearInterval(breaking_process);
                }
            });
            $this.bind("touchmove.perfect-scroll", function(e) {
                var touch = e.originalEvent.targetTouches[0];

                var current_coords = {};
                current_coords.pageX = touch.pageX;
                current_coords.pageY = touch.pageY;

                var difference_x = current_coords.pageX - start_coords.pageX,
                    difference_y = current_coords.pageY - start_coords.pageY;

                applyTouchMove(difference_x, difference_y);
                start_coords = current_coords;

                var current_time = (new Date()).getTime();
                speed.x = difference_x / (current_time - start_time);
                speed.y = difference_y / (current_time - start_time);
                start_time = current_time;

                e.preventDefault();
            });
            $this.bind("touchend.perfect-scroll", function(e) {
                breaking_process = setInterval(function() {
                    if(Math.abs(speed.x) < 0.01 && Math.abs(speed.y) < 0.01) {
                        clearInterval(breaking_process);
                        return;
                    }

                    applyTouchMove(speed.x * 30, speed.y * 30);

                    speed.x *= 0.8;
                    speed.y *= 0.8;
                }, 10);
            });
        };

        var destroy = function() {
            $scrollbar_x.remove();
            $scrollbar_y.remove();
            $this.unbind('mousewheel');
            $this.unbind('touchstart.perfect-scroll');
            $this.unbind('touchmove.perfect-scroll');
            $this.unbind('touchend.perfect-scroll');
            $(window).unbind('mousemove.perfect-scroll');
            $(window).unbind('mouseup.perfect-scroll');
            $this.data('perfect_scrollbar', null);
            $this.data('perfect_scrollbar_update', null);
            $this.data('perfect_scrollbar_destroy', null);
        };

        var isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent);

        var initialize = function() {
            updateBarSizeAndPosition();
            bindMouseScrollXHandler();
            bindMouseScrollYHandler();
            if(isMobile) bindMobileTouchHandler();
            if($this.mousewheel) bindMouseWheelHandler();
            $this.data('perfect_scrollbar', $this);
            $this.data('perfect_scrollbar_update', updateBarSizeAndPosition);
            $this.data('perfect_scrollbar_destroy', destroy);
        };

        // initialize
        initialize();

        return $this;
    };
})(jQuery));
<commit_msg>Take into account padding and margins on content<commit_after>/* Copyright (c) 2012 HyeonJe Jun (http://github.com/noraesae)
 * Licensed under the MIT License
 */
((function($) {
    $.fn.perfectScrollbar = function(option) {
        if(option === 'update') {
            if($(this).data('perfect_scrollbar_update')) {
                $(this).data('perfect_scrollbar_update')();
            }
            return $(this);
        }
        else if(option === 'destroy') {
            if($(this).data('perfect_scrollbar_destroy')) {
                $(this).data('perfect_scrollbar_destroy')();
            }
            return $(this);
        }

        if($(this).data('perfect_scrollbar')) {
            // if there's already perfect_scrollbar
            return $(this).data('perfect_scrollbar');
        }

        var $this = $(this).addClass('ps-container'),
            $content = $(this).children(),
            $scrollbar_x = $("

").appendTo($this),
            $scrollbar_y = $("

").appendTo($this),
            container_width,
            container_height,
            content_width,
            content_height,
            scrollbar_x_width,
            scrollbar_x_left,
            scrollbar_x_bottom = parseInt($scrollbar_x.css('bottom')),
            scrollbar_y_height,
            scrollbar_y_top,
            scrollbar_y_right = parseInt($scrollbar_y.css('right'));

        var updateContentScrollTop = function() {
            var scroll_top = parseInt(scrollbar_y_top * content_height / container_height);
            $this.scrollTop(scroll_top);
            $scrollbar_x.css({bottom: scrollbar_x_bottom - scroll_top});
        };

        var updateContentScrollLeft = function() {
            var scroll_left = parseInt(scrollbar_x_left * content_width / container_width);
            $this.scrollLeft(scroll_left);
            $scrollbar_y.css({right: scrollbar_y_right - scroll_left});
        };

        var updateBarSizeAndPosition = function() {
            container_width = $this.width();
            container_height = $this.height();
            content_width = $content.outerWidth(false);
            content_height = $content.outerHeight(false);
            if(container_width < content_width) {
                scrollbar_x_width = parseInt(container_width * container_width / content_width);
                scrollbar_x_left = parseInt($this.scrollLeft() * container_width / content_width);
            }
            else {
                scrollbar_x_width = 0;
                scrollbar_x_left = 0;
                $this.scrollLeft(0);
            }
            if(container_height < content_height) {
                scrollbar_y_height = parseInt(container_height * container_height / content_height);
                scrollbar_y_top = parseInt($this.scrollTop() * container_height / content_height);
            }
            else {
                scrollbar_y_height = 0;
                scrollbar_y_left = 0;
                $this.scrollTop(0);
            }

            $scrollbar_x.css({left: scrollbar_x_left + $this.scrollLeft(), bottom: scrollbar_x_bottom - $this.scrollTop(), width: scrollbar_x_width});
            $scrollbar_y.css({top: scrollbar_y_top + $this.scrollTop(), right: scrollbar_y_right - $this.scrollLeft(), height: scrollbar_y_height});
        };

        var moveBarX = function(current_left, delta_x) {
            var new_left = current_left + delta_x,
                max_left = container_width - scrollbar_x_width;

            if(new_left < 0) {
                scrollbar_x_left = 0;
            }
            else if(new_left > max_left) {
                scrollbar_x_left = max_left;
            }
            else {
                scrollbar_x_left = new_left;
            }
            $scrollbar_x.css({left: scrollbar_x_left + $this.scrollLeft()});
        }

        var moveBarY = function(current_top, delta_y) {
            var new_top = current_top + delta_y,
                max_top = container_height - scrollbar_y_height;

            if(new_top < 0) {
                scrollbar_y_top = 0;
            }
            else if(new_top > max_top) {
                scrollbar_y_top = max_top;
            }
            else {
                scrollbar_y_top = new_top;
            }
            $scrollbar_y.css({top: scrollbar_y_top + $this.scrollTop()});
        };

        var bindMouseScrollXHandler = function() {
            var current_left,
                current_page_x;

            $scrollbar_x.bind('mousedown.perfect-scroll', function(e) {
                current_page_x = e.pageX;
                current_left = $scrollbar_x.position().left;
                $scrollbar_x.addClass('in-scrolling');
                e.stopPropagation();
                e.preventDefault();
            });

            $(document).bind('mousemove.perfect-scroll', function(e) {
                if($scrollbar_x.hasClass('in-scrolling')) {
                    moveBarX(current_left, e.pageX - current_page_x);
                    updateContentScrollLeft();
                    e.stopPropagation();
                    e.preventDefault();
                }
            });

            $(document).bind('mouseup.perfect-scroll', function(e) {
                if($scrollbar_x.hasClass('in-scrolling')) {
                    $scrollbar_x.removeClass('in-scrolling');
                }
            });
        };

        var bindMouseScrollYHandler = function() {
            var current_top,
                current_page_y;

            $scrollbar_y.bind('mousedown.perfect-scroll', function(e) {
                current_page_y = e.pageY;
                current_top = $scrollbar_y.position().top;
                $scrollbar_y.addClass('in-scrolling');
                e.stopPropagation();
                e.preventDefault();
            });

            $(document).bind('mousemove.perfect-scroll', function(e) {
                if($scrollbar_y.hasClass('in-scrolling')) {
                    moveBarY(current_top, e.pageY - current_page_y);
                    updateContentScrollTop();
                    e.stopPropagation();
                    e.preventDefault();
                }
            });

            $(document).bind('mouseup.perfect-scroll', function(e) {
                if($scrollbar_y.hasClass('in-scrolling')) {
                    $scrollbar_y.removeClass('in-scrolling');
                }
            });
        };

        // bind handlers
        var bindMouseWheelHandler = function() {
            $this.mousewheel(function(e, delta, deltaX, deltaY) {
                $this.scrollTop($this.scrollTop() - (deltaY * 10));
                $this.scrollLeft($this.scrollLeft() + (deltaX * 10));

                // update bar position
                updateBarSizeAndPosition();

                if(content_height > container_height || content_width > container_width) {
                    e.preventDefault();
                }
            });
        };

        // bind mobile touch handler
        var bindMobileTouchHandler = function() {
            var applyTouchMove = function(difference_x, difference_y) {
                $this.scrollTop($this.scrollTop() - difference_y);
                $this.scrollLeft($this.scrollLeft() - difference_x);

                // update bar position
                updateBarSizeAndPosition();
            };

            var start_coords = {},
                start_time = 0,
                speed = {},
                breaking_process = null;

            $this.bind("touchstart.perfect-scroll", function(e) {
                var touch = e.originalEvent.targetTouches[0];

                start_coords.pageX = touch.pageX;
                start_coords.pageY = touch.pageY;

                start_time = (new Date()).getTime();

                if (breaking_process !== null) {
                    clearInterval(breaking_process);
                }
            });
            $this.bind("touchmove.perfect-scroll", function(e) {
                var touch = e.originalEvent.targetTouches[0];

                var current_coords = {};
                current_coords.pageX = touch.pageX;
                current_coords.pageY = touch.pageY;

                var difference_x = current_coords.pageX - start_coords.pageX,
                    difference_y = current_coords.pageY - start_coords.pageY;

                applyTouchMove(difference_x, difference_y);
                start_coords = current_coords;

                var current_time = (new Date()).getTime();
                speed.x = difference_x / (current_time - start_time);
                speed.y = difference_y / (current_time - start_time);
                start_time = current_time;

                e.preventDefault();
            });
            $this.bind("touchend.perfect-scroll", function(e) {
                breaking_process = setInterval(function() {
                    if(Math.abs(speed.x) < 0.01 && Math.abs(speed.y) < 0.01) {
                        clearInterval(breaking_process);
                        return;
                    }

                    applyTouchMove(speed.x * 30, speed.y * 30);

                    speed.x *= 0.8;
                    speed.y *= 0.8;
                }, 10);
            });
        };

        var destroy = function() {
            $scrollbar_x.remove();
            $scrollbar_y.remove();
            $this.unbind('mousewheel');
            $this.unbind('touchstart.perfect-scroll');
            $this.unbind('touchmove.perfect-scroll');
            $this.unbind('touchend.perfect-scroll');
            $(window).unbind('mousemove.perfect-scroll');
            $(window).unbind('mouseup.perfect-scroll');
            $this.data('perfect_scrollbar', null);
            $this.data('perfect_scrollbar_update', null);
            $this.data('perfect_scrollbar_destroy', null);
        };

        var isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent);

        var initialize = function() {
            updateBarSizeAndPosition();
            bindMouseScrollXHandler();
            bindMouseScrollYHandler();
            if(isMobile) bindMobileTouchHandler();
            if($this.mousewheel) bindMouseWheelHandler();
            $this.data('perfect_scrollbar', $this);
            $this.data('perfect_scrollbar_update', updateBarSizeAndPosition);
            $this.data('perfect_scrollbar_destroy', destroy);
        };

        // initialize
        initialize();

        return $this;
    };
})(jQuery));
<|endoftext|>


<commit_before>module.exports = PerformanceTrackerRunner;

var path = require('path');
var EventEmitter = require('events').EventEmitter;
var Promise = require('bluebird');
var async = require('async');

/*
 In order to facilitate better testing, constructor injection is used here. All dependencies can be mocked for testing.
 - a single parameter object could have been used instead, however this makes the parameter requirements too opaque
 */
function PerformanceTrackerRunner(job, commander, tester, nodeVersionUtil, stateUpdater,
                                  uploader, logUpdater, blackBoard, filer) {

    this.events = new EventEmitter();

    this.__commander = commander != null ? commander : new (require('../../utils/commander'));
    this.__tester = tester != null ? tester : new (require('./../../utils/tester'));
    this.__nodeVersionUtil = nodeVersionUtil != null ? nodeVersionUtil : new (require('./../../utils/versioner'));
    this.__stateUpdater = stateUpdater != null ? stateUpdater : new (require('./../../utils/state-updater'));
    this.__uploader = uploader != null ? uploader : new (require('./../../utils/uploader'));
    this.__logUpdater = logUpdater != null ? logUpdater : new (require('./../../utils/log-updater'));
    this.__blackBoard = blackBoard != null ? blackBoard : new (require('../../utils/blackboard'));
    this.__filer = filer != null ? filer : new (require('../../utils/filer'));

    this.__currentJob = job;

    this.__states = {
        running: 1,
        success: 2,
        error: 3,
        uploading: 4
    };
}

PerformanceTrackerRunner.prototype.start = function (callback) {

    var self = this;

    this.__emit('info', 'starting runner, repo: ' + self.__currentJob.repo);

    var state = {};
    var errors = {};
    var versions = self.__nodeVersionUtil.getVersions(self.__currentJob.message.config);

    self.__commander.run('cd ' + self.__currentJob.message.folder + ' && npm install', function (err, result) {

        if (err)
            return callback(err);

        async.eachSeries(versions, function (version, cb) {

            self.__runTests(version, state, errors)
                .then(function () {
                    cb();
                })
                .catch(function (err) {
                    cb(err);
                })

        }, function (e) {

            self.__logUpdater.done();

            if (e) {
                self.__displayErrors(e);
                return callback(e);
            }

            callback();
        });
    })
};

PerformanceTrackerRunner.prototype.__runTests = function (version, state, errors) {

    var self = this;
    var testFolder = self.__currentJob.message.folder + path.sep + self.__currentJob.message.config.testFolder;

    return new Promise(function (resolve, reject) {

        var context = null;

        self.__buildContext(version)
            .then(function (result) {
                context = result;
            })
            .tap(function () {
                self.__updateState(state, version, self.__states.running, 'running tests', context);
            })
            .then(function () {
                return self.__tester.test(testFolder);
            })
            .then(function (results) {
                return self.__appendContextTestResults(context, results);
            })
            .tap(function () {
                self.__updateState(state, version, self.__states.uploading, 'uploading metrics', context);
            })
            .then(function () {
                return self.__uploader.upload(context);
            })
            .tap(function () {
                self.__updateState(state, version, self.__states.success, 'run successful', context);
            })
            .then(function () {
                return self.__writeTestResults(context, errors, version, state);
            })
            .tap(function () {
                self.__emit('run-complete', context.test_results);
                resolve();
            })
            .catch(function (err) {

                errors[version] = err;
                self.__updateState(state, version, self.__states.error, 'run failed', context);

                // we are adding errors to an errors object, so just call back
                reject(errors);

                //reject(err);
            });
    })

};

PerformanceTrackerRunner.prototype.__buildContext = function (version) {

    var self = this;

    return new Promise(function (resolve, reject) {

        try {
            var job = self.__currentJob;
            var pkg = self.__filer.getPackageJSON(job.message.folder);

            var result = {
                version: version,
                name: pkg.name.toLowerCase(),
                module_version: pkg.version,
                path: job.message.folder,
                test_script: job.message.config.test_script,
                test_metrics: job.message.job_type.settings,
                test_results: {
                    context: {
                        version: pkg.version,
                        node: version,
                        owner: job.message.event.owner,
                        repo: job.message.event.name,
                        branch: job.message.event.branch
                    }
                }
            };

            resolve(result);
        } catch (err) {
            reject(err);
        }
    });
};

PerformanceTrackerRunner.prototype.__displayErrors = function (errors) {

    var self = this;

    console.log(errors);

    if (Object.keys(errors).length > 0) {
        // display output from failed node.js versions
        Object.keys(errors).forEach(function (version) {
            self.__blackBoard.chalkRed('  node v' + version + ':' + errors[version]);
        });
    }
};

PerformanceTrackerRunner.prototype.__appendContextTestResults = function (context, results) {
    return new Promise(function (resolve, reject) {

        try {
            var clonedContext = JSON.parse(JSON.stringify(context.test_results.context));

            context.test_results = results;
            context.test_results.context = clonedContext;

            resolve(context);
        } catch (err) {
            reject(err);
        }
    })
};

PerformanceTrackerRunner.prototype.__writeTestResults = function (context) {
    var self = this;

    return new Promise(function (resolve, reject) {
        self.__filer.writeJSONFile(context.path + path.sep + 'test_results_' + context.version + '.json',
            context.test_results, function (err, result) {

                if (err)
                    reject(err);

                resolve(result);
            });
    });
};

PerformanceTrackerRunner.prototype.__updateState = function (state, version, status, message, context) {
    state[version] = status;
    this.__stateUpdater.updateState(state);
    this.__emit('test-progress', {state: state, message: message, context: context});
};

PerformanceTrackerRunner.prototype.__emit = function (evt, data) {
    return this.events.emit(evt, data);
};

PerformanceTrackerRunner.prototype.on = function (evt, handler) {
    return this.events.on(evt, handler);
};

PerformanceTrackerRunner.prototype.removeListener = function (evt, handler) {
    return this.events.removeListener(evt, handler);
};<commit_msg>Added host_os to context payload<commit_after>module.exports = PerformanceTrackerRunner;

var os = require('os');
var path = require('path');
var EventEmitter = require('events').EventEmitter;
var Promise = require('bluebird');
var async = require('async');

/*
 In order to facilitate better testing, constructor injection is used here. All dependencies can be mocked for testing.
 - a single parameter object could have been used instead, however this makes the parameter requirements too opaque
 */
function PerformanceTrackerRunner(job, commander, tester, nodeVersionUtil, stateUpdater,
                                  uploader, logUpdater, blackBoard, filer) {

    this.events = new EventEmitter();

    this.__commander = commander != null ? commander : new (require('../../utils/commander'));
    this.__tester = tester != null ? tester : new (require('./../../utils/tester'));
    this.__nodeVersionUtil = nodeVersionUtil != null ? nodeVersionUtil : new (require('./../../utils/versioner'));
    this.__stateUpdater = stateUpdater != null ? stateUpdater : new (require('./../../utils/state-updater'));
    this.__uploader = uploader != null ? uploader : new (require('./../../utils/uploader'));
    this.__logUpdater = logUpdater != null ? logUpdater : new (require('./../../utils/log-updater'));
    this.__blackBoard = blackBoard != null ? blackBoard : new (require('../../utils/blackboard'));
    this.__filer = filer != null ? filer : new (require('../../utils/filer'));

    this.__currentJob = job;

    this.__states = {
        running: 1,
        success: 2,
        error: 3,
        uploading: 4
    };
}

PerformanceTrackerRunner.prototype.start = function (callback) {

    var self = this;

    this.__emit('info', 'starting runner, repo: ' + self.__currentJob.repo);

    var state = {};
    var errors = {};
    var versions = self.__nodeVersionUtil.getVersions(self.__currentJob.message.config);

    self.__commander.run('cd ' + self.__currentJob.message.folder + ' && npm install', function (err, result) {

        if (err)
            return callback(err);

        async.eachSeries(versions, function (version, cb) {

            self.__runTests(version, state, errors)
                .then(function () {
                    cb();
                })
                .catch(function (err) {
                    cb(err);
                })

        }, function (e) {

            self.__logUpdater.done();

            if (e) {
                self.__displayErrors(e);
                return callback(e);
            }

            callback();
        });
    })
};

PerformanceTrackerRunner.prototype.__runTests = function (version, state, errors) {

    var self = this;
    var testFolder = self.__currentJob.message.folder + path.sep + self.__currentJob.message.config.testFolder;

    return new Promise(function (resolve, reject) {

        var context = null;

        self.__buildContext(version)
            .then(function (result) {
                context = result;
            })
            .tap(function () {
                self.__updateState(state, version, self.__states.running, 'running tests', context);
            })
            .then(function () {
                return self.__tester.test(testFolder);
            })
            .then(function (results) {
                return self.__appendContextTestResults(context, results);
            })
            .tap(function () {
                self.__updateState(state, version, self.__states.uploading, 'uploading metrics', context);
            })
            .then(function () {
                console.log(context);
                return self.__uploader.upload(context);
            })
            .tap(function () {
                self.__updateState(state, version, self.__states.success, 'run successful', context);
            })
            .then(function () {
                return self.__writeTestResults(context, errors, version, state);
            })
            .tap(function () {
                self.__emit('run-complete', context.test_results);
                resolve();
            })
            .catch(function (err) {

                errors[version] = err;
                self.__updateState(state, version, self.__states.error, 'run failed', context);

                // we are adding errors to an errors object, so just call back
                reject(errors);

                //reject(err);
            });
    })

};

PerformanceTrackerRunner.prototype.__buildContext = function (version) {

    var self = this;

    return new Promise(function (resolve, reject) {

        try {
            var job = self.__currentJob;
            var pkg = self.__filer.getPackageJSON(job.message.folder);

            var result = {
                version: version,
                name: pkg.name.toLowerCase(),
                module_version: pkg.version,
                path: job.message.folder,
                test_script: job.message.config.test_script,
                test_metrics: job.message.job_type.settings,
                test_results: {
                    context: {
                        host_os: os.hostname() + '_' + os.platform() + '_' + os.arch(),
                        version: pkg.version,
                        node: version,
                        owner: job.message.event.owner,
                        repo: job.message.event.name,
                        branch: job.message.event.branch
                    }
                }
            };

            resolve(result);
        } catch (err) {
            reject(err);
        }
    });
};

PerformanceTrackerRunner.prototype.__displayErrors = function (errors) {

    var self = this;

    console.log(errors);

    if (Object.keys(errors).length > 0) {
        // display output from failed node.js versions
        Object.keys(errors).forEach(function (version) {
            self.__blackBoard.chalkRed('  node v' + version + ':' + errors[version]);
        });
    }
};

PerformanceTrackerRunner.prototype.__appendContextTestResults = function (context, results) {
    return new Promise(function (resolve, reject) {

        try {
            var clonedContext = JSON.parse(JSON.stringify(context.test_results.context));

            context.test_results = results;
            context.test_results.context = clonedContext;

            resolve(context);
        } catch (err) {
            reject(err);
        }
    })
};

PerformanceTrackerRunner.prototype.__writeTestResults = function (context) {
    var self = this;

    return new Promise(function (resolve, reject) {
        self.__filer.writeJSONFile(context.path + path.sep + 'test_results_' + context.version + '.json',
            context.test_results, function (err, result) {

                if (err)
                    reject(err);

                resolve(result);
            });
    });
};

PerformanceTrackerRunner.prototype.__updateState = function (state, version, status, message, context) {
    state[version] = status;
    this.__stateUpdater.updateState(state);
    this.__emit('test-progress', {state: state, message: message, context: context});
};

PerformanceTrackerRunner.prototype.__emit = function (evt, data) {
    return this.events.emit(evt, data);
};

PerformanceTrackerRunner.prototype.on = function (evt, handler) {
    return this.events.on(evt, handler);
};

PerformanceTrackerRunner.prototype.removeListener = function (evt, handler) {
    return this.events.removeListener(evt, handler);
};<|endoftext|>