]> git.cworth.org Git - obsolete/notmuch-web/blobdiff - node_modules/express/node_modules/qs/support/expresso/bin/expresso
Install the "express" node module via npm
[obsolete/notmuch-web] / node_modules / express / node_modules / qs / support / expresso / bin / expresso
diff --git a/node_modules/express/node_modules/qs/support/expresso/bin/expresso b/node_modules/express/node_modules/qs/support/expresso/bin/expresso
new file mode 100755 (executable)
index 0000000..ec1edc8
--- /dev/null
@@ -0,0 +1,856 @@
+#!/usr/bin/env node
+
+/*
+ * Expresso
+ * Copyright(c) TJ Holowaychuk <tj@vision-media.ca>
+ * (MIT Licensed)
+ */
+/**
+ * Module dependencies.
+ */
+
+var assert = require('assert'),
+    childProcess = require('child_process'),
+    http = require('http'),
+    path = require('path'),
+    sys = require('sys'),
+    cwd = process.cwd(),
+    fs = require('fs'),
+    defer;
+
+/**
+ * Expresso version.
+ */
+
+var version = '0.7.2';
+
+/**
+ * Failure count.
+ */
+
+var failures = 0;
+
+
+/**
+ * Number of tests executed.
+ */
+
+var testcount = 0;
+
+/**
+ * Whitelist of tests to run.
+ */
+var only = [];
+
+/**
+ * Boring output.
+ */
+var boring = false;
+
+/**
+ * Growl notifications.
+ */
+
+var growl = false;
+
+/**
+ * Server port.
+ */
+
+var port = 5555;
+
+/**
+ * Execute serially.
+ */
+
+var serial = false;
+
+/**
+ * Default timeout.
+ */
+
+var timeout = 2000;
+
+/**
+ * Quiet output.
+ */
+
+var quiet = false;
+
+/**
+ * Usage documentation.
+ */
+
+var usage = ''
+    + '[bold]{Usage}: expresso [options] <file ...>'
+    + '\n'
+    + '\n[bold]{Options}:'
+    + '\n  -g, --growl          Enable growl notifications'
+    + '\n  -c, --coverage       Generate and report test coverage'
+    + '\n  -q, --quiet          Suppress coverage report if 100%'
+    + '\n  -t, --timeout MS     Timeout in milliseconds, defaults to 2000'
+    + '\n  -r, --require PATH   Require the given module path'
+    + '\n  -o, --only TESTS     Execute only the comma sperated TESTS (can be set several times)'
+    + '\n  -I, --include PATH   Unshift the given path to require.paths'
+    + '\n  -p, --port NUM       Port number for test servers, starts at 5555'
+    + '\n  -s, --serial         Execute tests serially'
+    + '\n  -b, --boring         Suppress ansi-escape colors'
+    + '\n  -v, --version        Output version number'
+    + '\n  -h, --help           Display help information'
+    + '\n';
+
+// Parse arguments
+
+var files = [],
+    args = process.argv.slice(2);
+
+while (args.length) {
+    var arg = args.shift();
+    switch (arg) {
+        case '-h':
+        case '--help':
+            print(usage + '\n');
+            process.exit(1);
+            break;
+        case '-v':
+        case '--version':
+            sys.puts(version);
+            process.exit(1);
+            break;
+        case '-i':
+        case '-I':
+        case '--include':
+            if (arg = args.shift()) {
+                require.paths.unshift(arg);
+            } else {
+                throw new Error('--include requires a path');
+            }
+            break;
+        case '-o':
+        case '--only':
+            if (arg = args.shift()) {
+                only = only.concat(arg.split(/ *, */));
+            } else {
+                throw new Error('--only requires comma-separated test names');
+            }
+            break;
+        case '-p':
+        case '--port':
+            if (arg = args.shift()) {
+                port = parseInt(arg, 10);
+            } else {
+                throw new Error('--port requires a number');
+            }
+            break;
+        case '-r':
+        case '--require':
+            if (arg = args.shift()) {
+                require(arg);
+            } else {
+                throw new Error('--require requires a path');
+            }
+            break;
+        case '-t':
+        case '--timeout':
+          if (arg = args.shift()) {
+            timeout = parseInt(arg, 10);
+          } else {
+            throw new Error('--timeout requires an argument');
+          }
+          break;
+        case '-c':
+        case '--cov':
+        case '--coverage':
+            defer = true;
+            childProcess.exec('rm -fr lib-cov && node-jscoverage lib lib-cov', function(err){
+                if (err) throw err;
+                require.paths.unshift('lib-cov');
+                run(files);
+            })
+            break;
+        case '-q':
+        case '--quiet':
+            quiet = true;
+            break;
+        case '-b':
+        case '--boring':
+               boring = true;
+               break;
+        case '-g':
+        case '--growl':
+            growl = true;
+            break;
+        case '-s':
+        case '--serial':
+            serial = true;
+            break;
+        default:
+            if (/\.js$/.test(arg)) {
+                files.push(arg);
+            }
+            break;
+    }
+}
+
+/**
+ * Colorized sys.error().
+ *
+ * @param {String} str
+ */
+
+function print(str){
+    sys.error(colorize(str));
+}
+
+/**
+ * Colorize the given string using ansi-escape sequences.
+ * Disabled when --boring is set.
+ *
+ * @param {String} str
+ * @return {String}
+ */
+
+function colorize(str){
+    var colors = { bold: 1, red: 31, green: 32, yellow: 33 };
+    return str.replace(/\[(\w+)\]\{([^]*?)\}/g, function(_, color, str){
+        return boring
+            ? str
+            : '\x1B[' + colors[color] + 'm' + str + '\x1B[0m';
+    });
+}
+
+// Alias deepEqual as eql for complex equality
+
+assert.eql = assert.deepEqual;
+
+/**
+ * Assert that `val` is null.
+ *
+ * @param {Mixed} val
+ * @param {String} msg
+ */
+
+assert.isNull = function(val, msg) {
+    assert.strictEqual(null, val, msg);
+};
+
+/**
+ * Assert that `val` is not null.
+ *
+ * @param {Mixed} val
+ * @param {String} msg
+ */
+
+assert.isNotNull = function(val, msg) {
+    assert.notStrictEqual(null, val, msg);
+};
+
+/**
+ * Assert that `val` is undefined.
+ *
+ * @param {Mixed} val
+ * @param {String} msg
+ */
+
+assert.isUndefined = function(val, msg) {
+    assert.strictEqual(undefined, val, msg);
+};
+
+/**
+ * Assert that `val` is not undefined.
+ *
+ * @param {Mixed} val
+ * @param {String} msg
+ */
+
+assert.isDefined = function(val, msg) {
+    assert.notStrictEqual(undefined, val, msg);
+};
+
+/**
+ * Assert that `obj` is `type`.
+ *
+ * @param {Mixed} obj
+ * @param {String} type
+ * @api public
+ */
+
+assert.type = function(obj, type, msg){
+    var real = typeof obj;
+    msg = msg || 'typeof ' + sys.inspect(obj) + ' is ' + real + ', expected ' + type;
+    assert.ok(type === real, msg);
+};
+
+/**
+ * Assert that `str` matches `regexp`.
+ *
+ * @param {String} str
+ * @param {RegExp} regexp
+ * @param {String} msg
+ */
+
+assert.match = function(str, regexp, msg) {
+    msg = msg || sys.inspect(str) + ' does not match ' + sys.inspect(regexp);
+    assert.ok(regexp.test(str), msg);
+};
+
+/**
+ * Assert that `val` is within `obj`.
+ *
+ * Examples:
+ *
+ *    assert.includes('foobar', 'bar');
+ *    assert.includes(['foo', 'bar'], 'foo');
+ *
+ * @param {String|Array} obj
+ * @param {Mixed} val
+ * @param {String} msg
+ */
+
+assert.includes = function(obj, val, msg) {
+    msg = msg || sys.inspect(obj) + ' does not include ' + sys.inspect(val);
+    assert.ok(obj.indexOf(val) >= 0, msg);
+};
+
+/**
+ * Assert length of `val` is `n`.
+ *
+ * @param {Mixed} val
+ * @param {Number} n
+ * @param {String} msg
+ */
+
+assert.length = function(val, n, msg) {
+    msg = msg || sys.inspect(val) + ' has length of ' + val.length + ', expected ' + n;
+    assert.equal(n, val.length, msg);
+};
+
+/**
+ * Assert response from `server` with
+ * the given `req` object and `res` assertions object.
+ *
+ * @param {Server} server
+ * @param {Object} req
+ * @param {Object|Function} res
+ * @param {String} msg
+ */
+
+assert.response = function(server, req, res, msg){
+    // Check that the server is ready or defer
+    if (!server.fd) {
+        if (!('__deferred' in server)) {
+            server.__deferred = [];
+        }
+        server.__deferred.push(arguments);
+        if (!server.__started) {
+            server.listen(server.__port = port++, '127.0.0.1', function(){
+                if (server.__deferred) {
+                    process.nextTick(function(){
+                        server.__deferred.forEach(function(args){
+                          assert.response.apply(assert, args);
+                        });
+                    });
+                }
+            });
+            server.__started = true;
+        }
+        return;
+    }
+
+    // Callback as third or fourth arg
+    var callback = typeof res === 'function'
+        ? res
+        : typeof msg === 'function'
+            ? msg
+            : function(){};
+
+    // Default messate to test title
+    if (typeof msg === 'function') msg = null;
+    msg = msg || assert.testTitle;
+    msg += '. ';
+
+    // Pending responses
+    server.__pending = server.__pending || 0;
+    server.__pending++;
+
+    // Create client
+    if (!server.fd) {
+        server.listen(server.__port = port++, '127.0.0.1', issue);
+    } else {
+        issue();
+    }
+
+    function issue(){
+        if (!server.client)
+            server.client = http.createClient(server.__port);
+
+        // Issue request
+        var timer,
+            client = server.client,
+            method = req.method || 'GET',
+            status = res.status || res.statusCode,
+            data = req.data || req.body,
+            requestTimeout = req.timeout || 0;
+
+        var request = client.request(method, req.url, req.headers);
+
+        // Timeout
+        if (requestTimeout) {
+            timer = setTimeout(function(){
+                --server.__pending || server.close();
+                delete req.timeout;
+                assert.fail(msg + 'Request timed out after ' + requestTimeout + 'ms.');
+            }, requestTimeout);
+        }
+
+        if (data) request.write(data);
+        request.on('response', function(response){
+            response.body = '';
+            response.setEncoding('utf8');
+            response.on('data', function(chunk){ response.body += chunk; });
+            response.on('end', function(){
+                --server.__pending || server.close();
+                if (timer) clearTimeout(timer);
+
+                // Assert response body
+                if (res.body !== undefined) {
+                    var eql = res.body instanceof RegExp
+                      ? res.body.test(response.body)
+                      : res.body === response.body;
+                    assert.ok(
+                        eql,
+                        msg + 'Invalid response body.\n'
+                            + '    Expected: ' + sys.inspect(res.body) + '\n'
+                            + '    Got: ' + sys.inspect(response.body)
+                    );
+                }
+
+                // Assert response status
+                if (typeof status === 'number') {
+                    assert.equal(
+                        response.statusCode,
+                        status,
+                        msg + colorize('Invalid response status code.\n'
+                            + '    Expected: [green]{' + status + '}\n'
+                            + '    Got: [red]{' + response.statusCode + '}')
+                    );
+                }
+
+                // Assert response headers
+                if (res.headers) {
+                    var keys = Object.keys(res.headers);
+                    for (var i = 0, len = keys.length; i < len; ++i) {
+                        var name = keys[i],
+                            actual = response.headers[name.toLowerCase()],
+                            expected = res.headers[name],
+                            eql = expected instanceof RegExp
+                              ? expected.test(actual)
+                              : expected == actual;
+                        assert.ok(
+                            eql,
+                            msg + colorize('Invalid response header [bold]{' + name + '}.\n'
+                                + '    Expected: [green]{' + expected + '}\n'
+                                + '    Got: [red]{' + actual + '}')
+                        );
+                    }
+                }
+
+                // Callback
+                callback(response);
+            });
+        });
+        request.end();
+      }
+};
+
+/**
+ * Pad the given string to the maximum width provided.
+ *
+ * @param  {String} str
+ * @param  {Number} width
+ * @return {String}
+ */
+
+function lpad(str, width) {
+    str = String(str);
+    var n = width - str.length;
+    if (n < 1) return str;
+    while (n--) str = ' ' + str;
+    return str;
+}
+
+/**
+ * Pad the given string to the maximum width provided.
+ *
+ * @param  {String} str
+ * @param  {Number} width
+ * @return {String}
+ */
+
+function rpad(str, width) {
+    str = String(str);
+    var n = width - str.length;
+    if (n < 1) return str;
+    while (n--) str = str + ' ';
+    return str;
+}
+
+/**
+ * Report test coverage.
+ *
+ * @param  {Object} cov
+ */
+
+function reportCoverage(cov) {
+    // Stats
+    print('\n   [bold]{Test Coverage}\n');
+    var sep = '   +------------------------------------------+----------+------+------+--------+',
+        lastSep = '                                              +----------+------+------+--------+';
+    sys.puts(sep);
+    sys.puts('   | filename                                 | coverage | LOC  | SLOC | missed |');
+    sys.puts(sep);
+    for (var name in cov) {
+        var file = cov[name];
+        if (Array.isArray(file)) {
+            sys.print('   | ' + rpad(name, 40));
+            sys.print(' | ' + lpad(file.coverage.toFixed(2), 8));
+            sys.print(' | ' + lpad(file.LOC, 4));
+            sys.print(' | ' + lpad(file.SLOC, 4));
+            sys.print(' | ' + lpad(file.totalMisses, 6));
+            sys.print(' |\n');
+        }
+    }
+    sys.puts(sep);
+    sys.print('     ' + rpad('', 40));
+    sys.print(' | ' + lpad(cov.coverage.toFixed(2), 8));
+    sys.print(' | ' + lpad(cov.LOC, 4));
+    sys.print(' | ' + lpad(cov.SLOC, 4));
+    sys.print(' | ' + lpad(cov.totalMisses, 6));
+    sys.print(' |\n');
+    sys.puts(lastSep);
+    // Source
+    for (var name in cov) {
+        if (name.match(/\.js$/)) {
+            var file = cov[name];
+            if ((file.coverage < 100) || !quiet) {
+               print('\n   [bold]{' + name + '}:'); 
+               print(file.source);
+               sys.print('\n');
+            }
+        }
+    }
+}
+
+/**
+ * Populate code coverage data.
+ *
+ * @param  {Object} cov
+ */
+
+function populateCoverage(cov) {
+    cov.LOC = 
+    cov.SLOC =
+    cov.totalFiles =
+    cov.totalHits =
+    cov.totalMisses = 
+    cov.coverage = 0;
+    for (var name in cov) {
+        var file = cov[name];
+        if (Array.isArray(file)) {
+            // Stats
+            ++cov.totalFiles;
+            cov.totalHits += file.totalHits = coverage(file, true);
+            cov.totalMisses += file.totalMisses = coverage(file, false);
+            file.totalLines = file.totalHits + file.totalMisses;
+            cov.SLOC += file.SLOC = file.totalLines;
+            if (!file.source) file.source = [];
+            cov.LOC += file.LOC = file.source.length;
+            file.coverage = (file.totalHits / file.totalLines) * 100;
+            // Source
+            var width = file.source.length.toString().length;
+            file.source = file.source.map(function(line, i){
+                ++i;
+                var hits = file[i] === 0 ? 0 : (file[i] || ' ');
+                if (!boring) {
+                    if (hits === 0) {
+                        hits = '\x1b[31m' + hits + '\x1b[0m';
+                        line = '\x1b[41m' + line + '\x1b[0m';
+                    } else {
+                        hits = '\x1b[32m' + hits + '\x1b[0m';
+                    }
+                }
+                return '\n     ' + lpad(i, width) + ' | ' + hits + ' | ' + line;
+            }).join('');
+        }
+    }
+    cov.coverage = (cov.totalHits / cov.SLOC) * 100;
+}
+
+/**
+ * Total coverage for the given file data.
+ *
+ * @param  {Array} data
+ * @return {Type}
+ */
+
+function coverage(data, val) {
+    var n = 0;
+    for (var i = 0, len = data.length; i < len; ++i) {
+        if (data[i] !== undefined && data[i] == val) ++n;
+    }
+    return n;  
+}
+
+/**
+ * Test if all files have 100% coverage
+ *
+ * @param  {Object} cov
+ * @return {Boolean}
+ */
+
+function hasFullCoverage(cov) {
+  for (var name in cov) {
+    var file = cov[name];
+    if (file instanceof Array) {
+      if (file.coverage !== 100) {
+             return false;
+      }
+    }
+  }
+  return true;
+}
+
+/**
+ * Run the given test `files`, or try _test/*_.
+ *
+ * @param  {Array} files
+ */
+
+function run(files) {
+    cursor(false);
+    if (!files.length) {
+        try {
+            files = fs.readdirSync('test').map(function(file){
+                return 'test/' + file;
+            });
+        } catch (err) {
+            print('\n  failed to load tests in [bold]{./test}\n');
+            ++failures;
+            process.exit(1);
+        }
+    }
+    runFiles(files);
+}
+
+/**
+ * Show the cursor when `show` is true, otherwise hide it.
+ *
+ * @param {Boolean} show
+ */
+
+function cursor(show) {
+    if (show) {
+        sys.print('\x1b[?25h');
+    } else {
+        sys.print('\x1b[?25l');
+    }
+}
+
+/**
+ * Run the given test `files`.
+ *
+ * @param {Array} files
+ */
+
+function runFiles(files) {
+    if (serial) {
+        (function next(){
+            if (files.length) {
+                runFile(files.shift(), next);
+            }
+        })();
+    } else {
+      files.forEach(runFile);
+    }
+}
+
+/**
+ * Run tests for the given `file`, callback `fn()` when finished.
+ *
+ * @param {String} file
+ * @param {Function} fn
+ */
+
+function runFile(file, fn) {
+    if (file.match(/\.js$/)) {
+        var title = path.basename(file),
+            file = path.join(cwd, file),
+            mod = require(file.replace(/\.js$/, ''));
+        (function check(){
+           var len = Object.keys(mod).length;
+           if (len) {
+               runSuite(title, mod, fn);
+           } else {
+               setTimeout(check, 20);
+           }
+        })();
+    }
+}
+
+/**
+ * Report `err` for the given `test` and `suite`.
+ *
+ * @param {String} suite
+ * @param {String} test
+ * @param {Error} err
+ */
+
+function error(suite, test, err) {
+    ++failures;
+    var name = err.name,
+        stack = err.stack ? err.stack.replace(err.name, '') : '',
+        label = test === 'uncaught'
+            ? test
+            : suite + ' ' + test;
+    print('\n   [bold]{' + label + '}: [red]{' + name + '}' + stack + '\n');
+}
+
+/**
+ * Run the given tests, callback `fn()` when finished.
+ *
+ * @param  {String} title
+ * @param  {Object} tests
+ * @param  {Function} fn
+ */
+
+var dots = 0;
+function runSuite(title, tests, fn) {
+    // Keys
+    var keys = only.length
+        ? only.slice(0)
+        : Object.keys(tests);
+
+    // Setup
+    var setup = tests.setup || function(fn){ fn(); };
+
+    // Iterate tests
+    (function next(){
+        if (keys.length) {
+            var key,
+                test = tests[key = keys.shift()];
+            // Non-tests
+            if (key === 'setup') return next();
+
+            // Run test
+            if (test) {
+                try {
+                    ++testcount;
+                    assert.testTitle = key;
+                    if (serial) {
+                        sys.print('.');
+                        if (++dots % 25 === 0) sys.print('\n');
+                        setup(function(){
+                            if (test.length < 1) {
+                                test();
+                                next();
+                            } else {
+                                var id = setTimeout(function(){
+                                    throw new Error("'" + key + "' timed out");
+                                }, timeout);
+                                test(function(){
+                                    clearTimeout(id);
+                                    next();
+                                });
+                            } 
+                        });
+                    } else {
+                        test(function(fn){
+                            process.on('beforeExit', function(){
+                                try {
+                                    fn();
+                                } catch (err) {
+                                    error(title, key, err);
+                                }
+                            });
+                        });
+                    }
+                } catch (err) {
+                    error(title, key, err);
+                }
+            }
+            if (!serial) next();
+        } else if (serial) {
+          fn();
+        }
+    })();
+}
+
+/**
+ * Report exceptions.
+ */
+
+function report() {
+    cursor(true);
+    process.emit('beforeExit');
+    if (failures) {
+        print('\n   [bold]{Failures}: [red]{' + failures + '}\n\n');
+        notify('Failures: ' + failures);
+    } else {
+        if (serial) print('');
+        print('\n   [green]{100%} ' + testcount + ' tests\n');
+        notify('100% ok');
+    }
+    if (typeof _$jscoverage === 'object') {
+        populateCoverage(_$jscoverage);
+        if (!hasFullCoverage(_$jscoverage) || !quiet) {
+            reportCoverage(_$jscoverage);
+        }
+    }
+}
+
+/**
+ * Growl notify the given `msg`.
+ *
+ * @param {String} msg
+ */
+
+function notify(msg) {
+    if (growl) {
+        childProcess.exec('growlnotify -name Expresso -m "' + msg + '"');
+    }
+}
+
+// Report uncaught exceptions
+
+process.on('uncaughtException', function(err){
+    error('uncaught', 'uncaught', err);
+});
+
+// Show cursor
+
+['INT', 'TERM', 'QUIT'].forEach(function(sig){
+    process.on('SIG' + sig, function(){
+        cursor(true);
+        process.exit(1);
+    });
+});
+
+// Report test coverage when available
+// and emit "beforeExit" event to perform
+// final assertions
+
+var orig = process.emit;
+process.emit = function(event){
+    if (event === 'exit') {
+        report();
+        process.reallyExit(failures);
+    }
+    orig.apply(this, arguments);
+};
+
+// Run test files
+
+if (!defer) run(files);