<commit_before>/*!
 * ${copyright}
 */
sap.ui.define([
	"sap/ui/core/Control",
	"sap/f/CardRenderer"
], function (
	Control,
	CardRenderer
) {
	"use strict";

	/**
	 * Constructor for a new Card.
	 *
	 * @param {string} [sId] ID for the new control, generated automatically if no ID is given
	 * @param {object} [mSettings] Initial settings for the new control
	 *
	 * @class
	 * A control that represents a container with a predefined header and content.
	 *
	 * @extends sap.ui.core.Control
	 *
	 * @author SAP SE
	 * @version ${version}
	 *
	 * @constructor
	 * @public
	 * @since 1.64
	 * @alias sap.f.Card
	 * @ui5-metamodel This control/element also will be described in the UI5 (legacy) designtime metamodel
	 */
	var Card = Control.extend("sap.f.Card", /** @lends sap.f.Card.prototype */ {
		metadata: {
			library: "sap.f",
			interfaces: ["sap.f.ICard"],
			properties: {

				/**
				 * Defines the width of the card.
				 */
				width: { type: "sap.ui.core.CSSSize", group: "Appearance", defaultValue: "100%" },

				/**
				 * Defines the height of the card.
				 */
				height: { type: "sap.ui.core.CSSSize", group: "Appearance", defaultValue: "auto" }
			},
			aggregations: {

				/**
				 * Defines the header of the card.
				 */
				header: { type: "sap.f.cards.IHeader", multiple: false },

				/**
				 * Defines the content of the card.
				 */
				content: { type: "sap.ui.core.Control", multiple: false }
			}
		},
		renderer: CardRenderer
	});

	/**
	 * Implements sap.f.ICard interface.
	 *
	 * @returns {sap.f.cards.IHeader} The header of the card.
	 * @protected
	 */
	Card.prototype.getCardHeader = function () {
		return this.getHeader();
	};

	/**
	 * Implements sap.f.ICard interface.
	 *
	 * @returns {sap.ui.core.Control} The content of the card.
	 * @protected
	 */
	Card.prototype.getCardContent = function () {
		return this.getContent();
	};

	return Card;
});
<commit_msg>[INTERNAL] sap.f.Card: About section is added<commit_after>/*!
 * ${copyright}
 */
sap.ui.define([
	"sap/ui/core/Control",
	"sap/f/CardRenderer"
], function (
	Control,
	CardRenderer
) {
	"use strict";

	/**
	 * Constructor for a new Card.
	 *
	 * @param {string} [sId] ID for the new control, generated automatically if no ID is given
	 * @param {object} [mSettings] Initial settings for the new control
	 *
	 * @class
	 * A control that represents a container with a predefined header and content.
	 *
	 *
Overview

	 * The card is a container for grouping and displaying information.
	 *
	 *
Structure

	 * You can control the width and height of the card, using properties.
	 * The Card has the following aggregations:
	 *

	 *
header - can be either a {@link sap.f.cards.Header Header} or a {@link sap.f.cards.NumericHeader NumericHeader}
	 *
content - can be any {@link sap.ui.core.Control Control}.

	 *

	 *
	 *
Guidelines:

	 *

	 *
A card should represent a task or visualize a specific set of information.

	 *
It is recommended to use cards on home page layouts.

	 *
The card shouldn't be large with a lot of content.

	 *

	 *
	 *
Usage

	 * To show a KPI value or any numeric information, use {@link sap.f.cards.NumericHeader NumericHeader} as a card header.
	 * For any other use cases, use the regular {@link sap.f.cards.Header Header}.
	 * Recommended content:
	 * - List
	 * - Table
	 * - Object information
	 * - Charts
	 * - Timelines
	 * - Images
	 *
	 * When to use
	 *

	 *
When you need multiple cards on a home page layout.

	 *
When you have to achieve simple card visualization.

	 *

	 *
	 * When not to use
	 *

	 *
When you have to reuse the card between applications. For such cases, use: {@link sap.ui.integration.widgets.Card Integration Card}.

	 *
When you need nesting. For such cases, use: {@link sap.m.Panel Panel}.

	 *
When the card is not part of a card layout. For such cases, use: {@link sap.m.Panel Panel}.

	 *
When you need more header configuration flexibility.

	 *

	 *
	 * @extends sap.ui.core.Control
	 *
	 * @author SAP SE
	 * @version ${version}
	 *
	 * @constructor
	 * @public
	 * @since 1.64
	 * @alias sap.f.Card
	 * @ui5-metamodel This control/element also will be described in the UI5 (legacy) designtime metamodel
	 */
	var Card = Control.extend("sap.f.Card", /** @lends sap.f.Card.prototype */ {
		metadata: {
			library: "sap.f",
			interfaces: ["sap.f.ICard"],
			properties: {

				/**
				 * Defines the width of the card.
				 */
				width: { type: "sap.ui.core.CSSSize", group: "Appearance", defaultValue: "100%" },

				/**
				 * Defines the height of the card.
				 */
				height: { type: "sap.ui.core.CSSSize", group: "Appearance", defaultValue: "auto" }
			},
			aggregations: {

				/**
				 * Defines the header of the card.
				 */
				header: { type: "sap.f.cards.IHeader", multiple: false },

				/**
				 * Defines the content of the card.
				 */
				content: { type: "sap.ui.core.Control", multiple: false }
			}
		},
		renderer: CardRenderer
	});

	/**
	 * Implements sap.f.ICard interface.
	 *
	 * @returns {sap.f.cards.IHeader} The header of the card.
	 * @protected
	 */
	Card.prototype.getCardHeader = function () {
		return this.getHeader();
	};

	/**
	 * Implements sap.f.ICard interface.
	 *
	 * @returns {sap.ui.core.Control} The content of the card.
	 * @protected
	 */
	Card.prototype.getCardContent = function () {
		return this.getContent();
	};

	return Card;
});
<|endoftext|>


<commit_before>var expect = require('chai').expect;

describe('integration', function() {

  describe('cjs bundle', function() {

    var annotate = require('../../').annotate;
    var Injector = require('../../').Injector;
    var Module = require('../../').Module;

    it('should expose API', function() {
      expect(annotate).to.exist;
      expect(Injector).to.exist;
      expect(Module).to.exist;
    });

    it('should work bundled', function() {

      class BubType {
        constructor() {
          this.name = 'bub';
        }
      }

      function BazType() {
        this.name = 'baz';
      }

      var module = {
        foo: [
          'factory',
          function() {
            return 'foo-value';
          }
        ],
        bar: ['value', 'bar-value'],
        baz: ['type', BazType],
        bub: ['type', BubType]
      };
      var injector = new Injector([module]);

      expect(injector.get('foo')).to.equal('foo-value');
      expect(injector.get('bar')).to.equal('bar-value');

      var bub = injector.get('bub');
      expect(bub).to.be.an.instanceof(BubType);
      expect(bub.name).to.eql('bub');

      var baz = injector.get('baz');
      expect(baz).to.be.an.instanceof(BazType);
      expect(baz.name).to.eql('baz');
    });

  });

  describe('umd bundle', function() {

    var didi = require('../../dist/didi.umd.prod.js');

    it('should expose API', function() {
      expect(didi.annotate).to.exist;
      expect(didi.Injector).to.exist;
      expect(didi.Module).to.exist;
    });

  });

});
<commit_msg>style: use destructuring<commit_after>var { expect } = require('chai');

describe('integration', function() {

  describe('cjs bundle', function() {

    var annotate = require('../../').annotate;
    var Injector = require('../../').Injector;
    var Module = require('../../').Module;

    it('should expose API', function() {
      expect(annotate).to.exist;
      expect(Injector).to.exist;
      expect(Module).to.exist;
    });

    it('should work bundled', function() {

      class BubType {
        constructor() {
          this.name = 'bub';
        }
      }

      function BazType() {
        this.name = 'baz';
      }

      var module = {
        foo: [
          'factory',
          function() {
            return 'foo-value';
          }
        ],
        bar: ['value', 'bar-value'],
        baz: ['type', BazType],
        bub: ['type', BubType]
      };
      var injector = new Injector([module]);

      expect(injector.get('foo')).to.equal('foo-value');
      expect(injector.get('bar')).to.equal('bar-value');

      var bub = injector.get('bub');
      expect(bub).to.be.an.instanceof(BubType);
      expect(bub.name).to.eql('bub');

      var baz = injector.get('baz');
      expect(baz).to.be.an.instanceof(BazType);
      expect(baz.name).to.eql('baz');
    });

  });

  describe('umd bundle', function() {

    var didi = require('../../dist/didi.umd.prod.js');

    it('should expose API', function() {
      expect(didi.annotate).to.exist;
      expect(didi.Injector).to.exist;
      expect(didi.Module).to.exist;
    });

  });

});
<|endoftext|>


<commit_before>'use strict';

const assert = require('assert');
const app = require('../../../src/app');
const helpdeskService = app.service('helpdesk');
const chai = require('chai');
const expect = require('chai').expect;

describe('helpdesk service', function() {

	const testProblem =
		{
			_id: '5836bb5664582c35df3bc214',
			subject: 'Dies ist ein Titel',
			currentTarget: 'Dies ist der CurrentState',
			targetState: 'Dies ist der TargetState',
			category: 'dashboard',
			schoolId: '5836bb5664582c35df3bc000'
		};

	before(function (done) {
		this.timeout(10000);
		helpdeskService.create(testProblem)
			.then(result => {
				done();
			});
	});

	after(function(done) {
		helpdeskService.remove(testProblem)
			.then(result => {
				done();
			});
	});

	it('registered the helpdesk service', () => {
		assert.ok(helpdeskService);
	});

	it('POST /helpdesk with valid data', () => {

		let postBody = {
			subject: 'Dies ist ein Titel 2',
			currentTarget: 'Dies ist der CurrentState',
			targetState: 'Dies ist der TargetState',
			category: 'dashboard',
			schoolId: '5836bb5664582c35df3bc000'
		};

		return helpdeskService.create(postBody, { payload: {userId: '0000d213816abba584714c0a'}})
			.then(result => {
				expect(result.subject).to.equal('Dies ist ein Titel 2');
			}
		);
	});

	it('POST /helpdesk with invalid data', () => {

		let postBody = {
			subject: 'Dies ist ein Titel 3',
			currentTarget: 'Dies ist der CurrentState 2',
			targetState: 'Dies ist der TargetState 2',
			category: 'dashboard'
		};

		helpdeskService.create(postBody, { payload: {userId: '0000d213816abba584714c0a'}})
			.catch(err => {
				expect(err).to.not.be.undefined;
				expect(err.code).to.equal(400);
			}
		);
	});
});

<commit_msg>test added<commit_after>'use strict';

const assert = require('assert');
const app = require('../../../src/app');
const helpdeskService = app.service('helpdesk');
const chai = require('chai');
const expect = require('chai').expect;

describe('helpdesk service', function() {

	const testProblem =
		{
			_id: '5836bb5664582c35df3bc214',
			subject: 'Dies ist ein Titel',
			currentTarget: 'Dies ist der CurrentState',
			targetState: 'Dies ist der TargetState',
			category: 'dashboard',
			schoolId: '5836bb5664582c35df3bc000'
		};

	before(function (done) {
		this.timeout(10000);
		helpdeskService.create(testProblem)
			.then(result => {
				done();
			});
	});

	after(function(done) {
		helpdeskService.remove(testProblem)
			.then(result => {
				done();
			});
	});

	it('registered the helpdesk service', () => {
		assert.ok(helpdeskService);
	});

	it('POST /helpdesk with valid data', () => {

		let postBody = {
			subject: 'Dies ist ein Titel 2',
			currentTarget: 'Dies ist der CurrentState',
			targetState: 'Dies ist der TargetState',
			category: 'dashboard',
			schoolId: '5836bb5664582c35df3bc000'
		};

		return helpdeskService.create(postBody, { payload: {userId: '0000d213816abba584714c0a'}})
			.then(result => {
				expect(result.subject).to.equal('Dies ist ein Titel 2');
			}
		);
	});

	it('POST /helpdesk with invalid data', () => {

		let postBody = {
			subject: 'Dies ist ein Titel 3',
			currentTarget: 'Dies ist der CurrentState 2',
			targetState: 'Dies ist der TargetState 2',
			category: 'dashboard'
		};

		helpdeskService.create(postBody, { payload: {userId: '0000d213816abba584714c0a'}})
			.catch(err => {
				expect(err).to.not.be.undefined;
				expect(err.code).to.equal(400);
			}
		);
	});

	it('POST /helpdesk with invalid data regarding schoolID', () => {

		let postBody = {
			subject: 'Dies ist ein Titel 4',
			currentTarget: 'Dies ist der CurrentState 3',
			targetState: 'Dies ist der TargetState 3',
			category: 'dashboard',
			schoolId: '599ec0bb8e4e364ec18ff46c'
		};

		helpdeskService.create(postBody, { payload: {userId: '0000d213816abba584714c0a'}})
			.catch(err => {
				expect(err).to.not.be.undefined;
				expect(err.code).to.equal(403);
			}
		);
	});
});

