<commit_before>import Webiny from 'Webiny';
import Validator from './../Validation/Validator';

class Form extends Webiny.Ui.Component {

    constructor(props) {
        super(props);

        this.state = {
            model: {}
        };

        this.$isValid = null;
        this.fields = [];
        this.actions = [];
        this.layout = null;
        this.watches = {};

        this.bindMethods('submit', 'reset', 'cancel', 'attachToForm', 'attachValidators', 'detachFromForm', 'validateInput', 'validate');
    }

    componentWillMount() {
        super.componentWillMount();
        this.inputs = {};
        this.setState({model: _.clone(this.props.data)});
        if (this.props.container) {
            this.props.container.registerForm(this);
        }
    }

    componentWillReceiveProps(props) {
        super.componentWillReceiveProps(props);
        this.setState({model: _.clone(props.data)});
    }

    componentWillUpdate(newProps, newState) {
        super.componentWillUpdate(newProps, newState);
    }

    bindTo(name, callback = _.noop, defaultValue = null) {
        return super.bindTo('model.' + name, callback, defaultValue);
    }

    watch(name, callback) {
        const watches = this.watches[name] || new Set();
        watches.add(callback);
        this.watches[name] = watches;
        return () => {
            this.watches[name].delete(callback);
        };
    }

    /**
     * @private
     * @param children
     */
    prepareForm(children) {
        if (typeof children !== 'object' || children === null) {
            return;
        }

        React.Children.map(children, child => {
            if (child.type === 'fields') {
                const fields = _.isFunction(child.props.children) ? child.props.children.call(this, this.state.model, this) : child.props.children;
                this.fields = this.registerInputs(fields);
            }

            if (child.type === 'actions') {
                this.actions = _.isFunction(child.props.children) ? child.props.children(this.state.model, this) : child.props.children;
            }
        }, this);

        if (this.props.layout === false) {
            this.layout = (
                <layout>
                    <fields/>
                </layout>
            );
        }

        if (this.props.layout) {
            this.layout = this.props.layout.call(this);
        }
    }

    /**
     * @private
     * @param element
     * @returns {*}
     */
    replacePlaceholders(element) {
        if (typeof element !== 'object' || element === null) {
            return element;
        }

        if (element.type === 'fields') {
            return this.fields;
        }

        if (element.type === 'actions') {
            return this.actions;
        }

        if (element.props && element.props.children) {
            return React.cloneElement(element, _.omit(element.props, ['key', 'ref']), React.Children.map(element.props.children, item => {
                return this.replacePlaceholders(item);
            }));
        }

        return element;
    }

    /**
     * @private
     * @param input
     * @returns {*}
     */
    registerInput(input) {
        if (typeof input !== 'object' || input === null) {
            return input;
        }

        const newProps = {
            attachToForm: this.attachToForm,
            attachValidators: this.attachValidators,
            detachFromForm: this.detachFromForm,
            validateInput: this.validateInput,
            form: this
        };

        if (input.props && input.props.name) {
            // Add onChange callback to valueLink
            const name = _.upperFirst(_.camelCase(input.props.name));
            const callback = _.get(this.props, 'onChange' + name, _.noop);

            // Input changed callback, triggered on each input change
            const changeCallback = function inputChanged(newValue) {
                callback.bind(this, newValue);
                // See if there is a watch registered for changed input
                const watches = this.watches[input.props.name] || new Set();
                _.map(Array.from(watches), w => w(newValue));
            };

            newProps['valueLink'] = this.bindTo(input.props.name, changeCallback.bind(this), input.props.defaultValue);

            // Add input renderer
            if (_.has(this.props, 'render' + name)) {
                newProps.renderer = this.props['render' + name];
            }

            // Add options source
            if (_.has(this.props, 'options' + name)) {
                newProps.options = this.props['options' + name];
            }

            // Add options source
            if (_.has(this.props, 'optionRenderer' + name)) {
                const selectRenderers = this.props['optionRenderer' + name];
                newProps.optionRenderer = selectRenderers.option || null;
                newProps.selectedRenderer = selectRenderers.selected || null;
            }
            return React.cloneElement(input, newProps, input.props && input.props.children);
        }
        return React.cloneElement(input, _.omit(input.props, ['key', 'ref']), this.registerInputs(input.props && input.props.children));
    }

    /**
     * @private
     * @param children
     * @returns {*}
     */
    registerInputs(children) {
        if (typeof children !== 'object' || children === null) {
            return children;
        }
        return React.Children.map(children, this.registerInput, this);
    }

    /**
     * Get data this form is responsible for.
     * Form may receive data through props that is not handled by any of form input elements,
     * so we only return the data handled by form input elements.
     *
     * This method also clears data of any system keys that are used for React optimization, like $key
     *
     * @returns {{}}
     */
    getModel() {
        const model = {};
        _.each(this.inputs, (input, name) => {
            _.set(model, name, _.get(this.state.model, name));
        });

        return Webiny.Tools.removeKeys(model);
    }

    /**
     * Set form model (merge current model with given model object)
     * @param model
     * @returns {Form}
     */
    setModel(model) {
        _.merge(this.state.model, model);
        this.setState({model: this.state.model});
        return this;
    }

    /**
     * Get current form data including data from linked forms
     * @returns {Object|*}
     */
    getData() {
        const model = this.getModel();
        const forms = this.getLinkedForms();
        if (forms.length) {
            _.each(forms, form => {
                _.merge(model, form.getData());
            });
        }

        return model;
    }

    getLinkedForms() {
        if (this.props.container && this === this.props.container.mainForm) {
            return this.props.container.getLinkedForms();
        }

        if (!this.props.container && this.props.linkedForms) {
            return _.filter(this.props.linkedForms.split(',')).map(Webiny.Ui.Dispatcher.get);
        }

        return [];
    }

    submit(e) {
        if (e && e.preventDefault) {
            e.preventDefault();
        }

        // Validate main form first
        return this.validate().then(mainFormValid => {
            if (!mainFormValid) {
                this.props.onInvalid(this);
                return false;
            }

            // Now proceed to validation of linked forms, if any.
            const model = this.getModel();

            // Validate linked forms
            const forms = this.getLinkedForms();
            if (forms.length) {
                let valid = true;

                // Forms must be validated in a queue because we may have async validators
                let chain = Q();
                _.each(forms, form => {
                    chain = chain.then(() => {
                        return form.validate().then(formValid => {
                            if (formValid) {
                                _.merge(model, form.getData());
                                return true;
                            }

                            valid = false;
                            form.props.onInvalid(form);
                            return false;
                        });
                    });
                });

                return chain.then(() => {
                    if (valid) {
                        this.props.onSubmit(model, this.props.container);
                        return true;
                    }
                    return false;
                });
            }

            // If no linked forms are present...
            this.props.onSubmit(model, this.props.container);
            return true;
        });
    }

    reset() {
        // Reset all linked forms
        _.each(this.getLinkedForms(), form => form.reset());

        _.forIn(this.inputs, cmp => {
            cmp.component.setState({isValid: null});
        });
        this.$isValid = null;

        this.props.onReset();

        this.setState({model: _.clone(this.props.data)});
    }

    cancel() {
        this.props.onCancel();
    }

    isValid() {
        return this.$isValid;
    }

    attachValidators(props) {
        this.inputs[props.name].validators = Validator.parseValidateProperty(props.validate);
        this.inputs[props.name].messages = Validator.parseCustomValidationMessages(props.children);
    }

    attachToForm(component) {
        this.inputs[component.props.name] = {
            component,
            model: component.getValue()
        };
        this.attachValidators(component.props);
    }

    detachFromForm(component) {
        delete this.inputs[component.props.name];
    }

    validateInput(component) {
        const validators = this.inputs[component.props.name].validators;
        const hasValidators = Webiny.Tools.keys(validators).length;
        const messages = this.inputs[component.props.name].messages;
        // Validate input
        return Q(Validator.validate(component.getValue(), validators, this.inputs)).then(validationResults => {
            if (hasValidators) {
                const isValid = component.getValue() === null ? null : true;
                component.setState({isValid, validationResults});
            }
            return validationResults;
        }).catch(validationError => {
            // Set custom error message if defined
            const validator = validationError.validator;
            if (validator in messages) {
                validationError.setMessage(messages[validator]);
            }

            // Set component state to reflect validation error
            component.setState({
                isValid: false,
                validationMessage: validationError.message,
                validationResults: false
            });

            return false;
        });
    }

    validate() {
        let allIsValid = true;

        const inputs = this.inputs;
        // Inputs must be validated in a queue because we may have async validators
        let chain = Q(allIsValid).then(valid => valid);
        Object.keys(inputs).forEach(name => {
            const cmp = inputs[name].component;
            const hasValidators = inputs[name] && inputs[name].validators;
            const shouldValidate = (!cmp.hasValue() && cmp.isRequired()) || (cmp.hasValue() && cmp.state.isValid !== true);

            if (hasValidators && shouldValidate) {
                if (cmp.state.isValid === false || cmp.state.isValid === null) {
                    chain = chain.then(() => {
                        return this.validateInput(cmp).then(validationResult => {
                            if (validationResult === false) {
                                allIsValid = false;
                            }
                            return allIsValid;
                        });
                    });
                }
            }
        });

        return chain;
    }

    render() {
        this.prepareForm(this.props.children);
        return super.render();
    }
}

Form.defaultProps = {
    name: _.uniqueId('form-'),
    onSubmit: _.noop,
    onReset: _.noop,
    onCancel: _.noop,
    onInvalid: _.noop,
    showLoader: true,
    linkedForms: null
};

export default Form;<commit_msg>Input onChange handling<commit_after>import Webiny from 'Webiny';
import Validator from './../Validation/Validator';

class Form extends Webiny.Ui.Component {

    constructor(props) {
        super(props);

        this.state = {
            model: {}
        };

        this.$isValid = null;
        this.fields = [];
        this.actions = [];
        this.layout = null;
        this.watches = {};

        this.bindMethods('submit', 'reset', 'cancel', 'attachToForm', 'attachValidators', 'detachFromForm', 'validateInput', 'validate');
    }

    componentWillMount() {
        super.componentWillMount();
        this.inputs = {};
        this.setState({model: _.clone(this.props.data)});
        if (this.props.container) {
            this.props.container.registerForm(this);
        }
    }

