<commit_before>/**
* @license Apache-2.0
*
* Copyright (c) 2020 The Stdlib Authors.
*
* Licensed 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.
*/

'use strict';

/*
* When adding modules to the namespace, ensure that they are added in alphabetical order according to module name.
*/

// MODULES //

var setReadOnly = require( '@stdlib/utils/define-read-only-property' );

// MAIN //

/**
* Top-level namespace.
*
* @namespace ns
*/
var ns = {};

/**
* @name binary
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/binary}
*/
setReadOnly( ns, 'binary', require( '@stdlib/strided/base/binary' ) );

/**
* @name binaryAddonDispatch
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/binary-addon-dispatch}
*/
setReadOnly( ns, 'binaryAddonDispatch', require( '@stdlib/strided/base/binary-addon-dispatch' ) );

/**
* @name dmap
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/dmap}
*/
setReadOnly( ns, 'dmap', require( '@stdlib/strided/base/dmap' ) );

/**
* @name dmap2
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/dmap2}
*/
setReadOnly( ns, 'dmap2', require( '@stdlib/strided/base/dmap2' ) );

/**
* @name dmskmap
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/dmskmap}
*/
setReadOnly( ns, 'dmskmap', require( '@stdlib/strided/base/dmskmap' ) );

/**
* @name dmskmap2
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/dmskmap2}
*/
setReadOnly( ns, 'dmskmap2', require( '@stdlib/strided/base/dmskmap2' ) );

/**
* @name dtypeEnum2Str
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/dtype-enum2str}
*/
setReadOnly( ns, 'dtypeEnum2Str', require( '@stdlib/strided/base/dtype-enum2str' ) );

/**
* @name dtypeResolveEnum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/dtype-resolve-enum}
*/
setReadOnly( ns, 'dtypeResolveEnum', require( '@stdlib/strided/base/dtype-resolve-enum' ) );

/**
* @name dtypeStr2Enum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/dtype-str2enum}
*/
setReadOnly( ns, 'dtypeStr2Enum', require( '@stdlib/strided/base/dtype-str2enum' ) );

/**
* @name mapBy
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/map-by}
*/
setReadOnly( ns, 'mapBy', require( '@stdlib/strided/base/map-by' ) );

/**
* @name mapBy2
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/map-by2}
*/
setReadOnly( ns, 'mapBy2', require( '@stdlib/strided/base/map-by2' ) );

/**
* @name maxViewBufferIndex
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/max-view-buffer-index}
*/
setReadOnly( ns, 'maxViewBufferIndex', require( '@stdlib/strided/base/max-view-buffer-index' ) );

/**
* @name metaDataProps
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/meta-data-props}
*/
setReadOnly( ns, 'metaDataProps', require( '@stdlib/strided/base/meta-data-props' ) );

/**
* @name minViewBufferIndex
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/min-view-buffer-index}
*/
setReadOnly( ns, 'minViewBufferIndex', require( '@stdlib/strided/base/min-view-buffer-index' ) );

/**
* @name mskunary
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/mskunary}
*/
setReadOnly( ns, 'mskunary', require( '@stdlib/strided/base/mskunary' ) );

/**
* @name nullary
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/nullary}
*/
setReadOnly( ns, 'nullary', require( '@stdlib/strided/base/nullary' ) );

/**
* @name offsetView
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/offset-view}
*/
setReadOnly( ns, 'offsetView', require( '@stdlib/strided/base/offset-view' ) );

/**
* @name quaternary
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/quaternary}
*/
setReadOnly( ns, 'quaternary', require( '@stdlib/strided/base/quaternary' ) );

/**
* @name quinary
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/quinary}
*/
setReadOnly( ns, 'quinary', require( '@stdlib/strided/base/quinary' ) );

/**
* @name reinterpretComplex64
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/reinterpret-complex64}
*/
setReadOnly( ns, 'reinterpretComplex64', require( '@stdlib/strided/base/reinterpret-complex64' ) );

/**
* @name reinterpretComplex128
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/reinterpret-complex128}
*/
setReadOnly( ns, 'reinterpretComplex128', require( '@stdlib/strided/base/reinterpret-complex128' ) );

/**
* @name smap
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/smap}
*/
setReadOnly( ns, 'smap', require( '@stdlib/strided/base/smap' ) );

/**
* @name smap2
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/smap2}
*/
setReadOnly( ns, 'smap2', require( '@stdlib/strided/base/smap2' ) );

/**
* @name smskmap
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/smskmap}
*/
setReadOnly( ns, 'smskmap', require( '@stdlib/strided/base/smskmap' ) );

/**
* @name smskmap2
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/smskmap2}
*/
setReadOnly( ns, 'smskmap2', require( '@stdlib/strided/base/smskmap2' ) );

/**
* @name ternary
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/ternary}
*/
setReadOnly( ns, 'ternary', require( '@stdlib/strided/base/ternary' ) );

/**
* @name unary
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/unary}
*/
setReadOnly( ns, 'unary', require( '@stdlib/strided/base/unary' ) );

/**
* @name unaryAddonDispatch
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/unary-addon-dispatch}
*/
setReadOnly( ns, 'unaryAddonDispatch', require( '@stdlib/strided/base/unary-addon-dispatch' ) );

// EXPORTS //

module.exports = ns;
<commit_msg>Update namespace<commit_after>/**
* @license Apache-2.0
*
* Copyright (c) 2020 The Stdlib Authors.
*
* Licensed 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.
*/

'use strict';

/*
* When adding modules to the namespace, ensure that they are added in alphabetical order according to module name.
*/

// MODULES //

var setReadOnly = require( '@stdlib/utils/define-read-only-property' );

// MAIN //

/**
* Top-level namespace.
*
* @namespace ns
*/
var ns = {};

/**
* @name binary
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/binary}
*/
setReadOnly( ns, 'binary', require( '@stdlib/strided/base/binary' ) );

/**
* @name binaryAddonDispatch
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/binary-addon-dispatch}
*/
setReadOnly( ns, 'binaryAddonDispatch', require( '@stdlib/strided/base/binary-addon-dispatch' ) );

/**
* @name cmap
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/cmap}
*/
setReadOnly( ns, 'cmap', require( '@stdlib/strided/base/cmap' ) );

/**
* @name dmap
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/dmap}
*/
setReadOnly( ns, 'dmap', require( '@stdlib/strided/base/dmap' ) );

/**
* @name dmap2
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/dmap2}
*/
setReadOnly( ns, 'dmap2', require( '@stdlib/strided/base/dmap2' ) );

/**
* @name dmskmap
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/dmskmap}
*/
setReadOnly( ns, 'dmskmap', require( '@stdlib/strided/base/dmskmap' ) );

/**
* @name dmskmap2
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/dmskmap2}
*/
setReadOnly( ns, 'dmskmap2', require( '@stdlib/strided/base/dmskmap2' ) );

/**
* @name dtypeEnum2Str
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/dtype-enum2str}
*/
setReadOnly( ns, 'dtypeEnum2Str', require( '@stdlib/strided/base/dtype-enum2str' ) );

/**
* @name dtypeResolveEnum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/dtype-resolve-enum}
*/
setReadOnly( ns, 'dtypeResolveEnum', require( '@stdlib/strided/base/dtype-resolve-enum' ) );

/**
* @name dtypeStr2Enum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/dtype-str2enum}
*/
setReadOnly( ns, 'dtypeStr2Enum', require( '@stdlib/strided/base/dtype-str2enum' ) );

/**
* @name mapBy
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/map-by}
*/
setReadOnly( ns, 'mapBy', require( '@stdlib/strided/base/map-by' ) );

/**
* @name mapBy2
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/map-by2}
*/
setReadOnly( ns, 'mapBy2', require( '@stdlib/strided/base/map-by2' ) );

/**
* @name maxViewBufferIndex
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/max-view-buffer-index}
*/
setReadOnly( ns, 'maxViewBufferIndex', require( '@stdlib/strided/base/max-view-buffer-index' ) );

/**
* @name metaDataProps
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/meta-data-props}
*/
setReadOnly( ns, 'metaDataProps', require( '@stdlib/strided/base/meta-data-props' ) );

/**
* @name minViewBufferIndex
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/min-view-buffer-index}
*/
setReadOnly( ns, 'minViewBufferIndex', require( '@stdlib/strided/base/min-view-buffer-index' ) );

/**
* @name mskunary
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/mskunary}
*/
setReadOnly( ns, 'mskunary', require( '@stdlib/strided/base/mskunary' ) );

/**
* @name nullary
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/nullary}
*/
setReadOnly( ns, 'nullary', require( '@stdlib/strided/base/nullary' ) );

/**
* @name offsetView
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/offset-view}
*/
setReadOnly( ns, 'offsetView', require( '@stdlib/strided/base/offset-view' ) );

/**
* @name quaternary
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/quaternary}
*/
setReadOnly( ns, 'quaternary', require( '@stdlib/strided/base/quaternary' ) );

/**
* @name quinary
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/quinary}
*/
setReadOnly( ns, 'quinary', require( '@stdlib/strided/base/quinary' ) );

/**
* @name reinterpretComplex64
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/reinterpret-complex64}
*/
setReadOnly( ns, 'reinterpretComplex64', require( '@stdlib/strided/base/reinterpret-complex64' ) );

/**
* @name reinterpretComplex128
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/reinterpret-complex128}
*/
setReadOnly( ns, 'reinterpretComplex128', require( '@stdlib/strided/base/reinterpret-complex128' ) );

/**
* @name smap
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/smap}
*/
setReadOnly( ns, 'smap', require( '@stdlib/strided/base/smap' ) );

/**
* @name smap2
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/smap2}
*/
setReadOnly( ns, 'smap2', require( '@stdlib/strided/base/smap2' ) );

/**
* @name smskmap
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/smskmap}
*/
setReadOnly( ns, 'smskmap', require( '@stdlib/strided/base/smskmap' ) );

/**
* @name smskmap2
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/smskmap2}
*/
setReadOnly( ns, 'smskmap2', require( '@stdlib/strided/base/smskmap2' ) );

/**
* @name ternary
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/ternary}
*/
setReadOnly( ns, 'ternary', require( '@stdlib/strided/base/ternary' ) );

/**
* @name unary
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/unary}
*/
setReadOnly( ns, 'unary', require( '@stdlib/strided/base/unary' ) );

/**
* @name unaryAddonDispatch
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/strided/base/unary-addon-dispatch}
*/
setReadOnly( ns, 'unaryAddonDispatch', require( '@stdlib/strided/base/unary-addon-dispatch' ) );

// EXPORTS //

module.exports = ns;
<|endoftext|>


<commit_before>import Automaton, { State, Transition } from './automaton'
import { UnknownCharError, UnknownStateError,
	     DeterminismError, NoInitialStateError,
		 DuplicateStateError, DuplicateTransitionError } from '../errors'