<|endoftext|>


<commit_before>'use strict';

describe('Controller: TabbedCtrl', function () {

  var TabbedCtrl, scope;

    // load the controller's module
  beforeEach(module('emuwebApp'));

     //Initialize the controller and a mock scope
     beforeEach(inject(function ($controller, $rootScope, ConfigProviderService, modalService, viewState, Validationservice) {
       // initiate the controller and mock the scope
       scope = $rootScope.$new();
       scope.valid = Validationservice;
       spyOn(scope.valid, 'getSchema').and.returnValue({ data: { properties: { spectrogramSettings: {properties: {}}, levelDefinitions: {items: { properties: {}}}, linkDefinitions: {items: { properties: {}}}}}});
       TabbedCtrl = $controller('TabbedCtrl', {
         $scope: scope
       });
       scope.cps = ConfigProviderService;
       scope.cps.setVals(defaultEmuwebappConfig);
       scope.cps.curDbConfig = aeDbConfig;
       scope.modal = modalService;
       scope.vs = viewState;
     }));

   it('should set cursorInTextField', function () {
     spyOn(scope.vs, 'setEditing');
     spyOn(scope.vs, 'setcursorInTextField');
     scope.cursorInTextField();
     expect(scope.vs.setEditing).toHaveBeenCalledWith(true);
     expect(scope.vs.setcursorInTextField).toHaveBeenCalledWith(true);
   });

   it('should set cursorOutOfTextField', function () {
     spyOn(scope.vs, 'setEditing');
     spyOn(scope.vs, 'setcursorInTextField');
     scope.cursorOutOfTextField();
     expect(scope.vs.setEditing).toHaveBeenCalledWith(false);
     expect(scope.vs.setcursorInTextField).toHaveBeenCalledWith(false);
   });

   it('should set onClickTab', function () {
     scope.onClickTab({url: 'test'});
     expect(scope.currentTab).toEqual('test');
   });

   it('should check if isActiveTab', function () {
     scope.currentTab = 'test';
     expect(scope.isActiveTab('test')).toEqual({
		'background-color': '#FFF',
		'color': '#000'
	 });
     expect(scope.isActiveTab('nothing')).toEqual({});
   });

   it('should addDefinition (level)', function () {
     var origLength = scope.cps.curDbConfig.levelDefinitions.length;
     scope.addDefinition('level');
     expect(scope.cps.curDbConfig.levelDefinitions.length).toEqual(origLength + 1);
   });

   it('should addDefinition (levelattribute)', function () {
     scope.addDefinition('level');
     var key = 0;
     var origLength = scope.cps.curDbConfig.levelDefinitions[key].attributeDefinitions.length;
     scope.addDefinition('levelattribute', key);
     expect(scope.cps.curDbConfig.levelDefinitions[key].attributeDefinitions.length).toEqual(origLength + 1);
   });

   it('should addDefinition (link)', function () {
     var origLength = scope.cps.curDbConfig.linkDefinitions.length;
     scope.addDefinition('link');
     expect(scope.cps.curDbConfig.linkDefinitions.length).toEqual(origLength + 1);
   });

   it('should addDefinition (ssff)', function () {
     var origLength = scope.cps.curDbConfig.ssffTrackDefinitions.length;
     scope.addDefinition('ssff');
     expect(scope.cps.curDbConfig.ssffTrackDefinitions.length).toEqual(origLength + 1);
   });

   it('should addDefinition (perspective)', function () {
     var origLength = scope.cps.vals.perspectives.length;
     scope.addDefinition('perspective');
     expect(scope.cps.vals.perspectives.length).toEqual(origLength + 1);
   });

   it('should addDefinition (perspectiveAssign)', function () {
     scope.addDefinition('perspective');
     var key = 0;
     var origLength = scope.cps.vals.perspectives[key].signalCanvases.assign.length;
     scope.addDefinition('perspectiveAssign', key);
     expect(scope.cps.vals.perspectives[key].signalCanvases.assign.length).toEqual(origLength + 1);
   });

   it('should addDefinition (perspectiveContourColor)', function () {
     var key = 1;
     var origLength = scope.cps.vals.perspectives[key].signalCanvases.contourColors.length;
     scope.addDefinition('perspectiveContourColor', key);
     expect(scope.cps.vals.perspectives[key].signalCanvases.contourColors.length).toEqual(origLength + 1);
   });

   it('should addDefinition (perspectiveContourColorColor)', function () {
     var key = 1;
     var keyAttribute = 0;
     var origLength = scope.cps.vals.perspectives[key].signalCanvases.contourColors[keyAttribute].colors.length;
     scope.addDefinition('perspectiveContourColorColor', key, keyAttribute);
     expect(scope.cps.vals.perspectives[key].signalCanvases.contourColors[keyAttribute].colors.length).toEqual(origLength + 1);
   });

   it('should addDefinition (perspectiveContourLims)', function () {
     scope.addDefinition('perspective');
     var key = 0;
     var origLength = scope.cps.vals.perspectives[key].signalCanvases.contourLims.length;
     scope.addDefinition('perspectiveContourLims', key);
     expect(scope.cps.vals.perspectives[key].signalCanvases.contourLims.length).toEqual(origLength + 1);
   });

   it('should addDefinition (perspectiveOrderSignal)', function () {
     scope.addDefinition('perspective');
     var key = 0;
     var origLength = scope.cps.vals.perspectives[key].signalCanvases.order.length;
     scope.addDefinition('perspectiveOrderSignal', key);
     expect(scope.cps.vals.perspectives[key].signalCanvases.order.length).toEqual(origLength + 1);
   });

   it('should addDefinition (perspectiveOrderLevel)', function () {
     scope.addDefinition('perspective');
     var key = 0;
     var origLength = scope.cps.vals.perspectives[key].levelCanvases.order.length;
     scope.addDefinition('perspectiveOrderLevel', key);
     expect(scope.cps.vals.perspectives[key].levelCanvases.order.length).toEqual(origLength + 1);
   });

   it('should addDefinition (perspectiveOrderTwoDim)', function () {
     scope.addDefinition('perspective');
     var key = 0;
     var origLength = scope.cps.vals.perspectives[key].twoDimCanvases.order.length;
     scope.addDefinition('perspectiveOrderTwoDim', key);
     expect(scope.cps.vals.perspectives[key].twoDimCanvases.order.length).toEqual(origLength + 1);
   });

   it('should deleteDefinition (level)', function () {
     scope.addDefinition('level');
     var origLength = scope.cps.curDbConfig.levelDefinitions.length;
     scope.deleteDefinition('level', 0);
     expect(scope.cps.curDbConfig.levelDefinitions.length).toEqual(origLength - 1);
   });

   it('should deleteDefinition (levelattribute)', function () {
     var key = 0;
     scope.addDefinition('level');
     scope.addDefinition('levelattribute', key);
     var origLength = scope.cps.curDbConfig.levelDefinitions[key].attributeDefinitions.length;
     scope.deleteDefinition('levelattribute', key,  key);
     expect(scope.cps.curDbConfig.levelDefinitions[key].attributeDefinitions.length).toEqual(origLength - 1);
   });

   it('should deleteDefinition (link)', function () {
     scope.addDefinition('link');
     var origLength = scope.cps.curDbConfig.linkDefinitions.length;
     scope.deleteDefinition('link', 0);
     expect(scope.cps.curDbConfig.linkDefinitions.length).toEqual(origLength - 1);
   });

   it('should deleteDefinition (perspective)', function () {
     scope.addDefinition('perspective');
     var origLength = scope.cps.vals.perspectives.length;
     scope.deleteDefinition('perspective', 0);
     expect(scope.cps.vals.perspectives.length).toEqual(origLength - 1);
   });
   // deleteDefinition all other : todo !

});
<commit_msg>disabled tabbed add/delete tests<commit_after>'use strict';

describe('Controller: TabbedCtrl', function () {

  var TabbedCtrl, scope;

    // load the controller's module
  beforeEach(module('emuwebApp'));

     //Initialize the controller and a mock scope
     beforeEach(inject(function ($controller, $rootScope, ConfigProviderService, modalService, viewState, Validationservice) {
       // initiate the controller and mock the scope
       scope = $rootScope.$new();
       scope.valid = Validationservice;
       spyOn(scope.valid, 'getSchema').and.returnValue({ data: { properties: { spectrogramSettings: {properties: {}}, levelDefinitions: {items: { properties: {}}}, linkDefinitions: {items: { properties: {}}}}}});
       TabbedCtrl = $controller('TabbedCtrl', {
         $scope: scope
       });
       scope.cps = ConfigProviderService;
       scope.cps.setVals(defaultEmuwebappConfig);
       scope.cps.curDbConfig = aeDbConfig;
       scope.modal = modalService;
       scope.vs = viewState;
     }));

   it('should set cursorInTextField', function () {
     spyOn(scope.vs, 'setEditing');
     spyOn(scope.vs, 'setcursorInTextField');
     scope.cursorInTextField();
     expect(scope.vs.setEditing).toHaveBeenCalledWith(true);
     expect(scope.vs.setcursorInTextField).toHaveBeenCalledWith(true);
   });

   it('should set cursorOutOfTextField', function () {
     spyOn(scope.vs, 'setEditing');
     spyOn(scope.vs, 'setcursorInTextField');
     scope.cursorOutOfTextField();
     expect(scope.vs.setEditing).toHaveBeenCalledWith(false);
     expect(scope.vs.setcursorInTextField).toHaveBeenCalledWith(false);
   });

   it('should set onClickTab', function () {
     scope.onClickTab({url: 'test'});
     expect(scope.currentTab).toEqual('test');
   });

   it('should check if isActiveTab', function () {
     scope.currentTab = 'test';
     expect(scope.isActiveTab('test')).toEqual({
		'background-color': '#FFF',
		'color': '#000'
	 });
     expect(scope.isActiveTab('nothing')).toEqual({});
   });

   /*
   it('should addDefinition (level)', function () {
     var origLength = scope.cps.curDbConfig.levelDefinitions.length;
     scope.addDefinition('level');
     expect(scope.cps.curDbConfig.levelDefinitions.length).toEqual(origLength + 1);
   });

   it('should addDefinition (levelattribute)', function () {
     scope.addDefinition('level');
     var key = 0;
     var origLength = scope.cps.curDbConfig.levelDefinitions[key].attributeDefinitions.length;
     scope.addDefinition('levelattribute', key);
     expect(scope.cps.curDbConfig.levelDefinitions[key].attributeDefinitions.length).toEqual(origLength + 1);
   });

   it('should addDefinition (link)', function () {
     var origLength = scope.cps.curDbConfig.linkDefinitions.length;
     scope.addDefinition('link');
     expect(scope.cps.curDbConfig.linkDefinitions.length).toEqual(origLength + 1);
   });

   it('should addDefinition (ssff)', function () {
     var origLength = scope.cps.curDbConfig.ssffTrackDefinitions.length;
     scope.addDefinition('ssff');
     expect(scope.cps.curDbConfig.ssffTrackDefinitions.length).toEqual(origLength + 1);
   });

   it('should addDefinition (perspective)', function () {
     var origLength = scope.cps.vals.perspectives.length;
     scope.addDefinition('perspective');
     expect(scope.cps.vals.perspectives.length).toEqual(origLength + 1);
   });

   it('should addDefinition (perspectiveAssign)', function () {
     scope.addDefinition('perspective');
     var key = 0;
     var origLength = scope.cps.vals.perspectives[key].signalCanvases.assign.length;
     scope.addDefinition('perspectiveAssign', key);
     expect(scope.cps.vals.perspectives[key].signalCanvases.assign.length).toEqual(origLength + 1);
   });

   it('should addDefinition (perspectiveContourColor)', function () {
     var key = 1;
     var origLength = scope.cps.vals.perspectives[key].signalCanvases.contourColors.length;
     scope.addDefinition('perspectiveContourColor', key);
     expect(scope.cps.vals.perspectives[key].signalCanvases.contourColors.length).toEqual(origLength + 1);
   });

   it('should addDefinition (perspectiveContourColorColor)', function () {
     var key = 1;
     var keyAttribute = 0;
     var origLength = scope.cps.vals.perspectives[key].signalCanvases.contourColors[keyAttribute].colors.length;
     scope.addDefinition('perspectiveContourColorColor', key, keyAttribute);
     expect(scope.cps.vals.perspectives[key].signalCanvases.contourColors[keyAttribute].colors.length).toEqual(origLength + 1);
   });

   it('should addDefinition (perspectiveContourLims)', function () {
     scope.addDefinition('perspective');
     var key = 0;
     var origLength = scope.cps.vals.perspectives[key].signalCanvases.contourLims.length;
     scope.addDefinition('perspectiveContourLims', key);
     expect(scope.cps.vals.perspectives[key].signalCanvases.contourLims.length).toEqual(origLength + 1);
   });

   it('should addDefinition (perspectiveOrderSignal)', function () {
     scope.addDefinition('perspective');
     var key = 0;
     var origLength = scope.cps.vals.perspectives[key].signalCanvases.order.length;
     scope.addDefinition('perspectiveOrderSignal', key);
     expect(scope.cps.vals.perspectives[key].signalCanvases.order.length).toEqual(origLength + 1);
   });

   it('should addDefinition (perspectiveOrderLevel)', function () {
     scope.addDefinition('perspective');
     var key = 0;
     var origLength = scope.cps.vals.perspectives[key].levelCanvases.order.length;
     scope.addDefinition('perspectiveOrderLevel', key);
     expect(scope.cps.vals.perspectives[key].levelCanvases.order.length).toEqual(origLength + 1);
   });

   it('should addDefinition (perspectiveOrderTwoDim)', function () {
     scope.addDefinition('perspective');
     var key = 0;
     var origLength = scope.cps.vals.perspectives[key].twoDimCanvases.order.length;
     scope.addDefinition('perspectiveOrderTwoDim', key);
     expect(scope.cps.vals.perspectives[key].twoDimCanvases.order.length).toEqual(origLength + 1);
   });

   it('should deleteDefinition (level)', function () {
     scope.addDefinition('level');
     var origLength = scope.cps.curDbConfig.levelDefinitions.length;
     scope.deleteDefinition('level', 0);
     expect(scope.cps.curDbConfig.levelDefinitions.length).toEqual(origLength - 1);
   });

   it('should deleteDefinition (levelattribute)', function () {
     var key = 0;
     scope.addDefinition('level');
     scope.addDefinition('levelattribute', key);
     var origLength = scope.cps.curDbConfig.levelDefinitions[key].attributeDefinitions.length;
     scope.deleteDefinition('levelattribute', key,  key);
     expect(scope.cps.curDbConfig.levelDefinitions[key].attributeDefinitions.length).toEqual(origLength - 1);
   });

   it('should deleteDefinition (link)', function () {
     scope.addDefinition('link');
     var origLength = scope.cps.curDbConfig.linkDefinitions.length;
     scope.deleteDefinition('link', 0);
     expect(scope.cps.curDbConfig.linkDefinitions.length).toEqual(origLength - 1);
   });

   it('should deleteDefinition (perspective)', function () {
     scope.addDefinition('perspective');
     var origLength = scope.cps.vals.perspectives.length;
     scope.deleteDefinition('perspective', 0);
     expect(scope.cps.vals.perspectives.length).toEqual(origLength - 1);
   });
   // deleteDefinition all other : todo !
   */
});
<|endoftext|>


