<commit_before>/* Geena.utils.Proc
 *
 * This file is part of the geena package.
 * Copyright (c) 2014 Rhinostone <geena@rhinostone.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 *
 * { name: 'SIGABRT', action: 'A', desc: 'Process abort signal.' },
 * { name: 'SIGALRM', action: 'T', desc: 'Alarm clock.' },
 * { name: 'SIGBUS', action: 'A', desc: 'Access to an undefined portion of a memory object.' },
 * { name: 'SIGCHLD', action: 'I', desc: 'Child process terminated, stopped, or continued. ' },
 * { name: 'SIGCONT', action: 'C', desc: 'Continue executing, if stopped.' },
 * { name: 'SIGFPE', action: 'A', desc: 'Erroneous arithmetic operation.' },
 * { name: 'SIGHUP', action: 'T', desc: 'Hangup.' },
 * { name: 'SIGILL', action: 'A', desc: 'Illegal instruction.' },
 * { name: 'SIGINT', action: 'T', desc: 'Terminal interrupt signal.' },
 * { name: 'SIGKILL', action: 'T', desc: 'Kill (cannot be caught or ignored).' },
 * { name: 'SIGPIPE', action: 'T', desc: 'Write on a pipe with no one to read it.' },
 * { name: 'SIGQUIT', action: 'A', desc: 'Terminal quit signal.' },
 * { name: 'SIGSEGV', action: 'A', desc: 'Invalid memory reference.' },
 * { name: 'SIGSTOP', action: 'S', desc: 'Stop executing (cannot be caught or ignored).' },
 * { name: 'SIGTERM', action: 'T', desc: 'Termination signal.' },
 * { name: 'SIGTSTP', action: 'S', desc: 'Terminal stop signal.' },
 * { name: 'SIGTTIN', action: 'S', desc: 'Background process attempting read.' },
 * { name: 'SIGTTOU', action: 'S', desc: 'Background process attempting write.' },
 * { name: 'SIGUSR1', action: 'T', desc: 'User-defined signal 1.' },
 * { name: 'SIGUSR2', action: 'T', desc: 'User-defined signal 2.' },
 * { name: 'SIGPOLL', action: 'T', desc: 'Pollable event. ' },
 * { name: 'SIGPROF', action: 'T', desc: 'Profiling timer expired. ' },
 * { name: 'SIGSYS', action: 'A', desc: 'Bad system call.' },
 * { name: 'SIGTRAP', action: 'A', desc: 'Trace/breakpoint trap. ' },
 * { name: 'SIGURG', action: 'I', desc: 'High bandwidth data is available at a socket.' },
 * { name: 'SIGVTALRM', action: 'T', desc: 'Virtual timer expired.' },
 * { name: 'SIGXCPU', action: 'A', desc: 'CPU time limit exceeded.' },
 * { name: 'SIGXFSZ', action: 'A', desc: 'File size limit exceeded. ' }
 * */
var Proc;

//Imports
var fs      = require('fs');
var logger  = require( _(__dirname + '/logger') );
var spawn = require('child_process').spawn;

/**
 * @constructor
 *
 * @param {string} bundle
 *
 * */
Proc = function(bundle, proc, usePidFile){

    var _this   = this;
    this.PID    = null;
    this.path   = null;
    this.master = false;//used only by master.
    this.bundle = bundle;
    this.proc   = proc;
    this.bundles = [];

    if ( typeof(usePidFile) == 'undefined') {
        var usePidFile = true;
    }

    /**
     * Check target path
     * @param {string} path
     * @param {integer} PID Id of the PID to save
     * */

    var init = function(){
        //Default.
        var pathObj = new _( getPath('root') + '/tmp/pid/' );
        var path = pathObj.toString();
//        console.log('looking for path ', getPath('root') + "/tmp/pid/" );
//        console.log("init with path ...", path, " - BUNDLE : ", bundle );
//        console.log("about to create PID file under ", path, "["+bundle+"]");
        //Create dir if needed.
        console.log("MKDIR  pathObj (pid:"+_this.proc.pid+") - ", _this.bundle);
        process.list = (process.list == undefined) ? {} : process.list;
        process.pids = (process.pids == undefined) ? {} : process.pids;

        _this.register(_this.bundle, _this.proc.pid);
        console.log('registring ', _this.proc.pid);
        if (usePidFile) {
            pathObj.mkdir( function(err, path){
                console.log('path created ('+path+') now saving PID ' +  bundle);
                //logger.info('geena', 'PROC:INFO:1', 'path created ('+path+') now saving PID ' +  bundle, __stack);
                //Save file.
                if (!err) {
                    _this.PID = _this.proc.pid;
                    _this.path = path + pathObj.sep;
                    //Add PID file.
                    setPID(_this.bundle, _this.PID, _this.proc);
                    save(_this.bundle, _this.PID, _this.proc);
                }
            });
        }
    };

    var isMaster = function(){
        return (_this.master) ? true : false;
    };
    /**
     * Going to force restart by third party (kill 9).
     *
     * @param {string} bundle
     * @param {string} env
     * @param {number} pid
     *
     * @callback callback
     * @param {boolean|string} err
     * */
    var respawn = function(bundle, env, pid, callback){
        console.log("Exiting and re spawning : ", bundle, env);
        if (env == 'prod') {//won't loop forever for others env.
            // TODO - Count the restarts and prevent unilimited loop
            // TODO - Send notification to admin or/and root to the Fatal Error Page.

            var root = getPath('root');
            try {
                var version = process.getVersion(bundle);
            } catch (err) {
                var bundle = process.argv[3];
                console.log("Bundle ", bundle," already running...");
                dismiss(process.pid);
            }

            var outPath = _(root + '/out.'+bundle+'.'+version+'.log');
            var errPath = _(root + '/out.'+bundle+'.'+version+'.log');
            var nodePath = getPath('node');
            var geenaPath = _(root + '/geena');

            var opt = process.getShutdownConnectorSync();
            //Should kill existing one..
            opt.path = '/'+bundle + '/restart/'+ pid +'/' + env;

            var HttpClient = require('geena.com').Http;
            var httpClient = new HttpClient();

            if (httpClient) {
                //httpClient.query(opt);
                //We are not waiting for anything particular...do we ?
                httpClient.query(opt, function(err, msg){
                    //Now start new bundle.
                    callback(err);
                });
            } else {
                var err = new Error('No shutdown connector found.');
                console.error(err);
                callback(err);
            }
        } else {
            callback(false);
        }
    };

    var setPID = function(bundle, PID, proc){

        if (bundle != 'geena') {
            proc.title = 'geena: '+ bundle;
        } else {
            proc.title = bundle;
        }

        //Set event.
        setDefaultEvents(bundle, PID, proc);
    };

    var setDefaultEvents = function(bundle, PID, proc){

        if ( typeof(PID) != "undefined" && typeof(PID) == "number" ) {
            console.log("setting listeners for ", PID, ':', bundle);

            proc.dismiss = dismiss;
            proc.isMaster = isMaster;

            proc.on('SIGTERM', function(code){
                proc.exit(code);
            });

            proc.on('SIGINT', function(code){

                if (code == undefined) var code = 0;
                console.log("got exit code ", code, process.list);
                proc.exit(code);//tigger exit event.
            });

            //Will prevent the server from stopping.
            proc.on('uncaughtException', function(err){

                logger.exception('geena', 'FATAL_EXCEPTION:1', 'Special care needed !! ' + err + err.stack, function(err){
                    //TODO - Send an email to the administrator/dev
                    //TODO - Have a delegate handler to allow the dev to do its stuff. Maybe it's already there if any dev can override.
                    console.log('Fix your shit...');
                });
                console.log(err.stack);
                var bundle = process.argv[3];
                var pid = _this.getPidByBundleName(bundle);

                var env =  process.env.NODE_ENV || 'prod';
                //Wake up buddy !.
                respawn(bundle, env, pid, function(err){
                    proc.exit(1);
                });

            });

            proc.on('exit', function(code){

                if ( typeof(code) == 'undefined') {
                    code = 0;
                }

                var bundle = process.argv[3];
                console.log("@=>", _this.args);
                var pid = _this.getPidByBundleName(bundle);
                var env =  process.env.NODE_ENV || 'prod';
                console.log('bundle ', bundle, ' vs ', pid, " => ", process.pid);

                //console.log("got exit code ", "("+code+")", pid, " VS ", pid, " <=> geena: ", process.pid);
                //code = code || 0;
                //var obj = logger.emerg('geena', 'UTILS:EMERG1', 'process exit code ' + code);
                if (code == 0  && env != "debug" && env != "dev"/***/) {
                    // First child.
                    dismiss(pid);
                    // Then master.
                    dismiss(process.pid);
                }
            });

            proc.on('SIGHUP', function(code){
                console.log("Hanging up !", process.argv);

                var bundle = process.argv[3];
                var env =  process.env.NODE_ENV || 'prod';
                var pid = _this.getPidByBundleName(bundle);

                dismiss(pid);
                dismiss(process.pid);
            });

//            proc.stderr.resume();
//            proc.stderr.setEncoding('utf8');//Set encoding.
//            proc.stderr.on('data', function(err){
//                console.error("found err ", err);
//            });
        }
    };

    var dismiss = function(pid){
        if (pid == undefined) {
            var pid = _this.PID;
        }
        var bundleName = _this.getBundleNameByPid(pid);
        var path = _(_this.path + pid);

        fs.unlinkSync(path);
        if (bundleName != undefined) {
            fs.unlinkSync( _(getPath('mountPath') + '/' + bundleName) );
        }
        process.kill(pid, "SIGKILL");
    };

    /**
     * Save PID file
     * @param {string} bundle
     * @param {integer} PID Id of the PID to save
     *
     * @private
     * */
    var save = function(){
        var bundle = _this.bundle;
        var PID = _this.PID;
        var proc = _this.proc;
        var path = _this.path
        //Get PID path.
        if (
            typeof(bundle) != "undefined" && bundle != ""
            && typeof(PID) != "undefined" && PID != "" && PID != null
            && typeof(proc) != "undefined" && proc != "" && proc != null
        ) {
            var fileStream = fs.createWriteStream(path + PID);
            fileStream.once('open', function(fd) {
                fileStream.write(bundle);
                fileStream.end();
            });
        }
    };

    /**
     * Get PID
     * @param {string} bundle
     * @return {number} PID
     * */
    this.getPID = function(){

        try{
            return _this.PID;
        } catch (err) {
            logger.error(
                'geena',
                'UTILS:PROC:ERR:2',
                'Could not get PID for bundle: '+ _this.bundle,
                __stack
            );
            return null;
        }
    };

    this.getBundleNameByPid = function(pid){
        var list = process.list;
        console.log("list ", list, ':',  list[pid]);
        if ( typeof(list[pid]) != "undefined")
            return list[pid]
        else
            return undefined
    };

    this.getPidByBundleName = function(bundle){
        var list = process.pids;
        console.log("list ", list, ':',  list[bundle]);
        if ( typeof(list[bundle]) != "undefined")
            return list[bundle]
        else
            return undefined
    };

    this.setMaster = function(bool){
        if ( typeof(bool) == 'undefined' || bool == true) {
            _this.master = true;
        } else {
            _this.master = false;
        }
    };

    this.register = function(bundle, pid) {
        if ( bundle != 'geena' && _this.bundles.indexOf(bundle) == -1 ) {
            _this.bundles.push(bundle);
            process.list[pid] = bundle;
            process.pids[bundle] = pid;
        }
    };

    //Init.
    if ( typeof(this.bundle) == "undefined" ) {
        logger.warn(
            'geena',
            'UTILS:PROC:WARN:1',
            'Invalid or undefined proc name . Proc naming Aborted',
            __stack
        );
    } else {
        init();
    }
};

