<commit_before>/**
 * Copyright (c) 2016-present, Alejandro Mantilla <@AlejoJamC>.
 * All rights reserved.
 *
 * This source code is licensed under the MIT license found in the LICENSE
 * file in the root directory of this source tree or translated in the assets folder.
 */

var express     = require('express');
var base64      = require('../config/base64');
var crypto      = require('crypto');
var dashRoutes  = express.Router();
var fs          = require('fs');
var logger      = require('../config/logger').logger;
var multer      = require('multer');
var oracledb    = require('oracledb');
var path        = require('path');
var uuid        = require('node-uuid');

// Upload and rename files
var storage = multer.diskStorage({
    destination: 'uploads/',
    filename: function (req, file, cb) {
        crypto.pseudoRandomBytes(16, function (err, raw) {
            if (err) return cb(err);

            cb(null, raw.toString('hex') + path.extname(file.originalname))
        })
    }
});
var upload = multer({ storage: storage });

/* GET Index page. */
dashRoutes.get('/', function (req, res) {
    var error = '';
    // Basic error validator
    // Error
    if(typeof req.query.error !== 'undefined'){
        error = req.query.error;
    }
    // Session
    if(typeof req.session.userId === 'undefined' || typeof req.session.userId === ''){
        return res.redirect('/login');
    }
    // User Rol
    // If ............
    res.render('dash/search', {
        title   : 'Buscar | Identico',
        level   : '',
        layout  : 'dash',
        error   : error
    });
});

dashRoutes.get('/search/ajax', function (req, res) {
    var personDoc = req.query.cedula;
    oracledb.getConnection({
        user            : process.env.ORACLE_USERNAME,
        password        : process.env.ORACLE_PASSWORD,
        connectString   : process.env.ORACLE_HOST + ':' + process.env.ORACLE_PORT
        + '/' + process.env.ORACLE_SID
    }, function (err, connection) {
        if (err){
            logger.error(err.message);
            // error=0 trying to connect with database
            return res.send({ err : 'Error trying to connect with database.' , errCode : 0});
        }

        var sql = "SELECT N.IDPERSONA,N.PRIMERAPELLIDO,N.SEGUNDOAPELLIDO,N.PRIMERNOMBRE,N.SEGUNDONOMBRE," +
            "A.IDPERSONA AFILIADO, T.IDREFERIDO REFERIDO, " +
            "DECODE (NVL2(A.IDPERSONA,1,0) + NVL2(T.IDREFERIDO,2,0), 0, 'NO AFILIADO NI REFERIDO'," +
            " 1, 'AFILIADO', 2, 'REFERIDO',3, 'AFILIADO Y REFERIDO') TIPO" +
            " FROM NPERSONAS N, NAFILIADOS A, NAUTORIZACIONES T" +
            " WHERE N.IDPERSONA=A.IDPERSONA(+) AND N.IDPERSONA=T.IDREFERIDO(+) " +
            "AND N.NODOCUMENTO=" + personDoc;

        logger.info(sql);

        connection.execute(
            // The statement to execute
            sql,
            [ ],

            // The Callback function handles the SQL execution results
            function (err, result) {
                if (err) {
                    logger.error(err.message);
                    connection.close(
                        function(err) {
                            if (err) {
                                // error=1 trying to disconnect of database
                                logger.error(err.message);
                                return res.send({ err : 'trying to disconnect of database.' , errCode : 1});
                            }
                            logger.info('Connection to Oracle closed successfully!');
                            logger.info("1");
                        });
                    // Error doing select statement
                    return res.send({ err : 'Error doing select statement.'});
                }

                // Login success
                // Create the session
                if(typeof result.metaData === 'undefined' && typeof result.rows === 'undefined'){
                    logger.info('Validation error, empty values returned.');
                    connection.close(
                        function(err) {
                            if (err) {
                                // error=1 trying to disconnect of database
                                logger.error(err.message);
                                return res.send({ err : 'trying to disconnect of database.' , errCode : 1});
                            }
                            logger.info('Connection to Oracle closed successfully!');
                        });
                    return res.send({ data : 'Empty values returned.', code : 1});
                } else if(typeof result.rows[0] === 'undefined') {
                    logger.info('Validation error, empty values returned.');
                    connection.close(
                        function(err) {
                            if (err) {
                                // error=1 trying to disconnect of database
                                logger.error(err.message);
                                return res.send({ err : 'trying to disconnect of database.' , errCode : 1});
                            }
                            logger.info('Connection to Oracle closed successfully!');
                            logger.info("2");
                        });
                    return res.send({ data : 'Empty values returned.', code : 2});
                } else {
                    if(result.rows[0] == ''){
                        logger.info('Error trying to validate user credentials');
                        connection.close(
                            function(err) {
                                if (err) {
                                    // error=1 trying to disconnect of database
                                    logger.error(err.message);
                                    return res.send({ err : 'trying to disconnect of database.' , errCode : 1});
                                }
                                logger.info('Connection to Oracle closed successfully!');
                            });
                        return res.send({ data : 'Empty values returned.', code : 3});
                    }
                }

                var data = result;

                connection.close(
                    function(err) {
                        if (err) {
                            // error=1 trying to disconnect of database
                            logger.error(err.message);
                            return res.send({ err : 'trying to disconnect of database.' , errCode : 1});
                        }
                        logger.info('Connection to Oracle closed successfully!');
                        logger.info("3");

                    });
                logger.info(data);

                return res.send(data);

            }
        );
    });
});

/* GET Index page | Dashboard. */
dashRoutes.get('/dashboard', function (req, res) {
    // Basic error validator
    // Session
    if(typeof req.session.userId === 'undefined' || typeof req.session.userId === ''){
        return res.redirect('/login');
    }

    res.render('dash/index', {
        title   : 'Analytics Website | Index',
        level   : '',
        layout  : 'dash'
    });
});

/* GET Images handler page | Dashboard. */
dashRoutes.get('/dashboard/images', function (req, res) {
    res.render('dash/image', {
        title   : 'Analytics Website | Images',
        level   : '../',
        layout  : 'dash'
    });
});

/* POST Images handler page | Dashboard. */
dashRoutes.post('/dashboard/images/capture',  function (req, res) {

    if( typeof req.body.personid === 'undefined' || req.body.personid === ''){
        logger.info('Login credentials: Empty values.');
        // error=12 No person Id using image capture.
        return res.redirect('/dashboard/images?error=12');
    }

    //logger.info(req.body);

    //var encoded_image = req.body.finalimage;
    var binary_data = req.body.finalimage;

    // Random uuid to asign the new image
    var randomImageName = uuid.v4();
    var imagepath = 'uploads/' + randomImageName +'.jpg';
    // Create the file inside uploads folder
    var fileresult = fs.writeFile(imagepath, binary_data, {encoding: 'base64'}, function (err) {
        if(err){
            logger.info(err);
            logger.info('Error creating capture image');
            return res.redirect('/login?error=15');
        }

        // Save the image path in the database
        var personId = req.body.personid;
        // read the file
        var buf = fs.readFileSync(imagepath);
        var sql = "UPDATE HUELLA.NPERSONAS SET HUELLA.NPERSONAS.FOTO = :blob WHERE HUELLA.NPERSONAS.IDPERSONA =" + personId;

        // Save image route
        oracledb.autoCommit = true;
        oracledb.getConnection({
            user            : process.env.ORACLE_USERNAME,
            password        : process.env.ORACLE_PASSWORD,
            connectString   : process.env.ORACLE_HOST + ':' + process.env.ORACLE_PORT
            + '/' + process.env.ORACLE_SID
        }, function (err, connection) {
            if (err){
                logger.error(err.message);
                // error=0 trying to connect with database
                return res.redirect('/dashboard/images?error=0');
            }
            connection.execute(
                sql,
                [buf],
                // The Callback function handles the SQL execution results
                function (err, result) {
                    if (err) {
                        logger.error(err.message);
                        connection.close(
                            function(err) {
                                if (err) {
                                    // error=1 trying to disconnect of database
                                    logger.error(err.message);
                                    return res.redirect('/dashboard/images?error=1');
                                }
                                logger.info('Connection to Oracle closed successfully!');
                            });
                        // Error doing select statement
                        return res.redirect('/dashboard/images?error=12');
                    }

                    logger.info(result);

                    // UPDATE image capture success
                    connection.close(
                        function(err) {
                            if (err) {
                                // error=1 trying to disconnect of database
                                logger.error(err.message);
                                return res.redirect('/dashboard/images?error=1');
                            }
                            logger.info('Connection to Oracle closed successfully!');
                        });
                    res.redirect('/dashboard/images?flag=success');
                }
            );
        });
    });
});

/* POST Images handler page | Dashboard. */
dashRoutes.post('/dashboard/images/input', upload.single('inputpicture'), function (req, res) {
    if( typeof req.body.personid === 'undefined' || req.body.personid === ''){
        logger.info('Login credentials: Empty values.');
        // error=12 No person Id using image capture.
        return res.redirect('/login?error=12');
    }

    logger.info(req.file);
    //logger.info(req.body);

    var personId = req.body.personid;

    // read the file
    var buf = fs.readFileSync(req.file.path);

    /*var sql = "UPDATE HUELLA.NPERSONAS SET HUELLA.NPERSONAS.FOTO = " +
     buf + " WHERE HUELLA.NPERSONAS.IDPERSONA =" + personId;*/

    var sql = "UPDATE HUELLA.NPERSONAS SET HUELLA.NPERSONAS.FOTO = :blob WHERE HUELLA.NPERSONAS.IDPERSONA =" + personId;

    // Save image route
    oracledb.autoCommit = true;
    oracledb.getConnection({
        user            : process.env.ORACLE_USERNAME,
        password        : process.env.ORACLE_PASSWORD,
        connectString   : process.env.ORACLE_HOST + ':' + process.env.ORACLE_PORT
        + '/' + process.env.ORACLE_SID
    }, function (err, connection) {
        if (err){
            logger.error(err.message);
            // error=0 trying to connect with database
            return res.redirect('/dashboard/images?error=0');
        }

        connection.execute(
            sql,
            [buf],
            // The Callback function handles the SQL execution results
            function (err, result) {
                if (err) {
                    logger.error(err.message);
                    connection.close(
                        function(err) {
                            if (err) {
                                // error=1 trying to disconnect of database
                                logger.error(err.message);
                                return res.redirect('/dashboard/images?error=1');
                            }
                            logger.info('Connection to Oracle closed successfully!');
                        });
                    // Error doing select statement
                    return res.redirect('/dashboard/images?error=12');
                }

                if (result.rowsAffected != 1) {
                    logger.info('Error updating the image');
                    return res.redirect('/dashboard/images?error=2');
                }

                logger.info(result);

                // UPDATE image capture success
                connection.close(
                    function(err) {
                        if (err) {
                            // error=1 trying to disconnect of database
                            logger.error(err.message);
                            return res.redirect('/dashboard/images?error=1');
                        }
                        logger.info('Connection to Oracle closed successfully!');
                    });
                res.redirect('/dashboard/images?flag=success');
            }
        );
    });
});

module.exports = dashRoutes;<commit_msg>temproal route /applet<commit_after>/**
 * Copyright (c) 2016-present, Alejandro Mantilla <@AlejoJamC>.
 * All rights reserved.
 *
 * This source code is licensed under the MIT license found in the LICENSE
 * file in the root directory of this source tree or translated in the assets folder.
 */

