Name: js-handler/node_modules/nodeunit/lib/utils.js 
1:
/*!
2:
 * Nodeunit
3:
 * Copyright (c) 2010 Caolan McMahon
4:
 * MIT Licensed
5:
 */
6:
 
7:
/**
8:
 * Module dependencies
9:
 */
10:
 
11:
var async = require('../deps/async'),
12:
    fs = require('fs'),
13:
    util = require('util'),
14:
    Script = process.binding('evals').Script || process.binding('evals').NodeScript,
15:
    http = require('http');
16:
 
17:
 
18:
/**
19:
 * Detect if coffee-script, iced-coffeescript, or streamline are available and
20:
 * the respective file extensions to the search filter in modulePaths if it is.
21:
 */
22:
 
23:
var extensions = [ 'js' ];  // js is always supported: add it unconditionally
24:
var extensionPattern;
25:
 
26:
try {
27:
    require('coffee-script');
28:
    extensions.push('coffee');
29:
} catch (e) { }
30:
 
31:
try {
32:
    require('iced-coffee-script');
33:
    extensions.push('iced');
34:
} catch (e) { }
35:
 
36:
try {
37:
    require('streamline').register();
38:
    extensions.push('_coffee');
39:
    extensions.push('_js');
40:
} catch (e) { }
41:
 
42:
extensionPattern = new RegExp('\\.(?:' + extensions.join('|') + ')$');
43:
 
44:
 
45:
/**
46:
 * Finds all modules at each path in an array, If a path is a directory, it
47:
 * returns all supported file types inside it. This only reads 1 level deep in
48:
 * the directory and does not recurse through sub-directories.
49:
 *
50:
 * The extension (.js, .coffee etc) is stripped from the filenames so they can
51:
 * simply be require()'ed.
52:
 *
53:
 * @param {Array} paths
54:
 * @param {Function} callback
55:
 * @api public
56:
 */
57:
 
58:
exports.modulePaths = function (paths, callback) {
59:
    async.concat(paths, function (p, cb) {
60:
        fs.stat(p, function (err, stats) {
61:
            if (err) {
62:
                return cb(err);
63:
            }
64:
            if (stats.isFile()) {
65:
                return cb(null, [p]);
66:
            }
67:
            if (stats.isDirectory()) {
68:
                fs.readdir(p, function (err, files) {
69:
                    if (err) {
70:
                        return cb(err);
71:
                    }
72:
 
73:
                    // filter out any filenames with unsupported extensions
74:
                    var modules = files.filter(function (filename) {
75:
                        return extensionPattern.exec(filename);
76:
                    });
77:
 
78:
                    // remove extension from module name and prepend the
79:
                    // directory path
80:
                    var fullpaths = modules.map(function (filename) {
81:
                        var mod_name = filename.replace(extensionPattern, '');
82:
                        return [p, mod_name].join('/');
83:
                    });
84:
 
85:
                    // sort filenames here, because Array.map changes order
86:
                    fullpaths.sort();
87:
 
88:
                    cb(null, fullpaths);
89:
                });
90:
            }
91:
        });
92:
    }, callback);
93:
};
94:
 
95:
/**
96:
 * Evaluates JavaScript files in a sandbox, returning the context. The first
97:
 * argument can either be a single filename or an array of filenames. If
98:
 * multiple filenames are given their contents are concatenated before
99:
 * evalution. The second argument is an optional context to use for the sandbox.
100:
 *
101:
 * @param files
102:
 * @param {Object} sandbox
103:
 * @return {Object}
104:
 * @api public
105:
 */
106:
 
107:
exports.sandbox = function (files, /*optional*/sandbox) {
108:
    var source, script, result;
109:
    if (!(files instanceof Array)) {
110:
        files = [files];
111:
    }
112:
    source = files.map(function (file) {
113:
        return fs.readFileSync(file, 'utf8');
114:
    }).join('');
115:
 
116:
    if (!sandbox) {
117:
        sandbox = {};
118:
    }
119:
    script = new Script(source);
120:
    result = script.runInNewContext(sandbox);
121:
    return sandbox;
122:
};
123:
 
124:
/**
125:
 * Provides a http request, response testing environment.
126:
 *
127:
 * Example:
128:
 *
129:
 *  var httputil = require('nodeunit').utils.httputil
130:
 *  exports.testSomething = function(test) {
131:
 *    httputil(function (req, resp) {
132:
 *        resp.writeHead(200, {});
133:
 *        resp.end('test data');
134:
 *      },
135:
 *      function(server, client) {
136:
 *        client.fetch('GET', '/', {}, function(resp) {
137:
 *          test.equal('test data', resp.body);
138:
 *          server.close();
139:
 *          test.done();
140:
 *        })
141:
 *      });
142:
 *  };
143:
 *
144:
 * @param {Function} cgi
145:
 * @param {Function} envReady
146:
 * @api public
147:
 */
148:
exports.httputil = function (cgi, envReady) {
149:
    var hostname = process.env.HOSTNAME || 'localhost';
150:
    var port = process.env.PORT || 3000;
151:
 
152:
    var server = http.createServer(cgi);
153:
    server.listen(port, hostname);
154:
 
155:
    var client = http.createClient(port, hostname);
156:
    client.fetch = function (method, path, headers, respReady) {
157:
        var request = this.request(method, path, headers);
158:
        request.end();
159:
        request.on('response', function (response) {
160:
            response.setEncoding('utf8');
161:
            response.on('data', function (chunk) {
162:
                if (response.body) {
163:
                    response.body += chunk;
164:
                } else {
165:
                    response.body = chunk;
166:
                }
167:
            });
168:
            response.on('end', function () {
169:
                if (response.headers['content-type'] === 'application/json') {
170:
                    response.bodyAsObject = JSON.parse(response.body);
171:
                }
172:
                respReady(response);
173:
            });
174:
        });
175:
    };
176:
 
177:
    process.nextTick(function () {
178:
        if (envReady && typeof envReady === 'function') {
179:
            envReady(server, client);
180:
        }
181:
    });
182:
};
183:
 
184:
 
185:
/**
186:
 * Improves formatting of AssertionError messages to make deepEqual etc more
187:
 * readable.
188:
 *
189:
 * @param {Object} assertion
190:
 * @return {Object}
191:
 * @api public
192:
 */
193:
 
194:
exports.betterErrors = function (assertion) {
195:
    if (!assertion.error) {
196:
        return assertion;
197:
    }
198:
    var e = assertion.error;
199:
    if (e.actual && e.expected) {
200:
        var actual = util.inspect(e.actual, false, 10).replace(/\n$/, '');
201:
        var expected = util.inspect(e.expected, false, 10).replace(/\n$/, '');
202:
        var multiline = (
203:
            actual.indexOf('\n') !== -1 ||
204:
            expected.indexOf('\n') !== -1
205:
        );
206:
        var spacing = (multiline ? '\n' : ' ');
207:
        e._message = e.message;
208:
        e.stack = (
209:
            e.name + ':' + spacing +
210:
            actual + spacing + e.operator + spacing +
211:
            expected + '\n' +
212:
            e.stack.split('\n').slice(1).join('\n')
213:
        );
214:
    }
215:
    return assertion;
216:
};