    componentWillReceiveProps(props) {
        super.componentWillReceiveProps(props);
        this.setState({model: _.clone(props.data)});
    }

    componentWillUpdate(newProps, newState) {
        super.componentWillUpdate(newProps, newState);
    }

    bindTo(name, callback = _.noop, defaultValue = null) {
        return super.bindTo('model.' + name, callback, defaultValue);
    }

    watch(name, callback) {
        const watches = this.watches[name] || new Set();
        watches.add(callback);
        this.watches[name] = watches;
        return () => {
            this.watches[name].delete(callback);
        };
    }

    /**
     * @private
     * @param children
     */
    prepareForm(children) {
        if (typeof children !== 'object' || children === null) {
            return;
        }

        React.Children.map(children, child => {
            if (child.type === 'fields') {
                const fields = _.isFunction(child.props.children) ? child.props.children.call(this, this.state.model, this) : child.props.children;
                this.fields = this.registerInputs(fields);
            }

            if (child.type === 'actions') {
                this.actions = _.isFunction(child.props.children) ? child.props.children(this.state.model, this) : child.props.children;
            }
        }, this);

        if (this.props.layout === false) {
            this.layout = (
                <layout>
                    <fields/>
                </layout>
            );
        }

        if (this.props.layout) {
            this.layout = this.props.layout.call(this);
        }
    }

    /**
     * @private
     * @param element
     * @returns {*}
     */
    replacePlaceholders(element) {
        if (typeof element !== 'object' || element === null) {
            return element;
        }

        if (element.type === 'fields') {
            return this.fields;
        }

        if (element.type === 'actions') {
            return this.actions;
        }

        if (element.props && element.props.children) {
            return React.cloneElement(element, _.omit(element.props, ['key', 'ref']), React.Children.map(element.props.children, item => {
                return this.replacePlaceholders(item);
            }));
        }

        return element;
    }

    /**
     * @private
     * @param input
     * @returns {*}
     */
    registerInput(input) {
        if (typeof input !== 'object' || input === null) {
            return input;
        }

        const newProps = {
            attachToForm: this.attachToForm,
            attachValidators: this.attachValidators,
            detachFromForm: this.detachFromForm,
            validateInput: this.validateInput,
            form: this
        };

        if (input.props && input.props.name) {
            // Add onChange callback to valueLink
            const name = _.upperFirst(_.camelCase(input.props.name));

            // Callback can be set on Container (which will pass it to Form), on Form or on input itself
            const callback = _.get(input.props, 'onChange', _.get(this.props, 'onChange' + name, _.noop));

            // Input changed callback, triggered on each input change
            const changeCallback = function inputChanged(newValue) {
                callback.call(this, newValue, input);
                // See if there is a watch registered for changed input
                const watches = this.watches[input.props.name] || new Set();
                _.map(Array.from(watches), w => w(newValue));
            };

            newProps['valueLink'] = this.bindTo(input.props.name, changeCallback.bind(this), input.props.defaultValue);

            // Add input renderer
            if (_.has(this.props, 'render' + name)) {
                newProps.renderer = this.props['render' + name];
            }

            // Add options source
            if (_.has(this.props, 'options' + name)) {
                newProps.options = this.props['options' + name];
            }

            // Add options source
            if (_.has(this.props, 'optionRenderer' + name)) {
                const selectRenderers = this.props['optionRenderer' + name];
                newProps.optionRenderer = selectRenderers.option || null;
                newProps.selectedRenderer = selectRenderers.selected || null;
            }
            return React.cloneElement(input, newProps, input.props && input.props.children);
        }
        return React.cloneElement(input, _.omit(input.props, ['key', 'ref']), this.registerInputs(input.props && input.props.children));
    }

    /**
     * @private
     * @param children
     * @returns {*}
     */
    registerInputs(children) {
        if (typeof children !== 'object' || children === null) {
            return children;
        }
        return React.Children.map(children, this.registerInput, this);
    }

    /**
     * Get data this form is responsible for.
     * Form may receive data through props that is not handled by any of form input elements,
     * so we only return the data handled by form input elements.
     *
     * This method also clears data of any system keys that are used for React optimization, like $key
     *
     * @returns {{}}
     */
    getModel() {
        const model = {};
        _.each(this.inputs, (input, name) => {
            _.set(model, name, _.get(this.state.model, name));
        });

        return Webiny.Tools.removeKeys(model);
    }

    /**
     * Set form model (merge current model with given model object)
     * @param model
     * @returns {Form}
     */
    setModel(model) {
        _.merge(this.state.model, model);
        this.setState({model: this.state.model});
        return this;
    }

    /**
     * Get current form data including data from linked forms
     * @returns {Object|*}
     */
    getData() {
        const model = this.getModel();
        const forms = this.getLinkedForms();
        if (forms.length) {
            _.each(forms, form => {
                _.merge(model, form.getData());
            });
        }

        return model;
    }

    getLinkedForms() {
        if (this.props.container && this === this.props.container.mainForm) {
            return this.props.container.getLinkedForms();
        }

        if (!this.props.container && this.props.linkedForms) {
            return _.filter(this.props.linkedForms.split(',')).map(Webiny.Ui.Dispatcher.get);
        }

        return [];
    }

    submit(e) {
        if (e && e.preventDefault) {
            e.preventDefault();
        }

        // Validate main form first
        return this.validate().then(mainFormValid => {
            if (!mainFormValid) {
                this.props.onInvalid(this);
                return false;
            }

            // Now proceed to validation of linked forms, if any.
            const model = this.getModel();

            // Validate linked forms
            const forms = this.getLinkedForms();
            if (forms.length) {
                let valid = true;

                // Forms must be validated in a queue because we may have async validators
                let chain = Q();
                _.each(forms, form => {
                    chain = chain.then(() => {
                        return form.validate().then(formValid => {
                            if (formValid) {
                                _.merge(model, form.getData());
                                return true;
                            }

                            valid = false;
                            form.props.onInvalid(form);
                            return false;
                        });
                    });
                });

                return chain.then(() => {
                    if (valid) {
                        this.props.onSubmit(model, this.props.container);
                        return true;
                    }
                    return false;
                });
            }

            // If no linked forms are present...
            this.props.onSubmit(model, this.props.container);
            return true;
        });
    }

    reset() {
        // Reset all linked forms
        _.each(this.getLinkedForms(), form => form.reset());

        _.forIn(this.inputs, cmp => {
            cmp.component.setState({isValid: null});
        });
        this.$isValid = null;

        this.props.onReset();

        this.setState({model: _.clone(this.props.data)});
    }

    cancel() {
        this.props.onCancel();
    }

    isValid() {
        return this.$isValid;
    }

    attachValidators(props) {
        this.inputs[props.name].validators = Validator.parseValidateProperty(props.validate);
        this.inputs[props.name].messages = Validator.parseCustomValidationMessages(props.children);
    }

    attachToForm(component) {
        this.inputs[component.props.name] = {
            component,
            model: component.getValue()
        };
        this.attachValidators(component.props);
    }

    detachFromForm(component) {
        delete this.inputs[component.props.name];
    }

    validateInput(component) {
        const validators = this.inputs[component.props.name].validators;
        const hasValidators = Webiny.Tools.keys(validators).length;
        const messages = this.inputs[component.props.name].messages;
        // Validate input
        return Q(Validator.validate(component.getValue(), validators, this.inputs)).then(validationResults => {
            if (hasValidators) {
                const isValid = component.getValue() === null ? null : true;
                component.setState({isValid, validationResults});
            }
            return validationResults;
        }).catch(validationError => {
            // Set custom error message if defined
            const validator = validationError.validator;
            if (validator in messages) {
                validationError.setMessage(messages[validator]);
            }

            // Set component state to reflect validation error
            component.setState({
                isValid: false,
                validationMessage: validationError.message,
                validationResults: false
            });

            return false;
        });
    }

    validate() {
        let allIsValid = true;

        const inputs = this.inputs;
        // Inputs must be validated in a queue because we may have async validators
        let chain = Q(allIsValid).then(valid => valid);
        Object.keys(inputs).forEach(name => {
            const cmp = inputs[name].component;
            const hasValidators = inputs[name] && inputs[name].validators;
            const shouldValidate = (!cmp.hasValue() && cmp.isRequired()) || (cmp.hasValue() && cmp.state.isValid !== true);

            if (hasValidators && shouldValidate) {
                if (cmp.state.isValid === false || cmp.state.isValid === null) {
                    chain = chain.then(() => {
                        return this.validateInput(cmp).then(validationResult => {
                            if (validationResult === false) {
                                allIsValid = false;
                            }
                            return allIsValid;
                        });
                    });
                }
            }
        });

        return chain;
    }

    render() {
        this.prepareForm(this.props.children);
        return super.render();
    }
}

Form.defaultProps = {
    name: _.uniqueId('form-'),
    onSubmit: _.noop,
    onReset: _.noop,
    onCancel: _.noop,
    onInvalid: _.noop,
    showLoader: true,
    linkedForms: null
};

export default Form;<|endoftext|>


<commit_before>function web_debranding_dialog(instance) {
    var QWeb = instance.web.qweb;
    var _t = instance.web._t;

    instance.web.CrashManager.include({
        init: function () {
            this._super();
            var self = this;
            var model = new openerp.Model("ir.config_parameter");
            self.debranding_new_name = _t('Software');
            var r = model.query(['value'])
                .filter([['key', '=', 'web_debranding.new_name']])
                .limit(1)
                .all().then(function (data) {
                    if (!data.length)
                        return;
                    self.debranding_new_name = data[0].value;
                });
        },
    });

    instance.web.Dialog.include({
        init: function (parent, options, content) {
            if (parent && parent.debranding_new_name){
                var content_html = content.html().replace(/Odoo/ig, parent.debranding_new_name);
                var title = options['title'].replace(/Odoo/ig, parent.debranding_new_name);
                if (content)
                    content.html(content_html);
                options['title'] = title;
            }
            this._super(parent, options, content);
        },
    });
};
<commit_msg>[FIX] check variables before using<commit_after>function web_debranding_dialog(instance) {
    var QWeb = instance.web.qweb;
    var _t = instance.web._t;

    instance.web.CrashManager.include({
        init: function () {
            this._super();
            var self = this;
            var model = new openerp.Model("ir.config_parameter");
            self.debranding_new_name = _t('Software');
            var r = model.query(['value'])
                .filter([['key', '=', 'web_debranding.new_name']])
                .limit(1)
                .all().then(function (data) {
                    if (!data.length)
                        return;
                    self.debranding_new_name = data[0].value;
                });
        },
    });

    instance.web.Dialog.include({
        init: function (parent, options, content) {
            if (parent && parent.debranding_new_name){
                options = options || {};
                if (options['title']){
                    var title = options['title'].replace(/Odoo/ig, parent.debranding_new_name);
                    options['title'] = title;
                }
                if (content){
                    var content_html = content.html().replace(/Odoo/ig, parent.debranding_new_name);
                    content.html(content_html);
                }
            }
            this._super(parent, options, content);
        },
    });
};
<|endoftext|>