module.exports = Proc;<commit_msg>Added final error message for proc exit<commit_after>/* Geena.utils.Proc
 *
 * This file is part of the geena package.
 * Copyright (c) 2014 Rhinostone <geena@rhinostone.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 *
 * { name: 'SIGABRT', action: 'A', desc: 'Process abort signal.' },
 * { name: 'SIGALRM', action: 'T', desc: 'Alarm clock.' },
 * { name: 'SIGBUS', action: 'A', desc: 'Access to an undefined portion of a memory object.' },
 * { name: 'SIGCHLD', action: 'I', desc: 'Child process terminated, stopped, or continued. ' },
 * { name: 'SIGCONT', action: 'C', desc: 'Continue executing, if stopped.' },
 * { name: 'SIGFPE', action: 'A', desc: 'Erroneous arithmetic operation.' },
 * { name: 'SIGHUP', action: 'T', desc: 'Hangup.' },
 * { name: 'SIGILL', action: 'A', desc: 'Illegal instruction.' },
 * { name: 'SIGINT', action: 'T', desc: 'Terminal interrupt signal.' },
 * { name: 'SIGKILL', action: 'T', desc: 'Kill (cannot be caught or ignored).' },
 * { name: 'SIGPIPE', action: 'T', desc: 'Write on a pipe with no one to read it.' },
 * { name: 'SIGQUIT', action: 'A', desc: 'Terminal quit signal.' },
 * { name: 'SIGSEGV', action: 'A', desc: 'Invalid memory reference.' },
 * { name: 'SIGSTOP', action: 'S', desc: 'Stop executing (cannot be caught or ignored).' },
 * { name: 'SIGTERM', action: 'T', desc: 'Termination signal.' },
 * { name: 'SIGTSTP', action: 'S', desc: 'Terminal stop signal.' },
 * { name: 'SIGTTIN', action: 'S', desc: 'Background process attempting read.' },
 * { name: 'SIGTTOU', action: 'S', desc: 'Background process attempting write.' },
 * { name: 'SIGUSR1', action: 'T', desc: 'User-defined signal 1.' },
 * { name: 'SIGUSR2', action: 'T', desc: 'User-defined signal 2.' },
 * { name: 'SIGPOLL', action: 'T', desc: 'Pollable event. ' },
 * { name: 'SIGPROF', action: 'T', desc: 'Profiling timer expired. ' },
 * { name: 'SIGSYS', action: 'A', desc: 'Bad system call.' },
 * { name: 'SIGTRAP', action: 'A', desc: 'Trace/breakpoint trap. ' },
 * { name: 'SIGURG', action: 'I', desc: 'High bandwidth data is available at a socket.' },
 * { name: 'SIGVTALRM', action: 'T', desc: 'Virtual timer expired.' },
 * { name: 'SIGXCPU', action: 'A', desc: 'CPU time limit exceeded.' },
 * { name: 'SIGXFSZ', action: 'A', desc: 'File size limit exceeded. ' }
 * */
var Proc;

//Imports
var fs      = require('fs');
var logger  = require( _(__dirname + '/logger') );
var spawn = require('child_process').spawn;

/**
 * @constructor
 *
 * @param {string} bundle
 *
 * */
Proc = function(bundle, proc, usePidFile){

    var _this   = this;
    this.PID    = null;
    this.path   = null;
    this.master = false;//used only by master.
    this.bundle = bundle;
    this.proc   = proc;
    this.bundles = [];

    if ( typeof(usePidFile) == 'undefined') {
        var usePidFile = true;
    }

    /**
     * Check target path
     * @param {string} path
     * @param {integer} PID Id of the PID to save
     * */

    var init = function(){
        //Default.
        var pathObj = new _( getPath('root') + '/tmp/pid/' );
        var path = pathObj.toString();
//        console.log('looking for path ', getPath('root') + "/tmp/pid/" );
//        console.log("init with path ...", path, " - BUNDLE : ", bundle );
//        console.log("about to create PID file under ", path, "["+bundle+"]");
        //Create dir if needed.
        console.log("MKDIR  pathObj (pid:"+_this.proc.pid+") - ", _this.bundle);
        process.list = (process.list == undefined) ? {} : process.list;
        process.pids = (process.pids == undefined) ? {} : process.pids;

        _this.register(_this.bundle, _this.proc.pid);
        console.log('registring ', _this.proc.pid);
        if (usePidFile) {
            pathObj.mkdir( function(err, path){
                console.log('path created ('+path+') now saving PID ' +  bundle);
                //logger.info('geena', 'PROC:INFO:1', 'path created ('+path+') now saving PID ' +  bundle, __stack);
                //Save file.
                if (!err) {
                    _this.PID = _this.proc.pid;
                    _this.path = path + pathObj.sep;
                    //Add PID file.
                    setPID(_this.bundle, _this.PID, _this.proc);
                    save(_this.bundle, _this.PID, _this.proc);
                }
            });
        }
    };

    var isMaster = function(){
        return (_this.master) ? true : false;
    };
    /**
     * Going to force restart by third party (kill 9).
     *
     * @param {string} bundle
     * @param {string} env
     * @param {number} pid
     *
     * @callback callback
     * @param {boolean|string} err
     * */
    var respawn = function(bundle, env, pid, callback){
        console.log("Exiting and re spawning : ", bundle, env);
        if (env == 'prod') {//won't loop forever for others env.
            // TODO - Count the restarts and prevent unilimited loop
            // TODO - Send notification to admin or/and root to the Fatal Error Page.

            var root = getPath('root');
            try {
                var version = process.getVersion(bundle);
            } catch (err) {
                var bundle = process.argv[3];
                console.log("Bundle ", bundle," already running...");
                dismiss(process.pid);
            }

            var outPath = _(root + '/out.'+bundle+'.'+version+'.log');
            var errPath = _(root + '/out.'+bundle+'.'+version+'.log');
            var nodePath = getPath('node');
            var geenaPath = _(root + '/geena');

            var opt = process.getShutdownConnectorSync();
            //Should kill existing one..
            opt.path = '/'+bundle + '/restart/'+ pid +'/' + env;

            var HttpClient = require('geena.com').Http;
            var httpClient = new HttpClient();

            if (httpClient) {
                //httpClient.query(opt);
                //We are not waiting for anything particular...do we ?
                httpClient.query(opt, function(err, msg){
                    //Now start new bundle.
                    callback(err);
                });
            } else {
                var err = new Error('No shutdown connector found.');
                console.error(err);
                callback(err);
            }
        } else {
            callback(false);
        }
    };

    var setPID = function(bundle, PID, proc){

        if (bundle != 'geena') {
            proc.title = 'geena: '+ bundle;
        } else {
            proc.title = bundle;
        }

        //Set event.
        setDefaultEvents(bundle, PID, proc);
    };

    var setDefaultEvents = function(bundle, PID, proc){

        if ( typeof(PID) != "undefined" && typeof(PID) == "number" ) {
            console.log("setting listeners for ", PID, ':', bundle);

            proc.dismiss = dismiss;
            proc.isMaster = isMaster;

            proc.on('SIGTERM', function(code){
                proc.exit(code);
            });

            proc.on('SIGINT', function(code){

                if (code == undefined) var code = 0;
                console.log("got exit code ", code, process.list);
                proc.exit(code);//tigger exit event.
            });

            //Will prevent the server from stopping.
            proc.on('uncaughtException', function(err){

                logger.exception('geena', 'FATAL_EXCEPTION:1', 'Special care needed !! ' + err + err.stack, function(err){
                    //TODO - Send an email to the administrator/dev
                    //TODO - Have a delegate handler to allow the dev to do its stuff. Maybe it's already there if any dev can override.
                    console.log('Fix your shit...');
                });
                console.log(err.stack);
                var bundle = process.argv[3];
                var pid = _this.getPidByBundleName(bundle);

                var env =  process.env.NODE_ENV || 'prod';
                //Wake up buddy !.
                respawn(bundle, env, pid, function(err){
                    proc.exit(1);
                });

            });

            proc.on('exit', function(code){

                if ( typeof(code) == 'undefined') {
                    code = 0;
                }

                var bundle = process.argv[3];
                console.log("@=>", _this.args);
                var pid = _this.getPidByBundleName(bundle);
                var env =  process.env.NODE_ENV || 'prod';
                console.log('bundle ', bundle, ' vs ', pid, " => ", process.pid);

                //console.log("got exit code ", "("+code+")", pid, " VS ", pid, " <=> geena: ", process.pid);
                //code = code || 0;
                //var obj = logger.emerg('geena', 'UTILS:EMERG1', 'process exit code ' + code);
                if (code == 0  && env != "debug" && env != "dev"/***/) {
                    // First child.
                    dismiss(pid);
                    // Then master.
                    dismiss(process.pid);
                }
            });

            proc.on('SIGHUP', function(code){
                console.log("Hanging up !", process.argv);

                var bundle = process.argv[3];
                var env =  process.env.NODE_ENV || 'prod';
                var pid = _this.getPidByBundleName(bundle);

                dismiss(pid);
                dismiss(process.pid);
            });

//            proc.stderr.resume();
//            proc.stderr.setEncoding('utf8');//Set encoding.
//            proc.stderr.on('data', function(err){
//                console.error("found err ", err);
//            });
        }
    };

    var dismiss = function(pid){
        if (pid == undefined) {
            var pid = _this.PID;
        }
        var bundleName = _this.getBundleNameByPid(pid);
        var path = _(_this.path + pid);
        try {
            fs.unlinkSync(path);
            if (bundleName != undefined) {
                fs.unlinkSync( _(getPath('mountPath') + '/' + bundleName) );
            }
        } catch (err) {
            console.log('Final : ', err.stack)
            //Means that it does not exists anymore.
        }

        process.kill(pid, "SIGKILL");
    };

    /**
     * Save PID file
     * @param {string} bundle
     * @param {integer} PID Id of the PID to save
     *
     * @private
     * */
    var save = function(){
        var bundle = _this.bundle;
        var PID = _this.PID;
        var proc = _this.proc;
        var path = _this.path
        //Get PID path.
        if (
            typeof(bundle) != "undefined" && bundle != ""
            && typeof(PID) != "undefined" && PID != "" && PID != null
            && typeof(proc) != "undefined" && proc != "" && proc != null
        ) {
            var fileStream = fs.createWriteStream(path + PID);
            fileStream.once('open', function(fd) {
                fileStream.write(bundle);
                fileStream.end();
            });
        }
    };

    /**
     * Get PID
     * @param {string} bundle
     * @return {number} PID
     * */
    this.getPID = function(){

        try{
            return _this.PID;
        } catch (err) {
            logger.error(
                'geena',
                'UTILS:PROC:ERR:2',
                'Could not get PID for bundle: '+ _this.bundle,
                __stack
            );
            return null;
        }
    };

    this.getBundleNameByPid = function(pid){
        var list = process.list;
        console.log("list ", list, ':',  list[pid]);
        if ( typeof(list[pid]) != "undefined")
            return list[pid]
        else
            return undefined
    };

    this.getPidByBundleName = function(bundle){
        var list = process.pids;
        console.log("list ", list, ':',  list[bundle]);
        if ( typeof(list[bundle]) != "undefined")
            return list[bundle]
        else
            return undefined
    };

    this.setMaster = function(bool){
        if ( typeof(bool) == 'undefined' || bool == true) {
            _this.master = true;
        } else {
            _this.master = false;
        }
    };

    this.register = function(bundle, pid) {
        if ( bundle != 'geena' && _this.bundles.indexOf(bundle) == -1 ) {
            _this.bundles.push(bundle);
            process.list[pid] = bundle;
            process.pids[bundle] = pid;
        }
    };

    //Init.
    if ( typeof(this.bundle) == "undefined" ) {
        logger.warn(
            'geena',
            'UTILS:PROC:WARN:1',
            'Invalid or undefined proc name . Proc naming Aborted',
            __stack
        );
    } else {
        init();
    }
};