export default class NFA extends Automaton {
	addTransition (from, a, to) {
		const fs = this.getState(from)
		const ts = this.getState(to)

		if (!fs)
			throw new UnknownStateError(from)
		if (!ts)
			throw new UnknownStateError(to)
		if (!this.charInAlphabet(a))
			throw new UnknownCharError(a)
        if (fs.transitions.filter(t => t.a === a && t.to === to)[0])
            throw new DuplicateTransitionError({ from, a, to })

		this.states = this.states.map(e => {
			if (e.name === from)
				e.transitions = [ ...e.transitions, new Transition(from, a, to) ]
			return e
		})
	}
	removeTransition (from, a, to) {
		this.states = this.states.map(e => {
			if (e.name === from)
				e.transitions = e.transitions.filter(t => !(t.a === a && t.to === to))
			return e
		})
	}
	editTransition (_from, a, _to, { from, to }) {
		this.states = this.states.map(e => {
			if (e.name === _from)
				if (e.name !== from)
					e.transitions = e.transitions.filter(t => !(t.a === a && t.to === _to))
				else
					e.transitions = e.transitions.map(t => {
						if (t.a === a && t.to === _to)
							t.to = to
						return t
					})
			else if (e.name === from)
				this.addTransition(e.name, a, to)
			return e
		})
	}
	run (w) {
		if (!this.initialState)
			throw new NoInitialStateError()

		let currStates = [ this.getState(this.initialState) ]

		for (let a of w) {
			const transitions = currStates.reduce((accum, curr) => {
                return [ ...accum, ...curr.transitions.filter(t => t.a === a) ]
            }, [])

			if (transitions.length === 0)
				return false

			currStates = transitions.map(t => this.getState(t.to))
		}

		return currStates.reduce((accum, curr) => accum ? true :
            this.stateIsFinal(curr.name), false)
	}
}<commit_msg>Edit transition bug fix<commit_after>import Automaton, { State, Transition } from './automaton'
import { UnknownCharError, UnknownStateError,
	     DeterminismError, NoInitialStateError,
		 DuplicateStateError, DuplicateTransitionError } from '../errors'

export default class NFA extends Automaton {
	addTransition (from, a, to) {
		const fs = this.getState(from)
		const ts = this.getState(to)

		if (!fs)
			throw new UnknownStateError(from)
		if (!ts)
			throw new UnknownStateError(to)
		if (!this.charInAlphabet(a))
			throw new UnknownCharError(a)
        if (this.stateHasTransition(from, a, to))
            throw new DuplicateTransitionError({ from, a, to })

		this.states = this.states.map(e => {
			if (e.name === from)
				e.transitions = [ ...e.transitions, new Transition(from, a, to) ]
			return e
		})
	}
	removeTransition (from, a, to) {
		this.states = this.states.map(e => {
			if (e.name === from)
				e.transitions = e.transitions.filter(t => !(t.a === a && t.to === to))
			return e
		})
	}
	editTransition (_from, a, _to, { from, to }) {
		this.states = this.states.map(e => {
			if (e.name === _from)
				if (e.name !== from)
					e.transitions = e.transitions.filter(t => !(t.a === a && t.to === _to))
				else
					e.transitions = e.transitions.map(t => {
						if (t.a === a && t.to === _to) {
							if (this.stateHasTransition(from, a, to))
								throw new DuplicateTransitionError({ from, a, to })
							t.to = to
						}
						return t
					})
			else if (e.name === from)
				this.addTransition(e.name, a, to)
			return e
		})
	}
	stateHasTransition(from, a, to) {
		return this.getState(from).transitions.filter(t => t.a === a && t.to === to)[0]
	}
	run (w) {
		if (!this.initialState)
			throw new NoInitialStateError()

		let currStates = [ this.getState(this.initialState) ]

		for (let a of w) {
			const transitions = currStates.reduce((accum, curr) => {
                return [ ...accum, ...curr.transitions.filter(t => t.a === a) ]
            }, [])

			if (transitions.length === 0)
				return false

			currStates = transitions.map(t => this.getState(t.to))
		}

		return currStates.reduce((accum, curr) => accum ? true :
            this.stateIsFinal(curr.name), false)
	}
}<|endoftext|>


<commit_before>var airy;

airy = {
    socket: null,
    history: null,
    initialized: false,

    defaults: {
        'method': 'get',
        'change_state': false,
        'callback': null
    },

    init: function() {
        if (!airy.initialized) {
            airy.history = window.History;
            airy.configure.history();
            airy.configure.links();
            airy.configure.forms();
            airy.initialized = true;
        }
        airy.request('get', airy.history.getState().hash);
    },

    call: function(params) {
        var options = $.extend({}, airy.defaults, params);
        var url = airy.util.fix_url(airy.history.getState().hash);
        options.url = airy.util.fix_url(options.url);
        if (url == options.url || !options.change_state) {
            var params = [options.method, url];
            if (options.data)
                $.merge(params, [options.data]);
            if (typeof(options.callback) == "function")
                $.merge(params, [options.callback]);
            airy.socket.emit.apply(airy.socket, params);
        } else {
            airy.history.pushState(options, null, url);
        }
    },

    request: function(method, url, data, nostate) {
        // deprecated functionality
        if (airy.history.getState().hash == url || nostate) {
            airy.call({method: method, url: url, data: data, change_state: !nostate});
        } else {
            airy.history.pushState({method: method, data: data}, null, url);
        }
    },

    set_cookie: function(name, value, options) {
        $.cookie(name, value, options)
    },

    ui: {
        insert: function(target, data) {
            $(target).html(data);
        },
        append: function(target, data) {
            $(target).append(data);
        },
        prepend: function(target, data) {
            $(target).prepend(data);
        },
        remove: function(target) {
            $(target).remove();
        }
    },

    configure: {
        history: function() {
            airy.history.Adapter.bind(window, 'statechange', function() {
                var State = airy.history.getState();
                airy.call({method: State.data.method, url: State.hash, data: State.data.data, change_state: State.data.change_state});
            });
        },
        links: function() {
            $('a').live('click', function() {
                if (airy.options.is_airy_link($(this))) {
                    airy.request('get', $(this).attr('href'), null, airy.options.no_state_change(this));
                    return false;
                }
            });
        },
        forms: function() {
            $('form').live('submit', function() {
                if (airy.options.is_airy_form($(this))) {
                    var form_url = airy.history.getState().hash;
                    if ($(this).attr('action').length > 0) {
                        form_url = $(this).attr('action');
                    }
                    if ($(this).attr('method').toLowerCase() == 'get') {
                        airy.request('get', form_url+'?'+$(this).serialize(), null, airy.options.no_state_change($(this)));
                    } else if ($(this).attr('method').toLowerCase() == 'post') {
                        $(this).serializeForm(function(data, form) {
                            airy.request('post', form_url, data, airy.options.no_state_change(form));
                        }, $(this));
                    }
                    return false;
                }
            });
        }
    },

    options: {
        is_airy_link: function(link) {
            if (link.attr('href') && !link.attr('target') && !link.hasClass('no-airy')) {
                return true;
            }
            return false;
        },

        is_airy_form: function(form) {
            if (!form.hasClass('no-airy')) {
                return true;
            }
            return false;
        },

        no_state_change: function(item) {
            // when true airy will attempt to change the URL
            return $(item).hasClass('no-airy-state');
        }
    },

    util: {
        fix_url: function(url) {
            if (url[0] == ".") {
                url = url.substring(1);
            }
            if (url[0] != "/") {
                url = "/"+url;
            }
            return url;
        }
    }
}

$(function() {

    airy.socket = new io.connect("http://" + window.location.host, {'connect timeout': 1000});

    airy.socket.on('connect', function() {
        airy.init();
    });

    airy.socket.on('execute', function(data) {
        eval(data);
    });

});

<commit_msg>IE7 bugfix<commit_after>var airy;

airy = {
    socket: null,
    history: null,
    initialized: false,

    defaults: {
        'method': 'get',
        'change_state': false,
        'callback': null
    },

    init: function() {
        if (!airy.initialized) {
            airy.history = window.History;
            airy.configure.history();
            airy.configure.links();
            airy.configure.forms();
            airy.initialized = true;
        }
        airy.request('get', airy.history.getState().hash);
    },

    call: function(params) {
        var options = $.extend({}, airy.defaults, params);
        var url = airy.util.fix_url(airy.history.getState().hash);
        options.url = airy.util.fix_url(options.url);
        if (url == options.url || !options.change_state) {
            var params = [options.method, url];
            if (options.data)
                $.merge(params, [options.data]);
            if (typeof(options.callback) == "function")
                $.merge(params, [options.callback]);
            airy.socket.emit.apply(airy.socket, params);
        } else {
            airy.history.pushState(options, null, url);
        }
    },

    request: function(method, url, data, nostate) {
        // deprecated functionality
        if (airy.history.getState().hash == url || nostate) {
            airy.call({method: method, url: url, data: data, change_state: !nostate});
        } else {
            airy.history.pushState({method: method, data: data}, null, url);
        }
    },

    set_cookie: function(name, value, options) {
        $.cookie(name, value, options)
    },

    ui: {
        insert: function(target, data) {
            $(target).html(data);
        },
        append: function(target, data) {
            $(target).append(data);
        },
        prepend: function(target, data) {
            $(target).prepend(data);
        },
        remove: function(target) {
            $(target).remove();
        }
    },

    configure: {
        history: function() {
            airy.history.Adapter.bind(window, 'statechange', function() {
                var State = airy.history.getState();
                airy.call({method: State.data.method, url: State.hash, data: State.data.data, change_state: State.data.change_state});
            });
        },
        links: function() {
            $('a').live('click', function() {
                if (airy.options.is_airy_link($(this))) {
                    airy.request('get', $(this).attr('href'), null, airy.options.no_state_change(this));
                    return false;
                }
            });
        },
        forms: function() {
            $('form').live('submit', function() {
                if (airy.options.is_airy_form($(this))) {
                    var form_url = airy.history.getState().hash;
                    if ($(this).attr('action').length > 0) {
                        form_url = $(this).attr('action');
                    }
                    if ($(this).attr('method').toLowerCase() == 'get') {
                        airy.request('get', form_url+'?'+$(this).serialize(), null, airy.options.no_state_change($(this)));
                    } else if ($(this).attr('method').toLowerCase() == 'post') {
                        $(this).serializeForm(function(data, form) {
                            airy.request('post', form_url, data, airy.options.no_state_change(form));
                        }, $(this));
                    }
                    return false;
                }
            });
        }
    },

    options: {
        is_airy_link: function(link) {
            if (link.attr('href') && !link.attr('target') && !link.hasClass('no-airy')) {
                return true;
            }
            return false;
        },

        is_airy_form: function(form) {
            if (!form.hasClass('no-airy')) {
                return true;
            }
            return false;
        },

        no_state_change: function(item) {
            // when true airy will attempt to change the URL
            return $(item).hasClass('no-airy-state');
        }
    },

    util: {
        fix_url: function(url) {
            if (url.indexOf('.') == 0) {
                url = url.substring(1);
            }
            if (url.indexOf('/') != 0) {
                url = "/"+url;
            }
            return url;
        }
    }
}