<commit_before>if (typeof exports != "undefined") {
	var test = require("../driver.js").test;
	var testFail = require("../driver.js").testFail;
	var testAssert = require("../driver.js").testAssert;
}

var instructions = [
	{ keyword: '@import', label: 'HyperloopImport' },
	{ keyword: '@class', label: 'HyperloopClass' },
	{ keyword: '@compiler', label: 'HyperloopCompiler' }
];

for (var i = 0; i < instructions.length; i++) {
	var inst = instructions[i];
	var len = inst.keyword.length;

	test(inst.keyword + "()\n", {
		type: "Program",
		body: [
			{
				type: inst.label,
				start: 0,
				end: 2 + len,
				arguments: []
			}
		]
	});

	test(inst.keyword + "(1)\n", {
		type: "Program",
		body: [
			{
				type: inst.label,
				start: 0,
				end: 3 + len,
				arguments: [
					{
						type: 'Literal',
						start: 1 + len,
						end: 2 + len,
						value: 1
					}
				]
			}
		]
	});

	test(inst.keyword + "(1, 'quux')\n", {
		type: "Program",
		body: [
			{
				type: inst.label,
				start: 0,
				end: 11 + len,
				arguments: [
					{
						type: 'Literal',
						start: 1 + len,
						end: 2 + len,
						value: 1
					},
					{
						type: 'Literal',
						start: 4 + len,
						end: 10 + len,
						value: 'quux'
					}
				]
			}
		]
	});

	test(inst.keyword + "(function(){})\n", {
		type: "Program",
		body: [
			{
				type: inst.label,
				start: 0,
				end: 14 + len,
				arguments: [
					{
						type: 'FunctionExpression',
						start: 1 + len,
						end: 13 + len,
						id: null,
						params: [],
						body: {
							type: "BlockStatement",
							body: []
						}
					}
				]
			}
		]
	});

	test(inst.keyword + "(function foo(){})\n", {
		type: "Program",
		body: [
			{
				type: inst.label,
				start: 0,
				end: 18 + len,
				arguments: [
					{
						type: 'FunctionExpression',
						start: 1 + len,
						end: 17 + len,
						id: {
							type: "Identifier",
							start: 10 + len,
							end: 13 + len,
							loc: {
								start: {
									line: 1,
									column: 10 + len
								},
								end: {
									line: 1,
									column: 13 + len
								}
							},
							name: "foo"
						},
						params: [],
						body: {
							type: "BlockStatement",
							body: []
						}
					}
				]
			}
		]
	});

	test(inst.keyword + "({ cflags: ['-DDEBUG=1'] })\n", {
		type: "Program",
		body: [
			{
				type: inst.label,
				start: 0,
				end: 27 + len,
				arguments: [
					{
						type: 'ObjectExpression',
						start: 1 + len,
						end: 26 + len,
						properties: [
							{
								key: {
									type: 'Identifier',
									start: 3 + len,
									end: 9 + len,
									name: 'cflags'
								},
								value: {
									type: 'ArrayExpression',
									start: 11 + len,
									end: 24 + len,
									elements: [
										{
											type: 'Literal',
											start: 12 + len,
											end: 23 + len,
											value: "-DDEBUG=1",
											raw: "'-DDEBUG=1'"
										}
									]
								}
							}
						]
					}
				]
			}
		]
	});

	testFail(inst.keyword, "Unexpected token (1:" + len + ")");
	testFail(inst.keyword + "(", "Unexpected token (1:" + (1+len) + ")");
	testFail(inst.keyword + ".foo", "Unexpected token (1:" + len + ")");
	testFail(inst.keyword + "['foo']", "Unexpected token (1:" + (7+len) + ")");
}

test("var callback = @class(function(sender) {})\n", {
	type: "Program",
	start: 0,
	end: 42,
	body: [
		{
			type: "VariableDeclaration",
			start: 0,
			end: 42,
			declarations: [
				{
					type: "VariableDeclarator",
					start: 4,
					end: 42,
					id: {
						type: "Identifier",
						start: 4,
						end: 12,
						name: "callback"
					},
					init: {
						type: "HyperloopClass",
						start: 15,
						end: 42,
						arguments: [
							{
								type: "FunctionExpression",
								start: 22,
								end: 41,
								id: null,
								params: [
									{
										type: "Identifier",
										start: 31,
										end: 37,
										name: "sender"
									}
								],
								body: {
									type: "BlockStatement",
									start: 39,
									end: 41,
									body: []
								}
							}
						]
					}
				}
			],
			kind: "var"
		}
	]
});

test("var callback = @class('Classname', function(sender) {})\n", {
  "type": "Program",
  "start": 0,
  "end": 55,
  "body": [
    {
      "type": "VariableDeclaration",
      "start": 0,
      "end": 55,
      "declarations": [
        {
          "type": "VariableDeclarator",
          "start": 4,
          "end": 55,
          "id": {
            "type": "Identifier",
            "start": 4,
            "end": 12,
            "name": "callback"
          },
          "init": {
            "type": "HyperloopClass",
            "start": 15,
            "end": 55,
            "arguments": [
              {
                "type": "Literal",
                "start": 22,
                "end": 33,
                "value": "Classname",
                "raw": "'Classname'"
              },
              {
                "type": "FunctionExpression",
                "start": 35,
                "end": 54,
                "id": null,
                "params": [
                  {
                    "type": "Identifier",
                    "start": 44,
                    "end": 50,
                    "name": "sender"
                  }
                ],
                "body": {
                  "type": "BlockStatement",
                  "start": 52,
                  "end": 54,
                  "body": []
                }
              }
            ]
          }
        }
      ],
      "kind": "var"
    }
  ]
});

test("var callback = @class('Classname', [], function(sender) {})\n", {
  "type": "Program",
  "start": 0,
  "end": 59,
  "body": [
    {
      "type": "VariableDeclaration",
      "start": 0,
      "end": 59,
      "declarations": [
        {
          "type": "VariableDeclarator",
          "start": 4,
          "end": 59,
          "id": {
            "type": "Identifier",
            "start": 4,
            "end": 12,
            "name": "callback"
          },
          "init": {
            "type": "HyperloopClass",
            "start": 15,
            "end": 59,
            "arguments": [
              {
                "type": "Literal",
                "start": 22,
                "end": 33,
                "value": "Classname",
                "raw": "'Classname'"
              },
              {
                "type": "ArrayExpression",
                "start": 35,
                "end": 37,
                "elements": []
              },
              {
                "type": "FunctionExpression",
                "start": 39,
                "end": 58,
                "id": null,
                "params": [
                  {
                    "type": "Identifier",
                    "start": 48,
                    "end": 54,
                    "name": "sender"
                  }
                ],
                "body": {
                  "type": "BlockStatement",
                  "start": 56,
                  "end": 58,
                  "body": []
                }
              }
            ]
          }
        }
      ],
      "kind": "var"
    }
  ]
});

test("var callback = @class('Classname', ['interface1', 'interface2'], function(sender) {})\n", {
  "type": "Program",
  "start": 0,
  "end": 85,
  "body": [
    {
      "type": "VariableDeclaration",
      "start": 0,
      "end": 85,
      "declarations": [
        {
          "type": "VariableDeclarator",
          "start": 4,
          "end": 85,
          "id": {
            "type": "Identifier",
            "start": 4,
            "end": 12,
            "name": "callback"
          },
          "init": {
            "type": "HyperloopClass",
            "start": 15,
            "end": 85,
            "arguments": [
              {
                "type": "Literal",
                "start": 22,
                "end": 33,
                "value": "Classname",
                "raw": "'Classname'"
              },
              {
                "type": "ArrayExpression",
                "start": 35,
                "end": 63,
                "elements": [
                  {
                    "type": "Literal",
                    "start": 36,
                    "end": 48,
                    "value": "interface1",
                    "raw": "'interface1'"
                  },
                  {
                    "type": "Literal",
                    "start": 50,
                    "end": 62,
                    "value": "interface2",
                    "raw": "'interface2'"
                  }
                ]
              },
              {
                "type": "FunctionExpression",
                "start": 65,
                "end": 84,
                "id": null,
                "params": [
                  {
                    "type": "Identifier",
                    "start": 74,
                    "end": 80,
                    "name": "sender"
                  }
                ],
                "body": {
                  "type": "BlockStatement",
                  "start": 82,
                  "end": 84,
                  "body": []
                }
              }
            ]
          }
        }
      ],
      "kind": "var"
    }
  ]
});

testFail("@foo", "'@foo' is an invalid a hyperloop instruction (1:0)");
<commit_msg>a few more much more complicated hyperloop instruction tests<commit_after>if (typeof exports != "undefined") {
	var test = require("../driver.js").test;
	var testFail = require("../driver.js").testFail;
	var testAssert = require("../driver.js").testAssert;
}

var instructions = [
	{ keyword: '@import', label: 'HyperloopImport' },
	{ keyword: '@class', label: 'HyperloopClass' },
	{ keyword: '@compiler', label: 'HyperloopCompiler' }
];

