From ad7099a4e3f3d2035e3e26419a633b4bb1ce7b7c Mon Sep 17 00:00:00 2001 From: Adam Kocoloski Date: Wed, 11 Aug 2010 16:13:08 -0400 Subject: move futon into release overlay --- share/www/script/jspec/jspec.js | 1756 --------------------------------------- 1 file changed, 1756 deletions(-) delete mode 100644 share/www/script/jspec/jspec.js (limited to 'share/www/script/jspec/jspec.js') diff --git a/share/www/script/jspec/jspec.js b/share/www/script/jspec/jspec.js deleted file mode 100644 index d6daf5ef..00000000 --- a/share/www/script/jspec/jspec.js +++ /dev/null @@ -1,1756 +0,0 @@ - -// JSpec - Core - Copyright TJ Holowaychuk (MIT Licensed) - -;(function(){ - - JSpec = { - version : '3.3.2', - assert : true, - cache : {}, - suites : [], - modules : [], - allSuites : [], - matchers : {}, - stubbed : [], - options : {}, - request : 'XMLHttpRequest' in this ? XMLHttpRequest : null, - stats : { specs: 0, assertions: 0, failures: 0, passes: 0, specsFinished: 0, suitesFinished: 0 }, - - /** - * Default context in which bodies are evaluated. - * - * Replace context simply by setting JSpec.context - * to your own like below: - * - * JSpec.context = { foo : 'bar' } - * - * Contexts can be changed within any body, this can be useful - * in order to provide specific helper methods to specific suites. - * - * To reset (usually in after hook) simply set to null like below: - * - * JSpec.context = null - * - */ - - defaultContext : { - - /** - * Return an object used for proxy assertions. - * This object is used to indicate that an object - * should be an instance of _object_, not the constructor - * itself. - * - * @param {function} constructor - * @return {hash} - * @api public - */ - - an_instance_of : function(constructor) { - return { an_instance_of : constructor } - }, - - /** - * Load fixture at _path_. - * - * Fixtures are resolved as: - * - * - - * - .html - * - * @param {string} path - * @return {string} - * @api public - */ - - fixture : function(path) { - if (JSpec.cache[path]) return JSpec.cache[path] - return JSpec.cache[path] = - JSpec.tryLoading(JSpec.options.fixturePath + '/' + path) || - JSpec.tryLoading(JSpec.options.fixturePath + '/' + path + '.html') - } - }, - - // --- Objects - - reporters : { - - /** - * Report to server. - * - * Options: - * - uri specific uri to report to. - * - verbose weither or not to output messages - * - failuresOnly output failure messages only - * - * @api public - */ - - Server : function(results, options) { - var uri = options.uri || 'http://' + window.location.host + '/results' - JSpec.post(uri, { - stats: JSpec.stats, - options: options, - results: map(results.allSuites, function(suite) { - if (suite.hasSpecs()) - return { - description: suite.description, - specs: map(suite.specs, function(spec) { - return { - description: spec.description, - message: !spec.passed() ? spec.failure().message : null, - status: spec.requiresImplementation() ? 'pending' : - spec.passed() ? 'pass' : - 'fail', - assertions: map(spec.assertions, function(assertion){ - return { - passed: assertion.passed - } - }) - } - }) - } - }) - }) - if ('close' in main) main.close() - }, - - /** - * Default reporter, outputting to the DOM. - * - * Options: - * - reportToId id of element to output reports to, defaults to 'jspec' - * - failuresOnly displays only suites with failing specs - * - * @api public - */ - - DOM : function(results, options) { - var id = option('reportToId') || 'jspec', - report = document.getElementById(id), - failuresOnly = option('failuresOnly'), - classes = results.stats.failures ? 'has-failures' : '' - if (!report) throw 'JSpec requires the element #' + id + ' to output its reports' - - function bodyContents(body) { - return JSpec. - escape(JSpec.contentsOf(body)). - replace(/^ */gm, function(a){ return (new Array(Math.round(a.length / 3))).join(' ') }). - replace(/\r\n|\r|\n/gm, '
') - } - - report.innerHTML = '
\ - Passes: ' + results.stats.passes + ' \ - Failures: ' + results.stats.failures + ' \ - Duration: ' + results.duration + ' ms \ -
' + map(results.allSuites, function(suite) { - var displaySuite = failuresOnly ? suite.ran && !suite.passed() : suite.ran - if (displaySuite && suite.hasSpecs()) - return '' + - map(suite.specs, function(i, spec) { - return '' + - (spec.requiresImplementation() ? - '' : - (spec.passed() && !failuresOnly) ? - '' : - !spec.passed() ? - '' : - '') + - '' - }).join('') + '' - }).join('') + '
' + escape(suite.description) + '
' + escape(spec.description) + '' + escape(spec.description)+ '' + spec.assertionsGraph() + '' + escape(spec.description) + - map(spec.failures(), function(a){ return '' + escape(a.message) + '' }).join('') + - '' + spec.assertionsGraph() + '
' + bodyContents(spec.body) + '
' - }, - - /** - * Terminal reporter. - * - * @api public - */ - - Terminal : function(results, options) { - var failuresOnly = option('failuresOnly') - print(color("\n Passes: ", 'bold') + color(results.stats.passes, 'green') + - color(" Failures: ", 'bold') + color(results.stats.failures, 'red') + - color(" Duration: ", 'bold') + color(results.duration, 'green') + " ms \n") - - function indent(string) { - return string.replace(/^(.)/gm, ' $1') - } - - each(results.allSuites, function(suite) { - var displaySuite = failuresOnly ? suite.ran && !suite.passed() : suite.ran - if (displaySuite && suite.hasSpecs()) { - print(color(' ' + suite.description, 'bold')) - each(suite.specs, function(spec){ - var assertionsGraph = inject(spec.assertions, '', function(graph, assertion){ - return graph + color('.', assertion.passed ? 'green' : 'red') - }) - if (spec.requiresImplementation()) - print(color(' ' + spec.description, 'blue') + assertionsGraph) - else if (spec.passed() && !failuresOnly) - print(color(' ' + spec.description, 'green') + assertionsGraph) - else if (!spec.passed()) - print(color(' ' + spec.description, 'red') + assertionsGraph + - "\n" + indent(map(spec.failures(), function(a){ return a.message }).join("\n")) + "\n") - }) - print("") - } - }) - - quit(results.stats.failures) - } - }, - - Assertion : function(matcher, actual, expected, negate) { - extend(this, { - message: '', - passed: false, - actual: actual, - negate: negate, - matcher: matcher, - expected: expected, - - // Report assertion results - - report : function() { - if (JSpec.assert) - this.passed ? JSpec.stats.passes++ : JSpec.stats.failures++ - return this - }, - - // Run the assertion - - run : function() { - // TODO: remove unshifting - expected.unshift(actual) - this.result = matcher.match.apply(this, expected) - this.passed = negate ? !this.result : this.result - if (!this.passed) this.message = matcher.message.call(this, actual, expected, negate, matcher.name) - return this - } - }) - }, - - ProxyAssertion : function(object, method, times, negate) { - var self = this - var old = object[method] - - // Proxy - - object[method] = function(){ - args = toArray(arguments) - result = old.apply(object, args) - self.calls.push({ args : args, result : result }) - return result - } - - // Times - - this.times = { - once : 1, - twice : 2 - }[times] || times || 1 - - extend(this, { - calls: [], - message: '', - defer: true, - passed: false, - negate: negate, - object: object, - method: method, - - // Proxy return value - - and_return : function(result) { - this.expectedResult = result - return this - }, - - // Proxy arguments passed - - with_args : function() { - this.expectedArgs = toArray(arguments) - return this - }, - - // Check if any calls have failing results - - anyResultsFail : function() { - return any(this.calls, function(call){ - return self.expectedResult.an_instance_of ? - call.result.constructor != self.expectedResult.an_instance_of: - !equal(self.expectedResult, call.result) - }) - }, - - // Check if any calls have passing results - - anyResultsPass : function() { - return any(this.calls, function(call){ - return self.expectedResult.an_instance_of ? - call.result.constructor == self.expectedResult.an_instance_of: - equal(self.expectedResult, call.result) - }) - }, - - // Return the passing result - - passingResult : function() { - return this.anyResultsPass().result - }, - - // Return the failing result - - failingResult : function() { - return this.anyResultsFail().result - }, - - // Check if any arguments fail - - anyArgsFail : function() { - return any(this.calls, function(call){ - return any(self.expectedArgs, function(i, arg){ - if (arg == null) return call.args[i] == null - return arg.an_instance_of ? - call.args[i].constructor != arg.an_instance_of: - !equal(arg, call.args[i]) - - }) - }) - }, - - // Check if any arguments pass - - anyArgsPass : function() { - return any(this.calls, function(call){ - return any(self.expectedArgs, function(i, arg){ - return arg.an_instance_of ? - call.args[i].constructor == arg.an_instance_of: - equal(arg, call.args[i]) - - }) - }) - }, - - // Return the passing args - - passingArgs : function() { - return this.anyArgsPass().args - }, - - // Return the failing args - - failingArgs : function() { - return this.anyArgsFail().args - }, - - // Report assertion results - - report : function() { - if (JSpec.assert) - this.passed ? ++JSpec.stats.passes : ++JSpec.stats.failures - return this - }, - - // Run the assertion - - run : function() { - var methodString = 'expected ' + object.toString() + '.' + method + '()' + (negate ? ' not' : '' ) - - function times(n) { - return n > 2 ? n + ' times' : { 1: 'once', 2: 'twice' }[n] - } - - if (this.expectedResult != null && (negate ? this.anyResultsPass() : this.anyResultsFail())) - this.message = methodString + ' to return ' + puts(this.expectedResult) + - ' but ' + (negate ? 'it did' : 'got ' + puts(this.failingResult())) - - if (this.expectedArgs && (negate ? !this.expectedResult && this.anyArgsPass() : this.anyArgsFail())) - this.message = methodString + ' to be called with ' + puts.apply(this, this.expectedArgs) + - ' but was' + (negate ? '' : ' called with ' + puts.apply(this, this.failingArgs())) - - if (negate ? !this.expectedResult && !this.expectedArgs && this.calls.length >= this.times : this.calls.length != this.times) - this.message = methodString + ' to be called ' + times(this.times) + - ', but ' + (this.calls.length == 0 ? ' was not called' : ' was called ' + times(this.calls.length)) - - if (!this.message.length) - this.passed = true - - return this - } - }) - }, - - /** - * Specification Suite block object. - * - * @param {string} description - * @param {function} body - * @api private - */ - - Suite : function(description, body) { - var self = this - extend(this, { - body: body, - description: description, - suites: [], - specs: [], - ran: false, - hooks: { 'before' : [], 'after' : [], 'before_each' : [], 'after_each' : [] }, - - // Add a spec to the suite - - addSpec : function(description, body) { - var spec = new JSpec.Spec(description, body) - this.specs.push(spec) - JSpec.stats.specs++ // TODO: abstract - spec.suite = this - }, - - // Add a hook to the suite - - addHook : function(hook, body) { - this.hooks[hook].push(body) - }, - - // Add a nested suite - - addSuite : function(description, body) { - var suite = new JSpec.Suite(description, body) - JSpec.allSuites.push(suite) - suite.name = suite.description - suite.description = this.description + ' ' + suite.description - this.suites.push(suite) - suite.suite = this - }, - - // Invoke a hook in context to this suite - - hook : function(hook) { - if (this.suite) this.suite.hook(hook) - each(this.hooks[hook], function(body) { - JSpec.evalBody(body, "Error in hook '" + hook + "', suite '" + self.description + "': ") - }) - }, - - // Check if nested suites are present - - hasSuites : function() { - return this.suites.length - }, - - // Check if this suite has specs - - hasSpecs : function() { - return this.specs.length - }, - - // Check if the entire suite passed - - passed : function() { - return !any(this.specs, function(spec){ - return !spec.passed() - }) - } - }) - }, - - /** - * Specification block object. - * - * @param {string} description - * @param {function} body - * @api private - */ - - Spec : function(description, body) { - extend(this, { - body: body, - description: description, - assertions: [], - - // Add passing assertion - - pass : function(message) { - this.assertions.push({ passed: true, message: message }) - if (JSpec.assert) ++JSpec.stats.passes - }, - - // Add failing assertion - - fail : function(message) { - this.assertions.push({ passed: false, message: message }) - if (JSpec.assert) ++JSpec.stats.failures - }, - - // Run deferred assertions - - runDeferredAssertions : function() { - each(this.assertions, function(assertion){ - if (assertion.defer) assertion.run().report(), hook('afterAssertion', assertion) - }) - }, - - // Find first failing assertion - - failure : function() { - return find(this.assertions, function(assertion){ - return !assertion.passed - }) - }, - - // Find all failing assertions - - failures : function() { - return select(this.assertions, function(assertion){ - return !assertion.passed - }) - }, - - // Weither or not the spec passed - - passed : function() { - return !this.failure() - }, - - // Weither or not the spec requires implementation (no assertions) - - requiresImplementation : function() { - return this.assertions.length == 0 - }, - - // Sprite based assertions graph - - assertionsGraph : function() { - return map(this.assertions, function(assertion){ - return '' - }).join('') - } - }) - }, - - Module : function(methods) { - extend(this, methods) - }, - - JSON : { - - /** - * Generic sequences. - */ - - meta : { - '\b' : '\\b', - '\t' : '\\t', - '\n' : '\\n', - '\f' : '\\f', - '\r' : '\\r', - '"' : '\\"', - '\\' : '\\\\' - }, - - /** - * Escapable sequences. - */ - - escapable : /[\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, - - /** - * JSON encode _object_. - * - * @param {mixed} object - * @return {string} - * @api private - */ - - encode : function(object) { - var self = this - if (object == undefined || object == null) return 'null' - if (object === true) return 'true' - if (object === false) return 'false' - switch (typeof object) { - case 'number': return object - case 'string': return this.escapable.test(object) ? - '"' + object.replace(this.escapable, function (a) { - return typeof self.meta[a] === 'string' ? self.meta[a] : - '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4) - }) + '"' : - '"' + object + '"' - case 'object': - if (object.constructor == Array) - return '[' + map(object, function(val){ - return self.encode(val) - }).join(', ') + ']' - else if (object) - return '{' + map(object, function(key, val){ - return self.encode(key) + ':' + self.encode(val) - }).join(', ') + '}' - } - return 'null' - } - }, - - // --- DSLs - - DSLs : { - snake : { - expect : function(actual){ - return JSpec.expect(actual) - }, - - describe : function(description, body) { - return JSpec.currentSuite.addSuite(description, body) - }, - - it : function(description, body) { - return JSpec.currentSuite.addSpec(description, body) - }, - - before : function(body) { - return JSpec.currentSuite.addHook('before', body) - }, - - after : function(body) { - return JSpec.currentSuite.addHook('after', body) - }, - - before_each : function(body) { - return JSpec.currentSuite.addHook('before_each', body) - }, - - after_each : function(body) { - return JSpec.currentSuite.addHook('after_each', body) - }, - - should_behave_like : function(description) { - return JSpec.shareBehaviorsOf(description) - } - } - }, - - // --- Methods - - /** - * Check if _value_ is 'stop'. For use as a - * utility callback function. - * - * @param {mixed} value - * @return {bool} - * @api public - */ - - haveStopped : function(value) { - return value === 'stop' - }, - - /** - * Include _object_ which may be a hash or Module instance. - * - * @param {hash, Module} object - * @return {JSpec} - * @api public - */ - - include : function(object) { - var module = object.constructor == JSpec.Module ? object : new JSpec.Module(object) - this.modules.push(module) - if ('init' in module) module.init() - if ('utilities' in module) extend(this.defaultContext, module.utilities) - if ('matchers' in module) this.addMatchers(module.matchers) - if ('reporters' in module) extend(this.reporters, module.reporters) - if ('DSLs' in module) - each(module.DSLs, function(name, methods){ - JSpec.DSLs[name] = JSpec.DSLs[name] || {} - extend(JSpec.DSLs[name], methods) - }) - return this - }, - - /** - * Add a module hook _name_, which is immediately - * called per module with the _args_ given. An array of - * hook return values is returned. - * - * @param {name} string - * @param {...} args - * @return {array} - * @api private - */ - - hook : function(name, args) { - args = toArray(arguments, 1) - return inject(JSpec.modules, [], function(results, module){ - if (typeof module[name] == 'function') - results.push(JSpec.evalHook(module, name, args)) - }) - }, - - /** - * Eval _module_ hook _name_ with _args_. Evaluates in context - * to the module itself, JSpec, and JSpec.context. - * - * @param {Module} module - * @param {string} name - * @param {array} args - * @return {mixed} - * @api private - */ - - evalHook : function(module, name, args) { - hook('evaluatingHookBody', module, name) - try { return module[name].apply(module, args) } - catch(e) { error('Error in hook ' + module.name + '.' + name + ': ', e) } - }, - - /** - * Same as hook() however accepts only one _arg_ which is - * considered immutable. This function passes the arg - * to the first module, then passes the return value of the last - * module called, to the following module. - * - * @param {string} name - * @param {mixed} arg - * @return {mixed} - * @api private - */ - - hookImmutable : function(name, arg) { - return inject(JSpec.modules, arg, function(result, module){ - if (typeof module[name] == 'function') - return JSpec.evalHook(module, name, [result]) - }) - }, - - /** - * Find a suite by its description or name. - * - * @param {string} description - * @return {Suite} - * @api private - */ - - findSuite : function(description) { - return find(this.allSuites, function(suite){ - return suite.name == description || suite.description == description - }) - }, - - /** - * Share behaviors (specs) of the given suite with - * the current suite. - * - * @param {string} description - * @api public - */ - - shareBehaviorsOf : function(description) { - if (suite = this.findSuite(description)) this.copySpecs(suite, this.currentSuite) - else throw 'failed to share behaviors. ' + puts(description) + ' is not a valid Suite name' - }, - - /** - * Copy specs from one suite to another. - * - * @param {Suite} fromSuite - * @param {Suite} toSuite - * @api public - */ - - copySpecs : function(fromSuite, toSuite) { - each(fromSuite.specs, function(spec){ - var newSpec = new Object(); - extend(newSpec, spec); - newSpec.assertions = []; - toSuite.specs.push(newSpec); - }) - }, - - /** - * Convert arguments to an array. - * - * @param {object} arguments - * @param {int} offset - * @return {array} - * @api public - */ - - toArray : function(arguments, offset) { - return Array.prototype.slice.call(arguments, offset || 0) - }, - - /** - * Return ANSI-escaped colored string. - * - * @param {string} string - * @param {string} color - * @return {string} - * @api public - */ - - color : function(string, color) { - return "\u001B[" + { - bold : 1, - black : 30, - red : 31, - green : 32, - yellow : 33, - blue : 34, - magenta : 35, - cyan : 36, - white : 37 - }[color] + 'm' + string + "\u001B[0m" - }, - - /** - * Default matcher message callback. - * - * @api private - */ - - defaultMatcherMessage : function(actual, expected, negate, name) { - return 'expected ' + puts(actual) + ' to ' + - (negate ? 'not ' : '') + - name.replace(/_/g, ' ') + - ' ' + (expected.length > 1 ? - puts.apply(this, expected.slice(1)) : - '') - }, - - /** - * Normalize a matcher message. - * - * When no messge callback is present the defaultMatcherMessage - * will be assigned, will suffice for most matchers. - * - * @param {hash} matcher - * @return {hash} - * @api public - */ - - normalizeMatcherMessage : function(matcher) { - if (typeof matcher.message != 'function') - matcher.message = this.defaultMatcherMessage - return matcher - }, - - /** - * Normalize a matcher body - * - * This process allows the following conversions until - * the matcher is in its final normalized hash state. - * - * - '==' becomes 'actual == expected' - * - 'actual == expected' becomes 'return actual == expected' - * - function(actual, expected) { return actual == expected } becomes - * { match : function(actual, expected) { return actual == expected }} - * - * @param {mixed} body - * @return {hash} - * @api public - */ - - normalizeMatcherBody : function(body) { - switch (body.constructor) { - case String: - if (captures = body.match(/^alias (\w+)/)) return JSpec.matchers[last(captures)] - if (body.length < 4) body = 'actual ' + body + ' expected' - return { match: function(actual, expected) { return eval(body) }} - - case Function: - return { match: body } - - default: - return body - } - }, - - /** - * Get option value. This method first checks if - * the option key has been set via the query string, - * otherwise returning the options hash value. - * - * @param {string} key - * @return {mixed} - * @api public - */ - - option : function(key) { - return (value = query(key)) !== null ? value : - JSpec.options[key] || null - }, - - /** - * Check if object _a_, is equal to object _b_. - * - * @param {object} a - * @param {object} b - * @return {bool} - * @api private - */ - - equal: function(a, b) { - if (typeof a != typeof b) return - if (a === b) return true - if (a instanceof RegExp) - return a.toString() === b.toString() - if (a instanceof Date) - return Number(a) === Number(b) - if (typeof a != 'object') return - if (a.length !== undefined) - if (a.length !== b.length) return - else - for (var i = 0, len = a.length; i < len; ++i) - if (!equal(a[i], b[i])) - return - for (var key in a) - if (!equal(a[key], b[key])) - return - return true - }, - - /** - * Return last element of an array. - * - * @param {array} array - * @return {object} - * @api public - */ - - last : function(array) { - return array[array.length - 1] - }, - - /** - * Convert object(s) to a print-friend string. - * - * @param {...} object - * @return {string} - * @api public - */ - - puts : function(object) { - if (arguments.length > 1) - return map(toArray(arguments), function(arg){ - return puts(arg) - }).join(', ') - if (object === undefined) return 'undefined' - if (object === null) return 'null' - if (object === true) return 'true' - if (object === false) return 'false' - if (object.an_instance_of) return 'an instance of ' + object.an_instance_of.name - if (object.jquery && object.selector.length > 0) return 'selector ' + puts(object.selector) - if (object.jquery) return object.get(0).outerHTML - if (object.nodeName) return object.outerHTML - switch (object.constructor) { - case Function: return object.name || object - case String: - return '"' + object - .replace(/"/g, '\\"') - .replace(/\n/g, '\\n') - .replace(/\t/g, '\\t') - + '"' - case Array: - return inject(object, '[', function(b, v){ - return b + ', ' + puts(v) - }).replace('[,', '[') + ' ]' - case Object: - object.__hit__ = true - return inject(object, '{', function(b, k, v) { - if (k == '__hit__') return b - return b + ', ' + k + ': ' + (v && v.__hit__ ? '' : puts(v)) - }).replace('{,', '{') + ' }' - default: - return object.toString() - } - }, - - /** - * Escape HTML. - * - * @param {string} html - * @return {string} - * @api public - */ - - escape : function(html) { - return html.toString() - .replace(/&/gmi, '&') - .replace(/"/gmi, '"') - .replace(/>/gmi, '>') - .replace(/ current) while (++current <= end) values.push(current) - else while (--current >= end) values.push(current) - return '[' + values + ']' - }, - - /** - * Report on the results. - * - * @api public - */ - - report : function() { - this.duration = Number(new Date) - this.start - hook('reporting', JSpec.options) - new (JSpec.options.reporter || JSpec.reporters.DOM)(JSpec, JSpec.options) - }, - - /** - * Run the spec suites. Options are merged - * with JSpec options when present. - * - * @param {hash} options - * @return {JSpec} - * @api public - */ - - run : function(options) { - if (any(hook('running'), haveStopped)) return this - if (options) extend(this.options, options) - this.start = Number(new Date) - each(this.suites, function(suite) { JSpec.runSuite(suite) }) - return this - }, - - /** - * Run a suite. - * - * @param {Suite} suite - * @api public - */ - - runSuite : function(suite) { - this.currentSuite = suite - this.evalBody(suite.body) - suite.ran = true - hook('beforeSuite', suite), suite.hook('before') - each(suite.specs, function(spec) { - hook('beforeSpec', spec) - suite.hook('before_each') - JSpec.runSpec(spec) - hook('afterSpec', spec) - suite.hook('after_each') - }) - if (suite.hasSuites()) { - each(suite.suites, function(suite) { - JSpec.runSuite(suite) - }) - } - hook('afterSuite', suite), suite.hook('after') - this.stats.suitesFinished++ - }, - - /** - * Report a failure for the current spec. - * - * @param {string} message - * @api public - */ - - fail : function(message) { - JSpec.currentSpec.fail(message) - }, - - /** - * Report a passing assertion for the current spec. - * - * @param {string} message - * @api public - */ - - pass : function(message) { - JSpec.currentSpec.pass(message) - }, - - /** - * Run a spec. - * - * @param {Spec} spec - * @api public - */ - - runSpec : function(spec) { - this.currentSpec = spec - try { this.evalBody(spec.body) } - catch (e) { fail(e) } - spec.runDeferredAssertions() - destub() - this.stats.specsFinished++ - this.stats.assertions += spec.assertions.length - }, - - /** - * Require a dependency, with optional message. - * - * @param {string} dependency - * @param {string} message (optional) - * @return {JSpec} - * @api public - */ - - requires : function(dependency, message) { - hook('requiring', dependency, message) - try { eval(dependency) } - catch (e) { throw 'JSpec depends on ' + dependency + ' ' + message } - return this - }, - - /** - * Query against the current query strings keys - * or the queryString specified. - * - * @param {string} key - * @param {string} queryString - * @return {string, null} - * @api private - */ - - query : function(key, queryString) { - var queryString = (queryString || (main.location ? main.location.search : null) || '').substring(1) - return inject(queryString.split('&'), null, function(value, pair){ - parts = pair.split('=') - return parts[0] == key ? parts[1].replace(/%20|\+/gmi, ' ') : value - }) - }, - - /** - * Throw a JSpec related error. - * - * @param {string} message - * @param {Exception} e - * @api public - */ - - error : function(message, e) { - throw (message ? message : '') + e.toString() + - (e.line ? ' near line ' + e.line : '') - }, - - /** - * Ad-hoc POST request for JSpec server usage. - * - * @param {string} uri - * @param {string} data - * @api private - */ - - post : function(uri, data) { - if (any(hook('posting', uri, data), haveStopped)) return - var request = this.xhr() - request.open('POST', uri, false) - request.setRequestHeader('Content-Type', 'application/json') - request.send(JSpec.JSON.encode(data)) - }, - - /** - * Instantiate an XMLHttpRequest. - * - * Here we utilize IE's lame ActiveXObjects first which - * allow IE access serve files via the file: protocol, otherwise - * we then default to XMLHttpRequest. - * - * @return {XMLHttpRequest, ActiveXObject} - * @api private - */ - - xhr : function() { - return this.ieXhr() || new JSpec.request - }, - - /** - * Return Microsoft piece of crap ActiveXObject. - * - * @return {ActiveXObject} - * @api public - */ - - ieXhr : function() { - function object(str) { - try { return new ActiveXObject(str) } catch(e) {} - } - return object('Msxml2.XMLHTTP.6.0') || - object('Msxml2.XMLHTTP.3.0') || - object('Msxml2.XMLHTTP') || - object('Microsoft.XMLHTTP') - }, - - /** - * Check for HTTP request support. - * - * @return {bool} - * @api private - */ - - hasXhr : function() { - return JSpec.request || 'ActiveXObject' in main - }, - - /** - * Try loading _file_ returning the contents - * string or null. Chain to locate / read a file. - * - * @param {string} file - * @return {string} - * @api public - */ - - tryLoading : function(file) { - try { return JSpec.load(file) } catch (e) {} - }, - - /** - * Load a _file_'s contents. - * - * @param {string} file - * @param {function} callback - * @return {string} - * @api public - */ - - load : function(file, callback) { - if (any(hook('loading', file), haveStopped)) return - if ('readFile' in main) - return readFile(file) - else if (this.hasXhr()) { - var request = this.xhr() - request.open('GET', file, false) - request.send(null) - if (request.readyState == 4 && - (request.status == 0 || - request.status.toString().charAt(0) == 2)) - return request.responseText - } - else - error("failed to load `" + file + "'") - }, - - /** - * Load, pre-process, and evaluate a file. - * - * @param {string} file - * @param {JSpec} - * @api public - */ - - exec : function(file) { - if (any(hook('executing', file), haveStopped)) return this - eval('with (JSpec){' + this.preprocess(this.load(file)) + '}') - return this - } - } - - // --- Node.js support - - if (typeof GLOBAL === 'object' && typeof exports === 'object') - quit = process.exit, - print = require('sys').puts, - readFile = require('fs').readFileSync - - // --- Utility functions - - var main = this, - find = JSpec.any, - utils = 'haveStopped stub hookImmutable hook destub map any last pass fail range each option inject select \ - error escape extend puts query strip color does addMatchers callIterator toArray equal'.split(/\s+/) - while (utils.length) eval('var ' + utils[0] + ' = JSpec.' + utils.shift()) - if (!main.setTimeout) main.setTimeout = function(callback){ callback() } - - // --- Matchers - - addMatchers({ - equal : "===", - eql : "equal(actual, expected)", - be : "alias equal", - be_greater_than : ">", - be_less_than : "<", - be_at_least : ">=", - be_at_most : "<=", - be_a : "actual.constructor == expected", - be_an : "alias be_a", - be_an_instance_of : "actual instanceof expected", - be_null : "actual == null", - be_true : "actual == true", - be_false : "actual == false", - be_undefined : "typeof actual == 'undefined'", - be_type : "typeof actual == expected", - match : "typeof actual == 'string' ? actual.match(expected) : false", - respond_to : "typeof actual[expected] == 'function'", - have_length : "actual.length == expected", - be_within : "actual >= expected[0] && actual <= last(expected)", - have_length_within : "actual.length >= expected[0] && actual.length <= last(expected)", - - receive : { defer : true, match : function(actual, method, times) { - proxy = new JSpec.ProxyAssertion(actual, method, times, this.negate) - JSpec.currentSpec.assertions.push(proxy) - return proxy - }}, - - be_empty : function(actual) { - if (actual.constructor == Object && actual.length == undefined) - for (var key in actual) - return false; - return !actual.length - }, - - include : function(actual) { - for (state = true, i = 1; i < arguments.length; i++) { - arg = arguments[i] - switch (actual.constructor) { - case String: - case Number: - case RegExp: - case Function: - state = actual.toString().indexOf(arg) !== -1 - break - - case Object: - state = arg in actual - break - - case Array: - state = any(actual, function(value){ return equal(value, arg) }) - break - } - if (!state) return false - } - return true - }, - - throw_error : { match : function(actual, expected, message) { - try { actual() } - catch (e) { - this.e = e - var assert = function(arg) { - switch (arg.constructor) { - case RegExp : return arg.test(e.message || e.toString()) - case String : return arg == (e.message || e.toString()) - case Function : return e instanceof arg || e.name == arg.name - } - } - return message ? assert(expected) && assert(message) : - expected ? assert(expected) : - true - } - }, message : function(actual, expected, negate) { - // TODO: refactor when actual is not in expected [0] - var message_for = function(i) { - if (expected[i] == undefined) return 'exception' - switch (expected[i].constructor) { - case RegExp : return 'exception matching ' + puts(expected[i]) - case String : return 'exception of ' + puts(expected[i]) - case Function : return expected[i].name || 'Error' - } - } - exception = message_for(1) + (expected[2] ? ' and ' + message_for(2) : '') - return 'expected ' + exception + (negate ? ' not ' : '' ) + - ' to be thrown, but ' + (this.e ? 'got ' + puts(this.e) : 'nothing was') - }}, - - have : function(actual, length, property) { - return actual[property].length == length - }, - - have_at_least : function(actual, length, property) { - return actual[property].length >= length - }, - - have_at_most :function(actual, length, property) { - return actual[property].length <= length - }, - - have_within : function(actual, range, property) { - length = actual[property].length - return length >= range.shift() && length <= range.pop() - }, - - have_prop : function(actual, property, value) { - return actual[property] == null || - actual[property] instanceof Function ? false: - value == null ? true: - does(actual[property], 'eql', value) - }, - - have_property : function(actual, property, value) { - return actual[property] == null || - actual[property] instanceof Function ? false: - value == null ? true: - value === actual[property] - } - }) - -})() -- cgit v1.2.3