var express     = require('express');
var base64      = require('../config/base64');
var crypto      = require('crypto');
var dashRoutes  = express.Router();
var fs          = require('fs');
var logger      = require('../config/logger').logger;
var multer      = require('multer');
var oracledb    = require('oracledb');
var path        = require('path');
var uuid        = require('node-uuid');

// Upload and rename files
var storage = multer.diskStorage({
    destination: 'uploads/',
    filename: function (req, file, cb) {
        crypto.pseudoRandomBytes(16, function (err, raw) {
            if (err) return cb(err);

            cb(null, raw.toString('hex') + path.extname(file.originalname))
        })
    }
});
var upload = multer({ storage: storage });

/* GET Index page. */
dashRoutes.get('/', function (req, res) {
    var error = '';
    // Basic error validator
    // Error
    if(typeof req.query.error !== 'undefined'){
        error = req.query.error;
    }
    // Session
    if(typeof req.session.userId === 'undefined' || typeof req.session.userId === ''){
        return res.redirect('/login');
    }
    // User Rol
    // If ............
    res.render('dash/search', {
        title   : 'Buscar | Identico',
        level   : '',
        layout  : 'dash',
        error   : error
    });
});

dashRoutes.get('/search/ajax', function (req, res) {
    var personDoc = req.query.cedula;
    oracledb.getConnection({
        user            : process.env.ORACLE_USERNAME,
        password        : process.env.ORACLE_PASSWORD,
        connectString   : process.env.ORACLE_HOST + ':' + process.env.ORACLE_PORT
        + '/' + process.env.ORACLE_SID
    }, function (err, connection) {
        if (err){
            logger.error(err.message);
            // error=0 trying to connect with database
            return res.send({ err : 'Error trying to connect with database.' , errCode : 0});
        }

        var sql = "SELECT N.IDPERSONA,N.PRIMERAPELLIDO,N.SEGUNDOAPELLIDO,N.PRIMERNOMBRE,N.SEGUNDONOMBRE," +
            "A.IDPERSONA AFILIADO, T.IDREFERIDO REFERIDO, " +
            "DECODE (NVL2(A.IDPERSONA,1,0) + NVL2(T.IDREFERIDO,2,0), 0, 'NO AFILIADO NI REFERIDO'," +
            " 1, 'AFILIADO', 2, 'REFERIDO',3, 'AFILIADO Y REFERIDO') TIPO" +
            " FROM NPERSONAS N, NAFILIADOS A, NAUTORIZACIONES T" +
            " WHERE N.IDPERSONA=A.IDPERSONA(+) AND N.IDPERSONA=T.IDREFERIDO(+) " +
            "AND N.NODOCUMENTO=" + personDoc;

        logger.info(sql);

        connection.execute(
            // The statement to execute
            sql,
            [ ],

            // The Callback function handles the SQL execution results
            function (err, result) {
                if (err) {
                    logger.error(err.message);
                    connection.close(
                        function(err) {
                            if (err) {
                                // error=1 trying to disconnect of database
                                logger.error(err.message);
                                return res.send({ err : 'trying to disconnect of database.' , errCode : 1});
                            }
                            logger.info('Connection to Oracle closed successfully!');
                            logger.info("1");
                        });
                    // Error doing select statement
                    return res.send({ err : 'Error doing select statement.'});
                }

                // Login success
                // Create the session
                if(typeof result.metaData === 'undefined' && typeof result.rows === 'undefined'){
                    logger.info('Validation error, empty values returned.');
                    connection.close(
                        function(err) {
                            if (err) {
                                // error=1 trying to disconnect of database
                                logger.error(err.message);
                                return res.send({ err : 'trying to disconnect of database.' , errCode : 1});
                            }
                            logger.info('Connection to Oracle closed successfully!');
                        });
                    return res.send({ data : 'Empty values returned.', code : 1});
                } else if(typeof result.rows[0] === 'undefined') {
                    logger.info('Validation error, empty values returned.');
                    connection.close(
                        function(err) {
                            if (err) {
                                // error=1 trying to disconnect of database
                                logger.error(err.message);
                                return res.send({ err : 'trying to disconnect of database.' , errCode : 1});
                            }
                            logger.info('Connection to Oracle closed successfully!');
                            logger.info("2");
                        });
                    return res.send({ data : 'Empty values returned.', code : 2});
                } else {
                    if(result.rows[0] == ''){
                        logger.info('Error trying to validate user credentials');
                        connection.close(
                            function(err) {
                                if (err) {
                                    // error=1 trying to disconnect of database
                                    logger.error(err.message);
                                    return res.send({ err : 'trying to disconnect of database.' , errCode : 1});
                                }
                                logger.info('Connection to Oracle closed successfully!');
                            });
                        return res.send({ data : 'Empty values returned.', code : 3});
                    }
                }

                var data = result;

                connection.close(
                    function(err) {
                        if (err) {
                            // error=1 trying to disconnect of database
                            logger.error(err.message);
                            return res.send({ err : 'trying to disconnect of database.' , errCode : 1});
                        }
                        logger.info('Connection to Oracle closed successfully!');
                        logger.info("3");

                    });
                logger.info(data);

                return res.send(data);

            }
        );
    });
});

/* GET Index page | Dashboard. */
dashRoutes.get('/dashboard', function (req, res) {
    // Basic error validator
    // Session
    if(typeof req.session.userId === 'undefined' || typeof req.session.userId === ''){
        return res.redirect('/login');
    }

    res.render('dash/index', {
        title   : 'Analytics Website | Index',
        level   : '',
        layout  : 'dash'
    });
});

/* GET Images handler page | Dashboard. */
dashRoutes.get('/dashboard/images', function (req, res) {
    res.render('dash/image', {
        title   : 'Analytics Website | Images',
        level   : '../',
        layout  : 'dash'
    });
});

/* POST Images handler page | Dashboard. */
dashRoutes.post('/dashboard/images/capture',  function (req, res) {

    if( typeof req.body.personid === 'undefined' || req.body.personid === ''){
        logger.info('Login credentials: Empty values.');
        // error=12 No person Id using image capture.
        return res.redirect('/dashboard/images?error=12');
    }

    //logger.info(req.body);

    //var encoded_image = req.body.finalimage;
    var binary_data = req.body.finalimage;

    // Random uuid to asign the new image
    var randomImageName = uuid.v4();
    var imagepath = 'uploads/' + randomImageName +'.jpg';
    // Create the file inside uploads folder
    var fileresult = fs.writeFile(imagepath, binary_data, {encoding: 'base64'}, function (err) {
        if(err){
            logger.info(err);
            logger.info('Error creating capture image');
            return res.redirect('/login?error=15');
        }

        // Save the image path in the database
        var personId = req.body.personid;
        // read the file
        var buf = fs.readFileSync(imagepath);
        var sql = "UPDATE HUELLA.NPERSONAS SET HUELLA.NPERSONAS.FOTO = :blob WHERE HUELLA.NPERSONAS.IDPERSONA =" + personId;

        // Save image route
        oracledb.autoCommit = true;
        oracledb.getConnection({
            user            : process.env.ORACLE_USERNAME,
            password        : process.env.ORACLE_PASSWORD,
            connectString   : process.env.ORACLE_HOST + ':' + process.env.ORACLE_PORT
            + '/' + process.env.ORACLE_SID
        }, function (err, connection) {
            if (err){
                logger.error(err.message);
                // error=0 trying to connect with database
                return res.redirect('/dashboard/images?error=0');
            }
            connection.execute(
                sql,
                [buf],
                // The Callback function handles the SQL execution results
                function (err, result) {
                    if (err) {
                        logger.error(err.message);
                        connection.close(
                            function(err) {
                                if (err) {
                                    // error=1 trying to disconnect of database
                                    logger.error(err.message);
                                    return res.redirect('/dashboard/images?error=1');
                                }
                                logger.info('Connection to Oracle closed successfully!');
                            });
                        // Error doing select statement
                        return res.redirect('/dashboard/images?error=12');
                    }

                    logger.info(result);

                    // UPDATE image capture success
                    connection.close(
                        function(err) {
                            if (err) {
                                // error=1 trying to disconnect of database
                                logger.error(err.message);
                                return res.redirect('/dashboard/images?error=1');
                            }
                            logger.info('Connection to Oracle closed successfully!');
                        });
                    res.redirect('/dashboard/images?flag=success');
                }
            );
        });
    });
});

/* POST Images handler page | Dashboard. */
dashRoutes.post('/dashboard/images/input', upload.single('inputpicture'), function (req, res) {
    if( typeof req.body.personid === 'undefined' || req.body.personid === ''){
        logger.info('Login credentials: Empty values.');
        // error=12 No person Id using image capture.
        return res.redirect('/login?error=12');
    }

    logger.info(req.file);
    //logger.info(req.body);

    var personId = req.body.personid;

    // read the file
    var buf = fs.readFileSync(req.file.path);

    /*var sql = "UPDATE HUELLA.NPERSONAS SET HUELLA.NPERSONAS.FOTO = " +
     buf + " WHERE HUELLA.NPERSONAS.IDPERSONA =" + personId;*/

    var sql = "UPDATE HUELLA.NPERSONAS SET HUELLA.NPERSONAS.FOTO = :blob WHERE HUELLA.NPERSONAS.IDPERSONA =" + personId;

    // Save image route
    oracledb.autoCommit = true;
    oracledb.getConnection({
        user            : process.env.ORACLE_USERNAME,
        password        : process.env.ORACLE_PASSWORD,
        connectString   : process.env.ORACLE_HOST + ':' + process.env.ORACLE_PORT
        + '/' + process.env.ORACLE_SID
    }, function (err, connection) {
        if (err){
            logger.error(err.message);
            // error=0 trying to connect with database
            return res.redirect('/dashboard/images?error=0');
        }

        connection.execute(
            sql,
            [buf],
            // The Callback function handles the SQL execution results
            function (err, result) {
                if (err) {
                    logger.error(err.message);
                    connection.close(
                        function(err) {
                            if (err) {
                                // error=1 trying to disconnect of database
                                logger.error(err.message);
                                return res.redirect('/dashboard/images?error=1');
                            }
                            logger.info('Connection to Oracle closed successfully!');
                        });
                    // Error doing select statement
                    return res.redirect('/dashboard/images?error=12');
                }

                if (result.rowsAffected != 1) {
                    logger.info('Error updating the image');
                    return res.redirect('/dashboard/images?error=2');
                }

                logger.info(result);

                // UPDATE image capture success
                connection.close(
                    function(err) {
                        if (err) {
                            // error=1 trying to disconnect of database
                            logger.error(err.message);
                            return res.redirect('/dashboard/images?error=1');
                        }
                        logger.info('Connection to Oracle closed successfully!');
                    });
                res.redirect('/dashboard/images?flag=success');
            }
        );
    });
});

/* GET Fingerprint applet page. */
dashRoutes.get('/applet', function (req, res) {
    var error = '';
    // Basic error validator
    // Error
    if(typeof req.query.error !== 'undefined'){
        error = req.query.error;
    }
    // Session
    if(typeof req.session.userId === 'undefined' || typeof req.session.userId === ''){
        return res.redirect('/login');
    }
    // User Rol
    // If ............
    res.render('dash/applet', {
        title   : 'Applet | Identico',
        level   : '',
        layout  : 'dash',
        error   : error
    });
});