<commit_before>import deepFreeze from 'deep-freeze';
import initialState from '../reducers/initialState';
import getXP from './getXP';

deepFreeze(initialState);

it('should return correct initial values', () => {
  const result = getXP(initialState);

  expect(result).toEqual({
    spent: 0,
    gainedFromFlaws: 0,
    available: 30,
    bankable: 5
  });
});

it('should calculate values', () => {
  const state = {
    character: {
      basicInfo: {
        archetype: '',
        clan: 'Brujah'
      },
      attributes: {
        physical: {
          dotsFromRank: 7
        },
        social: {
          dotsFromRank: 5,
          dotsPurchased: 2
        },
        mental: {
          dotsFromRank: 3,
          dotsPurchased: 1
        }
      },
      skills: {
        availableStartingDots: [
          {
            dots: 4,
            count: 0
          },
          {
            dots: 3,
            count: 1
          },
          {
            dots: 2,
            count: 2
          },
          {
            dots: 1,
            count: 4
          }
        ],
        academics: {
          startingDots: 4,
          dotsPurchased: 1
        },
        animalKen: {
          startingDots: 3,
          dotsPurchased: 2
        },
        athletics: {
          startingDots: 2,
          dotsPurchased: 1
        },
        awareness: {
          dotsPurchased: 1
        }
      },
      backgrounds: {
        availableStartingDots: [
          {
            dots: 3,
            count: 0
          },
          {
            dots: 2,
            count: 0
          },
          {
            dots: 1,
            count: 0
          }
        ],
        alternateIdentity: {
          startingDots: 3,
          dotsPurchased: 2
        },
        fame: {
          startingDots: 1,
          dotsPurchased: 1
        },
        haven: {
          dotsPurchased: 2
        },
        generation: {
          startingDots: 2 // Ancilla
        }
      },
      disciplines: {
        inClan: {
          availableStartingDots: [
            {
              dots: 2,
              count: 0
            },
            {
              dots: 1,
              count: 0
            }
          ],
          Celerity: {
            startingDots: 2,
            dotsPurchased: 1
          },
          Potence: {
            startingDots: 1,
            dotsPurchased: 2
          },
          Presence: {
            startingDots: 1
          }
        },
        outOfClan: {
          availableStartingDots: [],
          Dominate: {
            dotsPurchased: 2
          }
        }
      },
      merits: [
        {
          name: 'Burning Wrath',
          points: 2
        },
        {
          name: 'Brotherhood',
          points: 1
        }
      ],
      flaws: [
        {
          name: 'Blood Rot',
          points: 5
        },
        {
          name: 'Addiction',
          points: 2
        }
      ],
      morality: {
        path: 'Humanity',
        startingDots: 5
      }
    }
  };

  deepFreeze(state);

  const result = getXP(state);

  expect(result).toEqual({
    spent: 112, // 6+3 + 10+8+10+6+2 + 8+10+4+2+4 + 9+6+9 + 4+8 + 2+1
    gainedFromFlaws: 7,
    available: -75,
    bankable: 0
  });
});

it('should calculate generation costs', () => {
  const state = {
    character: {
      basicInfo: {
        archetype: '',
        clan: ''
      },
      attributes: {
        physical: {},
        social: {},
        mental: {}
      },
      skills: {},
      backgrounds: {
        availableStartingDots: [
          {
            dots: 3,
            count: 1
          },
          {
            dots: 2,
            count: 1
          },
          {
            dots: 1,
            count: 0
          }
        ],
        generation: {
          startingDots: 1, // Neonate
          dotsPurchased: 2 // to Pretender Elder
        }
      },
      disciplines: {
        inClan: {},
        outOfClan: {}
      },
      merits: [],
      flaws: [],
      morality: {
        path: 'Humanity',
        startingDots: 5
      }
    }
  };

  deepFreeze(state);

  const result = getXP(state);

  expect(result).toEqual({
    spent: 10,
    gainedFromFlaws: 0,
    available: 20,
    bankable: 5
  });
});

it('should calculate morality costs', () => {
  const state = {
    character: {
      basicInfo: {
        archetype: '',
        clan: ''
      },
      attributes: {
        physical: {},
        social: {},
        mental: {}
      },
      skills: {},
      backgrounds: {
        availableStartingDots: [
          {
            dots: 3,
            count: 1
          },
          {
            dots: 2,
            count: 1
          },
          {
            dots: 1,
            count: 0
          }
        ],
        generation: {
          startingDots: 1
        }
      },
      disciplines: {
        inClan: {},
        outOfClan: {}
      },
      merits: [],
      flaws: [],
      morality: {
        path: 'Humanity',
        startingDots: 5,
        dotsPurchased: 1
      }
    }
  };

  deepFreeze(state);

  const result = getXP(state);

  expect(result).toEqual({
    spent: 10,
    gainedFromFlaws: 0,
    available: 20,
    bankable: 5
  });
});

it('should calculate bankable when available is less', () => {
  const state = {
    mode: {
      isEraser: false
    },
    character: {
      basicInfo: {
        archetype: '',
        clan: ''
      },
      attributes: {
        physical: {
          dotsPurchased: 9
        },
        social: {},
        mental: {}
      },
      skills: {
        availableStartingDots: [
          {
            dots: 4,
            count: 1
          },
          {
            dots: 3,
            count: 2
          },
          {
            dots: 2,
            count: 3
          },
          {
            dots: 1,
            count: 4
          }
        ]
      },
      backgrounds: {
        availableStartingDots: [
          {
            dots: 3,
            count: 1
          },
          {
            dots: 2,
            count: 1
          },
          {
            dots: 1,
            count: 0
          }
        ],
        generation: {
          startingDots: 1
        }
      },
      disciplines: {
        inClan: {
          availableStartingDots: [
            {
              dots: 2,
              count: 1
            },
            {
              dots: 1,
              count: 2
            }
          ]
        },
        outOfClan: {
          availableStartingDots: []
        }
      },
      merits: [],
      flaws: [],
      morality: {
        path: 'Humanity',
        startingDots: 5
      }
    }
  };

  deepFreeze(state);

  const result = getXP(state);

  expect(result).toEqual({
    spent: 27,
    gainedFromFlaws: 0,
    available: 3,
    bankable: 3
  });
});
<commit_msg>Add test of selector caching<commit_after>import deepFreeze from 'deep-freeze';
import initialState from '../reducers/initialState';
import getXP from './getXP';

deepFreeze(initialState);

it('should return correct initial values', () => {
  const result = getXP(initialState);

  expect(result).toEqual({
    spent: 0,
    gainedFromFlaws: 0,
    available: 30,
    bankable: 5
  });
});

it('should calculate values', () => {
  const state = {
    character: {
      basicInfo: {
        archetype: '',
        clan: 'Brujah'
      },
      attributes: {
        physical: {
          dotsFromRank: 7
        },
        social: {
          dotsFromRank: 5,
          dotsPurchased: 2
        },
        mental: {
          dotsFromRank: 3,
          dotsPurchased: 1
        }
      },
      skills: {
        availableStartingDots: [
          {
            dots: 4,
            count: 0
          },
          {
            dots: 3,
            count: 1
          },
          {
            dots: 2,
            count: 2
          },
          {
            dots: 1,
            count: 4
          }
        ],
        academics: {
          startingDots: 4,
          dotsPurchased: 1
        },
        animalKen: {
          startingDots: 3,
          dotsPurchased: 2
        },
        athletics: {
          startingDots: 2,
          dotsPurchased: 1
        },
        awareness: {
          dotsPurchased: 1
        }
      },
      backgrounds: {
        availableStartingDots: [
          {
            dots: 3,
            count: 0
          },
          {
            dots: 2,
            count: 0
          },
          {
            dots: 1,
            count: 0
          }
        ],
        alternateIdentity: {
          startingDots: 3,
          dotsPurchased: 2
        },
        fame: {
          startingDots: 1,
          dotsPurchased: 1
        },
        haven: {
          dotsPurchased: 2
        },
        generation: {
          startingDots: 2 // Ancilla
        }
      },
      disciplines: {
        inClan: {
          availableStartingDots: [
            {
              dots: 2,
              count: 0
            },
            {
              dots: 1,
              count: 0
            }
          ],
          Celerity: {
            startingDots: 2,
            dotsPurchased: 1
          },
          Potence: {
            startingDots: 1,
            dotsPurchased: 2
          },
          Presence: {
            startingDots: 1
          }
        },
        outOfClan: {
          availableStartingDots: [],
          Dominate: {
            dotsPurchased: 2
          }
        }
      },
      merits: [
        {
          name: 'Burning Wrath',
          points: 2
        },
        {
          name: 'Brotherhood',
          points: 1
        }
      ],
      flaws: [
        {
          name: 'Blood Rot',
          points: 5
        },
        {
          name: 'Addiction',
          points: 2
        }
      ],
      morality: {
        path: 'Humanity',
        startingDots: 5
      }
    }
  };

  deepFreeze(state);

  const result = getXP(state);

  expect(result).toEqual({
    spent: 112, // 6+3 + 10+8+10+6+2 + 8+10+4+2+4 + 9+6+9 + 4+8 + 2+1
    gainedFromFlaws: 7,
    available: -75,
    bankable: 0
  });
});