$(function() {

    airy.socket = new io.connect("http://" + window.location.host, {'connect timeout': 1000});

    airy.socket.on('connect', function() {
        airy.init();
    });

    airy.socket.on('execute', function(data) {
        eval(data);
    });

});

<|endoftext|>


<commit_before>describe('Resource /apps', function () {

  /**
   * npm dependencies
   */

  var mongoose = require('mongoose');

  /**
   * Models
   */

  var App = require('../../../api/models/App');
  var Segment = require('../../../api/models/Segment');

  var randomId = mongoose.Types.ObjectId;

  before(function (done) {
    setupTestDb(done);
  });

  describe('POST /apps', function () {

    var createdApp;

    before(function (done) {
      logoutUser(done);
    });

    it('returns error if not logged in',

      function (done) {

        var newApp = {
          name: 'My New App'
        };

        request
          .post('/apps')
          .send(newApp)
          .expect('Content-Type', /json/)
          .expect(401)
          .expect({
            status: 401,
            error: 'Unauthorized'
          })
          .end(done);

      });

    it('logging in user',

      function (done) {
        loginUser(done);
      });

    it('should return error if name is not present', function (done) {

      var newApp = {};

      request
        .post('/apps')
        .set('cookie', loginCookie)
        .send(newApp)
        .expect('Content-Type', /json/)
        .expect(400)
        .expect({
          "error": [
            "App name is required"
          ],
          "status": 400
        })
        .end(done);

    });

    it('should create new app',

      function (done) {

        var newApp = {
          name: 'new-app'
        };

        request
          .post('/apps')
          .set('cookie', loginCookie)
          .send(newApp)
          .expect('Content-Type', /json/)
          .expect(201)
          .expect(function (res) {
            createdApp = res.body;
            if (res.body.name !== newApp.name) {
              return 'Saved app\'s name does not match';
            }
          })
          .end(done);

      });

    it('should add the app creator to the team and make him admin',
      function () {

        var loginUserAccid = saved.accounts.first._id;

        expect(createdApp.team)
          .to.have.length(1);

        expect(createdApp.team[0].admin)
          .to.eql(true);

        expect(createdApp.team[0].accid.toString())
          .to.eql(loginUserAccid.toString());
      });

  });

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

    before(function (done) {
      logoutUser(done);
    });

    it('returns error if not logged in',

      function (done) {

        var newApp = {};

        request
          .get('/apps')
          .send(newApp)
          .expect('Content-Type', /json/)
          .expect(401)
          .expect({
            status: 401,
            error: 'Unauthorized'
          })
          .end(done);

      });

    it('logging in user',

      function (done) {
        loginUser(done);
      });

    it('fetches all apps belonging to account',

      function (done) {

        request
          .get('/apps')
          .set('cookie', loginCookie)
          .expect('Content-Type', /json/)
          .expect(200)
          .end(function (err, res) {

            if (err) return done(err);

            expect(res.body)
              .to.be.an("array");

            expect(res.body[0].team)
              .to.be.an("array");

            expect(res.body[0].team[0])
              .to.have.property("admin", true);

            expect(res.body[0].team[0].accid)
              .to.be.an("object");

            expect(res.body[0].team[0].accid)
              .to.have.property("_id");

            expect(res.body[0].team[0].accid)
              .to.have.property("name");

            expect(res.body[0].team[0].accid)
              .to.have.property("email");

            done();
          });

      });

  });

  describe('GET /apps/:aid', function () {

    before(function (done) {
      logoutUser(done);
    });

    it('returns error if not logged in',

      function (done) {

        request
          .get('/apps/' + randomId())
          .expect('Content-Type', /json/)
          .expect(401)
          .end(done);
      });

    it('logging in user',

      function (done) {
        loginUser(done);
      });

    it('fetches app with given id',

      function (done) {

        request
          .get('/apps/' + saved.apps.first._id)
          .set('cookie', loginCookie)
          .expect('Content-Type', /json/)
          .expect(function (res) {

            expect(res.body.team[0])
              .to.have.property("accid")
              .that.is.an("object")
              .and.has.keys(['_id', 'name', 'email'])
              .and.has.property('_id', saved.accounts.first._id.toString());

          })
          .expect(200)
          .end(done);

      });

    it('returns error if no app with id is present',

      function (done) {

        request
          .get('/apps/' + randomId())
          .set('cookie', loginCookie)
          .expect('Content-Type', /json/)
          .expect(404)
          .expect({
            "error": "Not Found",
            "status": 404
          })
          .end(done);

      });

    it('returns error if user doesnt have access to app',

      function (done) {

        request
          .get('/apps/' + saved.apps.second._id)
          .set('cookie', loginCookie)
          .expect('Content-Type', /json/)
          .expect(403)
          .end(done);

      });
  });

  describe('PUT /apps/:aid/name', function () {

    before(function (done) {
      logoutUser(done);
    });

    it('returns error if not logged in',

      function (done) {

        var newName = 'Heres my new name';

        request
          .put('/apps/' + saved.apps.first._id + '/name')
          .send({
            name: newName
          })
          .expect('Content-Type', /json/)
          .expect(401)
          .end(done);

      });

    it('logging in user', function (done) {
      loginUser(done);
    });

    it('updates app name',

      function (done) {

        var newName = 'New App Name';

        request
          .put('/apps/' + saved.apps.first._id + '/name')
          .send({
            name: newName
          })
          .set('cookie', loginCookie)
          .expect('Content-Type', /json/)
          .expect(200)
          .expect(function (res) {
            if (res.body.name !== newName) {
              return 'Name was not updated';
            }
          })
          .end(done);

      });

  });

  describe('PUT /apps/:aid/show-message-box', function () {

    before(function (done) {
      logoutUser(done);
    });

    it('should return error if not logged in',
      function (done) {

        var status = false;

        request
          .put('/apps/' + saved.apps.first._id + '/show-message-box')
          .send({
            status: status
          })
          .expect('Content-Type', /json/)
          .expect(401)
          .end(done);

      });

    it('logging in user', function (done) {
      loginUser(done);
    });

    it('should return error if status is not boolean',
      function (done) {

        var status = 'false';

        request
          .put('/apps/' + saved.apps.first._id + '/show-message-box')
          .send({
            status: status
          })
          .set('cookie', loginCookie)
          .expect('Content-Type', /json/)
          .expect(400)
          .expect({
            "status": 400,
            "error": "Message box status should be either true or false"
          })
          .end(done);

      });

    it('should update app showMessageBox status',

      function (done) {

        expect(saved.apps.first.showMessageBox)
          .to.be.true;

        var status = false;

        request
          .put('/apps/' + saved.apps.first._id + '/show-message-box')
          .send({
            status: status
          })
          .set('cookie', loginCookie)
          .expect('Content-Type', /json/)
          .expect(200)
          .expect(function (res) {

            var app = res.body;

            expect(app.showMessageBox)
              .to.be.false;

          })
          .end(done);

      });

  });

  describe('POST /apps/:aid/send-code-to-developer', function () {

    var url;
    var sendToEmail = 'prattbhatt@gmail.com';

    before(function (done) {
      logoutUser(done);
      url = '/apps/' + saved.apps.first._id + '/send-code-to-developer';
    });

    it('returns error if not logged in',

      function (done) {

        request
          .post(url)
          .send({
            email: sendToEmail
          })
          .expect('Content-Type', /json/)
          .expect(401)
          .end(done);

      });

    it('logging in user', function (done) {
      loginUser(done);
    });

    it('should send the installation code to developer',

      function (done) {

        request
          .post(url)
          .send({
            email: sendToEmail
          })
          .set('cookie', loginCookie)
          .expect('Content-Type', /json/)
          .expect(200)
          .expect(function (res) {

            expect(res.body.message)
              .to.eql('Mail sent');

          })
          .end(done);

      });

  });

  describe('PUT /apps/:aid/color', function () {

    before(function (done) {
      logoutUser(done);
    });

    it('returns error if not logged in',

      function (done) {

        var newColor = '#FEFEFE';

        request
          .put('/apps/' + saved.apps.first._id + '/color')
          .send({
            color: newColor
          })
          .expect('Content-Type', /json/)
          .expect(401)
          .end(done);

      });

    it('logging in user', function (done) {
      loginUser(done);
    });

    it('should return error is invalid color code',

      function (done) {

        var newColor = '#FEFE';

        request
          .put('/apps/' + saved.apps.first._id + '/color')
          .send({
            color: newColor
          })
          .set('cookie', loginCookie)
          .expect('Content-Type', /json/)
          .expect(400)
          .expect({
            "error": "Provide valid color code",
            "status": 400
          })
          .end(done);

      });

    it('updates app name',

      function (done) {

        var newColor = '#FEFEFE';

        request
          .put('/apps/' + saved.apps.first._id + '/color')
          .send({
            color: newColor
          })
          .set('cookie', loginCookie)
          .expect('Content-Type', /json/)
          .expect(200)
          .expect(function (res) {
            expect(res.body.color)
              .to.eql(newColor);
          })
          .end(done);

      });

  });

  describe('PUT /apps/:aid/activate', function () {

    var url;
    var aid;

    before(function (done) {
      logoutUser(done);
      aid = saved.apps.first._id;
      url = '/apps/' + aid + '/activate';
    });

    it('should return error if not logged in', function (done) {

      request
        .put(url)
        .expect('Content-Type', /json/)
        .expect(401)
        .end(done);

    });

    it('logging in user', function (done) {
      loginUser(done);
    });

    it('should activate app',

      function (done) {

        async.series([

          function shouldBeInActive(cb) {
            App.findById(aid, function (err, app) {
              expect(err)
                .to.not.exist;

              expect(app.isActive)
                .to.be.false;

              cb();
            })
          },

          function activateApp(cb) {

            request
              .put(url)
              .set('cookie', loginCookie)
              .expect('Content-Type', /json/)
              .expect(200)
              .expect(function (res) {
                expect(res.body.isActive)
                  .to.be.true;
              })
              .end(cb);
          },

          function shouldBeActive(cb) {

            App.findById(aid, function (err, app) {
              expect(err)
                .to.not.exist;

              expect(app.isActive)
                .to.be.true;

              cb();
            })

          },

          function shouldHaveCreatedPredefinedSegments(cb) {
            Segment.find({
              aid: aid
            })
              .exec(function (err, segs) {

                expect(err)
                  .to.not.exist;

                var preSegs = _.filter(segs, {
                  predefined: true
                });

                // expecting three health filters
                expect(preSegs.length)
                  .to.eql(3);

                cb();
              })
          }

        ], done);

      });

    // WARNING: Run this test after the previous test where the app got activated
    it('should not create predefined segments if app already active',

      function (done) {

        async.series([

          function shouldBeActiveBefore(cb) {
            App.findById(aid, function (err, app) {
              expect(err)
                .to.not.exist;
              expect(app.isActive)
                .to.be.true;

              cb();
            })
          },

          function shouldHaveThreePredefinedSegments(cb) {
            Segment
              .find({
                aid: aid
              })
              .exec(function (err, segs) {

                expect(err)
                  .to.not.exist;

                var preSegs = _.filter(segs, {
                  predefined: true
                });

                // expecting three health filters
                expect(preSegs.length)
                  .to.eql(3);

                cb();
              });
          },

          function activateApp(cb) {

            request
              .put(url)
              .set('cookie', loginCookie)
              .expect('Content-Type', /json/)
              .expect(200)
              .expect(function (res) {
                expect(res.body.isActive)
                  .to.be.true;
              })
              .end(cb);
          },

          function shouldRemainActiveAfter(cb) {

            App.findById(aid, function (err, app) {
              expect(err)
                .to.not.exist;

              expect(app.isActive)
                .to.be.true;

              cb();
            })

          },

          function shouldStillHaveThreePredefinedSegments(cb) {
            Segment
              .find({
                aid: aid
              })
              .exec(function (err, segs) {

                expect(err)
                  .to.not.exist;

                var preSegs = _.filter(segs, {
                  predefined: true
                });

                // expecting three health filters
                expect(preSegs.length)
                  .to.eql(3);

                cb();
              });
          }

        ], done);

      });

  });

});
<commit_msg>api: update AppController tests to accept subdomain<commit_after>describe('Resource /apps', function () {

  /**
   * npm dependencies
   */

  var mongoose = require('mongoose');

  /**
   * Models
   */

  var App = require('../../../api/models/App');
  var Segment = require('../../../api/models/Segment');

  var randomId = mongoose.Types.ObjectId;

  before(function (done) {
    setupTestDb(done);
  });

  describe('POST /apps', function () {

    var createdApp;

    before(function (done) {
      logoutUser(done);
    });

    it('returns error if not logged in',

      function (done) {

        var newApp = {
          name: 'My New App',
          subdomain: 'my-New-app'
        };

        request
          .post('/apps')
          .send(newApp)
          .expect('Content-Type', /json/)
          .expect(401)
          .expect({
            status: 401,
            error: 'Unauthorized'
          })
          .end(done);

      });

    it('logging in user',

      function (done) {
        loginUser(done);
      });

    it('should return error if name/subdomain is not present', function (done) {

      var newApp = {};

      request
        .post('/apps')
        .set('cookie', loginCookie)
        .send(newApp)
        .expect('Content-Type', /json/)
        .expect(400)
        .expect({
          "error": [
            "App subdomain is required",
            "App name is required"
          ],
          "status": 400
        })
        .end(done);

    });

    it('should create new app',

      function (done) {

        var newApp = {
          name: 'new-app',
          subdomain: 'newapp'
        };

        request
          .post('/apps')
          .set('cookie', loginCookie)
          .send(newApp)
          .expect('Content-Type', /json/)
          .expect(201)
          .expect(function (res) {
            createdApp = res.body;
            if (res.body.name !== newApp.name) {
              return 'Saved app\'s name does not match';
            }
          })
          .end(done);

      });

    it('should add the app creator to the team and make him admin',
      function () {

        var loginUserAccid = saved.accounts.first._id;

        expect(createdApp.team)
          .to.have.length(1);

        expect(createdApp.team[0].admin)
          .to.eql(true);

        expect(createdApp.team[0].accid.toString())
          .to.eql(loginUserAccid.toString());
      });

  });

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

    before(function (done) {
      logoutUser(done);
    });

    it('returns error if not logged in',

      function (done) {

        var newApp = {};

        request
          .get('/apps')
          .send(newApp)
          .expect('Content-Type', /json/)
          .expect(401)
          .expect({
            status: 401,
            error: 'Unauthorized'
          })
          .end(done);

      });

    it('logging in user',

      function (done) {
        loginUser(done);
      });

    it('fetches all apps belonging to account',

      function (done) {

        request
          .get('/apps')
          .set('cookie', loginCookie)
          .expect('Content-Type', /json/)
          .expect(200)
          .end(function (err, res) {

            if (err) return done(err);

            expect(res.body)
              .to.be.an("array");

            expect(res.body[0].team)
              .to.be.an("array");

            expect(res.body[0].team[0])
              .to.have.property("admin", true);

            expect(res.body[0].team[0].accid)
              .to.be.an("object");

            expect(res.body[0].team[0].accid)
              .to.have.property("_id");

            expect(res.body[0].team[0].accid)
              .to.have.property("name");

            expect(res.body[0].team[0].accid)
              .to.have.property("email");

            done();
          });

      });

  });

  describe('GET /apps/:aid', function () {

    before(function (done) {
      logoutUser(done);
    });

    it('returns error if not logged in',

      function (done) {

        request
          .get('/apps/' + randomId())
          .expect('Content-Type', /json/)
          .expect(401)
          .end(done);
      });

    it('logging in user',

      function (done) {
        loginUser(done);
      });

    it('fetches app with given id',

      function (done) {

        request
          .get('/apps/' + saved.apps.first._id)
          .set('cookie', loginCookie)
          .expect('Content-Type', /json/)
          .expect(function (res) {

            expect(res.body.team[0])
              .to.have.property("accid")
              .that.is.an("object")
              .and.has.keys(['_id', 'name', 'email'])
              .and.has.property('_id', saved.accounts.first._id.toString());

          })
          .expect(200)
          .end(done);

      });

    it('returns error if no app with id is present',

      function (done) {

        request
          .get('/apps/' + randomId())
          .set('cookie', loginCookie)
          .expect('Content-Type', /json/)
          .expect(404)
          .expect({
            "error": "Not Found",
            "status": 404
          })
          .end(done);

      });

    it('returns error if user doesnt have access to app',

      function (done) {

        request
          .get('/apps/' + saved.apps.second._id)
          .set('cookie', loginCookie)
          .expect('Content-Type', /json/)
          .expect(403)
          .end(done);

      });
  });

  describe('PUT /apps/:aid/name', function () {

    before(function (done) {
      logoutUser(done);
    });

    it('returns error if not logged in',

      function (done) {

        var newName = 'Heres my new name';

        request
          .put('/apps/' + saved.apps.first._id + '/name')
          .send({
            name: newName
          })
          .expect('Content-Type', /json/)
          .expect(401)
          .end(done);

      });

    it('logging in user', function (done) {
      loginUser(done);
    });

    it('updates app name',

      function (done) {

        var newName = 'New App Name';

        request
          .put('/apps/' + saved.apps.first._id + '/name')
          .send({
            name: newName
          })
          .set('cookie', loginCookie)
          .expect('Content-Type', /json/)
          .expect(200)
          .expect(function (res) {
            if (res.body.name !== newName) {
              return 'Name was not updated';
            }
          })
          .end(done);

      });

  });

  describe('PUT /apps/:aid/show-message-box', function () {

    before(function (done) {
      logoutUser(done);
    });

    it('should return error if not logged in',
      function (done) {

        var status = false;

        request
          .put('/apps/' + saved.apps.first._id + '/show-message-box')
          .send({
            status: status
          })
          .expect('Content-Type', /json/)
          .expect(401)
          .end(done);

      });

    it('logging in user', function (done) {
      loginUser(done);
    });

    it('should return error if status is not boolean',
      function (done) {

        var status = 'false';

        request
          .put('/apps/' + saved.apps.first._id + '/show-message-box')
          .send({
            status: status
          })
          .set('cookie', loginCookie)
          .expect('Content-Type', /json/)
          .expect(400)
          .expect({
            "status": 400,
            "error": "Message box status should be either true or false"
          })
          .end(done);

      });

    it('should update app showMessageBox status',

      function (done) {

        expect(saved.apps.first.showMessageBox)
          .to.be.true;

        var status = false;

        request
          .put('/apps/' + saved.apps.first._id + '/show-message-box')
          .send({
            status: status
          })
          .set('cookie', loginCookie)
          .expect('Content-Type', /json/)
          .expect(200)
          .expect(function (res) {

            var app = res.body;

            expect(app.showMessageBox)
              .to.be.false;

          })
          .end(done);

      });

  });

  describe('POST /apps/:aid/send-code-to-developer', function () {

    var url;
    var sendToEmail = 'prattbhatt@gmail.com';

    before(function (done) {
      logoutUser(done);
      url = '/apps/' + saved.apps.first._id + '/send-code-to-developer';
    });

    it('returns error if not logged in',

      function (done) {

        request
          .post(url)
          .send({
            email: sendToEmail
          })
          .expect('Content-Type', /json/)
          .expect(401)
          .end(done);

      });

    it('logging in user', function (done) {
      loginUser(done);
    });

    it('should send the installation code to developer',

      function (done) {

        request
          .post(url)
          .send({
            email: sendToEmail
          })
          .set('cookie', loginCookie)
          .expect('Content-Type', /json/)
          .expect(200)
          .expect(function (res) {

            expect(res.body.message)
              .to.eql('Mail sent');

          })
          .end(done);

      });

  });

  describe('PUT /apps/:aid/color', function () {

    before(function (done) {
      logoutUser(done);
    });

    it('returns error if not logged in',

      function (done) {

        var newColor = '#FEFEFE';

        request
          .put('/apps/' + saved.apps.first._id + '/color')
          .send({
            color: newColor
          })
          .expect('Content-Type', /json/)
          .expect(401)
          .end(done);

      });

    it('logging in user', function (done) {
      loginUser(done);
    });

    it('should return error is invalid color code',

      function (done) {

        var newColor = '#FEFE';

        request
          .put('/apps/' + saved.apps.first._id + '/color')
          .send({
            color: newColor
          })
          .set('cookie', loginCookie)
          .expect('Content-Type', /json/)
          .expect(400)
          .expect({
            "error": "Provide valid color code",
            "status": 400
          })
          .end(done);

      });

    it('updates app name',

      function (done) {

        var newColor = '#FEFEFE';

        request
          .put('/apps/' + saved.apps.first._id + '/color')
          .send({
            color: newColor
          })
          .set('cookie', loginCookie)
          .expect('Content-Type', /json/)
          .expect(200)
          .expect(function (res) {
            expect(res.body.color)
              .to.eql(newColor);
          })
          .end(done);

      });

  });

  describe('PUT /apps/:aid/activate', function () {

    var url;
    var aid;

    before(function (done) {
      logoutUser(done);
      aid = saved.apps.first._id;
      url = '/apps/' + aid + '/activate';
    });

    it('should return error if not logged in', function (done) {

      request
        .put(url)
        .expect('Content-Type', /json/)
        .expect(401)
        .end(done);

    });

    it('logging in user', function (done) {
      loginUser(done);
    });

    it('should activate app',

      function (done) {

        async.series([

          function shouldBeInActive(cb) {
            App.findById(aid, function (err, app) {
              expect(err)
                .to.not.exist;

              expect(app.isActive)
                .to.be.false;

              cb();
            })
          },

          function activateApp(cb) {

            request
              .put(url)
              .set('cookie', loginCookie)
              .expect('Content-Type', /json/)
              .expect(200)
              .expect(function (res) {
                expect(res.body.isActive)
                  .to.be.true;
              })
              .end(cb);
          },

          function shouldBeActive(cb) {

            App.findById(aid, function (err, app) {
              expect(err)
                .to.not.exist;

              expect(app.isActive)
                .to.be.true;

              cb();
            })

          },

          function shouldHaveCreatedPredefinedSegments(cb) {
            Segment.find({
              aid: aid
            })
              .exec(function (err, segs) {

                expect(err)
                  .to.not.exist;

                var preSegs = _.filter(segs, {
                  predefined: true
                });

                // expecting three health filters
                expect(preSegs.length)
                  .to.eql(3);

                cb();
              })
          }

        ], done);

      });

    // WARNING: Run this test after the previous test where the app got activated
    it('should not create predefined segments if app already active',

      function (done) {

        async.series([

          function shouldBeActiveBefore(cb) {
            App.findById(aid, function (err, app) {
              expect(err)
                .to.not.exist;
              expect(app.isActive)
                .to.be.true;

              cb();
            })
          },

          function shouldHaveThreePredefinedSegments(cb) {
            Segment
              .find({
                aid: aid
              })
              .exec(function (err, segs) {

                expect(err)
                  .to.not.exist;

                var preSegs = _.filter(segs, {
                  predefined: true
                });

                // expecting three health filters
                expect(preSegs.length)
                  .to.eql(3);

                cb();
              });
          },

          function activateApp(cb) {

            request
              .put(url)
              .set('cookie', loginCookie)
              .expect('Content-Type', /json/)
              .expect(200)
              .expect(function (res) {
                expect(res.body.isActive)
                  .to.be.true;
              })
              .end(cb);
          },

          function shouldRemainActiveAfter(cb) {

            App.findById(aid, function (err, app) {
              expect(err)
                .to.not.exist;

              expect(app.isActive)
                .to.be.true;

              cb();
            })

          },

          function shouldStillHaveThreePredefinedSegments(cb) {
            Segment
              .find({
                aid: aid
              })
              .exec(function (err, segs) {

                expect(err)
                  .to.not.exist;

                var preSegs = _.filter(segs, {
                  predefined: true
                });

                // expecting three health filters
                expect(preSegs.length)
                  .to.eql(3);

                cb();
              });
          }

        ], done);

      });

  });

});
<|endoftext|>


