mirror of
https://github.com/jsdoc/jsdoc.git
synced 2025-12-08 19:46:11 +00:00
Plugin tests
Tests for the plugin framework as well as for the plugins shipping with JSDoc
This commit is contained in:
parent
034205baa8
commit
a6f68d838c
112
jsdoc.js
112
jsdoc.js
@ -34,7 +34,7 @@ load(__dirname + '/lib/rhino-shim.js');
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
|
||||
|
||||
/** Data representing the environment in which this app is running.
|
||||
@namespace
|
||||
*/
|
||||
@ -44,20 +44,20 @@ env = {
|
||||
start: new Date(),
|
||||
finish: null
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
The command line arguments passed into jsdoc.
|
||||
@type Array
|
||||
*/
|
||||
args: Array.prototype.slice.call(args, 0),
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
The parsed JSON data from the configuration file.
|
||||
@type Object
|
||||
*/
|
||||
conf: {},
|
||||
|
||||
|
||||
/**
|
||||
The command line arguments, parsed into a key/value hash.
|
||||
@type Object
|
||||
@ -79,12 +79,13 @@ app = {
|
||||
}
|
||||
|
||||
try { main(); }
|
||||
catch(e) {
|
||||
if (e.rhinoException != null) {
|
||||
catch(e) {
|
||||
if (e.rhinoException != null) {
|
||||
e.rhinoException.printStackTrace();
|
||||
}
|
||||
else throw e;
|
||||
}
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
finally { env.run.finish = new Date(); }
|
||||
|
||||
/** Print string/s out to the console.
|
||||
@ -119,7 +120,7 @@ function include(filepath) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
Cause the VM running jsdoc to exit running.
|
||||
@param {number} [n = 0] The exit status.
|
||||
*/
|
||||
@ -128,6 +129,33 @@ function exit(n) {
|
||||
java.lang.System.exit(n);
|
||||
}
|
||||
|
||||
function installPlugins(plugins, p) {
|
||||
var dictionary = require('jsdoc/tag/dictionary'),
|
||||
parser = p || app.jsdoc.parser;
|
||||
|
||||
// allow user-defined plugins to...
|
||||
for (var i = 0, leni = plugins.length; i < leni; i++) {
|
||||
var plugin = require(plugins[i]);
|
||||
|
||||
//...register event handlers
|
||||
if (plugin.handlers) {
|
||||
for (var eventName in plugin.handlers) {
|
||||
parser.on(eventName, plugin.handlers[eventName]);
|
||||
}
|
||||
}
|
||||
|
||||
//...define tags
|
||||
if (plugin.defineTags) {
|
||||
plugin.defineTags(dictionary);
|
||||
}
|
||||
|
||||
//...add a node visitor
|
||||
if (plugin.nodeVisitor) {
|
||||
parser.addNodeVisitor(plugin.nodeVisitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
|
||||
@ -144,11 +172,10 @@ function main() {
|
||||
}
|
||||
},
|
||||
resolver,
|
||||
dictionary = require('jsdoc/tag/dictionary'),
|
||||
fs = require('fs');
|
||||
|
||||
|
||||
env.opts = jsdoc.opts.parser.parse(env.args);
|
||||
|
||||
|
||||
try {
|
||||
env.conf = JSON.parse(
|
||||
fs.readFileSync( env.opts.configure || __dirname + '/conf.json' )
|
||||
@ -162,10 +189,10 @@ function main() {
|
||||
env.conf = JSON.parse(example);
|
||||
}
|
||||
catch(e) {
|
||||
throw('Configuration file cannot be evaluated. ' + e);
|
||||
throw('Configuration file cannot be evaluated. ' + e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// allow to pass arguments from configuration file
|
||||
if (env.conf.opts) {
|
||||
for (var opt in env.conf.opts) {
|
||||
@ -179,47 +206,26 @@ function main() {
|
||||
env.opts._ = env.conf.opts._.concat( env.opts._ );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (env.opts.query) {
|
||||
env.opts.query = require('common/query').toObject(env.opts.query);
|
||||
}
|
||||
|
||||
|
||||
// which version of javascript will be supported? (rhino only)
|
||||
if (typeof version === 'function') {
|
||||
version(env.conf.jsVersion || 180);
|
||||
}
|
||||
|
||||
|
||||
if (env.opts.help) {
|
||||
console.log( jsdoc.opts.parser.help() );
|
||||
exit(0);
|
||||
}
|
||||
else if (env.opts.test) {
|
||||
} else if (env.opts.test) {
|
||||
include('test/runner.js');
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// allow user-defined plugins to...
|
||||
|
||||
if (env.conf.plugins) {
|
||||
for (var i = 0, leni = env.conf.plugins.length; i < leni; i++) {
|
||||
var plugin = require(env.conf.plugins[i]);
|
||||
|
||||
//...register event handlers
|
||||
if (plugin.handlers) {
|
||||
for (var eventName in plugin.handlers) {
|
||||
app.jsdoc.parser.on(eventName, plugin.handlers[eventName]);
|
||||
}
|
||||
}
|
||||
|
||||
//...define tags
|
||||
if (plugin.defineTags) {
|
||||
plugin.defineTags(dictionary);
|
||||
}
|
||||
|
||||
//...add a node visitor
|
||||
if (plugin.nodeVisitor) {
|
||||
app.jsdoc.parser.addNodeVisitor(plugin.nodeVisitor);
|
||||
}
|
||||
}
|
||||
installPlugins(env.conf.plugins);
|
||||
}
|
||||
|
||||
// any source file named package.json is treated special
|
||||
@ -231,25 +237,25 @@ function main() {
|
||||
}
|
||||
|
||||
if (env.opts._.length > 0) { // are there any files to scan and parse?
|
||||
|
||||
|
||||
var includeMatch = (env.conf.source && env.conf.source.includePattern)? new RegExp(env.conf.source.includePattern) : null,
|
||||
excludeMatch = (env.conf.source && env.conf.source.excludePattern)? new RegExp(env.conf.source.excludePattern) : null;
|
||||
|
||||
|
||||
sourceFiles = app.jsdoc.scanner.scan(env.opts._, (env.opts.recurse? 10 : undefined), includeMatch, excludeMatch);
|
||||
|
||||
require('jsdoc/src/handlers').attachTo(app.jsdoc.parser);
|
||||
|
||||
|
||||
docs = app.jsdoc.parser.parse(sourceFiles, env.opts.encoding);
|
||||
|
||||
|
||||
//The files are ALWAYS useful for the templates to have
|
||||
//If there is no package.json, just create an empty package
|
||||
var packageDocs = new (require('jsdoc/package').Package)(packageJson);
|
||||
packageDocs.files = sourceFiles || [];
|
||||
docs.push(packageDocs);
|
||||
|
||||
|
||||
function indexAll(docs) {
|
||||
var lookupTable = {};
|
||||
|
||||
|
||||
docs.forEach(function(doc) {
|
||||
if ( !lookupTable.hasOwnProperty(doc.longname) ) {
|
||||
lookupTable[doc.longname] = [];
|
||||
@ -258,12 +264,12 @@ function main() {
|
||||
});
|
||||
docs.index = lookupTable;
|
||||
}
|
||||
|
||||
|
||||
indexAll(docs);
|
||||
|
||||
|
||||
require('jsdoc/augment').addInherited(docs);
|
||||
require('jsdoc/borrow').resolveBorrows(docs);
|
||||
|
||||
|
||||
if (env.opts.explain) {
|
||||
console.log(docs);
|
||||
exit(0);
|
||||
@ -279,7 +285,7 @@ function main() {
|
||||
}
|
||||
|
||||
env.opts.template = env.opts.template || 'templates/default';
|
||||
|
||||
|
||||
// should define a global "publish" function
|
||||
include(env.opts.template + '/publish.js');
|
||||
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
/**
|
||||
@overview Demonstrate how to modify the source code before the parser sees it.
|
||||
@module plugins/comentConvert
|
||||
@module plugins/commentConvert
|
||||
@author Michael Mathews <micmath@gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
|
||||
exports.handlers = {
|
||||
///
|
||||
/// Convert ///-style comments into jsdoc comments.
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
exports.handlers = {
|
||||
/**
|
||||
Translate HTML tags in descriptions into safe entities.
|
||||
Replaces <, & and newlines
|
||||
*/
|
||||
newDoclet: function(e) {
|
||||
if (e.doclet.description) {
|
||||
|
||||
@ -6,12 +6,12 @@
|
||||
|
||||
|
||||
exports.handlers = {
|
||||
///
|
||||
/// Remove rails tags from the source input (e.g. <% foo bar %>)
|
||||
/// @param e
|
||||
/// @param e.filename
|
||||
/// @param e.source
|
||||
///
|
||||
/**
|
||||
* Remove rails tags from the source input (e.g. <% foo bar %>)
|
||||
* @param e
|
||||
* @param e.filename
|
||||
* @param e.source
|
||||
*/
|
||||
beforeParse: function(e) {
|
||||
if (e.filename.match(/\.erb$/)) {
|
||||
e.source = e.source.replace(/<%.*%>/g, "");
|
||||
|
||||
@ -8,35 +8,36 @@ exports.handlers = {
|
||||
Support @source tag. Expected value like:
|
||||
{ "filename": "myfile.js", "lineno": 123 }
|
||||
Modifies the corresponding meta values on the given doclet.
|
||||
@source { "filename": "sourcetag.js", "lineno": 13 }
|
||||
*/
|
||||
newDoclet: function(e) {
|
||||
var tags = e.doclet.tags,
|
||||
tag,
|
||||
value;
|
||||
|
||||
|
||||
//console.log(e.doclet);
|
||||
// any user-defined tags in this doclet?
|
||||
// any user-defined tags in this doclet?
|
||||
if (typeof tags !== 'undefined') {
|
||||
// only interested in the @source tags
|
||||
tags = tags.filter(function($) {
|
||||
return $.title === 'source';
|
||||
});
|
||||
|
||||
|
||||
if (tags.length) {
|
||||
// take the first one
|
||||
tag = tags[0];
|
||||
|
||||
|
||||
try {
|
||||
value = JSON.parse(tag.value);
|
||||
}
|
||||
catch(e) {
|
||||
throw new Error('@source tag expects a valid JSON value, like { "filename": "myfile.js", "lineno": 123 }.');
|
||||
}
|
||||
|
||||
|
||||
!e.doclet.meta && (e.doclet.meta = {});
|
||||
e.doclet.meta.filename = value.filename || '';
|
||||
e.doclet.meta.lineno = value.lineno || '';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
20
plugins/test/fixtures/railsTemplate.js.erb
vendored
Normal file
20
plugins/test/fixtures/railsTemplate.js.erb
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
/**
|
||||
@overview Strips the rails template tags from a js.erb file
|
||||
@module plugins/railsTemplate
|
||||
@author Jannon Frank <jannon@jannon.net>
|
||||
*/
|
||||
|
||||
|
||||
exports.handlers = {
|
||||
/**
|
||||
* Remove rails tags from the source input (e.g. <% foo bar %>)
|
||||
* @param e
|
||||
* @param e.filename
|
||||
* @param e.source
|
||||
*/
|
||||
beforeParse: function(e) {
|
||||
if (e.filename.match(/\.erb$/)) {
|
||||
e.source = e.source.replace(/<%.*%> /g, "");
|
||||
}
|
||||
}
|
||||
};
|
||||
13
plugins/test/specs/commentConvert.js
Normal file
13
plugins/test/specs/commentConvert.js
Normal file
@ -0,0 +1,13 @@
|
||||
describe("commentConvert plugin", function() {
|
||||
var parser = new (require("jsdoc/src/parser")).Parser(),
|
||||
plugin = require('plugins/commentConvert'),
|
||||
docSet;
|
||||
|
||||
installPlugins(['plugins/commentConvert'], parser);
|
||||
docSet = jasmine.getDocSetFromFile("plugins/commentConvert.js", parser);
|
||||
|
||||
it("should convert '///-style comments into jsdoc comments", function() {
|
||||
var doclet = docSet.getByLongname("module:plugins/commentConvert.handlers.beforeParse");
|
||||
expect(doclet.length).toEqual(1);
|
||||
});
|
||||
});
|
||||
13
plugins/test/specs/escapeHtml.js
Normal file
13
plugins/test/specs/escapeHtml.js
Normal file
@ -0,0 +1,13 @@
|
||||
describe("escapeHtml plugin", function() {
|
||||
var parser = new (require("jsdoc/src/parser")).Parser(),
|
||||
plugin = require('plugins/escapeHtml'),
|
||||
docSet;
|
||||
|
||||
installPlugins(['plugins/escapeHtml'], parser);
|
||||
docSet = jasmine.getDocSetFromFile("plugins/escapeHtml.js", parser);
|
||||
|
||||
it("should escape '&', '<' and newlines in doclet descriptions", function() {
|
||||
var doclet = docSet.getByLongname("module:plugins/escapeHtml.handlers.newDoclet");
|
||||
expect(doclet[0].description).toEqual("Translate HTML tags in descriptions into safe entities.<br> Replaces <, & and newlines");
|
||||
});
|
||||
});
|
||||
22
plugins/test/specs/markdown.js
Normal file
22
plugins/test/specs/markdown.js
Normal file
@ -0,0 +1,22 @@
|
||||
/**
|
||||
@overview Translate doclet descriptions from MarkDown into HTML.
|
||||
@module plugins/markdown
|
||||
@author Michael Mathews <micmath@gmail.com>
|
||||
*/
|
||||
|
||||
var mdParser = require('evilstreak/markdown');
|
||||
|
||||
exports.handlers = {
|
||||
/**
|
||||
Translate markdown syntax in a new doclet's description into HTML. Is run
|
||||
by JSDoc 3 whenever a "newDoclet" event fires.
|
||||
*/
|
||||
newDoclet: function(e) {
|
||||
if (e.doclet.description) {
|
||||
e.doclet.description = mdParser.toHTML(e.doclet.description)
|
||||
.replace( /&/g, "&" ) // because markdown escapes these
|
||||
.replace( /</g, "<" )
|
||||
.replace( />/g, ">" );
|
||||
}
|
||||
}
|
||||
};
|
||||
15
plugins/test/specs/railsTemplate.js
Normal file
15
plugins/test/specs/railsTemplate.js
Normal file
@ -0,0 +1,15 @@
|
||||
describe("railsTemplate plugin", function() {
|
||||
var parser = new (require("jsdoc/src/parser")).Parser(),
|
||||
plugin = require('plugins/railsTemplate');
|
||||
|
||||
|
||||
installPlugins(['plugins/railsTemplate'], parser);
|
||||
require('jsdoc/src/handlers').attachTo(parser);
|
||||
|
||||
it("should remove <% %> rails template tags from the source of *.erb files", function() {
|
||||
var path = require("path"),
|
||||
docSet = parser.parse([path.join(__dirname, "plugins/test/fixtures/railsTemplate.js.erb")]);
|
||||
|
||||
expect(docSet[2].description).toEqual("Remove rails tags from the source input (e.g. )");
|
||||
});
|
||||
});
|
||||
13
plugins/test/specs/shout.js
Normal file
13
plugins/test/specs/shout.js
Normal file
@ -0,0 +1,13 @@
|
||||
describe("shout plugin", function() {
|
||||
var parser = new (require("jsdoc/src/parser")).Parser(),
|
||||
plugin = require('plugins/shout'),
|
||||
docSet;
|
||||
|
||||
installPlugins(['plugins/shout'], parser);
|
||||
docSet = jasmine.getDocSetFromFile("plugins/shout.js", parser);
|
||||
|
||||
it("should make the description uppercase", function() {
|
||||
var doclet = docSet.getByLongname("module:plugins/shout.handlers.newDoclet");
|
||||
expect(doclet[0].description).toEqual("MAKE YOUR DESCRIPTIONS MORE SHOUTIER.");
|
||||
});
|
||||
});
|
||||
15
plugins/test/specs/sourcetag.js
Normal file
15
plugins/test/specs/sourcetag.js
Normal file
@ -0,0 +1,15 @@
|
||||
describe("sourcetag plugin", function() {
|
||||
var parser = new (require("jsdoc/src/parser")).Parser(),
|
||||
plugin = require('plugins/sourcetag'),
|
||||
docSet;
|
||||
|
||||
installPlugins(['plugins/sourcetag'], parser);
|
||||
docSet = jasmine.getDocSetFromFile("plugins/sourcetag.js", parser);
|
||||
|
||||
it("should set the lineno and filename of the doclet's meta property", function() {
|
||||
var doclet = docSet.getByLongname("module:plugins/sourcetag.handlers.newDoclet");
|
||||
expect(doclet[0].meta).toBeDefined();
|
||||
expect(doclet[0].meta.filename).toEqual("sourcetag.js");
|
||||
expect(doclet[0].meta.lineno).toEqual(13);
|
||||
});
|
||||
});
|
||||
10
test/fixtures/plugins.js
vendored
Normal file
10
test/fixtures/plugins.js
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
/**
|
||||
* @name virtual
|
||||
*/
|
||||
|
||||
var foo = "bar";
|
||||
|
||||
/**
|
||||
* @foo bar
|
||||
*/
|
||||
var test = "tada";
|
||||
23
test/fixtures/testPlugin1.js
vendored
Normal file
23
test/fixtures/testPlugin1.js
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
exports.handlers = {
|
||||
fileBegin: jasmine.createSpy('fileBegin'),
|
||||
beforeParse: jasmine.createSpy('beforeParse'),
|
||||
jsdocCommentFound: jasmine.createSpy('jsdocCommentFound'),
|
||||
symbolFound: jasmine.createSpy('symbolFound'),
|
||||
newDoclet: jasmine.createSpy('newDoclet'),
|
||||
fileComplete: jasmine.createSpy('fileComplete')
|
||||
};
|
||||
|
||||
exports.defineTags = function(dictionary) {
|
||||
dictionary.defineTag("foo", {
|
||||
canHaveName: true,
|
||||
onTagged: function(doclet, tag) {
|
||||
doclet.foo = true;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
exports.nodeVisitor = {
|
||||
visitNode: jasmine.createSpy("plugin 1 visitNode").andCallFake(function(node, e, parser, currentSourceName) {
|
||||
e.stopPropagation = true;
|
||||
})
|
||||
};
|
||||
12
test/fixtures/testPlugin2.js
vendored
Normal file
12
test/fixtures/testPlugin2.js
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
exports.handlers = {
|
||||
fileBegin: jasmine.createSpy('fileBegin'),
|
||||
beforeParse: jasmine.createSpy('beforeParse'),
|
||||
jsdocCommentFound: jasmine.createSpy('jsdocCommentFound'),
|
||||
symbolFound: jasmine.createSpy('symbolFound'),
|
||||
newDoclet: jasmine.createSpy('newDoclet'),
|
||||
fileComplete: jasmine.createSpy('fileComplete')
|
||||
};
|
||||
|
||||
exports.nodeVisitor = {
|
||||
visitNode: jasmine.createSpy("plugin 2 visitNode")
|
||||
};
|
||||
@ -1,9 +1,8 @@
|
||||
exports.getDocSetFromFile = function(filename) {
|
||||
exports.getDocSetFromFile = function(filename, parser) {
|
||||
var sourceCode = readFile(__dirname + '/' + filename),
|
||||
testParser,
|
||||
testParser = parser || new (require('jsdoc/src/parser')).Parser(),
|
||||
doclets;
|
||||
|
||||
testParser = new (require('jsdoc/src/parser')).Parser();
|
||||
require('jsdoc/src/handlers').attachTo(testParser);
|
||||
|
||||
doclets = testParser.parse('javascript:' + sourceCode);
|
||||
|
||||
40
test/specs/jsdoc/plugins.js
Normal file
40
test/specs/jsdoc/plugins.js
Normal file
@ -0,0 +1,40 @@
|
||||
describe("plugins", function() {
|
||||
installPlugins(['test/fixtures/testPlugin1', 'test/fixtures/testPlugin2']);
|
||||
|
||||
var plugin1 = require('test/fixtures/testPlugin1'),
|
||||
plugin2 = require('test/fixtures/testPlugin2'),
|
||||
docSet;
|
||||
|
||||
docSet = jasmine.getDocSetFromFile("test/fixtures/plugins.js", app.jsdoc.parser);
|
||||
|
||||
it("should fire the plugin's event handlers", function() {
|
||||
expect(plugin1.handlers.fileBegin).toHaveBeenCalled();
|
||||
expect(plugin1.handlers.beforeParse).toHaveBeenCalled();
|
||||
expect(plugin1.handlers.jsdocCommentFound).toHaveBeenCalled();
|
||||
expect(plugin1.handlers.symbolFound).toHaveBeenCalled();
|
||||
expect(plugin1.handlers.newDoclet).toHaveBeenCalled();
|
||||
expect(plugin1.handlers.fileComplete).toHaveBeenCalled();
|
||||
|
||||
expect(plugin2.handlers.fileBegin).toHaveBeenCalled();
|
||||
expect(plugin2.handlers.beforeParse).toHaveBeenCalled();
|
||||
expect(plugin2.handlers.jsdocCommentFound).toHaveBeenCalled();
|
||||
expect(plugin2.handlers.symbolFound).toHaveBeenCalled();
|
||||
expect(plugin2.handlers.newDoclet).toHaveBeenCalled();
|
||||
expect(plugin2.handlers.fileComplete).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should add the plugin's tag definitions to the dictionary", function() {
|
||||
var test = docSet.getByLongname("test");
|
||||
|
||||
expect(test[0].longname).toEqual("test");
|
||||
expect(test[0].foo).toEqual(true);
|
||||
});
|
||||
|
||||
it("should call the plugin's visitNode function", function() {
|
||||
expect(plugin1.nodeVisitor.visitNode).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should not call a second plugin's visitNode function if the first stopped propagation", function() {
|
||||
expect(plugin2.nodeVisitor.visitNode).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user