<commit_before>(function (w, $, toastr) {
    /* Default properties and their values for notification items */
    var ITEM_DEFAULTS = {
            type: 'success',
            message: '',
            title: ''
        },
        /* Toastr option default overrides */
        TOASTR_DEFAULTS = {
            closeButton: true,
            newestOnTop: true,
            preventDuplicates: true,
            timeout: 10000
        };

    /* Extend toastr.options with our defined defaults here */
    $.extend(toastr.options, TOASTR_DEFAULTS);

    var items = w.notifications || [],
        i = 0, l = items.length;

    for (i; i < l; i++) {
        var item = $.extend({}, ITEM_DEFAULTS, items[i]);
        addNotification(item);
    }

    /**
     * Add a new notification to Toastr
     * @param {object} item contains info for a new toastr notification.
     * A default  item object looks like this
     * {
     *     type: '', (valid types are: "success", "error", "info", or "warning")
     *     message: '', the notification message.
     *     title: '', (the notification title. Can be left empty.)
     *     timeout: '' (number, optional and is passed into the toastr function)
     * }
     */
    function addNotification(item) {
        var type = item.type,
            title = item.title,
            message = item.message,
            timeout = item.timeout,
            options = {};

        /* Add timeout to the options object if it exists */
        if ('undefined' !== typeof timeout) {
            options.timeout = timeout;
        }

        /* Call the toastr function if it exists */
        if ('function' === typeof toastr[type]) {
            toastr[type](message, title, options);
        }
    }
})(window, jQuery, toastr);
<commit_msg>[Assets]: Notifications - added API to create toastr notifications after page load<commit_after>/**
 * Notifications component
 * This component should:
 *  - provide an API to show different types of Toastr notifications; and
 *  - show flash notifications on page load.
 *
 * The flash notifications is configured as an array of objects where each object is a notification.
 * A notification object looks like:
 * {
 *     type: '',    {string} valid toastr notification types: 'success', 'error', 'info', or 'warning'
 *     message: '', {string} the notification message
 *     title: '',   {string} (optional) the notification title
 *     timeout: ''  {number} (optional) toastr timeout duration (in ms)
 * }
 */
;var Notification = (function ($, toastr, flashNotifications) {
    /* Toastr option overrides */
    var OVERRIDES = {
        closeButton: true,
        newestOnTop: true,
        preventDuplicates: true,
        timeout: 10000
    };

    /* Extend toastr.options with our defined overrides here */
    $.extend(toastr.options, OVERRIDES);

    showFlashNotifications();

    return {
        add: add,
        success: function (message, title, options) {
            add('success', message, title, options);
        },
        error: function (message, title, options) {
            add('error', message, title, options);
        },
        info: function (message, title, options) {
            add('info', message, title, options);
        },
        warning: function (message, title, options) {
            add('warning', message, title, options);
        }
    };

    /**
     * Show flash notifications on page load.
     */
    function showFlashNotifications() {
        var i = 0, l = flashNotifications.length;

        for (i; i < l; i++) {
            var item = flashNotifications[i];
            var type = item.type, message = item.message || '', title = item.title || '', timeout = item.timeout,
                options = {};

            /* Add timeout to the options object if it exists */
            if ('undefined' !== typeof timeout) {
                options.timeout = timeout;
            }

            add(type, message, title, options);
        }
    }

    /**
     * Add a new notification to Toastr
     * @param {string} type valid types for toastr: 'success', 'error', 'info', or 'warning'.
     * @param {string} message the notification message.
     * @param {string} title optional notification title
     * @param {object} options further options to pass into toastr
     */
    function add(type, message, title, options) {
        /* Call the toastr function if it exists */
        if ('function' === typeof toastr[type]) {
            toastr[type](message, title, options);
        }
    }
})(jQuery, toastr, window.notifications || []);

<|endoftext|>


<commit_before>'use strict';

const Immutable = require('immutable');

const collapseCashflows = (cashflows, startValue) => {
  startValue = typeof startValue === 'undefined' ? 0 : startValue;

  const sortByDate = (a, b) => {
    const dateA = parseInt(a.get('date').replace('-', ''), 10);
    const dateB = parseInt(b.get('date').replace('-', ''), 10);
    return dateA - dateB;
  };

  const mergeCashflowPoints = (cashflow) => {
    const mergedMap = cashflow.reduce((acc, point) => {
        const date = point.get('date');
        const grossAmount = point.get('grossAmount');
        const info = point.get('info');
        if (acc.has(date)) {
          acc = acc.setIn([date, 'grossAmount'], acc.getIn([date, 'grossAmount']) + grossAmount);
          acc = acc.setIn([date, 'info'], acc.getIn([date, 'info']).push(info));
        } else {
          acc = acc.set(date, point);
          acc = acc.setIn([date, 'info'], Immutable.Vector(info));
        }
        return acc;
      },
      Immutable.Map()
    );
    return mergedMap.toVector().sort(sortByDate);
  };

  // create startPoint with startValue and most ancient date. Insert it in history
  const getFlowFirstPoint = (cashflow) =>
    cashflow.reduce((firstPointAcc, point) => firstPointAcc = point.get('date') < firstPointAcc.get('date') ? point : firstPointAcc);

  const firstDate = cashflows.reduce((acc, flow) => flow.length > 0 && getFlowFirstPoint(flow).get('date') < acc ?
    getFlowFirstPoint(flow).get('date') : acc, 'z'
  );

  const startPoint = Immutable.Map({
    date: firstDate,
    grossAmount: startValue,
    info:{
      description: 'START_VALUE'
    }
  });

  cashflows = cashflows.set('history', cashflows.get('history').push(startPoint));

  // return cashflows with merged points
  return Immutable.Map({
    cashflow: cashflows.map((cashflow) => mergeCashflowPoints(cashflow))
  });
};

module.exports = collapseCashflows;
<commit_msg>[core] mergeCashflowPoints: fixed bug in sortByDatestr.replace('-') replaces only first occurence. now using str.split('-').join('') to remove all occurences before parsing to Int.<commit_after>'use strict';

const Immutable = require('immutable');

const collapseCashflows = (cashflows, startValue) => {
  startValue = typeof startValue === 'undefined' ? 0 : startValue;

  const sortByDate = (a, b) => {
    const dateA = parseInt(a.get('date').split('-').join(''), 10);
    const dateB = parseInt(b.get('date').split('-').join(''), 10);
    return dateA - dateB;
  };

  const mergeCashflowPoints = (cashflow) => {
    const mergedMap = cashflow.reduce((acc, point) => {
        const date = point.get('date');
        const grossAmount = point.get('grossAmount');
        const info = point.get('info');
        if (acc.has(date)) {
          acc = acc.setIn([date, 'grossAmount'], acc.getIn([date, 'grossAmount']) + grossAmount);
          acc = acc.setIn([date, 'info'], acc.getIn([date, 'info']).push(info));
        } else {
          acc = acc.set(date, point);
          acc = acc.setIn([date, 'info'], Immutable.Vector(info));
        }
        return acc;
      },
      Immutable.Map()
    );

    return mergedMap.toVector().sort(sortByDate);
  };

  // create startPoint with startValue and most ancient date. Insert it in history
  const getFlowFirstPoint = (cashflow) =>
    cashflow.reduce((firstPointAcc, point) => firstPointAcc = point.get('date') < firstPointAcc.get('date') ? point : firstPointAcc);

  const firstDate = cashflows.reduce((acc, flow) => flow.length > 0 && getFlowFirstPoint(flow).get('date') < acc ?
    getFlowFirstPoint(flow).get('date') : acc, 'z'
  );

  const startPoint = Immutable.Map({
    date: firstDate,
    grossAmount: startValue,
    info:{
      description: 'START_VALUE'
    }
  });

  cashflows = cashflows.set('history', cashflows.get('history').push(startPoint));

  // return cashflows with merged points
  return Immutable.Map({
    cashflow: cashflows.map((cashflow) => mergeCashflowPoints(cashflow))
  });
};

module.exports = collapseCashflows;
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import isEmpty from 'lodash/isEmpty';
import Components from 'rsg-components/Components';
import TableOfContents from 'rsg-components/TableOfContents';
import Message from 'rsg-components/Message';
import StyleGuideRenderer from 'rsg-components/StyleGuide/StyleGuideRenderer';
import { HOMEPAGE, DOCS_CONFIG } from '../../../scripts/consts';

export default class StyleGuide extends Component {
	static propTypes = {
		config: PropTypes.object.isRequired,
		components: PropTypes.array.isRequired,
		sections: PropTypes.array.isRequired,
		sidebar: PropTypes.bool,
		singleExample: PropTypes.bool,
	};
	static defaultProps = {
		sidebar: true,
	};
	static childContextTypes = {
		codeKey: PropTypes.number.isRequired,
		config: PropTypes.object.isRequired,
		singleExample: PropTypes.bool,
	};

	getChildContext() {
		return {
			codeKey: this.props.codeKey,
			config: this.props.config,
			singleExample: this.props.singleExample,
		};
	}

	renderComponents(components, sections, sidebar, singleExample) {
		if (!isEmpty(components) || !isEmpty(sections)) {
			return (
				<Components
					components={components}
					sections={sections}
					sidebar={sidebar}
				/>
			);
		}

		return (
			<Message>
				No components or sections found.
				Check [the `components` and `sections` options]({DOCS_CONFIG}) in your style guide config.
			</Message>
		);
	}

	renderTableOfContents(components, sections) {
		return <TableOfContents components={components} sections={sections} />;
	}

	render() {
		let { config, components, sections, sidebar, singleExample } = this.props;

		return (
			<StyleGuideRenderer
				title={config.title}
				homepageUrl={HOMEPAGE}
				components={this.renderComponents(components, sections, sidebar, singleExample)}
				sections={sections}
				toc={this.renderTableOfContents(components, sections)}
				sidebar={sidebar}
			/>
		);
	}
}
<commit_msg>Fix: Don’t show sidebar if there are no components found<commit_after>import React, { Component, PropTypes } from 'react';
import isEmpty from 'lodash/isEmpty';
import Components from 'rsg-components/Components';
import TableOfContents from 'rsg-components/TableOfContents';
import Message from 'rsg-components/Message';
import StyleGuideRenderer from 'rsg-components/StyleGuide/StyleGuideRenderer';
import { HOMEPAGE, DOCS_CONFIG } from '../../../scripts/consts';

export default class StyleGuide extends Component {
	static propTypes = {
		config: PropTypes.object.isRequired,
		components: PropTypes.array.isRequired,
		sections: PropTypes.array.isRequired,
		sidebar: PropTypes.bool,
		singleExample: PropTypes.bool,
	};
	static defaultProps = {
		sidebar: true,
	};
	static childContextTypes = {
		codeKey: PropTypes.number.isRequired,
		config: PropTypes.object.isRequired,
		singleExample: PropTypes.bool,
	};

	getChildContext() {
		return {
			codeKey: this.props.codeKey,
			config: this.props.config,
			singleExample: this.props.singleExample,
		};
	}

	renderComponents(components, sections, sidebar, singleExample) {
		if (!isEmpty(components) || !isEmpty(sections)) {
			return (
				<Components
					components={components}
					sections={sections}
					sidebar={sidebar}
				/>
			);
		}

		return (
			<Message>
				No components or sections found.
				Check [the `components` and `sections` options]({DOCS_CONFIG}) in your style guide config.
			</Message>
		);
	}

	renderTableOfContents(components, sections) {
		return <TableOfContents components={components} sections={sections} />;
	}