module.exports = Proc;<|endoftext|>


<commit_before>// ==UserScript==
// @name        studis-online
// @namespace   studis-online.de
// @include     http://*.studis-online.de/Fragen-Brett/*
// @require     https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js
// @version     1
// @grant       none
// ==/UserScript==

$.noConflict(); // Konflikte mit Beitragseditor vermeiden

var Page = new Page();
var ThreadOverview = new ThreadOverview();
var Thread = new Thread();
var Post = new Post();

$(document).ready(function() {
    fillPostSubjectIfEmpty();
    keepPrivateMessages();
    removeCurrentNews();
    removeMarkAsReadedLinks();
    removePagingText();
    reducePagingWidth();
    insertLetterToMarkThreadAsRead();
    insertDeleteQuoteButtons();
    scaleImageWidthInThreads();
});

function ThreadOverview() {
    this.markAsReadedLinks = $('a[title~="Punkte)"]');
    this.forumTable = $('.ston-forumtab');
    this.redDotElements = this.forumTable.find("span[title='Neu']");
}

function Page() {
    this.pagingElements = $('.ston-f-paging');

    // Ob es sich um die Thread-Übersicht-Seite handelt
    this.isThreadOverview = function() {
        return window.location.pathname === '/Fragen-Brett/list.php';
    };

    // Ob es sich um die Private-Message-(Senden)-Seite handelt
    // FIXME: True auf der PrivateMessageOverview
    this.isPrivateMessage = function() {
        //return $('form[action="http://www.studis-online.de/Fragen-Brett/pm.php"]').length === 1;
        return window.location.pathname === '/Fragen-Brett/pm.php';
    };
}

function Thread() {
    this.textblockElements = $('.ston-f-textblock');
    this.markAsReadedLinks = $('a[title~="Punkte)"]');
}

function Post() {
    this.bodyElement = $('#post-body');
    this.subjectInput = $('#phorum_subject');
    this.deleteQuoteButtonWidth = 16;
    this.deleteQuoteButtonHTML = '';
    this.keepPrivateMessageCheckbox = $('input[name="keep"]');

    // Funktion auf allen Quotes ausführen
    this.doForEachQuote = function(forEach) { return this.bodyElement.find('blockquote').each(forEach); };

    // Lösch-Button zu allen Zitaten hinzufügen
    this.addDeleteQuoteButtons = function() {
      this.doForEachQuote(function() {
          var postQuoteElement = $(this);
          Post.addDeleteQuoteButton(postQuoteElement);
      });
    }

    // Lösch-Button zu einem Zitat hinzufügen
    this.addDeleteQuoteButton = function(blockquote) {
       var deleteQuoteElements = blockquote.find('.gston-delete-quote');

       if(deleteQuoteElements.length === 0) {
          var position = blockquote.offset().left - this.bodyElement.offset().left + blockquote.innerWidth() - this.deleteQuoteButtonWidth - 5;
          var deleteButtonElement = $(this.deleteQuoteButtonHTML);

          deleteButtonElement.click(function() {
             blockquote.remove();
          });

          blockquote.children().first().prepend(deleteButtonElement);
       }
    };

}

// Füllt den Betreff eines Posts, falls leer
function fillPostSubjectIfEmpty() {
    if(Post.subjectInput.length > 0) {
       let threadSubject = Post.subjectInput.attr('value');
       Post.subjectInput.parent().find('span').text(threadSubject);
    }
}

// Gesendete Nachrichten speichern
function keepPrivateMessages() {
    if(Page.isPrivateMessage()) {
       Post.keepPrivateMessageCheckbox.click();
    }
}

// Entfernt die aktuellen Meldungen aus der Thread-Übersicht
function removeCurrentNews() {
    // TODO Bundle and remove at once
    var newsElement = $('.ston-klein').filter(function() { return $(this).text().indexOf('Aktuelle Meldungen') === 0});
    newsElement.prev().remove(); //

    newsElement.next().remove(); //

    newsElement.next().remove(); //

    newsElement.remove(); // news
}

// Entfernt den Hinweistext, auf welcher Seite man sich befindet => 'Seite 1 von 24'
function removePagingText() {
    Page.pagingElements.each(function() {
       let pagingCountTextElement = $(this).children().first();
       if(pagingCountTextElement.text().indexOf('Seite') === 0) {
            pagingCountTextElement.remove();
       }
    });
}

// Zeilenumbruch beim Verkleinern des Browsers weiter hinaus zögern
function reducePagingWidth() {
    Page.pagingElements.each(function() {
       $(this).children().last().css('margin-right', '0px');
    });
}

// Entfernt Thema als Gelesen Markieren in Threads
function removeMarkAsReadedLinks() {
    ThreadOverview.markAsReadedLinks.each(function() {
       $(this).remove();
    });

    Thread.markAsReadedLinks.each(function() {
        $(this).remove();
    })
}

// Ersetzt "rote Punkte" (== ungelesen) durch Briefe, welche beim Klick, den Thread als gelesen markieren
function insertLetterToMarkThreadAsRead() {
    if(Page.isThreadOverview()) {
       var redDotElements = ThreadOverview.redDotElements;

       redDotElements.each(function() {
           var redDotElement = $(this);
           var threadLinkElement = redDotElement.parent();
           var unreadedThreadImageElement = $('');
           unreadedThreadImageElement.click(function() {
               var markThreadReadHref = threadLinkElement.attr('href') + ',markthreadread';
               $.ajax({url: markThreadReadHref, success: function(result) {
                  unreadedThreadImageElement.remove();
               }});
           });
           threadLinkElement.before(unreadedThreadImageElement);
           redDotElement.remove();
       });
    } else {
       console.warn("Es gibt mehr als eine Threadübersicht.");
    }
}

// Button zum Löschen von Zitaten
function insertDeleteQuoteButtons() {
    Post.addDeleteQuoteButtons();
    Post.bodyElement.bind("DOMSubtreeModified", function() {
       Post.addDeleteQuoteButtons();
    })
}

// Breite der Bilder in Beiträgen an die Fenstergröße anpassen
// .ston-f-textblock img { max-width: 100%};
function scaleImageWidthInThreads() {
    var images = Thread.textblockElements.find('img');

    images.each(function() {
        $(this).css('max-width', '100%');
    });
}
<commit_msg>features added<commit_after>// ==UserScript==
// @name        studis-online
// @namespace   studis-online.de
// @include     http://*.studis-online.de/Fragen-Brett/*
// @require     https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js
// @version     1
// @grant       none
// ==/UserScript==

$.noConflict(); // Konflikte mit Beitragseditor vermeiden

var Page = new Page();
var ThreadOverview = new ThreadOverview();
var Thread = new Thread();
var Post = new Post();
var SidePanel = new SidePanel();

$(document).ready(function() {
    embedYoutubeLinks();
    cleanUpThreadOverviewTitle();
    fillPostSubjectIfEmpty();
    keepPrivateMessages();
    removeCurrentNews();
    removeFirstPagingInThreadOverview();
    removeMarkAsReadedLinks();
    removePagingText();
    reducePagingWidth();
    insertLetterToMarkThreadAsRead();
    insertDeleteQuoteButtons();
    scaleImageWidthInThreads();
});

function ThreadOverview() {
    this.markAsReadedLinks = $('a[title~="Punkte)"]');
    this.forumTable = $('.ston-forumtab');
    this.redDotElements = this.forumTable.find("span[title='Neu']");
    this.newCreateThreadButton = function() {
        return $('Neues Thema');
    }
}

function Page() {
    this.pagingElements = $('.ston-f-paging');

    // Ob es sich um die Thread-Übersicht-Seite handelt
    this.isThreadOverview = function() {
        return window.location.pathname === '/Fragen-Brett/list.php';
    };

    // Ob es sich um die Private-Message-(Senden)-Seite handelt
    // FIXME: True auf der PrivateMessageOverview
    this.isPrivateMessage = function() {
        //return $('form[action="http://www.studis-online.de/Fragen-Brett/pm.php"]').length === 1;
        return window.location.pathname === '/Fragen-Brett/pm.php';
    };
}

function Thread() {
    this.textblockElements = $('.ston-f-textblock');
    this.markAsReadedLinks = $('a[title~="Punkte)"]');
    this.firstLevelYoutubeLinks = $('.ston-f-textblock > a[href*="youtube.com/watch?"]');
}

function Post() {
    this.bodyElement = $('#post-body');
    this.subjectInput = $('#phorum_subject');
    this.deleteQuoteButtonWidth = 16;
    this.deleteQuoteButtonHTML = '';
    this.keepPrivateMessageCheckbox = $('input[name="keep"]');

    // Funktion auf allen Quotes ausführen
    this.doForEachQuote = function(forEach) { return this.bodyElement.find('blockquote').each(forEach); };

    // Lösch-Button zu allen Zitaten hinzufügen
    this.addDeleteQuoteButtons = function() {
      this.doForEachQuote(function() {
          var postQuoteElement = $(this);
          Post.addDeleteQuoteButton(postQuoteElement);
      });
    }

    // Lösch-Button zu einem Zitat hinzufügen
    this.addDeleteQuoteButton = function(blockquote) {
       var deleteQuoteElements = blockquote.find('.gston-delete-quote');

       if(deleteQuoteElements.length === 0) {
          var position = blockquote.offset().left - this.bodyElement.offset().left + blockquote.innerWidth() - this.deleteQuoteButtonWidth - 5;
          var deleteButtonElement = $(this.deleteQuoteButtonHTML);

          deleteButtonElement.click(function() {
             blockquote.remove();
          });

          blockquote.children().first().prepend(deleteButtonElement);
       }
    };
}

function SidePanel() {
    this.buttons = $('#ston-sp-buttons');
    this.writeButton = this.buttons.find('a[href*="Fragen-Brett/posting.php?"]');
}

// Ersetzt die obere Seitennavigation durch "Neues Thema"-Button
function removeFirstPagingInThreadOverview() { // TODO: function name
    if(Page.isThreadOverview()) {
        var firstPagingElement = Page.pagingElements.first();
        firstPagingElement.before(ThreadOverview.newCreateThreadButton());
        firstPagingElement.remove();
    }
}