it('should calculate generation costs', () => {
  const state = {
    character: {
      basicInfo: {
        archetype: '',
        clan: ''
      },
      attributes: {
        physical: {},
        social: {},
        mental: {}
      },
      skills: {},
      backgrounds: {
        availableStartingDots: [
          {
            dots: 3,
            count: 1
          },
          {
            dots: 2,
            count: 1
          },
          {
            dots: 1,
            count: 0
          }
        ],
        generation: {
          startingDots: 1, // Neonate
          dotsPurchased: 2 // to Pretender Elder
        }
      },
      disciplines: {
        inClan: {},
        outOfClan: {}
      },
      merits: [],
      flaws: [],
      morality: {
        path: 'Humanity',
        startingDots: 5
      }
    }
  };

  deepFreeze(state);

  const result = getXP(state);

  expect(result).toEqual({
    spent: 10,
    gainedFromFlaws: 0,
    available: 20,
    bankable: 5
  });
});

it('should calculate morality costs', () => {
  const state = {
    character: {
      basicInfo: {
        archetype: '',
        clan: ''
      },
      attributes: {
        physical: {},
        social: {},
        mental: {}
      },
      skills: {},
      backgrounds: {
        availableStartingDots: [
          {
            dots: 3,
            count: 1
          },
          {
            dots: 2,
            count: 1
          },
          {
            dots: 1,
            count: 0
          }
        ],
        generation: {
          startingDots: 1
        }
      },
      disciplines: {
        inClan: {},
        outOfClan: {}
      },
      merits: [],
      flaws: [],
      morality: {
        path: 'Humanity',
        startingDots: 5,
        dotsPurchased: 1
      }
    }
  };

  deepFreeze(state);

  const result = getXP(state);

  expect(result).toEqual({
    spent: 10,
    gainedFromFlaws: 0,
    available: 20,
    bankable: 5
  });
});

it('should calculate bankable when available is less', () => {
  const state = {
    mode: {
      isEraser: false
    },
    character: {
      basicInfo: {
        archetype: '',
        clan: ''
      },
      attributes: {
        physical: {
          dotsPurchased: 9
        },
        social: {},
        mental: {}
      },
      skills: {
        availableStartingDots: [
          {
            dots: 4,
            count: 1
          },
          {
            dots: 3,
            count: 2
          },
          {
            dots: 2,
            count: 3
          },
          {
            dots: 1,
            count: 4
          }
        ]
      },
      backgrounds: {
        availableStartingDots: [
          {
            dots: 3,
            count: 1
          },
          {
            dots: 2,
            count: 1
          },
          {
            dots: 1,
            count: 0
          }
        ],
        generation: {
          startingDots: 1
        }
      },
      disciplines: {
        inClan: {
          availableStartingDots: [
            {
              dots: 2,
              count: 1
            },
            {
              dots: 1,
              count: 2
            }
          ]
        },
        outOfClan: {
          availableStartingDots: []
        }
      },
      merits: [],
      flaws: [],
      morality: {
        path: 'Humanity',
        startingDots: 5
      }
    }
  };

  deepFreeze(state);

  const result = getXP(state);

  expect(result).toEqual({
    spent: 27,
    gainedFromFlaws: 0,
    available: 3,
    bankable: 3
  });
});

it('should cache', () => {
  const state = {
    character: {
      basicInfo: {
        archetype: '',
        clan: ''
      },
      attributes: {
        physical: {},
        social: {},
        mental: {}
      },
      skills: {},
      backgrounds: {
        availableStartingDots: [
          {
            dots: 3,
            count: 1
          },
          {
            dots: 2,
            count: 1
          },
          {
            dots: 1,
            count: 0
          }
        ],
        generation: {
          startingDots: 1
        }
      },
      disciplines: {
        inClan: {},
        outOfClan: {}
      },
      merits: [],
      flaws: [],
      morality: {
        path: 'Humanity',
        startingDots: 5
      }
    }
  };

  const previousRecomputations = getXP.recomputations();

  getXP(state);
  getXP(state);

  expect(getXP.recomputations()).toBe(previousRecomputations + 1);
});
<|endoftext|>


<commit_before>import 'kendo-ui/js/kendo.button.min';
import {Container} from 'aurelia-dependency-injection';
import {TemplatingEngine} from 'aurelia-templating';
import {TemplateCompiler} from 'src/common/template-compiler';
import {initialize} from 'aurelia-pal-browser';
import {TaskQueue} from 'aurelia-task-queue';
import {DOM} from 'aurelia-pal';
import {WidgetBase} from 'src/common/widget-base';

describe('WidgetBase', () => {
  let sut;
  let templateCompilerFake;
  let container;
  let templatingEngine;

  beforeEach(() => {
    initialize();

    // noop angular callback
    kendo.ui.Widget.prototype.angular = () => {};

    templateCompilerFake = {
      initialize: jasmine.createSpy()
    };

    container = new Container();
    container.registerInstance(TemplateCompiler, templateCompilerFake);
    container.registerInstance(TaskQueue, {});

    templatingEngine = container.get(TemplatingEngine);
    sut = templatingEngine.createViewModelForUnitTest(WidgetBase);

    jQuery.fn.myControl = {
      widget: {
        prototype: {
          options: {}
        }
      }
    };
  });

  it('initializes the templatecontroller in the constructor', () => {
    expect(templateCompilerFake.initialize).toHaveBeenCalled();
  });

  it('stores kendoOptions and kendoEvents when control is configured', () => {
    let controlName = 'kendoButton';
    let a = sut.control(controlName);

    expect(a).toBe(sut);
    expect(a.controlName).toBe('kendoButton');
    expect(a.kendoOptions).toBe(jQuery.fn[controlName].widget.prototype.options);
    expect(a.kendoEvents).toBe(jQuery.fn[controlName].widget.prototype.events);
  });

  it('throws error when Kendo control does not exist', () => {
    let controlName = 'kendoNonExisting';
    expect(() => sut.control(controlName)).toThrow(new Error('The name of control kendoNonExisting is invalid or not set'));
  });

  it('stores viewmodel', () => {
    let vm = {};
    sut.viewModel = { some: 'prop' };
    sut.linkViewModel(vm);

    expect(sut.viewModel).toBe(vm);
  });

  it('throws error linkViewModel is called without viewModel', () => {
    expect(function() {
      sut.linkViewModel(undefined);
    }).toThrow(new Error('viewModel is not set'));
  });

  it('destroys the Kendo widget', () => {
    let destroySpy = jasmine.createSpy();
    let widget = {
      destroy: destroySpy
    };
    sut.destroy(widget);

    expect(destroySpy).toHaveBeenCalled();
  });

  it('getEventOptions registers on events', () => {
    let element = DOM.createElement('div');
    sut.kendoEvents = ['ready', 'done', 'finished'];
    element.setAttributeNode(document.createAttribute('k-on-ready'));
    element.setAttributeNode(document.createAttribute('k-on-done'));

    let returnedOptions = sut.getEventOptions(element);

    expect(returnedOptions.ready).not.toBeUndefined();
    expect(returnedOptions.done).not.toBeUndefined();
    expect(returnedOptions.finished).toBeUndefined();
  });

  it('getEventOptions throws when kendo event does not exist', () => {
    let element = DOM.createElement('div');
    sut.kendoEvents = ['ready'];
    sut.controlName = 'myControl';
    element.setAttributeNode(document.createAttribute('k-on-done'));

    expect(function() {
      sut.getEventOptions(element);
    }).toThrow(new Error('done is not an event on the myControl control'));
  });

  it('createWidget throws error when option is missing', () => {
    expect(function() {
      sut.createWidget();
    }).toThrow(new Error('the createWidget() function needs to be called with an object'));

    expect(function() {
      sut.createWidget({
        parentCtx: {}
      });
    }).toThrow(new Error('element is not set'));

    expect(function() {
      sut.createWidget({
        element: DOM.createElement('div')
      });
    }).toThrow(new Error('parentCtx is not set'));
  });

  it('createWidget calls hooks', () => {
    let beforeSpy = jasmine.createSpy();
    sut._getOptions = jasmine.createSpy().and.returnValue({});
    sut.controlName = 'kendoButton';
    sut.createWidget({
      element: DOM.createElement('div'),
      parentCtx: {},
      beforeInitialize: beforeSpy
    });

    expect(beforeSpy).toHaveBeenCalled();

    let afterSpy = jasmine.createSpy();
    sut.createWidget({
      element: DOM.createElement('div'),
      parentCtx: {},
      afterInitialize: afterSpy
    });

    expect(afterSpy).toHaveBeenCalled();
  });

  it('createWidget sets parent context on options and widget', () => {
    sut._getOptions = jasmine.createSpy().and.returnValue({});
    sut.controlName = 'kendoButton';
    let parentCtx = { a: 'b'};
    let widget = sut.createWidget({
      element: DOM.createElement('div'),
      parentCtx: parentCtx
    });

    expect(widget._$parent.a).toBe('b');
    expect(widget.options._$parent[0].a).toBe('b');
  });

  it('sets viewResources on the widget', () => {
    sut._getOptions = jasmine.createSpy().and.returnValue({});
    sut.controlName = 'kendoButton';
    let parentCtx = { a: 'b'};
    let viewResources = {
      'a': 'b'
    };
    sut.useViewResources(viewResources);
    let widget = sut.createWidget({
      element: DOM.createElement('div'),
      parentCtx: parentCtx
    });

    expect(widget._$resources).toBe(viewResources);
    expect(widget.options._$resources[0].a).toBe('b');
  });

  it('createWidget looks at the rootElement for event attributes when a rootElement is supplied', () => {
    sut.getOptionsFromBindables = jasmine.createSpy().and.returnValue({});
    let events = ['test1', 'test2'];

    sut.kendoEvents = events;
    sut.controlName = 'kendoButton';
    sut.viewModel = { options: {} };

    let attrs = events.map(e => 'k-on-' + e);

    let rootElement = DOM.createElement('div');
    rootElement.setAttribute(attrs[0], 'test');
    rootElement.setAttribute(attrs[1], 'test2');

    let widget = sut.createWidget({
      element: DOM.createElement('div'),
      parentCtx: {},
      rootElement: rootElement
    });

    expect(widget.options[events[0]]).toEqual(jasmine.any(Function));
    expect(widget.options[events[1]]).toEqual(jasmine.any(Function));
  });

  it('handles value binding and sets initial value', () => {
    sut._getOptions = jasmine.createSpy().and.returnValue({});
    let widgetFake = {
      first: jasmine.createSpy(),
      value: jasmine.createSpy().and.returnValue('initialValue')
    };
    sut._createWidget = () => widgetFake;
    sut.controlName = 'kendoDropDownList';
    sut.viewModel = {};
    sut.useValueBinding();

    let widget = sut.createWidget({
      element: DOM.createElement('div'),
      parentCtx: {}
    });

    // check if initial kValue is set
    // verify that the change event is registered to
    expect(widgetFake.value).toHaveBeenCalled();
    let args = widgetFake.first.calls.argsFor(0);
    expect(args[0]).toBe('change');
    expect(widgetFake.first).toHaveBeenCalled();
    expect(sut.viewModel.kValue).toBe('initialValue');

    // raise 'change' event, check if kValue changed
    widgetFake.value = jasmine.createSpy().and.returnValue('changedValue');
    args[1]({ sender: widget });
    expect(sut.viewModel.kValue).toBe('changedValue');
  });
});
<commit_msg>no message<commit_after>import 'kendo-ui/js/kendo.button.min';
import {Container} from 'aurelia-dependency-injection';
import {TemplatingEngine} from 'aurelia-templating';
import {TemplateCompiler} from 'src/common/template-compiler';
import {initialize} from 'aurelia-pal-browser';
import {TaskQueue} from 'aurelia-task-queue';
import {DOM} from 'aurelia-pal';
import {WidgetBase} from 'src/common/widget-base';