<commit_before>"use strict";

function equals(a, b) {
  return !!(JSON.stringify(a) === JSON.stringify(b));
}

var speedTest = function(name, num, func) {
  var startTime = Date.now();
  for (var i = 0; i < num; i++) {
    func();
  }
  console.log(name + ((Date.now() - startTime))/num + ' ms');
}

Tinytest.add('Minify Maxify - test date', function(test) {
  var newTimeStamp = 1409300873188;
  var newDate = new Date(newTimeStamp);

  var obj = {
    updatedAt: newDate
  };

  var toString = MiniMax.stringify(obj);
  var fromString = MiniMax.parse(toString);

  console.log('toString', toString);
  console.log('fromString', fromString);

  test.instanceOf(obj.updatedAt, Date, 'Test Date is not handled correctly');
  test.instanceOf(fromString.updatedAt, Date, 'Date is not handled correctly');
});

Tinytest.add('Minify Maxify - raw test', function(test) {
  var foo = ['_id', false, true, null, -1, 0, 1, 1.1, -1.1, 'foo', new Date(), undefined, [1], [ 'foo', 'bar'], { foo: 'bar'}];
  var barMini = MiniMax.minify(foo);
  var bar = MiniMax.maxify(barMini);
  test.isTrue(equals(foo,  bar), 'Raw compare failed "' + JSON.stringify(barMini) + '" -> "' + JSON.stringify(bar) + '"');
});