for (var i = 0; i < instructions.length; i++) {
	var inst = instructions[i];
	var len = inst.keyword.length;

	test(inst.keyword + "()\n", {
		type: "Program",
		body: [
			{
				type: inst.label,
				start: 0,
				end: 2 + len,
				arguments: []
			}
		]
	});

	test(inst.keyword + "(1)\n", {
		type: "Program",
		body: [
			{
				type: inst.label,
				start: 0,
				end: 3 + len,
				arguments: [
					{
						type: 'Literal',
						start: 1 + len,
						end: 2 + len,
						value: 1
					}
				]
			}
		]
	});

	test(inst.keyword + "(1, 'quux')\n", {
		type: "Program",
		body: [
			{
				type: inst.label,
				start: 0,
				end: 11 + len,
				arguments: [
					{
						type: 'Literal',
						start: 1 + len,
						end: 2 + len,
						value: 1
					},
					{
						type: 'Literal',
						start: 4 + len,
						end: 10 + len,
						value: 'quux'
					}
				]
			}
		]
	});

	test(inst.keyword + "(function(){})\n", {
		type: "Program",
		body: [
			{
				type: inst.label,
				start: 0,
				end: 14 + len,
				arguments: [
					{
						type: 'FunctionExpression',
						start: 1 + len,
						end: 13 + len,
						id: null,
						params: [],
						body: {
							type: "BlockStatement",
							body: []
						}
					}
				]
			}
		]
	});

	test(inst.keyword + "(function foo(){})\n", {
		type: "Program",
		body: [
			{
				type: inst.label,
				start: 0,
				end: 18 + len,
				arguments: [
					{
						type: 'FunctionExpression',
						start: 1 + len,
						end: 17 + len,
						id: {
							type: "Identifier",
							start: 10 + len,
							end: 13 + len,
							loc: {
								start: {
									line: 1,
									column: 10 + len
								},
								end: {
									line: 1,
									column: 13 + len
								}
							},
							name: "foo"
						},
						params: [],
						body: {
							type: "BlockStatement",
							body: []
						}
					}
				]
			}
		]
	});

	test(inst.keyword + "({ cflags: ['-DDEBUG=1'] })\n", {
		type: "Program",
		body: [
			{
				type: inst.label,
				start: 0,
				end: 27 + len,
				arguments: [
					{
						type: 'ObjectExpression',
						start: 1 + len,
						end: 26 + len,
						properties: [
							{
								key: {
									type: 'Identifier',
									start: 3 + len,
									end: 9 + len,
									name: 'cflags'
								},
								value: {
									type: 'ArrayExpression',
									start: 11 + len,
									end: 24 + len,
									elements: [
										{
											type: 'Literal',
											start: 12 + len,
											end: 23 + len,
											value: "-DDEBUG=1",
											raw: "'-DDEBUG=1'"
										}
									]
								}
							}
						]
					}
				]
			}
		]
	});

	testFail(inst.keyword, "Unexpected token (1:" + len + ")");
	testFail(inst.keyword + "(", "Unexpected token (1:" + (1+len) + ")");
	testFail(inst.keyword + ".foo", "Unexpected token (1:" + len + ")");
	testFail(inst.keyword + "['foo']", "Unexpected token (1:" + (7+len) + ")");
}

test("var callback = @class(function(sender) {})\n", {
	type: "Program",
	start: 0,
	end: 42,
	body: [
		{
			type: "VariableDeclaration",
			start: 0,
			end: 42,
			declarations: [
				{
					type: "VariableDeclarator",
					start: 4,
					end: 42,
					id: {
						type: "Identifier",
						start: 4,
						end: 12,
						name: "callback"
					},
					init: {
						type: "HyperloopClass",
						start: 15,
						end: 42,
						arguments: [
							{
								type: "FunctionExpression",
								start: 22,
								end: 41,
								id: null,
								params: [
									{
										type: "Identifier",
										start: 31,
										end: 37,
										name: "sender"
									}
								],
								body: {
									type: "BlockStatement",
									start: 39,
									end: 41,
									body: []
								}
							}
						]
					}
				}
			],
			kind: "var"
		}
	]
});

test("var callback = @class('Classname', function(sender) {})\n", {
  "type": "Program",
  "start": 0,
  "end": 55,
  "body": [
    {
      "type": "VariableDeclaration",
      "start": 0,
      "end": 55,
      "declarations": [
        {
          "type": "VariableDeclarator",
          "start": 4,
          "end": 55,
          "id": {
            "type": "Identifier",
            "start": 4,
            "end": 12,
            "name": "callback"
          },
          "init": {
            "type": "HyperloopClass",
            "start": 15,
            "end": 55,
            "arguments": [
              {
                "type": "Literal",
                "start": 22,
                "end": 33,
                "value": "Classname",
                "raw": "'Classname'"
              },
              {
                "type": "FunctionExpression",
                "start": 35,
                "end": 54,
                "id": null,
                "params": [
                  {
                    "type": "Identifier",
                    "start": 44,
                    "end": 50,
                    "name": "sender"
                  }
                ],
                "body": {
                  "type": "BlockStatement",
                  "start": 52,
                  "end": 54,
                  "body": []
                }
              }
            ]
          }
        }
      ],
      "kind": "var"
    }
  ]
});

test("var callback = @class('Classname', [], function(sender) {})\n", {
  "type": "Program",
  "start": 0,
  "end": 59,
  "body": [
    {
      "type": "VariableDeclaration",
      "start": 0,
      "end": 59,
      "declarations": [
        {
          "type": "VariableDeclarator",
          "start": 4,
          "end": 59,
          "id": {
            "type": "Identifier",
            "start": 4,
            "end": 12,
            "name": "callback"
          },
          "init": {
            "type": "HyperloopClass",
            "start": 15,
            "end": 59,
            "arguments": [
              {
                "type": "Literal",
                "start": 22,
                "end": 33,
                "value": "Classname",
                "raw": "'Classname'"
              },
              {
                "type": "ArrayExpression",
                "start": 35,
                "end": 37,
                "elements": []
              },
              {
                "type": "FunctionExpression",
                "start": 39,
                "end": 58,
                "id": null,
                "params": [
                  {
                    "type": "Identifier",
                    "start": 48,
                    "end": 54,
                    "name": "sender"
                  }
                ],
                "body": {
                  "type": "BlockStatement",
                  "start": 56,
                  "end": 58,
                  "body": []
                }
              }
            ]
          }
        }
      ],
      "kind": "var"
    }
  ]
});

test("var callback = @class('Classname', ['interface1', 'interface2'], function(sender) {})\n", {
  "type": "Program",
  "start": 0,
  "end": 85,
  "body": [
    {
      "type": "VariableDeclaration",
      "start": 0,
      "end": 85,
      "declarations": [
        {
          "type": "VariableDeclarator",
          "start": 4,
          "end": 85,
          "id": {
            "type": "Identifier",
            "start": 4,
            "end": 12,
            "name": "callback"
          },
          "init": {
            "type": "HyperloopClass",
            "start": 15,
            "end": 85,
            "arguments": [
              {
                "type": "Literal",
                "start": 22,
                "end": 33,
                "value": "Classname",
                "raw": "'Classname'"
              },
              {
                "type": "ArrayExpression",
                "start": 35,
                "end": 63,
                "elements": [
                  {
                    "type": "Literal",
                    "start": 36,
                    "end": 48,
                    "value": "interface1",
                    "raw": "'interface1'"
                  },
                  {
                    "type": "Literal",
                    "start": 50,
                    "end": 62,
                    "value": "interface2",
                    "raw": "'interface2'"
                  }
                ]
              },
              {
                "type": "FunctionExpression",
                "start": 65,
                "end": 84,
                "id": null,
                "params": [
                  {
                    "type": "Identifier",
                    "start": 74,
                    "end": 80,
                    "name": "sender"
                  }
                ],
                "body": {
                  "type": "BlockStatement",
                  "start": 82,
                  "end": 84,
                  "body": []
                }
              }
            ]
          }
        }
      ],
      "kind": "var"
    }
  ]
});

test("var callback = @class(function foo(sender) { NSLog('clicked on button=%@', sender); })", {
  "type": "Program",
  "start": 0,
  "end": 86,
  "body": [
    {
      "type": "VariableDeclaration",
      "start": 0,
      "end": 86,
      "declarations": [
        {
          "type": "VariableDeclarator",
          "start": 4,
          "end": 86,
          "id": {
            "type": "Identifier",
            "start": 4,
            "end": 12,
            "name": "callback"
          },
          "init": {
            "type": "HyperloopClass",
            "start": 15,
            "end": 86,
            "arguments": [
              {
                "type": "FunctionExpression",
                "start": 22,
                "end": 85,
                "id": {
                  "type": "Identifier",
                  "start": 31,
                  "end": 34,
                  "name": "foo"
                },
                "params": [
                  {
                    "type": "Identifier",
                    "start": 35,
                    "end": 41,
                    "name": "sender"
                  }
                ],
                "body": {
                  "type": "BlockStatement",
                  "start": 43,
                  "end": 85,
                  "body": [
                    {
                      "type": "ExpressionStatement",
                      "start": 45,
                      "end": 83,
                      "expression": {
                        "type": "CallExpression",
                        "start": 45,
                        "end": 82,
                        "callee": {
                          "type": "Identifier",
                          "start": 45,
                          "end": 50,
                          "name": "NSLog"
                        },
                        "arguments": [
                          {
                            "type": "Literal",
                            "start": 51,
                            "end": 73,
                            "value": "clicked on button=%@",
                            "raw": "'clicked on button=%@'"
                          },
                          {
                            "type": "Identifier",
                            "start": 75,
                            "end": 81,
                            "name": "sender"
                          }
                        ]
                      }
                    }
                  ]
                }
              }
            ]
          }
        }
      ],
      "kind": "var"
    }
  ]
});