// Entfernt die Angabe der Seitenanzahl aus dem Title
// Entfernt den den Text "Unterform" aus der Thread Übersicht
// TODO: Für Threads und Unterordner übernehmen
function cleanUpThreadOverviewTitle() {
    if(Page.isThreadOverview()) {
        var title = $('h1');
        var topTitle = $('.ston-spitz');
        topTitle.remove();
        title.addClass('ston-farbe');
        title.text(title.text().substring(0, title.text().indexOf('[') - 1));
    }
}

// Ersetzt Youtube-Links durch Youtube-Player
function embedYoutubeLinks() {
    Thread.firstLevelYoutubeLinks.each(function() {
        var youtubeLink = $(this);
        var youtubeEmbeddedSource = 'https://youtube.com/embed/' + youtubeLink.attr('href').substring(youtubeLink.attr('href').indexOf('watch?v=') + 8);
        var youtubeEmbeddedIFrame = $('

');
        youtubeLink.before(youtubeEmbeddedIFrame);
        youtubeLink.remove();
    });
}

// Füllt den Betreff eines Posts, falls leer
function fillPostSubjectIfEmpty() {
    if(Post.subjectInput.length > 0) {
       let threadSubject = Post.subjectInput.attr('value');
       Post.subjectInput.parent().find('span').text(threadSubject);
    }
}

// Gesendete Nachrichten speichern
function keepPrivateMessages() {
    if(Page.isPrivateMessage()) {
       Post.keepPrivateMessageCheckbox.click();
    }
}

// Entfernt die aktuellen Meldungen aus der Thread-Übersicht
function removeCurrentNews() {
    // TODO Bundle and remove at once
    var newsElement = $('.ston-klein').filter(function() { return $(this).text().indexOf('Aktuelle Meldungen') === 0});
    newsElement.prev().remove(); //

    newsElement.next().remove(); //

    newsElement.next().remove(); //

    newsElement.remove(); // news
}

// Entfernt den Hinweistext, auf welcher Seite man sich befindet => 'Seite 1 von 24'
function removePagingText() {
    Page.pagingElements.each(function() {
       let pagingCountTextElement = $(this).children().first();
       if(pagingCountTextElement.text().indexOf('Seite') === 0) {
            pagingCountTextElement.remove();
       }
    });
}

// Zeilenumbruch beim Verkleinern des Browsers weiter hinaus zögern
function reducePagingWidth() {
    Page.pagingElements.each(function() {
       $(this).children().last().css('margin-right', '0px');
    });
}

// Entfernt Thema als Gelesen Markieren in Threads
function removeMarkAsReadedLinks() {
    ThreadOverview.markAsReadedLinks.each(function() {
       $(this).remove();
    });

    Thread.markAsReadedLinks.each(function() {
        $(this).remove();
    })
}

// Ersetzt "rote Punkte" (== ungelesen) durch Briefe, welche beim Klick, den Thread als gelesen markieren
function insertLetterToMarkThreadAsRead() {
    if(Page.isThreadOverview()) {
       var redDotElements = ThreadOverview.redDotElements;

       redDotElements.each(function() {
           var redDotElement = $(this);
           var threadLinkElement = redDotElement.parent();
           var unreadedThreadImageElement = $('');
           unreadedThreadImageElement.click(function() {
               var markThreadReadHref = threadLinkElement.attr('href') + ',markthreadread';
               $.ajax({url: markThreadReadHref, success: function(result) {
                  unreadedThreadImageElement.remove();
               }});
           });
           threadLinkElement.before(unreadedThreadImageElement);
           redDotElement.remove();
       });
    } else {
       console.warn("Es gibt mehr als eine Threadübersicht.");
    }
}

// Button zum Löschen von Zitaten
function insertDeleteQuoteButtons() {
    Post.addDeleteQuoteButtons();
    Post.bodyElement.bind("DOMSubtreeModified", function() {
       Post.addDeleteQuoteButtons();
    })
}

// Breite der Bilder in Beiträgen an die Fenstergröße anpassen
// .ston-f-textblock img { max-width: 100%};
function scaleImageWidthInThreads() {
    var images = Thread.textblockElements.find('img');

    images.each(function() {
        $(this).css('max-width', '100%');
    });
}
<|endoftext|>


<commit_before>CodeMirror.defineMode("go", function(config) {
  var indentUnit = config.indentUnit;

  var keywords = {
    "break":true, "case":true, "chan":true, "const":true, "continue":true,
    "default":true, "defer":true, "else":true, "fallthrough":true, "for":true,
    "func":true, "go":true, "goto":true, "if":true, "import":true,
    "interface":true, "map":true, "package":true, "range":true, "return":true,
    "select":true, "struct":true, "switch":true, "type":true, "var":true,
    "bool":true, "byte":true, "complex64":true, "complex128":true,
    "float32":true, "float64":true, "int8":true, "int16":true, "int32":true,
    "int64":true, "string":true, "uint8":true, "uint16":true, "uint32":true,
    "uint64":true, "int":true, "uint":true, "uintptr":true
  };

  var atoms = {
    "true":true, "false":true, "iota":true, "nil":true, "append":true,
    "cap":true, "close":true, "complex":true, "copy":true, "imag":true,
    "len":true, "make":true, "new":true, "panic":true, "print":true,
    "println":true, "real":true, "recover":true
  };

  var isOperatorChar = /[+\-*&^%:=<>!|\/]/;

  var curPunc;

  function tokenBase(stream, state) {
    var ch = stream.next();
    if (ch == '"' || ch == "'" || ch == "`") {
      state.tokenize = tokenString(ch);
      return state.tokenize(stream, state);
    }
    if (/[\d\.]/.test(ch)) {
      if (ch == ".") {
        stream.match(/^[0-9]+([eE][\-+]?[0-9]+)?/);
      } else if (ch == "0") {
        stream.match(/^[xX][0-9a-fA-F]+/) || stream.match(/^0[0-7]+/);
      } else {
        stream.match(/^[0-9]*\.?[0-9]*([eE][\-+]?[0-9]+)?/);
      }
      return "number";
    }
    if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
      curPunc = ch;
      return null;
    }
    if (ch == "/") {
      if (stream.eat("*")) {
        state.tokenize = tokenComment;
        return tokenComment(stream, state);
      }
      if (stream.eat("/")) {
        stream.skipToEnd();
        return "comment";
      }
    }
    if (isOperatorChar.test(ch)) {
      stream.eatWhile(isOperatorChar);
      return "operator";
    }
    stream.eatWhile(/[\w\$_]/);
    var cur = stream.current();
    if (keywords.propertyIsEnumerable(cur)) {
      if (cur == "case" || cur == "default") curPunc = "case";
      return "keyword";
    }
    if (atoms.propertyIsEnumerable(cur)) return "atom";
    return "variable";
  }

  function tokenString(quote) {
    return function(stream, state) {
      var escaped = false, next, end = false;
      while ((next = stream.next()) != null) {
        if (next == quote && !escaped) {end = true; break;}
        escaped = !escaped && next == "\\";
      }
      if (end || !(escaped || quote == "`"))
        state.tokenize = tokenBase;
      return "string";
    };
  }

  function tokenComment(stream, state) {
    var maybeEnd = false, ch;
    while (ch = stream.next()) {
      if (ch == "/" && maybeEnd) {
        state.tokenize = tokenBase;
        break;
      }
      maybeEnd = (ch == "*");
    }
    return "comment";
  }

  function Context(indented, column, type, align, prev) {
    this.indented = indented;
    this.column = column;
    this.type = type;
    this.align = align;
    this.prev = prev;
  }
  function pushContext(state, col, type) {
    return state.context = new Context(state.indented, col, type, null, state.context);
  }
  function popContext(state) {
    var t = state.context.type;
    if (t == ")" || t == "]" || t == "}")
      state.indented = state.context.indented;
    return state.context = state.context.prev;
  }

  // Interface

  return {
    startState: function(basecolumn) {
      return {
        tokenize: null,
        context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
        indented: 0,
        startOfLine: true
      };
    },

    token: function(stream, state) {
      var ctx = state.context;
      if (stream.sol()) {
        if (ctx.align == null) ctx.align = false;
        state.indented = stream.indentation();
        state.startOfLine = true;
        if (ctx.type == "case") ctx.type = "}";
      }
      if (stream.eatSpace()) return null;
      curPunc = null;
      var style = (state.tokenize || tokenBase)(stream, state);
      if (style == "comment") return style;
      if (ctx.align == null) ctx.align = true;

      if (curPunc == "{") pushContext(state, stream.column(), "}");
      else if (curPunc == "[") pushContext(state, stream.column(), "]");
      else if (curPunc == "(") pushContext(state, stream.column(), ")");
      else if (curPunc == "case") ctx.type = "case";
      else if (curPunc == "}" && ctx.type == "}") ctx = popContext(state);
      else if (curPunc == ctx.type) popContext(state);
      state.startOfLine = false;
      return style;
    },

    indent: function(state, textAfter) {
      if (state.tokenize != tokenBase && state.tokenize != null) return 0;
      var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
      if (ctx.type == "case" && /^(?:case|default)\b/.test(textAfter)) {
        state.context.type = "}";
        return ctx.indented;
      }
      var closing = firstChar == ctx.type;
      if (ctx.align) return ctx.column + (closing ? 0 : 1);
      else return ctx.indented + (closing ? 0 : indentUnit);
    },

    electricChars: "{}:",
    blockCommentStart: "/*",
    blockCommentEnd: "*/",
    lineComment: "//"
  };
});