describe('WidgetBase', () => {
  let sut;
  let templateCompilerFake;
  let container;
  let templatingEngine;

  beforeEach(() => {
    initialize();

    // noop angular callback
    kendo.ui.Widget.prototype.angular = () => {};

    templateCompilerFake = {
      initialize: jasmine.createSpy()
    };

    container = new Container();
    container.registerInstance(TemplateCompiler, templateCompilerFake);
    container.registerInstance(TaskQueue, {});

    templatingEngine = container.get(TemplatingEngine);
    sut = templatingEngine.createViewModelForUnitTest(WidgetBase);

    jQuery.fn.myControl = {
      widget: {
        prototype: {
          options: {}
        }
      }
    };
  });

  it('initializes the templatecontroller in the constructor', () => {
    expect(templateCompilerFake.initialize).toHaveBeenCalled();
  });

  it('stores kendoOptions and kendoEvents when control is configured', () => {
    let controlName = 'kendoButton';
    let a = sut.control(controlName);

    expect(a).toBe(sut);
    expect(a.controlName).toBe('kendoButton');
    expect(a.kendoOptions).toBe(jQuery.fn[controlName].widget.prototype.options);
    expect(a.kendoEvents).toBe(jQuery.fn[controlName].widget.prototype.events);
  });

  it('throws error when Kendo control does not exist', () => {
    let controlName = 'kendoNonExisting';
    expect(() => sut.control(controlName)).toThrow(new Error('The name of control kendoNonExisting is invalid or not set'));
  });

  it('stores viewmodel', () => {
    let vm = {};
    sut.viewModel = { some: 'prop' };
    sut.linkViewModel(vm);

    expect(sut.viewModel).toBe(vm);
  });

  it('throws error linkViewModel is called without viewModel', () => {
    expect(function() {
      sut.linkViewModel(undefined);
    }).toThrow(new Error('viewModel is not set'));
  });

  it('destroys the Kendo widget', () => {
    let destroySpy = jasmine.createSpy();
    let widget = {
      destroy: destroySpy
    };
    sut.destroy(widget);

    expect(destroySpy).toHaveBeenCalled();
  });

  it('getEventOptions registers on events', () => {
    let element = DOM.createElement('div');
    sut.kendoEvents = ['ready', 'done', 'finished'];
    element.setAttributeNode(document.createAttribute('k-on-ready'));
    element.setAttributeNode(document.createAttribute('k-on-done'));

    let returnedOptions = sut.getEventOptions(element);

    expect(returnedOptions.ready).not.toBeUndefined();
    expect(returnedOptions.done).not.toBeUndefined();
    expect(returnedOptions.finished).toBeUndefined();
  });

  it('getEventOptions throws when kendo event does not exist', () => {
    let element = DOM.createElement('div');
    sut.kendoEvents = ['ready'];
    sut.controlName = 'myControl';
    element.setAttributeNode(document.createAttribute('k-on-done'));

    expect(function() {
      sut.getEventOptions(element);
    }).toThrow(new Error('done is not an event on the myControl control'));
  });

  it('createWidget throws error when option is missing', () => {
    expect(function() {
      sut.createWidget();
    }).toThrow(new Error('the createWidget() function needs to be called with an object'));

    expect(function() {
      sut.createWidget({
        parentCtx: {}
      });
    }).toThrow(new Error('element is not set'));

    expect(function() {
      sut.createWidget({
        element: DOM.createElement('div')
      });
    }).toThrow(new Error('parentCtx is not set'));
  });

  it('createWidget calls hooks', () => {
    let beforeSpy = jasmine.createSpy();
    sut._getOptions = jasmine.createSpy().and.returnValue({});
    sut.controlName = 'kendoButton';
    sut.createWidget({
      element: DOM.createElement('div'),
      parentCtx: {},
      beforeInitialize: beforeSpy
    });

    expect(beforeSpy).toHaveBeenCalled();

    let afterSpy = jasmine.createSpy();
    sut.createWidget({
      element: DOM.createElement('div'),
      parentCtx: {},
      afterInitialize: afterSpy
    });

    expect(afterSpy).toHaveBeenCalled();
  });

  it('createWidget sets parent context on options and widget', () => {
    sut._getOptions = jasmine.createSpy().and.returnValue({});
    sut.controlName = 'kendoButton';
    let parentCtx = { a: 'b'};
    let widget = sut.createWidget({
      element: DOM.createElement('div'),
      parentCtx: parentCtx
    });

    expect(widget._$parent.a).toBe('b');
    expect(widget.options._$parent[0].a).toBe('b');
  });

  it('sets viewResources on the widget', () => {
    sut._getOptions = jasmine.createSpy().and.returnValue({});
    sut.controlName = 'kendoButton';
    let parentCtx = { a: 'b'};
    let viewResources = {
      'a': 'b'
    };
    sut.useViewResources(viewResources);
    let widget = sut.createWidget({
      element: DOM.createElement('div'),
      parentCtx: parentCtx
    });

    expect(widget._$resources).toBe(viewResources);
    expect(widget.options._$resources[0].a).toBe('b');
  });

  it('createWidget looks at the rootElement for event attributes when a rootElement is supplied', () => {
    sut.getOptionsFromBindables = jasmine.createSpy().and.returnValue({});
    let events = ['test1', 'test2'];

    sut.kendoEvents = events;
    sut.controlName = 'kendoButton';
    sut.viewModel = { options: {} };

    let attrs = events.map(e => 'k-on-' + e);

    let rootElement = DOM.createElement('div');
    rootElement.setAttribute(attrs[0], 'test');
    rootElement.setAttribute(attrs[1], 'test2');

    let widget = sut.createWidget({
      element: DOM.createElement('div'),
      parentCtx: {},
      rootElement: rootElement
    });

    expect(widget.options[events[0]]).toEqual(jasmine.any(Function));
    expect(widget.options[events[1]]).toEqual(jasmine.any(Function));
  });

  it('handles value binding and sets initial value', () => {
    sut._getOptions = jasmine.createSpy().and.returnValue({});
    let widgetFake = {
      first: jasmine.createSpy(),
      value: jasmine.createSpy().and.returnValue('initialValue')
    };
    sut._createWidget = () => widgetFake;
    sut.controlName = 'kendoDropDownList';
    sut.viewModel = {};
    sut.useValueBinding();

    let widget = sut.createWidget({
      element: DOM.createElement('div'),
      parentCtx: {}
    });

    // check if initial kValue is set
    // verify that the change event is registered to
    expect(widgetFake.value).toHaveBeenCalled();
    let args = widgetFake.first.calls.argsFor(0);
    expect(args[0]).toBe('change');
    expect(widgetFake.first).toHaveBeenCalled();
    expect(sut.viewModel.kValue).toBe('initialValue');

    // raise 'change' event, check if kValue changed
    widgetFake.value = jasmine.createSpy().and.returnValue('changedValue');
    args[1]({ sender: widget });
    expect(sut.viewModel.kValue).toBe('changedValue');
  });

  it('uses valueBindingProperty', () => {
    sut.controlName = 'kendoMobileSwitch';
    sut.viewModel = {};
    sut.useValueBinding('checked', 'check');
    let widgetFake = {
      first: jasmine.createSpy(),
      check: jasmine.createSpy()
    };
    sut._createWidget = () => widgetFake;

    let widget = sut.createWidget({
      element: DOM.createElement('div'),
      parentCtx: {}
    });

    sut.handlePropertyChanged(widget, 'kChecked', 2, 1);
    sut.handlePropertyChanged(widget, 'kValue', 4, 3);

    expect(widget.check).toHaveBeenCalledWith(2);
    expect(widget.check).not.toHaveBeenCalledWith(4);
  });

  it('_handleChange takes valueBindingProperty into account', () => {
    sut.viewModel = {};
    let widget = {
      check: jasmine.createSpy().and.returnValue('foo')
    };
    sut.useValueBinding('checked', 'check');

    sut._handleChange(widget);

    expect(widget.check).toHaveBeenCalled();
    expect(sut.viewModel.kChecked).toBe('foo');
  });
});
<|endoftext|>


<commit_before>(function (root, factory)
{
    if (typeof define === 'function' && define.amd)
    {
        // AMD. Register as an anonymous module.
        define(['videojs'], factory);
    }
    else if (typeof module === 'object' && module.exports)
    {
        // Node. Does not work with strict CommonJS, but
        // only CommonJS-like environments that support module.exports,
        // like Node.
        module.exports = factory(require('video.js'));
    }
    else
    {
        // Browser globals (root is window)
        root.returnExports = factory(root.videojs);
    }
}(this, function (videojs)
{
    /**
     * Audio-only engine for the opus-recorder library.
     *
     * Audio is encoded using libopus.
     *
     * @class
     * @augments videojs.RecordBase
     */
    videojs.OpusRecorderEngine = videojs.extend(videojs.RecordBase,
    {
        /**
         * Setup recording engine.
         */
        setup: function(stream, mediaType, debug)
        {
            this.inputStream = stream;
            this.mediaType = mediaType;
            this.debug = debug;

            this.engine = new Recorder({
                leaveStreamOpen: true,
                numberOfChannels: this.audioChannels,
                bufferLength: this.bufferSize,
                encoderSampleRate: this.sampleRate,
                encoderPath: this.audioWorkerURL
            });
            this.engine.addEventListener('dataAvailable',
                this.onRecordingAvailable.bind(this));

            this.engine.stream = stream;
            this.engine.sourceNode = this.engine.audioContext.createMediaStreamSource(
                stream);
            this.engine.sourceNode.connect(this.engine.filterNode ||
                this.engine.scriptProcessorNode);
            this.engine.sourceNode.connect(this.engine.monitorNode);
            this.engine.eventTarget.dispatchEvent(new Event('streamReady'));
        },

        /**
         * Start recording.
         */
        start: function()
        {
            this.engine.start();
        },

        /**
         * Stop recording.
         */
        stop: function()
        {
            this.engine.stop();
        },

        onRecordingAvailable: function(data)
        {
            // Opus format stored in an Ogg container
            var blob = new Blob([data.detail], {type: 'audio/ogg'});

            this.onStopRecording(blob);
        }
    });

}));
<commit_msg>opus-recorder plugin also supports pause/resume<commit_after>(function (root, factory)
{
    if (typeof define === 'function' && define.amd)
    {
        // AMD. Register as an anonymous module.
        define(['videojs'], factory);
    }
    else if (typeof module === 'object' && module.exports)
    {
        // Node. Does not work with strict CommonJS, but
        // only CommonJS-like environments that support module.exports,
        // like Node.
        module.exports = factory(require('video.js'));
    }
    else
    {
        // Browser globals (root is window)
        root.returnExports = factory(root.videojs);
    }
}(this, function (videojs)
{
    /**
     * Audio-only engine for the opus-recorder library.
     *
     * Audio is encoded using libopus.
     *
     * @class
     * @augments videojs.RecordBase
     */
    videojs.OpusRecorderEngine = videojs.extend(videojs.RecordBase,
    {
        /**
         * Setup recording engine.
         */
        setup: function(stream, mediaType, debug)
        {
            this.inputStream = stream;
            this.mediaType = mediaType;
            this.debug = debug;

            this.engine = new Recorder({
                leaveStreamOpen: true,
                numberOfChannels: this.audioChannels,
                bufferLength: this.bufferSize,
                encoderSampleRate: this.sampleRate,
                encoderPath: this.audioWorkerURL
            });
            this.engine.addEventListener('dataAvailable',
                this.onRecordingAvailable.bind(this));

            this.engine.stream = stream;
            this.engine.sourceNode = this.engine.audioContext.createMediaStreamSource(
                stream);
            this.engine.sourceNode.connect(this.engine.filterNode ||
                this.engine.scriptProcessorNode);
            this.engine.sourceNode.connect(this.engine.monitorNode);
            this.engine.eventTarget.dispatchEvent(new Event('streamReady'));
        },

        /**
         * Start recording.
         */
        start: function()
        {
            this.engine.start();
        },

        /**
         * Stop recording.
         */
        stop: function()
        {
            this.engine.stop();
        },

        /**
         * Pause recording.
         */
        pause: function()
        {
            this.engine.pause();
        },

        /**
         * Resume recording.
         */
        resume: function()
        {
            this.engine.resume();
        },

        onRecordingAvailable: function(data)
        {
            // Opus format stored in an Ogg container
            var blob = new Blob([data.detail], {type: 'audio/ogg'});

            this.onStopRecording(blob);
        }
    });

}));
<|endoftext|>