test("@import('UIKit/UIApplication');\n" +
"@import('Foundation/NSLog');\n" +
"\n" +
"@compiler({\n" +
"	cflags: ['-DDEBUG=1']\n" +
"});\n" +
"\n" +
"var callback = @class(function foo(sender) {\n" +
"	NSLog('clicked on button=%@', sender);\n" +
"});", {
  "type": "Program",
  "start": 0,
  "end": 190,
  "body": [
    {
      "type": "HyperloopImport",
      "start": 0,
      "end": 31,
      "arguments": [
        {
          "type": "Literal",
          "start": 8,
          "end": 29,
          "value": "UIKit/UIApplication",
          "raw": "'UIKit/UIApplication'"
        }
      ]
    },
    {
      "type": "HyperloopImport",
      "start": 32,
      "end": 60,
      "arguments": [
        {
          "type": "Literal",
          "start": 40,
          "end": 58,
          "value": "Foundation/NSLog",
          "raw": "'Foundation/NSLog'"
        }
      ]
    },
    {
      "type": "HyperloopCompiler",
      "start": 62,
      "end": 100,
      "arguments": [
        {
          "type": "ObjectExpression",
          "start": 72,
          "end": 98,
          "properties": [
            {
              "key": {
                "type": "Identifier",
                "start": 75,
                "end": 81,
                "name": "cflags"
              },
              "value": {
                "type": "ArrayExpression",
                "start": 83,
                "end": 96,
                "elements": [
                  {
                    "type": "Literal",
                    "start": 84,
                    "end": 95,
                    "value": "-DDEBUG=1",
                    "raw": "'-DDEBUG=1'"
                  }
                ]
              },
              "kind": "init"
            }
          ]
        }
      ]
    },
    {
      "type": "VariableDeclaration",
      "start": 102,
      "end": 189,
      "declarations": [
        {
          "type": "VariableDeclarator",
          "start": 106,
          "end": 189,
          "id": {
            "type": "Identifier",
            "start": 106,
            "end": 114,
            "name": "callback"
          },
          "init": {
            "type": "HyperloopClass",
            "start": 117,
            "end": 189,
            "arguments": [
              {
                "type": "FunctionExpression",
                "start": 124,
                "end": 188,
                "id": {
                  "type": "Identifier",
                  "start": 133,
                  "end": 136,
                  "name": "foo"
                },
                "params": [
                  {
                    "type": "Identifier",
                    "start": 137,
                    "end": 143,
                    "name": "sender"
                  }
                ],
                "body": {
                  "type": "BlockStatement",
                  "start": 145,
                  "end": 188,
                  "body": [
                    {
                      "type": "ExpressionStatement",
                      "start": 148,
                      "end": 186,
                      "expression": {
                        "type": "CallExpression",
                        "start": 148,
                        "end": 185,
                        "callee": {
                          "type": "Identifier",
                          "start": 148,
                          "end": 153,
                          "name": "NSLog"
                        },
                        "arguments": [
                          {
                            "type": "Literal",
                            "start": 154,
                            "end": 176,
                            "value": "clicked on button=%@",
                            "raw": "'clicked on button=%@'"
                          },
                          {
                            "type": "Identifier",
                            "start": 178,
                            "end": 184,
                            "name": "sender"
                          }
                        ]
                      }
                    }
                  ]
                }
              }
            ]
          }
        }
      ],
      "kind": "var"
    }
  ]
});

testFail("@foo", "'@foo' is an invalid a hyperloop instruction (1:0)");
<|endoftext|>


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

/**
 * This represents the mobile device, and provides properties for inspecting the model, version, UUID of the
 * phone, etc.
 * @constructor
 */
/*function ETPush() {
    this.available = false;
    this.platform = null;
    this.version = null;
    this.uuid = null;
    this.cordova = null;
    this.model = null;

    var me = this;

    channel.onCordovaReady.subscribe(function() {
        me.getInfo(function(info) {
            //ignoring info.cordova returning from native, we should use value from cordova.version defined in cordova.js
            //TODO: CB-5105 native implementations should not return info.cordova
            var buildLabel = cordova.version;
            me.available = true;
            me.platform = info.platform;
            me.version = info.version;
            me.uuid = info.uuid;
            me.cordova = buildLabel;
            me.model = info.model;
            channel.onCordovaInfoReady.fire();
        },function(e) {
            me.available = false;
            utils.alert("[ERROR] Error initializing Cordova: " + e);
        });
    });
}
*/

/**
 * Get device info
 *
 * @param {Function} successCallback The function to call when the heading data is available
 * @param {Function} errorCallback The function to call when there is an error getting the heading data. (OPTIONAL)
 */

 var ETPush = {
    Test: function(successCallback, errorCallback) {
        cordova.exec(successCallback, errorCallback, "SdkWrapper", "test", []);
    },
    register: function(successCallback, errorCallback, accessToken, appID)
    {

    },
    //returns boolean with whether device notifications are active
    isPushEnabled: function(SuccessCallback, errorCallback) {
        cordova.exec(successCallback, errorCallback, "SdkWrapper", "isPushEnabled", []);
    },
    //returns the uniqe device identifier
    safeDeviceIdentifier: function(SuccessCallback, errorCallback) {
        cordova.exec(successCallback, errorCallback, "SdkWrapper", "safeDeviceIdentifier", []);
    },
    //get the current subscriber key
    getSubscriberKey: function(SuccessCallback, errorCallback, subscriberKey) {
        cordova.exec(successCallback, errorCallback, "SdkWrapper", "getSubscriberKey", []);
    },
    //set the current subscriber key
    setSubscriberKey: function(SuccessCallback, errorCallback,subscriberKey, value) {
        cordova.exec(successCallback, errorCallback, "SdkWrapper", "getSubscriberKey", []);
    },
    // add a tag
    addTag: function(SuccessCallback, errorCallback, tag, value) {
        cordova.exec(successCallback, errorCallback, "SdkWrapper", "getSubscriberKey", []);
    },
    //remove a tag
    removeTag: function(SuccessCallback, errorCallback, tag) {
        cordova.exec(successCallback, errorCallback, "SdkWrapper", "getSubscriberKey", []);
    },
    //return all the tags
    allTags: function(SuccessCallback, errorCallback) {
        cordova.exec(successCallback, errorCallback, "SdkWrapper", "getSubscriberKey", []);
    },
    //add an attribute and set its value
    addAttribute: function(SuccessCallback, errorCallback, name, var value) {
        cordova.exec(successCallback, errorCallback, "SdkWrapper", "getSubscriberKey", []);
    },
    //remove an attribute
    removeAttribute: function(SuccessCallback, errorCallback, name, var value) {
        cordova.exec(successCallback, errorCallback, "SdkWrapper", "getSubscriberKey", []);
    },
    //returns all attributes
    allAttributes: function(SuccessCallback, errorCallback) {
        cordova.exec(successCallback, errorCallback, "SdkWrapper", "getSubscriberKey", []);
    },
 }

<commit_msg>attempting to fix project setup<commit_after>/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
*/

/**
 * This represents the mobile device, and provides properties for inspecting the model, version, UUID of the
 * phone, etc.
 * @constructor
 */
/*function ETPush() {
    this.available = false;
    this.platform = null;
    this.version = null;
    this.uuid = null;
    this.cordova = null;
    this.model = null;

    var me = this;

    channel.onCordovaReady.subscribe(function() {
        me.getInfo(function(info) {
            //ignoring info.cordova returning from native, we should use value from cordova.version defined in cordova.js
            //TODO: CB-5105 native implementations should not return info.cordova
            var buildLabel = cordova.version;
            me.available = true;
            me.platform = info.platform;
            me.version = info.version;
            me.uuid = info.uuid;
            me.cordova = buildLabel;
            me.model = info.model;
            channel.onCordovaInfoReady.fire();
        },function(e) {
            me.available = false;
            utils.alert("[ERROR] Error initializing Cordova: " + e);
        });
    });
}
*/

/**
 * Get device info
 *
 * @param {Function} successCallback The function to call when the heading data is available
 * @param {Function} errorCallback The function to call when there is an error getting the heading data. (OPTIONAL)
 */

 var ETPush = {
    Test: function(successCallback, errorCallback) {
        cordova.exec(successCallback, errorCallback, "SdkWrapper", "test", []);
    },
    register: function(successCallback, errorCallback, accessToken, appID)
    {

    },
    //returns boolean with whether device notifications are active
    isPushEnabled: function(SuccessCallback, errorCallback) {
        cordova.exec(successCallback, errorCallback, "SdkWrapper", "isPushEnabled", []);
    },
    //returns the uniqe device identifier
    safeDeviceIdentifier: function(SuccessCallback, errorCallback) {
        cordova.exec(successCallback, errorCallback, "SdkWrapper", "safeDeviceIdentifier", []);
    },
    //get the current subscriber key
    getSubscriberKey: function(SuccessCallback, errorCallback, subscriberKey) {
        cordova.exec(successCallback, errorCallback, "SdkWrapper", "getSubscriberKey", []);
    },
    //set the current subscriber key
    setSubscriberKey: function(SuccessCallback, errorCallback,subscriberKey, value) {
        cordova.exec(successCallback, errorCallback, "SdkWrapper", "getSubscriberKey", []);
    },
    // add a tag
    addTag: function(SuccessCallback, errorCallback, tag, value) {
        cordova.exec(successCallback, errorCallback, "SdkWrapper", "getSubscriberKey", []);
    },
    //remove a tag
    removeTag: function(SuccessCallback, errorCallback, tag) {
        cordova.exec(successCallback, errorCallback, "SdkWrapper", "getSubscriberKey", []);
    },
    //return all the tags
    allTags: function(SuccessCallback, errorCallback) {
        cordova.exec(successCallback, errorCallback, "SdkWrapper", "getSubscriberKey", []);
    },
    //add an attribute and set its value
    addAttribute: function(SuccessCallback, errorCallback, name, value) {
        cordova.exec(successCallback, errorCallback, "SdkWrapper", "getSubscriberKey", []);
    },
    //remove an attribute
    removeAttribute: function(SuccessCallback, errorCallback, name, value) {
        cordova.exec(successCallback, errorCallback, "SdkWrapper", "getSubscriberKey", []);
    },
    //returns all attributes
    allAttributes: function(SuccessCallback, errorCallback) {
        cordova.exec(successCallback, errorCallback, "SdkWrapper", "getSubscriberKey", []);
    },
 }

<|endoftext|>


<commit_before>var should = require('should');
var request = require('supertest');
var server = require('../../../app');

process.env.A127_ENV = 'test';

describe('controllers', function() {

  describe('hello_world', function() {

    describe('GET /hello', function() {

      it('should return a default string', function(done) {

        request(server)
          .get('/hello')
          .set('Accept', 'application/json')
          .expect('Content-Type', /json/)
          .expect(200)
          .end(function(err, res) {
            should.not.exist(err);

            res.body.should.eql('Hello, there!');

            done();
          });
      });

      it('should accept a name parameter', function(done) {

        request(server)
          .get('/hello')
          .query({
            name: 'Scott'
          })
          .set('Accept', 'application/json')
          .expect('Content-Type', /json/)
          .expect(200)
          .end(function(err, res) {
            should.not.exist(err);

            res.body.should.eql('Hello, there!');

            done();
          });
      });
    });
  });
});
<commit_msg>3 commit<commit_after>var should = require('should');
var request = require('supertest');
var server = require('../../../app');