Tinytest.add('Minify Maxify - raw test object', function(test) {
  var foo = { a: ['_id', false, true, null, -1, 0, 1, 1.1, -1.1, 'foo', new Date(), undefined, [1], [ 'foo', 'bar'], { foo: 'bar'}] };
  var barMini = MiniMax.minify(foo);
  var bar = MiniMax.maxify(barMini);

  test.isTrue(equals(foo,  bar), 'Raw compare failed "' + JSON.stringify(barMini) + '" -> "' + JSON.stringify(bar) + '"');
});

Tinytest.add('Minify Maxify - dictionary raw', function(test) {
  var MiniMaxDB = new MiniMax({
    // We add the most general words in databases
    dictionary: ['_id', 'createdAt', 'createdBy', 'updatedAt', 'updatedBy']
  });
  var foo = {
    _id: '333',
    createdBy: 'Morten',
    createdAt: new Date(),
    updatedBy: 'Morten',
    updatedAt: new Date(),
    a: ['_id', false, true, null, -1, 0, 1, 1.1, -1.1, 'foo', new Date(), undefined, [1], [ 'foo', 'bar'], { foo: 'bar'}]
  };
  var barMini = MiniMaxDB.minify(foo);
  var bar = MiniMaxDB.maxify(barMini);
console.log('BAR', barMini);
  test.isTrue(equals(foo,  bar), 'Raw compare failed "' + JSON.stringify(barMini) + '" -> "' + JSON.stringify(bar)) + '"';
});

Tinytest.add('Minify Maxify - test', function(test) {
  var minResult, maxResult, ejsonResult, savedBytes;

  var testObject = function(text, obj) {
    minResult = MiniMax.stringify(obj);

    maxResult = MiniMax.parse(minResult);

    ejsonResult = EJSON.stringify(obj);

    savedBytes = ejsonResult.length - minResult.length;

    console.log(ejsonResult.length + ' > ' + minResult.length + ' '+ Math.round(savedBytes/ejsonResult.length*100) + "%");

    console.log(maxResult);

    console.log(obj);

    test.isTrue(EJSON.equals(maxResult, obj), text);
  };

  var myJSON = '{"vLAfXEQoH2NNabXxg":{"_id":"vLAfXEQoH2NNabXxg","test":"sdfasfd"},"j8Ycq3xRXdEv9ur6L":{"_id":"j8Ycq3xRXdEv9ur6L","test":"sdfasfdafds"},"2Nbn5sCwTPz4okHmM":{"_id":"2Nbn5sCwTPz4okHmM","test":"sasdfasdf"},"oaKpnn5jSoL7zKvrX":{"_id":"oaKpnn5jSoL7zKvrX","test":"sdfasdfasdfasdfasfd"},"Fs4v4G2ne7mWMXKc9":{"_id":"Fs4v4G2ne7mWMXKc9","test":"sdfassdfasdfasfd"},"Z6aLeFGQBr93ZheSd":{"_id":"Z6aLeFGQBr93ZheSd","test":"sdfassdfasdfasfd"},"7s6RJQb4PcgQiCCRb":{"_id":"7s6RJQb4PcgQiCCRb","test":"sdfassdfasdfasfd"},"Q5JFFTT5EmnFh3tzY":{"_id":"Q5JFFTT5EmnFh3tzY","test":"sdfassdfasdfasfd"},"39CTTezRCEkSGf6Le":{"_id":"39CTTezRCEkSGf6Le","test":"sdfassdfasdfasfd"},"bcYCkPgBhXT35z4kA":{"_id":"bcYCkPgBhXT35z4kA","test":"sdfassdfasdfasfd"},"tR8FY8whuhMnZ2Bxe":{"_id":"tR8FY8whuhMnZ2Bxe","test":"sdfassdfasdfasfd"},"4r2QZRZvEWtHdy5q7":{"_id":"4r2QZRZvEWtHdy5q7","test":"sdfassdfasdfasfd"},"tguqzvrFQXwz2AvHb":{"_id":"tguqzvrFQXwz2AvHb","test":"sdfassdfasdfasfd"},"8HxwbxD7qEEge2Mrx":{"_id":"8HxwbxD7qEEge2Mrx","test":"sdfassdfasdfasfd"},"gWNved592HcgCZmfp":{"_id":"gWNved592HcgCZmfp","test":"sdfassdfasdfasfd"},"Cvwh25TrNJjDDeayN":{"_id":"Cvwh25TrNJjDDeayN","test":"sdfassdfasdfasfd"},"XGSfRdQ6Mse4prtMu":{"_id":"XGSfRdQ6Mse4prtMu","test":"sdfassdfasdfasfd"},"6s8FJegBhE5mFnF5L":{"_id":"6s8FJegBhE5mFnF5L","test":"sdfassdfasdfasfd"},"nv4soZdioGTBL6TCW":{"_id":"nv4soZdioGTBL6TCW","test":"sdfassdfasdfasfd"},"ebYsF5dnBQgz9u7P8":{"_id":"ebYsF5dnBQgz9u7P8","test":"sdfassdfasdfasfd"},"ZZTtjv28kTCy6C8ay":{"_id":"ZZTtjv28kTCy6C8ay","test":"sdfassdfasdfasfd"},"js2ZkmMddvSusmH7f":{"_id":"js2ZkmMddvSusmH7f","test":"sdfassdfasdfasfd"},"c4dyme3fdD4nuTR4t":{"_id":"c4dyme3fdD4nuTR4t","test":"sdfassdfasdfasfd"},"FJjQtcycR7JiECCiP":{"_id":"FJjQtcycR7JiECCiP","test":"sdfassdfasdfasfd"},"GBHam3iwqAe6f6BEn":{"_id":"GBHam3iwqAe6f6BEn","test":"sdfassdfasdfasfd"},"dJaqSTworxZq6X8PQ":{"_id":"dJaqSTworxZq6X8PQ","test":"sdfassdfasdfasfd"},"FfG2GDDc9nv9q2B2X":{"_id":"FfG2GDDc9nv9q2B2X","test":"sdfassdfasdfasfd"},"J9cktf2Rd6yywLYoy":{"_id":"J9cktf2Rd6yywLYoy","test":"sdfassdfasdfasfd"},"PxGPYKN8PCJDox6gb":{"_id":"PxGPYKN8PCJDox6gb","test":"sdfassdfasdfasfd"},"Do8xG2TxP7fPqQG4a":{"_id":"Do8xG2TxP7fPqQG4a","test":"sdfassdfasdfasfd"},"uMicLdcKmFKkvYgr5":{"_id":"uMicLdcKmFKkvYgr5","test":"sdfassdfasdfasfd"},"BWvrtnYk8FmJQCnFr":{"_id":"BWvrtnYk8FmJQCnFr","test":"sdfassdfasdfasfd"},"XrSq3ZR5GYgXrfide":{"_id":"XrSq3ZR5GYgXrfide","test":"sdfassdfasdfasfd"},"dayYw3Y67R72xAXc5":{"_id":"dayYw3Y67R72xAXc5","test":"sdfassdfasdfasfd"},"rPTMEQKofvMmkJ3xG":{"_id":"rPTMEQKofvMmkJ3xG","test":"sdfassdfasdfasfd", "test2":{"_id":"sfsdfsdfsdfds", "value":"hmmm"}, "test":[0,1,2,3,4,5,6,7, "bingo", {"bar":"foo"}]}}';

  testObject('org json object', EJSON.parse(myJSON));

  testObject('object 2', {
      "5qSjMxCjkNF2SFBy6": {
      _id: "5qSjMxCjkNF2SFBy6",
      foo: "test"
    },
      "rbieX9SbdGgfSWCd7": {
      _id: "rbieX9SbdGgfSWCd7",
      foo: "test",
      bar: "okay"
    }
  });

  testObject('object 3', {
      "5qSjMxCjkNF2SFBy6": {
      _id: "5qSjMxCjkNF2SFBy6",
      foo: "test"
    },
      "rbieX9SbdGgfSWCd7": {
      _id: "rbieX9SbdGgfSWCd7",
      foo: "test",
      bar: "okay",
      test: false,
      test2: true,
      ok: null
    }
  });

  var iterations = 10;

  // speed test
  speedTest('JSON.parse time: ', iterations, function() {
    JSON.parse(myJSON);
  });

  speedTest('EJSON.parse time: ', iterations, function() {
    EJSON.parse(myJSON);
  });

  speedTest('MiniMax.maxify time: ', iterations, function() {
    MiniMax.maxify(minResult);
  });

  speedTest('JSON.stringify time: ', iterations, function() {
    JSON.stringify(myJSON);
  });

  speedTest('EJSON.stringify time: ', iterations, function() {
    EJSON.stringify(myJSON);
  });

  speedTest('MiniMax.minify time: ', iterations, function() {
    MiniMax.minify(maxResult);
  });

});