module.exports = dashRoutes;<|endoftext|>


<commit_before>Utils = {
  loadTemplates: function() {
    var templates = {};
    $('*[type="text/x-js-template"]').map(function() {
      var name = $(this).attr('name');
      var source = $(this).html().replace('>', '>');
      if(name.split('/')[1][0] == '_') { Handlebars.registerPartial(name.replace('/', ''), source) }
      templates[name] = Handlebars.compile(source);
    });
    return templates;
  },
  queryString: function(params) {
    if(!params) return '';
    var query = _.compact(_.map(params, function(value, key) { return value ? key + '=' + value : null }));
    return query.length > 0 ? '?' + query.join('&') : '';
  },
  duration: function(started, finished) {
    started  = new Date(started);
    finished = finished ? new Date(finished) : new Date();
    return started ? Math.round((finished - started) / 1000) : 0;
  },
  activateTab: function(element, tab) {
    $('.tabs li', element).removeClass('active');
    $('#tab_' + tab.toLowerCase(), element).addClass('active');
  },
  animated: function(element) {
    return !!element.queue()[0];
  },
  flash: function(element) {
    if(!element.length == 0 && !Utils.animated(element)) {
      Utils._flash(element);
    }
  },
  _flash: function(element) {
    element.effect('highlight', {}, 1000, function () {
      Utils._flash(element)
    });
  },
  unflash: function(element) {
    if(!element.length == 0) {
      element.stop().css({ 'background-color': '', 'background-image': '' });
    }
  },
  filterLog: function(string) {
    // string = Handlebars.Utils.escapeExpression(string);
    string = Utils.stripPaths(string);
    string = Utils.escapeRuby(string);
    string = Utils.foldLog(string);
    string = Deansi.parse(string);
    return string;
  },
  stripPaths: function(string) {
    return string.replace(/\/tmp\/travis\/builds(\/[^\/\n]+){2}\//g, '');
  },
  escapeRuby: function(string) {
    return string.replace(/#<(\w+.*?)>/, '#<$1>');
  },
  foldLog: function(string) {
    string = Utils.unfoldLog(string);
    var folds = {
      // 'clone': /(^|<\/div>)(\$ git clone.*\r?\n(?:(Initialized|remote:|Receiving|Resolving).*?\r?\n)*)/m,
      // 'clean':   /(^|<\\/div>)(\\$ git clean.*\\r?\\n(?:Removing .*\\r?\\n)+\\r?\\n*)/gm,
      // 'fetch':   /(^|<\\/div>)(\\$ git fetch.*\\r?\\nFrom .*\\n.*)\\r?\\n/gm,
      'bundle':  /(^|<\/div>)(\$ bundle install.*\r?\n*(?:(Fetching|Updating|Using|Installing|remote:|Receiving|Resolving|Unpacking).+\r?\n*)*)/gm,
      'migrate': /(^|<\/div>)(\$ rake db:migrate[\s\S]*(?:^== +\w+: migrated \(.*\) =+\r?\n))\r?\n?/gm,
      'exec':    /(^|<\/div>)(\/home\/([^\/]+)\/.rvm\/rubies\/\S*?\/(ruby|rbx|jruby) .*?)\r?\n/gm
    };
    _.each(folds, function(fold, type) {
      string = string.replace(fold, function() { return arguments[1] + '
' + arguments[2].trim() + '
'; });
    });
    string = string.replace(/([\.-_*SEF]{120})\n?/g, '$1\n')
    return string;
  },
  unfoldLog: function(string) {
    return string.replace(/
([\s\S]*?)<\/div>/mg, '$1\n');
  },
  updateTimes: function(element) {
    $('.timeago', element).timeago();
    $('.duration', element).readableTime();

    if(!Utils._updateTimesInterval) {
      Utils._updateTimesInterval = setInterval(function() { Utils.updateTimes() }, 3000);
    }
  },
  readableTime: function(duration) {
    var days    = Math.floor(duration / 86400)
    var hours   = Math.floor(duration % 86400 / 3600);
    var minutes = Math.floor(duration % 3600 / 60);
    var seconds = duration % 60;

    if(days > 0) {
      return 'more than 24 hrs';
    } else {
      var result = [];
      if(hours   > 0) { result.push(hours + ' hrs'); }
      if(minutes > 0) { result.push(minutes + ' min'); }
      if(seconds > 0) { result.push(seconds + ' sec'); }
      return result.length > 0 ? result.join(' ') : '-';
    }
  },
  updateGithubStats: function(repository, element) {
    if(!window.__TESTING__) {
      $.getJSON('http://github.com/api/v2/json/repos/show/' + repository.get('slug') + '?callback=?', function(data) {
        var url = 'http://github.com/' + repository.get('slug');
        element.find('.watchers').attr('href', url + '/watchers').text(data.repository.watchers);
        element.find('.forks').attr('href', url + '/network').text(data.repository.forks);
      });
    }
  }
}

function trace() {
  try {
    i.dont.exist; // force an exception
  } catch(e) {
    var lines = e.stack.split('\n').slice(2);
    var stack = _.map(lines, function(line) { return line.replace(/^\s*at/, ''); });
    console.log('trace -------------------------------');
    _.each(stack, function(line) { console.log(line); });
  }
}

<commit_msg>Adding line breaks to separate build by line.<commit_after>Utils = {
  loadTemplates: function() {
    var templates = {};
    $('*[type="text/x-js-template"]').map(function() {
      var name = $(this).attr('name');
      var source = $(this).html().replace('>', '>');
      if(name.split('/')[1][0] == '_') { Handlebars.registerPartial(name.replace('/', ''), source) }
      templates[name] = Handlebars.compile(source);
    });
    return templates;
  },
  queryString: function(params) {
    if(!params) return '';
    var query = _.compact(_.map(params, function(value, key) { return value ? key + '=' + value : null }));
    return query.length > 0 ? '?' + query.join('&') : '';
  },
  duration: function(started, finished) {
    started  = new Date(started);
    finished = finished ? new Date(finished) : new Date();
    return started ? Math.round((finished - started) / 1000) : 0;
  },
  activateTab: function(element, tab) {
    $('.tabs li', element).removeClass('active');
    $('#tab_' + tab.toLowerCase(), element).addClass('active');
  },
  animated: function(element) {
    return !!element.queue()[0];
  },
  flash: function(element) {
    if(!element.length == 0 && !Utils.animated(element)) {
      Utils._flash(element);
    }
  },
  _flash: function(element) {
    element.effect('highlight', {}, 1000, function () {
      Utils._flash(element)
    });
  },
  unflash: function(element) {
    if(!element.length == 0) {
      element.stop().css({ 'background-color': '', 'background-image': '' });
    }
  },
  filterLog: function(string) {
    // string = Handlebars.Utils.escapeExpression(string);
    string = Utils.stripPaths(string);
    string = Utils.escapeRuby(string);
    string = Utils.foldLog(string);
    string = Deansi.parse(string);
    string = Utils.breakLines(string);
    return string;
  },
  stripPaths: function(string) {
    return string.replace(/\/tmp\/travis\/builds(\/[^\/\n]+){2}\//g, '');
  },
  escapeRuby: function(string) {
    return string.replace(/#<(\w+.*?)>/, '#<$1>');
  },
  breakLines: function(string) {
    var newstring = "";
    var counter = 0;
    _.each(string.split('\n'), function (line) {
      counter++;
      newstring += "
" + counter+ "" + line + "
"
    })
    return newstring;
  },
  foldLog: function(string) {
    string = Utils.unfoldLog(string);
    var folds = {
      // 'clone': /(^|<\/div>)(\$ git clone.*\r?\n(?:(Initialized|remote:|Receiving|Resolving).*?\r?\n)*)/m,
      // 'clean':   /(^|<\\/div>)(\\$ git clean.*\\r?\\n(?:Removing .*\\r?\\n)+\\r?\\n*)/gm,
      // 'fetch':   /(^|<\\/div>)(\\$ git fetch.*\\r?\\nFrom .*\\n.*)\\r?\\n/gm,
      'bundle':  /(^|<\/div>)(\$ bundle install.*\r?\n*(?:(Fetching|Updating|Using|Installing|remote:|Receiving|Resolving|Unpacking).+\r?\n*)*)/gm,
      'migrate': /(^|<\/div>)(\$ rake db:migrate[\s\S]*(?:^== +\w+: migrated \(.*\) =+\r?\n))\r?\n?/gm,
      'exec':    /(^|<\/div>)(\/home\/([^\/]+)\/.rvm\/rubies\/\S*?\/(ruby|rbx|jruby) .*?)\r?\n/gm
    };
    _.each(folds, function(fold, type) {
      string = string.replace(fold, function() { return arguments[1] + '
\n' + arguments[2].trim() + '
\n'; });
    });
    string = string.replace(/([\.-_*SEF]{120})\n?/g, '$1\n')
    return string;
  },
  unfoldLog: function(string) {
    return string.replace(/
([\s\S]*?)<\/div>/mg, '$1\n');
  },
  updateTimes: function(element) {
    $('.timeago', element).timeago();
    $('.duration', element).readableTime();

    if(!Utils._updateTimesInterval) {
      Utils._updateTimesInterval = setInterval(function() { Utils.updateTimes() }, 3000);
    }
  },
  readableTime: function(duration) {
    var days    = Math.floor(duration / 86400)
    var hours   = Math.floor(duration % 86400 / 3600);
    var minutes = Math.floor(duration % 3600 / 60);
    var seconds = duration % 60;

    if(days > 0) {
      return 'more than 24 hrs';
    } else {
      var result = [];
      if(hours   > 0) { result.push(hours + ' hrs'); }
      if(minutes > 0) { result.push(minutes + ' min'); }
      if(seconds > 0) { result.push(seconds + ' sec'); }
      return result.length > 0 ? result.join(' ') : '-';
    }
  },
  updateGithubStats: function(repository, element) {
    if(!window.__TESTING__) {
      $.getJSON('http://github.com/api/v2/json/repos/show/' + repository.get('slug') + '?callback=?', function(data) {
        var url = 'http://github.com/' + repository.get('slug');
        element.find('.watchers').attr('href', url + '/watchers').text(data.repository.watchers);
        element.find('.forks').attr('href', url + '/network').text(data.repository.forks);
      });
    }
  }
}

function trace() {
  try {
    i.dont.exist; // force an exception
  } catch(e) {
    var lines = e.stack.split('\n').slice(2);
    var stack = _.map(lines, function(line) { return line.replace(/^\s*at/, ''); });
    console.log('trace -------------------------------');
    _.each(stack, function(line) { console.log(line); });
  }
}
<|endoftext|>


<commit_before>/**
 * core/widgets data store: widget tests.
 *
 * Site Kit by Google, Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Internal dependencies
 */
import {
	createTestRegistry,
	unsubscribeFromAll,
	muteConsole,
} from '../../../../../tests/js/utils';
import { STORE_NAME } from './constants';

describe( 'core/widgets Widget areas', () => {
	let registry;
	let store;

	beforeEach( () => {
		registry = createTestRegistry();
		store = registry.stores[ STORE_NAME ].store;
	} );

	afterEach( () => {
		unsubscribeFromAll( registry );
	} );

	describe( 'actions', () => {
		describe( 'assignWidgetArea', () => {
			it( 'should implicitly create a context when assigning a widget area, if one does not exist', () => {
				// Assign this widget area to the dashboard context.
				registry.dispatch( STORE_NAME ).assignWidgetArea( 'header', 'dashboard' );

				const { contextAssignments } = store.getState();

				expect( contextAssignments.dashboard ).toEqual( [ 'header' ] );
			} );

			it( 'should re-use a context if one is already created', () => {
				registry.dispatch( STORE_NAME ).assignWidgetArea( 'header', 'dashboard' );
				registry.dispatch( STORE_NAME ).assignWidgetArea( 'footer', 'dashboard' );

				const { contextAssignments } = store.getState();

				expect( contextAssignments.dashboard ).toEqual( [ 'header', 'footer' ] );
			} );

			it( 'should assign a registered widget area to a context', () => {
				// Register the widget area.
				const slug = 'header';
				const settings = {
					priority: 10,
					title: 'Your Site',
					subtitle: 'Learn about your site!',
					icon: '/wp-content/plugins/googlesitekit/header.svg',
					style: 'boxes',
				};
				registry.dispatch( STORE_NAME ).registerWidgetArea( slug, settings );

				// Assign this widget area to the dashboard context.
				registry.dispatch( STORE_NAME ).assignWidgetArea( slug, 'dashboard' );

				// Get all assigned widget areas for the dashboard context.
				const dashboardAreas = registry.select( STORE_NAME ).getWidgetAreas( 'dashboard' );

				expect( dashboardAreas ).toHaveLength( 1 );
				expect( dashboardAreas.some( ( area ) => area.slug === slug ) ).toEqual( true );
			} );
		} );

		describe( 'registerWidgetArea', () => {
			it( 'should register a widget area', () => {
				const slug = 'header';
				const settings = {
					priority: 10,
					title: 'Your Site',
					subtitle: 'Learn about your site!',
					icon: '/wp-content/plugins/googlesitekit/header.svg',
					style: 'boxes',
				};
				registry.dispatch( STORE_NAME ).registerWidgetArea( slug, settings );
				const state = store.getState();

				expect( registry.select( STORE_NAME ).isWidgetAreaRegistered( slug ) ).toEqual( true );
				// There is no selector for unassigned widget areas, so we inspect the store directly for
				// this test.
				expect( state.areas ).toMatchObject( {
					[ slug ]: { ...settings, slug },
				} );
			} );

			it( 'requires a slug', () => {
				expect( () => {
					registry.dispatch( STORE_NAME ).registerWidgetArea( null, {} );
				} ).toThrow( 'slug is required.' );
			} );

			it( 'requires settings', () => {
				// (It will throw for the first missing param, because the settings argument is
				// always defined .)
				expect( () => {
					registry.dispatch( STORE_NAME ).registerWidgetArea( 'my-cool-slug' );
				} ).toThrow( 'settings.title is required.' );
			} );

			it( 'requires a title and subtitle in settings', () => {
				// Mute warning about duplicate slug registrations for this test.
				muteConsole( 'warn' );

				expect( () => {
					registry.dispatch( STORE_NAME ).registerWidgetArea( 'header', {} );
				} ).toThrow( 'settings.title is required.' );

				expect( () => {
					registry.dispatch( STORE_NAME ).registerWidgetArea( 'header', {
						title: 'Analytics Header',
					} );
				} ).toThrow( 'settings.subtitle is required.' );

				expect( () => {
					registry.dispatch( STORE_NAME ).registerWidgetArea( 'header', {
						title: 'Analytics Header',
						subtitle: 'Analytics tell you about visitors',
					} );
				} ).not.toThrow();

				expect( () => {
					registry.dispatch( STORE_NAME ).registerWidgetArea( 'header', {
						title: 'Analytics Header',
						subtitle: 'Analytics tell you about visitors',
						style: 'composite',
					} );
				} ).not.toThrow();
			} );

			it( 'should register multiple widget areas', () => {
				const slugOne = 'dashboard-header';
				const settingsOne = {
					priority: 10,
					title: 'Header',
					subtitle: 'Cool stuff only!',
					icon: '/wp-content/plugins/googlesitekit/header.svg',
					style: 'boxes',
				};
				const slugTwo = 'dashboard-footer';
				const settingsTwo = {
					priority: 12,
					title: 'Footer',
					subtitle: 'Less important stuff.',
					icon: '/wp-content/plugins/googlesitekit/footer.svg',
					style: 'boxes',
				};
				registry.dispatch( STORE_NAME ).registerWidgetArea( slugOne, settingsOne );
				registry.dispatch( STORE_NAME ).registerWidgetArea( slugTwo, settingsTwo );
				const state = store.getState();

				expect( registry.select( STORE_NAME ).isWidgetAreaRegistered( slugOne ) ).toEqual( true );
				expect( registry.select( STORE_NAME ).isWidgetAreaRegistered( slugTwo ) ).toEqual( true );
				// There is no selector for unassigned widget areas, so we inspect the store directly for
				// this test.
				expect( state.areas ).toMatchObject( {
					[ slugOne ]: { ...settingsOne, slug: slugOne },
					[ slugTwo ]: { ...settingsTwo, slug: slugTwo },
				} );
			} );

			it( 'should use priority: 10 as a default', () => {
				const slug = 'pageviews';
				const settings = {
					title: 'Page Views',
					subtitle: 'See all your views!',
					icon: '/wp-content/plugins/googlesitekit/pageviews.svg',
					style: 'boxes', // 'composite'
				};
				registry.dispatch( STORE_NAME ).registerWidgetArea( slug, settings );
				const state = store.getState();

				expect( registry.select( STORE_NAME ).isWidgetAreaRegistered( slug ) ).toEqual( true );
				// There is no selector for unassigned widget areas, so we inspect the store directly for
				// this test.
				expect( state.areas ).toMatchObject( {
					[ slug ]: { ...settings, priority: 10, slug },
				} );
			} );

			it( 'should not overwrite an existing widget area', () => {
				const slug = 'pageviews';
				const settings = {
					priority: 10,
					title: 'Page Views',
					subtitle: 'See all your views!',
					icon: '/wp-content/plugins/googlesitekit/pageviews.svg',
					style: 'boxes', // 'composite'
				};
				// We don't want other widget areas to be able to overwrite existing areas.
				const differentSettings = {
					priority: 10,
					title: 'Mega Page Views',
					subtitle: 'Subscribe for more features!',
					icon: '/wp-content/plugins/googlesitekit/pageviews.svg',
					style: 'composite',
				};
				registry.dispatch( STORE_NAME ).registerWidgetArea( slug, settings );

				// Mute warning about duplicate slug since we expect it below anyway.
				muteConsole( 'warn' );

				// Expect console warning about duplicate slug.
				const consoleWarnSpy = jest.spyOn( global.console, 'warn' );
				registry.dispatch( STORE_NAME ).registerWidgetArea( slug, differentSettings );
				expect( consoleWarnSpy ).toHaveBeenCalledWith( `Could not register widget area with slug "${ slug }". Widget area "${ slug }" is already registered.` );
				consoleWarnSpy.mockClear();

				const state = store.getState();

				// Ensure the original settings are registered.
				expect( state.areas ).toMatchObject( {
					[ slug ]: { ...settings, slug },
				} );
				expect( state.areas ).not.toMatchObject( {
					[ slug ]: { ...differentSettings, slug },
				} );
			} );
		} );
	} );

	describe( 'selectors', () => {
		describe( 'getWidgetAreas', () => {
			it( 'requires a contextSlug', () => {
				expect( () => {
					registry.select( STORE_NAME ).getWidgetAreas();
				} ).toThrow( 'contextSlug is required.' );
			} );

			it( 'returns all registered widget areas', () => {
				// Register the widget area.
				const slugOne = 'header';
				const slugTwo = 'subheader';
				const settings = {
					priority: 10,
					title: 'Your Site',
					subtitle: 'Learn about your site!',
					icon: '/wp-content/plugins/googlesitekit/header.svg',
					style: 'boxes',
				};
				registry.dispatch( STORE_NAME ).registerWidgetArea( slugOne, settings );
				registry.dispatch( STORE_NAME ).registerWidgetArea( slugTwo, settings );

				// Assign this widget area to the dashboard context.
				registry.dispatch( STORE_NAME ).assignWidgetArea( slugOne, 'dashboard' );
				registry.dispatch( STORE_NAME ).assignWidgetArea( slugTwo, 'dashboard' );

				// Get all assigned widget areas for the dashboard context.
				const dashboardAreas = registry.select( STORE_NAME ).getWidgetAreas( 'dashboard' );

				expect( dashboardAreas ).toMatchObject( [
					{ ...settings, slug: slugOne },
					{ ...settings, slug: slugTwo },
				] );
			} );

			it( 'does not return unregistered widget areas', () => {
				// Assign this widget area to the dashboard context.
				registry.dispatch( STORE_NAME ).assignWidgetArea( 'area-one', 'dashboard' );
				registry.dispatch( STORE_NAME ).assignWidgetArea( 'area-two', 'dashboard' );

				// Get all assigned widget areas for the dashboard context.
				const dashboardAreas = registry.select( STORE_NAME ).getWidgetAreas( 'dashboard' );

				expect( dashboardAreas ).toHaveLength( 0 );
			} );

			it( 'returns widget areas that were registered after they were assigned', () => {
				const slugOne = 'header';
				const slugTwo = 'subheader';

				// Assign this widget area to the dashboard context.
				registry.dispatch( STORE_NAME ).assignWidgetArea( slugOne, 'dashboard' );
				registry.dispatch( STORE_NAME ).assignWidgetArea( slugTwo, 'dashboard' );

				// Register the widget areas.
				const settings = {
					priority: 10,
					title: 'Your Site',
					subtitle: 'Learn about your site!',
					icon: '/wp-content/plugins/googlesitekit/header.svg',
					style: 'boxes',
				};
				registry.dispatch( STORE_NAME ).registerWidgetArea( slugOne, settings );
				registry.dispatch( STORE_NAME ).registerWidgetArea( slugTwo, settings );

				// Get all assigned widget areas for the dashboard context.
				const dashboardAreas = registry.select( STORE_NAME ).getWidgetAreas( 'dashboard' );

				expect( dashboardAreas ).toMatchObject( [
					{ ...settings, slug: slugOne },
					{ ...settings, slug: slugTwo },
				] );
			} );

			it( 'returns the widget areas sorted by priority', () => {
				// Register the widget area.
				const slugLowest = 'header';
				const slugMedium = 'header2';
				const slugMediumTwo = 'header3';
				const slugHighest = 'header4';
				const settings = {
					title: 'Your title',
					subtitle: 'Okay!',
					icon: '/wp-content/plugins/googlesitekit/header.svg',
					style: 'boxes',
				};
				registry.dispatch( STORE_NAME ).registerWidgetArea( slugLowest, { ...settings, priority: 5 } );
				registry.dispatch( STORE_NAME ).registerWidgetArea( slugMedium, { ...settings, priority: 10 } );
				registry.dispatch( STORE_NAME ).registerWidgetArea( slugMediumTwo, { ...settings, priority: 10 } );
				registry.dispatch( STORE_NAME ).registerWidgetArea( slugHighest, { ...settings, priority: 15 } );

				// Assign this widget area to the dashboard context.
				registry.dispatch( STORE_NAME ).assignWidgetArea( slugLowest, 'dashboard' );
				registry.dispatch( STORE_NAME ).assignWidgetArea( slugMedium, 'dashboard' );
				registry.dispatch( STORE_NAME ).assignWidgetArea( slugMediumTwo, 'dashboard' );
				registry.dispatch( STORE_NAME ).assignWidgetArea( slugHighest, 'dashboard' );

				// Get all assigned widget areas for the dashboard context.
				const dashboardAreas = registry.select( STORE_NAME ).getWidgetAreas( 'dashboard' );

				// The lowest priority appears first.
				expect( dashboardAreas[ 0 ] ).toMatchObject( { ...settings, slug: slugLowest } );
				// Widgets assigned with the same priority should be last-in, last-out.
				expect( dashboardAreas[ 1 ] ).toMatchObject( { ...settings, slug: slugMedium } );
				expect( dashboardAreas[ 2 ] ).toMatchObject( { ...settings, slug: slugMediumTwo } );
				expect( dashboardAreas[ 3 ] ).toMatchObject( { ...settings, slug: slugHighest } );
			} );
		} );

		describe( 'getWidgetArea', () => {
			it( 'returns an area if the widget area is registered', () => {
				registry.dispatch( STORE_NAME ).registerWidgetArea( 'TestArea', {
					title: 'Test Header',
					subtitle: 'Cool stuff for yoursite.com',
					style: 'composite',
				} );

				expect( registry.select( STORE_NAME ).getWidgetArea( 'TestArea' ) ).toEqual( {
					icon: undefined,
					priority: 10,
					title: 'Test Header',
					subtitle: 'Cool stuff for yoursite.com',
					style: 'composite',
					slug: 'TestArea',
				} );
			} );

			it( 'returns null if the widget area is not registered', () => {
				expect( registry.select( STORE_NAME ).getWidgetArea( 'NotRealArea' ) ).toEqual( null );
			} );
		} );

		describe( 'isWidgetAreaRegistered', () => {
			it( 'returns true if the widget area is registered', () => {
				registry.dispatch( STORE_NAME ).registerWidgetArea( 'TestArea', {
					title: 'Test Header',
					subtitle: 'Cool stuff for yoursite.com',
					style: 'composite',
				} );

				expect( registry.select( STORE_NAME ).isWidgetAreaRegistered( 'TestArea' ) ).toEqual( true );
			} );

			it( 'returns false if the widget area is not registered', () => {
				expect( registry.select( STORE_NAME ).isWidgetAreaRegistered( 'NotRealArea' ) ).toEqual( false );
			} );
		} );
	} );
} );
<commit_msg>Fix widget area tests.<commit_after>/**
 * core/widgets data store: widget tests.
 *
 * Site Kit by Google, Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Internal dependencies
 */
import {
	createTestRegistry,
	unsubscribeFromAll,
	muteConsole,
} from '../../../../../tests/js/utils';
import { STORE_NAME } from './constants';

describe( 'core/widgets Widget areas', () => {
	let registry;
	let store;

	beforeEach( () => {
		registry = createTestRegistry();
		store = registry.stores[ STORE_NAME ].store;
	} );

	afterEach( () => {
		unsubscribeFromAll( registry );
	} );

	describe( 'actions', () => {
		describe( 'assignWidgetArea', () => {
			it( 'should implicitly create a context when assigning a widget area, if one does not exist', () => {
				// Assign this widget area to the testarea context.
				registry.dispatch( STORE_NAME ).assignWidgetArea( 'header', 'testarea' );

				const { contextAssignments } = store.getState();

				expect( contextAssignments.testarea ).toEqual( [ 'header' ] );
			} );

			it( 'should re-use a context if one is already created', () => {
				registry.dispatch( STORE_NAME ).assignWidgetArea( 'header', 'testarea' );
				registry.dispatch( STORE_NAME ).assignWidgetArea( 'footer', 'testarea' );

				const { contextAssignments } = store.getState();

				expect( contextAssignments.testarea ).toEqual( [ 'header', 'footer' ] );
			} );

			it( 'should assign a registered widget area to a context', () => {
				// Register the widget area.
				const slug = 'header';
				const settings = {
					priority: 10,
					title: 'Your Site',
					subtitle: 'Learn about your site!',
					icon: '/wp-content/plugins/googlesitekit/header.svg',
					style: 'boxes',
				};
				registry.dispatch( STORE_NAME ).registerWidgetArea( slug, settings );

				// Assign this widget area to the testarea context.
				registry.dispatch( STORE_NAME ).assignWidgetArea( slug, 'testarea' );

				// Get all assigned widget areas for the testarea context.
				const testareaAreas = registry.select( STORE_NAME ).getWidgetAreas( 'testarea' );

				expect( testareaAreas ).toHaveLength( 1 );
				expect( testareaAreas.some( ( area ) => area.slug === slug ) ).toEqual( true );
			} );
		} );

		describe( 'registerWidgetArea', () => {
			it( 'should register a widget area', () => {
				const slug = 'header';
				const settings = {
					priority: 10,
					title: 'Your Site',
					subtitle: 'Learn about your site!',
					icon: '/wp-content/plugins/googlesitekit/header.svg',
					style: 'boxes',
				};
				registry.dispatch( STORE_NAME ).registerWidgetArea( slug, settings );
				const state = store.getState();

				expect( registry.select( STORE_NAME ).isWidgetAreaRegistered( slug ) ).toEqual( true );
				// There is no selector for unassigned widget areas, so we inspect the store directly for
				// this test.
				expect( state.areas ).toMatchObject( {
					[ slug ]: { ...settings, slug },
				} );
			} );

			it( 'requires a slug', () => {
				expect( () => {
					registry.dispatch( STORE_NAME ).registerWidgetArea( null, {} );
				} ).toThrow( 'slug is required.' );
			} );

			it( 'requires settings', () => {
				// (It will throw for the first missing param, because the settings argument is
				// always defined .)
				expect( () => {
					registry.dispatch( STORE_NAME ).registerWidgetArea( 'my-cool-slug' );
				} ).toThrow( 'settings.title is required.' );
			} );

			it( 'requires a title and subtitle in settings', () => {
				// Mute warning about duplicate slug registrations for this test.
				muteConsole( 'warn' );

				expect( () => {
					registry.dispatch( STORE_NAME ).registerWidgetArea( 'header', {} );
				} ).toThrow( 'settings.title is required.' );

				expect( () => {
					registry.dispatch( STORE_NAME ).registerWidgetArea( 'header', {
						title: 'Analytics Header',
					} );
				} ).toThrow( 'settings.subtitle is required.' );

				expect( () => {
					registry.dispatch( STORE_NAME ).registerWidgetArea( 'header', {
						title: 'Analytics Header',
						subtitle: 'Analytics tell you about visitors',
					} );
				} ).not.toThrow();

				expect( () => {
					registry.dispatch( STORE_NAME ).registerWidgetArea( 'header', {
						title: 'Analytics Header',
						subtitle: 'Analytics tell you about visitors',
						style: 'composite',
					} );
				} ).not.toThrow();
			} );

			it( 'should register multiple widget areas', () => {
				const slugOne = 'dashboard-header';
				const settingsOne = {
					priority: 10,
					title: 'Header',
					subtitle: 'Cool stuff only!',
					icon: '/wp-content/plugins/googlesitekit/header.svg',
					style: 'boxes',
				};
				const slugTwo = 'dashboard-footer';
				const settingsTwo = {
					priority: 12,
					title: 'Footer',
					subtitle: 'Less important stuff.',
					icon: '/wp-content/plugins/googlesitekit/footer.svg',
					style: 'boxes',
				};
				registry.dispatch( STORE_NAME ).registerWidgetArea( slugOne, settingsOne );
				registry.dispatch( STORE_NAME ).registerWidgetArea( slugTwo, settingsTwo );
				const state = store.getState();

				expect( registry.select( STORE_NAME ).isWidgetAreaRegistered( slugOne ) ).toEqual( true );
				expect( registry.select( STORE_NAME ).isWidgetAreaRegistered( slugTwo ) ).toEqual( true );
				// There is no selector for unassigned widget areas, so we inspect the store directly for
				// this test.
				expect( state.areas ).toMatchObject( {
					[ slugOne ]: { ...settingsOne, slug: slugOne },
					[ slugTwo ]: { ...settingsTwo, slug: slugTwo },
				} );
			} );

			it( 'should use priority: 10 as a default', () => {
				const slug = 'pageviews';
				const settings = {
					title: 'Page Views',
					subtitle: 'See all your views!',
					icon: '/wp-content/plugins/googlesitekit/pageviews.svg',
					style: 'boxes', // 'composite'
				};
				registry.dispatch( STORE_NAME ).registerWidgetArea( slug, settings );
				const state = store.getState();

				expect( registry.select( STORE_NAME ).isWidgetAreaRegistered( slug ) ).toEqual( true );
				// There is no selector for unassigned widget areas, so we inspect the store directly for
				// this test.
				expect( state.areas ).toMatchObject( {
					[ slug ]: { ...settings, priority: 10, slug },
				} );
			} );

			it( 'should not overwrite an existing widget area', () => {
				const slug = 'pageviews';
				const settings = {
					priority: 10,
					title: 'Page Views',
					subtitle: 'See all your views!',
					icon: '/wp-content/plugins/googlesitekit/pageviews.svg',
					style: 'boxes', // 'composite'
				};
				// We don't want other widget areas to be able to overwrite existing areas.
				const differentSettings = {
					priority: 10,
					title: 'Mega Page Views',
					subtitle: 'Subscribe for more features!',
					icon: '/wp-content/plugins/googlesitekit/pageviews.svg',
					style: 'composite',
				};
				registry.dispatch( STORE_NAME ).registerWidgetArea( slug, settings );

				// Mute warning about duplicate slug since we expect it below anyway.
				muteConsole( 'warn' );

				// Expect console warning about duplicate slug.
				const consoleWarnSpy = jest.spyOn( global.console, 'warn' );
				registry.dispatch( STORE_NAME ).registerWidgetArea( slug, differentSettings );
				expect( consoleWarnSpy ).toHaveBeenCalledWith( `Could not register widget area with slug "${ slug }". Widget area "${ slug }" is already registered.` );
				consoleWarnSpy.mockClear();

				const state = store.getState();

				// Ensure the original settings are registered.
				expect( state.areas ).toMatchObject( {
					[ slug ]: { ...settings, slug },
				} );
				expect( state.areas ).not.toMatchObject( {
					[ slug ]: { ...differentSettings, slug },
				} );
			} );
		} );
	} );

	describe( 'selectors', () => {
		describe( 'getWidgetAreas', () => {
			it( 'requires a contextSlug', () => {
				expect( () => {
					registry.select( STORE_NAME ).getWidgetAreas();
				} ).toThrow( 'contextSlug is required.' );
			} );

			it( 'returns all registered widget areas', () => {
				// Register the widget area.
				const slugOne = 'header';
				const slugTwo = 'subheader';
				const settings = {
					priority: 10,
					title: 'Your Site',
					subtitle: 'Learn about your site!',
					icon: '/wp-content/plugins/googlesitekit/header.svg',
					style: 'boxes',
				};
				registry.dispatch( STORE_NAME ).registerWidgetArea( slugOne, settings );
				registry.dispatch( STORE_NAME ).registerWidgetArea( slugTwo, settings );

				// Assign this widget area to the testarea context.
				registry.dispatch( STORE_NAME ).assignWidgetArea( slugOne, 'testarea' );
				registry.dispatch( STORE_NAME ).assignWidgetArea( slugTwo, 'testarea' );

				// Get all assigned widget areas for the testarea context.
				const testareaAreas = registry.select( STORE_NAME ).getWidgetAreas( 'testarea' );

				expect( testareaAreas ).toMatchObject( [
					{ ...settings, slug: slugOne },
					{ ...settings, slug: slugTwo },
				] );
			} );

			it( 'does not return unregistered widget areas', () => {
				// Assign this widget area to the testarea context.
				registry.dispatch( STORE_NAME ).assignWidgetArea( 'area-one', 'testarea' );
				registry.dispatch( STORE_NAME ).assignWidgetArea( 'area-two', 'testarea' );

				// Get all assigned widget areas for the testarea context.
				const testareaAreas = registry.select( STORE_NAME ).getWidgetAreas( 'testarea' );

				expect( testareaAreas ).toHaveLength( 0 );
			} );

			it( 'returns widget areas that were registered after they were assigned', () => {
				const slugOne = 'header';
				const slugTwo = 'subheader';

				// Assign this widget area to the testarea context.
				registry.dispatch( STORE_NAME ).assignWidgetArea( slugOne, 'testarea' );
				registry.dispatch( STORE_NAME ).assignWidgetArea( slugTwo, 'testarea' );

				// Register the widget areas.
				const settings = {
					priority: 10,
					title: 'Your Site',
					subtitle: 'Learn about your site!',
					icon: '/wp-content/plugins/googlesitekit/header.svg',
					style: 'boxes',
				};
				registry.dispatch( STORE_NAME ).registerWidgetArea( slugOne, settings );
				registry.dispatch( STORE_NAME ).registerWidgetArea( slugTwo, settings );

				// Get all assigned widget areas for the testarea context.
				const testareaAreas = registry.select( STORE_NAME ).getWidgetAreas( 'testarea' );

				expect( testareaAreas ).toMatchObject( [
					{ ...settings, slug: slugOne },
					{ ...settings, slug: slugTwo },
				] );
			} );

			it( 'returns the widget areas sorted by priority', () => {
				// Register the widget area.
				const slugLowest = 'header';
				const slugMedium = 'header2';
				const slugMediumTwo = 'header3';
				const slugHighest = 'header4';
				const settings = {
					title: 'Your title',
					subtitle: 'Okay!',
					icon: '/wp-content/plugins/googlesitekit/header.svg',
					style: 'boxes',
				};
				registry.dispatch( STORE_NAME ).registerWidgetArea( slugLowest, { ...settings, priority: 5 } );
				registry.dispatch( STORE_NAME ).registerWidgetArea( slugMedium, { ...settings, priority: 10 } );
				registry.dispatch( STORE_NAME ).registerWidgetArea( slugMediumTwo, { ...settings, priority: 10 } );
				registry.dispatch( STORE_NAME ).registerWidgetArea( slugHighest, { ...settings, priority: 15 } );

				// Assign this widget area to the testarea context.
				registry.dispatch( STORE_NAME ).assignWidgetArea( slugLowest, 'testarea' );
				registry.dispatch( STORE_NAME ).assignWidgetArea( slugMedium, 'testarea' );
				registry.dispatch( STORE_NAME ).assignWidgetArea( slugMediumTwo, 'testarea' );
				registry.dispatch( STORE_NAME ).assignWidgetArea( slugHighest, 'testarea' );

				// Get all assigned widget areas for the testarea context.
				const testareaAreas = registry.select( STORE_NAME ).getWidgetAreas( 'testarea' );

				// The lowest priority appears first.
				expect( testareaAreas[ 0 ] ).toMatchObject( { ...settings, slug: slugLowest } );
				// Widgets assigned with the same priority should be last-in, last-out.
				expect( testareaAreas[ 1 ] ).toMatchObject( { ...settings, slug: slugMedium } );
				expect( testareaAreas[ 2 ] ).toMatchObject( { ...settings, slug: slugMediumTwo } );
				expect( testareaAreas[ 3 ] ).toMatchObject( { ...settings, slug: slugHighest } );
			} );
		} );

		describe( 'getWidgetArea', () => {
			it( 'returns an area if the widget area is registered', () => {
				registry.dispatch( STORE_NAME ).registerWidgetArea( 'TestArea', {
					title: 'Test Header',
					subtitle: 'Cool stuff for yoursite.com',
					style: 'composite',
				} );

				expect( registry.select( STORE_NAME ).getWidgetArea( 'TestArea' ) ).toEqual( {
					icon: undefined,
					priority: 10,
					title: 'Test Header',
					subtitle: 'Cool stuff for yoursite.com',
					style: 'composite',
					slug: 'TestArea',
				} );
			} );

			it( 'returns null if the widget area is not registered', () => {
				expect( registry.select( STORE_NAME ).getWidgetArea( 'NotRealArea' ) ).toEqual( null );
			} );
		} );

		describe( 'isWidgetAreaRegistered', () => {
			it( 'returns true if the widget area is registered', () => {
				registry.dispatch( STORE_NAME ).registerWidgetArea( 'TestArea', {
					title: 'Test Header',
					subtitle: 'Cool stuff for yoursite.com',
					style: 'composite',
				} );

				expect( registry.select( STORE_NAME ).isWidgetAreaRegistered( 'TestArea' ) ).toEqual( true );
			} );

			it( 'returns false if the widget area is not registered', () => {
				expect( registry.select( STORE_NAME ).isWidgetAreaRegistered( 'NotRealArea' ) ).toEqual( false );
			} );
		} );
	} );
} );
<|endoftext|>


<commit_before>define(module, function(exports, require, make) {

  var net = require('net');
  var http = require('http');
  var fs = require('fs');
  var crypto = require('crypto');
  var domain = require('domain');
  var useragent = require('useragent');
  var mustache = require('mustache');
  var mime = require('mime');
  var qp = require('qp-utility');
  var fss = require('qp-library/fss');
  var fso = require('qp-library/fso');
  var url = require('qp-library/url');
  var exit = require('qp-library/exit');
  var term = require('qp-library/term');
  var log = require('qp-library/log');

  make({

    ns: 'qp-library/http_server',

    title: '',
    name: '',
    port: 80,
    www: '',
    external: {},
    favicon: 'none',
    headers: {},
    cors: {
      preflight: {
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Credentials': 'true',
        'Access-Control-Allow-Methods': 'GET,POST',
        'Access-Control-Allow-Headers': 'SessionId, Content-Type, Accept, X-Requested-With'
      },
      request: {
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Credentials': 'true'
      }
    },
    templates: {},

    http_server: null,
    enable_domain: true,
    _setup: null,

    mime_types: {
      text: mime.lookup('txt'),
      html: mime.lookup('html'),
      css: mime.lookup('css'),
      js: mime.lookup('js'),
      json: mime.lookup('json'),
      ico: mime.lookup('ico')
    },

    handlers: {

      template: function(send, id, data, headers) {
        var template = this.templates[id];
        if (template) {
          send.data(mustache.render(fss.read(template.path), data), this.mime(template.type), headers);
        }
      },

      text: function(send, msg, headers) {
        send.data(msg, this.mime('text'), headers);
      },

      html: function(send, html, headers) {
        send.data(html, this.mime('html'), headers);
      },

      data: function(send, data, mime, headers) {
        send(200, { mime: mime, size: Buffer.byteLength(data) }, data, headers);
      },

      file: function(send, file, headers) {
        if (file.is_file && file.exists) {
          send(200, file, fs.createReadStream(file.fullname), headers);
        } else {
          send(404);
        }
      },

      json: function(send, o, headers) {
        var data = JSON.stringify(o, null, 2);
        send(200, { mime: this.mime('json'), size: Buffer.byteLength(data) }, data, headers);
      }

    },

    init: function(config) {
      // log.clear();
      exit.handler(this.on_stop);
      if (config.authenticate) this.authenticate = config.authenticate.bind(this);
      if (config.on_request) this.on_request = config.on_request.bind(this);
      if (config.on_notify) this.on_notify = config.on_notify.bind(this);
      if (config.on_connect) this.on_connect = config.on_connect.bind(this);
      if (config.on_connected) this.on_connected = config.on_connected.bind(this);
      if (config.on_message) this.on_message = config.on_message.bind(this);
      if (config.setup) this._setup = config.setup.bind(this);
      this.create_server();
    },

    setup: function() {
      this.http_server.listen(this.port);
      if (this._setup) this._setup();
      this.start();
    },

    start: function() {
      this.on_start();
    },

    add_handler: function(key, handler) {
      this.handlers[key] = handler.bind(this);
    },

    create_server: function() {
      if (this.enable_domain) {
        this.http_server = http.createServer(function(req, res) {
          var d = domain.create();
          d.on('error', this.on_error.bind(this, req, res));
          d.add(req);
          d.add(res);
          d.run(this.run_request.bind(this, req, res));
        }.bind(this));
      } else {
        process.on('uncaughtException', this.on_error.bind(this, undefined, undefined));
        this.http_server = http.createServer(function(req, res) {
          this.run_request.call(this, req, res);
        }.bind(this));
      }
    },

    mime: function(type) {
      return this.mime_types[type] || (this.mime_types[type] = mime.lookup(type));
    },

    read_data: function(req, done) {
      var post_data = '';
      req.on('data', function(data) { post_data += data; });
      req.on('end', function() { done.call(this, null, post_data); }.bind(this));
    },

    read_json: function(req, done) {
      var json = '';
      req.on('data', function(data) { json += data; });
      req.on('end', function() { done.call(this, null, JSON.parse(json)); }.bind(this));
    },

    read_agent: function(req) {
      req.ua = useragent.parse(req.headers['user-agent']);
    },

    ip_address: function(req) {
      var ip_address;
      var forwarded = req.headers['x-forwarded-for'];
      if (forwarded) {
        ip_address = forwarded.split(',')[0];
      }
      return ip_address || req.connection.remoteAddress;
    },

    user_agent: function(req) { return req.headers['user-agent']; },

    session_id: function(o) {
      if (qp.is(o, 'url')) {
        return o.get_params().sid || '';
      } else {
        return o.headers['session-id'] || '';
      }
    },

    status: function(code, include_code) {
      var description = http.STATUS_CODES[code] || '';
      return (include_code ? code : '') + (description ? ' - ' + description : '');
    },

    run_request: function(req, res) {
      var req_url = url.create({ url: req.url });
      var send = this.send.bind(this, req_url, req, res);
      qp.each(this.handlers, function(handler, key) {
        send[key] = handler.bind(this, send);
      }, this);
      if (req.method === 'GET' && req_url.equals('/favicon.ico') && this.favicon === 'none') {
        send(200, { mime: this.mime('ico'), size: 0 }, '');
      } else {
        this.on_request(req.method, req_url, send, req, res);
      }
    },

    send: function(req_url, req, res, status, stat, data, headers) {
      if (!res.done) {
        res.done = true;
        var status_color = status < 200 ? 'magenta' : status < 300 ? 'green' : status < 400 ? 'yellow' : 'white_red';
        var method_color = status >= 400 ? 'white_red' : 'blue';
        var url_color = status >= 400 ? 'white_red' : 'white';
        log(log[status_color](status), log[method_color](qp.rpad(req.method, 4)), log[url_color](req_url.fullname));
        if (arguments.length === 3) {
          res.writeHead(204, this.headers);
          res.end();
        } else {
          res.writeHead(status, this.create_headers(stat, headers));
          if (qp.is(data, 'string')) {
            res.write(data);
            res.end();
          } else if (qp.is(data, 'readstream')) {
            data.pipe(res);
          } else {
            res.end();
          }
        }
      }
    },

    create_headers: function(stat, headers) {
      if (!stat) { return this.headers; }
      stat.mtime = stat.mtime || qp.now();
      return qp.assign({
        'ETag': JSON.stringify([stat.ino || 'x', stat.size, stat.mtime.getTime()].join('-')),
        'Last-Modified': stat.mtime.toUTCString(),
        'Content-Type': stat.mime,
        'Content-Length': stat.size
      }, this.headers, headers);
    },

    on_request: function(method, url, send) { send(204); },

    on_start: function() {
      // log(log.blue_white(' *** %s:%s *** '), this.name, this.port);
    },

    on_stop: function() {
      process.exit(0);
    },

    on_error: function(http_request, http_response, error) {
      try {
        this.http_server.close();
        log('Exception:', http_request ? http_request.url : ' ...');
        log(error.stack);
        if (http_response) {
          http_response.statusCode = 500;
          http_response.setHeader('content-type', 'text/plain');
          http_response.end(error.stack);
        }
      } catch (error1) {
        log(error1.stack);
      } finally {
        log('Terminated');
        process.exit(1);
      }
    }

  });

});
<commit_msg>http_server - rethink on initialisation logic<commit_after>define(module, function(exports, require, make) {

  var http = require('http');
  var fs = require('fs');
  var domain = require('domain');
  var useragent = require('useragent');
  var mustache = require('mustache');
  var mime = require('mime');
  var qp = require('qp-utility');
  var fss = require('qp-library/fss');
  var url = require('qp-library/url');
  var log = require('qp-library/log');

  make({

    ns: 'qp-library/http_server',

    title: '',
    name: '',
    port: 80,
    www: '',
    external: {},
    favicon: 'none',
    headers: {},
    cors: {
      preflight: {
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Credentials': 'true',
        'Access-Control-Allow-Methods': 'GET,POST',
        'Access-Control-Allow-Headers': 'SessionId, Content-Type, Accept, X-Requested-With'
      },
      request: {
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Credentials': 'true'
      }
    },
    templates: {},

    http_server: null,
    enable_domain: true,

    mime_types: {
      text: mime.lookup('txt'),
      html: mime.lookup('html'),
      css: mime.lookup('css'),
      js: mime.lookup('js'),
      json: mime.lookup('json'),
      ico: mime.lookup('ico')
    },

    handlers: {

      template: function(send, id, data, headers) {
        var template = this.templates[id];
        if (template) {
          send.data(mustache.render(fss.read(template.path), data), this.mime(template.type), headers);
        }
      },

      text: function(send, msg, headers) {
        send.data(msg, this.mime('text'), headers);
      },

      html: function(send, html, headers) {
        send.data(html, this.mime('html'), headers);
      },

      data: function(send, data, mime, headers) {
        send(200, { mime: mime, size: Buffer.byteLength(data) }, data, headers);
      },

      file: function(send, file, headers) {
        if (file.is_file && file.exists) {
          send(200, file, fs.createReadStream(file.fullname), headers);
        } else {
          send(404);
        }
      },

      json: function(send, o, headers) {
        var data = JSON.stringify(o, null, 2);
        send(200, { mime: this.mime('json'), size: Buffer.byteLength(data) }, data, headers);
      }

    },

    start: function() {
      this.http_server.listen(this.port);
      this.on_start();
    },

    add_handler: function(key, handler) {
      this.handlers[key] = handler.bind(this);
    },

    create_server: function() {
      if (this.enable_domain) {
        this.http_server = http.createServer(function(req, res) {
          var d = domain.create();
          d.on('error', this.on_error.bind(this, req, res));
          d.add(req);
          d.add(res);
          d.run(this.run_request.bind(this, req, res));
        }.bind(this));
      } else {
        process.on('uncaughtException', this.on_error.bind(this, undefined, undefined));
        this.http_server = http.createServer(function(req, res) {
          this.run_request.call(this, req, res);
        }.bind(this));
      }
    },

    create_server_info: function(o) {
      fss.write_json(this.www, 'info.json', o || {});
    },

    mime: function(type) {
      return this.mime_types[type] || (this.mime_types[type] = mime.lookup(type));
    },

    read_data: function(req, done) {
      var post_data = '';
      req.on('data', function(data) { post_data += data; });
      req.on('end', function() { done.call(this, null, post_data); }.bind(this));
    },

    read_json: function(req, done) {
      var json = '';
      req.on('data', function(data) { json += data; });
      req.on('end', function() { done.call(this, null, JSON.parse(json)); }.bind(this));
    },

    read_agent: function(req) {
      req.ua = useragent.parse(req.headers['user-agent']);
    },

    ip_address: function(req) {
      var ip_address;
      var forwarded = req.headers['x-forwarded-for'];
      if (forwarded) {
        ip_address = forwarded.split(',')[0];
      }
      return ip_address || req.connection.remoteAddress;
    },

    user_agent: function(req) { return req.headers['user-agent']; },

    session_id: function(o) {
      if (qp.is(o, 'url')) {
        return o.get_params().sid || '';
      } else {
        return o.headers['session-id'] || '';
      }
    },

    status: function(code, include_code) {
      var description = http.STATUS_CODES[code] || '';
      return (include_code ? code : '') + (description ? ' - ' + description : '');
    },

    run_request: function(req, res) {
      var req_url = url.create({ url: req.url });
      var send = this.send.bind(this, req_url, req, res);
      qp.each(this.handlers, function(handler, key) {
        send[key] = handler.bind(this, send);
      }, this);
      if (req.method === 'GET' && req_url.equals('/favicon.ico') && this.favicon === 'none') {
        send(200, { mime: this.mime('ico'), size: 0 }, '');
      } else {
        this.on_request(req.method, req_url, send, req, res);
      }
    },

    send: function(req_url, req, res, status, stat, data, headers) {
      if (!res.done) {
        res.done = true;
        var status_color = status < 200 ? 'magenta' : status < 300 ? 'green' : status < 400 ? 'yellow' : 'white_red';
        var method_color = status >= 400 ? 'white_red' : 'blue';
        var url_color = status >= 400 ? 'white_red' : 'white';
        log(log[status_color](status), log[method_color](qp.rpad(req.method, 4)), log[url_color](req_url.fullname));
        if (arguments.length === 3) {
          res.writeHead(204, this.headers);
          res.end();
        } else {
          res.writeHead(status, this.create_headers(stat, headers));
          if (qp.is(data, 'string')) {
            res.write(data);
            res.end();
          } else if (qp.is(data, 'readstream')) {
            data.pipe(res);
          } else {
            res.end();
          }
        }
      }
    },

    create_headers: function(stat, headers) {
      if (!stat) { return this.headers; }
      stat.mtime = stat.mtime || qp.now();
      return qp.assign({
        'ETag': JSON.stringify([stat.ino || 'x', stat.size, stat.mtime.getTime()].join('-')),
        'Last-Modified': stat.mtime.toUTCString(),
        'Content-Type': stat.mime,
        'Content-Length': stat.size
      }, this.headers, headers);
    },

    on_request: function(method, url, send) { send(204); },

    on_start: function() { },

    on_stop: function() { process.exit(0); },

    on_error: function(http_request, http_response, error) {
      try {
        this.http_server.close();
        log('Exception:', http_request ? http_request.url : ' ...');
        log(error.stack);
        if (http_response) {
          http_response.statusCode = 500;
          http_response.setHeader('content-type', 'text/plain');
          http_response.end(error.stack);
        }
      } catch (error1) {
        log(error1.stack);
      } finally {
        log('Terminated');
        process.exit(1);
      }
    }

  });

});
<|endoftext|>


<commit_before>//
// This is our "Enter Walk-in" flow controller
//
controllers.controller(
    'WalkinHospitalNumberCtrl',
    function($scope, $modalInstance, $modal, $rootScope,
             schema, options,
             Episode){

        $scope.model = {
            hospitalNumber : null
        }
        $scope.patient = null;

        //
        // When we've created an episode with this flow, tag it to the correct
        // teams and then kill the modal.
        //
        $scope.tag_and_close = function(episode){
            if(!episode.newItem){
                episode = new Episode(episode, schema);
            };
            if(!episode.tagging[0].makeCopy){
                episode.tagging[0] = episode.newItem('tagging',{
                    column: {name: 'tagging', fields: [] }
                })
            }
            var teams = episode.tagging[0].makeCopy();
            var location = episode.location[0].makeCopy();
            teams.walkin = true;
            teams.walkin_triage = true;
            location.category = 'Walkin';

            //
            // Pre fill some tests:
            //
            var stool_ocp = episode.newItem('microbiology_test',
                                       {column: $rootScope.fields.microbiology_test});

            var malaria_film = episode.newItem('microbiology_test',
                                       {column: $rootScope.fields.microbiology_test});

            episode.tagging[0].save(teams).then(function(){
                episode.location[0].save(location).then(function(){
                    stool_ocp.save({test: 'Stool OCP'}).then(function(){
                        malaria_film.save({test: 'Malaria Film'}).then(function(){
                            episode.active = true;
                            $modalInstance.close(episode);
                        });
                    });
                })
            });
        };

        //
        // We have an initial hospital number - we can now figure out whether to
        // Add or pull over.
        //
        $scope.findByHospitalNumber = function(){
            Episode.findByHospitalNumber(
                $scope.model.hospitalNumber,
                {
                    newPatient: $scope.new_patient,
                    newForPatient: $scope.new_for_patient,
                    error: function(){
                  // This shouldn't happen, but we should probably handle it better
                  alert('ERROR: More than one patient found with hospital number');
                        $modalInstance.close(null)
                    }
                }
            );
        };

        //
        // Create a new patient
        //
        $scope.new_patient = function(result){
      // There is no patient with this hospital number
      // Show user the form for creating a new episode,
            // with the hospital number pre-populated
      modal = $modal.open({
        templateUrl: '/templates/modals/add_walkin_episode.html/',
        controller: 'AddEpisodeCtrl',
        resolve: {
          schema: function() { return schema; },
          options: function() { return options; },
          demographics: function() {
            return { hospital_number: $scope.hospitalNumber }
          }
        }
      }).result.then(function(result) {
        // The user has created the episode, or cancelled
                if(result){ // We made an episode!
                    $scope.tag_and_close(result);
                }else{
            $modalInstance.close(result);
                }
      });
        };

        //
        // Create a new episode for an existing patient
        //
        $scope.new_for_patient = function(patient){
            if(patient.active_episode_id && _.keys(patient.episodes).length > 0){
              alert('This walkin patient is a current inpatient!');
        //         // Offer to import the data from this episode.
        // for (var eix in patient.episodes) {
        //   patient.episodes[eix] = new Episode(patient.episodes[eix], schema);
        // };
        // modal = $modal.open({
        //   templateUrl: '/templates/modals/reopen_episode.html/',
        //   controller: 'ReopenEpisodeCtrl',
        //   resolve: {
        //     patient: function() { return patient; },
        //   }
        // }).result.then(
        //             function(result) {
        //                 if(!_.isString(result)){
        //                     $scope.tag_and_close(result);
        //                     return
        //                 };
        //       var demographics;
        //       if (result == 'open-new') {
        //         // User has chosen to open a new episode
        //                     $scope.add_for_patient(patient);
        //       } else {
        //         // User has chosen to reopen an episode, or cancelled
        //         $modalInstance.close(result);
        //       };
        //     },
        //             function(result){ $modalInstance.close(result); });
            }else{
                $scope.add_for_patient(patient);
            };
        };

        //
        // Add a new episode for an existing patient. Pre-fill the relevant demographics
        //
        $scope.add_for_patient = function(patient){
            var demographics = patient.demographics[0];
            if(demographics.date_of_birth){
                var dob = moment(demographics.date_of_birth, 'YYYY-MM-DD')
                    .format('DD/MM/YYYY');
        demographics.date_of_birth = dob;
            }
      modal = $modal.open({
        templateUrl: '/templates/modals/add_walkin_episode.html/',
        controller: 'AddEpisodeCtrl',
        resolve: {
          schema: function() { return schema; },
          options: function() { return options; },
          demographics: function() { return demographics; }
        }
      }).result.then(function(result) {
        // The user has created the episode, or cancelled
                if(result){ // We made an episode!
                    $scope.tag_and_close(result);
                }else{
            $modalInstance.close(result);
                }
      });
        };

        // Let's have a nice way to kill the modal.
        $scope.cancel = function() {
          $modalInstance.close('cancel');
        };
    }
);
<commit_msg>Set the episode category correctly, don't override tagginggs.<commit_after>//
// This is our "Enter Walk-in" flow controller
//
controllers.controller(
    'WalkinHospitalNumberCtrl',
    function($scope, $modalInstance, $modal, $rootScope, $q,
             schema, options,
             Episode){

        $scope.model = {
            hospitalNumber : null
        }
        $scope.patient = null;

        //
        // When we've created an episode with this flow, tag it to the correct
        // teams and then kill the modal.
        //
        $scope.tag_and_close = function(episode){
            if(!episode.newItem){
                episode = new Episode(episode, schema);
            };
            var ep = episode.makeCopy();
            var location = episode.location[0].makeCopy();
            ep.category = 'Walkin';

            //
            // Pre fill some tests:
            //
            var stool_ocp = episode.newItem('microbiology_test',
                                       {column: $rootScope.fields.microbiology_test});

            var malaria_film = episode.newItem('microbiology_test',
                                       {column: $rootScope.fields.microbiology_test});

            $q.all([
                episode.save(ep),
                episode.location[0].save(location),
                stool_ocp.save({test: 'Stool OCP'}),
                malaria_film.save({test: 'Malaria Film'})
            ]).then(function(){
                episode.active = true;
                $modalInstance.close(episode);
            })

        };

        //
        // We have an initial hospital number - we can now figure out whether to
        // Add or pull over.
        //
        $scope.findByHospitalNumber = function(){
            Episode.findByHospitalNumber(
                $scope.model.hospitalNumber,
                {
                    newPatient: $scope.new_patient,
                    newForPatient: $scope.new_for_patient,
                    error: function(){
                  // This shouldn't happen, but we should probably handle it better
                  alert('ERROR: More than one patient found with hospital number');
                        $modalInstance.close(null)
                    }
                }
            );
        };

        //
        // Create a new patient
        //
        $scope.new_patient = function(result){
      // There is no patient with this hospital number
      // Show user the form for creating a new episode,
            // with the hospital number pre-populated
      modal = $modal.open({
        templateUrl: '/templates/modals/add_walkin_episode.html/',
        controller: 'AddEpisodeCtrl',
        resolve: {
          schema: function() { return schema; },
          options: function() { return options; },
          demographics: function() {
            return { hospital_number: $scope.hospitalNumber }
          }
        }
      }).result.then(function(result) {
        // The user has created the episode, or cancelled
                if(result){ // We made an episode!
                    $scope.tag_and_close(result);
                }else{
            $modalInstance.close(result);
                }
      });
        };

        //
        // Create a new episode for an existing patient
        //
        $scope.new_for_patient = function(patient){
            if(patient.active_episode_id && _.keys(patient.episodes).length > 0){
              alert('This walkin patient is a current inpatient!');
        //         // Offer to import the data from this episode.
        // for (var eix in patient.episodes) {
        //   patient.episodes[eix] = new Episode(patient.episodes[eix], schema);
        // };
        // modal = $modal.open({
        //   templateUrl: '/templates/modals/reopen_episode.html/',
        //   controller: 'ReopenEpisodeCtrl',
        //   resolve: {
        //     patient: function() { return patient; },
        //   }
        // }).result.then(
        //             function(result) {
        //                 if(!_.isString(result)){
        //                     $scope.tag_and_close(result);
        //                     return
        //                 };
        //       var demographics;
        //       if (result == 'open-new') {
        //         // User has chosen to open a new episode
        //                     $scope.add_for_patient(patient);
        //       } else {
        //         // User has chosen to reopen an episode, or cancelled
        //         $modalInstance.close(result);
        //       };
        //     },
        //             function(result){ $modalInstance.close(result); });
            }else{
                $scope.add_for_patient(patient);
            };
        };

        //
        // Add a new episode for an existing patient. Pre-fill the relevant demographics
        //
        $scope.add_for_patient = function(patient){
            var demographics = patient.demographics[0];
            if(demographics.date_of_birth){
                var dob = moment(demographics.date_of_birth, 'YYYY-MM-DD')
                    .format('DD/MM/YYYY');
        demographics.date_of_birth = dob;
            }
      modal = $modal.open({
        templateUrl: '/templates/modals/add_walkin_episode.html/',
        controller: 'AddEpisodeCtrl',
        resolve: {
          schema: function() { return schema; },
          options: function() { return options; },
          demographics: function() { return demographics; }
        }
      }).result.then(function(result) {
        // The user has created the episode, or cancelled
                if(result){ // We made an episode!
                    $scope.tag_and_close(result);
                }else{
            $modalInstance.close(result);
                }
      });
        };

        // Let's have a nice way to kill the modal.
        $scope.cancel = function() {
          $modalInstance.close('cancel');
        };
    }
);
<|endoftext|>


<commit_before>/* @flow */
import "module-alias/register"

import { ListElement } from "../dist/elements/list"
import { createSuggestion } from "./helpers"
import { render } from "solid-js/web"

function getOlElement(suggestions) {
  const rootElement = document.createElement("div")

  const selectCallback = jasmine.createSpy("suggestion.selected")

  const { component, setMovement, setConfirmed } = ListElement({ suggestions, selectCallback, movement: "move-to-top" })

  render(() => component, rootElement)

  const intentionList = rootElement.querySelector("#intentions-list")
  olElement = intentionList.firstElementChild
  return { olElement, selectCallback, setMovement, setConfirmed }
}

export function click(elm: HTMLElement) {
  try {
    // @ts-ignore internal solid API
    elm.$$click(new MouseEvent("click"))
  } catch (e) {
    elm.click()
  }
}

const suggestions = [
  createSuggestion("Suggestion 1", jasmine.createSpy("suggestion.selected.0"), "someClass", "someIcon"),
  createSuggestion("Suggestion 2", jasmine.createSpy("suggestion.selected.1")),
  createSuggestion("Suggestion 3", jasmine.createSpy("suggestion.selected.2"), "anotherClass"),
]

describe("Intentions list element", function () {
  it("renders the list", () => {
    const { olElement } = getOlElement(suggestions)
    expect(olElement.children.length).toBe(3)
    expect(olElement.children[0].textContent).toBe("Suggestion 1")
    expect(olElement.children[1].textContent).toBe("Suggestion 2")
    expect(olElement.children[2].textContent).toBe("Suggestion 3")
    expect(olElement.children[0].children[0].className).toBe("someClass icon icon-someIcon")
    expect(olElement.children[2].children[0].className).toBe("anotherClass")
  })
  it("handles click", function () {
    const { olElement, selectCallback } = getOlElement(suggestions)
    click(olElement.children[1].children[0])
    expect(selectCallback).toHaveBeenCalledWith(suggestions[1])
  })
  it("handles movement", () => {
    const { olElement, setMovement } = getOlElement(suggestions)

    setMovement("down")

    expect(suggestions[0].title).toBe(olElement.children[0].textContent)

    setMovement("down")

    expect(suggestions[1].title).toBe(olElement.children[1].textContent)

    setMovement("down")

    expect(suggestions[2].title).toBe(olElement.children[2].textContent)

    setMovement("up")

    expect(suggestions[1].title).toBe(olElement.children[1].textContent)

    setMovement("up")

    expect(suggestions[0].title).toBe(olElement.children[0].textContent)

    setMovement("up")

    expect(suggestions[2].title).toBe(olElement.children[2].textContent)
  })
})
<commit_msg>test: fix olElement was not defined<commit_after>/* @flow */
import "module-alias/register"

import { ListElement } from "../dist/elements/list"
import { createSuggestion } from "./helpers"
import { render } from "solid-js/web"

/* eslint-disable-next-line no-shadow */
function getOlElement(suggestions) {
  const rootElement = document.createElement("div")

  const selectCallback = jasmine.createSpy("suggestion.selected")

  const { component, setMovement, setConfirmed } = ListElement({ suggestions, selectCallback, movement: "move-to-top" })

  render(() => component, rootElement)

  const intentionList = rootElement.querySelector("#intentions-list")
  const olElement = intentionList.firstElementChild
  return { olElement, selectCallback, setMovement, setConfirmed }
}

export function click(elm: HTMLElement) {
  try {
    // @ts-ignore internal solid API
    elm.$$click(new MouseEvent("click"))
  } catch (e) {
    elm.click()
  }
}

const suggestions = [
  createSuggestion("Suggestion 1", jasmine.createSpy("suggestion.selected.0"), "someClass", "someIcon"),
  createSuggestion("Suggestion 2", jasmine.createSpy("suggestion.selected.1")),
  createSuggestion("Suggestion 3", jasmine.createSpy("suggestion.selected.2"), "anotherClass"),
]

describe("Intentions list element", function () {
  it("renders the list", () => {
    const { olElement } = getOlElement(suggestions)
    expect(olElement.children.length).toBe(3)
    expect(olElement.children[0].textContent).toBe("Suggestion 1")
    expect(olElement.children[1].textContent).toBe("Suggestion 2")
    expect(olElement.children[2].textContent).toBe("Suggestion 3")
    expect(olElement.children[0].children[0].className).toBe("someClass icon icon-someIcon")
    expect(olElement.children[2].children[0].className).toBe("anotherClass")
  })
  it("handles click", function () {
    const { olElement, selectCallback } = getOlElement(suggestions)
    click(olElement.children[1].children[0])
    expect(selectCallback).toHaveBeenCalledWith(suggestions[1])
  })
  it("handles movement", () => {
    const { olElement, setMovement } = getOlElement(suggestions)

    setMovement("down")

    expect(suggestions[0].title).toBe(olElement.children[0].textContent)

    setMovement("down")

    expect(suggestions[1].title).toBe(olElement.children[1].textContent)

    setMovement("down")

    expect(suggestions[2].title).toBe(olElement.children[2].textContent)

    setMovement("up")

    expect(suggestions[1].title).toBe(olElement.children[1].textContent)

    setMovement("up")

    expect(suggestions[0].title).toBe(olElement.children[0].textContent)

    setMovement("up")

    expect(suggestions[2].title).toBe(olElement.children[2].textContent)
  })
})
<|endoftext|>