CodeMirror.defineMIME("text/x-go", "go");
<commit_msg>[go mode] Add ')' as electric character.<commit_after>CodeMirror.defineMode("go", function(config) {
  var indentUnit = config.indentUnit;

  var keywords = {
    "break":true, "case":true, "chan":true, "const":true, "continue":true,
    "default":true, "defer":true, "else":true, "fallthrough":true, "for":true,
    "func":true, "go":true, "goto":true, "if":true, "import":true,
    "interface":true, "map":true, "package":true, "range":true, "return":true,
    "select":true, "struct":true, "switch":true, "type":true, "var":true,
    "bool":true, "byte":true, "complex64":true, "complex128":true,
    "float32":true, "float64":true, "int8":true, "int16":true, "int32":true,
    "int64":true, "string":true, "uint8":true, "uint16":true, "uint32":true,
    "uint64":true, "int":true, "uint":true, "uintptr":true
  };

  var atoms = {
    "true":true, "false":true, "iota":true, "nil":true, "append":true,
    "cap":true, "close":true, "complex":true, "copy":true, "imag":true,
    "len":true, "make":true, "new":true, "panic":true, "print":true,
    "println":true, "real":true, "recover":true
  };

  var isOperatorChar = /[+\-*&^%:=<>!|\/]/;

  var curPunc;

  function tokenBase(stream, state) {
    var ch = stream.next();
    if (ch == '"' || ch == "'" || ch == "`") {
      state.tokenize = tokenString(ch);
      return state.tokenize(stream, state);
    }
    if (/[\d\.]/.test(ch)) {
      if (ch == ".") {
        stream.match(/^[0-9]+([eE][\-+]?[0-9]+)?/);
      } else if (ch == "0") {
        stream.match(/^[xX][0-9a-fA-F]+/) || stream.match(/^0[0-7]+/);
      } else {
        stream.match(/^[0-9]*\.?[0-9]*([eE][\-+]?[0-9]+)?/);
      }
      return "number";
    }
    if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
      curPunc = ch;
      return null;
    }
    if (ch == "/") {
      if (stream.eat("*")) {
        state.tokenize = tokenComment;
        return tokenComment(stream, state);
      }
      if (stream.eat("/")) {
        stream.skipToEnd();
        return "comment";
      }
    }
    if (isOperatorChar.test(ch)) {
      stream.eatWhile(isOperatorChar);
      return "operator";
    }
    stream.eatWhile(/[\w\$_]/);
    var cur = stream.current();
    if (keywords.propertyIsEnumerable(cur)) {
      if (cur == "case" || cur == "default") curPunc = "case";
      return "keyword";
    }
    if (atoms.propertyIsEnumerable(cur)) return "atom";
    return "variable";
  }

  function tokenString(quote) {
    return function(stream, state) {
      var escaped = false, next, end = false;
      while ((next = stream.next()) != null) {
        if (next == quote && !escaped) {end = true; break;}
        escaped = !escaped && next == "\\";
      }
      if (end || !(escaped || quote == "`"))
        state.tokenize = tokenBase;
      return "string";
    };
  }

  function tokenComment(stream, state) {
    var maybeEnd = false, ch;
    while (ch = stream.next()) {
      if (ch == "/" && maybeEnd) {
        state.tokenize = tokenBase;
        break;
      }
      maybeEnd = (ch == "*");
    }
    return "comment";
  }

  function Context(indented, column, type, align, prev) {
    this.indented = indented;
    this.column = column;
    this.type = type;
    this.align = align;
    this.prev = prev;
  }
  function pushContext(state, col, type) {
    return state.context = new Context(state.indented, col, type, null, state.context);
  }
  function popContext(state) {
    var t = state.context.type;
    if (t == ")" || t == "]" || t == "}")
      state.indented = state.context.indented;
    return state.context = state.context.prev;
  }

  // Interface

  return {
    startState: function(basecolumn) {
      return {
        tokenize: null,
        context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
        indented: 0,
        startOfLine: true
      };
    },

    token: function(stream, state) {
      var ctx = state.context;
      if (stream.sol()) {
        if (ctx.align == null) ctx.align = false;
        state.indented = stream.indentation();
        state.startOfLine = true;
        if (ctx.type == "case") ctx.type = "}";
      }
      if (stream.eatSpace()) return null;
      curPunc = null;
      var style = (state.tokenize || tokenBase)(stream, state);
      if (style == "comment") return style;
      if (ctx.align == null) ctx.align = true;

      if (curPunc == "{") pushContext(state, stream.column(), "}");
      else if (curPunc == "[") pushContext(state, stream.column(), "]");
      else if (curPunc == "(") pushContext(state, stream.column(), ")");
      else if (curPunc == "case") ctx.type = "case";
      else if (curPunc == "}" && ctx.type == "}") ctx = popContext(state);
      else if (curPunc == ctx.type) popContext(state);
      state.startOfLine = false;
      return style;
    },

    indent: function(state, textAfter) {
      if (state.tokenize != tokenBase && state.tokenize != null) return 0;
      var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
      if (ctx.type == "case" && /^(?:case|default)\b/.test(textAfter)) {
        state.context.type = "}";
        return ctx.indented;
      }
      var closing = firstChar == ctx.type;
      if (ctx.align) return ctx.column + (closing ? 0 : 1);
      else return ctx.indented + (closing ? 0 : indentUnit);
    },

    electricChars: "{}):",
    blockCommentStart: "/*",
    blockCommentEnd: "*/",
    lineComment: "//"
  };
});

CodeMirror.defineMIME("text/x-go", "go");
<|endoftext|>


<commit_before>/* global describe, beforeEach, it */
"use strict";

const should = require("should");
const sinon = require("sinon");
const TemplatePluginEnvironment = require("./helpers/TemplatePluginEnvironment");
const ConcatSource = require("webpack-sources").ConcatSource;
const AmdMainTemplatePlugin = require("../lib/AmdMainTemplatePlugin");

describe("AmdMainTemplatePlugin", () => {
	let env;

	const applyTemplatePluginWithOptions = function(Plugin, name) {
		const plugin = new Plugin(name);
		const templatePluginEnvironment = new TemplatePluginEnvironment();
		const environment = templatePluginEnvironment.getEnvironmentStub();
		environment.mainTemplate.applyPluginsWaterfall = () => "templateName";
		plugin.apply(environment);
		return templatePluginEnvironment;
	};

	const setupPluginAndGetEventBinding = function(name) {
		const templatePlugin = applyTemplatePluginWithOptions(AmdMainTemplatePlugin, name);
		const eventBindings = templatePlugin.getEventBindings();
		return eventBindings[0];
	};

	beforeEach(() => {
		env = {
			modulesListWithExternals: [{
				id: "module-1",
				external: true,
				request: {
					amd: "external-amd-module"
				}
			}, {
				id: "module-2",
				external: true,
				request: "external-non-amd-module"
			}, {
				id: "module-3",
				external: true
			}, {
				id: "module-4",
				external: false
			}]
		};
	});

	it("has apply function", () => new AmdMainTemplatePlugin().apply.should.be.a.Function());

	describe("when applied", () => {
		beforeEach(() =>
			env.templatePlugin = applyTemplatePluginWithOptions(AmdMainTemplatePlugin, "foo"));

		describe("event handlers", () => {
			beforeEach(() => env.eventBindings = env.templatePlugin.getEventBindings());

			it("binds one handlers", () => env.eventBindings.length.should.be.exactly(1));

			describe("render-with-entry handler", () => {
				beforeEach(() => env.eventBinding = env.eventBindings[0]);

				it("binds to render-with-entry event", () =>
					env.eventBinding.name.should.be.exactly("render-with-entry"));

				describe("with name", () => {
					beforeEach(() => {
						env.chunk = {
							modules: env.modulesListWithExternals
						};
						env.eventBinding = setupPluginAndGetEventBinding("foo");
					});

					it("creates source wrapper with module name and external dependencies", () => {
						const source = env.eventBinding.handler("moduleSource()", env.chunk, "bar");
						source.should.be.instanceof(ConcatSource);
						source.source().should.be.exactly("define(\"templateName\", [\"external-amd-module\",\"external-non-amd-module\",null], function(__WEBPACK_EXTERNAL_MODULE_module_1__, __WEBPACK_EXTERNAL_MODULE_module_2__, __WEBPACK_EXTERNAL_MODULE_module_3__) { return moduleSource()});");
					});
				});

				describe("with external dependencies", () => {
					beforeEach(() => {
						env.chunk = {
							modules: env.modulesListWithExternals
						};
						env.eventBinding = setupPluginAndGetEventBinding();
					});

					it("creates source wrapper with external dependencies", () => {
						const source = env.eventBinding.handler("moduleSource()", env.chunk, "bar");
						source.should.be.instanceof(ConcatSource);
						source.source().should.be.exactly("define([\"external-amd-module\",\"external-non-amd-module\",null], function(__WEBPACK_EXTERNAL_MODULE_module_1__, __WEBPACK_EXTERNAL_MODULE_module_2__, __WEBPACK_EXTERNAL_MODULE_module_3__) { return moduleSource()});");
					});
				});

				describe("with only local dependencies", () => {
					beforeEach(() => {
						const externalFlag = {
							external: false
						};
						const noExternals = env.modulesListWithExternals.map((module) => Object.assign(module, externalFlag));
						env.chunk = {
							modules: noExternals
						};
						env.eventBinding = setupPluginAndGetEventBinding();
					});

					it("creates source wrapper with callback only", () => {
						const source = env.eventBinding.handler("moduleSource()", env.chunk, "bar");
						source.should.be.instanceof(ConcatSource);
						source.source().should.be.exactly("define(function() { return moduleSource()});");
					});
				});
			});
		});

		describe("main template event handlers", () => {
			beforeEach(() =>
				env.mainTemplateBindings = env.templatePlugin.getMainTemplateBindings());

			it("binds two handlers", () => env.mainTemplateBindings.length.should.be.exactly(2));

			describe("global-hash-paths handler", () => {
				beforeEach(() => env.mainTemplateBinding = env.mainTemplateBindings[0]);

				it("binds to global-hash-paths event", () =>
					env.mainTemplateBinding.name.should.be.exactly("global-hash-paths"));

				it("adds name to path array", () =>
					env.mainTemplateBinding.handler([]).should.deepEqual(["foo"]));
			});

			describe("hash handler", () => {
				beforeEach(() => env.mainTemplateBinding = env.mainTemplateBindings[1]);

				it("binds to hash event", () => env.mainTemplateBinding.name.should.be.exactly("hash"));

				it("updates hash", () => {
					const hash = {
						update: sinon.spy()
					};
					env.mainTemplateBinding.handler(hash);

					hash.update.callCount.should.be.exactly(2);
					hash.update.firstCall.args[0].should.be.exactly("exports amd");
					hash.update.secondCall.args[0].should.be.exactly("foo");
				});
			});
		});
	});
});
<commit_msg>Update mocked chunk in tests<commit_after>/* global describe, beforeEach, it */
"use strict";

const should = require("should");
const sinon = require("sinon");
const TemplatePluginEnvironment = require("./helpers/TemplatePluginEnvironment");
const ConcatSource = require("webpack-sources").ConcatSource;
const AmdMainTemplatePlugin = require("../lib/AmdMainTemplatePlugin");