//Test API:
//test.isFalse(v, msg)
//test.isTrue(v, msg)
//test.equalactual, expected, message, not
//test.length(obj, len)
//test.include(s, v)
//test.isNaN(v, msg)
//test.isUndefined(v, msg)
//test.isNotNull
//test.isNull
//test.throws(func)
//test.instanceOf(obj, klass)
//test.notEqual(actual, expected, message)
//test.runId()
//test.exception(exception)
//test.expect_fail()
//test.ok(doc)
//test.fail(doc)
//test.equal(a, b, msg)
<commit_msg>Added extensive tests<commit_after>"use strict";

function equals(a, b) {
  return !!(JSON.stringify(a) === JSON.stringify(b));
}

var speedTest = function(name, num, func) {
  var startTime = Date.now();
  for (var i = 0; i < num; i++) {
    func();
  }
  console.log(name + ((Date.now() - startTime))/num + ' ms');
}

Tinytest.add('Minify Maxify - test date', function(test) {
  var newTimeStamp = 1409300873188;
  var newDate = new Date(newTimeStamp);

  var obj = {
    updatedAt: newDate
  };

  var toString = MiniMax.stringify(obj);
  var fromString = MiniMax.parse(toString);

  console.log('toString', toString);
  console.log('fromString', fromString);

  test.instanceOf(obj.updatedAt, Date, 'Test Date is not handled correctly');
  test.instanceOf(fromString.updatedAt, Date, 'Date is not handled correctly');
});

Tinytest.add('Minify Maxify - raw test', function(test) {
  var foo = ['_id', false, true, null, -1, 0, 1, 1.1, -1.1, 'foo', new Date(), undefined, [1], [ 'foo', 'bar'], { foo: 'bar'}];
  var barMini = MiniMax.minify(foo);
  var bar = MiniMax.maxify(barMini);
  test.isTrue(equals(foo,  bar), 'Raw compare failed "' + JSON.stringify(barMini) + '" -> "' + JSON.stringify(bar) + '"');
});

Tinytest.add('Minify Maxify - raw test object', function(test) {
  var foo = { a: ['_id', false, true, null, -1, 0, 1, 1.1, -1.1, 'foo', new Date(), undefined, [1], [ 'foo', 'bar'], { foo: 'bar'}] };
  var barMini = MiniMax.minify(foo);
  var bar = MiniMax.maxify(barMini);

  test.isTrue(equals(foo,  bar), 'Raw compare failed "' + JSON.stringify(barMini) + '" -> "' + JSON.stringify(bar) + '"');
});

Tinytest.add('Minify Maxify - dictionary raw', function(test) {
  var MiniMaxDB = new MiniMax({
    // We add the most general words in databases
    dictionary: ['_id', 'createdAt', 'createdBy', 'updatedAt', 'updatedBy']
  });
  var foo = {
    _id: '333',
    createdBy: 'Morten',
    createdAt: new Date(),
    updatedBy: 'Morten',
    updatedAt: new Date(),
    a: ['_id', false, true, null, -1, 0, 1, 1.1, -1.1, 'foo', new Date(), undefined, [1], [ 'foo', 'bar'], { foo: 'bar'}]
  };
  var barMini = MiniMaxDB.minify(foo);
  var bar = MiniMaxDB.maxify(barMini);

console.log('BAR', barMini);
  test.isTrue(equals(foo,  bar), 'Raw compare failed "' + JSON.stringify(barMini) + '" -> "' + JSON.stringify(bar) + '"');
});

Tinytest.add('Minify Maxify - dictionary raw medium', function(test) {
  var MiniMaxDB = new MiniMax({
    // We add the most general words in databases
    dictionary: ['_id', 'createdAt', 'createdBy', 'updatedAt', 'updatedBy']
  });

  var map = {};

  for (var i = 0; i < 5; i++) {

    var id = Random.id();

    var d = new Date();

    map[id] = {
      _id: id,
      createdBy: 'Morten',
      createdAt: d,
      updatedBy: 'Morten',
      updatedAt: d,
      a: ['_id', false, true, null, -1, 0, 1, 1.1, -1.1, 'foo', new Date(), undefined, [1], [ 'foo', 'bar'], { foo: 'bar'}]
    };

  }

  var ejsonMap = EJSON.stringify(map);

  var barMini = MiniMaxDB.minify(map);
  var bar = MiniMaxDB.maxify(barMini);

  _.each(map, function(item, id) {
    var strA = EJSON.stringify(item);
    var strB = EJSON.stringify(bar[id]);
    test.equal(strA, strB, 'Raw compare of ' + id + ' failed');
  });

  // var barEjsonMap = EJSON.stringify(bar);

  // test.equal(ejsonMap,  barEjsonMap, 'Raw compare failed');
});

Tinytest.add('Minify Maxify - dictionary raw bigger', function(test) {
  var MiniMaxDB = new MiniMax({
    // We add the most general words in databases
    dictionary: ['_id', 'createdAt', 'createdBy', 'updatedAt', 'updatedBy'],
    progressive: false
  });

  var map = {};

  for (var i = 0; i < 500; i++) {

    var id = Random.id();

    var d = new Date();

    map[id] = {
      _id: id,
      createdBy: 'Morten',
      createdAt: d,
      updatedBy: 'Morten',
      updatedAt: d,
      a: ['_id', false, true, null, -1, 0, 1, 1.1, -1.1, 'foo', new Date(), undefined, [1], [ 'foo', 'bar'], { foo: 'bar'}]
    };

  }

  var ejsonMap = EJSON.stringify(map);

  var barMini = MiniMaxDB.minify(map);
  var bar = MiniMaxDB.maxify(barMini);

  _.each(map, function(item, id) {
    var strA = EJSON.stringify(item);
    var strB = EJSON.stringify(bar[id]);
    test.equal(strA, strB, 'Raw compare of ' + id + ' failed');
  });

});

Tinytest.add('Minify Maxify - dictionary raw bigger progressive', function(test) {
  var MiniMaxDB = new MiniMax({
    // We add the most general words in databases
    dictionary: ['_id', 'createdAt', 'createdBy', 'updatedAt', 'updatedBy'],
    progressive: true
  });

  var map = {};

  for (var i = 0; i < 500; i++) {

    var id = Random.id();

    var d = new Date();

    map[id] = {
      _id: id,
      createdBy: 'Morten',
      createdAt: d,
      updatedBy: 'Morten',
      updatedAt: d,
      a: ['_id', false, true, null, -1, 0, 1, 1.1, -1.1, 'foo', new Date(), undefined, [1], [ 'foo', 'bar'], { foo: 'bar'}]
    };

  }

  var ejsonMap = EJSON.stringify(map);

  var barMini = MiniMaxDB.stringify(map);
  var bar = MiniMaxDB.parse(barMini);

  barMini = MiniMaxDB.stringify(bar);
  bar = MiniMaxDB.parse(barMini);

  _.each(map, function(item, id) {
    var strA = EJSON.stringify(item);
    var strB = EJSON.stringify(bar[id]);
    test.equal(strA, strB, 'Raw compare of ' + id + ' failed');
  });

});