process.env.A127_ENV = 'test';

describe('controllers', function() {

  describe('hello_world', function() {

    describe('GET /hello', function() {

      it('should return a default string', function(done) {

        request(server)
          .get('/hello')
          .set('Accept', 'application/json')
          .expect('Content-Type', /json/)
          .expect(200)
          .end(function(err, res) {
            should.not.exist(err);

            res.body.should.eql('Hello there!');

            done();
          });
      });

      it('should accept a name parameter', function(done) {

        request(server)
          .get('/hello')
          .query({
            name: 'Scott'
          })
          .set('Accept', 'application/json')
          .expect('Content-Type', /json/)
          .expect(200)
          .end(function(err, res) {
            should.not.exist(err);

            res.body.should.eql('Hello there!');

            done();
          });
      });
    });
  });
});
<|endoftext|>


<commit_before>/*global jasmine, __karma__, window*/
Error.stackTraceLimit = Infinity;

// The default time that jasmine waits for an asynchronous test to finish is five seconds.
// If this timeout is too short the CI may fail randomly because our asynchronous tests can
// take longer in some situations (e.g Saucelabs and Browserstack tunnels)
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;

__karma__.loaded = function () {};

var baseDir = '/base';
var specFiles = Object.keys(window.__karma__.files).filter(isSpecFile);

// Configure the base path and map the different node packages.
System.config({
  baseURL: baseDir,
  paths: {
    'node:*': 'node_modules/*'
  },
  map: {
    'rxjs': 'node:rxjs',
    'main': 'main.js',
    'tslib': 'node:tslib/tslib.js',

    // Angular specific mappings.
    '@angular/core': 'node:@angular/core/bundles/core.umd.js',
    '@angular/core/testing': 'node:@angular/core/bundles/core-testing.umd.js',
    '@angular/common': 'node:@angular/common/bundles/common.umd.js',
    '@angular/common/testing': 'node:@angular/common/bundles/common-testing.umd.js',
    '@angular/common/http': 'node:@angular/common/bundles/common-http.umd.js',
    '@angular/common/http/testing': 'node:@angular/common/bundles/common-http-testing.umd.js',
    '@angular/compiler': 'node:@angular/compiler/bundles/compiler.umd.js',
    '@angular/compiler/testing': 'node:@angular/compiler/bundles/compiler-testing.umd.js',
    '@angular/http': 'node:@angular/http/bundles/http.umd.js',
    '@angular/http/testing': 'node:@angular/http/bundles/http-testing.umd.js',
    '@angular/forms': 'node:@angular/forms/bundles/forms.umd.js',
    '@angular/forms/testing': 'node:@angular/forms/bundles/forms-testing.umd.js',
    '@angular/animations': 'node:@angular/animations/bundles/animations.umd.js',
    '@angular/animations/browser': 'node:@angular/animations/bundles/animations-browser.umd.js',
    '@angular/platform-browser/animations':
      'node:@angular/platform-browser/bundles/platform-browser-animations.umd',
    '@angular/platform-browser':
      'node:@angular/platform-browser/bundles/platform-browser.umd.js',
    '@angular/platform-browser/testing':
      'node:@angular/platform-browser/bundles/platform-browser-testing.umd.js',
    '@angular/platform-browser-dynamic':
      'node:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
    '@angular/platform-browser-dynamic/testing':
      'node:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',

    '@angular/material': 'node:@angular/material/bundles/material.umd.js',
    '@angular/cdk': 'node:@angular/cdk/bundles/cdk.umd.js',
    '@angular/cdk/a11y': 'node:@angular/cdk/bundles/cdk-a11y.umd.js',
    '@angular/cdk/accordion': 'node:@angular/cdk/bundles/cdk-accordion.umd.js',
    '@angular/cdk/bidi': 'node:@angular/cdk/bundles/cdk-bidi.umd.js',
    '@angular/cdk/coercion': 'node:@angular/cdk/bundles/cdk-coercion.umd.js',
    '@angular/cdk/collections': 'node:@angular/cdk/bundles/cdk-collections.umd.js',
    '@angular/cdk/keycodes': 'node:@angular/cdk/bundles/cdk-keycodes.umd.js',
    '@angular/cdk/layout': 'node:@angular/cdk/bundles/cdk-layout.umd.js',
    '@angular/cdk/observers': 'node:@angular/cdk/bundles/cdk-observers.umd.js',
    '@angular/cdk/overlay': 'node:@angular/cdk/bundles/cdk-overlay.umd.js',
    '@angular/cdk/platform': 'node:@angular/cdk/bundles/cdk-platform.umd.js',
    '@angular/cdk/portal': 'node:@angular/cdk/bundles/cdk-portal.umd.js',
    '@angular/cdk/rxjs': 'node:@angular/cdk/bundles/cdk-rxjs.umd.js',
    '@angular/cdk/scrolling': 'node:@angular/cdk/bundles/cdk-scrolling.umd.js',
    '@angular/cdk/stepper': 'node:@angular/cdk/bundles/cdk-stepper.umd.js',
    '@angular/cdk/table': 'node:@angular/cdk/bundles/cdk-table.umd.js',

    // Path mappings for local packages that can be imported inside of tests.
    '@angular/flex-layout': 'dist/packages/flex-layout/public-api.js'
  },
  packages: {
    // Thirdparty barrels.
    'rxjs': {main: 'index'},
    'rxjs/operators': {main: 'index'},

    // Set the default extension for the root package, because otherwise the demo-app can't
    // be built within the production mode. Due to missing file extensions.
    '.': {
      defaultExtension: 'js'
    }
  }
});

// Configure the Angular test bed and run all specs once configured.
 configureTestBed()
  .then(runSpecs)
  .then(__karma__.start, __karma__.error);

/** Runs the specs in Karma. */
function runSpecs() {
  // By importing all spec files, Karma will run the tests directly.
  return Promise.all(specFiles.map(function(fileName) {
    return System.import(fileName);
  }));
}

/** Whether the specified file is part of Angular Flex-Layout. */
function isSpecFile(path) {
  return path.slice(-8) === '.spec.js' && path.indexOf('node_modules') === -1;
}

/** Configures Angular's TestBed. */
function configureTestBed() {
  return Promise.all([
    System.import('@angular/core/testing'),
    System.import('@angular/platform-browser-dynamic/testing')
  ]).then(function (providers) {
    var testing = providers[0];
    var testingBrowser = providers[1];

    var testBed = testing.TestBed.initTestEnvironment(
      testingBrowser.BrowserDynamicTestingModule,
      testingBrowser.platformBrowserDynamicTesting()
    );

    patchTestBedToDestroyFixturesAfterEveryTest(testBed);
  });
}

/**
 * Monkey-patches TestBed.resetTestingModule such that any errors that occur during component
 * destruction are thrown instead of silently logged. Also runs TestBed.resetTestingModule after
 * each unit test.
 *
 * Without this patch, the combination of two behaviors is problematic for Angular Flex-Layout:
 * - TestBed.resetTestingModule catches errors thrown on fixture destruction and logs them without
 *     the errors ever being thrown. This means that any component errors that occur in ngOnDestroy
 *     can encounter errors silently and still pass unit tests.
 * - TestBed.resetTestingModule is only called *before* a test is run, meaning that even *if* the
 *    aforementioned errors were thrown, they would be reported for the wrong test (the test that's
 *    about to start, not the test that just finished).
 */
function patchTestBedToDestroyFixturesAfterEveryTest(testBed) {
  // Original resetTestingModule function of the TestBed.
  var _resetTestingModule = testBed.resetTestingModule;

  // Monkey-patch the resetTestingModule to destroy fixtures outside of a try/catch block.
  // With https://github.com/angular/angular/commit/2c5a67134198a090a24f6671dcdb7b102fea6eba
  // errors when destroying components are no longer causing Jasmine to fail.
  testBed.resetTestingModule = function() {
    try {
      this._activeFixtures.forEach(function (fixture) { fixture.destroy(); });
    } finally {
      this._activeFixtures = [];
      // Regardless of errors or not, run the original reset testing module function.
      _resetTestingModule.call(this);
    }
  };

  // Angular's testing package resets the testing module before each test. This doesn't work well
  // for us because it doesn't allow developers to see what test actually failed.
  // Fixing this by resetting the testing module after each test.
  // https://github.com/angular/angular/blob/master/packages/core/testing/src/before_each.ts#L25
  afterEach(function() {
    testBed.resetTestingModule();
  });
}
<commit_msg>build: fix runtime errors not being logged out on karma initialization<commit_after>/*global jasmine, __karma__, window*/
Error.stackTraceLimit = Infinity;

// The default time that jasmine waits for an asynchronous test to finish is five seconds.
// If this timeout is too short the CI may fail randomly because our asynchronous tests can
// take longer in some situations (e.g Saucelabs and Browserstack tunnels)
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;

__karma__.loaded = function () {};

var baseDir = '/base';
var specFiles = Object.keys(window.__karma__.files).filter(isSpecFile);

