diff --git a/LICENSE.md b/LICENSE.md index aadd4b88..fd9407a6 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,7 +1,7 @@ License ======= -JSDoc Toolkit Version 3 is free software. +JSDoc 3 is free software. Copyright 2010 (c) Michael Mathews @@ -21,7 +21,7 @@ In Addition =========== Third party software is included, used-by or distributed along -with JSDoc Toolkit Version 3. Each is provided under its own license +with JSDoc 3. Each is provided under its own license and has source available from other locations. Rhino @@ -81,22 +81,40 @@ http://creativecommons.org/licenses/LGPL/2.1/ http://goessner.net/ http://goessner.net/download/prj/jsonxml/ -jsUnity +JSpec ------- -jsUnity is Copyright (c) 2009 Ates Goral -Universal JavaScript Testing Framework v0.6 http://jsunity.com/ +JSpec is copyright (c) 2008 - 2010 TJ Holowaychuk tj@vision-media.ca -http://github.com/atesgoral/jsunity +http://github.com/visionmedia/jspec -Licensed under the MIT license -http://www.opensource.org/licenses/mit-license.php +Licensed under the MIT license. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. JSONSchema Validator -------------------- JSONSchema is copyright (c) 2007 Kris Zyp SitePen (www.sitepen.com) -Licensed under the MIT (MIT-LICENSE.txt) license. http://github.com/kriszyp/commonjs-utils/blob/master/lib/json-schema.js -http://www.sitepen.com/blog/2010/03/02/commonjs-utilities/ \ No newline at end of file +http://www.sitepen.com/blog/2010/03/02/commonjs-utilities/ + +Licensed under the MIT license. \ No newline at end of file diff --git a/java/build.xml b/java/build.xml index 226b6729..6153fb98 100644 --- a/java/build.xml +++ b/java/build.xml @@ -1,10 +1,13 @@ - + + + - + + - + - + - - + + - - + + + + + + + \ No newline at end of file diff --git a/jsdoc.jar b/jsdoc.jar index c1a381ab..1c1c71d9 100644 Binary files a/jsdoc.jar and b/jsdoc.jar differ diff --git a/lib/jsunity.js b/lib/jsunity.js deleted file mode 100644 index 36639157..00000000 --- a/lib/jsunity.js +++ /dev/null @@ -1,391 +0,0 @@ -//<% -/** - * jsUnity Universal JavaScript Testing Framework v0.6 - * http://jsunity.com/ - * - * Copyright (c) 2009 Ates Goral - * Licensed under the MIT license. - * http://www.opensource.org/licenses/mit-license.php - */ - -jsUnity = (function () { - function fmt(str) { - var a = Array.prototype.slice.call(arguments, 1); - return str.replace(/\?/g, function () { return a.shift(); }); - } - - function hash(v) { - if (v instanceof Object) { - var arr = []; - - for (var p in v) { - arr.push(p); - arr.push(hash(v[p])); - } - - return arr.join("#"); - } else { - return String(v); - } - } - - var defaultAssertions = { - assertException: function (fn, message) { - try { - fn instanceof Function && fn(); - } catch (e) { - return; - } - - throw fmt("?: (?) does not raise an exception or not a function", - message || "assertException", fn); - }, - - assertTrue: function (actual, message) { - if (!actual) { - throw fmt("?: (?) does not evaluate to true", - message || "assertTrue", actual); - } - }, - - assertFalse: function (actual, message) { - if (actual) { - throw fmt("?: (?) does not evaluate to false", - message || "assertFalse", actual); - } - }, - - assertIdentical: function (expected, actual, message) { - if (expected !== actual) { - throw fmt("?: (?) is not identical to (?)", - message || "assertIdentical", actual, expected); - } - }, - - assertNotIdentical: function (expected, actual, message) { - if (expected === actual) { - throw fmt("?: (?) is identical to (?)", - message || "assertNotIdentical", actual, expected); - } - }, - - assertEqual: function (expected, actual, message) { - if (hash(expected) != hash(actual)) { - throw fmt("?: (?) is not equal to (?)", - message || "assertEqual", actual, expected); - } - }, - - assertNotEqual: function (expected, actual, message) { - if (hash(expected) == hash(actual)) { - throw fmt("?: (?) is equal to (?)", - message || "assertNotEqual", actual, expected); - } - }, - - assertMatch: function (re, actual, message) { - if (!re.test(actual)) { - throw fmt("?: (?) does not match (?)", - message || "assertMatch", actual, re); - } - }, - - assertNotMatch: function (re, actual, message) { - if (re.test(actual)) { - throw fmt("?: (?) matches (?)", - message || "assertNotMatch", actual, re); - } - }, - - assertTypeOf: function (typ, actual, message) { - if (typeof actual !== typ) { - throw fmt("?: (?) is not of type (?)", - message || "assertTypeOf", actual, typ); - } - }, - - assertNotTypeOf: function (typ, actual, message) { - if (typeof actual === typ) { - throw fmt("?: (?) is of type (?)", - message || "assertNotTypeOf", actual, typ); - } - }, - - assertInstanceOf: function (cls, actual, message) { - if (!(actual instanceof cls)) { - throw fmt("?: (?) is not an instance of (?)", - message || "assertInstanceOf", actual, cls); - } - }, - - assertNotInstanceOf: function (cls, actual, message) { - if (actual instanceof cls) { - throw fmt("?: (?) is an instance of (?)", - message || "assertNotInstanceOf", actual, cls); - } - }, - - assertNull: function (actual, message) { - if (actual !== null) { - throw fmt("?: (?) is not null", - message || "assertNull", actual); - } - }, - - assertNotNull: function (actual, message) { - if (actual === null) { - throw fmt("?: (?) is null", - message || "assertNotNull", actual); - } - }, - - assertUndefined: function (actual, message) { - if (actual !== undefined) { - throw fmt("?: (?) is not undefined", - message || "assertUndefined", actual); - } - }, - - assertNotUndefined: function (actual, message) { - if (actual === undefined) { - throw fmt("?: (?) is undefined", - message || "assertNotUndefined", actual); - } - }, - - assertNaN: function (actual, message) { - if (!isNaN(actual)) { - throw fmt("?: (?) is not NaN", - message || "assertNaN", actual); - } - }, - - assertNotNaN: function (actual, message) { - if (isNaN(actual)) { - throw fmt("?: (?) is NaN", - message || "assertNotNaN", actual); - } - }, - - fail: function (message) { - throw message || "fail"; - } - }; - - function plural(cnt, unit) { - return cnt + " " + unit + (cnt == 1 ? "" : "s"); - } - - function splitFunction(fn) { - var tokens = - /^[\s\r\n]*function[\s\r\n]*([^\(\s\r\n]*?)[\s\r\n]*\([^\)\s\r\n]*\)[\s\r\n]*\{((?:[^}]*\}?)+)\}[\s\r\n]*$/ - .exec(fn); - - if (!tokens) { - throw "Invalid function."; - } - - return { - name: tokens[1].length ? tokens[1] : undefined, - body: tokens[2] - }; - } - - var probeOutside = function () { - try { - return eval( - [ "typeof ", " === \"function\" && ", "" ].join(arguments[0])); - } catch (e) { - return false; - } - }; - - function parseSuiteString(str) { - var obj = {}; - - var probeInside = new Function( - splitFunction(probeOutside).body + str); - - var tokenRe = /(\w+)/g; // todo: wiser regex - var tokens; - - while ((tokens = tokenRe.exec(str))) { - var token = tokens[1]; - var fn; - - if (!obj[token] - && (fn = probeInside(token)) - && fn != probeOutside(token)) { - - obj[token] = fn; - } - } - - return parseSuiteObject(obj); - } - - function parseSuiteFunction(fn) { - var fnParts = splitFunction(fn); - var suite = parseSuiteString(fnParts.body); - - suite.suiteName = fnParts.name; - - return suite; - } - - function parseSuiteArray(tests) { - var obj = {}; - - for (var i = 0; i < tests.length; i++) { - var item = tests[i]; - - if (!obj[item]) { - switch (typeof item) { - case "function": - var fnParts = splitFunction(item); - obj[fnParts.name] = item; - break; - case "string": - var fn; - - if (fn = probeOutside(item)) { - obj[item] = fn; - } - } - } - } - - return parseSuiteObject(obj); - } - - function parseSuiteObject(obj) { - var suite = new jsUnity.TestSuite(obj.suiteName, obj); - - for (var name in obj) { - if (obj.hasOwnProperty(name)) { - var fn = obj[name]; - - if (typeof fn === "function") { - if (/^test/.test(name)) { - suite.tests.push({ name: name, fn: fn }); - } else if (/^setUp|tearDown$/.test(name)) { - suite[name] = fn; - } - } - } - } - - return suite; - } - - return { - TestSuite: function (suiteName, scope) { - this.suiteName = suiteName; - this.scope = scope; - this.tests = []; - this.setUp = undefined; - this.tearDown = undefined; - }, - - TestResults: function () { - this.suiteName = undefined; - this.total = 0; - this.passed = 0; - this.failed = 0; - this.duration = 0; - }, - - assertions: defaultAssertions, - - env: { - defaultScope: this, - - getDate: function () { - return new Date(); - } - }, - - attachAssertions: function (scope) { - scope = scope || this.env.defaultScope; - - for (var fn in jsUnity.assertions) { - scope[fn] = jsUnity.assertions[fn]; - } - }, - - log: function () {}, - - error: function (s) { this.log("[ERROR] " + s); }, - - compile: function (v) { - if (v instanceof jsUnity.TestSuite) { - return v; - } else if (v instanceof Function) { - return parseSuiteFunction(v); - } else if (v instanceof Array) { - return parseSuiteArray(v); - } else if (v instanceof Object) { - return parseSuiteObject(v); - } else if (typeof v === "string") { - return parseSuiteString(v); - } else { - throw "Argument must be a function, array, object, string or " - + "TestSuite instance."; - } - }, - - run: function () { - var results = new jsUnity.TestResults(); - - var suiteNames = []; - var start = jsUnity.env.getDate(); - - for (var i = 0; i < arguments.length; i++) { - try { - var suite = jsUnity.compile(arguments[i]); - } catch (e) { - this.error("Invalid test suite: " + e); - return false; - } - - var cnt = suite.tests.length; - - this.log("Running " - + (suite.suiteName || "unnamed test suite")); - this.log(plural(cnt, "test") + " found"); - - suiteNames.push(suite.suiteName); - results.total += cnt; - - for (var j = 0; j < cnt; j++) { - var test = suite.tests[j]; - - try { - suite.setUp && suite.setUp(); - test.fn.call(suite.scope); - suite.tearDown && suite.tearDown(); - - results.passed++; - - this.log("[PASSED] " + test.name); - } catch (e) { - suite.tearDown && suite.tearDown(); - - this.log("[FAILED] " + test.name + ": " + e); - } - } - } - - results.suiteName = suiteNames.join(","); - results.failed = results.total - results.passed; - results.duration = jsUnity.env.getDate() - start; - - this.log(plural(results.passed, "test") + " passed"); - this.log(plural(results.failed, "test") + " failed"); - this.log(plural(results.duration, "millisecond") + " elapsed"); - - return results; - } - }; -})(); -//%> diff --git a/main.js b/main.js index 0ad6b7a4..cce42ba4 100644 --- a/main.js +++ b/main.js @@ -58,7 +58,9 @@ java.lang.System.exit(0); } else if (opts.test) { - require('jsdoc/test').runAll(); + //require('jsdoc/test').runAll(); + load(BASEDIR+'/test/lib/jspec.js'); + load(BASEDIR + '/test/runall.js'); java.lang.System.exit(0); } diff --git a/modules/goessner/json2xml.js b/modules/goessner/json2xml.js index 5988c4df..5283249f 100644 --- a/modules/goessner/json2xml.js +++ b/modules/goessner/json2xml.js @@ -30,7 +30,7 @@ var json2xml = (typeof exports === 'undefined')? {} : exports; // like commonjs if (hasChild) { for (var m in v) { if (m == "#text") - xml += lines(v[m]); + xml += makeSafe(v[m]); else if (m == "#cdata") xml += ""; else if (m.charAt(0) != "@") @@ -40,7 +40,7 @@ var json2xml = (typeof exports === 'undefined')? {} : exports; // like commonjs } } else { // added special-character transform, but this needs to be better handled [micmath] - xml += ind + "<" + name + ">" + makeSafe(lines(v.toString())) + "\n"; + xml += ind + "<" + name + ">" + makeSafe(v.toString()) + "\n"; } return xml; }, @@ -64,7 +64,7 @@ var json2xml = (typeof exports === 'undefined')? {} : exports; // like commonjs // xml special charaters str = str.replace(/ (MIT Licensed) + +;(function(){ + + JSpec = { + version : '4.3.2', + assert : true, + cache : {}, + suites : [], + modules : [], + allSuites : [], + sharedBehaviors: [], + 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') + }, + + /** + * Load json fixture at _path_. + * + * JSON fixtures are resolved as: + * + * - + * - .json + * + * @param {string} path + * @return {object} + * @api public + */ + + json_fixture: function(path) { + if (!JSpec.cache['json:' + path]) + JSpec.cache['json:' + path] = + JSpec.tryLoading(JSpec.options.fixturePath + '/' + path) || + JSpec.tryLoading(JSpec.options.fixturePath + '/' + path + '.json') + try { + return eval('(' + JSpec.cache['json:' + path] + ')') + } catch (e) { + throw 'json_fixture("' + path + '"): ' + e + } + } + }, + + // --- 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.isExecutable()) + 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.isExecutable()) + 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.isExecutable()) { + 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, + old = object[method] + + // Proxy + + object[method] = function(){ + var 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, isShared) { + var self = this + extend(this, { + body: body, + description: description, + suites: [], + sharedBehaviors: [], + specs: [], + ran: false, + shared: isShared, + hooks: { 'before' : [], 'after' : [], + 'before_each' : [], 'after_each' : [], + 'before_nested' : [], 'after_nested' : []}, + + // 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 before hook to the suite + + addBefore : function(options, body) { + body.options = options || {} + this.befores.push(body) + }, + + // Add an after hook to the suite + + addAfter : function(options, body) { + body.options = options || {} + this.afters.unshift(body) + }, + + // Add a hook to the suite + + addHook : function(hook, body) { + this.hooks[hook].push(body) + }, + + // Add a nested suite + + addSuite : function(description, body, isShared) { + var suite = new JSpec.Suite(description, body, isShared) + 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 (hook != 'before' && hook != 'after') + 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() + }) + }, + + isShared : function(){ + return this.shared + }, + + isExecutable : function() { + return !this.isShared() && this.hasSpecs() + } + }) + }, + + /** + * 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, false) + }, + + 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) + }, + + before_nested : function(body) { + return JSpec.currentSuite.addHook('before_nested', body) + }, + + after_nested : function(body){ + return JSpec.currentSuite.addhook('after_nested', body) + }, + + shared_behaviors_for : function(description, body){ + return JSpec.currentSuite.addSuite(description, body, true) + }, + + 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) + return module[name].apply(module, args) + }, + + /** + * 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 shared example suite by its description or name. + * First searches parent tree of suites for shared behavior + * before falling back to global scoped nested behaviors. + * + * @param {string} description + * @return {Suite} + * @api private + */ + + findSharedBehavior : function(description) { + var behavior + return (behavior = JSpec.findLocalSharedBehavior(description)) + ? behavior + : JSpec.findGlobalSharedBehavior(description) + }, + + /** + * Find a shared example suite within the current suite's + * parent tree by its description or name. + * + * @param {string} description + * @return {Suite} + * @api private + */ + + findLocalSharedBehavior : function(description) { + var behavior, + currentSuite = JSpec.currentSuite.suite + while (currentSuite) + if (behavior = find(currentSuite.suites, JSpec.suiteDescriptionPredicate(description))) + return behavior + else + currentSuite = currentSuite.suite + }, + + /** + * Find a shared example suite within the global + * scope by its description or name. + * + * @param {string} description + * @return {Suite} + * @api private + */ + + findGlobalSharedBehavior : function(description) { + return find(JSpec.suites, JSpec.suiteDescriptionPredicate(description)) + }, + + /** + * Build a predicate that will match a suite based on name or description + * + * @param {string} description + * @return {function} + * @api private + */ + + suiteDescriptionPredicate : function(description) { + return 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) { + var suite = JSpec.findSharedBehavior(description) + if (suite) + JSpec.evalBody(suite.body) + else + throw new Error("failed to find shared behaviors named `" + description + "'") + }, + + + /** + * 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) { + if (option('disableColors')) { + return string + } else { + 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) { + var captures + 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() + } + }, + + /** + * Parse an XML String and return a 'document'. + * + * @param {string} text + * @return {document} + * @api public + */ + + parseXML : function(text) { + var xmlDoc + if (window.DOMParser) + xmlDoc = (new DOMParser()).parseFromString(text, "text/xml") + else { + xmlDoc = new ActiveXObject("Microsoft.XMLDOM") + xmlDoc.async = "false" + xmlDoc.loadXML(text) + } + return xmlDoc + }, + + /** + * 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) { + if (!suite.isShared()) + { + this.currentSuite = suite + this.evalBody(suite.body) + suite.ran = true + hook('beforeSuite', suite), suite.hook('before'), suite.hook('before_nested') + 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_nested'), 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 + }) + }, + + /** + * 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 + throw new 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') { + var fs = require('fs') + quit = process.exit + print = require('sys').puts + readFile = function(file){ + return fs.readFileSync(file).toString('utf8') + } + } + + // --- 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) { + var 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 (var state = true, i = 1; i < arguments.length; i++) { + var 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' + } + } + var 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] == null ? false : actual[property].length == length + }, + + have_at_least : function(actual, length, property) { + return actual[property] == null ? (length === 0) : actual[property].length >= length + }, + + have_at_most :function(actual, length, property) { + return actual[property] == null || actual[property].length <= length + }, + + have_within : function(actual, range, property) { + var length = actual[property] == undefined ? 0 : actual[property].length + return length >= range.shift() && length <= range.pop() + }, + + have_prop : function(actual, property, value) { + var actualVal = actual[property], actualType = typeof actualVal + return (actualType == 'function' || actualType == 'undefined') ? false : + typeof value === 'undefined' || + does(actual[property],'eql',value) + }, + + have_property : function(actual, property, value) { + var actualVal = actual[property], actualType = typeof actualVal + return (actualType == 'function' || actualType == 'undefined') ? false : + typeof value === 'undefined' || + value === actualVal + } + }) + +})() diff --git a/test/runall.js b/test/runall.js new file mode 100644 index 00000000..1eb3d52c --- /dev/null +++ b/test/runall.js @@ -0,0 +1,9 @@ +load(BASEDIR + '/test/tests/01_jsdoc_opts.js'); +load(BASEDIR + '/test/tests/02_jsdoc_src.js'); + +// see http://visionmedia.github.com/jspec/ +JSpec.run({ + reporter: JSpec.reporters.Terminal, + failuresOnly: false +}) +.report(); \ No newline at end of file diff --git a/test/tests/01_jsdoc_opts.js b/test/tests/01_jsdoc_opts.js new file mode 100644 index 00000000..338378dc --- /dev/null +++ b/test/tests/01_jsdoc_opts.js @@ -0,0 +1,98 @@ +(function() { + var jsdoc; + + JSpec.describe('jsdoc/opts.js', function() { + + before_each(function() { + jsdoc = { opts: require('jsdoc/opts') }; + }); + + describe('The object exported by the jsdoc/opts module', function() { + it('should be an object', function() { + expect(jsdoc.opts).to(be_an, Object); + }); + + it('should have a set method', function() { + expect(jsdoc.opts).to(respond_to, 'set'); + }); + }); + + describe('The jsdoc.opts#set method', function() { + it('should return an object', function() { + var returnedValue = jsdoc.opts.set('main.js'); + expect(returnedValue).to(be_an, Object); + }); + }); + + describe('The return value of jsdoc.opts#set when called with no arguments', function() { + it('should have a property named `destination`', function() { + var returnedValue = jsdoc.opts.set(); + expect(returnedValue).to(have_property, 'destination', 'jsdoc.xml'); + }); + + it('should have a property named `template`', function() { + var returnedValue = jsdoc.opts.set(); + expect(returnedValue).to(have_property, 'template', 'default'); + }); + + it('should have a property named `_`', function() { + var returnedValue = jsdoc.opts.set(); + expect(returnedValue).to(have_property, '_'); + }); + }); + + describe('The default value for the property named `opts._`', function() { + it('should be an empty array', function() { + var returnedValue = jsdoc.opts.set(); + expect(returnedValue._).to(be_a, Array); + expect(returnedValue._).to(have_length, 0); + }); + }); + + //// setting the destination option + describe('The return value of jsdoc.opts#set when called with `["-d", "foo/bar.json"]`', function() { + it('should have a property `destination` set to "foo/bar.json"', function() { + var returnedValue = jsdoc.opts.set(['-d', 'foo/bar.json']); + expect(returnedValue.destination).to(be, 'foo/bar.json'); + }); + }); + + describe('The return value of jsdoc.opts#set when called with `["--destination", "flib/flub.json"]`', function() { + it('should have a property `destination` set to "flib/flub.json"', function() { + var returnedValue = jsdoc.opts.set(['--destination', 'flib/flub.json']); + expect(returnedValue.destination).to(be, 'flib/flub.json'); + }); + }); + + describe('The return value of jsdoc.opts#set when called with `["-d", ""]`', function() { + it('should have a property `destination` set to ""', function() { + var returnedValue = jsdoc.opts.set(['-d', '']); + expect(returnedValue.destination).to(be, ''); + }); + }); + + //// setting the template option + describe('The return value of jsdoc.opts#set when called with `["-t", "mytemplate"]`', function() { + it('should have a property `template` set to "mytemplate"', function() { + var returnedValue = jsdoc.opts.set(['-t', 'mytemplate']); + expect(returnedValue.template).to(be, 'mytemplate'); + }); + }); + + describe('The return value of jsdoc.opts#set when called with `["--template", "mytemplate"]`', function() { + it('should have a property `template` set to "mytemplate"', function() { + var returnedValue = jsdoc.opts.set(['--template', 'mytemplate']); + expect(returnedValue.template).to(be, 'mytemplate'); + }); + }); + + //// setting the _ option + describe('The return value of jsdoc.opts#set when called with `["one", "two"]`', function() { + it('should have a property `_` set to ["one", "two"]', function() { + var returnedValue = jsdoc.opts.set(["one", "two"]); + expect(returnedValue._).to(eql, ["one", "two"]); + }); + }); + }); + +})(); diff --git a/test/tests/02_jsdoc_src.js b/test/tests/02_jsdoc_src.js new file mode 100644 index 00000000..6f790b19 --- /dev/null +++ b/test/tests/02_jsdoc_src.js @@ -0,0 +1,21 @@ +(function() { + var jsdoc; + + JSpec.describe('jsdoc/src.js', function() { + + before_each(function() { + jsdoc = { src: require('jsdoc/src') }; + }); + + describe('The object exported by the jsdoc/src module', function() { + it('should be an object', function() { + expect(jsdoc.src).to(be_an, Object); + }); + + it('should have a `getFilePaths` method', function() { + expect(jsdoc.src).to(respond_to, 'getFilePaths'); + }); + }); + }); + +})(); diff --git a/tests/docset.js b/tests/docset.js deleted file mode 100644 index 5aa4516b..00000000 --- a/tests/docset.js +++ /dev/null @@ -1,77 +0,0 @@ -(function() { - var jsdoc = { parser: require('jsdoc/parser') }; - - jsdoc.parser.parseFiles(BASEDIR + 'tests/docset.js'); - var docset = jsdoc.parser.result; - - var testSuite = { - suiteName: 'docset', - - setUp: function() { - }, - - tearDown: function() { - }, - - testDocsetGetMethodDocsByPath: function() { - var docs = docset.getDocsByPath('Shape'); - - assertEqual(docs.length, 1, 'All constructor doclets by that path name are found.'); - assertEqual(docs[0].tagText('isa'), 'constructor', 'The found constructor doclet has the correct isa.'); - assertEqual(docs[0].tagText('name'), 'Shape', 'The found constructor doclet has the correct name.'); - assertEqual(docs[0].tagText('memberof'), '', 'The found constructor doclet has the correct memberof.'); - - docs = docset.getDocsByPath('Shape#init'); - - assertEqual(docs.length, 1, 'All instance method doclets by that path name are found.'); - assertEqual(docs[0].tagText('isa'), 'method', 'The found instance method doclet has the correct isa.'); - assertEqual(docs[0].tagText('name'), 'init', 'The found instance method doclet has the correct name.'); - assertEqual(docs[0].tagText('memberof'), 'Shape#', 'The found instance method doclet has the correct memberof.'); - - - docs = docset.getDocsByPath('Shape.validate'); - - assertEqual(docs.length, 1, 'All static method doclets by that path name are found.'); - assertEqual(docs[0].tagText('isa'), 'method', 'The found static method doclet has the correct isa.'); - assertEqual(docs[0].tagText('name'), 'validate', 'The found static method doclet has the correct name.'); - assertEqual(docs[0].tagText('memberof'), 'Shape', 'The found static method doclet has the correct memberof.'); - }, - - testDocsetGetEventDocsByPath: function() { - var docs = docset.getDocsByPath('Shape#event:init'); - - assertEqual(docs.length, 1, 'All instance event doclets by that path name are found.'); - assertEqual(docs[0].tagText('isa'), 'event', 'The found instance event doclet has the correct isa.'); - assertEqual(docs[0].tagText('name'), 'init', 'The found instance event doclet has the correct name.'); - assertEqual(docs[0].tagText('memberof'), 'Shape#', 'The found instance event doclet has the correct memberof.'); - - docs = docset.getDocsByPath('Shape.event:validate'); - - assertEqual(docs.length, 1, 'All static event doclets by that path name are found.'); - assertEqual(docs[0].tagText('isa'), 'event', 'The found static event doclet has the correct isa.'); - assertEqual(docs[0].tagText('name'), 'validate', 'The static instance event doclet has the correct name.'); - assertEqual(docs[0].tagText('memberof'), 'Shape', 'The static instance event doclet has the correct memberof.'); - } - }; - - testSuites.push(testSuite); -})(); - -function sample() { - - /** @constructor */ - function Shape() { - } - - /** @method */ - Shape.validate = function(shape) {}; - - /** @event Shape.validate */ - addEvent(Shape, 'validate'); - - /** @method */ - Shape.prototype.init = function(opts) {}; - - /** @event Shape#event:init */ - addEvent(Shape.prototype, 'init'); -} diff --git a/tests/opts.js b/tests/opts.js deleted file mode 100644 index 964e156b..00000000 --- a/tests/opts.js +++ /dev/null @@ -1,35 +0,0 @@ -(function() { - var jsdoc = { opts: require('jsdoc/opts') }; - - var testSuite = { - suiteName: 'jsdoc/opts', - - setUp: function() { - }, - - tearDown: function() { - }, - - testOptsApi: function() { - assertEqual(typeof jsdoc.opts.set, 'function'); - }, - - testOptsSetDefault: function() { - var opts = jsdoc.opts.set(); - - assertEqual(typeof opts, 'object'); - assertEqual(typeof opts.destination, 'string'); - assertEqual(opts.destination, 'jsdoc.xml'); - }, - - testOptsSet: function() { - var opts = jsdoc.opts.set(['-d', 'mydestination.json']); - - assertEqual(typeof opts, 'object'); - assertEqual(typeof opts.destination, 'string'); - assertEqual(opts.destination, 'mydestination.json'); - } - }; - - testSuites.push(testSuite); -})(); \ No newline at end of file diff --git a/tests/tag_const.js b/tests/tag_const.js deleted file mode 100644 index 29434136..00000000 --- a/tests/tag_const.js +++ /dev/null @@ -1,78 +0,0 @@ -(function() { - var jsdoc = { parser: require('jsdoc/parser') }; - - jsdoc.parser.parseFiles(BASEDIR + 'tests/tag_const.js'); - var docset = jsdoc.parser.result; - - var testSuite = { - suiteName: 'tag_const', - - setUp: function() { - }, - - tearDown: function() { - }, - - testConstDocs: function() { - assertEqual(typeof docset, 'object'); - }, - - testConstCompactTag: function() { - var docs = docset.getDocsByPath('pi'); - assertEqual(docs.length, 1, '1 doclet by that name is found.'); - - var doc = docs[0].toObject(); - - assertEqual(typeof doc, 'object', 'The found doclet is an object.'); - assertEqual(doc.path, 'pi', 'The found doclet has the expected path.'); - assertEqual(doc.type, 'number', 'The found doclet has the expected type.'); - assertEqual(doc.desc, "The ratio of any circle's circumference to its diameter.", 'The found doclet has the expected desc.'); - }, - - testConstCompactVerbose: function() { - var doc = docset.getDocsByPath('e'); - assertEqual(doc.length, 1, '1 doclet by that name is found.'); - - doc = doc[0]; - - assertEqual(typeof doc, 'object', 'The found doclet is an object.'); - assertEqual(doc.tagText('path'), 'e', 'The found doclet has the expected path.'); - assertEqual(doc.tagText('type'), 'number', 'The found doclet has the expected type.'); - assertEqual(doc.tagText('desc'), "Euler's number.", 'The found doclet has the expected desc.'); - }, - - testConstCodename: function() { - var doc = docset.getDocsByPath('c'); - assertEqual(doc.length, 1, '1 doclet by that name is found.'); - - doc = doc[0]; - - assertEqual(typeof doc, 'object', 'The found doclet is an object.'); - assertEqual(doc.tagText('path'), 'c', 'The found doclet has the expected path.'); - assertEqual(doc.tagText('type'), 'number', 'The found doclet has the expected type.'); - assertEqual(doc.tagText('desc'), "Speed of light(m/s)", 'The found doclet has the expected desc.'); - } - }; - - testSuites.push(testSuite); -})(); - -function sample() { - - /** - * @const {number} pi The ratio of any circle's circumference to its diameter. - */ - - /** - * Euler's number. - * @const {number} e - */ - - /** - * Speed of light(m/s) - * @const {number} - * - */ - var c = 299792458; // <- name will be found here - -} \ No newline at end of file diff --git a/tests/tag_constructor.js b/tests/tag_constructor.js deleted file mode 100644 index bc4152b8..00000000 --- a/tests/tag_constructor.js +++ /dev/null @@ -1,113 +0,0 @@ -(function() { - var jsdoc = { parser: require('jsdoc/parser') }; - - jsdoc.parser.parseFiles(BASEDIR + 'tests/tag_constructor.js'); - var docset = jsdoc.parser.result; - - var testSuite = { - suiteName: 'tag_constructor', - - setUp: function() { - }, - - tearDown: function() { - }, - - testConstructorDocs: function() { - assertEqual(typeof docset, 'object'); - }, - - testConstructorCompactTag: function() { - var doc = docset.getDocsByPath('Triangle'); - assertEqual(doc.length, 1, '1 doclet by that name is found.'); - - doc = doc[0]; - - assertEqual(typeof doc, 'object', 'The found doclet is an object.'); - assertEqual(doc.tagText('name'), 'Triangle', 'The found doclet has the expected name.'); - assertEqual(doc.tagText('path'), 'Triangle', 'The found doclet has the expected path.'); - assertEqual(doc.tagText('isa'), 'constructor', 'The found doclet has the expected isa.'); - assertEqual(doc.tagText('desc'), 'A three-sided polygon.', 'The found doclet has the expected desc.'); - }, - - testConstructorFromCode: function() { - var doc = docset.getDocsByPath('shapes.Quadrilateral'); - assertEqual(doc.length, 1, '1 doclet by that name is found.'); - - doc = doc[0]; - - assertEqual(typeof doc, 'object', 'The found doclet is an object.'); - assertEqual(doc.tagText('path'), 'shapes.Quadrilateral', 'The found doclet has the expected path.'); - assertEqual(doc.tagText('name'), 'Quadrilateral', 'The found doclet has the expected name.'); - assertEqual(doc.tagText('memberof'), 'shapes', 'The found doclet has the expected memberof.'); - assertEqual(doc.tagText('desc'), '', 'The found doclet has the expected desc.'); - }, - - testConstructorBeforeVar: function() { - var doc = docset.getDocsByPath('Polygon'); - assertEqual(doc.length, 1, '1 doclet by that name is found.'); - - doc = doc[0]; - - assertEqual(typeof doc, 'object', 'The found doclet is an object.'); - assertEqual(doc.tagText('path'), 'Polygon', 'The found doclet has the expected path.'); - assertEqual(doc.tagText('name'), 'Polygon', 'The found doclet has the expected name.'); - assertEqual(doc.tagText('memberof'), '', 'The found doclet has the expected memberof.'); - assertEqual(doc.tagText('desc'), 'Jsdoc is before the `var`.', 'The found doclet has the expected desc.'); - }, - - testConstructorNested: function() { - var doc = docset.getDocsByPath('Polygon#Rhombus'); - assertEqual(doc.length, 1, '1 doclet by that name is found.'); - - doc = doc[0]; - - assertEqual(typeof doc, 'object', 'The found doclet is an object.'); - assertEqual(doc.tagText('path'), 'Polygon#Rhombus', 'The found doclet has the expected path.'); - assertEqual(doc.tagText('name'), 'Rhombus', 'The found doclet has the expected name.'); - assertEqual(doc.tagText('memberof'), 'Polygon#', 'The found doclet has the expected memberof.'); - assertEqual(doc.tagText('isa'), 'constructor', 'The found doclet has the expected isa.'); - }, - - testConstructorInVarList: function() { - var doc = docset.getDocsByPath('Trapezoid'); - assertEqual(doc.length, 1, '1 doclet by that name is found.'); - - doc = doc[0]; - - assertEqual(typeof doc, 'object', 'The found doclet is an object.'); - } - }; - - testSuites.push(testSuite); -})(); - -function sample() { - - /**@constructor Triangle A three-sided polygon.*/ - /** - * A four-sided polygon having equal-length sides meeting at right angles. - * @constructor - * @name Square - */ - someIgnoredCode = function() {} - - /** @constructor */ - shapes.Quadrilateral = new Klass("shapes", "Quadrilateral"); - - /** - Jsdoc is before the `var`. - @constructor - */ - var Polygon = function() { - /** A nested constructor - @constructor - */ - this.Rhombus = function () {} - }, - /** - In a list of vars. - @constructor - */ - Trapezoid = function() {}; -} \ No newline at end of file diff --git a/tests/tag_enum.js b/tests/tag_enum.js deleted file mode 100644 index 06bca27e..00000000 --- a/tests/tag_enum.js +++ /dev/null @@ -1,89 +0,0 @@ -(function() { - var jsdoc = { parser: require('jsdoc/parser') }; - - jsdoc.parser.parseFiles(BASEDIR + 'tests/tag_enum.js'); - var docset = jsdoc.parser.result; - - var testSuite = { - suiteName: 'tag_enum', - - setUp: function() { - }, - - tearDown: function() { - }, - - testEnumDocs: function() { - assertEqual(typeof docset, 'object'); - }, - - testEnumCompactTag: function() { - var doc = docset.getDocsByPath('buttons'); - assertEqual(doc.length, 1, '1 doclet by that name is found.'); - - doc = doc[0]; - - assertEqual(typeof doc, 'object', 'The found doclet is an object.'); - assertEqual(doc.tagText('path'), 'buttons', 'The found doclet has the expected path.'); - assertEqual(doc.tagText('type'), 'string', 'The found doclet has the expected type.'); - assertEqual(doc.tagText('desc'), 'Text equivalents for editor buttons.', 'The found doclet has the expected desc.'); - }, - - testEnumCompactMembers: function() { - var doc = docset.getDocsByPath('replies'); - assertEqual(doc.length, 1, '1 doclet by that name replies is found.'); - - doc = docset.getDocsByPath('replies.YES'); - assertEqual(doc.length, 1, '1 doclet by that name YES is found.'); - - doc = doc[0]; - - assertEqual(doc.tagText('memberof'), 'replies', 'The found doclet is a member of the enum.'); - - doc = docset.getDocsByPath('replies.NO'); - assertEqual(doc.length, 1, '1 doclet by that name NO is found.'); - }, - - testEnumThis: function() { - var doc = docset.getDocsByPath('Chart#colors'); - assertEqual(doc.length, 1, '1 doclet by that name is found.'); - } - }; - - testSuites.push(testSuite); -})(); - -function sample() { - - /** @enum {string} buttons Text equivalents for editor buttons. */ - this['buttons'] = { BOLD: 'B', ITALIC: 'I', CLOSE: 'X' }; - - /** - Valid replies. - @enum - */ - var replies = { - /** A positive response. */ - YES: 1, - - /** A negative response. */ - NO: -1, - - /** An uncertain response */ - MAYBE: 0 - } - - /** @constructor */ - function Chart() { - /** - Valid colors. - @enum {string} - */ - this.colors = { - RED: '#F00', - BLUE: '#00F', - GREEN: '#0F0' - } - } - -} \ No newline at end of file diff --git a/tests/tag_example.js b/tests/tag_example.js deleted file mode 100644 index b36307d9..00000000 --- a/tests/tag_example.js +++ /dev/null @@ -1,47 +0,0 @@ -(function() { - var jsdoc = { parser: require('jsdoc/parser') }; - - jsdoc.parser.parseFiles(BASEDIR + 'tests/tag_example.js'); - var docset = jsdoc.parser.result; - - var testSuite = { - suiteName: 'tag_example', - - setUp: function() { - }, - - tearDown: function() { - }, - - testExample: function() { - var docs = docset.getDocsByPath('rotate'); - - assertEqual(docs.length, 1, 'All doclets by that path name are found.'); - - var doc = docs[0].toObject(), - examples = doc.example; - - assertEqual(typeof examples, 'object', 'The doclet has examples.'); - assertEqual(examples.length, 2, 'The doclet has the expected number of examples.'); - assertEqual(examples[0], ' var myShape = new Shape();\n rotate(myShape, 90, {0, 0});\n', 'The doclet has the expected text.'); - - assertEqual(examples[1], '{key: rotate(myShape, -45) } // thats not a type expression\n', 'The doclet has the expected text when braces are at the start.'); - - } - }; - - testSuites.push(testSuite); -})(); - -function sample() { - - /** - * @method - * @example - * var myShape = new Shape(); - * rotate(myShape, 90, {0, 0}); - * @example {key: rotate(myShape, -45) } // thats not a type expression - */ - function rotate(shape, deg, axis) { - } -} diff --git a/tests/tag_namespace.js b/tests/tag_namespace.js deleted file mode 100644 index ccd6ec78..00000000 --- a/tests/tag_namespace.js +++ /dev/null @@ -1,41 +0,0 @@ -(function() { - var jsdoc = { parser: require('jsdoc/parser') }; - - jsdoc.parser.parseFiles(BASEDIR + 'tests/tag_namespace.js'); - var docset = jsdoc.parser.result; - - var testSuite = { - suiteName: 'tag_namespace', - - setUp: function() { - }, - - tearDown: function() { - }, - - testNsDocs: function() { - assertEqual(typeof docset, 'object'); - }, - - testNsCompactTag: function() { - var doc = docset.getDocsByPath('polygons'); - assertEqual(doc.length, 1, '1 doclet by that name is found.'); - }, - - testNsNested: function() { - var doc = docset.getDocsByPath('polygons.quadrilaterals'); - assertEqual(doc.length, 1, '1 doclet by that name is found.'); - } - }; - - testSuites.push(testSuite); -})(); - -function sample() { - - /** @namespace polygons Closed figure made by joining line segments. */ - this['polygons'] = {}; - - /** @namespace */ - polygons.quadrilaterals = {}; -} \ No newline at end of file diff --git a/tests/tag_param.js b/tests/tag_param.js deleted file mode 100644 index 4baa65d0..00000000 --- a/tests/tag_param.js +++ /dev/null @@ -1,131 +0,0 @@ -(function() { - var jsdoc = { parser: require('jsdoc/parser') }; - - jsdoc.parser.parseFiles(BASEDIR + 'tests/tag_param.js'); - var docset = jsdoc.parser.result; - - var testSuite = { - suiteName: 'tag_param', - - setUp: function() { - }, - - tearDown: function() { - }, - - testParamWithSimpleType: function() { - var docs = docset.getDocsByPath('Shape'); - - assertEqual(docs.length, 1, 'All constructor doclets by that path name are found.'); - - var doc = docs[0].toObject(), - params = doc.param; -//print('>>> doc is '+doc.toSource()); -//print('>>> params is '+params.toSource()); - assertEqual(params[0].name, 'top', 'The found parameter has the correct name.'); - assertEqual(typeof params[0].type, 'object', 'The found parameter has types.'); - assertEqual(params[0].type.length, 1, 'The found parameter has the correct number of types.'); - assertEqual(params[0].type[0], 'number', 'The found parameter has the correct type value.'); - - }, - - testParamWithNullableType: function() { - var docs = docset.getDocsByPath('Shape'); - - assertEqual(docs.length, 1, 'All constructor doclets by that path name are found.'); - - var doc = docs[0].toObject(), - params = doc.param; - - assertEqual(params[1].name, 'left', 'The found parameter has the correct name.'); - assertEqual(typeof params[1].type, 'object', 'The found parameter has types.'); - assertEqual(params[1].type.length, 1, 'The found parameter has the correct number of types.'); - assertEqual(params[1].type[0], 'number', 'The found parameter has the correct type value.'); - assertEqual(params[1].nullable, false, 'The found parameter has the correct !nullable value.'); - assertEqual(params[2].nullable, true, 'The found parameter has the correct ?nullable value.'); - }, - - testParamWithOptionalType: function() { - var docs = docset.getDocsByPath('Shape'); - - assertEqual(docs.length, 1, 'All doclets by that path name are found.'); - - var doc = docs[0].toObject(), - params = doc.param; - - assertEqual(params[3].name, 'fixed', 'The found parameter has the correct name.'); - assertEqual(typeof params[1].type, 'object', 'The found parameter has types.'); - assertEqual(params[3].type.length, 1, 'The found parameter has the correct number of types.'); - assertEqual(params[3].type[0], 'boolean', 'The found parameter has the correct type value.'); - assertEqual(params[3].nullable, undefined, 'The found parameter has the default nullable value.'); - assertEqual(params[3].optional, true, 'The found parameter has the correct optional value.'); - }, - - testParamWithMultipleType: function() { - var docs = docset.getDocsByPath('rotate'); - - assertEqual(docs.length, 1, 'All doclets by that path name are found.'); - - var doc = docs[0].toObject(), - params = doc.param; - - assertEqual(params[0].name, 'deg', 'The found parameter has the correct name.'); - assertEqual(typeof params[0].type, 'object', 'The found parameter has types.'); - assertEqual(params[0].type.length, 2, 'The found parameter has the correct number of types.'); - assertEqual(params[0].type[0], 'Degree', 'The found parameter has the correct type[0] value.'); - assertEqual(params[0].type[1], 'number', 'The found parameter has the correct type[1] value.'); - - assertEqual(params[1].name, 'axis', 'The found parameter has the correct name.'); - assertEqual(params[1].optional, true, 'The found parameter has the correct optional.'); - - }, - - testParamDesc: function() { - var docs = docset.getDocsByPath('label'); - - assertEqual(docs.length, 1, 'All doclets by that path name are found.'); - - var doc = docs[0].toObject(), - param = doc.param; - - assertEqual(typeof param, 'object', 'The found parameter has the expected type.'); - assertEqual(param.name, 'labelText', 'The found parameter has the correct name.'); - assertEqual(typeof param.type, 'object', 'The found parameter has types.'); - assertEqual(param.type.length, 2, 'The found parameter has the correct number of types.'); - assertEqual(param.type[0], 'Function', 'The found parameter has the correct type[0] value.'); - assertEqual(param.type[1], 'string', 'The found parameter has the correct type[1] value.'); - assertEqual(param.desc, 'A number\n or a function.', 'The found parameter has the expected description.'); - assertEqual(param.defaultvalue, '"hello world"', 'The found parameter has the expected defaultvalue.'); - } - }; - - testSuites.push(testSuite); -})(); - -function sample() { - - /** @constructor - @param {number} top - @param {!number} left - @param {?number} sides - @param {boolean=} fixed - */ - function Shape(top, left, sides, fixed) { - } - - /** @method - @param {Degree|number} deg - @param [axis] - */ - function rotate(deg, axis) { - - } - - /** @method - @param { Function | string } [ labelText = "hello world" ] A number - or a function. - */ - function label(labelText) { - - } -} diff --git a/tests/tag_returns.js b/tests/tag_returns.js deleted file mode 100644 index 4e4bb851..00000000 --- a/tests/tag_returns.js +++ /dev/null @@ -1,43 +0,0 @@ -(function() { - var jsdoc = { parser: require('jsdoc/parser') }; - - jsdoc.parser.parseFiles(BASEDIR + 'tests/tag_returns.js'); - var docset = jsdoc.parser.result; - - var testSuite = { - suiteName: 'tag_returns', - - setUp: function() { - }, - - tearDown: function() { - }, - - testExample: function() { - var docs = docset.getDocsByPath('data'); - - assertEqual(docs.length, 1, 'All doclets by that path name are found.'); - - var doc = docs[0].toObject(), - returns = doc.returns; - - assertEqual(typeof returns, 'object', 'The doclet has examples.'); - assertEqual(returns.length, 2, 'The doclet has the expected number of examples.'); - assertEqual(returns[0].text, 'blah blah', 'The tag has the expected text.'); - - assertEqual(returns[1].type, 'boolean', 'The tag has the expected type.'); - } - }; - - testSuites.push(testSuite); -})(); - -function sample() { - - /** - * @method - * @returns {boolean} - */ - function data(name, value) { - } -}