describe("AmdMainTemplatePlugin", () => {
	let env;

	const applyTemplatePluginWithOptions = function(Plugin, name) {
		const plugin = new Plugin(name);
		const templatePluginEnvironment = new TemplatePluginEnvironment();
		const environment = templatePluginEnvironment.getEnvironmentStub();
		environment.mainTemplate.applyPluginsWaterfall = () => "templateName";
		plugin.apply(environment);
		return templatePluginEnvironment;
	};

	const setupPluginAndGetEventBinding = function(name) {
		const templatePlugin = applyTemplatePluginWithOptions(AmdMainTemplatePlugin, name);
		const eventBindings = templatePlugin.getEventBindings();
		return eventBindings[0];
	};

	beforeEach(() => {
		env = {
			modulesListWithExternals: [{
				id: "module-1",
				external: true,
				request: {
					amd: "external-amd-module"
				}
			}, {
				id: "module-2",
				external: true,
				request: "external-non-amd-module"
			}, {
				id: "module-3",
				external: true
			}, {
				id: "module-4",
				external: false
			}]
		};
	});

	it("has apply function", () => new AmdMainTemplatePlugin().apply.should.be.a.Function());

	describe("when applied", () => {
		beforeEach(() =>
			env.templatePlugin = applyTemplatePluginWithOptions(AmdMainTemplatePlugin, "foo"));

		describe("event handlers", () => {
			beforeEach(() => env.eventBindings = env.templatePlugin.getEventBindings());

			it("binds one handlers", () => env.eventBindings.length.should.be.exactly(1));

			describe("render-with-entry handler", () => {
				beforeEach(() => env.eventBinding = env.eventBindings[0]);

				it("binds to render-with-entry event", () =>
					env.eventBinding.name.should.be.exactly("render-with-entry"));

				describe("with name", () => {
					beforeEach(() => {
						env.chunk = {
							getModules: () => env.modulesListWithExternals
						};
						env.eventBinding = setupPluginAndGetEventBinding("foo");
					});

					it("creates source wrapper with module name and external dependencies", () => {
						const source = env.eventBinding.handler("moduleSource()", env.chunk, "bar");
						source.should.be.instanceof(ConcatSource);
						source.source().should.be.exactly("define(\"templateName\", [\"external-amd-module\",\"external-non-amd-module\",null], function(__WEBPACK_EXTERNAL_MODULE_module_1__, __WEBPACK_EXTERNAL_MODULE_module_2__, __WEBPACK_EXTERNAL_MODULE_module_3__) { return moduleSource()});");
					});
				});

				describe("with external dependencies", () => {
					beforeEach(() => {
						env.chunk = {
							getModules: () => env.modulesListWithExternals
						};
						env.eventBinding = setupPluginAndGetEventBinding();
					});

					it("creates source wrapper with external dependencies", () => {
						const source = env.eventBinding.handler("moduleSource()", env.chunk, "bar");
						source.should.be.instanceof(ConcatSource);
						source.source().should.be.exactly("define([\"external-amd-module\",\"external-non-amd-module\",null], function(__WEBPACK_EXTERNAL_MODULE_module_1__, __WEBPACK_EXTERNAL_MODULE_module_2__, __WEBPACK_EXTERNAL_MODULE_module_3__) { return moduleSource()});");
					});
				});

				describe("with only local dependencies", () => {
					beforeEach(() => {
						const externalFlag = {
							external: false
						};
						const noExternals = env.modulesListWithExternals.map((module) => Object.assign(module, externalFlag));
						env.chunk = {
							getModules: () => env.modulesListWithExternals
						};
						env.eventBinding = setupPluginAndGetEventBinding();
					});

					it("creates source wrapper with callback only", () => {
						const source = env.eventBinding.handler("moduleSource()", env.chunk, "bar");
						source.should.be.instanceof(ConcatSource);
						source.source().should.be.exactly("define(function() { return moduleSource()});");
					});
				});
			});
		});

		describe("main template event handlers", () => {
			beforeEach(() =>
				env.mainTemplateBindings = env.templatePlugin.getMainTemplateBindings());

			it("binds two handlers", () => env.mainTemplateBindings.length.should.be.exactly(2));

			describe("global-hash-paths handler", () => {
				beforeEach(() => env.mainTemplateBinding = env.mainTemplateBindings[0]);

				it("binds to global-hash-paths event", () =>
					env.mainTemplateBinding.name.should.be.exactly("global-hash-paths"));

				it("adds name to path array", () =>
					env.mainTemplateBinding.handler([]).should.deepEqual(["foo"]));
			});

			describe("hash handler", () => {
				beforeEach(() => env.mainTemplateBinding = env.mainTemplateBindings[1]);

				it("binds to hash event", () => env.mainTemplateBinding.name.should.be.exactly("hash"));

				it("updates hash", () => {
					const hash = {
						update: sinon.spy()
					};
					env.mainTemplateBinding.handler(hash);

					hash.update.callCount.should.be.exactly(2);
					hash.update.firstCall.args[0].should.be.exactly("exports amd");
					hash.update.secondCall.args[0].should.be.exactly("foo");
				});
			});
		});
	});
});
<|endoftext|>


<commit_before>var Immutable = require("../../seamless-immutable.js");
var JSC       = require("jscheck");
var TestUtils = require("../TestUtils.js");
var assert    = require("chai").assert;
var _         = require("lodash")
var check     = TestUtils.check;

function generateArrayOfObjects() {
  return JSC.array()().map(function() { return JSC.object()(); });
}

module.exports = function() {
  describe("#merge", function() {
    function generateMergeTestsFor(specifiers) {
      var runs = 100;

      function checkMultiple(callback) {
        check(runs, specifiers, function(list) {
          var useVarArgs = !(list instanceof Array);

          if (arguments.length > 1) {
            list = Array.prototype.slice.call(arguments);
          } else if (useVarArgs) {
            list = [list]
          }

          assert.notStrictEqual(list.length, 0, "Can't usefully check merge() with no objects");

          var immutable = Immutable(list[0]);

          function runMerge(others) {
            others = others || list;

            return useVarArgs ?
              immutable.merge.apply(immutable, others) :
              immutable.merge(others);
          }

          callback(immutable, list, runMerge);
        })
      }

      it("prioritizes the arguments' properties", function() {
        checkMultiple(function(immutable, mutables, runMerge) {
          var expectedChanges = {};

          _.each(mutables, function(mutable) {
            var keys = _.keys(immutable);

            assert.notStrictEqual(keys.length, 0, "Can't usefully check merge() with an empty object");

            // Randomly change some values that share keys with the immutable.
            _.each(keys, function(key) {
              if (Math.random() > 0.5) {
                var value    = immutable[key],
                    suffix   = JSC.string()(),
                    newValue = value + suffix;

                assert.notStrictEqual(value, newValue, "Failed to change value (" + value + ") by appending \"" + suffix + "\"");

                // Record that we expect this to end up in the final result.
                expectedChanges[key] = newValue;

                mutable[key]  = newValue;
              } else if (mutable.hasOwnProperty(key) && mutable[key] !== immutable[key]) {
                // NaN will break tests, though not the actual function.
                if (isNaN(mutable[key])) {
                  mutable[key] = 0;
                }

                expectedChanges[key] = mutable[key];
              }
            });
          });

          var result = runMerge(mutables);

          _.each(expectedChanges, function(expectedValue, key) {
            assert.notStrictEqual(expectedValue, immutable[key],
              "Expected to change key (" + key + "), but expected change was the same as the old value (" + expectedValue + ")");

            assert.strictEqual(result[key], expectedValue,
              "The merged object did not keep the key/newValue pair as expected.");
          });
        });
      });

      it("contains all the arguments' properties", function() {
        checkMultiple(function(immutable, mutables, runMerge) {
          var result = runMerge();

          _.each(mutables, function(mutable, index) {
            _.each(mutable, function (value, key) {
              assert(result.hasOwnProperty(key));
            });
          });
        });
      });

      it("contains all the original's properties", function() {
        checkMultiple(function(immutable, mutables, runMerge) {
          var result = runMerge();

          _.each(immutable, function (value, key) {
            assert(result.hasOwnProperty(key));
          });
        });
      });

      it("returns an Immutable Object", function() {
        checkMultiple(function(immutable, mutables, runMerge) {
          var result = runMerge();

          assert.instanceOf(result, Object);
          assert(Immutable.isImmutable(result));
        });
      });

      // Sanity check to make sure our QuickCheck logic isn't off the rails.
      it("passes a basic sanity check on canned input", function() {
        var expected = Immutable({all: "your base", are: {belong: "to us"}});
        var actual   = Immutable({all: "your base", are: {belong: "to them"}}).merge({are: {belong: "to us"}})

        assert.deepEqual(actual, expected);
      });
    }

    describe("when passed a single object", function() {
      generateMergeTestsFor([JSC.object()]);
    });

    describe("when passed multiple objects", function() {
      generateMergeTestsFor([JSC.object(), JSC.object(), JSC.object()]);
    });

    describe("when passed an array of objects", function() {
      generateMergeTestsFor([generateArrayOfObjects]);
    });
  });
};<commit_msg>Don't unnecessarily run the sanity check test. Once is sufficient.<commit_after>var Immutable = require("../../seamless-immutable.js");
var JSC       = require("jscheck");
var TestUtils = require("../TestUtils.js");
var assert    = require("chai").assert;
var _         = require("lodash")
var check     = TestUtils.check;

function generateArrayOfObjects() {
  return JSC.array()().map(function() { return JSC.object()(); });
}

module.exports = function() {
  describe("#merge", function() {
    function generateMergeTestsFor(specifiers) {
      var runs = 100;

      function checkMultiple(callback) {
        check(runs, specifiers, function(list) {
          var useVarArgs = !(list instanceof Array);

          if (arguments.length > 1) {
            list = Array.prototype.slice.call(arguments);
          } else if (useVarArgs) {
            list = [list]
          }

          assert.notStrictEqual(list.length, 0, "Can't usefully check merge() with no objects");

          var immutable = Immutable(list[0]);

          function runMerge(others) {
            others = others || list;

            return useVarArgs ?
              immutable.merge.apply(immutable, others) :
              immutable.merge(others);
          }

          callback(immutable, list, runMerge);
        })
      }

      it("prioritizes the arguments' properties", function() {
        checkMultiple(function(immutable, mutables, runMerge) {
          var expectedChanges = {};

          _.each(mutables, function(mutable) {
            var keys = _.keys(immutable);

            assert.notStrictEqual(keys.length, 0, "Can't usefully check merge() with an empty object");

            // Randomly change some values that share keys with the immutable.
            _.each(keys, function(key) {
              if (Math.random() > 0.5) {
                var value    = immutable[key],
                    suffix   = JSC.string()(),
                    newValue = value + suffix;

                assert.notStrictEqual(value, newValue, "Failed to change value (" + value + ") by appending \"" + suffix + "\"");

                // Record that we expect this to end up in the final result.
                expectedChanges[key] = newValue;

                mutable[key]  = newValue;
              } else if (mutable.hasOwnProperty(key) && mutable[key] !== immutable[key]) {
                // NaN will break tests, though not the actual function.
                if (isNaN(mutable[key])) {
                  mutable[key] = 0;
                }

                expectedChanges[key] = mutable[key];
              }
            });
          });

          var result = runMerge(mutables);

          _.each(expectedChanges, function(expectedValue, key) {
            assert.notStrictEqual(expectedValue, immutable[key],
              "Expected to change key (" + key + "), but expected change was the same as the old value (" + expectedValue + ")");

            assert.strictEqual(result[key], expectedValue,
              "The merged object did not keep the key/newValue pair as expected.");
          });
        });
      });

      it("contains all the arguments' properties", function() {
        checkMultiple(function(immutable, mutables, runMerge) {
          var result = runMerge();

          _.each(mutables, function(mutable, index) {
            _.each(mutable, function (value, key) {
              assert(result.hasOwnProperty(key));
            });
          });
        });
      });

      it("contains all the original's properties", function() {
        checkMultiple(function(immutable, mutables, runMerge) {
          var result = runMerge();

          _.each(immutable, function (value, key) {
            assert(result.hasOwnProperty(key));
          });
        });
      });

      it("returns an Immutable Object", function() {
        checkMultiple(function(immutable, mutables, runMerge) {
          var result = runMerge();

          assert.instanceOf(result, Object);
          assert(Immutable.isImmutable(result));
        });
      });
    }

    // Sanity check to make sure our QuickCheck logic isn't off the rails.
    it("passes a basic sanity check on canned input", function() {
      var expected = Immutable({all: "your base", are: {belong: "to us"}});
      var actual   = Immutable({all: "your base", are: {belong: "to them"}}).merge({are: {belong: "to us"}})

      assert.deepEqual(actual, expected);
    });

    describe("when passed a single object", function() {
      generateMergeTestsFor([JSC.object()]);
    });

    describe("when passed multiple objects", function() {
      generateMergeTestsFor([JSC.object(), JSC.object(), JSC.object()]);
    });

    describe("when passed an array of objects", function() {
      generateMergeTestsFor([generateArrayOfObjects]);
    });
  });
};<|endoftext|>


<commit_before>import setCurrentScreenAction from "src/actions/ScreenActions.js";
import { SET_CURRENT_SCREEN, MENU_SCREEN,
         GAME_SCREEN} from "src/actions/ScreenActions.js";