// Configure the base path and map the different node packages.
System.config({
  baseURL: baseDir,
  paths: {
    'node:*': 'node_modules/*'
  },
  map: {
    'rxjs': 'node:rxjs',
    'main': 'main.js',
    'tslib': 'node:tslib/tslib.js',

    // Angular specific mappings.
    '@angular/core': 'node:@angular/core/bundles/core.umd.js',
    '@angular/core/testing': 'node:@angular/core/bundles/core-testing.umd.js',
    '@angular/common': 'node:@angular/common/bundles/common.umd.js',
    '@angular/common/testing': 'node:@angular/common/bundles/common-testing.umd.js',
    '@angular/common/http': 'node:@angular/common/bundles/common-http.umd.js',
    '@angular/common/http/testing': 'node:@angular/common/bundles/common-http-testing.umd.js',
    '@angular/compiler': 'node:@angular/compiler/bundles/compiler.umd.js',
    '@angular/compiler/testing': 'node:@angular/compiler/bundles/compiler-testing.umd.js',
    '@angular/http': 'node:@angular/http/bundles/http.umd.js',
    '@angular/http/testing': 'node:@angular/http/bundles/http-testing.umd.js',
    '@angular/forms': 'node:@angular/forms/bundles/forms.umd.js',
    '@angular/forms/testing': 'node:@angular/forms/bundles/forms-testing.umd.js',
    '@angular/animations': 'node:@angular/animations/bundles/animations.umd.js',
    '@angular/animations/browser': 'node:@angular/animations/bundles/animations-browser.umd.js',
    '@angular/platform-browser/animations':
      'node:@angular/platform-browser/bundles/platform-browser-animations.umd',
    '@angular/platform-browser':
      'node:@angular/platform-browser/bundles/platform-browser.umd.js',
    '@angular/platform-browser/testing':
      'node:@angular/platform-browser/bundles/platform-browser-testing.umd.js',
    '@angular/platform-browser-dynamic':
      'node:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
    '@angular/platform-browser-dynamic/testing':
      'node:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',

    '@angular/material': 'node:@angular/material/bundles/material.umd.js',
    '@angular/cdk': 'node:@angular/cdk/bundles/cdk.umd.js',
    '@angular/cdk/a11y': 'node:@angular/cdk/bundles/cdk-a11y.umd.js',
    '@angular/cdk/accordion': 'node:@angular/cdk/bundles/cdk-accordion.umd.js',
    '@angular/cdk/bidi': 'node:@angular/cdk/bundles/cdk-bidi.umd.js',
    '@angular/cdk/coercion': 'node:@angular/cdk/bundles/cdk-coercion.umd.js',
    '@angular/cdk/collections': 'node:@angular/cdk/bundles/cdk-collections.umd.js',
    '@angular/cdk/keycodes': 'node:@angular/cdk/bundles/cdk-keycodes.umd.js',
    '@angular/cdk/layout': 'node:@angular/cdk/bundles/cdk-layout.umd.js',
    '@angular/cdk/observers': 'node:@angular/cdk/bundles/cdk-observers.umd.js',
    '@angular/cdk/overlay': 'node:@angular/cdk/bundles/cdk-overlay.umd.js',
    '@angular/cdk/platform': 'node:@angular/cdk/bundles/cdk-platform.umd.js',
    '@angular/cdk/portal': 'node:@angular/cdk/bundles/cdk-portal.umd.js',
    '@angular/cdk/rxjs': 'node:@angular/cdk/bundles/cdk-rxjs.umd.js',
    '@angular/cdk/scrolling': 'node:@angular/cdk/bundles/cdk-scrolling.umd.js',
    '@angular/cdk/stepper': 'node:@angular/cdk/bundles/cdk-stepper.umd.js',
    '@angular/cdk/table': 'node:@angular/cdk/bundles/cdk-table.umd.js',

    // Path mappings for local packages that can be imported inside of tests.
    '@angular/flex-layout': 'dist/packages/flex-layout/public-api.js'
  },
  packages: {
    // Thirdparty barrels.
    'rxjs': {main: 'index'},
    'rxjs/operators': {main: 'index'},

    // Set the default extension for the root package, because otherwise the demo-app can't
    // be built within the production mode. Due to missing file extensions.
    '.': {
      defaultExtension: 'js'
    }
  }
});

// Configure the Angular test bed and run all specs once configured.
configureTestBed()
  .then(runSpecs)
  .then(__karma__.start, function(error) {
    // Passing in the error object directly to Karma won't log out the stack trace and
    // passing the `originalErr` doesn't work correctly either. We have to log out the
    // stack trace so we can actually debug errors before the tests have started.
    console.error(error.originalErr.stack);
    __karma__.error(error);
  });

/** Runs the specs in Karma. */
function runSpecs() {
  // By importing all spec files, Karma will run the tests directly.
  return Promise.all(specFiles.map(function(fileName) {
    return System.import(fileName);
  }));
}

/** Whether the specified file is part of Angular Flex-Layout. */
function isSpecFile(path) {
  return path.slice(-8) === '.spec.js' && path.indexOf('node_modules') === -1;
}

/** Configures Angular's TestBed. */
function configureTestBed() {
  return Promise.all([
    System.import('@angular/core/testing'),
    System.import('@angular/platform-browser-dynamic/testing')
  ]).then(function (providers) {
    var testing = providers[0];
    var testingBrowser = providers[1];

    var testBed = testing.TestBed.initTestEnvironment(
      testingBrowser.BrowserDynamicTestingModule,
      testingBrowser.platformBrowserDynamicTesting()
    );

    patchTestBedToDestroyFixturesAfterEveryTest(testBed);
  });
}

/**
 * Monkey-patches TestBed.resetTestingModule such that any errors that occur during component
 * destruction are thrown instead of silently logged. Also runs TestBed.resetTestingModule after
 * each unit test.
 *
 * Without this patch, the combination of two behaviors is problematic for Angular Flex-Layout:
 * - TestBed.resetTestingModule catches errors thrown on fixture destruction and logs them without
 *     the errors ever being thrown. This means that any component errors that occur in ngOnDestroy
 *     can encounter errors silently and still pass unit tests.
 * - TestBed.resetTestingModule is only called *before* a test is run, meaning that even *if* the
 *    aforementioned errors were thrown, they would be reported for the wrong test (the test that's
 *    about to start, not the test that just finished).
 */
function patchTestBedToDestroyFixturesAfterEveryTest(testBed) {
  // Original resetTestingModule function of the TestBed.
  var _resetTestingModule = testBed.resetTestingModule;

  // Monkey-patch the resetTestingModule to destroy fixtures outside of a try/catch block.
  // With https://github.com/angular/angular/commit/2c5a67134198a090a24f6671dcdb7b102fea6eba
  // errors when destroying components are no longer causing Jasmine to fail.
  testBed.resetTestingModule = function() {
    try {
      this._activeFixtures.forEach(function (fixture) { fixture.destroy(); });
    } finally {
      this._activeFixtures = [];
      // Regardless of errors or not, run the original reset testing module function.
      _resetTestingModule.call(this);
    }
  };

  // Angular's testing package resets the testing module before each test. This doesn't work well
  // for us because it doesn't allow developers to see what test actually failed.
  // Fixing this by resetting the testing module after each test.
  // https://github.com/angular/angular/blob/master/packages/core/testing/src/before_each.ts#L25
  afterEach(function() {
    testBed.resetTestingModule();
  });
}
<|endoftext|>


<commit_before>var should = require('should');
var request = require('supertest');
var server = require('../../../app');

var mockSchemas = require('../mock_data/mock_schemas');
var targetSchemas = require('../mock_data/target_schemas');
var mockObjects = require('../mock_data/mock_objects');

//BATCH ARRAY VALIDATION:
// 1- We can't send large object with supertest at this point (POST objects/validate is for small arrays)
//    Even if we could swagger will freeze when validating such a large dataset, replace objects and schema by "something" to get threw this
//    Following CURL will fail but this is an example:
//    $ curl -X POST -H "Content-Type: application/json" --data '{"something":{"schema":{},"objects":"'$(cat NE_22k_example.json)'-"}}' http://10.30.90.174:9000/objects/validate
//
// 2- To send large number of object use the POST objects/gzipped/validate and attach to it a gzipped json file containing {schema: {} and objects: []}
//    Following curl was used at some point before sending multipart/form-data and a param named "file"
//    $ curl -v -s --trace-ascii http_tracery @_NE_22k_example.json.gz -H "Content-Type: application/json" -H "Content-Encoding: gzip" -X POST http://10.30.90.174:9000/objects/gzipped/validate
//
// 3- Method POST objects/gzipped/valdiate now attends multipart/form-data so we can retreive file inside the express api
//    Both following curls commands actually should still works
//    TRUE <= $ curl -F "file=@NE_111k.json.gz" http:10.30.90.174:9000/objects/gzipped/validate
//    FALSE <= $ curl -F "file=@NE_111k_with_errors.json.gz" http:10.30.90.174:9000/objects/gzipped/validate
//    But now supertest method attach() support attached files with multipart/form-data so curl are kinda useless

var objects22k = [{"_start": 123}, {"_start": 12223}];
var basic = {
  "required": [ "_start"]
};

