path = require 'path'
fs = require 'fs'
xfs = require 'fs-extra'
rimraf = require 'rimraf'
Docco = require '../docco'
path = require 'path'
fs = require 'fs'
xfs = require 'fs-extra'
rimraf = require 'rimraf'
Docco = require '../docco'Determine the test and resources paths
testPath = path.dirname fs.realpathSync(__filename)
dataPath = path.join testPath, "data"
resourcesPath = path.normalize path.join(testPath, "/resources")test runner
test = (msg, f) ->
console.log "\n===========================================\n", msg
f()a la jasmine: renamed test runnr which does nothing, i.e. is used for (temporarily) disabled tests:
xtest = (msg, f) ->
console.log "\n================SKIPPED===================\n", msg
returnassert function:
equal = (a, b, msg) ->
throw new Error("TEST FAILED: " + msg + " (" + a + " !== " + b + ")") if (a != b)
a == b
ensureDirectory = (dir, f) ->
xfs.mkdirsSync(dir)
f()Run a Docco pass, and check that the number of output files is equal to what is expected. We assume there is one CSS file that is always copied to the output, so we check that the number of output files is (matched_sources + 1).
testDoccoRun = (testName, sources, options=null, callback=null) ->
destPath = path.join dataPath, testNameRemove the data directory for this test run
cleanup = (callback) -> rimraf destPath, callback
cleanup (error) ->
equal not error, true, "path cleaned up properly"
options?.output = destPath
opts = options || {}
opts.args = sourcesconsole.log “going to run docco with options: “, opts
Docco.document opts, (error, info) ->Calculate the number of expected files in the output, and then the number of files actually found in the output path.
files = []
for src, i in sourcesconsole.log “check output for file: “, { index: i src: src }
files = files.concat(info.source_infos[i].destDocFile)
extra_files = 0
if options
if options.markdown
extra_files = 2
else if options.template
extra_files = 0
else if options.css
extra_files = 2
else
extra_files = 2
expected = files.length + extra_files
found = fs.readdirSync(destPath).lengthCheck the expected number of files against the number of files that were actually found.
equal found, expected, "find expected output (#{expected} files) - (#{found})"Trigger the completion callback if it’s specified
callback() if callback?Optional markdown output should be supported
test "markdown from docco", ->
testDoccoRun "markdown_output",
["#{testPath}/tests.coffee"],
markdown: trueCustom jst template files should be supported
test "custom JST template file", ->
testDoccoRun "custom_jst",
["#{testPath}/tests.coffee"],
template: "#{resourcesPath}/pagelet/docco.jst"Custom CSS files should be supported
test "custom CSS file", ->
testDoccoRun "custom_css",
["#{testPath}/tests.coffee"],
css: "#{resourcesPath}/pagelet/docco.css"Specifying a filetype independent of extension should be supported
test "specify an extension", ->
testDoccoRun "specify_extension",
["#{testPath}/comments/noextension"],
extension: ".coffee"Comments should be parsed properly
There are special data files located in test/comments for each supported
language. The first comment in each file corresponds to the expected number
of comments to be parsed from its contents.
This test iterates over all the known Docco languages, and tests the ones
that have a corresponding data file in test/comments.
test "single line and block comment parsing", ->
commentsPath = path.join testPath, "comments"
options =
template: "#{commentsPath}/comments.jst"
blocks : trueConstruct a list of languages to test asynchronously. It’s important
that these be tested one at a time, to avoid conflicts between multiple
file extensions for a language. e.g. c.c and c.h both output to
c.html, so they must be run at separate times.
languageKeys = (ext for ext,l of Docco.languages)
testNextLanguage = (keys,callback) ->
return callback?() if not keys.length
extension = keys.shift()
language = Docco.languages[extension]
languageExample = path.join commentsPath, "#{language.name}#{extension}"
languageTest = "comments_test/#{language.name}"
languagePath = path.join dataPath, languageTest
languageOutput = path.join languagePath, "#{language.name}.html"Skip over this language if there is no corresponding test
return testNextLanguage(keys, callback) if not path.existsSync languageExampleRun them through docco with the custom comments.jst file that
outputs a CSV list of doc blocks text.
testDoccoRun languageTest, [languageExample], options, ->Be sure the expected output file exists
equal true, path.existsSync(languageOutput), "#{languageOutput} -> output file created properly"Read in the output file contents, split them into a list of comments.
content = fs.readFileSync(languageOutput).toString()
comments = (c.trim() for c in content.split(',') when c.trim() != '')
equal true, comments.length >= 1, 'expect at least the descriptor comment'Parse the first comment (special case), to identify the expected comment counts, based on whether we’re matching block comments or not.
descriptor = comments[0].match(/^Single:([0-9]*) - Block:([0-9]*)$/)
if !descriptor
console.log "comment is malformed! ", comments
expected = parseInt(if l.blocks and options.blocks then descriptor[2] else descriptor[1])
equal comments.length, expected, [
""
"#{path.basename(languageOutput)} comments"
"------------------------"
" blocks : #{options.blocks}"
" expected : #{expected}"
" found : #{comments.length}"
].join '\n'Invoke the next test
testNextLanguage keys, callbackKick off the first language test
testNextLanguage languageKeys.slice(), ->Test to be sure block comments are excluded when not explicitly specified. In this case, the test will check for the existence of only 1 comment in all languages (a single-line)
options.blocks = false
testNextLanguage languageKeys.slice()test "url references (defined up front)", ->
ensureDirectory dataPath, ->
sourceFile = "#{dataPath}/_urlref.coffee"
fs.writeFileSync sourceFile, [
"# [google]: http://www.google.com",
"#",
"# Look at this link to [Google][]!",
"console.log 'This must be Thursday.'",
"# And this link to [Google][] as well.",
"console.log 'I never could get the hang of Thursdays.'"
].join('\n')
outPath = path.join dataPath, "_urlreferences1"
outFile = "#{outPath}/_urlref.html"
rimraf outPath, (error) ->
equal not error, true
Docco.document {
cwd: dataPath,
output: outPath,
args: [sourceFile]
}, ->
contents = fs.readFileSync(outFile).toString()
count = contents.match ///<a\shref="http://www.google.com">Google</a>///g
equal count?.length, 2, "find expected (2) resolved url references"
test "url references (defined at the end)", ->
ensureDirectory dataPath, ->
sourceFile = "#{dataPath}/_urlref.coffee"
fs.writeFileSync sourceFile, [
"# Look at this link to [Google][]!",
"console.log 'This must be Thursday.'",
"# And this link to [Google][] as well.",
"console.log 'I never could get the hang of Thursdays.'",
"# [google]: http://www.google.com"
].join('\n')
outPath = path.join dataPath, "_urlreferences2"
outFile = "#{outPath}/_urlref.html"
rimraf outPath, (error) ->
equal not error, true
Docco.document {
cwd: dataPath,
output: outPath,
args: [sourceFile]
}, ->
contents = fs.readFileSync(outFile).toString()
count = contents.match ///<a\shref="http://www.google.com">Google</a>///g
equal count?.length, 2, "find expected (2) resolved url references"Paths should be recursively created if needed
ensureDirectory should properly create complex output paths.
test "create complex paths that do not exist", ->
exist = fs.existsSync or path.existsSync
outputPath = path.join dataPath, 'complex/path/that/doesnt/exist'
rimraf outputPath, (error) ->
equal not error, true
ensureDirectory outputPath, ->
equal exist(outputPath), true, 'created output path: ' + outputPath
stat = fs.statSync outputPath
equal stat.isDirectory(), true, "target is directory"