describe("Screen Actions", () => {

  it("should exist", () => {
    setCurrentScreenAction.should.exist;
  });

  it("should be a function", () => {
    setCurrentScreenAction.should.be.function;
  });

  it("should create action of type SET_CURRENT_SCREEN", () => {
    const action = setCurrentScreenAction(MENU_SCREEN);
    action.type.should.be.equal(SET_CURRENT_SCREEN);
  });

  it("should have parameter screen equal to function argument", () => {
    var action = setCurrentScreenAction(MENU_SCREEN);

    const setMenuScreenAction = {
      screen: MENU_SCREEN,
      type: SET_CURRENT_SCREEN
    };

    action.should.be.eql(setMenuScreenAction);

    action = setCurrentScreenAction(GAME_SCREEN);

    const setGameScreenAction = {
      screen: GAME_SCREEN,
      type: SET_CURRENT_SCREEN
    };

    action.should.be.eql(setGameScreenAction);
  });

});
<commit_msg>Refactor change ‘var’ statement to ‘const’<commit_after>import setCurrentScreenAction from "src/actions/ScreenActions.js";
import { SET_CURRENT_SCREEN, MENU_SCREEN,
         GAME_SCREEN} from "src/actions/ScreenActions.js";

describe("Screen Actions", () => {

  it("should exist", () => {
    setCurrentScreenAction.should.exist;
  });

  it("should be a function", () => {
    setCurrentScreenAction.should.be.function;
  });

  it("should create action of type SET_CURRENT_SCREEN", () => {
    const action = setCurrentScreenAction(MENU_SCREEN);
    action.type.should.be.equal(SET_CURRENT_SCREEN);
  });

  it("should have parameter screen equal to function argument", () => {
    const action = setCurrentScreenAction(MENU_SCREEN);

    const setMenuScreenAction = {
      screen: MENU_SCREEN,
      type: SET_CURRENT_SCREEN
    };

    action.should.be.eql(setMenuScreenAction);

    action = setCurrentScreenAction(GAME_SCREEN);

    const setGameScreenAction = {
      screen: GAME_SCREEN,
      type: SET_CURRENT_SCREEN
    };

    action.should.be.eql(setGameScreenAction);
  });

});
<|endoftext|>


<commit_before>var mongodb = process.env['TEST_NATIVE'] != null ? require('../lib/mongodb').native() : require('../lib/mongodb').pure();
var useSSL = process.env['USE_SSL'] != null ? true : false;
var native_parser = (process.env['TEST_NATIVE'] != null);

var testCase = require('nodeunit').testCase,
  debug = require('util').debug,
  inspect = require('util').inspect,
  nodeunit = require('nodeunit'),
  gleak = require('../dev/tools/gleak'),
  Db = mongodb.Db,
  Cursor = mongodb.Cursor,
  Collection = mongodb.Collection,
  Server = mongodb.Server;

var MONGODB = 'integration_tests';
var client = null;

/**
 * Retrieve the server information for the current
 * instance of the db client
 *
 * @ignore
 */
exports.setUp = function(callback) {
  var self = exports;
  client = new Db(MONGODB, new Server("127.0.0.1", 27017, {auto_reconnect: true, poolSize: 4, ssl:useSSL}), {native_parser: (process.env['TEST_NATIVE'] != null)});
  client.open(function(err, db_p) {
    if(numberOfTestsRun == (Object.keys(self).length)) {
      // If first test drop the db
      client.dropDatabase(function(err, done) {
        callback();
      });
    } else {
      return callback();
    }
  });
}

/**
 * Retrieve the server information for the current
 * instance of the db client
 *
 * @ignore
 */
exports.tearDown = function(callback) {
  var self = this;
  numberOfTestsRun = numberOfTestsRun - 1;
  // Close connection
  client.close();
  callback();
}

/**
 * Correctly call the aggregation framework using a pipeline in an Array.
 *
 * @_class collection
 * @_function aggregate
 * @ignore
 */
exports.shouldCorrectlyExecuteSimpleAggregationPipelineUsingArray = function(test) {
  var db = new Db('integration_tests', new Server("127.0.0.1", 27017,
   {auto_reconnect: false, poolSize: 4, ssl:useSSL}), {native_parser: native_parser});

  // Establish connection to db
  db.open(function(err, db) {
    // Some docs for insertion
    var docs = [{
        title : "this is my title", author : "bob", posted : new Date() ,
        pageViews : 5, tags : [ "fun" , "good" , "fun" ], other : { foo : 5 },
        comments : [
          { author :"joe", text : "this is cool" }, { author :"sam", text : "this is bad" }
        ]}];

    // Validate that we are running on at least version 2.1 of MongoDB
    db.admin().serverInfo(function(err, result){

      if(parseInt((result.version.replace(/\./g, ''))) >= 210) {
        // Create a collection
        db.createCollection('shouldCorrectlyExecuteSimpleAggregationPipelineUsingArray', function(err, collection) {
          // Insert the docs
          collection.insert(docs, {safe:true}, function(err, result) {

            // Execute aggregate, notice the pipeline is expressed as an Array
            collection.aggregate([
                { $project : {
                	author : 1,
                	tags : 1
                }},
                { $unwind : "$tags" },
                { $group : {
                	_id : {tags : "$tags"},
                	authors : { $addToSet : "$author" }
                }}
              ], function(err, result) {
                test.equal(null, err);
                test.equal('good', result[0]._id.tags);
                test.deepEqual(['bob'], result[0].authors);
                test.equal('fun', result[1]._id.tags);
                test.deepEqual(['bob'], result[1].authors);

                db.close();
                test.done();
            });
          });
        });
      } else {
        db.close();
        test.done();
      }
    });
  });
}

/**
 * Correctly call the aggregation framework using a pipeline expressed as an argument list.
 *
 * @_class collection
 * @_function aggregate
 * @ignore
 */
exports.shouldFailWhenExecutingSimpleAggregationPipelineUsingArgumentsNotAnArray = function(test) {
  var db = new Db('integration_tests', new Server("127.0.0.1", 27017,
   {auto_reconnect: false, poolSize: 4, ssl:useSSL}), {native_parser: native_parser});

  // Establish connection to db
  db.open(function(err, db) {
    // Some docs for insertion
    var docs = [{
        title : "this is my title", author : "bob", posted : new Date() ,
        pageViews : 5, tags : [ "fun" , "good" , "fun" ], other : { foo : 5 },
        comments : [
          { author :"joe", text : "this is cool" }, { author :"sam", text : "this is bad" }
        ]}];

    // Validate that we are running on at least version 2.1 of MongoDB
    db.admin().serverInfo(function(err, result){

      if(parseInt((result.version.replace(/\./g, ''))) >= 210) {
        // Create a collection
        client.createCollection('shouldCorrectlyExecuteSimpleAggregationPipelineUsingArguments', function(err, collection) {
          // Insert the docs
          collection.insert(docs, {safe:true}, function(err, result) {
            // Execute aggregate, notice the pipeline is expressed as function call parameters
            // instead of an Array.
            collection.aggregate(
                { $project : {
                	author : 1,
                	tags : 1
                }},
                { $unwind : "$tags" },
                { $group : {
                 _id : { tags : 1 },
                 authors : { $addToSet : "$author" }
                }}
              , function(err, result) {
                test.equal(null, err);
                test.equal('good', result[0]._id.tags);
                test.deepEqual(['bob'], result[0].authors);
                test.equal('fun', result[1]._id.tags);
                test.deepEqual(['bob'], result[1].authors);

                db.close();
                test.done();
            });
          });
        });
      } else {
        db.close();
        test.done();
      }
    });
  });
}

/**
 * Correctly call the aggregation framework using a pipeline expressed as an argument list.
 *
 * @_class collection
 * @_function aggregate
 * @ignore
 */
exports.shouldFailWhenExecutingSimpleAggregationPipelineUsingArgumentsUsingSingleObject = function(test) {
  var db = new Db('integration_tests', new Server("127.0.0.1", 27017,
   {auto_reconnect: false, poolSize: 4, ssl:useSSL}), {native_parser: native_parser});

  // Establish connection to db
  db.open(function(err, db) {
    // Some docs for insertion
    var docs = [{
        title : "this is my title", author : "bob", posted : new Date() ,
        pageViews : 5, tags : [ "fun" , "good" , "fun" ], other : { foo : 5 },
        comments : [
          { author :"joe", text : "this is cool" }, { author :"sam", text : "this is bad" }
        ]}];

    // Validate that we are running on at least version 2.1 of MongoDB
    db.admin().serverInfo(function(err, result){

      if(parseInt((result.version.replace(/\./g, ''))) >= 210) {
        // Create a collection
        client.createCollection('shouldCorrectlyExecuteSimpleAggregationPipelineUsingArguments', function(err, collection) {
          // Insert the docs
          collection.insert(docs, {safe:true}, function(err, result) {
            // Execute aggregate, notice the pipeline is expressed as function call parameters
            // instead of an Array.
            collection.aggregate(
                { $project : {
                  author : 1,
                  tags : 1
                }},
                { $unwind : "$tags" },
                { $group : {
                 _id : { tags : 1 },
                 authors : { $addToSet : "$author" }
                }}
              , function(err, result) {
                test.equal(null, err);
                test.equal('good', result[0]._id.tags);
                test.deepEqual(['bob'], result[0].authors);
                test.equal('fun', result[1]._id.tags);
                test.deepEqual(['bob'], result[1].authors);

                db.close();
                test.done();
            });
          });
        });
      } else {
        db.close();
        test.done();
      }
    });
  });
}

/**
 * @ignore
 */
exports.shouldCorrectlyFailAndReturnError = function(test) {
  // Some docs for insertion
  var docs = [{
      title : "this is my title", author : "bob", posted : new Date() ,
      pageViews : 5, tags : [ "fun" , "good" , "fun" ], other : { foo : 5 },
      comments : [
        { author :"joe", text : "this is cool" }, { author :"sam", text : "this is bad" }
      ]}];

  client.admin().serverInfo(function(err, result){
    if(parseInt((result.version.replace(/\./g, ''))) >= 210) {
      // Create a collection
      client.createCollection('shouldCorrectlyFailAndReturnError', function(err, collection) {
        // Insert the docs
        collection.insert(docs, {safe:true}, function(err, result) {
          // Execute aggregate
          collection.aggregate(
              { $project : {
              	author : 1,
              	tags : 1,
              }},
              { $32unwind : "$tags" },
              { $group : {
              	_id : { tags : 1 },
              	authors : { $addToSet : "$author" }
              }}
            , function(err, result) {
              test.ok(err != null);
              test.done();
          });
        });
      });
    } else {
      test.done();
    }
  });
}

// /**
//  * @ignore
//  */
// exports.shouldCorrectlyExecuteAggregationWithExplain = function(test) {
//   // Some docs for insertion
//   var docs = [{
//       title : "this is my title", author : "bob", posted : new Date() ,
//       pageViews : 5, tags : [ "fun" , "good" , "fun" ], other : { foo : 5 },
//       comments : [
//         { author :"joe", text : "this is cool" }, { author :"sam", text : "this is bad" }
//       ]}];