describe('controllers', function () {

  describe('json_object', function () {

    describe('POST /object/validate', function () {

      it('should return an error 400 if body is missing', function (done) {

        request(server)
          .post('/object/validate')
          .set('Accept', 'application/json')
          .expect('Content-Type', /json/)
          .expect(400)
          .end(function (err, res) {
            should.not.exist(err);
            //res.status.should.eql(400);
            done();
          });
      });

      it('should return an error 400 if schema is missing from body', function (done) {

        request(server)
          .post('/object/validate')
          .send({object: {}})
          .set('Accept', 'application/json')
          .expect('Content-Type', /json/)
          .expect(400)
          .end(function (err, res) {
            should.not.exist(err);
            done();
          });
      });

      it('should return an error 422 if schema is an invalid json schema', function (done) {

        request(server)
          .post('/object/validate')
          .send({ schema: { "required": "yolo123"}, object: { yolo : 123}})
          .set('Accept', 'application/json')
          .expect('Content-Type', /json/)
          .expect(422)
          .end(function (err, res) {
            should.not.exist(err);
            should.exist(res.body.code);
            should.exist(res.body.message);
            done();
          });
      });

      it('should accept master schema and a valid faceDetect object', function (done) {

        request(server)
          .post('/object/validate')
          .send({schema: targetSchemas.master, object: mockObjects.faceValid})
          .set('Accept', 'application/json')
          .expect('Content-Type', /json/)
          .expect(200)
          .end(function (err, res) {
            should.not.exist(err);
            res.body.should.eql({ isValid: true });
            done();
          });
      });

      it('should accept multimedia_document_content schema and a valid faceDetect object', function (done) {

        request(server)
          .post('/object/validate')
          .send({schema: targetSchemas.multimedia_document_content, object: mockObjects.faceValid})
          .set('Accept', 'application/json')
          .expect('Content-Type', /json/)
          .expect(200)
          .end(function (err, res) {
            should.not.exist(err);
            res.body.should.eql({ isValid: true });
            done();
          });
      });

      it('should return { isValid: false, errors: [] } with multimedia_document_content schema and invalid faceDetect object', function (done) {

        request(server)
          .post('/object/validate')
          .send({schema: targetSchemas.multimedia_document_content, object: { yolo : 123}})
          .set('Accept', 'application/json')
          .expect('Content-Type', /json/)
          .expect(200)
          .end(function (err, res) {
            //TODO fix
            should.not.exist(err);
            should.exist(res.body.isValid);
            should.exist(res.body.errors);
            res.body.isValid.should.eql(false);
            done();
          });
      });

    });

    describe('POST /objects/validate', function () {

      it('should return { isValid : true } with objects22k', function (done) {
        request(server)
          .post('/objects/validate')
          .send({schema: basic, objects: objects22k})
          .set('Accept', 'application/json')
          .expect('Content-Type', /json/)
          .expect(200)
          .end(function (err, res) {
            should.not.exist(err);
            done();
          });
      });
    });

    describe('POST /objects/gzipped/validate', function () {

      it('should return { isValid : true } with 22k', function (done) {
        request(server)
          .post('/objects/gzipped/validate')
          .attach('file', './test/api/gzip_data/NE_22k.json.gz')
          .expect('Content-Type', /json/)
          .expect(200)
          .end(function (err, res) {
            should.not.exist(err);
            res.body.isValid.should.eql(true);
            done();
          });
      });

      it('should return { isValid : false } with 22k_with_errors', function (done) {
        request(server)
          .post('/objects/gzipped/validate')
          .attach('file', './test/api/gzip_data/NE_22k_with_error.json.gz')
          .expect('Content-Type', /json/)
          .expect(200)
          .end(function (err, res) {
            should.not.exist(err);
            res.body.isValid.should.eql(false);
            done();
          });
      });

      it('should return 400 with 22k_missing_schema', function (done) {
        request(server)
          .post('/objects/gzipped/validate')
          .attach('file', './test/api/gzip_data/NE_22k_missing_schema.json.gz')
          .expect('Content-Type', /json/)
          .expect(400)
          .end(function (err, res) {
            should.not.exist(err);
            done();
          });
      });

      it('should return 422 with 22k_invalid_schema', function (done) {
        request(server)
          .post('/objects/gzipped/validate')
          .attach('file', './test/api/gzip_data/NE_22k_invalid_schema.json.gz')
          .expect('Content-Type', /json/)
          .expect(422)
          .end(function (err, res) {
            should.not.exist(err);
            done();
          });
      });

      it('should return { isValid : true } with 111k', function (done) {
        request(server)
          .post('/objects/gzipped/validate')
          .attach('file', './test/api/gzip_data/NE_111k.json.gz')
          .expect('Content-Type', /json/)
          .expect(200)
          .end(function (err, res) {
            should.not.exist(err);
            res.body.isValid.should.eql(true);
            done();
          });
      });

      /*it('should return { isValid : true } with 111k_complex_schema', function (done) {
        this.timeout(50000);
        request(server)
          .post('/objects/gzipped/validate')
          .attach('file', './test/api/gzip_data/NE_111k_complex_schema.json.gz')
          .expect('Content-Type', /json/)
          .expect(200)
          .end(function (err, res) {
            should.not.exist(err);
            res.body.isValid.should.eql(false);
            done();
          });
      });*/
    });

  });

});
<commit_msg>Fixed unit test with new path<commit_after>var should = require('should');
var request = require('supertest');
var server = require('../../../app');

var mockSchemas = require('../mock_data/mock_schemas');
var targetSchemas = require('../mock_data/target_schemas');
var mockObjects = require('../mock_data/mock_objects');

//BATCH ARRAY VALIDATION:
// 1- We can't send large object with supertest at this point (POST objects/validate is for small arrays)
//    Even if we could swagger will freeze when validating such a large dataset, replace objects and schema by "something" to get threw this
//    Following CURL will fail but this is an example:
//    $ curl -X POST -H "Content-Type: application/json" --data '{"something":{"schema":{},"objects":"'$(cat NE_22k_example.json)'-"}}' http://10.30.90.174:9000/objects/validate
//
// 2- To send large number of object use the POST objects/gzipped/validate and attach to it a gzipped json file containing {schema: {} and objects: []}
//    Following curl was used at some point before sending multipart/form-data and a param named "file"
//    $ curl -v -s --trace-ascii http_tracery @_NE_22k_example.json.gz -H "Content-Type: application/json" -H "Content-Encoding: gzip" -X POST http://10.30.90.174:9000/objects/gzipped/validate
//
// 3- Method POST objects/gzipped/valdiate now attends multipart/form-data so we can retreive file inside the express api
//    Both following curls commands actually should still works
//    TRUE <= $ curl -F "file=@NE_111k.json.gz" http:10.30.90.174:9000/objects/gzipped/validate
//    FALSE <= $ curl -F "file=@NE_111k_with_errors.json.gz" http:10.30.90.174:9000/objects/gzipped/validate
//    But now supertest method attach() support attached files with multipart/form-data so curl are kinda useless

var objects22k = [{"_start": 123}, {"_start": 12223}];
var basic = {
  "required": [ "_start"]
};

describe('controllers', function () {

  describe('json_object', function () {

    describe('POST /object/validate', function () {

      it('should return an error 400 if body is missing', function (done) {

        request(server)
          .post('/psc-schema-validation-service/object/validate')
          .set('Accept', 'application/json')
          .expect('Content-Type', /json/)
          .expect(400)
          .end(function (err, res) {
            should.not.exist(err);
            //res.status.should.eql(400);
            done();
          });
      });

      it('should return an error 400 if schema is missing from body', function (done) {

        request(server)
          .post('/psc-schema-validation-service/object/validate')
          .send({object: {}})
          .set('Accept', 'application/json')
          .expect('Content-Type', /json/)
          .expect(400)
          .end(function (err, res) {
            should.not.exist(err);
            done();
          });
      });

      it('should return an error 422 if schema is an invalid json schema', function (done) {

        request(server)
          .post('/psc-schema-validation-service/object/validate')
          .send({ schema: { "required": "yolo123"}, object: { yolo : 123}})
          .set('Accept', 'application/json')
          .expect('Content-Type', /json/)
          .expect(422)
          .end(function (err, res) {
            should.not.exist(err);
            should.exist(res.body.code);
            should.exist(res.body.message);
            done();
          });
      });

      it('should accept master schema and a valid faceDetect object', function (done) {

        request(server)
          .post('/psc-schema-validation-service/object/validate')
          .send({schema: targetSchemas.master, object: mockObjects.faceValid})
          .set('Accept', 'application/json')
          .expect('Content-Type', /json/)
          .expect(200)
          .end(function (err, res) {
            should.not.exist(err);
            res.body.should.eql({ isValid: true });
            done();
          });
      });

      it('should accept multimedia_document_content schema and a valid faceDetect object', function (done) {

        request(server)
          .post('/psc-schema-validation-service/object/validate')
          .send({schema: targetSchemas.multimedia_document_content, object: mockObjects.faceValid})
          .set('Accept', 'application/json')
          .expect('Content-Type', /json/)
          .expect(200)
          .end(function (err, res) {
            should.not.exist(err);
            res.body.should.eql({ isValid: true });
            done();
          });
      });

      it('should return { isValid: false, errors: [] } with multimedia_document_content schema and invalid faceDetect object', function (done) {

        request(server)
          .post('/psc-schema-validation-service/object/validate')
          .send({schema: targetSchemas.multimedia_document_content, object: { yolo : 123}})
          .set('Accept', 'application/json')
          .expect('Content-Type', /json/)
          .expect(200)
          .end(function (err, res) {
            //TODO fix
            should.not.exist(err);
            should.exist(res.body.isValid);
            should.exist(res.body.errors);
            res.body.isValid.should.eql(false);
            done();
          });
      });

    });

    describe('POST /objects/validate', function () {

      it('should return { isValid : true } with objects22k', function (done) {
        request(server)
          .post('/psc-schema-validation-service/objects/validate')
          .send({schema: basic, objects: objects22k})
          .set('Accept', 'application/json')
          .expect('Content-Type', /json/)
          .expect(200)
          .end(function (err, res) {
            should.not.exist(err);
            done();
          });
      });
    });

    describe('POST /objects/gzipped/validate', function () {

      it('should return { isValid : true } with 22k', function (done) {
        request(server)
          .post('/psc-schema-validation-service/objects/gzipped/validate')
          .attach('file', './test/api/gzip_data/NE_22k.json.gz')
          .expect('Content-Type', /json/)
          .expect(200)
          .end(function (err, res) {
            should.not.exist(err);
            res.body.isValid.should.eql(true);
            done();
          });
      });

      it('should return { isValid : false } with 22k_with_errors', function (done) {
        request(server)
          .post('/psc-schema-validation-service/objects/gzipped/validate')
          .attach('file', './test/api/gzip_data/NE_22k_with_error.json.gz')
          .expect('Content-Type', /json/)
          .expect(200)
          .end(function (err, res) {
            should.not.exist(err);
            res.body.isValid.should.eql(false);
            done();
          });
      });

      it('should return 400 with 22k_missing_schema', function (done) {
        request(server)
          .post('/psc-schema-validation-service/objects/gzipped/validate')
          .attach('file', './test/api/gzip_data/NE_22k_missing_schema.json.gz')
          .expect('Content-Type', /json/)
          .expect(400)
          .end(function (err, res) {
            should.not.exist(err);
            done();
          });
      });

      it('should return 422 with 22k_invalid_schema', function (done) {
        request(server)
          .post('/psc-schema-validation-service/objects/gzipped/validate')
          .attach('file', './test/api/gzip_data/NE_22k_invalid_schema.json.gz')
          .expect('Content-Type', /json/)
          .expect(422)
          .end(function (err, res) {
            should.not.exist(err);
            done();
          });
      });

      it('should return { isValid : true } with 111k', function (done) {
        request(server)
          .post('/psc-schema-validation-service/objects/gzipped/validate')
          .attach('file', './test/api/gzip_data/NE_111k.json.gz')
          .expect('Content-Type', /json/)
          .expect(200)
          .end(function (err, res) {
            should.not.exist(err);
            res.body.isValid.should.eql(true);
            done();
          });
      });

      /*it('should return { isValid : true } with 111k_complex_schema', function (done) {
        this.timeout(50000);
        request(server)
          .post('/psc-schema-validation-service/objects/gzipped/validate')
          .attach('file', './test/api/gzip_data/NE_111k_complex_schema.json.gz')
          .expect('Content-Type', /json/)
          .expect(200)
          .end(function (err, res) {
            should.not.exist(err);
            res.body.isValid.should.eql(false);
            done();
          });
      });*/
    });

  });

});
<|endoftext|>