Tinytest.add('Minify Maxify - test', function(test) {
  var minResult, maxResult, ejsonResult, savedBytes;

  var testObject = function(text, obj) {
    minResult = MiniMax.stringify(obj);

    maxResult = MiniMax.parse(minResult);

    ejsonResult = EJSON.stringify(obj);

    savedBytes = ejsonResult.length - minResult.length;

    console.log(ejsonResult.length + ' > ' + minResult.length + ' '+ Math.round(savedBytes/ejsonResult.length*100) + "%");

    console.log(maxResult);

    console.log(obj);

    test.isTrue(EJSON.equals(maxResult, obj), text);
  };

  var myJSON = '{"vLAfXEQoH2NNabXxg":{"_id":"vLAfXEQoH2NNabXxg","test":"sdfasfd"},"j8Ycq3xRXdEv9ur6L":{"_id":"j8Ycq3xRXdEv9ur6L","test":"sdfasfdafds"},"2Nbn5sCwTPz4okHmM":{"_id":"2Nbn5sCwTPz4okHmM","test":"sasdfasdf"},"oaKpnn5jSoL7zKvrX":{"_id":"oaKpnn5jSoL7zKvrX","test":"sdfasdfasdfasdfasfd"},"Fs4v4G2ne7mWMXKc9":{"_id":"Fs4v4G2ne7mWMXKc9","test":"sdfassdfasdfasfd"},"Z6aLeFGQBr93ZheSd":{"_id":"Z6aLeFGQBr93ZheSd","test":"sdfassdfasdfasfd"},"7s6RJQb4PcgQiCCRb":{"_id":"7s6RJQb4PcgQiCCRb","test":"sdfassdfasdfasfd"},"Q5JFFTT5EmnFh3tzY":{"_id":"Q5JFFTT5EmnFh3tzY","test":"sdfassdfasdfasfd"},"39CTTezRCEkSGf6Le":{"_id":"39CTTezRCEkSGf6Le","test":"sdfassdfasdfasfd"},"bcYCkPgBhXT35z4kA":{"_id":"bcYCkPgBhXT35z4kA","test":"sdfassdfasdfasfd"},"tR8FY8whuhMnZ2Bxe":{"_id":"tR8FY8whuhMnZ2Bxe","test":"sdfassdfasdfasfd"},"4r2QZRZvEWtHdy5q7":{"_id":"4r2QZRZvEWtHdy5q7","test":"sdfassdfasdfasfd"},"tguqzvrFQXwz2AvHb":{"_id":"tguqzvrFQXwz2AvHb","test":"sdfassdfasdfasfd"},"8HxwbxD7qEEge2Mrx":{"_id":"8HxwbxD7qEEge2Mrx","test":"sdfassdfasdfasfd"},"gWNved592HcgCZmfp":{"_id":"gWNved592HcgCZmfp","test":"sdfassdfasdfasfd"},"Cvwh25TrNJjDDeayN":{"_id":"Cvwh25TrNJjDDeayN","test":"sdfassdfasdfasfd"},"XGSfRdQ6Mse4prtMu":{"_id":"XGSfRdQ6Mse4prtMu","test":"sdfassdfasdfasfd"},"6s8FJegBhE5mFnF5L":{"_id":"6s8FJegBhE5mFnF5L","test":"sdfassdfasdfasfd"},"nv4soZdioGTBL6TCW":{"_id":"nv4soZdioGTBL6TCW","test":"sdfassdfasdfasfd"},"ebYsF5dnBQgz9u7P8":{"_id":"ebYsF5dnBQgz9u7P8","test":"sdfassdfasdfasfd"},"ZZTtjv28kTCy6C8ay":{"_id":"ZZTtjv28kTCy6C8ay","test":"sdfassdfasdfasfd"},"js2ZkmMddvSusmH7f":{"_id":"js2ZkmMddvSusmH7f","test":"sdfassdfasdfasfd"},"c4dyme3fdD4nuTR4t":{"_id":"c4dyme3fdD4nuTR4t","test":"sdfassdfasdfasfd"},"FJjQtcycR7JiECCiP":{"_id":"FJjQtcycR7JiECCiP","test":"sdfassdfasdfasfd"},"GBHam3iwqAe6f6BEn":{"_id":"GBHam3iwqAe6f6BEn","test":"sdfassdfasdfasfd"},"dJaqSTworxZq6X8PQ":{"_id":"dJaqSTworxZq6X8PQ","test":"sdfassdfasdfasfd"},"FfG2GDDc9nv9q2B2X":{"_id":"FfG2GDDc9nv9q2B2X","test":"sdfassdfasdfasfd"},"J9cktf2Rd6yywLYoy":{"_id":"J9cktf2Rd6yywLYoy","test":"sdfassdfasdfasfd"},"PxGPYKN8PCJDox6gb":{"_id":"PxGPYKN8PCJDox6gb","test":"sdfassdfasdfasfd"},"Do8xG2TxP7fPqQG4a":{"_id":"Do8xG2TxP7fPqQG4a","test":"sdfassdfasdfasfd"},"uMicLdcKmFKkvYgr5":{"_id":"uMicLdcKmFKkvYgr5","test":"sdfassdfasdfasfd"},"BWvrtnYk8FmJQCnFr":{"_id":"BWvrtnYk8FmJQCnFr","test":"sdfassdfasdfasfd"},"XrSq3ZR5GYgXrfide":{"_id":"XrSq3ZR5GYgXrfide","test":"sdfassdfasdfasfd"},"dayYw3Y67R72xAXc5":{"_id":"dayYw3Y67R72xAXc5","test":"sdfassdfasdfasfd"},"rPTMEQKofvMmkJ3xG":{"_id":"rPTMEQKofvMmkJ3xG","test":"sdfassdfasdfasfd", "test2":{"_id":"sfsdfsdfsdfds", "value":"hmmm"}, "test":[0,1,2,3,4,5,6,7, "bingo", {"bar":"foo"}]}}';

  testObject('org json object', EJSON.parse(myJSON));

  testObject('object 2', {
      "5qSjMxCjkNF2SFBy6": {
      _id: "5qSjMxCjkNF2SFBy6",
      foo: "test"
    },
      "rbieX9SbdGgfSWCd7": {
      _id: "rbieX9SbdGgfSWCd7",
      foo: "test",
      bar: "okay"
    }
  });

  testObject('object 3', {
      "5qSjMxCjkNF2SFBy6": {
      _id: "5qSjMxCjkNF2SFBy6",
      foo: "test"
    },
      "rbieX9SbdGgfSWCd7": {
      _id: "rbieX9SbdGgfSWCd7",
      foo: "test",
      bar: "okay",
      test: false,
      test2: true,
      ok: null
    }
  });

  var iterations = 10;

  // speed test
  speedTest('JSON.parse time: ', iterations, function() {
    JSON.parse(myJSON);
  });

  speedTest('EJSON.parse time: ', iterations, function() {
    EJSON.parse(myJSON);
  });

  speedTest('MiniMax.maxify time: ', iterations, function() {
    MiniMax.maxify(minResult);
  });

  speedTest('JSON.stringify time: ', iterations, function() {
    JSON.stringify(myJSON);
  });

  speedTest('EJSON.stringify time: ', iterations, function() {
    EJSON.stringify(myJSON);
  });

  speedTest('MiniMax.minify time: ', iterations, function() {
    MiniMax.minify(maxResult);
  });

});

//Test API:
//test.isFalse(v, msg)
//test.isTrue(v, msg)
//test.equalactual, expected, message, not
//test.length(obj, len)
//test.include(s, v)
//test.isNaN(v, msg)
//test.isUndefined(v, msg)
//test.isNotNull
//test.isNull
//test.throws(func)
//test.instanceOf(obj, klass)
//test.notEqual(actual, expected, message)
//test.runId()
//test.exception(exception)
//test.expect_fail()
//test.ok(doc)
//test.fail(doc)
//test.equal(a, b, msg)
<|endoftext|>


<commit_before>import { connect } from 'react-redux';
import React from 'react';
import S from 'string';
import classNames from 'classnames';
import TransformQuestion from './TransformQuestion';
import MultiNumberQuestionState from '../../states/MultiNumberQuestionState';
import QuestionDetail from '../parts/QuestionDetail';
import Value from '../parts/Value';

/** CheckboxQuestion, RadioQuestionの基底クラス */
class MatrixQuestion extends TransformQuestion {
  /** 追加の入力elementを作成する */
  static createAdditionalInputElement(question, item, subItem) {
    const matrixType = question.getMatrixType();
    if (matrixType !== 'checkbox' && matrixType !== 'radio') return null;

    const targetItem = question.isMatrixReverse() ? item : subItem;
    if (!targetItem.hasAdditionalInput()) return null;

    const name = question.isMatrixReverse() ? question.getAdditionalOutputName(subItem, item) : question.getAdditionalOutputName(item, subItem);
    return (

        <input type={targetItem.getAdditionalInputType()} name={name} disabled className="disabled additional-input" />
        {targetItem.getUnit()}

    );
  }

  /** inputを作成する */
  static createInputElement(tableId, rowId, question, item, subItem) {
    const matrixType = question.getMatrixType();
    const name = question.isMatrixReverse() ? question.getOutputName(subItem, item) : question.getOutputName(item, subItem);
    const value = question.isMatrixReverse() ? question.getOutputValue(item) : question.getOutputValue(subItem);
    switch (matrixType) {
      case 'radio':
        return (
          <input
            type={matrixType}
            name={name}
            value={value}
            className="matrix-value"
            data-parsley-class-handler={`#${tableId}`}
            data-parsley-required
            data-parsley-required-message="すべての行について選択してください"
          />
        );
      case 'text':
        return (
          <input
            type={matrixType}
            name={name}
            data-parsley-required
          />
        );
      case 'number':
        return (
          <input
            type={matrixType}
            name={name}
            className="sdj-numeric"
            size="4"
            data-parsley-required
          />
        );
      case 'checkbox':
        return (
          <input
            type={matrixType}
            name={name}
            value={value}
            className="matrix-value"
            data-parsley-class-handler={`#${rowId}`}
            data-parsley-required
            data-parsley-multiple={item.getId()}
            data-parsley-required-message="最低一つ選択してください"
          />
        );
      default:
        throw new Error(`不明なmatrixTypeです: ${matrixType}`);
    }
  }

  /** 列の合計行を作成する */
  constructor(props) {
    super(props, MultiNumberQuestionState);
  }

  createSumColRow(question, items, replacer) {
    const { options } = this.props;
    if (question.getMatrixType() === 'number' && question.isMatrixSumCols()) {
      return (

          合計
          {
            items.map((item) => {
              const totalName = question.getOutputTotalColName(item);
              const colId = `${question.getId()}_${item.getId()}_sum`;
              const totalEqualTo = item.getTotalEqualTo();
              const showValidation = options.isShowDetail() && !S(totalEqualTo).isEmpty();
              return (

                  { showValidation ?
<Value className="" value={totalEqualTo} />と一致
 : null}
                  <input
                    name={totalName}
                    className="sdj-sum disabled"
                    type="number"
                    readOnly
                    defaultValue="0"
                    data-parsley-required
                    data-parsley-type="digits"
                    data-parsley-equal={!S(totalEqualTo).isEmpty() ? replacer.id2Value(totalEqualTo) : null}
                  />

              );
            })
          }

      );
    }
    return null;
  }

  createRow(tableId, item, itemIndex, subItems, replacer) {
    const { options, question } = this.props;
    const rowId = `${question.getId()}_${item.getId()}`;
    const totalName = question.getOutputTotalRowName(item);
    let sumEl = null;
    if (question.getMatrixType() === 'number' && question.isMatrixSumRows()) {
      const totalEqualTo = item.getTotalEqualTo();
      const showValidation = options.isShowDetail() && !S(totalEqualTo).isEmpty();
      sumEl = (

          { showValidation ?
<Value className="" value={totalEqualTo} />と一致
 : null}
          <input
            name={totalName}
            className="sdj-sum disabled"
            type="number"
            readOnly
            defaultValue="0"
            data-parsley-required
            data-parsley-type="digits"
            data-parsley-equal={!S(totalEqualTo).isEmpty() ? replacer.id2Value(totalEqualTo) : null}
          />

      );
    }
    return (

          {this.createItemDetail(item)}

        {subItems.map(subItem => (
          <td key={`${question.getId()}_${item.getId()}_${subItem.getId()}`}>

              {MatrixQuestion.createInputElement(tableId, rowId, question, item, subItem)}
              {MatrixQuestion.createAdditionalInputElement(question, item, subItem)}

          	))
        }
        {sumEl}

    );
  }

  createItemDetail(item) {
    const { question, options } = this.props;
    if (!options.isShowDetail()) return null;

    return (

        {question.isRandom() && item.isRandomFixed() ? ランダム固定 : null}

    );
  }

  /** 描画 */
  render() {
    const { replacer, question, options } = this.props;
    const title = question.getTitle();
    const description = question.getDescription();
    const tableId = `${question.getId()}_table`;
    const items = question.getTransformedItems();
    const subItems = question.getTransformedSubItems();
    return (

 { this.rootEl = el; }} className={this.constructor.name}>
        {S(title).isEmpty() ? null :
}
        {S(description).isEmpty() ?
          null :
}

                {subItems.map(subItem => (

                    {this.createItemDetail(subItem)}

                ))}
                {question.getMatrixType() === 'number' && question.isMatrixSumRows() ? 合計	 : null}

              {items.map((item, itemIndex) => this.createRow(tableId, item, itemIndex, subItems, replacer))}
              {this.createSumColRow(question, subItems, replacer)}

        { options.isShowDetail() ? (
          <QuestionDetail
            question={question}
            random
            subItemsRandom
            matrixReverse
          />) : null }

    );
  }
}

const stateToProps = state => ({
  survey: state.getSurvey(),
  runtime: state.getRuntime(),
  view: state.getViewSetting(),
  options: state.getOptions(),
});