//   client.admin().serverInfo(function(err, result){
//     if(parseInt((result.version.replace(/\./g, ''))) >= 210) {
//       // Create a collection
//       client.createCollection('shouldCorrectlyExecuteAggregationWithExplain', function(err, collection) {
//         // Insert the docs
//         collection.insert(docs, {safe:true}, function(err, result) {
//           // Execute aggregate
//           collection.aggregate(
//               [{ $project : {
//               	author : 1,
//               	tags : 1,
//               }},
//               { $unwind : "$tags" },
//               { $group : {
//               	_id : { tags : 1 },
//               	authors : { $addToSet : "$author" }
//               }}],
//               {explain:true}
//             , function(err, result) {
//               test.equal(null, err);
//               test.ok(result['serverPipeline'] != null);
//               test.done();
//           });
//         });
//       });
//     } else {
//       test.done();
//     }
//   });
// }

/**
 * Retrieve the server information for the current
 * instance of the db client
 *
 * @ignore
 */
exports.noGlobalsLeaked = function(test) {
  var leaks = gleak.detectNew();
  test.equal(0, leaks.length, "global var leak detected: " + leaks.join(', '));
  test.done();
}

/**
 * Retrieve the server information for the current
 * instance of the db client
 *
 * @ignore
 */
var numberOfTestsRun = Object.keys(this).length - 2;<commit_msg>Fixed remaining tests<commit_after>var mongodb = process.env['TEST_NATIVE'] != null ? require('../lib/mongodb').native() : require('../lib/mongodb').pure();
var useSSL = process.env['USE_SSL'] != null ? true : false;
var native_parser = (process.env['TEST_NATIVE'] != null);

var testCase = require('nodeunit').testCase,
  debug = require('util').debug,
  inspect = require('util').inspect,
  nodeunit = require('nodeunit'),
  gleak = require('../dev/tools/gleak'),
  Db = mongodb.Db,
  Cursor = mongodb.Cursor,
  Collection = mongodb.Collection,
  Server = mongodb.Server;

var MONGODB = 'integration_tests';
var client = null;

/**
 * Retrieve the server information for the current
 * instance of the db client
 *
 * @ignore
 */
exports.setUp = function(callback) {
  var self = exports;
  client = new Db(MONGODB, new Server("127.0.0.1", 27017, {auto_reconnect: true, poolSize: 4, ssl:useSSL}), {native_parser: (process.env['TEST_NATIVE'] != null)});
  client.open(function(err, db_p) {
    if(numberOfTestsRun == (Object.keys(self).length)) {
      // If first test drop the db
      client.dropDatabase(function(err, done) {
        callback();
      });
    } else {
      return callback();
    }
  });
}

/**
 * Retrieve the server information for the current
 * instance of the db client
 *
 * @ignore
 */
exports.tearDown = function(callback) {
  var self = this;
  numberOfTestsRun = numberOfTestsRun - 1;
  // Close connection
  client.close();
  callback();
}

/**
 * Correctly call the aggregation framework using a pipeline in an Array.
 *
 * @_class collection
 * @_function aggregate
 * @ignore
 */
exports.shouldCorrectlyExecuteSimpleAggregationPipelineUsingArray = function(test) {
  var db = new Db('integration_tests', new Server("127.0.0.1", 27017,
   {auto_reconnect: false, poolSize: 4, ssl:useSSL}), {native_parser: native_parser});

  // Establish connection to db
  db.open(function(err, db) {
    // Some docs for insertion
    var docs = [{
        title : "this is my title", author : "bob", posted : new Date() ,
        pageViews : 5, tags : [ "fun" , "good" , "fun" ], other : { foo : 5 },
        comments : [
          { author :"joe", text : "this is cool" }, { author :"sam", text : "this is bad" }
        ]}];

    // Validate that we are running on at least version 2.1 of MongoDB
    db.admin().serverInfo(function(err, result){

      if(parseInt((result.version.replace(/\./g, ''))) >= 210) {
        // Create a collection
        db.createCollection('shouldCorrectlyExecuteSimpleAggregationPipelineUsingArray', function(err, collection) {
          // Insert the docs
          collection.insert(docs, {safe:true}, function(err, result) {

            // Execute aggregate, notice the pipeline is expressed as an Array
            collection.aggregate([
                { $project : {
                	author : 1,
                	tags : 1
                }},
                { $unwind : "$tags" },
                { $group : {
                	_id : {tags : "$tags"},
                	authors : { $addToSet : "$author" }
                }}
              ], function(err, result) {
                test.equal(null, err);
                test.equal('good', result[0]._id.tags);
                test.deepEqual(['bob'], result[0].authors);
                test.equal('fun', result[1]._id.tags);
                test.deepEqual(['bob'], result[1].authors);

                db.close();
                test.done();
            });
          });
        });
      } else {
        db.close();
        test.done();
      }
    });
  });
}

/**
 * Correctly call the aggregation framework using a pipeline expressed as an argument list.
 *
 * @_class collection
 * @_function aggregate
 * @ignore
 */
exports.shouldFailWhenExecutingSimpleAggregationPipelineUsingArgumentsNotAnArray = function(test) {
  var db = new Db('integration_tests', new Server("127.0.0.1", 27017,
   {auto_reconnect: false, poolSize: 4, ssl:useSSL}), {native_parser: native_parser});

  // Establish connection to db
  db.open(function(err, db) {
    // Some docs for insertion
    var docs = [{
        title : "this is my title", author : "bob", posted : new Date() ,
        pageViews : 5, tags : [ "fun" , "good" , "fun" ], other : { foo : 5 },
        comments : [
          { author :"joe", text : "this is cool" }, { author :"sam", text : "this is bad" }
        ]}];

    // Validate that we are running on at least version 2.1 of MongoDB
    db.admin().serverInfo(function(err, result){

      if(parseInt((result.version.replace(/\./g, ''))) >= 210) {
        // Create a collection
        client.createCollection('shouldCorrectlyExecuteSimpleAggregationPipelineUsingArguments', function(err, collection) {
          // Insert the docs
          collection.insert(docs, {safe:true}, function(err, result) {
            // Execute aggregate, notice the pipeline is expressed as function call parameters
            // instead of an Array.
            collection.aggregate(
                { $project : {
                	author : 1,
                	tags : 1
                }},
                { $unwind : "$tags" },
                { $group : {
                	_id : {tags : "$tags"},
                	authors : { $addToSet : "$author" }
                }}
              , function(err, result) {
                test.equal(null, err);
                test.equal('good', result[0]._id.tags);
                test.deepEqual(['bob'], result[0].authors);
                test.equal('fun', result[1]._id.tags);
                test.deepEqual(['bob'], result[1].authors);

                db.close();
                test.done();
            });
          });
        });
      } else {
        db.close();
        test.done();
      }
    });
  });
}

/**
 * Correctly call the aggregation framework using a pipeline expressed as an argument list.
 *
 * @_class collection
 * @_function aggregate
 * @ignore
 */
exports.shouldFailWhenExecutingSimpleAggregationPipelineUsingArgumentsUsingSingleObject = function(test) {
  var db = new Db('integration_tests', new Server("127.0.0.1", 27017,
   {auto_reconnect: false, poolSize: 4, ssl:useSSL}), {native_parser: native_parser});

  // Establish connection to db
  db.open(function(err, db) {
    // Some docs for insertion
    var docs = [{
        title : "this is my title", author : "bob", posted : new Date() ,
        pageViews : 5, tags : [ "fun" , "good" , "fun" ], other : { foo : 5 },
        comments : [
          { author :"joe", text : "this is cool" }, { author :"sam", text : "this is bad" }
        ]}];

    // Validate that we are running on at least version 2.1 of MongoDB
    db.admin().serverInfo(function(err, result){

      if(parseInt((result.version.replace(/\./g, ''))) >= 210) {
        // Create a collection
        client.createCollection('shouldCorrectlyExecuteSimpleAggregationPipelineUsingArguments', function(err, collection) {
          // Insert the docs
          collection.insert(docs, {safe:true}, function(err, result) {
            // Execute aggregate, notice the pipeline is expressed as function call parameters
            // instead of an Array.
            collection.aggregate(
                { $project : {
                	author : 1,
                	tags : 1
                }},
                { $unwind : "$tags" },
                { $group : {
                	_id : {tags : "$tags"},
                	authors : { $addToSet : "$author" }
                }}
              , function(err, result) {
                test.equal(null, err);
                test.equal('good', result[0]._id.tags);
                test.deepEqual(['bob'], result[0].authors);
                test.equal('fun', result[1]._id.tags);
                test.deepEqual(['bob'], result[1].authors);

                db.close();
                test.done();
            });
          });
        });
      } else {
        db.close();
        test.done();
      }
    });
  });
}

/**
 * @ignore
 */
exports.shouldCorrectlyFailAndReturnError = function(test) {
  // Some docs for insertion
  var docs = [{
      title : "this is my title", author : "bob", posted : new Date() ,
      pageViews : 5, tags : [ "fun" , "good" , "fun" ], other : { foo : 5 },
      comments : [
        { author :"joe", text : "this is cool" }, { author :"sam", text : "this is bad" }
      ]}];

  client.admin().serverInfo(function(err, result){
    if(parseInt((result.version.replace(/\./g, ''))) >= 210) {
      // Create a collection
      client.createCollection('shouldCorrectlyFailAndReturnError', function(err, collection) {
        // Insert the docs
        collection.insert(docs, {safe:true}, function(err, result) {
          // Execute aggregate
          collection.aggregate(
              { $project : {
              	author : 1,
              	tags : 1,
              }},
              { $32unwind : "$tags" },
              { $group : {
              	_id : { tags : 1 },
              	authors : { $addToSet : "$author" }
              }}
            , function(err, result) {
              test.ok(err != null);
              test.done();
          });
        });
      });
    } else {
      test.done();
    }
  });
}

// /**
//  * @ignore
//  */
// exports.shouldCorrectlyExecuteAggregationWithExplain = function(test) {
//   // Some docs for insertion
//   var docs = [{
//       title : "this is my title", author : "bob", posted : new Date() ,
//       pageViews : 5, tags : [ "fun" , "good" , "fun" ], other : { foo : 5 },
//       comments : [
//         { author :"joe", text : "this is cool" }, { author :"sam", text : "this is bad" }
//       ]}];

//   client.admin().serverInfo(function(err, result){
//     if(parseInt((result.version.replace(/\./g, ''))) >= 210) {
//       // Create a collection
//       client.createCollection('shouldCorrectlyExecuteAggregationWithExplain', function(err, collection) {
//         // Insert the docs
//         collection.insert(docs, {safe:true}, function(err, result) {
//           // Execute aggregate
//           collection.aggregate(
//               [{ $project : {
//               	author : 1,
//               	tags : 1,
//               }},
//               { $unwind : "$tags" },
//               { $group : {
//               	_id : { tags : 1 },
//               	authors : { $addToSet : "$author" }
//               }}],
//               {explain:true}
//             , function(err, result) {
//               test.equal(null, err);
//               test.ok(result['serverPipeline'] != null);
//               test.done();
//           });
//         });
//       });
//     } else {
//       test.done();
//     }
//   });
// }

/**
 * Retrieve the server information for the current
 * instance of the db client
 *
 * @ignore
 */
exports.noGlobalsLeaked = function(test) {
  var leaks = gleak.detectNew();
  test.equal(0, leaks.length, "global var leak detected: " + leaks.join(', '));
  test.done();
}

/**
 * Retrieve the server information for the current
 * instance of the db client
 *
 * @ignore
 */
var numberOfTestsRun = Object.keys(this).length - 2;<|endoftext|>