<commit_before>/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2019
 */
import { createSelector } from 'reselect';

import { UIDatabase } from '../database';

export const selectSortKey = ({ prescriber }) => {
  const { sortKey } = prescriber;
  return sortKey;
};

export const selectIsAscending = ({ prescriber }) => {
  const { isAscending } = prescriber;
  return isAscending;
};

export const selectSearchTerm = ({ prescriber }) => {
  const { searchTerm } = prescriber;
  return searchTerm;
};

export const selectNumberOfPrescribers = () => {
  const numberOfPrescribers = UIDatabase.objects('Prescriber').length;
  return numberOfPrescribers;
};

export const selectFilteredPrescribers = createSelector(
  [selectSearchTerm, selectNumberOfPrescribers],
  searchTerm => {
    const [lastName, firstName] = searchTerm.split(',').map(name => name.trim());

    const queryString = 'lastName BEGINSWITH[c] $0 AND firstName BEGINSWITH[c] $1';
    const newData = UIDatabase.objects('Prescriber').filtered(queryString, lastName, firstName);

    return newData;
  }
);

export const selectSortedPrescribers = createSelector(
  [selectSortKey, selectIsAscending, selectFilteredPrescribers],
  (sortKey, isAscending, prescribers) => prescribers.sorted(sortKey, isAscending)
);

export const selectPrescriberModalOpen = ({ prescriber }) => {
  const { isCreatingPrescriber, isEditingPrescriber } = prescriber;
  return isCreatingPrescriber || isEditingPrescriber;
};
<commit_msg>Add editable prescirber selector<commit_after>/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2019
 */
import { createSelector } from 'reselect';

import { UIDatabase } from '../database';

export const selectSortKey = ({ prescriber }) => {
  const { sortKey } = prescriber;
  return sortKey;
};

export const selectIsAscending = ({ prescriber }) => {
  const { isAscending } = prescriber;
  return isAscending;
};

export const selectSearchTerm = ({ prescriber }) => {
  const { searchTerm } = prescriber;
  return searchTerm;
};

export const selectNumberOfPrescribers = () => {
  const numberOfPrescribers = UIDatabase.objects('Prescriber').length;
  return numberOfPrescribers;
};

export const selectFilteredPrescribers = createSelector(
  [selectSearchTerm, selectNumberOfPrescribers],
  searchTerm => {
    const [lastName, firstName] = searchTerm.split(',').map(name => name.trim());

    const queryString = 'lastName BEGINSWITH[c] $0 AND firstName BEGINSWITH[c] $1';
    const newData = UIDatabase.objects('Prescriber').filtered(queryString, lastName, firstName);

    return newData;
  }
);

export const selectSortedPrescribers = createSelector(
  [selectSortKey, selectIsAscending, selectFilteredPrescribers],
  (sortKey, isAscending, prescribers) => prescribers.sorted(sortKey, isAscending)
);

export const selectPrescriberModalOpen = ({ prescriber }) => {
  const { isCreatingPrescriber, isEditingPrescriber } = prescriber;

  return isCreatingPrescriber || isEditingPrescriber;
};

export const selectCanEditPrescriber = ({ prescriber }) => {
  const { currentPrescriber } = prescriber;
  const { fromThisStore } = currentPrescriber ?? {};

  return fromThisStore ?? true;
};
<|endoftext|>


<commit_before>/**
 * @jest-environment ./test/helpers/jest-thunderbird-environment.cjs
 */

import { apply } from "./../../../addon/ad/compose_window";
import { LoggerStub } from './../../../addon/lib/logger_stub.js';

var AutomaticDictionary = {
  Lib: {},
  window_managers: []
};
//Helper function to copy prototypes
AutomaticDictionary.extend = function (destination,source) {
  return Object.assign(destination, source);
}

apply(AutomaticDictionary);

import { jest } from '@jest/globals'

describe('ComposeWindow', () => {
  var factory = function(){
    return new AutomaticDictionary.ComposeWindow({
      ad: {
        window: { id: 'stubbed-window-id' },
        addEventListener: jest.fn()
      },
      logger: LoggerStub,
      logo_url: 'stubbed-logo-url'
    });
  };
  var eventEmitterFactory = function(){
    return {
      addListener: jest.fn(),
      addEventListener: jest.fn(),
      removeListener: jest.fn(),
      removeEventListener: jest.fn()
    }
  }
  beforeEach(() => {
    browser.compose_ext = {
      onLanguageChange: eventEmitterFactory(),
      onRecipientsChange: eventEmitterFactory(),
      showNotification: jest.fn()
    };
    browser.windows.onFocusChanged = eventEmitterFactory();
    browser.windows.get = jest.fn().mockResolvedValue({
      tabs: [{id: 'stubbed-tab-id' } ]
    })
  })

  describe('canManageWindow', () => {
    it("detects matching window locations", () => {
      var matching_urls = [
        'chrome://whatever/messengercompose.xul',
        'chrome://whatever/messengercompose.xhtml'
      ]
      matching_urls.forEach((url) => {
        var window_stub = { document: { location: url } };
        expect(AutomaticDictionary.ComposeWindow.canManageWindow(window_stub)).toBe(true);
      })
    });

    it('rejects other locations', () => {
      var rejected_urls = [
        'chrome://messenger/content/messenger.xhmtl',
        'chrome://mozapps/content/extensions/aboutaddons.html'
      ];
      rejected_urls.forEach((url) => {
        var window_stub = { document: { location: url } };
        expect(AutomaticDictionary.ComposeWindow.canManageWindow(window_stub)).toBe(false);
      })
    });
  });

  describe('setListeners', () => {
    it('sets listeners on compose_ext', () => {
      var compose_window = factory();
      compose_window.setListeners();
      expect(browser.compose_ext.onLanguageChange.addListener).toHaveBeenCalled()
      expect(browser.compose_ext.onRecipientsChange.addListener).toHaveBeenCalled()
      expect(browser.windows.onFocusChanged.addListener).toHaveBeenCalled();
    });
  });

  describe('getCurrentLang', () => {
    it('returns what compose_ext returns', async () => {
      var compose_window = factory();
      browser.compose_ext.getCurrentLanguage = jest.fn().mockReturnValue('ca')

      expect(await compose_window.getCurrentLang()).toBe('ca')
      expect(browser.compose_ext.getCurrentLanguage).toHaveBeenCalledWith('stubbed-tab-id')
    })
  });

  describe('getTabId', () => {
    it('returns what compose_ext returns', async () => {
      var compose_window = factory();

      expect(compose_window.getTabId()).resolves.toBe('stubbed-tab-id');
      expect(browser.windows.get).toHaveBeenCalledWith('stubbed-window-id', {populate: true})
    })
  });

  describe('recipients', () => {
    describe('when recipients is a single string', () => {
      it('returns the recipients from that tab', async () => {
        var details = {'to': 'Joe'}
        var compose_window = factory();
        browser.compose.getComposeDetails = jest.fn().mockResolvedValue(details);

        expect(compose_window.recipients()).resolves.toStrictEqual(['Joe']);
      });
    })

    describe('when recipients is an array of strings', () => {
      it('returns the recipients from that tab', async () => {
        var details = {'to': ['Joe']}
        var compose_window = factory();
        browser.compose.getComposeDetails = jest.fn().mockResolvedValue(details);

        expect(compose_window.recipients()).resolves.toStrictEqual(['Joe']);
      });
    })

    describe('when recipients is an array of strings that needs to be normalized', () => {
      it('returns the recipients normalized', async () => {
        var details = {'to': ['Joe <joe@example.com>', 'Big band! <big.+band@example.com']}
        var compose_window = factory();
        browser.compose.getComposeDetails = jest.fn().mockResolvedValue(details);

        expect(compose_window.recipients()).resolves.toStrictEqual(
          ['joe@example.com','big.+band@example.com']);
      });
    })

    describe('when recipients is a compose recipients object', () => {
      //var composeRecipientsFactory = function()
      it('returns the recipients from that tab', async () => {
        var composeDetails = {
          to: [
            { type: 'contact', id: 'contact-recipient-id'},
            { type: 'mailingList', id: 'mailing-list-recipient-id'}
          ]
        }
        browser.compose.getComposeDetails = jest.fn().mockResolvedValue(composeDetails);
        browser.contacts.get = jest.fn().mockResolvedValue({
          properties: { PrimaryEmail: 'contact-email@example.com'}
        })
        browser.mailingLists.get = jest.fn().mockResolvedValue({
          properties: { name: 'mailinglist-email@example.com'}
        });
        var compose_window = factory();

        expect(await compose_window.recipients()).toStrictEqual(
          ["contact-email@example.com", "mailinglist-email@example.com"]);

        expect(browser.compose.getComposeDetails).toHaveBeenCalledWith('stubbed-tab-id');
        expect(browser.contacts.get).toHaveBeenCalledWith('contact-recipient-id');
        expect(browser.mailingLists.get).toHaveBeenCalledWith('mailing-list-recipient-id')
      });
    })
  });

  describe('showMessage', () => {
    it('forwards to compose_ext', async () => {
      var compose_window = factory();
      await compose_window.showMessage('message', {buttons: []})

      expect(browser.compose_ext.showNotification).toHaveBeenCalledWith(
        'stubbed-tab-id',
        'message',
        {
          logo_url: 'stubbed-logo-url',
          buttons: []
        }
      )
    })
  });

})<commit_msg>Complete unit tests for composer_window<commit_after>/**
 * @jest-environment ./test/helpers/jest-thunderbird-environment.cjs
 */

import { apply } from "./../../../addon/ad/compose_window";
import { LoggerStub } from './../../../addon/lib/logger_stub.js';

var AutomaticDictionary = {
  Lib: {},
  window_managers: []
};
//Helper function to copy prototypes
AutomaticDictionary.extend = function (destination,source) {
  return Object.assign(destination, source);
}

apply(AutomaticDictionary);

import { jest } from '@jest/globals'