export default connect(
  stateToProps,
)(MatrixQuestion);

<commit_msg>表形式のバリデーションメッセージを列でグルーピングに対応<commit_after>import { connect } from 'react-redux';
import React from 'react';
import S from 'string';
import classNames from 'classnames';
import TransformQuestion from './TransformQuestion';
import MultiNumberQuestionState from '../../states/MultiNumberQuestionState';
import QuestionDetail from '../parts/QuestionDetail';
import Value from '../parts/Value';

/** CheckboxQuestion, RadioQuestionの基底クラス */
class MatrixQuestion extends TransformQuestion {
  /** 追加の入力elementを作成する */
  static createAdditionalInputElement(question, item, subItem) {
    const matrixType = question.getMatrixType();
    if (matrixType !== 'checkbox' && matrixType !== 'radio') return null;

    const targetItem = question.isMatrixReverse() ? item : subItem;
    if (!targetItem.hasAdditionalInput()) return null;

    const name = question.isMatrixReverse() ? question.getAdditionalOutputName(subItem, item) : question.getAdditionalOutputName(item, subItem);
    return (

        <input type={targetItem.getAdditionalInputType()} name={name} disabled className="disabled additional-input" />
        {targetItem.getUnit()}

    );
  }

  /** inputを作成する */
  static createInputElement(tableId, rowId, question, item, subItem) {
    const matrixType = question.getMatrixType();
    const name = question.isMatrixReverse() ? question.getOutputName(subItem, item) : question.getOutputName(item, subItem);
    const value = question.isMatrixReverse() ? question.getOutputValue(item) : question.getOutputValue(subItem);
    switch (matrixType) {
      case 'radio':
        return (
          <input
            type={matrixType}
            name={name}
            value={value}
            className="matrix-value"
            data-parsley-class-handler={`#${tableId}`}
            data-parsley-required
            data-parsley-required-message={`すべての${question.isMatrixReverse() ? '列' : '行'}について選択してください`}
          />
        );
      case 'text':
        return (
          <input
            type={matrixType}
            name={name}
            data-parsley-required
          />
        );
      case 'number':
        return (
          <input
            type={matrixType}
            name={name}
            className="sdj-numeric"
            size="4"
            data-parsley-required
          />
        );
      case 'checkbox':
        return (
          <input
            type={matrixType}
            name={name}
            value={value}
            className="matrix-value"
            data-parsley-class-handler={`#${rowId}`}
            data-parsley-required
            data-parsley-multiple={item.getId()}
            data-parsley-required-message="最低一つ選択してください"
          />
        );
      default:
        throw new Error(`不明なmatrixTypeです: ${matrixType}`);
    }
  }

  /** 列の合計行を作成する */
  constructor(props) {
    super(props, MultiNumberQuestionState);
  }

  createSumColRow(question, items, replacer) {
    const { options } = this.props;
    if (question.getMatrixType() === 'number' && question.isMatrixSumCols()) {
      return (

          合計
          {
            items.map((item) => {
              const totalName = question.getOutputTotalColName(item);
              const colId = `${question.getId()}_${item.getId()}_sum`;
              const totalEqualTo = item.getTotalEqualTo();
              const showValidation = options.isShowDetail() && !S(totalEqualTo).isEmpty();
              return (

                  { showValidation ?
<Value className="" value={totalEqualTo} />と一致
 : null}
                  <input
                    name={totalName}
                    className="sdj-sum disabled"
                    type="number"
                    readOnly
                    defaultValue="0"
                    data-parsley-required
                    data-parsley-type="digits"
                    data-parsley-equal={!S(totalEqualTo).isEmpty() ? replacer.id2Value(totalEqualTo) : null}
                  />

              );
            })
          }

      );
    }
    return null;
  }

  createRow(tableId, item, itemIndex, subItems, replacer) {
    const { options, question } = this.props;
    const rowId = `${question.getId()}_${item.getId()}`;
    const totalName = question.getOutputTotalRowName(item);
    let sumEl = null;
    if (question.getMatrixType() === 'number' && question.isMatrixSumRows()) {
      const totalEqualTo = item.getTotalEqualTo();
      const showValidation = options.isShowDetail() && !S(totalEqualTo).isEmpty();
      sumEl = (

          { showValidation ?
<Value className="" value={totalEqualTo} />と一致
 : null}
          <input
            name={totalName}
            className="sdj-sum disabled"
            type="number"
            readOnly
            defaultValue="0"
            data-parsley-required
            data-parsley-type="digits"
            data-parsley-equal={!S(totalEqualTo).isEmpty() ? replacer.id2Value(totalEqualTo) : null}
          />

      );
    }
    return (

          {this.createItemDetail(item)}

        {subItems.map(subItem => (
          <td key={`${question.getId()}_${item.getId()}_${subItem.getId()}`}>

              {MatrixQuestion.createInputElement(tableId, rowId, question, item, subItem)}
              {MatrixQuestion.createAdditionalInputElement(question, item, subItem)}

          	))
        }
        {sumEl}

    );
  }

  createItemDetail(item) {
    const { question, options } = this.props;
    if (!options.isShowDetail()) return null;

    return (

        {question.isRandom() && item.isRandomFixed() ? ランダム固定 : null}

    );
  }

  /** 描画 */
  render() {
    const { replacer, question, options } = this.props;
    const title = question.getTitle();
    const description = question.getDescription();
    const tableId = `${question.getId()}_table`;
    const items = question.getTransformedItems();
    const subItems = question.getTransformedSubItems();
    return (

 { this.rootEl = el; }} className={this.constructor.name}>
        {S(title).isEmpty() ? null :
}
        {S(description).isEmpty() ?
          null :
}

                {subItems.map(subItem => (

                    {this.createItemDetail(subItem)}

                ))}
                {question.getMatrixType() === 'number' && question.isMatrixSumRows() ? 合計	 : null}

              {items.map((item, itemIndex) => this.createRow(tableId, item, itemIndex, subItems, replacer))}
              {this.createSumColRow(question, subItems, replacer)}

        { options.isShowDetail() ? (
          <QuestionDetail
            question={question}
            random
            subItemsRandom
            matrixReverse
          />) : null }

    );
  }
}

const stateToProps = state => ({
  survey: state.getSurvey(),
  runtime: state.getRuntime(),
  view: state.getViewSetting(),
  options: state.getOptions(),
});

export default connect(
  stateToProps,
)(MatrixQuestion);

<|endoftext|>


<commit_before>/** MIT License (c) copyright B Cavalier & J Hann */

// TODO:
// 1. Incrementally recompute the join for items added to or removed from the
//    primary adapter.  This requires precomputing and hanging onto the joinMap
// 2. Recompute the join when items are added to or removed from the supplimental

(function(define) {
define(function (require) {

"use strict";

	var when = require('when');

	function JoinAdapter(primary, options) {

		if(!(options && options.joinWith && options.strategy)) {
			throw new Error('options.joinWith and options.strategy are required');
		}

		this.identifier = primary.identifier;
		this.comparator = primary.comparator;
		this.provide = primary.provide;

		this._primary = primary;
		this._options = options;
		this._joinStrategy = options.strategy;
	}

	JoinAdapter.prototype = {

		getOptions: function() {
			return this._primary.getOptions();
		},

		watch: function(added, removed) {
			return this._primary.watch(added, removed);
		},

		forEach: function(lambda) {
			var joined = this._joined;
			if(!joined) {
				joined = this._joined = this._doJoin();
			}

			return when(joined, function(joined) {
				for(var i = 0, len = joined.length; i < len; i++) {
					lambda(joined[i]);
				}
			});
		},

		add: function(item) {
			// Force the join to be recomputed
			// It is possible to incrementally compute the join only for
			// the new item, but for now, punt.
			var self = this;
			return when(this._primary.add(item), function(added) {
				if(added) {
					self._joined = null;
				}

				return added;
			});
		},

		remove: function(item) {
			// Similarly, force join recompute .. optimize with incremental later
			var self = this;
			return when(this._primary.remove(item), function(removed) {
				if(removed) {
					self._joined = null;
				}

				return removed;
			});
		},

		_doJoin: function() {
			var left, right;

			left = this._primary;
			right = this._options.joinWith;

			return this._joinStrategy(left, right);
		}
	};

	return JoinAdapter;

});
})(
	typeof define == 'function'
		? define
		: function(factory) { module.exports = factory(require); }
);
<commit_msg>Refactored JoinAdapter to be a decorator rather than a wrapper to avoid problems with Hub-decorated adapter events in QueryAdapter<commit_after>/** MIT License (c) copyright B Cavalier & J Hann */

// TODO:
// 1. Incrementally recompute the join for items added to or removed from the
//    primary adapter.  This requires precomputing and hanging onto the joinMap
// 2. Recompute the join when items are added to or removed from the supplimental

(function(define) {
define(function (require) {

"use strict";

	var when, methodsToReplace;

	when = require('when');

	methodsToReplace = {
		add: 1,
		update: 1,
		remove: 1,
		clear: 1
	};

	/**
	 * Decorates the supplied primary adapter so that it will provide
	 * data that is joined from a secondary source specified in options.joinWith
	 * using the join strategy specified in options.strategy
	 *
	 * @param primary {Object} primary adapter
	 * @param options.joinWith {Object} secondary adapter
	 * @param options.strategy {Function} join strategy to use in joining
	 *  data from the primary and secondary adapters
	 */
	return function makeJoined(primary, options) {

		if(!(options && options.joinWith && options.strategy)) {
			throw new Error('options.joinWith and options.strategy are required');
		}

		var forEachOrig, joined, methodName, secondary, joinStrategy, primaryProxy;

		secondary = options.joinWith;
		joinStrategy = options.strategy;

		function replaceMethod(adapter, methodName) {
			var orig = adapter[methodName];

			adapter[methodName] = function() {
				// Force the join to be recomputed when data changes
				// This is way too aggressive, but also very safe.
				// We can optimize to incrementally recompute if it
				// becomes a problem.
				joined = null;
				return orig.apply(adapter, arguments);
			}
		}

		// Replace the primary adapters cola event methods
		for(methodName in methodsToReplace) {
			replaceMethod(primary, methodName);
		}

		// Create a proxy adapter that has a forEach that provides
		// access to the primary adapter's *original* data.  We must
		// send this to the join strategy since we're *replacing* the
		// primary adapter's forEach with one that calls the joinStrategy.
		// That would lead to an infinite call cycle.
		forEachOrig = primary.forEach;
		primaryProxy = {
			forEach: function() {
				return forEachOrig.apply(primary, arguments);
			}
		};

		primary.forEach = function(lambda) {
			if(!joined) {
				joined = joinStrategy(primaryProxy, secondary);
			}

			return when(joined, function(joined) {
				for(var i = 0, len = joined.length; i < len; i++) {
					lambda(joined[i]);
				}
			});
		};

		return primary;
	};

});
})(
	typeof define == 'function'
		? define
		: function(factory) { module.exports = factory(require); }
);
<|endoftext|>