	render() {
		let { config, components, sections, sidebar, singleExample } = this.props;

		return (
			<StyleGuideRenderer
				title={config.title}
				homepageUrl={HOMEPAGE}
				components={this.renderComponents(components, sections, sidebar, singleExample)}
				sections={sections}
				toc={this.renderTableOfContents(components, sections)}
				sidebar={(isEmpty(components) && isEmpty(sections)) ? false : sidebar}
			/>
		);
	}
}
<|endoftext|>


<commit_before>/*!
 * ${copyright}
 */
sap.ui.define(['jquery.sap.global', './InputBaseRenderer', 'sap/ui/core/Renderer'],
	function(jQuery, InputBaseRenderer, Renderer) {
		"use strict";

		/**
		 * ComboBoxBase renderer.
		 *
		 * @namespace
		 */
		var ComboBoxBaseRenderer = Renderer.extend(InputBaseRenderer);

		/**
		 * CSS class to be applied to the root element of the ComboBoxBase.
		 *
		 * @readonly
		 * @const {string}
		 */
		ComboBoxBaseRenderer.CSS_CLASS = "sapMComboBoxBase";

		/**
		 * Add extra styles for input container.
		 *
		 * @param {sap.ui.core.RenderManager} oRm The RenderManager that can be used for writing to the render output buffer.
		 * @param {sap.ui.core.Control} oControl An object representation of the control that should be rendered.
		 */
		ComboBoxBaseRenderer.addOuterStyles = function(oRm, oControl) {
			oRm.addStyle("max-width", oControl.getMaxWidth());
		};

		/**
		 * Add classes to the ComboBox.
		 *
		 * @param {sap.ui.core.RenderManager} oRm The RenderManager that can be used for writing to the render output buffer.
		 * @param {sap.ui.core.Control} oControl An object representation of the control that should be rendered.
		 */
		ComboBoxBaseRenderer.addOuterClasses = function(oRm, oControl) {
			var CSS_CLASS = ComboBoxBaseRenderer.CSS_CLASS;

			oRm.addClass(CSS_CLASS);
			oRm.addClass(CSS_CLASS + "Input");

			if (!oControl.getEnabled()) {
				oRm.addClass(CSS_CLASS + "Disabled");
			}
		};

		/**
		 * Add inner classes to the ComboBox's input element.
		 *
		 * @param {sap.ui.core.RenderManager} oRm The RenderManager that can be used for writing to the render output buffer.
		 * @param {sap.ui.core.Control} oControl An object representation of the control that should be rendered.
		 */
		ComboBoxBaseRenderer.addInnerClasses = function(oRm, oControl) {
			oRm.addClass(ComboBoxBaseRenderer.CSS_CLASS + "InputInner");
		};

		/**
		 * Add inner styles to the ComboBox's input element.
		 *
		 * @param {sap.ui.core.RenderManager} oRm The RenderManager that can be used for writing to the render output buffer.
		 * @param {sap.ui.core.Control} oControl An object representation of the control that should be rendered.
		 */
		ComboBoxBaseRenderer.addInnerStyles = function(oRm, oControl) {
			oRm.writeAttribute("autocomplete", "off");
			oRm.writeAttribute("autocorrect", "off");
			oRm.writeAttribute("autocapitalize", "off");
		};

		/**
		 * Renders the ComboBox's arrow, using the provided {@link sap.ui.core.RenderManager}.
		 *
		 * @param {sap.ui.core.RenderManager} oRm The RenderManager that can be used for writing to the render output buffer.
		 * @param {sap.ui.core.Control} oControl An object representation of the control that should be rendered.
		 */
		ComboBoxBaseRenderer.writeInnerContent = function(oRm, oControl) {
			oRm.write('

");
		};

		return ComboBoxBaseRenderer;

	}, /* bExport= */ true);<commit_msg>[INTERNAL] m.ComboBox: adds the role presentation to the arrow<commit_after>/*!
 * ${copyright}
 */
sap.ui.define(['jquery.sap.global', './InputBaseRenderer', 'sap/ui/core/Renderer'],
	function(jQuery, InputBaseRenderer, Renderer) {
		"use strict";

		/**
		 * ComboBoxBase renderer.
		 *
		 * @namespace
		 */
		var ComboBoxBaseRenderer = Renderer.extend(InputBaseRenderer);

		/**
		 * CSS class to be applied to the root element of the ComboBoxBase.
		 *
		 * @readonly
		 * @const {string}
		 */
		ComboBoxBaseRenderer.CSS_CLASS = "sapMComboBoxBase";

		/**
		 * Add extra styles for input container.
		 *
		 * @param {sap.ui.core.RenderManager} oRm The RenderManager that can be used for writing to the render output buffer.
		 * @param {sap.ui.core.Control} oControl An object representation of the control that should be rendered.
		 */
		ComboBoxBaseRenderer.addOuterStyles = function(oRm, oControl) {
			oRm.addStyle("max-width", oControl.getMaxWidth());
		};

		/**
		 * Add classes to the ComboBox.
		 *
		 * @param {sap.ui.core.RenderManager} oRm The RenderManager that can be used for writing to the render output buffer.
		 * @param {sap.ui.core.Control} oControl An object representation of the control that should be rendered.
		 */
		ComboBoxBaseRenderer.addOuterClasses = function(oRm, oControl) {
			var CSS_CLASS = ComboBoxBaseRenderer.CSS_CLASS;

			oRm.addClass(CSS_CLASS);
			oRm.addClass(CSS_CLASS + "Input");

			if (!oControl.getEnabled()) {
				oRm.addClass(CSS_CLASS + "Disabled");
			}
		};

		/**
		 * Add inner classes to the ComboBox's input element.
		 *
		 * @param {sap.ui.core.RenderManager} oRm The RenderManager that can be used for writing to the render output buffer.
		 * @param {sap.ui.core.Control} oControl An object representation of the control that should be rendered.
		 */
		ComboBoxBaseRenderer.addInnerClasses = function(oRm, oControl) {
			oRm.addClass(ComboBoxBaseRenderer.CSS_CLASS + "InputInner");
		};

		/**
		 * Add inner styles to the ComboBox's input element.
		 *
		 * @param {sap.ui.core.RenderManager} oRm The RenderManager that can be used for writing to the render output buffer.
		 * @param {sap.ui.core.Control} oControl An object representation of the control that should be rendered.
		 */
		ComboBoxBaseRenderer.addInnerStyles = function(oRm, oControl) {
			oRm.writeAttribute("autocomplete", "off");
			oRm.writeAttribute("autocorrect", "off");
			oRm.writeAttribute("autocapitalize", "off");
		};

		/**
		 * Renders the ComboBox's arrow, using the provided {@link sap.ui.core.RenderManager}.
		 *
		 * @param {sap.ui.core.RenderManager} oRm The RenderManager that can be used for writing to the render output buffer.
		 * @param {sap.ui.core.Control} oControl An object representation of the control that should be rendered.
		 */
		ComboBoxBaseRenderer.writeInnerContent = function(oRm, oControl) {
			oRm.write('

");
		};

		return ComboBoxBaseRenderer;

	}, /* bExport= */ true);<|endoftext|>


<commit_before>/*!
 * ${copyright}
 */

sap.ui.define([
	"./library"
], function(
	library
) {
	"use strict";

	/**
	 * @private
	 * @ui5-restricted sap.m.P13nFilterPanel
	 * @since 1.74
	 * @alias sap.m.P13nOperationsHelper
	 */
	var P13nOperationsHelper = function () {
		this.init();
	};

	var Operation = library.P13nConditionOperation;

	P13nOperationsHelper.prototype.oIncludeOperations = {
		"default": [
			Operation.EQ,
			Operation.BT,
			Operation.LT,
			Operation.LE,
			Operation.GT,
			Operation.GE
		],
		"string": [
			Operation.Contains,
			Operation.EQ,
			Operation.BT,
			Operation.StartsWith,
			Operation.EndsWith,
			Operation.LT,
			Operation.LE,
			Operation.GT,
			Operation.GE
		],
		"date": [
			Operation.EQ,
			Operation.BT,
			Operation.LT,
			Operation.LE,
			Operation.GT,
			Operation.GE
		],
		"time": [
			Operation.EQ,
			Operation.BT,
			Operation.LT,
			Operation.LE,
			Operation.GT,
			Operation.GE
		],
		"datetime": [
			Operation.EQ,
			Operation.BT,
			Operation.LT,
			Operation.LE,
			Operation.GT,
			Operation.GE
		],
		"numeric": [
			Operation.EQ,
			Operation.BT,
			Operation.LT,
			Operation.LE,
			Operation.GT,
			Operation.GE
		],
		"numc": [
			Operation.Contains,
			Operation.EQ,
			Operation.BT,
			Operation.EndsWith,
			Operation.LT,
			Operation.LE,
			Operation.GT,
			Operation.GE
		],
		"boolean": [
			Operation.EQ
		]
	};
	P13nOperationsHelper.prototype.oExcludeOperationsDefault = {
		"default": [
				Operation.EQ
			]
	};
	P13nOperationsHelper.prototype.oExcludeOperationsExtended = {
		"default": [
			Operation.EQ,
			Operation.BT,
			Operation.LT,
			Operation.LE,
			Operation.GT,
			Operation.GE
		],
		"string": [
			Operation.Contains,
			Operation.EQ,
			Operation.BT,
			Operation.StartsWith,
			Operation.EndsWith,
			Operation.LT,
			Operation.LE,
			Operation.GT,
			Operation.GE
		],
		"date": [
			Operation.EQ,
			Operation.BT,
			Operation.LT,
			Operation.LE,
			Operation.GT,
			Operation.GE
		],
		"time": [
			Operation.EQ,
			Operation.BT,
			Operation.LT,
			Operation.LE,
			Operation.GT,
			Operation.GE
		],
		"datetime": [
			Operation.EQ,
			Operation.BT,
			Operation.LT,
			Operation.LE,
			Operation.GT,
			Operation.GE
		],
		"numeric": [
			Operation.EQ,
			Operation.BT,
			Operation.LT,
			Operation.LE,
			Operation.GT,
			Operation.GE
		],
		"numc": [
			Operation.Contains,
			Operation.EQ,
			Operation.BT,
			Operation.EndsWith,
			Operation.LT,
			Operation.LE,
			Operation.GT,
			Operation.GE
		],
		"boolean": [
			Operation.EQ
		]
	};

	P13nOperationsHelper.prototype.init = function () {
		this.oExcludeOperations = this.oExcludeOperationsDefault;
	};

	P13nOperationsHelper.prototype.setUseExcludeOperationsExtended = function () {
		this.oExcludeOperations = this.oExcludeOperationsExtended;
	};

	P13nOperationsHelper.prototype.getIncludeOperationsByType = function (sType) {
		if (!sType) {
			sType = "default";
		}
		// Return a copy of the operations list so it could be modified later per field
		return this.oIncludeOperations[sType].map(function (sOperation) {return sOperation;});
	};

	P13nOperationsHelper.prototype.getExcludeOperationsByType = function (sType) {
		if (!sType) {
			sType = "default";
		}
		// Return a copy of the operations list so it could be modified later per field
		return this.oExcludeOperations[sType].map(function (sOperation) {return sOperation;});
	};

	P13nOperationsHelper.prototype.getIncludeTypes = function () {
		return Object.keys(this.oIncludeOperations);
	};

	P13nOperationsHelper.prototype.getExcludeTypes = function () {
		return Object.keys(this.oExcludeOperations);
	};

	return P13nOperationsHelper;

}, /* bExport= */true);
<commit_msg>[INTERNAL] sap.m.P13nOperationsHelper: fix JSDoc (it's a class)<commit_after>/*!
 * ${copyright}
 */

sap.ui.define([
	"./library"
], function(
	library
) {
	"use strict";

	/**
	 * @private
	 * @ui5-restricted sap.m.P13nFilterPanel
	 * @since 1.74
	 * @alias sap.m.P13nOperationsHelper
	 * @class
	 */
	var P13nOperationsHelper = function () {
		this.init();
	};

	var Operation = library.P13nConditionOperation;

	P13nOperationsHelper.prototype.oIncludeOperations = {
		"default": [
			Operation.EQ,
			Operation.BT,
			Operation.LT,
			Operation.LE,
			Operation.GT,
			Operation.GE
		],
		"string": [
			Operation.Contains,
			Operation.EQ,
			Operation.BT,
			Operation.StartsWith,
			Operation.EndsWith,
			Operation.LT,
			Operation.LE,
			Operation.GT,
			Operation.GE
		],
		"date": [
			Operation.EQ,
			Operation.BT,
			Operation.LT,
			Operation.LE,
			Operation.GT,
			Operation.GE
		],
		"time": [
			Operation.EQ,
			Operation.BT,
			Operation.LT,
			Operation.LE,
			Operation.GT,
			Operation.GE
		],
		"datetime": [
			Operation.EQ,
			Operation.BT,
			Operation.LT,
			Operation.LE,
			Operation.GT,
			Operation.GE
		],
		"numeric": [
			Operation.EQ,
			Operation.BT,
			Operation.LT,
			Operation.LE,
			Operation.GT,
			Operation.GE
		],
		"numc": [
			Operation.Contains,
			Operation.EQ,
			Operation.BT,
			Operation.EndsWith,
			Operation.LT,
			Operation.LE,
			Operation.GT,
			Operation.GE
		],
		"boolean": [
			Operation.EQ
		]
	};
	P13nOperationsHelper.prototype.oExcludeOperationsDefault = {
		"default": [
				Operation.EQ
			]
	};
	P13nOperationsHelper.prototype.oExcludeOperationsExtended = {
		"default": [
			Operation.EQ,
			Operation.BT,
			Operation.LT,
			Operation.LE,
			Operation.GT,
			Operation.GE
		],
		"string": [
			Operation.Contains,
			Operation.EQ,
			Operation.BT,
			Operation.StartsWith,
			Operation.EndsWith,
			Operation.LT,
			Operation.LE,
			Operation.GT,
			Operation.GE
		],
		"date": [
			Operation.EQ,
			Operation.BT,
			Operation.LT,
			Operation.LE,
			Operation.GT,
			Operation.GE
		],
		"time": [
			Operation.EQ,
			Operation.BT,
			Operation.LT,
			Operation.LE,
			Operation.GT,
			Operation.GE
		],
		"datetime": [
			Operation.EQ,
			Operation.BT,
			Operation.LT,
			Operation.LE,
			Operation.GT,
			Operation.GE
		],
		"numeric": [
			Operation.EQ,
			Operation.BT,
			Operation.LT,
			Operation.LE,
			Operation.GT,
			Operation.GE
		],
		"numc": [
			Operation.Contains,
			Operation.EQ,
			Operation.BT,
			Operation.EndsWith,
			Operation.LT,
			Operation.LE,
			Operation.GT,
			Operation.GE
		],
		"boolean": [
			Operation.EQ
		]
	};

	P13nOperationsHelper.prototype.init = function () {
		this.oExcludeOperations = this.oExcludeOperationsDefault;
	};

	P13nOperationsHelper.prototype.setUseExcludeOperationsExtended = function () {
		this.oExcludeOperations = this.oExcludeOperationsExtended;
	};

	P13nOperationsHelper.prototype.getIncludeOperationsByType = function (sType) {
		if (!sType) {
			sType = "default";
		}
		// Return a copy of the operations list so it could be modified later per field
		return this.oIncludeOperations[sType].map(function (sOperation) {return sOperation;});
	};

	P13nOperationsHelper.prototype.getExcludeOperationsByType = function (sType) {
		if (!sType) {
			sType = "default";
		}
		// Return a copy of the operations list so it could be modified later per field
		return this.oExcludeOperations[sType].map(function (sOperation) {return sOperation;});
	};

	P13nOperationsHelper.prototype.getIncludeTypes = function () {
		return Object.keys(this.oIncludeOperations);
	};

	P13nOperationsHelper.prototype.getExcludeTypes = function () {
		return Object.keys(this.oExcludeOperations);
	};

	return P13nOperationsHelper;

}, /* bExport= */true);
<|endoftext|>


<commit_before>/* global module */

module.exports = [
	"ActionSelect.spec.js",
	"ActionSheet.spec.js",
	"App.spec.js",
	"AppWithBackground.spec.js",
	"Breadcrumbs.spec.js",
	// "Carousel.spec.js",
	"CheckBox.spec.js",
	"ComboBox.spec.js",
	"ContextMenuSupportIntegration.spec.js",
	// "Dialog.spec.js",
	// "IconTabBar.spec.js",
	"Image.spec.js",
	"Label.spec.js",
	"LightBox.spec.js",
	"Link.spec.js",
	"MessageBox.spec.js",
	"MessagePage.spec.js",
	"MessagePopover.spec.js",
	"MessageStrip.spec.js",
	"MessageToast.spec.js",
	"MessageView.spec.js",
	"MultiInput.spec.js",
	"NotificationListGroup.spec.js",
	"NotificationListItem.spec.js",
	"ObjectHeaderVisualTest.spec.js",
	"ObjectNumberVisualTest.spec.js",
	"OverflowToolbar.spec.js",
	"OverflowToolbarInRTE.spec.js",
	"Page.spec.js",
	"Panel.spec.js",
	"PlanningCalendar.spec.js",
	"Popover.spec.js",
	"ProgressIndicator.spec.js",
	// "QuickView.spec.js",
	"QuickViewCard.spec.js",
	"RadioButton.spec.js",
	// "RadioButtonGroup.spec.js",
	"RatingIndicator.spec.js",
	"ResponsivePopover.spec.js",
	"Select.spec.js",
	"SelectDialog.spec.js",
	"SemanticPage.spec.js",
	// "SplitApp.spec.js",
	"StepInput.spec.js",
	"Switch.spec.js",
	"Toolbar.spec.js",
	"TableSelectDialog.spec.js",
	// "Text.spec.js",
	"TimePicker.spec.js",
	"Token.spec.js",
	"Tokenizer.spec.js",
	"Wizard.spec.js"
];
<commit_msg>[INTERNAL] VisualTests: now working<commit_after>/* global module */

module.exports = [
	"ActionSelect.spec.js",
	"ActionSheet.spec.js",
	"App.spec.js",
	"AppWithBackground.spec.js",
	"Breadcrumbs.spec.js",
	"Carousel.spec.js",
	"CheckBox.spec.js",
	"ComboBox.spec.js",
	"ContextMenuSupportIntegration.spec.js",
	"Dialog.spec.js",
	"IconTabBar.spec.js",
	"Image.spec.js",
	"Label.spec.js",
	"LightBox.spec.js",
	"Link.spec.js",
	"MessageBox.spec.js",
	"MessagePage.spec.js",
	"MessagePopover.spec.js",
	"MessageStrip.spec.js",
	"MessageToast.spec.js",
	"MessageView.spec.js",
	"MultiInput.spec.js",
	"NotificationListGroup.spec.js",
	"NotificationListItem.spec.js",
	"ObjectHeaderVisualTest.spec.js",
	"ObjectNumberVisualTest.spec.js",
	"OverflowToolbar.spec.js",
	"OverflowToolbarInRTE.spec.js",
	"Page.spec.js",
	"Panel.spec.js",
	"PlanningCalendar.spec.js",
	"Popover.spec.js",
	"ProgressIndicator.spec.js",
	"QuickView.spec.js",
	"QuickViewCard.spec.js",
	"RadioButton.spec.js",
	"RadioButtonGroup.spec.js",
	"RatingIndicator.spec.js",
	"ResponsivePopover.spec.js",
	"Select.spec.js",
	"SelectDialog.spec.js",
	"SemanticPage.spec.js",
	"SplitApp.spec.js",
	"StepInput.spec.js",
	"Switch.spec.js",
	"Toolbar.spec.js",
	"TableSelectDialog.spec.js",
	"Text.spec.js",
	"TimePicker.spec.js",
	"Token.spec.js",
	"Tokenizer.spec.js",
	"Wizard.spec.js"
];
<|endoftext|>


<commit_before>/*!
 * ${copyright}
 */
/*global QUnit */
sap.ui.define([
	'sap/ui/thirdparty/URI',
	'sap/ui/test/Opa',
	'sap/ui/test/Opa5',
	"sap/ui/thirdparty/jquery",
	'sap/ui/test/qunitPause'
], function(URI, Opa, Opa5, jQueryDOM, QUnitPause) {
	"use strict";

	QUnitPause.setupAfterQUnit();

	QUnit.begin(function (oDetails) {
		Opa._usageReport.begin({uri: new URI().toString(), totalTests: oDetails.totalTests});
	});

	QUnit.moduleStart(function (oDetails) {
		Opa._usageReport.moduleStart(oDetails);
	});

	QUnit.testStart(function () {
		Opa._usageReport.testStart();
	});

	QUnit.testDone(function (oDetails) {
		Opa._usageReport.testDone(oDetails);

		var bQUnitTimeout = oDetails.assertions.some(function (oAssertion) {
			return !oAssertion.result && oAssertion.message === "Test timed out";
		});

		if (bQUnitTimeout) {
			Opa._stopQueue({qunitTimeout: QUnit.config.testTimeout / 1000});
		}
	});

	QUnit.moduleDone(function (oDetails) {
		Opa._usageReport.moduleDone(oDetails);
	});

	QUnit.done(function (oDetails) {
		Opa._usageReport.done(oDetails);
	});

	/* When you require this file, it will also introduce global variables: opaTest, opaSkip and opaTodo.
	 * It will also alter some settings of QUnit.config - testTimout will be increased to 90 if you do not specify your own.
	 * QUnit.reorder will be set to false, because OPA tests are often depending on each other.
	 */

	// Export to global namespace to be backwards compatible
	window.opaSkip = opaSkip;
	window.opaTest = opaTest;
	// QUnit.todo introduced in v2
	window.opaTodo = QUnit.todo ? opaTodo : opaTest;

	/**
	 * QUnit test adapter for OPA: add a test to be executed by QUnit
	 * Has the same signature as QUnit.test (QUnit version is also considered)
	 * Suggested usage:
	 *

	 * sap.ui.require(["sap/ui/test/Opa5", "sap/ui/test/opaQunit"], function (Opa5, opaTest) {
	 *
	 *    Opa5.extendConfig({
	 *        assertions: new Opa5({
	 *            checkIfSomethingIsOk : function () {
	 *                this.waitFor({
	 *                    success: function () {
	 *                        Opa5.assert.ok(true, "Everything is fine");
	 *                    }
	 *                });
	 *            }
	 *        })
	 *    });
	 *
	 *    opaTest("Should test something", function (Given, When, Then) {
	 *       // Implementation of the test
	 *       Then.checkIfSomethingIsOk();
	 *    });
	 *
	 * });
	 *

	 *
	 * @public
	 * @alias module:sap/ui/test/opaQunit
	 * @function
	 * @static
	 * @param {string} testName name of the QUnit test.
	 * @param {int} [expected] only supported in QUnit v1.x: denotes how many assertions are expected to be made in the test.
	 * @param {function} callback the test function. Expects 3 arguments, in order:
	 * {@link sap.ui.test.Opa.config}.arrangements, {@link sap.ui.test.Opa.config}.actions, {@link sap.ui.test.Opa.config}.assertions.
	 * These arguments will be prefilled by OPA
	 * @param {boolean} [async=false] available only in QUnit v1.x. Indicates whether the test is asynchronous. False by default.
	 */
	function opaTest() {
		callQUnit("test", arguments, function (assert, fnDone) {
			Opa._usageReport.opaEmpty();
			resetOPA();
			fnDone();
		}, function (assert, fnDone, oOptions) {
			Opa._usageReport.opaEmpty(oOptions);

			// add the error message to QUnit test results
			// will cause exception in case of QUnit timeout since the last test has already finished
			// ("Cannot read property 'failedAssertions' of null")
			assert.ok(false, oOptions.errorMessage);

			resetOPA();

			if (!QUnitPause.shouldPauseOnAssert()) {
				QUnitPause.emitPause();
			}

			var oPauseDeferred = jQueryDOM.Deferred();
			QUnitPause.onResume(function () {
				// let OPA finish before QUnit starts executing the next test
				// call fnStart only if QUnit did not timeout
				if (!oOptions.qunitTimeout) {
					setTimeout(fnDone, 0);
				}
				oPauseDeferred.resolve();
			});

			return oPauseDeferred.promise();
		});
	}

	/**
	 * QUnit test adapter for OPA: add a test to be executed by QUnit
	 * The test is expected to have at least one failing assertion during its run, or to timeout with either OPA or QUnit timeout
	 * Has the same signature as QUnit.todo (QUnit version is also considered)
	 *
	 * @public
	 * @function
	 * @static
	 * @param {string} testName name of the QUnit test.
	 * @param {int} [expected] only supported in QUnit v1.x: denotes how many assertions are expected to be made in the test.
	 * @param {function} callback the test function. Expects 3 arguments, in order:
	 * {@link sap.ui.test.Opa.config}.arrangements, {@link sap.ui.test.Opa.config}.actions, {@link sap.ui.test.Opa.config}.assertions.
	 * These arguments will be prefilled by OPA
	 * @param {boolean} [async=false] available only in QUnit v1.x. Indicates whether the test is asynchronous. False by default.
	 */
	function opaTodo() {
		callQUnit("todo", arguments, function (assert, fnDone) {
			resetOPA();
			fnDone();
		}, function (assert, fnDone, oOptions) {
			if (oOptions.qunitTimeout) {
				resetOPA();
			} else {
				// to pass the test, add error in case of OPA timeout
				assert.ok(false, oOptions.errorMessage);
				resetOPA();
				// let OPA finish before QUnit starts executing the next test
				// call fnStart only if QUnit did not timeout
				setTimeout(fnDone, 0);
			}
		});
	}

	/**
	 * QUnit test adapter for OPA: add a test to be skipped by QUnit
	 * Has the same signature as QUnit.skip (QUnit version is also considered)
	 *
	 * @public
	 * @function
	 * @static
	 * @param {string} testName name of the QUnit test.
	 * @param {int} [expected] only supported in QUnit v1.x: denotes how many assertions are expected to be made in the test.
	 * @param {function} callback the test function. Expects 3 arguments, in order:
	 * {@link sap.ui.test.Opa.config}.arrangements, {@link sap.ui.test.Opa.config}.actions, {@link sap.ui.test.Opa.config}.assertions.
	 * These arguments will be prefilled by OPA
	 * @param {boolean} [async=false] available only in QUnit v1.x. Indicates whether the test is asynchronous. False by default.
	 */
	function opaSkip(testName, expected, callback, async) {
		configQUnit();
		var fnTestBody = function () {};
		if (isQUnit2()) {
			QUnit.skip(testName, fnTestBody);
		} else {
			QUnit.skip(testName, expected, fnTestBody, async);
		}
	}

	// configure QUnit, modify test callback to include OPA start, and enqueue the test with QUnit
	function callQUnit(sQUnitFn, aArgs, fnDone, fnFail) {
		configQUnit();
		// parse arguments passed to OPA adapter
		var mTestBodyArgs = {
			testName: aArgs[0],
			expected: aArgs.length === 2 ? null : aArgs[1],
			callback: aArgs.length === 2 ? aArgs[1] : aArgs[2],
			async: aArgs[3]
		};

		if (isQUnit2() && typeof mTestBodyArgs.async !== "undefined") {
			throw new Error("Qunit >=2.0 is used, which no longer supports the 'async' parameter for tests.");
		}

		// create and configure the callback to be executed by QUnit at test runtime
		var fnTestBody = createTestBody(mTestBodyArgs, fnDone, fnFail);

		// build arguments for the adapted QUnit function
		var mQUnitFnArgs = [mTestBodyArgs.testName, fnTestBody, mTestBodyArgs.async];

		if (!isQUnit2()) {
			mQUnitFnArgs.splice(1, 0, mTestBodyArgs.expected);
		}

		// call adapted QUnit function
		QUnit[sQUnitFn].apply(this, mQUnitFnArgs);
	}

	// include OPA configuration and queue execution in test callback
	function createTestBody(mConfig, fnDone, fnFail) {
		return function(assert) {
			var fnAsync = assert.async();
			Opa.config.testName = mConfig.testName;
			Opa.assert = assert;
			Opa5.assert = assert;

			if (isQUnit2() && mConfig.expected !== null) {
				assert.expect(mConfig.expected);
			}

			// fill in OPA queue
			// preserve QUnit 'this' in order to access it from waitFor statements
			mConfig.callback.call(this, Opa.config.arrangements, Opa.config.actions, Opa.config.assertions);

			QUnitPause.setupBeforeOpaTest();

			Opa.emptyQueue()
				.done(function () {
					fnDone(assert, fnAsync);
				})
				.fail(function (oOptions) {
					fnFail(assert, fnAsync, oOptions);
				});
		};
	}

	function configQUnit() {
		//Increase QUnit's timeout to 90 seconds to match default OPA timeouts
		// is only done if there is no timeout or the timeout is the default of QUnit
		if (!QUnit.config.testTimeout || QUnit.config.testTimeout === 30000) {
			QUnit.config.testTimeout  = 90000;
		}
		QUnit.config.reorder = false;
		// better chance that screenshots will capture the current failure
		QUnit.config.scrolltop = false;
	}

	function resetOPA() {
		Opa.assert = undefined;
		Opa5.assert = undefined;
	}

	function isQUnit2() {
		return QUnit.test.length === 2;
	}

	QUnit.config.urlConfig.push({
		id: "opaExecutionDelay",
		value: {
			400: "fast",
			700: "medium",
			1000: "slow"
		},
		label: "Opa speed",
		tooltip: "Each waitFor will be delayed by a number of milliseconds. If it is not set Opa will execute the tests as fast as possible"
	});

	// synchronously hook QUnit custom async assertions from extension
	Opa5._getEventProvider().attachEvent('onExtensionAfterInit',function(oEvent) {
		var oParams = oEvent.getParameters();
		if (oParams.extension.getAssertions) {
			var oAssertions = oParams.extension.getAssertions();
			jQueryDOM.each(oAssertions,function(sName,fnAssertion) {
				QUnit.assert[sName] = function() {
					var qunitThis = this;
					// call the assertion in the app window
					// assertion is async, push results when ready
					var oAssertionPromise = fnAssertion.apply(oParams.appWindow, arguments)
						.always(function (oResult) {
							qunitThis.push(
								oResult.result,
								oResult.actual,
								oResult.expected,
								oResult.message
							);
						});

					// schedule async assertion promise on waitFor flow so test waits till assertion is ready
					Opa.config.assertions._schedulePromiseOnFlow(oAssertionPromise);
				};
			});
		}
	});

	return opaTest;
});
<commit_msg>[INTERNAL] opaQunit: show ui5 version in qunit page<commit_after>/*!
 * ${copyright}
 */
/*global QUnit */
sap.ui.define([
	'sap/ui/thirdparty/URI',
	'sap/ui/test/Opa',
	'sap/ui/test/Opa5',
	"sap/ui/thirdparty/jquery",
	'sap/ui/test/qunitPause'
], function(URI, Opa, Opa5, jQueryDOM, QUnitPause) {
	"use strict";

	QUnitPause.setupAfterQUnit();

	QUnit.begin(function (oDetails) {
		// add ui5 version in the user agent string bar
		if (sap && sap.ui) {
			jQueryDOM('#qunit-userAgent')[0].innerText += "; UI5: " + sap.ui.version;
		}

		Opa._usageReport.begin({uri: new URI().toString(), totalTests: oDetails.totalTests});
	});

	QUnit.moduleStart(function (oDetails) {
		Opa._usageReport.moduleStart(oDetails);
	});

	QUnit.testStart(function () {
		Opa._usageReport.testStart();
	});

	QUnit.testDone(function (oDetails) {
		Opa._usageReport.testDone(oDetails);

		var bQUnitTimeout = oDetails.assertions.some(function (oAssertion) {
			return !oAssertion.result && oAssertion.message === "Test timed out";
		});

		if (bQUnitTimeout) {
			Opa._stopQueue({qunitTimeout: QUnit.config.testTimeout / 1000});
		}
	});

	QUnit.moduleDone(function (oDetails) {
		Opa._usageReport.moduleDone(oDetails);
	});

	QUnit.done(function (oDetails) {
		Opa._usageReport.done(oDetails);
	});

	/* When you require this file, it will also introduce global variables: opaTest, opaSkip and opaTodo.
	 * It will also alter some settings of QUnit.config - testTimout will be increased to 90 if you do not specify your own.
	 * QUnit.reorder will be set to false, because OPA tests are often depending on each other.
	 */

	// Export to global namespace to be backwards compatible
	window.opaSkip = opaSkip;
	window.opaTest = opaTest;
	// QUnit.todo introduced in v2
	window.opaTodo = QUnit.todo ? opaTodo : opaTest;

	/**
	 * QUnit test adapter for OPA: add a test to be executed by QUnit
	 * Has the same signature as QUnit.test (QUnit version is also considered)
	 * Suggested usage:
	 *

	 * sap.ui.require(["sap/ui/test/Opa5", "sap/ui/test/opaQunit"], function (Opa5, opaTest) {
	 *
	 *    Opa5.extendConfig({
	 *        assertions: new Opa5({
	 *            checkIfSomethingIsOk : function () {
	 *                this.waitFor({
	 *                    success: function () {
	 *                        Opa5.assert.ok(true, "Everything is fine");
	 *                    }
	 *                });
	 *            }
	 *        })
	 *    });
	 *
	 *    opaTest("Should test something", function (Given, When, Then) {
	 *       // Implementation of the test
	 *       Then.checkIfSomethingIsOk();
	 *    });
	 *
	 * });
	 *

	 *
	 * @public
	 * @alias module:sap/ui/test/opaQunit
	 * @function
	 * @static
	 * @param {string} testName name of the QUnit test.
	 * @param {int} [expected] only supported in QUnit v1.x: denotes how many assertions are expected to be made in the test.
	 * @param {function} callback the test function. Expects 3 arguments, in order:
	 * {@link sap.ui.test.Opa.config}.arrangements, {@link sap.ui.test.Opa.config}.actions, {@link sap.ui.test.Opa.config}.assertions.
	 * These arguments will be prefilled by OPA
	 * @param {boolean} [async=false] available only in QUnit v1.x. Indicates whether the test is asynchronous. False by default.
	 */
	function opaTest() {
		callQUnit("test", arguments, function (assert, fnDone) {
			Opa._usageReport.opaEmpty();
			resetOPA();
			fnDone();
		}, function (assert, fnDone, oOptions) {
			Opa._usageReport.opaEmpty(oOptions);

			// add the error message to QUnit test results
			// will cause exception in case of QUnit timeout since the last test has already finished
			// ("Cannot read property 'failedAssertions' of null")
			assert.ok(false, oOptions.errorMessage);

			resetOPA();

			if (!QUnitPause.shouldPauseOnAssert()) {
				QUnitPause.emitPause();
			}

			var oPauseDeferred = jQueryDOM.Deferred();
			QUnitPause.onResume(function () {
				// let OPA finish before QUnit starts executing the next test
				// call fnStart only if QUnit did not timeout
				if (!oOptions.qunitTimeout) {
					setTimeout(fnDone, 0);
				}
				oPauseDeferred.resolve();
			});

			return oPauseDeferred.promise();
		});
	}

	/**
	 * QUnit test adapter for OPA: add a test to be executed by QUnit
	 * The test is expected to have at least one failing assertion during its run, or to timeout with either OPA or QUnit timeout
	 * Has the same signature as QUnit.todo (QUnit version is also considered)
	 *
	 * @public
	 * @function
	 * @static
	 * @param {string} testName name of the QUnit test.
	 * @param {int} [expected] only supported in QUnit v1.x: denotes how many assertions are expected to be made in the test.
	 * @param {function} callback the test function. Expects 3 arguments, in order:
	 * {@link sap.ui.test.Opa.config}.arrangements, {@link sap.ui.test.Opa.config}.actions, {@link sap.ui.test.Opa.config}.assertions.
	 * These arguments will be prefilled by OPA
	 * @param {boolean} [async=false] available only in QUnit v1.x. Indicates whether the test is asynchronous. False by default.
	 */
	function opaTodo() {
		callQUnit("todo", arguments, function (assert, fnDone) {
			resetOPA();
			fnDone();
		}, function (assert, fnDone, oOptions) {
			if (oOptions.qunitTimeout) {
				resetOPA();
			} else {
				// to pass the test, add error in case of OPA timeout
				assert.ok(false, oOptions.errorMessage);
				resetOPA();
				// let OPA finish before QUnit starts executing the next test
				// call fnStart only if QUnit did not timeout
				setTimeout(fnDone, 0);
			}
		});
	}

	/**
	 * QUnit test adapter for OPA: add a test to be skipped by QUnit
	 * Has the same signature as QUnit.skip (QUnit version is also considered)
	 *
	 * @public
	 * @function
	 * @static
	 * @param {string} testName name of the QUnit test.
	 * @param {int} [expected] only supported in QUnit v1.x: denotes how many assertions are expected to be made in the test.
	 * @param {function} callback the test function. Expects 3 arguments, in order:
	 * {@link sap.ui.test.Opa.config}.arrangements, {@link sap.ui.test.Opa.config}.actions, {@link sap.ui.test.Opa.config}.assertions.
	 * These arguments will be prefilled by OPA
	 * @param {boolean} [async=false] available only in QUnit v1.x. Indicates whether the test is asynchronous. False by default.
	 */
	function opaSkip(testName, expected, callback, async) {
		configQUnit();
		var fnTestBody = function () {};
		if (isQUnit2()) {
			QUnit.skip(testName, fnTestBody);
		} else {
			QUnit.skip(testName, expected, fnTestBody, async);
		}
	}

	// configure QUnit, modify test callback to include OPA start, and enqueue the test with QUnit
	function callQUnit(sQUnitFn, aArgs, fnDone, fnFail) {
		configQUnit();
		// parse arguments passed to OPA adapter
		var mTestBodyArgs = {
			testName: aArgs[0],
			expected: aArgs.length === 2 ? null : aArgs[1],
			callback: aArgs.length === 2 ? aArgs[1] : aArgs[2],
			async: aArgs[3]
		};

		if (isQUnit2() && typeof mTestBodyArgs.async !== "undefined") {
			throw new Error("Qunit >=2.0 is used, which no longer supports the 'async' parameter for tests.");
		}

		// create and configure the callback to be executed by QUnit at test runtime
		var fnTestBody = createTestBody(mTestBodyArgs, fnDone, fnFail);

		// build arguments for the adapted QUnit function
		var mQUnitFnArgs = [mTestBodyArgs.testName, fnTestBody, mTestBodyArgs.async];

		if (!isQUnit2()) {
			mQUnitFnArgs.splice(1, 0, mTestBodyArgs.expected);
		}

		// call adapted QUnit function
		QUnit[sQUnitFn].apply(this, mQUnitFnArgs);
	}

	// include OPA configuration and queue execution in test callback
	function createTestBody(mConfig, fnDone, fnFail) {
		return function(assert) {
			var fnAsync = assert.async();
			Opa.config.testName = mConfig.testName;
			Opa.assert = assert;
			Opa5.assert = assert;

			if (isQUnit2() && mConfig.expected !== null) {
				assert.expect(mConfig.expected);
			}

			// fill in OPA queue
			// preserve QUnit 'this' in order to access it from waitFor statements
			mConfig.callback.call(this, Opa.config.arrangements, Opa.config.actions, Opa.config.assertions);

			QUnitPause.setupBeforeOpaTest();

			Opa.emptyQueue()
				.done(function () {
					fnDone(assert, fnAsync);
				})
				.fail(function (oOptions) {
					fnFail(assert, fnAsync, oOptions);
				});
		};
	}

	function configQUnit() {
		//Increase QUnit's timeout to 90 seconds to match default OPA timeouts
		// is only done if there is no timeout or the timeout is the default of QUnit
		if (!QUnit.config.testTimeout || QUnit.config.testTimeout === 30000) {
			QUnit.config.testTimeout  = 90000;
		}
		QUnit.config.reorder = false;
		// better chance that screenshots will capture the current failure
		QUnit.config.scrolltop = false;
	}

	function resetOPA() {
		Opa.assert = undefined;
		Opa5.assert = undefined;
	}

	function isQUnit2() {
		return QUnit.test.length === 2;
	}

	QUnit.config.urlConfig.push({
		id: "opaExecutionDelay",
		value: {
			400: "fast",
			700: "medium",
			1000: "slow"
		},
		label: "Opa speed",
		tooltip: "Each waitFor will be delayed by a number of milliseconds. If it is not set Opa will execute the tests as fast as possible"
	});

	// synchronously hook QUnit custom async assertions from extension
	Opa5._getEventProvider().attachEvent('onExtensionAfterInit',function(oEvent) {
		var oParams = oEvent.getParameters();
		if (oParams.extension.getAssertions) {
			var oAssertions = oParams.extension.getAssertions();
			jQueryDOM.each(oAssertions,function(sName,fnAssertion) {
				QUnit.assert[sName] = function() {
					var qunitThis = this;
					// call the assertion in the app window
					// assertion is async, push results when ready
					var oAssertionPromise = fnAssertion.apply(oParams.appWindow, arguments)
						.always(function (oResult) {
							qunitThis.push(
								oResult.result,
								oResult.actual,
								oResult.expected,
								oResult.message
							);
						});

					// schedule async assertion promise on waitFor flow so test waits till assertion is ready
					Opa.config.assertions._schedulePromiseOnFlow(oAssertionPromise);
				};
			});
		}
	});

	return opaTest;
});
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

const { mocha, expect, testDB } = require('../common');
const moment = require('moment');
const Meter = require('../../models/Meter');
const Reading = require('../../models/Reading');

mocha.describe('Barchart Readings', () => {
	let meter;
	const timestamp1 = moment('2017-01-01');
	const timestamp2 = timestamp1.clone().add(1, 'hour');
	const timestamp3 = timestamp2.clone().add(1, 'hour');
	const timestamp4 = timestamp3.clone().add(1, 'hour');
	const timestamp5 = timestamp4.clone().add(1, 'hour');

	mocha.beforeEach(async () => {
		conn = testDB.getConnection();
		await new Meter(undefined, 'Meter', null, false, true, Meter.type.MAMAC).insert(conn);
		meter = await Meter.getByName('Meter', conn);
	});

	mocha.it('barchart readings with no specified time interval', async () => {
		conn = testDB.getConnection();
		const reading1 = new Reading(meter.id, 100, timestamp1, timestamp2);
		const reading2 = new Reading(meter.id, 200, timestamp2, timestamp3);
		const reading3 = new Reading(meter.id, 300, timestamp3, timestamp4);
		const reading4 = new Reading(meter.id, 400, timestamp4, timestamp5);
		await Reading.insertAll([reading1, reading2, reading3, reading4], conn);

		// TODO: This is awkward. Is there a better way to have conn as a non-optional
		// without requiring changing EVERY call to getBarchartReadings?
		// If not, well, we need to change every call.
		const barchartReadings = await Reading.getBarchartReadings([meter.id], moment.duration(2, 'h'), null, null, conn);
		expect(barchartReadings[meter.id]).to.have.lengthOf(2);
		const expectedFirstReading = Math.floor(reading1.reading + reading2.reading);
		expect(barchartReadings[meter.id][0].reading_sum).to.equal(expectedFirstReading);
		const expectedSecondReading = Math.floor(reading3.reading + reading4.reading);
		expect(barchartReadings[meter.id][1].reading_sum).to.equal(expectedSecondReading);
	});

	mocha.it('barchart readings with time interval', async () => {
		conn = testDB.getConnection();
		const reading1 = new Reading(meter.id, 10, timestamp1, timestamp2);
		const reading2 = new Reading(meter.id, 100, timestamp2, timestamp3);
		const reading3 = new Reading(meter.id, 1000, timestamp3, timestamp4);
		const reading4 = new Reading(meter.id, 400, timestamp4, timestamp5);
		await Reading.insertAll([reading1, reading2, reading3, reading4], conn);

		const startTimestamp = timestamp1.clone().add(30, 'minutes');
		const endTimestamp = startTimestamp.clone().add(2, 'hours');
		const barchartReadings = await Reading.getBarchartReadings([meter.id], moment.duration(2, 'h'), startTimestamp, endTimestamp, conn);
		expect(barchartReadings[meter.id]).to.have.lengthOf(1);
		const expectedFirstReading = Math.floor((reading1.reading * 0.5) + reading2.reading + (reading3.reading * 0.5));
		expect(barchartReadings[meter.id][0].reading_sum).to.equal(expectedFirstReading);
	});

	mocha.it('barchart readings with overlapping duration and time interval', async () => {
		conn = testDB.getConnection();
		const reading1 = new Reading(meter.id, 10, timestamp1, timestamp2);
		const reading2 = new Reading(meter.id, 100, timestamp2, timestamp3);
		const reading3 = new Reading(meter.id, 1000, timestamp3, timestamp4);
		const reading4 = new Reading(meter.id, 400, timestamp4, timestamp5);
		await Reading.insertAll([reading1, reading2, reading3, reading4], conn);

		const startTimestamp = timestamp1.clone().add(15, 'minutes');
		const endTimestamp = startTimestamp.clone().add(50, 'days');
		const barchartReadings = await Reading.getBarchartReadings([meter.id], moment.duration(1, 'h'), startTimestamp, endTimestamp, conn);
		expect(barchartReadings[meter.id]).to.have.lengthOf(4);
		const expectedFirstReading = Math.floor((reading1.reading * 0.75) + (reading2.reading * 0.25));
		expect(barchartReadings[meter.id][0].reading_sum).to.equal(expectedFirstReading);
		const expectedSecondReading = Math.floor((reading2.reading * 0.75) + (reading3.reading * 0.25));
		expect(barchartReadings[meter.id][1].reading_sum).to.equal(expectedSecondReading);
		const expectedThirdReading = Math.floor((reading3.reading * 0.75) + (reading4.reading * 0.25));
		expect(barchartReadings[meter.id][2].reading_sum).to.equal(expectedThirdReading);
		const expectedFourthReading = Math.floor(reading4.reading * 0.75);
		expect(barchartReadings[meter.id][3].reading_sum).to.equal(expectedFourthReading);
	});

	mocha.it('barchart readings with a missing reading', async () => {
		conn = testDB.getConnection();
		const reading1 = new Reading(meter.id, 10, timestamp1, timestamp2);
		const reading2 = new Reading(meter.id, 100, timestamp2, timestamp3);
		const reading4 = new Reading(meter.id, 400, timestamp4, timestamp5);
		await Reading.insertAll([reading1, reading2, reading4], conn);

		const startTimestamp = timestamp1.clone().add(30, 'minutes');
		const endTimestamp = startTimestamp.clone().add(5, 'hours');
		const barchartReadings = await Reading.getBarchartReadings([meter.id], moment.duration(1, 'h'), startTimestamp, endTimestamp, conn);
		expect(barchartReadings[meter.id]).to.have.lengthOf(4);
		const expectedFirstReading = Math.floor((reading1.reading * 0.5) + (reading2.reading * 0.5));
		expect(barchartReadings[meter.id][0].reading_sum).to.equal(expectedFirstReading);
		const expectedSecondReading = Math.floor(reading2.reading * 0.5);
		expect(barchartReadings[meter.id][1].reading_sum).to.equal(expectedSecondReading);
		const expectedThirdReading = Math.floor(reading4.reading * 0.5);
		expect(barchartReadings[meter.id][2].reading_sum).to.equal(expectedThirdReading);
		const expectedFourthReading = Math.floor(reading4.reading * 0.5);
		expect(barchartReadings[meter.id][3].reading_sum).to.equal(expectedFourthReading);
	});

	mocha.it('barchart readings with a smaller time interval than duration', async () => {
		conn = testDB.getConnection();
		const reading1 = new Reading(meter.id, 100, timestamp1, timestamp2);
		const reading2 = new Reading(meter.id, 1000, timestamp2, timestamp3);
		await Reading.insertAll([reading1, reading2], conn);

		const startTimestamp = timestamp1.clone().add(30, 'minutes');
		const endTimestamp = startTimestamp.clone().add(15, 'minutes');
		const barchartReadings = await Reading.getBarchartReadings([meter.id], moment.duration(1, 'h'), startTimestamp, endTimestamp, conn);
		expect(barchartReadings[meter.id]).to.have.lengthOf(1);
		const expectedFirstReading = Math.floor(reading1.reading * 0.25);
		expect(barchartReadings[meter.id][0].reading_sum).to.equal(expectedFirstReading);
	});

	mocha.it('barchart readings with multiple meters', async () => {
		conn = testDB.getConnection();
		await new Meter(undefined, 'Meter2', null, false, true, Meter.type.MAMAC).insert(conn);
		await new Meter(undefined, 'Meter3', null, false, true, Meter.type.MAMAC).insert(conn);
		const meter2 = await Meter.getByName('Meter2', conn);
		const meter3 = await Meter.getByName('Meter3', conn);
		const readingMeter1 = new Reading(meter.id, 100, timestamp1, timestamp2);
		const readingMeter2 = new Reading(meter2.id, 200, timestamp1, timestamp2);
		const readingMeter3 = new Reading(meter3.id, 300, timestamp1, timestamp2);
		await Reading.insertAll([readingMeter1, readingMeter2, readingMeter3], conn);

		const startTimestamp = timestamp1.clone();
		const endTimestamp = startTimestamp.clone().add(2, 'hours');
		const barchartReadings = await Reading.getBarchartReadings(
			[meter.id, meter2.id, meter3.id],
			moment.duration(1, 'hour'),
			startTimestamp,
			endTimestamp,
			conn
		);
		expect(Object.keys(barchartReadings)).to.have.lengthOf(3);
		expect(barchartReadings[meter.id]).to.have.lengthOf(1);
		expect(barchartReadings[meter2.id]).to.have.lengthOf(1);
		expect(barchartReadings[meter3.id]).to.have.lengthOf(1);
		expect(barchartReadings[meter.id][0].reading_sum).to.equal(readingMeter1.reading);
		expect(barchartReadings[meter2.id][0].reading_sum).to.equal(readingMeter2.reading);
		expect(barchartReadings[meter3.id][0].reading_sum).to.equal(readingMeter3.reading);
	});

	mocha.it('returns correct results when no readings exist', async () => {
		conn = testDB.getConnection();
		const result = await Reading.getBarchartReadings([meter.id], moment.duration(1, 'day'), null, null, conn);
		expect(result).to.deep.equal({ [meter.id]: [] });
	});
});
<commit_msg>test Travis failure<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

const { mocha, expect, testDB } = require('../common');
const moment = require('moment');
const Meter = require('../../models/Meter');
const Reading = require('../../models/Reading');

mocha.describe('Barchart Readings', () => {
	let meter;
	const timestamp1 = moment('2017-01-01');
	const timestamp2 = timestamp1.clone().add(1, 'hour');
	const timestamp3 = timestamp2.clone().add(1, 'hour');
	const timestamp4 = timestamp3.clone().add(1, 'hour');
	const timestamp5 = timestamp4.clone().add(1, 'hour');

	mocha.beforeEach(async () => {
		conn = testDB.getConnection();
		await new Meter(undefined, 'Meter', null, false, true, Meter.type.MAMAC).insert(conn);
		meter = await Meter.getByName('Meter', conn);
	});

	mocha.it('barchart readings with no specified time interval', async () => {
		conn = testDB.getConnection();
		const reading1 = new Reading(meter.id, 100, timestamp1, timestamp2);
		const reading2 = new Reading(meter.id, 200, timestamp2, timestamp3);
		const reading3 = new Reading(meter.id, 300, timestamp3, timestamp4);
		const reading4 = new Reading(meter.id, 400, timestamp4, timestamp5);
		await Reading.insertAll([reading1, reading2, reading3, reading4], conn);

		// TODO: This is awkward. Is there a better way to have conn as a non-optional
		// without requiring changing EVERY call to getBarchartReadings?
		// If not, well, we need to change every call.
		// Silly change to see if get Travis error.
		const barchartReadings = await Reading.getBarchartReadings([meter.id], moment.duration(2, 'h'), null, null, conn);
		expect(barchartReadings[meter.id]).to.have.lengthOf(2);
		const expectedFirstReading = Math.floor(reading1.reading + reading2.reading);
		expect(barchartReadings[meter.id][0].reading_sum).to.equal(expectedFirstReading);
		const expectedSecondReading = Math.floor(reading3.reading + reading4.reading);
		expect(barchartReadings[meter.id][1].reading_sum).to.equal(expectedSecondReading);
	});

	mocha.it('barchart readings with time interval', async () => {
		conn = testDB.getConnection();
		const reading1 = new Reading(meter.id, 10, timestamp1, timestamp2);
		const reading2 = new Reading(meter.id, 100, timestamp2, timestamp3);
		const reading3 = new Reading(meter.id, 1000, timestamp3, timestamp4);
		const reading4 = new Reading(meter.id, 400, timestamp4, timestamp5);
		await Reading.insertAll([reading1, reading2, reading3, reading4], conn);

		const startTimestamp = timestamp1.clone().add(30, 'minutes');
		const endTimestamp = startTimestamp.clone().add(2, 'hours');
		const barchartReadings = await Reading.getBarchartReadings([meter.id], moment.duration(2, 'h'), startTimestamp, endTimestamp, conn);
		expect(barchartReadings[meter.id]).to.have.lengthOf(1);
		const expectedFirstReading = Math.floor((reading1.reading * 0.5) + reading2.reading + (reading3.reading * 0.5));
		expect(barchartReadings[meter.id][0].reading_sum).to.equal(expectedFirstReading);
	});

	mocha.it('barchart readings with overlapping duration and time interval', async () => {
		conn = testDB.getConnection();
		const reading1 = new Reading(meter.id, 10, timestamp1, timestamp2);
		const reading2 = new Reading(meter.id, 100, timestamp2, timestamp3);
		const reading3 = new Reading(meter.id, 1000, timestamp3, timestamp4);
		const reading4 = new Reading(meter.id, 400, timestamp4, timestamp5);
		await Reading.insertAll([reading1, reading2, reading3, reading4], conn);

		const startTimestamp = timestamp1.clone().add(15, 'minutes');
		const endTimestamp = startTimestamp.clone().add(50, 'days');
		const barchartReadings = await Reading.getBarchartReadings([meter.id], moment.duration(1, 'h'), startTimestamp, endTimestamp, conn);
		expect(barchartReadings[meter.id]).to.have.lengthOf(4);
		const expectedFirstReading = Math.floor((reading1.reading * 0.75) + (reading2.reading * 0.25));
		expect(barchartReadings[meter.id][0].reading_sum).to.equal(expectedFirstReading);
		const expectedSecondReading = Math.floor((reading2.reading * 0.75) + (reading3.reading * 0.25));
		expect(barchartReadings[meter.id][1].reading_sum).to.equal(expectedSecondReading);
		const expectedThirdReading = Math.floor((reading3.reading * 0.75) + (reading4.reading * 0.25));
		expect(barchartReadings[meter.id][2].reading_sum).to.equal(expectedThirdReading);
		const expectedFourthReading = Math.floor(reading4.reading * 0.75);
		expect(barchartReadings[meter.id][3].reading_sum).to.equal(expectedFourthReading);
	});

	mocha.it('barchart readings with a missing reading', async () => {
		conn = testDB.getConnection();
		const reading1 = new Reading(meter.id, 10, timestamp1, timestamp2);
		const reading2 = new Reading(meter.id, 100, timestamp2, timestamp3);
		const reading4 = new Reading(meter.id, 400, timestamp4, timestamp5);
		await Reading.insertAll([reading1, reading2, reading4], conn);

		const startTimestamp = timestamp1.clone().add(30, 'minutes');
		const endTimestamp = startTimestamp.clone().add(5, 'hours');
		const barchartReadings = await Reading.getBarchartReadings([meter.id], moment.duration(1, 'h'), startTimestamp, endTimestamp, conn);
		expect(barchartReadings[meter.id]).to.have.lengthOf(4);
		const expectedFirstReading = Math.floor((reading1.reading * 0.5) + (reading2.reading * 0.5));
		expect(barchartReadings[meter.id][0].reading_sum).to.equal(expectedFirstReading);
		const expectedSecondReading = Math.floor(reading2.reading * 0.5);
		expect(barchartReadings[meter.id][1].reading_sum).to.equal(expectedSecondReading);
		const expectedThirdReading = Math.floor(reading4.reading * 0.5);
		expect(barchartReadings[meter.id][2].reading_sum).to.equal(expectedThirdReading);
		const expectedFourthReading = Math.floor(reading4.reading * 0.5);
		expect(barchartReadings[meter.id][3].reading_sum).to.equal(expectedFourthReading);
	});

	mocha.it('barchart readings with a smaller time interval than duration', async () => {
		conn = testDB.getConnection();
		const reading1 = new Reading(meter.id, 100, timestamp1, timestamp2);
		const reading2 = new Reading(meter.id, 1000, timestamp2, timestamp3);
		await Reading.insertAll([reading1, reading2], conn);

		const startTimestamp = timestamp1.clone().add(30, 'minutes');
		const endTimestamp = startTimestamp.clone().add(15, 'minutes');
		const barchartReadings = await Reading.getBarchartReadings([meter.id], moment.duration(1, 'h'), startTimestamp, endTimestamp, conn);
		expect(barchartReadings[meter.id]).to.have.lengthOf(1);
		const expectedFirstReading = Math.floor(reading1.reading * 0.25);
		expect(barchartReadings[meter.id][0].reading_sum).to.equal(expectedFirstReading);
	});

	mocha.it('barchart readings with multiple meters', async () => {
		conn = testDB.getConnection();
		await new Meter(undefined, 'Meter2', null, false, true, Meter.type.MAMAC).insert(conn);
		await new Meter(undefined, 'Meter3', null, false, true, Meter.type.MAMAC).insert(conn);
		const meter2 = await Meter.getByName('Meter2', conn);
		const meter3 = await Meter.getByName('Meter3', conn);
		const readingMeter1 = new Reading(meter.id, 100, timestamp1, timestamp2);
		const readingMeter2 = new Reading(meter2.id, 200, timestamp1, timestamp2);
		const readingMeter3 = new Reading(meter3.id, 300, timestamp1, timestamp2);
		await Reading.insertAll([readingMeter1, readingMeter2, readingMeter3], conn);

		const startTimestamp = timestamp1.clone();
		const endTimestamp = startTimestamp.clone().add(2, 'hours');
		const barchartReadings = await Reading.getBarchartReadings(
			[meter.id, meter2.id, meter3.id],
			moment.duration(1, 'hour'),
			startTimestamp,
			endTimestamp,
			conn
		);
		expect(Object.keys(barchartReadings)).to.have.lengthOf(3);
		expect(barchartReadings[meter.id]).to.have.lengthOf(1);
		expect(barchartReadings[meter2.id]).to.have.lengthOf(1);
		expect(barchartReadings[meter3.id]).to.have.lengthOf(1);
		expect(barchartReadings[meter.id][0].reading_sum).to.equal(readingMeter1.reading);
		expect(barchartReadings[meter2.id][0].reading_sum).to.equal(readingMeter2.reading);
		expect(barchartReadings[meter3.id][0].reading_sum).to.equal(readingMeter3.reading);
	});

	mocha.it('returns correct results when no readings exist', async () => {
		conn = testDB.getConnection();
		const result = await Reading.getBarchartReadings([meter.id], moment.duration(1, 'day'), null, null, conn);
		expect(result).to.deep.equal({ [meter.id]: [] });
	});
});
<|endoftext|>


<commit_before>/**
 * Replaces string placeholders with corresponding template string
 */
if (!('format' in String.prototype)) {
  String.prototype.format = function () {
    var args = arguments;
    return this.replace(/{(\d+)}/g, function (match, number) {
      return typeof args[number] !== undefined ? args[number] : match;
    });
  };
}

angular.autoValidate = angular.autoValidate || {
  errorMessages: {}
};

angular.autoValidate.errorMessages['en-us'] = angular.autoValidate.errorMessages['en-gb'] = {
  defaultMsg: 'Please add error message for {0}',
  email: 'Please enter a valid email address',
  minlength: 'Please enter at least {0} characters',
  maxlength: 'You have entered more than the maximum {0} characters',
  min: 'Please enter the minimum number of {0}',
  max: 'Please enter the maximum number of {0}',
  required: 'This field is required',
  date: 'Please enter a valid date',
  pattern: 'Please ensure the entered information adheres to this pattern {0}',
  number: 'Please enter a valid number',
  url: 'Please enter a valid URL in the format of http(s)://www.google.com'
};

function DefaultErrorMessageResolverFn($q, $http) {
  var currentCulture = 'en-gb',

    i18nFileRootPath = 'js/angular-auto-validate/dist/lang',

    cultureRetrievalPromise,

    loadRemoteCulture = function (culture) {
      cultureRetrievalPromise = $http.get('{0}/jcs-auto-validate_{1}.json'.format(i18nFileRootPath, culture.toLowerCase()));
      return cultureRetrievalPromise;
    },

    /**
     * @ngdoc function
     * @name defaultErrorMessageResolver#setI18nFileRootPath
     * @methodOf defaultErrorMessageResolver
     *
     * @description
     * Set the root path to the il8n files on the server
     *
     * @param {String} rootPath - The root path on the server to the il8n file - this defaults
     * to 'js/angular-auto-validate/lang/'
     */
    setI18nFileRootPath = function (rootPath) {
      i18nFileRootPath = rootPath;
    },

    /**
     * @ngdoc function
     * @name defaultErrorMessageResolver#setCulture
     * @methodOf defaultErrorMessageResolver
     *
     * @description
     * Set the culture for the error messages by loading an the correct culture resource file.
     *
     * @param {String} culture - The new culture in the format of 'en-gb' etc.
     * @param {Function} cultureLoadingFn - A optional function to load the culture resolve which should
     * return a promise which is resolved with the culture errorMessage object.  If a function is not specified
     * the culture file is loaded from the **i18nFileRootPath**.
     * @returns {Promise} - A promise which is resolved with the loaded culture error messages object.
     */
    setCulture = function (culture, cultureLoadingFn) {
      var defer = $q.defer();
      cultureLoadingFn = cultureLoadingFn || loadRemoteCulture;
      currentCulture = culture.toLowerCase();
      if (angular.autoValidate.errorMessages[currentCulture] === undefined) {
        cultureRetrievalPromise = cultureLoadingFn(culture);
        cultureRetrievalPromise.then(function (response) {
          cultureRetrievalPromise = undefined;
          angular.autoValidate.errorMessages[currentCulture] = response.data;
          defer.resolve(angular.autoValidate.errorMessages[currentCulture]);
        }, function (err) {
          angular.autoValidate.errorMessages[currentCulture] = {
            defaultMsg: 'Loading culture failed!'
          };
          cultureRetrievalPromise = null;
          defer.reject(err);
        });
      } else {
        defer.resolve(angular.autoValidate.errorMessages[currentCulture]);
      }

      return defer.promise;
    },

    getErrorMessages = function (culture) {
      var defer = $q.defer();
      culture = culture === undefined ? currentCulture : culture.toLowerCase();
      if (cultureRetrievalPromise !== undefined) {
        cultureRetrievalPromise.then(function () {
          defer.resolve(angular.autoValidate.errorMessages[culture]);
        }, function (err) {
          defer.reject(err);
        });
      } else {
        defer.resolve(angular.autoValidate.errorMessages[culture]);
      }
      return defer.promise;
    },

    getMessageTypeOverride = function (errorType, el) {
      var overrideKey;

      if (el) {
        // try and find an attribute which overrides the given error type in the form of errorType-err-type="someMsgKey"
        errorType += '-err-type';

        overrideKey = el.attr('ng-' + errorType);
        if (overrideKey === undefined) {
          overrideKey = el.attr('data-ng-' + errorType) || el.attr(errorType);
        }

        if (overrideKey) {
          overrideKey = overrideKey.replace(/[\W]/g, '');
        }
      }

      return overrideKey;
    },

    /**
     * @ngdoc function
     * @name defaultErrorMessageResolver#resolve
     * @methodOf defaultErrorMessageResolver
     *
     * @description
     * Resolves a validate error type into a user validation error message
     *
     * @param {String} errorType - The type of validation error that has occurred.
     * @param {Element} el - The input element that is the source of the validation error.
     * @returns {Promise} A promise that is resolved when the validation message has been produced.
     */
    resolve = function (errorType, el) {
      var defer = $q.defer(),
        errMsg,
        parameters = [],
        parameter,
        messageTypeOverride;

      if (cultureRetrievalPromise !== undefined) {
        cultureRetrievalPromise.then(function () {
          resolve(errorType, el).then(function (msg) {
            defer.resolve(msg);
          });
        });
      } else {
        errMsg = angular.autoValidate.errorMessages[currentCulture][errorType];
        messageTypeOverride = getMessageTypeOverride(errorType, el);
        if (messageTypeOverride) {
          errMsg = angular.autoValidate.errorMessages[currentCulture][messageTypeOverride];
        }

        if (errMsg === undefined && messageTypeOverride !== undefined) {
          errMsg = angular.autoValidate.errorMessages[currentCulture].defaultMsg.format(messageTypeOverride);
        } else if (errMsg === undefined) {
          errMsg = angular.autoValidate.errorMessages[currentCulture].defaultMsg.format(errorType);
        }

        if (el && el.attr) {
          try {
            parameter = el.attr('ng-' + errorType);
            if (parameter === undefined) {
              parameter = el.attr('data-ng-' + errorType) || el.attr(errorType);
            }

            parameters.push(parameter || '');

            errMsg = errMsg.format(parameters);
          } catch (e) {}
        }

        defer.resolve(errMsg);
      }

      return defer.promise;
    };

  return {
    setI18nFileRootPath: setI18nFileRootPath,
    setCulture: setCulture,
    getErrorMessages: getErrorMessages,
    resolve: resolve
  };
}

DefaultErrorMessageResolverFn.$inject = [
  '$q',
  '$http'
];

angular.module('jcs-autoValidate').factory('defaultErrorMessageResolver', DefaultErrorMessageResolverFn);
<commit_msg>Change the default language to 'default'<commit_after>/**
 * Replaces string placeholders with corresponding template string
 */
if (!('format' in String.prototype)) {
  String.prototype.format = function () {
    var args = arguments;
    return this.replace(/{(\d+)}/g, function (match, number) {
      return typeof args[number] !== undefined ? args[number] : match;
    });
  };
}

angular.autoValidate = angular.autoValidate || {
  errorMessages: {}
};

angular.autoValidate.errorMessages['default'] = {
  defaultMsg: 'Please add error message for {0}',
  email: 'Please enter a valid email address',
  minlength: 'Please enter at least {0} characters',
  maxlength: 'You have entered more than the maximum {0} characters',
  min: 'Please enter the minimum number of {0}',
  max: 'Please enter the maximum number of {0}',
  required: 'This field is required',
  date: 'Please enter a valid date',
  pattern: 'Please ensure the entered information adheres to this pattern {0}',
  number: 'Please enter a valid number',
  url: 'Please enter a valid URL in the format of http(s)://www.google.com'
};

function DefaultErrorMessageResolverFn($q, $http) {
  var currentCulture = 'default',

    i18nFileRootPath = 'js/angular-auto-validate/dist/lang',

    cultureRetrievalPromise,

    loadRemoteCulture = function (culture) {
      cultureRetrievalPromise = $http.get('{0}/jcs-auto-validate_{1}.json'.format(i18nFileRootPath, culture.toLowerCase()));
      return cultureRetrievalPromise;
    },

    /**
     * @ngdoc function
     * @name defaultErrorMessageResolver#setI18nFileRootPath
     * @methodOf defaultErrorMessageResolver
     *
     * @description
     * Set the root path to the il8n files on the server
     *
     * @param {String} rootPath - The root path on the server to the il8n file - this defaults
     * to 'js/angular-auto-validate/lang/'
     */
    setI18nFileRootPath = function (rootPath) {
      i18nFileRootPath = rootPath;
    },

    /**
     * @ngdoc function
     * @name defaultErrorMessageResolver#setCulture
     * @methodOf defaultErrorMessageResolver
     *
     * @description
     * Set the culture for the error messages by loading an the correct culture resource file.
     *
     * @param {String} culture - The new culture in the format of 'en-gb' etc.
     * @param {Function} cultureLoadingFn - A optional function to load the culture resolve which should
     * return a promise which is resolved with the culture errorMessage object.  If a function is not specified
     * the culture file is loaded from the **i18nFileRootPath**.
     * @returns {Promise} - A promise which is resolved with the loaded culture error messages object.
     */
    setCulture = function (culture, cultureLoadingFn) {
      var defer = $q.defer();
      cultureLoadingFn = cultureLoadingFn || loadRemoteCulture;
      currentCulture = culture.toLowerCase();
      if (angular.autoValidate.errorMessages[currentCulture] === undefined) {
        cultureRetrievalPromise = cultureLoadingFn(culture);
        cultureRetrievalPromise.then(function (response) {
          cultureRetrievalPromise = undefined;
          angular.autoValidate.errorMessages[currentCulture] = response.data;
          defer.resolve(angular.autoValidate.errorMessages[currentCulture]);
        }, function (err) {
          angular.autoValidate.errorMessages[currentCulture] = {
            defaultMsg: 'Loading culture failed!'
          };
          cultureRetrievalPromise = null;
          defer.reject(err);
        });
      } else {
        defer.resolve(angular.autoValidate.errorMessages[currentCulture]);
      }

      return defer.promise;
    },

    getErrorMessages = function (culture) {
      var defer = $q.defer();
      culture = culture === undefined ? currentCulture : culture.toLowerCase();
      if (cultureRetrievalPromise !== undefined) {
        cultureRetrievalPromise.then(function () {
          defer.resolve(angular.autoValidate.errorMessages[culture]);
        }, function (err) {
          defer.reject(err);
        });
      } else {
        defer.resolve(angular.autoValidate.errorMessages[culture]);
      }
      return defer.promise;
    },

    getMessageTypeOverride = function (errorType, el) {
      var overrideKey;

      if (el) {
        // try and find an attribute which overrides the given error type in the form of errorType-err-type="someMsgKey"
        errorType += '-err-type';

        overrideKey = el.attr('ng-' + errorType);
        if (overrideKey === undefined) {
          overrideKey = el.attr('data-ng-' + errorType) || el.attr(errorType);
        }

        if (overrideKey) {
          overrideKey = overrideKey.replace(/[\W]/g, '');
        }
      }

      return overrideKey;
    },

    /**
     * @ngdoc function
     * @name defaultErrorMessageResolver#resolve
     * @methodOf defaultErrorMessageResolver
     *
     * @description
     * Resolves a validate error type into a user validation error message
     *
     * @param {String} errorType - The type of validation error that has occurred.
     * @param {Element} el - The input element that is the source of the validation error.
     * @returns {Promise} A promise that is resolved when the validation message has been produced.
     */
    resolve = function (errorType, el) {
      var defer = $q.defer(),
        errMsg,
        parameters = [],
        parameter,
        messageTypeOverride;

      if (cultureRetrievalPromise !== undefined) {
        cultureRetrievalPromise.then(function () {
          resolve(errorType, el).then(function (msg) {
            defer.resolve(msg);
          });
        });
      } else {
        errMsg = angular.autoValidate.errorMessages[currentCulture][errorType];
        messageTypeOverride = getMessageTypeOverride(errorType, el);
        if (messageTypeOverride) {
          errMsg = angular.autoValidate.errorMessages[currentCulture][messageTypeOverride];
        }

        if (errMsg === undefined && messageTypeOverride !== undefined) {
          errMsg = angular.autoValidate.errorMessages[currentCulture].defaultMsg.format(messageTypeOverride);
        } else if (errMsg === undefined) {
          errMsg = angular.autoValidate.errorMessages[currentCulture].defaultMsg.format(errorType);
        }

        if (el && el.attr) {
          try {
            parameter = el.attr('ng-' + errorType);
            if (parameter === undefined) {
              parameter = el.attr('data-ng-' + errorType) || el.attr(errorType);
            }

            parameters.push(parameter || '');

            errMsg = errMsg.format(parameters);
          } catch (e) {}
        }

        defer.resolve(errMsg);
      }

      return defer.promise;
    };

  return {
    setI18nFileRootPath: setI18nFileRootPath,
    setCulture: setCulture,
    getErrorMessages: getErrorMessages,
    resolve: resolve
  };
}

DefaultErrorMessageResolverFn.$inject = [
  '$q',
  '$http'
];

angular.module('jcs-autoValidate').factory('defaultErrorMessageResolver', DefaultErrorMessageResolverFn);
<|endoftext|>


<commit_before>const { authenticate } = require('@feathersjs/authentication');
const globalHooks = require('../../../hooks');

const { sortByGradeAndOrName, prepareGradeLevelUnset, saveSuccessor } = require('../hooks/helpers/classHooks');
const { paginate } = require('../../../utils/array');

const restrictToCurrentSchool = globalHooks.ifNotLocal(globalHooks.restrictToCurrentSchool);
const restrictToUsersOwnClasses = globalHooks.ifNotLocal(globalHooks.restrictToUsersOwnClasses);

class Classes {
	constructor(options) {
		this.options = options || {};
	}

	async getSchoolYearsFromQuery(query) {
		if ((query.year || {}).$in) return query.year.$in;
		if (query.year) return [query.year];

		const school = await this.app.service('schools').get(query.schoolId);
		const years = school.years.schoolYears.map((y) => y._id);
		years.push({ $exists: false }); // to find classes that dont have a year
		return years;
	}

	async findClassesByYear(params) {
		const years = await this.getSchoolYearsFromQuery(params.query);

		const classPromises = years.map((y) => {
			const yearParams = Object.assign(
				{},
				params,
				{ query: Object.assign({}, params.query, { year: y._id || y }) },
			);
			return this.app.service('classModel').find(yearParams);
		});
		const classesByYear = await Promise.all(classPromises);
		const data = classesByYear.reduce((acc, current) => acc.concat(current.data || current), []);

		if (params.query.$paginate !== false && params.paginate !== false) params.query.$paginate = true;
		const result = paginate(data, params.query);
		return result;
	}

	async find(params) {
		if ((params.query.$sort || {}).year && params.query.schoolId) {
			return this.findClassesByYear(params);
		}

		return this.app.service('classModel').find(params);
	}

	get(id, params) {
		return this.app.service('classModel').get(id, params);
	}

	create(data, params) {
		return this.app.service('classModel').create(data, params);
	}

	update(id, data, params) {
		return this.app.service('classModel').update(id, data, params);
	}

	patch(id, data, params) {
		return this.app.service('classModel').patch(id, data, params);
	}

	remove(id, params) {
		return this.app.service('classModel').remove(id, params);
	}

	setup(app) {
		this.app = app;
	}
}

const classesService = new Classes({
	paginate: {
		default: 25,
		max: 100,
	},
});

const classesHooks = {
	before: {
		all: [authenticate('jwt')],
		find: [
			globalHooks.hasPermission('CLASS_VIEW'),
			restrictToCurrentSchool,
			restrictToUsersOwnClasses,
			sortByGradeAndOrName,
			globalHooks.mapPaginationQuery,
		],
		get: [
			restrictToCurrentSchool,
			restrictToUsersOwnClasses,
		],
		create: [
			globalHooks.hasPermission('CLASS_CREATE'),
			restrictToCurrentSchool,
		],
		update: [
			globalHooks.hasPermission('CLASS_EDIT'),
			restrictToCurrentSchool,
			prepareGradeLevelUnset,
		],
		patch: [
			globalHooks.hasPermission('CLASS_EDIT'),
			restrictToCurrentSchool,
			globalHooks.permitGroupOperation,
			prepareGradeLevelUnset,
		],
		remove: [globalHooks.hasPermission('CLASS_REMOVE'), restrictToCurrentSchool, globalHooks.permitGroupOperation],
	},
	after: {
		all: [],
		find: [],
		get: [
			globalHooks.ifNotLocal(
				globalHooks.denyIfNotCurrentSchool({
					errorMessage: 'Die angefragte Gruppe gehört nicht zur eigenen Schule!',
				}),
			)],
		create: [
			saveSuccessor,
		],
		update: [],
		patch: [],
		remove: [],
	},
};

module.exports = { classesService, classesHooks };
<commit_msg>add inline comments<commit_after>const { authenticate } = require('@feathersjs/authentication');
const globalHooks = require('../../../hooks');

const { sortByGradeAndOrName, prepareGradeLevelUnset, saveSuccessor } = require('../hooks/helpers/classHooks');
const { paginate } = require('../../../utils/array');

const restrictToCurrentSchool = globalHooks.ifNotLocal(globalHooks.restrictToCurrentSchool);
const restrictToUsersOwnClasses = globalHooks.ifNotLocal(globalHooks.restrictToUsersOwnClasses);

class Classes {
	constructor(options) {
		this.options = options || {};
	}

	/**
	 * retrieves the year from the query, or from the school of the user.
	 * @param {Object} query feathers query
	 */
	async getSchoolYearsFromQuery(query) {
		if ((query.year || {}).$in) return query.year.$in;
		if (query.year) return [query.year];

		const school = await this.app.service('schools').get(query.schoolId);
		const years = school.years.schoolYears.map((y) => y._id);
		years.push({ $exists: false }); // to find classes that dont have a year
		return years;
	}

	/**
	 * returns classes just like the class-model service would, but sorted by years.
	 * @param {Object} params feathers params object.
	 */
	async findClassesByYear(params) {
		const years = await this.getSchoolYearsFromQuery(params.query);

		const classPromises = years.map((y) => {
			const yearParams = Object.assign(
				{},
				params,
				{ query: Object.assign({}, params.query, { year: y._id || y }) },
			);
			return this.app.service('classModel').find(yearParams);
		});
		const classesByYear = await Promise.all(classPromises);
		const data = classesByYear.reduce((acc, current) => acc.concat(current.data || current), []);

		if (params.query.$paginate !== false && params.paginate !== false) params.query.$paginate = true;
		const result = paginate(data, params.query);
		return result;
	}

	async find(params) {
		if ((params.query.$sort || {}).year && params.query.schoolId) {
			return this.findClassesByYear(params);
		}

		return this.app.service('classModel').find(params);
	}

	get(id, params) {
		return this.app.service('classModel').get(id, params);
	}

	create(data, params) {
		return this.app.service('classModel').create(data, params);
	}

	update(id, data, params) {
		return this.app.service('classModel').update(id, data, params);
	}

	patch(id, data, params) {
		return this.app.service('classModel').patch(id, data, params);
	}

	remove(id, params) {
		return this.app.service('classModel').remove(id, params);
	}

	setup(app) {
		this.app = app;
	}
}

const classesService = new Classes({
	paginate: {
		default: 25,
		max: 100,
	},
});

const classesHooks = {
	before: {
		all: [authenticate('jwt')],
		find: [
			globalHooks.hasPermission('CLASS_VIEW'),
			restrictToCurrentSchool,
			restrictToUsersOwnClasses,
			sortByGradeAndOrName,
			globalHooks.mapPaginationQuery,
		],
		get: [
			restrictToCurrentSchool,
			restrictToUsersOwnClasses,
		],
		create: [
			globalHooks.hasPermission('CLASS_CREATE'),
			restrictToCurrentSchool,
		],
		update: [
			globalHooks.hasPermission('CLASS_EDIT'),
			restrictToCurrentSchool,
			prepareGradeLevelUnset,
		],
		patch: [
			globalHooks.hasPermission('CLASS_EDIT'),
			restrictToCurrentSchool,
			globalHooks.permitGroupOperation,
			prepareGradeLevelUnset,
		],
		remove: [globalHooks.hasPermission('CLASS_REMOVE'), restrictToCurrentSchool, globalHooks.permitGroupOperation],
	},
	after: {
		all: [],
		find: [],
		get: [
			globalHooks.ifNotLocal(
				globalHooks.denyIfNotCurrentSchool({
					errorMessage: 'Die angefragte Gruppe gehört nicht zur eigenen Schule!',
				}),
			)],
		create: [
			saveSuccessor,
		],
		update: [],
		patch: [],
		remove: [],
	},
};

module.exports = { classesService, classesHooks };
<|endoftext|>


<commit_before>Template.forgotPassword.events({
  'submit form': function(e,t){
    event.preventDefault();
    var email = $('[name=email]').val();
    if isNotEmpty (email) {
      Accounts.forgotPassword({email:email},function(err){
        if (err) {
          sAlert.error(err.reason);
        } else {
          sAlert.info('Email Sent, Please check your mailbox to reset your password');
        }
      });
    }
    return false;
  }
});
<commit_msg>solved the missing brackets error<commit_after>Template.forgotPassword.events({
  'submit form': function(e,t){
    event.preventDefault();
    var email = $('[name=email]').val();
    if (isNotEmpty (email)) {
      Accounts.forgotPassword({email:email},function(err){
        if (err) {
          sAlert.error(err.reason);
        } else {
          sAlert.info('Email Sent, Please check your mailbox to reset your password');
        }
      });
    }
    return false;
  }
});
<|endoftext|>