summaryrefslogtreecommitdiff
path: root/share/www/script/jspec/jspec.js
diff options
context:
space:
mode:
authorAdam Kocoloski <adam@cloudant.com>2010-08-11 16:13:08 -0400
committerAdam Kocoloski <adam@cloudant.com>2010-08-11 17:39:38 -0400
commitad7099a4e3f3d2035e3e26419a633b4bb1ce7b7c (patch)
tree435656380eb6cefc7abe3d20369f022a75a014f3 /share/www/script/jspec/jspec.js
parent67eff5876bca3108baf37b97cfc9f9e5920dcdb7 (diff)
move futon into release overlay
Diffstat (limited to 'share/www/script/jspec/jspec.js')
-rw-r--r--share/www/script/jspec/jspec.js1756
1 files changed, 0 insertions, 1756 deletions
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 <tj@vision-media.ca> (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:
- *
- * - <path>
- * - <path>.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, '<br/>')
- }
-
- report.innerHTML = '<div id="jspec-report" class="' + classes + '"><div class="heading"> \
- <span class="passes">Passes: <em>' + results.stats.passes + '</em></span> \
- <span class="failures">Failures: <em>' + results.stats.failures + '</em></span> \
- <span class="passes">Duration: <em>' + results.duration + '</em> ms</span> \
- </div><table class="suites">' + map(results.allSuites, function(suite) {
- var displaySuite = failuresOnly ? suite.ran && !suite.passed() : suite.ran
- if (displaySuite && suite.hasSpecs())
- return '<tr class="description"><td colspan="2">' + escape(suite.description) + '</td></tr>' +
- map(suite.specs, function(i, spec) {
- return '<tr class="' + (i % 2 ? 'odd' : 'even') + '">' +
- (spec.requiresImplementation() ?
- '<td class="requires-implementation" colspan="2">' + escape(spec.description) + '</td>' :
- (spec.passed() && !failuresOnly) ?
- '<td class="pass">' + escape(spec.description)+ '</td><td>' + spec.assertionsGraph() + '</td>' :
- !spec.passed() ?
- '<td class="fail">' + escape(spec.description) +
- map(spec.failures(), function(a){ return '<em>' + escape(a.message) + '</em>' }).join('') +
- '</td><td>' + spec.assertionsGraph() + '</td>' :
- '') +
- '<tr class="body"><td colspan="2"><pre>' + bodyContents(spec.body) + '</pre></td></tr>'
- }).join('') + '</tr>'
- }).join('') + '</table></div>'
- },
-
- /**
- * 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 '<span class="assertion ' + (assertion.passed ? 'passed' : 'failed') + '"></span>'
- }).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__ ? '<circular reference>' : puts(v))
- }).replace('{,', '{') + ' }'
- default:
- return object.toString()
- }
- },
-
- /**
- * Escape HTML.
- *
- * @param {string} html
- * @return {string}
- * @api public
- */
-
- escape : function(html) {
- return html.toString()
- .replace(/&/gmi, '&amp;')
- .replace(/"/gmi, '&quot;')
- .replace(/>/gmi, '&gt;')
- .replace(/</gmi, '&lt;')
- },
-
- /**
- * Perform an assertion without reporting.
- *
- * This method is primarily used for internal
- * matchers in order retain DRYness. May be invoked
- * like below:
- *
- * does('foo', 'eql', 'foo')
- * does([1,2], 'include', 1, 2)
- *
- * External hooks are not run for internal assertions
- * performed by does().
- *
- * @param {mixed} actual
- * @param {string} matcher
- * @param {...} expected
- * @return {mixed}
- * @api private
- */
-
- does : function(actual, matcher, expected) {
- var assertion = new JSpec.Assertion(JSpec.matchers[matcher], actual, toArray(arguments, 2))
- return assertion.run().result
- },
-
- /**
- * Perform an assertion.
- *
- * expect(true).to('be', true)
- * expect('foo').not_to('include', 'bar')
- * expect([1, [2]]).to('include', 1, [2])
- *
- * @param {mixed} actual
- * @return {hash}
- * @api public
- */
-
- expect : function(actual) {
- function assert(matcher, args, negate) {
- var expected = toArray(args, 1)
- matcher.negate = negate
- assertion = new JSpec.Assertion(matcher, actual, expected, negate)
- hook('beforeAssertion', assertion)
- if (matcher.defer) assertion.run()
- else JSpec.currentSpec.assertions.push(assertion.run().report()), hook('afterAssertion', assertion)
- return assertion.result
- }
-
- function to(matcher) {
- return assert(matcher, arguments, false)
- }
-
- function not_to(matcher) {
- return assert(matcher, arguments, true)
- }
-
- return {
- to : to,
- should : to,
- not_to: not_to,
- should_not : not_to
- }
- },
-
- /**
- * Strim whitespace or chars.
- *
- * @param {string} string
- * @param {string} chars
- * @return {string}
- * @api public
- */
-
- strip : function(string, chars) {
- return string.
- replace(new RegExp('[' + (chars || '\\s') + ']*$'), '').
- replace(new RegExp('^[' + (chars || '\\s') + ']*'), '')
- },
-
- /**
- * Call an iterator callback with arguments a, or b
- * depending on the arity of the callback.
- *
- * @param {function} callback
- * @param {mixed} a
- * @param {mixed} b
- * @return {mixed}
- * @api private
- */
-
- callIterator : function(callback, a, b) {
- return callback.length == 1 ? callback(b) : callback(a, b)
- },
-
- /**
- * Extend an object with another.
- *
- * @param {object} object
- * @param {object} other
- * @api public
- */
-
- extend : function(object, other) {
- each(other, function(property, value){
- object[property] = value
- })
- },
-
- /**
- * Iterate an object, invoking the given callback.
- *
- * @param {hash, array} object
- * @param {function} callback
- * @return {JSpec}
- * @api public
- */
-
- each : function(object, callback) {
- if (object.constructor == Array)
- for (var i = 0, len = object.length; i < len; ++i)
- callIterator(callback, i, object[i])
- else
- for (var key in object)
- if (object.hasOwnProperty(key))
- callIterator(callback, key, object[key])
- },
-
- /**
- * Iterate with memo.
- *
- * @param {hash, array} object
- * @param {object} memo
- * @param {function} callback
- * @return {object}
- * @api public
- */
-
- inject : function(object, memo, callback) {
- each(object, function(key, value){
- memo = (callback.length == 2 ?
- callback(memo, value):
- callback(memo, key, value)) ||
- memo
- })
- return memo
- },
-
- /**
- * Destub _object_'s _method_. When no _method_ is passed
- * all stubbed methods are destubbed. When no arguments
- * are passed every object found in JSpec.stubbed will be
- * destubbed.
- *
- * @param {mixed} object
- * @param {string} method
- * @api public
- */
-
- destub : function(object, method) {
- if (method) {
- if (object['__prototype__' + method])
- delete object[method]
- else
- object[method] = object['__original__' + method]
- delete object['__prototype__' + method]
- delete object['__original____' + method]
- }
- else if (object) {
- for (var key in object)
- if (captures = key.match(/^(?:__prototype__|__original__)(.*)/))
- destub(object, captures[1])
- }
- else
- while (JSpec.stubbed.length)
- destub(JSpec.stubbed.shift())
- },
-
- /**
- * Stub _object_'s _method_.
- *
- * stub(foo, 'toString').and_return('bar')
- *
- * @param {mixed} object
- * @param {string} method
- * @return {hash}
- * @api public
- */
-
- stub : function(object, method) {
- hook('stubbing', object, method)
- JSpec.stubbed.push(object)
- var type = object.hasOwnProperty(method) ? '__original__' : '__prototype__'
- object[type + method] = object[method]
- object[method] = function(){}
- return {
- and_return : function(value) {
- if (typeof value == 'function') object[method] = value
- else object[method] = function(){ return value }
- }
- }
- },
-
- /**
- * Map callback return values.
- *
- * @param {hash, array} object
- * @param {function} callback
- * @return {array}
- * @api public
- */
-
- map : function(object, callback) {
- return inject(object, [], function(memo, key, value){
- memo.push(callIterator(callback, key, value))
- })
- },
-
- /**
- * Returns the first matching expression or null.
- *
- * @param {hash, array} object
- * @param {function} callback
- * @return {mixed}
- * @api public
- */
-
- any : function(object, callback) {
- return inject(object, null, function(state, key, value){
- if (state == undefined)
- return callIterator(callback, key, value) ? value : state
- })
- },
-
- /**
- * Returns an array of values collected when the callback
- * given evaluates to true.
- *
- * @param {hash, array} object
- * @return {function} callback
- * @return {array}
- * @api public
- */
-
- select : function(object, callback) {
- return inject(object, [], function(selected, key, value){
- if (callIterator(callback, key, value))
- selected.push(value)
- })
- },
-
- /**
- * Define matchers.
- *
- * @param {hash} matchers
- * @api public
- */
-
- addMatchers : function(matchers) {
- each(matchers, function(name, body){
- JSpec.addMatcher(name, body)
- })
- },
-
- /**
- * Define a matcher.
- *
- * @param {string} name
- * @param {hash, function, string} body
- * @api public
- */
-
- addMatcher : function(name, body) {
- hook('addingMatcher', name, body)
- if (name.indexOf(' ') != -1) {
- var matchers = name.split(/\s+/)
- var prefix = matchers.shift()
- each(matchers, function(name) {
- JSpec.addMatcher(prefix + '_' + name, body(name))
- })
- }
- this.matchers[name] = this.normalizeMatcherMessage(this.normalizeMatcherBody(body))
- this.matchers[name].name = name
- },
-
- /**
- * Add a root suite to JSpec.
- *
- * @param {string} description
- * @param {body} function
- * @api public
- */
-
- describe : function(description, body) {
- var suite = new JSpec.Suite(description, body)
- hook('addingSuite', suite)
- this.allSuites.push(suite)
- this.suites.push(suite)
- },
-
- /**
- * Return the contents of a function body.
- *
- * @param {function} body
- * @return {string}
- * @api public
- */
-
- contentsOf : function(body) {
- return body.toString().match(/^[^\{]*{((.*\n*)*)}/m)[1]
- },
-
- /**
- * Evaluate a JSpec capture body.
- *
- * @param {function} body
- * @param {string} errorMessage (optional)
- * @return {Type}
- * @api private
- */
-
- evalBody : function(body, errorMessage) {
- var dsl = this.DSL || this.DSLs.snake
- var matchers = this.matchers
- var context = this.context || this.defaultContext
- var contents = this.contentsOf(body)
- hook('evaluatingBody', dsl, matchers, context, contents)
- try { with (dsl){ with (context) { with (matchers) { eval(contents) }}} }
- catch(e) { error(errorMessage, e) }
- },
-
- /**
- * Pre-process a string of JSpec.
- *
- * @param {string} input
- * @return {string}
- * @api private
- */
-
- preprocess : function(input) {
- if (typeof input != 'string') return
- input = hookImmutable('preprocessing', input)
- return input.
- replace(/\t/g, ' ').
- replace(/\r\n|\n|\r/g, '\n').
- split('__END__')[0].
- replace(/([\w\.]+)\.(stub|destub)\((.*?)\)$/gm, '$2($1, $3)').
- replace(/describe\s+(.*?)$/gm, 'describe($1, function(){').
- replace(/^\s+it\s+(.*?)$/gm, ' it($1, function(){').
- replace(/^ *(before_each|after_each|before|after)(?= |\n|$)/gm, 'JSpec.currentSuite.addHook("$1", function(){').
- replace(/^\s*end(?=\s|$)/gm, '});').
- replace(/-\{/g, 'function(){').
- replace(/(\d+)\.\.(\d+)/g, function(_, a, b){ return range(a, b) }).
- replace(/\.should([_\.]not)?[_\.](\w+)(?: |;|$)(.*)$/gm, '.should$1_$2($3)').
- replace(/([\/\s]*)(.+?)\.(should(?:[_\.]not)?)[_\.](\w+)\((.*)\)\s*;?$/gm, '$1 expect($2).$3($4, $5)').
- replace(/, \)/g, ')').
- replace(/should\.not/g, 'should_not')
- },
-
- /**
- * Create a range string which can be evaluated to a native array.
- *
- * @param {int} start
- * @param {int} end
- * @return {string}
- * @api public
- */
-
- range : function(start, end) {
- var current = parseInt(start), end = parseInt(end), values = [current]
- if (end > 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]
- }
- })
-
-})()