describe('ComposeWindow', () => {
  var factory = function(){
    return new AutomaticDictionary.ComposeWindow({
      ad: {
        window: { id: 'stubbed-window-id' },
        addEventListener: jest.fn()
      },
      logger: LoggerStub,
      logo_url: 'stubbed-logo-url',
      notification_time: 4000
    });
  };
  var eventEmitterFactory = function(){
    return {
      addListener: jest.fn(),
      addEventListener: jest.fn(),
      removeListener: jest.fn(),
      removeEventListener: jest.fn()
    }
  }
  beforeEach(() => {
    browser.compose_ext = {
      onLanguageChange: eventEmitterFactory(),
      onRecipientsChange: eventEmitterFactory(),
      showNotification: jest.fn(),
      setSpellCheckerLanguage: jest.fn(),
      canSpellCheck: jest.fn().mockResolvedValue(true)
    };
    browser.windows.onFocusChanged = eventEmitterFactory();
    browser.windows.get = jest.fn().mockResolvedValue({
      tabs: [{id: 'stubbed-tab-id' } ]
    })
  })

  describe('canManageWindow', () => {
    it("detects matching window locations", () => {
      var matching_urls = [
        'chrome://whatever/messengercompose.xul',
        'chrome://whatever/messengercompose.xhtml'
      ]
      matching_urls.forEach((url) => {
        var window_stub = { document: { location: url } };
        expect(AutomaticDictionary.ComposeWindow.canManageWindow(window_stub)).toBe(true);
      })
    });

    it('rejects other locations', () => {
      var rejected_urls = [
        'chrome://messenger/content/messenger.xhmtl',
        'chrome://mozapps/content/extensions/aboutaddons.html'
      ];
      rejected_urls.forEach((url) => {
        var window_stub = { document: { location: url } };
        expect(AutomaticDictionary.ComposeWindow.canManageWindow(window_stub)).toBe(false);
      })
    });
  });

  describe('setListeners', () => {
    it('sets listeners on compose_ext', () => {
      var compose_window = factory();
      compose_window.setListeners();
      expect(browser.compose_ext.onLanguageChange.addListener).toHaveBeenCalled()
      expect(browser.compose_ext.onRecipientsChange.addListener).toHaveBeenCalled()
      expect(browser.windows.onFocusChanged.addListener).toHaveBeenCalled();
    });
  });

  describe('getCurrentLang', () => {
    it('returns what compose_ext returns', async () => {
      var compose_window = factory();
      browser.compose_ext.getCurrentLanguage = jest.fn().mockReturnValue('ca')

      expect(await compose_window.getCurrentLang()).toBe('ca')
      expect(browser.compose_ext.getCurrentLanguage).toHaveBeenCalledWith('stubbed-tab-id')
    })
  });

  describe('getTabId', () => {
    it('returns what compose_ext returns', async () => {
      var compose_window = factory();

      expect(compose_window.getTabId()).resolves.toBe('stubbed-tab-id');
      expect(browser.windows.get).toHaveBeenCalledWith('stubbed-window-id', {populate: true})
    })
  });

  describe('recipients', () => {
    describe('when recipients is a single string', () => {
      it('returns the recipients from that tab', async () => {
        var details = {'to': 'Joe'}
        var compose_window = factory();
        browser.compose.getComposeDetails = jest.fn().mockResolvedValue(details);

        expect(compose_window.recipients()).resolves.toStrictEqual(['Joe']);
      });
    })

    describe('when recipients is an array of strings', () => {
      it('returns the recipients from that tab', async () => {
        var details = {'to': ['Joe']}
        var compose_window = factory();
        browser.compose.getComposeDetails = jest.fn().mockResolvedValue(details);

        expect(compose_window.recipients()).resolves.toStrictEqual(['Joe']);
      });
    })

    describe('when recipients is an array of strings that needs to be normalized', () => {
      it('returns the recipients normalized', async () => {
        var details = {'to': ['Joe <joe@example.com>', 'Big band! <big.+band@example.com']}
        var compose_window = factory();
        browser.compose.getComposeDetails = jest.fn().mockResolvedValue(details);

        expect(compose_window.recipients()).resolves.toStrictEqual(
          ['joe@example.com','big.+band@example.com']);
      });
    })

    describe('when recipients is a compose recipients object', () => {
      //var composeRecipientsFactory = function()
      it('returns the recipients from that tab', async () => {
        var composeDetails = {
          to: [
            { type: 'contact', id: 'contact-recipient-id'},
            { type: 'mailingList', id: 'mailing-list-recipient-id'}
          ]
        }
        browser.compose.getComposeDetails = jest.fn().mockResolvedValue(composeDetails);
        browser.contacts.get = jest.fn().mockResolvedValue({
          properties: { PrimaryEmail: 'contact-email@example.com'}
        })
        browser.mailingLists.get = jest.fn().mockResolvedValue({
          properties: { name: 'mailinglist-email@example.com'}
        });
        var compose_window = factory();

        expect(await compose_window.recipients()).toStrictEqual(
          ["contact-email@example.com", "mailinglist-email@example.com"]);

        expect(browser.compose.getComposeDetails).toHaveBeenCalledWith('stubbed-tab-id');
        expect(browser.contacts.get).toHaveBeenCalledWith('contact-recipient-id');
        expect(browser.mailingLists.get).toHaveBeenCalledWith('mailing-list-recipient-id')
      });
    })
  });

  describe('showMessage', () => {
    it('forwards to compose_ext', async () => {
      var compose_window = factory();
      await compose_window.showMessage('message', {buttons: []})

      expect(browser.compose_ext.showNotification).toHaveBeenCalledWith(
        'stubbed-tab-id',
        'message',
        {
          logo_url: 'stubbed-logo-url',
          buttons: []
        }
      )
    })
  });

  describe('changeLabel', () => {
    it('forwards to compose_ext', async () => {
      var compose_window = factory();
      await compose_window.changeLabel('message')

      expect(browser.compose_ext.showNotification).toHaveBeenCalledWith(
        'stubbed-tab-id',
        'message',
        {
          logo_url: 'stubbed-logo-url',
          notification_time: 4000
        }
      )
    })
  });

  describe('changeLanguage', () => {
    it('sets spellchecker language via compose_ext', async () => {
      var compose_window = factory();
      await compose_window.changeLanguage('en')

      expect(browser.compose_ext.setSpellCheckerLanguage).toHaveBeenCalledWith('stubbed-tab-id', 'en')
    })
  })

  describe('canSpellCheck', () => {
    it('returns true when spellchecker is available', async () => {
      var compose_window = factory();
      expect(await compose_window.canSpellCheck()).toBe(true)

      expect(browser.compose_ext.canSpellCheck).toHaveBeenCalledWith('stubbed-tab-id')
    })
  })
})<|endoftext|>


<commit_before>const promise = require('bluebird');

const initOptions = {
  // Initialization Options
  promiseLib: promise
};

const pgp = require('pg-promise')(initOptions);
pgp.pg.types.setTypeParser(20, BigInt);
const ctStr = require('./db_connect.json');

const db = pgp(ctStr);

db.connect()
  .then(obj => {
    // log server version:
    const serverVersion = obj.client.serverVersion;
    console.log(serverVersion);

    obj.done(); // success, release the connection;
  })
  .catch(error => {
    console.log('ERROR:', error.message || error);
  });

module.exports = db;
<commit_msg>Merging changes from the localCorrection.<commit_after>const promise = require('bluebird');

const initOptions = {
  // Initialization Options
  promiseLib: promise
};

const pgp = require('pg-promise')(initOptions);
pgp.pg.types.setTypeParser(20, BigInt);
const ctStr = require('./db_connect.json');

const db = pgp(ctStr);

module.exports = db;
<|endoftext|>


<commit_before>var WIDTH = 250, HEIGHT = 220;

var ROW_HEIGHT = 15, LABEL_WIDTH = 50, MARGIN_TOP = 25;

var sizeFn = absoluteSize;

var entries = null;

var buttons = d3.select("#canvas-svg5").append("div").style("margin-bottom", "10px");
/*
var showCounts = buttons.append("span").attr("class", "btn btn-primary").text("Counts").on("click", function() {
    showPct.classed("btn-primary", false);
    showCounts.classed("btn-primary", true);
    sizeFn = absoluteSize;
    render();
});

var showPct = buttons.append("span").attr("class", "btn").text("Percentage").on("click", function() {
    showPct.classed("btn-primary", true);
    showCounts.classed("btn-primary", false);
    sizeFn = relativeSize;
    render();
});
*/
var svg = d3.select("#canvas-svg5").append("svg").attr({
    width: WIDTH + 20,
    height: HEIGHT
});

var maleScale = d3.scale.linear(), femaleScale = d3.scale.linear(), maleAxis = d3.svg.axis().orient("top").tickSize(-HEIGHT, 0, 0).scale(maleScale), femaleAxis = d3.svg.axis().orient("top").tickSize(-HEIGHT, 0, 0).scale(femaleScale);

svg.append("text").text("车型").attr({
    x: LABEL_WIDTH ,
    y: MARGIN_TOP -5,
    fill: "rgb(203,47,43)",
    class:"p4-content"
});

svg.append("text").text("微博提及频次").attr({
    x: LABEL_WIDTH + 50,
    y: MARGIN_TOP -5,
    fill: "rgb(242,150,0)",
    class:"p4-content"
});

svg.append("image")
    .attr("x",LABEL_WIDTH - 35)
    .attr("y",MARGIN_TOP )
    .attr("width",14.5)
    .attr("height",14.5)
    .attr("xlink:href","../img/p19-6.png");

svg.append("image")
    .attr("x",LABEL_WIDTH - 35)
    .attr("y",MARGIN_TOP + 15)
    .attr("width",14.5)
    .attr("height",14.5)
    .attr("xlink:href","../img/p23-2.png");

svg.append("image")
    .attr("x",LABEL_WIDTH - 35)
    .attr("y",MARGIN_TOP + 30)
    .attr("width",14.5)
    .attr("height",14.5)
    .attr("xlink:href","../img/p19-6.png");

svg.append("image")
    .attr("x",LABEL_WIDTH - 35)
    .attr("y",MARGIN_TOP + 45)
    .attr("width",14.5)
    .attr("height",14.5)
    .attr("xlink:href","../img/p23-2.png");

svg.append("image")
    .attr("x",LABEL_WIDTH - 35)
    .attr("y",MARGIN_TOP + 60)
    .attr("width",14.5)
    .attr("height",14.5)
    .attr("xlink:href","../img/p19-10.png");

svg.append("image")
    .attr("x",LABEL_WIDTH - 35)
    .attr("y",MARGIN_TOP + 75)
    .attr("width",14.5)
    .attr("height",14.5)
    .attr("xlink:href","../img/p23-6.png");

svg.append("image")
    .attr("x",LABEL_WIDTH - 35)
    .attr("y",MARGIN_TOP + 90)
    .attr("width",14.5)
    .attr("height",14.5)
    .attr("xlink:href","../img/p23-7.png");

svg.append("image")
    .attr("x",LABEL_WIDTH - 35)
    .attr("y",MARGIN_TOP + 105)
    .attr("width",16.5)
    .attr("height",14.5)
    .attr("xlink:href","../img/p23-8.png");

svg.append("image")
    .attr("x",LABEL_WIDTH - 35)
    .attr("y",MARGIN_TOP + 120)
    .attr("width",14.5)
    .attr("height",14.5)
    .attr("xlink:href","../img/p23-9.png");

svg.append("image")
    .attr("x",LABEL_WIDTH - 35)
    .attr("y",MARGIN_TOP + 135)
    .attr("width",14.5)
    .attr("height",14.5)
    .attr("xlink:href","../img/p19-3.png");

svg.append("image")
    .attr("x",LABEL_WIDTH - 35)
    .attr("y",MARGIN_TOP + 150)
    .attr("width",14.5)
    .attr("height",14.5)
    .attr("xlink:href","../img/p23-11.png");

svg.append("image")
    .attr("x",LABEL_WIDTH - 35)
    .attr("y",MARGIN_TOP + 165)
    .attr("width",14.5)
    .attr("height",14.5)
    .attr("xlink:href","../img/p23-12.png");

svg.append("image")
    .attr("x",LABEL_WIDTH - 35)
    .attr("y",MARGIN_TOP + 180)
    .attr("width",14.5)
    .attr("height",14.5)
    .attr("xlink:href","../img/p19-6.png");

/*
svg.append("text").text("2").attr({
    x: WIDTH,
    y: MARGIN_TOP + 12,
    fill: "white",
    class:"p4-content",
    "text-anchor": "end"
});
*/
var data = [ // <-A
        {num:1, expense: 43, category: "GT",total:50},
        {num:2, expense: 26, category: "元",total:50},
        {num:3, expense: 25, category: "福克斯",total:50},
        {num:4, expense: 23, category: "宋",total:50},
        {num:5, expense: 21, category: "H7",total:50},
        {num:6, expense: 18, category: "楼兰",total:50},
        {num:7, expense: 18, category: "大陆",total:50},
        {num:8, expense: 17, category: "α5概念车",total:50},
        {num:9, expense: 17, category: "NSX",total:50},
        {num:10, expense: 16, category: "GLE",total:50},
        {num:10, expense: 16, category: "XC90",total:50},
        {num:10, expense: 16, category: "ES",total:50},
        {num:10, expense: 16, category: "金牛座",total:50}
    ];

function render(data, category) {
        var svg5 = d3.select("#canvas-svg5")
        svg5.append("div").attr("class", "p23wrapper");
        var div = d3.select("div.p23wrapper").selectAll("div.p19hbar") // <-B
                .data(data)
                .enter()
                .append("div")
                    .attr("class", "p23-chart")
                .append("div")
                    .attr("class", "p19hbar");
        d3.select("div.p23wrapper").selectAll("div.p23-chart")
            .append("span")
            .attr("class","text-right");
        div.append("span")
            .attr("class","p19number");
        div.append("span")
            .attr("class","p19left");
        d3.select("#canvas-svg5").selectAll("div.p19hbar") // <-C
                .data(data)
            .exit().remove();

        d3.select("#canvas-svg5").selectAll("div.p23-chart") // <-D
                .data(data)
            .attr("class", "p23-chart")
            .style("width", function (d) {
                return (d.expense * 4 +50) + "px";}
            );

        my_data = d3.select("#canvas-svg5").selectAll("div.p19hbar") // <-D
                .data(data)
            .attr("class", "p19hbar")
            .style("width", function (d) {
            //    return (d.category * 0.2) + "px";}
                return (d.total) + "px";}
            );
            my_data.select("span.p19number")
                .text(function (d) {
                    return d.num;
                });
            my_data.select("span.p19left")
                .text(function (d) {
                    return d.category;
                });
            d3.select("div.p23wrapper").selectAll("div.p23-chart")
                .select("span.text-right")
                .text(function (d) {
                    return d.expense;
                });
    }
    render(data);

/*
function relativeSize(row, entries) {
    femaleScale.domain([ 0, 1 ]).range([ 0, (WIDTH - LABEL_WIDTH) / 2 ]);
    maleScale.domain([ 0, 1 ]).range([ 0, -(WIDTH - LABEL_WIDTH) / 2 ]);
    femaleAxis.ticks(4).tickFormat(function(val) {
        return val * 100 + "%";
    });
    maleAxis.ticks(4).tickFormat(function(val) {
        return val * 100 + "%";
    });
    row.select(".male").attr({
        width: function(d) {
            return maleScale(0) - maleScale(d.maleRatio);
        },
        x: function(d) {
            return maleScale(d.maleRatio);
        }
    });
    row.select(".female").attr({
        width: function(d) {
            return femaleScale(d.femaleRatio) - femaleScale(0);
        },
        x: function(d) {
            return femaleScale(0);
        }
    });
}
*/
function absoluteSize(row, entries) {
    var max = d3.max(entries, function(d) {
        return Math.max(d.female, d.male);
    });
    femaleScale.domain([ 0, max ]).range([ 0, (WIDTH - LABEL_WIDTH) / 2 ]);
    maleScale.domain([ 0, max ]).range([ 0, -(WIDTH - LABEL_WIDTH) / 2 ]);
    femaleAxis.ticks(0).tickFormat(null);
    maleAxis.ticks(0).tickFormat(null);
    row.select(".male").attr({
        width: function(d) {
            return maleScale(0) - maleScale(d.male);
        },
        x: function(d) {
            return maleScale(d.male);
        }
    });
    row.select(".female").attr({
        width: function(d) {
            return femaleScale(d.female) - femaleScale(0);
        },
        x: function(d) {
            return femaleScale(0);
        }
    });
}

function cleanup(data) {
    data = data.filter(function(d) {
        var gender = d[GENDER];
        var age = d[AGE];
        return (gender == "Male" || gender == "Female") && parseInt(age).toString() == age;
    });
    //data.forEach(function(d) {});
    return data;
}<commit_msg>update p23<commit_after>var WIDTH = 250, HEIGHT = 220;

var ROW_HEIGHT = 15, LABEL_WIDTH = 50, MARGIN_TOP = 25;

var sizeFn = absoluteSize;

var entries = null;

var buttons = d3.select("#canvas-svg5").append("div").style("margin-bottom", "10px");
/*
var showCounts = buttons.append("span").attr("class", "btn btn-primary").text("Counts").on("click", function() {
    showPct.classed("btn-primary", false);
    showCounts.classed("btn-primary", true);
    sizeFn = absoluteSize;
    render();
});

var showPct = buttons.append("span").attr("class", "btn").text("Percentage").on("click", function() {
    showPct.classed("btn-primary", true);
    showCounts.classed("btn-primary", false);
    sizeFn = relativeSize;
    render();
});
*/
var svg = d3.select("#canvas-svg5").append("svg").attr({
    width: WIDTH + 20,
    height: HEIGHT
});

var maleScale = d3.scale.linear(), femaleScale = d3.scale.linear(), maleAxis = d3.svg.axis().orient("top").tickSize(-HEIGHT, 0, 0).scale(maleScale), femaleAxis = d3.svg.axis().orient("top").tickSize(-HEIGHT, 0, 0).scale(femaleScale);

svg.append("text").text("车型").attr({
    x: LABEL_WIDTH ,
    y: MARGIN_TOP -5,
    fill: "rgb(203,47,43)",
    class:"p4-content"
});

svg.append("text").text("微博提及频次").attr({
    x: LABEL_WIDTH + 50,
    y: MARGIN_TOP -5,
    fill: "rgb(242,150,0)",
    class:"p4-content"
});

svg.append("image")
    .attr("x",LABEL_WIDTH - 35)
    .attr("y",MARGIN_TOP )
    .attr("width",14.5)
    .attr("height",14.5)
    .attr("xlink:href","http://autoshanghai2015-cdn.prvalue.cn/img/p19-6.png");

svg.append("image")
    .attr("x",LABEL_WIDTH - 35)
    .attr("y",MARGIN_TOP + 15)
    .attr("width",14.5)
    .attr("height",14.5)
    .attr("xlink:href","http://autoshanghai2015-cdn.prvalue.cn/img/p23-2.png");

svg.append("image")
    .attr("x",LABEL_WIDTH - 35)
    .attr("y",MARGIN_TOP + 30)
    .attr("width",14.5)
    .attr("height",14.5)
    .attr("xlink:href","http://autoshanghai2015-cdn.prvalue.cn/img/p19-6.png");

svg.append("image")
    .attr("x",LABEL_WIDTH - 35)
    .attr("y",MARGIN_TOP + 45)
    .attr("width",14.5)
    .attr("height",14.5)
    .attr("xlink:href","http://autoshanghai2015-cdn.prvalue.cn/img/p23-2.png");

svg.append("image")
    .attr("x",LABEL_WIDTH - 35)
    .attr("y",MARGIN_TOP + 60)
    .attr("width",14.5)
    .attr("height",14.5)
    .attr("xlink:href","http://autoshanghai2015-cdn.prvalue.cn/img/p19-10.png");

svg.append("image")
    .attr("x",LABEL_WIDTH - 35)
    .attr("y",MARGIN_TOP + 75)
    .attr("width",14.5)
    .attr("height",14.5)
    .attr("xlink:href","http://autoshanghai2015-cdn.prvalue.cn/img/p23-6.png");

svg.append("image")
    .attr("x",LABEL_WIDTH - 35)
    .attr("y",MARGIN_TOP + 90)
    .attr("width",14.5)
    .attr("height",14.5)
    .attr("xlink:href","http://autoshanghai2015-cdn.prvalue.cn/img/p23-7.png");

svg.append("image")
    .attr("x",LABEL_WIDTH - 35)
    .attr("y",MARGIN_TOP + 105)
    .attr("width",16.5)
    .attr("height",14.5)
    .attr("xlink:href","http://autoshanghai2015-cdn.prvalue.cn/img/p23-8.png");

svg.append("image")
    .attr("x",LABEL_WIDTH - 35)
    .attr("y",MARGIN_TOP + 120)
    .attr("width",14.5)
    .attr("height",14.5)
    .attr("xlink:href","http://autoshanghai2015-cdn.prvalue.cn/img/p23-9.png");

svg.append("image")
    .attr("x",LABEL_WIDTH - 35)
    .attr("y",MARGIN_TOP + 135)
    .attr("width",14.5)
    .attr("height",14.5)
    .attr("xlink:href","http://autoshanghai2015-cdn.prvalue.cn/img/p19-3.png");

svg.append("image")
    .attr("x",LABEL_WIDTH - 35)
    .attr("y",MARGIN_TOP + 150)
    .attr("width",14.5)
    .attr("height",14.5)
    .attr("xlink:href","http://autoshanghai2015-cdn.prvalue.cn/img/p23-11.png");

svg.append("image")
    .attr("x",LABEL_WIDTH - 35)
    .attr("y",MARGIN_TOP + 165)
    .attr("width",14.5)
    .attr("height",14.5)
    .attr("xlink:href","http://autoshanghai2015-cdn.prvalue.cn/img/p23-12.png");

svg.append("image")
    .attr("x",LABEL_WIDTH - 35)
    .attr("y",MARGIN_TOP + 180)
    .attr("width",14.5)
    .attr("height",14.5)
    .attr("xlink:href","http://autoshanghai2015-cdn.prvalue.cn/img/p19-6.png");

/*
svg.append("text").text("2").attr({
    x: WIDTH,
    y: MARGIN_TOP + 12,
    fill: "white",
    class:"p4-content",
    "text-anchor": "end"
});
*/
var data = [ // <-A
        {num:1, expense: 43, category: "GT",total:50},
        {num:2, expense: 26, category: "元",total:50},
        {num:3, expense: 25, category: "福克斯",total:50},
        {num:4, expense: 23, category: "宋",total:50},
        {num:5, expense: 21, category: "H7",total:50},
        {num:6, expense: 18, category: "楼兰",total:50},
        {num:7, expense: 18, category: "大陆",total:50},
        {num:8, expense: 17, category: "α5概念车",total:50},
        {num:9, expense: 17, category: "NSX",total:50},
        {num:10, expense: 16, category: "GLE",total:50},
        {num:10, expense: 16, category: "XC90",total:50},
        {num:10, expense: 16, category: "ES",total:50},
        {num:10, expense: 16, category: "金牛座",total:50}
    ];

function render(data, category) {
        var svg5 = d3.select("#canvas-svg5")
        svg5.append("div").attr("class", "p23wrapper");
        var div = d3.select("div.p23wrapper").selectAll("div.p19hbar") // <-B
                .data(data)
                .enter()
                .append("div")
                    .attr("class", "p23-chart")
                .append("div")
                    .attr("class", "p19hbar");
        d3.select("div.p23wrapper").selectAll("div.p23-chart")
            .append("span")
            .attr("class","text-right");
        div.append("span")
            .attr("class","p19number");
        div.append("span")
            .attr("class","p19left");
        d3.select("#canvas-svg5").selectAll("div.p19hbar") // <-C
                .data(data)
            .exit().remove();

        d3.select("#canvas-svg5").selectAll("div.p23-chart") // <-D
                .data(data)
            .attr("class", "p23-chart")
            .style("width", function (d) {
                return (d.expense * 4 +50) + "px";}
            );

        my_data = d3.select("#canvas-svg5").selectAll("div.p19hbar") // <-D
                .data(data)
            .attr("class", "p19hbar")
            .style("width", function (d) {
            //    return (d.category * 0.2) + "px";}
                return (d.total) + "px";}
            );
            my_data.select("span.p19number")
                .text(function (d) {
                    return d.num;
                });
            my_data.select("span.p19left")
                .text(function (d) {
                    return d.category;
                });
            d3.select("div.p23wrapper").selectAll("div.p23-chart")
                .select("span.text-right")
                .text(function (d) {
                    return d.expense;
                });
    }
    render(data);

/*
function relativeSize(row, entries) {
    femaleScale.domain([ 0, 1 ]).range([ 0, (WIDTH - LABEL_WIDTH) / 2 ]);
    maleScale.domain([ 0, 1 ]).range([ 0, -(WIDTH - LABEL_WIDTH) / 2 ]);
    femaleAxis.ticks(4).tickFormat(function(val) {
        return val * 100 + "%";
    });
    maleAxis.ticks(4).tickFormat(function(val) {
        return val * 100 + "%";
    });
    row.select(".male").attr({
        width: function(d) {
            return maleScale(0) - maleScale(d.maleRatio);
        },
        x: function(d) {
            return maleScale(d.maleRatio);
        }
    });
    row.select(".female").attr({
        width: function(d) {
            return femaleScale(d.femaleRatio) - femaleScale(0);
        },
        x: function(d) {
            return femaleScale(0);
        }
    });
}
*/
function absoluteSize(row, entries) {
    var max = d3.max(entries, function(d) {
        return Math.max(d.female, d.male);
    });
    femaleScale.domain([ 0, max ]).range([ 0, (WIDTH - LABEL_WIDTH) / 2 ]);
    maleScale.domain([ 0, max ]).range([ 0, -(WIDTH - LABEL_WIDTH) / 2 ]);
    femaleAxis.ticks(0).tickFormat(null);
    maleAxis.ticks(0).tickFormat(null);
    row.select(".male").attr({
        width: function(d) {
            return maleScale(0) - maleScale(d.male);
        },
        x: function(d) {
            return maleScale(d.male);
        }
    });
    row.select(".female").attr({
        width: function(d) {
            return femaleScale(d.female) - femaleScale(0);
        },
        x: function(d) {
            return femaleScale(0);
        }
    });
}

function cleanup(data) {
    data = data.filter(function(d) {
        var gender = d[GENDER];
        var age = d[AGE];
        return (gender == "Male" || gender == "Female") && parseInt(age).toString() == age;
    });
    //data.forEach(function(d) {});
    return data;
}<|endoftext|>