diff --git a/.eslintignore b/.eslintignore index 89963b9..e9cf2e8 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,4 @@ node_modules coverage -test/fixtures \ No newline at end of file +test/fixtures +test-output \ No newline at end of file diff --git a/README.md b/README.md index 278c18b..a0a6a25 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,6 @@ [![NPM version](https://badge.fury.io/js/thought.svg)](http://badge.fury.io/js/thought) [![Travis Build Status](https://travis-ci.org/nknapp/thought.svg?branch=master)](https://travis-ci.org/nknapp/thought) [![Coverage Status](https://img.shields.io/coveralls/nknapp/thought.svg)](https://coveralls.io/r/nknapp/thought) -[![Greenkeeper badge](https://badges.greenkeeper.io/nknapp/thought.svg)](https://greenkeeper.io/) > A customizable documentation generator for github projects @@ -66,9 +65,8 @@ In the default configuration, this will generate a `README.md` from the informat Consider the following example
-
├── LICENSE.md
-├── examples
+├── examples/
├── index.js
└── package.json
@@ -164,11 +162,10 @@ You can find the default configuration in the [partials/](partials/) directory.
has the structure.
-
├── helpers.js
-├─┬ partials
+├─┬ partials/
│ ├── api.md.hbs
-│ ├─┬ badge
+│ ├─┬ badge/
│ │ ├── appveyor.md.hbs
│ │ ├── coveralls.md.hbs
│ │ ├── greenkeeper.md.hbs
@@ -183,7 +180,7 @@ has the structure.
│ ├── overview.md.hbs
│ └── usage.md.hbs
├── preprocessor.js
-└─┬ templates
+└─┬ templates/
├── CONTRIBUTING.md.hbs
└── README.md.hbs
@@ -229,30 +226,15 @@ as context data, but if you return promises, they will be resolved seamlessly.
-## API-reference
-
-
-
-## thought(options)
-Execute Thought in the current directory
-
-**Kind**: global function
-**Api**: public
-
-| Param | Type | Description |
-| --- | --- | --- |
-| options | object
| |
-| [options.cwd] | string
| the working directory to use as project root |
-| [options.addToGit] | boolean
| add created files to git |
-
-
## License
-`thought` is published under the MIT-license.
+`thought` is published under the MIT-license.
+
See [LICENSE.md](LICENSE.md) for details.
+
## Release-Notes
For release notes, see [CHANGELOG.md](CHANGELOG.md)
diff --git a/bin/thought.js b/bin/thought.js
index 1227609..06a2b56 100755
--- a/bin/thought.js
+++ b/bin/thought.js
@@ -37,16 +37,20 @@ program
changeDir()
var packageJson = findPackage()
if (!(packageJson.scripts && packageJson.scripts.thought)) {
+ /* eslint-disable no-console */
console.log('\nNot registered in package.json yet!\n' +
'I can add a `scripts`-property to your package.json to ensure that ' +
'documentation is generated automatically on version bumps.\n' +
'If you want that, run `thought init`\n')
+ /* eslint-enable no-console */
}
thought({
addToGit: options.addToGit,
debug: program.debug
}).done(function (filenames) {
+ /* eslint-disable no-console */
console.log('The following files were updated: ' + filenames.join(', '))
+ /* eslint-enable no-console */
})
})
@@ -58,7 +62,7 @@ program
require('../lib/check-engines.js')()
.then(require('../lib/init.js'))
.done(function () {
- console.log('OK')
+ console.log('OK') // eslint-disable-line no-console
})
})
@@ -68,7 +72,7 @@ program
.action(function () {
require('../lib/check-engines.js')()
.done(function () {
- console.log('OK')
+ console.log('OK') // eslint-disable-line no-console
})
})
@@ -78,7 +82,7 @@ program
.action(function () {
changeDir()
require('../lib/up-to-date.js')().done(function () {
- console.log('OK')
+ console.log('OK') // eslint-disable-line no-console
})
})
@@ -101,5 +105,6 @@ function changeDir () {
var moduleRoot = path.dirname(packageJson.paths.absolute)
process.chdir(moduleRoot)
+ // eslint-disable-next-line no-console
console.log("I'm running inside module '" + packageJson.name + "' in '" + moduleRoot)
}
diff --git a/examples/.eslintrc.js b/examples/.eslintrc.js
index 05c39c7..e3611dd 100644
--- a/examples/.eslintrc.js
+++ b/examples/.eslintrc.js
@@ -3,5 +3,8 @@ module.exports = {
"plugins": [
"standard",
"promise"
- ]
+ ],
+ "rules": {
+ "no-console": "off"
+ }
};
diff --git a/handlebars/helpers.js b/handlebars/helpers.js
index 67b1629..20971b2 100644
--- a/handlebars/helpers.js
+++ b/handlebars/helpers.js
@@ -1,9 +1,9 @@
-var fs = require('fs')
var path = require('path')
var cp = require('child_process')
var _ = require('lodash')
var debug = require('debug')('thought:helpers')
-var glob = require('glob')
+var Promise = require('bluebird')
+var glob = Promise.promisify(require('glob'))
var findPackage = require('find-package')
var Handlebars = require('handlebars')
var qfs = require('m-io/fs')
@@ -31,10 +31,10 @@ module.exports = {
include: function (filename, language) {
return qfs.read(filename).then(function (contents) {
return '```' +
- (_.isString(language) ? language : path.extname(filename).substr(1)) +
- '\n' +
- contents +
- '\n```\n'
+ (_.isString(language) ? language : path.extname(filename).substr(1)) +
+ '\n' +
+ contents +
+ '\n```\n'
})
},
@@ -71,9 +71,9 @@ module.exports = {
.then(function (contents) {
// Relative path to the current module (e.g. "../"). This path must be replaced
// by the module name in the
- var modulePath = path.relative(path.dirname(filename), '.') + '/'
+ var modulePath = path.relative(path.dirname(filename), '.')
debug('example modulepath', modulePath)
- var requireModuleRegex = new RegExp(`require\\('${_.escapeRegExp(modulePath)}(.*?)'\\)`, 'm')
+ var requireModuleRegex = new RegExp(regex`require\('${modulePath}/?(.*?)'\)`, 'g')
if (options && options.hash && options.hash.snippet) {
contents = contents.match(/---\n' + tree.trim() + '\n
'
})
- if (components.length === 0) {
- defer.reject("Cannot find a single file for '" + globPattern + "' in '" + baseDir + "'")
- return
- }
- var treeObject = treeFromPathComponents(components)
- var tree = require('archy')(treeObject)
- defer.fulfill('\n' + tree + '
')
- })
- return defer.promise
},
/**
- * Render an object hierarchy
+ * Render an object hierarchy of the form
+ *
+ * ```
+ * {
+ * prop1: 'value',
+ * prop2: 'value',
+ * ...,
+ * children: [
+ * {
+ * prop1: 'value',
+ * propt2: 'value',
+ * ...,
+ * children: ...
+ * }
+ * ]
+ * }
+ * ```
* @param object
* @param options
* @param {function} options.fn computes the label for a node based on the node itself
@@ -184,9 +204,7 @@ module.exports = {
* @param options block-helper options
*/
withPackageOf: function (filePath, options) {
- if (options.data) {
- var data = Handlebars.createFrame(options.data || {})
- }
+ const data = Handlebars.createFrame(options.data)
data.url = githubUrl(filePath)
data.package = findPackage(path.resolve(filePath), false)
return options.fn(this, {data: data})
@@ -200,7 +218,7 @@ module.exports = {
* Returns the path to the github repository (below github.com) based on the $.repository.url.
* @param options
* @returns {string=} the repository path within github.com (or null)
- */
+ */
githubRepo: githubRepo,
/**
@@ -341,7 +359,7 @@ function treeFromPathComponents (files, label) {
// Condense path if directory only has one entry
if (result.nodes.length === 1 && _.isPlainObject(result.nodes[0])) {
return {
- label: (result.label ? result.label + '/' : '') + result.nodes[0].label,
+ label: (result.label || '') + result.nodes[0].label,
nodes: result.nodes[0].nodes
}
} else {
@@ -362,9 +380,8 @@ function githubUrl (filePath) {
}
function githubRepo (options) {
- var url = null
try {
- url = options.data.root.package.repository.url
+ var url = options.data.root.package.repository.url
var match = url.match(/.*?(:\/\/|@)github\.com[/:](.*?)(#.*?)?$/)
if (match) {
return match[2].replace(/\.git$/, '')
@@ -372,7 +389,11 @@ function githubRepo (options) {
return null
}
} catch (e) {
- console.log('Cannot find repository url')
- url = null
+ // No repositor-url exists
+ return null
}
}
+
+function regex (strings, ...args) {
+ return String.raw(strings, ...args.map(_.escapeRegExp))
+}
diff --git a/lib/check-engines.js b/lib/check-engines.js
index 87518fc..526a4a6 100644
--- a/lib/check-engines.js
+++ b/lib/check-engines.js
@@ -14,6 +14,7 @@ module.exports = function () {
throw new Error('npm<2.13.0 will not execute the `version`-script in your package.json.\n' +
'Please upgrade to at least 2.13.0.')
} else {
+ // eslint-disable-next-line no-console
console.log('npm@' + stdout.trim() + ': OK')
}
})
diff --git a/lib/dev-server.js b/lib/dev-server.js
index 8ceed18..4284cdd 100644
--- a/lib/dev-server.js
+++ b/lib/dev-server.js
@@ -5,6 +5,7 @@ var thought = customize().load(require('../customize.js')('.'))
function handleMessage (message) {
switch (message.cmd) {
case 'run': {
+ // eslint-disable-next-line no-console
console.log('Running thought')
return thought.run()
}
@@ -16,7 +17,6 @@ process.on('message', (message) => {
.then((result) => {
process.send({ message: message, result: result })
}, (err) => {
- console.error('error', err)
process.send({ error: err })
})
})
diff --git a/lib/init.js b/lib/init.js
index 60d96a1..e1f4751 100644
--- a/lib/init.js
+++ b/lib/init.js
@@ -46,6 +46,7 @@ module.exports = function () {
})
.spread(function (stderr, stdout) {
debug('git commit package.json...', 'stdout', stdout, 'stderr', stderr)
+ // eslint-disable-next-line no-console
console.log('\nI have committed a new package.json. Please verify the changes made to the file!')
})
}
diff --git a/package.json b/package.json
index 9b661e8..ea1b164 100644
--- a/package.json
+++ b/package.json
@@ -32,6 +32,7 @@
},
"dependencies": {
"archy": "^1.0.0",
+ "bluebird": "^3.5.0",
"cheerio": "^0.22.0",
"commander": "^2.8.1",
"customize": "^1.0.0",
@@ -49,7 +50,6 @@
"trace-and-clarify-if-possible": "^1.0.0"
},
"devDependencies": {
- "bluebird": "^3.5.0",
"chai": "^3.2.0",
"chai-as-promised": "^5.1.0",
"customize-engine-handlebars": "^2.0.0-alpha.0",
diff --git a/test/dev-server-spec.js b/test/dev-server-spec.js
index e48aa99..80cf79a 100644
--- a/test/dev-server-spec.js
+++ b/test/dev-server-spec.js
@@ -36,9 +36,9 @@ xdescribe('the thought dev-server', function () {
'result': {
'handlebars': {
'CONTRIBUTING.md': fs.readFileSync('test/fixtures/scenarios/simple-project/expected/CONTRIBUTING.md',
- { encoding: 'utf-8'}),
+ {encoding: 'utf-8'}),
'README.md': fs.readFileSync('test/fixtures/scenarios/simple-project/expected/README.md',
- { encoding: 'utf-8'})
+ {encoding: 'utf-8'})
}
}
})
diff --git a/test/fixtures/dir-tree.output.complex.filter.txt b/test/fixtures/dir-tree.output.complex.filter.txt
index 8753eae..7379c1d 100644
--- a/test/fixtures/dir-tree.output.complex.filter.txt
+++ b/test/fixtures/dir-tree.output.complex.filter.txt
@@ -1,7 +1,8 @@
-dir-tree/
-├── subdirA/
-│ ├── bDir/
-│ └── cFile.txt
-└── subdirB/
- ├── bFile.md
- └── subdirC/
\ No newline at end of file
+
+├─┬ subdirA/
+│ ├── bDir/
+│ └── cFile.txt
+└─┬ subdirB/
+ ├── bFile.md
+ └── subdirC/
+
\ No newline at end of file
diff --git a/test/fixtures/dir-tree.output.condensed.txt b/test/fixtures/dir-tree.output.condensed.txt
new file mode 100644
index 0000000..2314ecc
--- /dev/null
+++ b/test/fixtures/dir-tree.output.condensed.txt
@@ -0,0 +1,8 @@
+
+├─┬ subdirA/
+│ ├── aFile.txt
+│ └─┬ bDir/
+│ └── aFile.txt
+└─┬ subdirB/subdirC/
+ └── aFile.txt
+
\ No newline at end of file
diff --git a/test/fixtures/dir-tree.output.filtered.txt b/test/fixtures/dir-tree.output.filtered.txt
index 0f37672..37e51a2 100644
--- a/test/fixtures/dir-tree.output.filtered.txt
+++ b/test/fixtures/dir-tree.output.filtered.txt
@@ -1,7 +1,8 @@
-dir-tree/
-└── subdirA/
- ├── aFile.txt
- ├── bDir/
- │ ├── aFile.txt
- │ └── bFile.txt
- └── cFile.txt
\ No newline at end of file
+
+subdirA/
+├── aFile.txt
+├─┬ bDir/
+│ ├── aFile.txt
+│ └── bFile.txt
+└── cFile.txt
+
\ No newline at end of file
diff --git a/test/fixtures/dir-tree.output.txt b/test/fixtures/dir-tree.output.txt
index 59af554..779c712 100644
--- a/test/fixtures/dir-tree.output.txt
+++ b/test/fixtures/dir-tree.output.txt
@@ -1,12 +1,13 @@
-dir-tree/
-├── subdirA/
-│ ├── aFile.txt
-│ ├── bDir/
-│ │ ├── aFile.txt
-│ │ └── bFile.txt
-│ └── cFile.txt
-└── subdirB/
- ├── bFile.md
- └── subdirC/
- ├── aFile.txt
- └── bFile.txt
\ No newline at end of file
+
+├─┬ subdirA/
+│ ├── aFile.txt
+│ ├─┬ bDir/
+│ │ ├── aFile.txt
+│ │ └── bFile.txt
+│ └── cFile.txt
+└─┬ subdirB/
+ ├── bFile.md
+ └─┬ subdirC/
+ ├── aFile.txt
+ └── bFile.txt
+
\ No newline at end of file
diff --git a/test/fixtures/example-helper/examples/full.js b/test/fixtures/example-helper/examples/full.js
new file mode 100644
index 0000000..610f912
--- /dev/null
+++ b/test/fixtures/example-helper/examples/full.js
@@ -0,0 +1,3 @@
+require('../')
+require('..')
+require('../file')
diff --git a/test/fixtures/example-helper/examples/output.full.md b/test/fixtures/example-helper/examples/output.full.md
new file mode 100644
index 0000000..a0955be
--- /dev/null
+++ b/test/fixtures/example-helper/examples/output.full.md
@@ -0,0 +1,5 @@
+```js
+require('example-helper')
+require('example-helper')
+require('example-helper/file')
+```
\ No newline at end of file
diff --git a/test/fixtures/example-helper/examples/output.snippet-full.md b/test/fixtures/example-helper/examples/output.snippet-full.md
new file mode 100644
index 0000000..c9cf1e2
--- /dev/null
+++ b/test/fixtures/example-helper/examples/output.snippet-full.md
@@ -0,0 +1,9 @@
+```js
+var project = require('abc')
+var file2 = require('file2')
+
+// ------------
+--parent (2)--
+├── --child (0)--
+└── --emptyChild ()--
+
\ No newline at end of file
diff --git a/test/fixtures/shout.js b/test/fixtures/shout.js
new file mode 100644
index 0000000..0bfe729
--- /dev/null
+++ b/test/fixtures/shout.js
@@ -0,0 +1,2 @@
+// Output the path of this script relative to the cwd (for the exec-helper-test
+console.log(require('path').relative(process.cwd(), __filename).toUpperCase())
diff --git a/test/git-spec.js b/test/git-spec.js
index 8545885..6e324a5 100644
--- a/test/git-spec.js
+++ b/test/git-spec.js
@@ -31,13 +31,13 @@ describe('The "addToGit" option', function () {
.then(() => git.statusAsync())
// Check only which files have been added to the index
.then((status) => {
- return status.files
+ return status.files
.filter(fileEntry => fileEntry.index === 'A')
.map(fileEntry => fileEntry.path)
.sort()
- }
+ }
)
- .then((files) => expect(files).to.deep.equal(['CONTRIBUTING.md','README.md']))
+ .then((files) => expect(files).to.deep.equal(['CONTRIBUTING.md', 'README.md']))
})
})
})
diff --git a/test/helper-spec.js b/test/helper-spec.js
index 28f03dc..3c4f9f8 100644
--- a/test/helper-spec.js
+++ b/test/helper-spec.js
@@ -5,48 +5,358 @@
* Released under the MIT license.
*/
-/* global describe */
-/* global it */
-// /* global xdescribe */
-// /* global xit */
+/* eslint-env mocha */
'use strict'
var fs = require('fs')
-var helpers = require('../handlebars/helpers.js')
+var handlebars = require('promised-handlebars')(require('handlebars'))
+const helpers = require('../handlebars/helpers.js')
+handlebars.registerHelper(helpers)
var chai = require('chai')
var chaiAsPromised = require('chai-as-promised')
chai.use(chaiAsPromised)
var expect = chai.expect
+var path = require('path')
+function executeInDir (directory) {
+ var oldCwd = null
-describe('thought-helper', function () {
- describe("'dirTree'", function () {
+ before(function () {
+ oldCwd = process.cwd()
+ process.chdir(directory)
+ })
+
+ after(function () {
+ process.chdir(oldCwd)
+ })
+}
+
+/**
+ * Return an expectation for the result of a handlebars run
+ * @param {string} template the handlebars-template
+ * @param {object} input the input object
+ * @param {string=} workingDirectory the working directory to execute the test in
+ * @returns {*}
+ */
+function expectHbs (template, input) {
+ return expect(
+ Promise.resolve()
+ .then(() => {
+ return handlebars.compile(template, {noEscape: true})(input)
+ })
+ .then((result) => result.trim())
+ )
+}
+
+/**
+ *
+ * @param {string} filename
+ * @returns {string}
+ */
+function fixture (filename) {
+ const absPath = path.join(__dirname, 'fixtures', filename)
+ try {
+ const result = fs.readFileSync(absPath, {encoding: 'utf-8'}).trim()
+ return result
+ } catch (e) {
+ if (e.code === 'ENOENT') {
+ fs.writeFileSync(absPath, 'Automatically created fixture template')
+ return 'Automatically created fixture template'
+ }
+ }
+}
+
+describe('thought-helpers:', function () {
+ describe('The "dirTree" helper', function () {
it('should return a file-hierarchy as markdown code', function () {
- expect(helpers.dirTree('test/fixtures/dir-tree'))
- .to.eventually.equal(fs.readFileSync('test/fixtures/dir-tree.output.txt', { encoding: 'utf-8' }).trim())
+ return expectHbs('{{dirTree directory}}', {directory: 'test/fixtures/dir-tree'})
+ .to.eventually.equal(fixture('dir-tree.output.txt'))
})
it('should filter specific entries throw globs', function () {
- expect(helpers.dirTree('test/fixtures/dir-tree', '!**/subdirB'))
- .to.eventually.equal(fs.readFileSync('test/fixtures/dir-tree.output.filtered.txt', { encoding: 'utf-8' }).trim())
+ return expectHbs('{{dirTree directory glob}}', {directory: 'test/fixtures/dir-tree', glob: '!(subdirB)/**'})
+ .to.eventually.equal(fixture('dir-tree.output.filtered.txt'))
+ })
+
+ it('should condense paths with a single subdirectory into a single node', function () {
+ return expectHbs('{{dirTree directory glob}}', {directory: 'test/fixtures/dir-tree', glob: '**/aFile.txt'})
+ .to.eventually.equal(fixture('dir-tree.output.condensed.txt'))
})
it('should work with more complex globs', function () {
- expect(helpers.dirTree('test/fixtures/dir-tree', '!**/+(aFile.txt|bFile.txt)'))
- .to.eventually.equal(fs.readFileSync('test/fixtures/dir-tree.output.complex.filter.txt', { encoding: 'utf-8' }).trim())
+ return expectHbs('{{dirTree directory glob}}', {
+ directory: 'test/fixtures/dir-tree',
+ glob: '**/!(aFile.txt|bFile.txt)'
+ })
+ .to.eventually.equal(fixture('dir-tree.output.complex.filter.txt'))
+ })
+
+ it('should throw an error if the glob does not resolve to any files', function () {
+ return expectHbs('{{dirTree directory}}', {directory: 'non-existing-dir'})
+ .to.be.rejectedWith('Cannot find a single file for \'**\' in \'non-existing-dir\'')
})
})
- describe("'example'", function () {
+ describe('The "example" helper', function () {
+ executeInDir('test/fixtures/example-helper')
+
it('should resolve the current project properly', function () {
- return expect(helpers.example('test/fixtures/example.js'))
- .to.eventually.contain("require('thought')")
+ return expectHbs(
+ '{{example file}}',
+ {file: 'examples/full.js'}
+ )
+ .to.eventually.equal(fixture('example-helper/examples/output.full.md'))
})
it('should return the marked part of the file if `options.hash.snippet` is true', function () {
- return expect(helpers.example('test/fixtures/example.js', { hash: { snippet: true } }))
- .to.eventually.equal('```js\nconsole.log(project)\n```')
+ return expectHbs(
+ '{{example file snippet=true}}',
+ {file: 'examples/snippet.js'}
+ )
+ .to.eventually.equal(fixture('example-helper/examples/output.snippet.md'))
+ })
+
+ it('should ignore the snippet markers, if "snippet=true" is not set`', function () {
+ return expectHbs(
+ '{{example file}}',
+ {file: 'examples/snippet.js'}
+ )
+ .to.eventually.equal(fixture('example-helper/examples/output.snippet-full.md'))
+ })
+ })
+
+ describe('The "json"-helper', function () {
+ it('should display a javascript-object as JSON', function () {
+ return expectHbs('{{json .}}', {a: {b: 2}, c: [1, 2, 'a', 'b']})
+ .to.eventually.equal(fixture('json.output.simple.md'))
+ })
+ })
+
+ describe('The "include"-helper', function () {
+ it('should include a file into fences', function () {
+ return expectHbs('{{include file}}', {file: 'test/fixtures/include/javascript.js'})
+ .to.eventually.equal(fixture('include/output.javascript.md'))
+ })
+
+ it('should use the file extension as language descriptor', function () {
+ return expectHbs('{{include file}}', {file: 'test/fixtures/include/text.txt'})
+ .to.eventually.equal(fixture('include/output.text.md'))
+ })
+
+ it('should prefer the file language descriptor provided as second parameter', function () {
+ return expectHbs('{{include file "txt"}}', {file: 'test/fixtures/include/javascript.js'})
+ .to.eventually.equal(fixture('include/output.javascript-as-text.md'))
+ })
+ })
+
+ describe('The "includeRaw"-helper', function () {
+ it('should include a file without any fences', function () {
+ return expectHbs('{{includeRaw file}}', {file: 'test/fixtures/include/javascript.js'})
+ .to.eventually.equal(fixture('include/javascript.js'))
+ })
+ })
+
+ describe('The "exec"-helper', function () {
+ it('should execute a command and return the output in a fence', function () {
+ return expectHbs('{{exec "node test/fixtures/shout.js"}}', {})
+ .to.eventually.equal(fixture('exec.output.default.md'))
+ })
+
+ it('should add language to the fence if the "lang"-option is set', function () {
+ return expectHbs('{{exec "node test/fixtures/shout.js" lang="js"}}', {})
+ .to.eventually.equal(fixture('exec.output.as.js.md'))
+ })
+
+ it('should not output fences if lang="raw"', function () {
+ return expectHbs('{{exec "node test/fixtures/shout.js" lang="raw"}}', {})
+ .to.eventually.equal(fixture('exec.output.raw.md'))
+ })
+
+ it('should surround the output with single backticks if lang="inline"', function () {
+ return expectHbs('{{exec "node test/fixtures/shout.js" lang="inline"}}', {})
+ .to.eventually.equal(fixture('exec.output.inline.md'))
+ })
+
+ it('should chdir to the directory provided as cwd="..."', function () {
+ return expectHbs('{{exec "node shout.js" cwd="test/fixtures"}}', {})
+ .to.eventually.equal(fixture('exec.output.cwd.md'))
+ })
+ })
+
+ describe('The "renderTree"-helper', function () {
+ it('render a tree', function () {
+ return expectHbs('{{#renderTree tree}}--{{prop1}} ({{children.length}})--{{/renderTree}}', {tree: tree()})
+ .to.eventually.equal(fixture('renderTree.output.md'))
+ })
+
+ function tree () {
+ return {
+ prop1: 'parent',
+ children: [
+ {
+ prop1: 'child',
+ children: []
+ },
+ {
+ prop1: 'emptyChild'
+ }
+
+ ]
+ }
+ }
+ })
+
+ /**
+ * Replace some versions by versions currently in package.json
+ * @param expectedString
+ */
+ function versions (expectedString) {
+ var thought = require('../package').version
+ var customize = require('customize/package').version
+ return expectedString
+ .replace(/THOUGHT_VERSION/g, `v${thought}`)
+ .replace(/CUSTOMIZE_VERSION/g, `v${customize}`)
+ }
+
+ describe('The "withPackageOf"-helper', function () {
+ it('should create a url and package.json for file on github (based on the current package version)', function () {
+ return expectHbs(
+ '{{#withPackageOf file}} {{@url}} - {{@package.name}} {{/withPackageOf}}',
+ {file: 'test/fixtures/shout.js'}
+ )
+ .to.eventually.equal(versions(fixture('include/withPackageOf.default.md')))
+ })
+
+ it('should create a url and package.json for files in dependency projects (based on the their current package version)', function () {
+ return expectHbs(
+ '{{#withPackageOf file}} {{@url}} - {{@package.name}} {{/withPackageOf}}',
+ {file: require.resolve('customize/helpers-io.js')}
+ )
+ .to.eventually.equal(versions(fixture('include/withPackageOf.dependency.md')))
+ })
+
+ it('should not create an url for files without repository-property in the pacakge.json', function () {
+ return expectHbs(
+ '{{#withPackageOf file}} {{@url}} - {{@package.name}} {{/withPackageOf}}',
+ {file: require.resolve('./fixtures/no-git-repo/package.json')}
+ )
+ .to.eventually.equal(versions(fixture('include/withPackageOf.no-repo.md')))
+ })
+ })
+
+ describe('The "github"-helper', function () {
+ it('should create a url to file on github (based on the current package version)', function () {
+ return expectHbs(
+ '{{github file}}',
+ {file: 'test/fixtures/shout.js'}
+ )
+ .to.eventually.equal(versions(fixture('include/github.default.md')))
+ })
+
+ it('should create a url files in dependency projects (based on the their current package version)', function () {
+ return expectHbs(
+ '{{github file}}',
+ {file: require.resolve('customize/helpers-io.js')}
+ )
+ .to.eventually.equal(versions(fixture('include/github.dependency.md')))
+ })
+ })
+
+ describe('The "htmlId"-helper', function () {
+ it('should keep valid names intact', function () {
+ expect(helpers.htmlId('abc')).to.equal('abc')
+ })
+
+ it('should replace spaces by minus', function () {
+ expect(helpers.htmlId('abc cde')).to.equal('abc-cde')
+ })
+
+ it('should remove invalid characters', function () {
+ expect(helpers.htmlId('a$b&c%d')).to.equal('abcd')
+ })
+
+ it('should keep umlaut characters', function () {
+ expect(helpers.htmlId('mäxchen')).to.equal('mäxchen')
+ })
+
+ it('should convert everything to lower-case', function () {
+ expect(helpers.htmlId('ABCDE')).to.equal('abcde')
+ })
+
+ it('should not remove japanese characters', function () {
+ expect(helpers.htmlId('ハッピークリスマス')).to.equal('ハッピークリスマス')
+ })
+ })
+
+ describe('The "npm"-helper', function () {
+ it('should create a link to the npm-page, given the package name', function () {
+ return expectHbs(
+ '{{npm file}}',
+ {file: 'bootprint-openapi'}
+ )
+ .to.eventually.equal('[bootprint-openapi](https://npmjs.com/package/bootprint-openapi)')
+ })
+ })
+
+ describe('The "hasCoveralls"-helper (positive)', function () {
+ executeInDir('test/fixtures/hasCoveralls-helper')
+
+ it('should return true, if coveralls is mentioned in the .travis.yml file', function () {
+ return expectHbs(
+ '{{#if (hasCoveralls)}}yeah{{else}}nope{{/if}}',
+ {}
+ )
+ .to.eventually.equal('yeah')
+ })
+ })
+
+ describe('The "hasCoveralls"-helper (negative)', function () {
+ executeInDir('test/fixtures/hasCoveralls-helper-false')
+
+ it('should return true, if coveralls is not configured', function () {
+ return expectHbs(
+ '{{#if (hasCoveralls)}}yeah{{else}}nope{{/if}}',
+ {}
+ )
+ .to.eventually.equal('nope')
+ })
+ })
+
+ describe('The "githubRepo"-helper', function () {
+ it('should return the name of organization/repository in a module with a configured repository on github (e.g. Thought itself)', function () {
+ return expectHbs('{{githubRepo}}', {
+ 'package': {
+ 'name': 'no-github-repo',
+ 'repository': {
+ 'type': 'git',
+ 'url': 'https://github.com/nknapp/thought.git'
+ }
+ }
+ })
+ .to.eventually.equal('nknapp/thought')
+ })
+
+ it('should return null in a module with no configured git repo', function () {
+ return expectHbs('{{githubRepo}}', {
+ package: {
+ name: 'no-git-repo'
+ }
+ })
+ .not.to.eventually.be.ok()
+ })
+
+ it('should return null in a module with a repository that is not on github', function () {
+ return expectHbs('{{githubRepo}}', {
+ 'package': {
+ 'name': 'no-github-repo',
+ 'repository': {
+ 'type': 'git',
+ 'url': 'https://custom-git.com/somepath.git'
+ }
+ }
+ })
+ .not.to.eventually.be.ok()
})
})
})
diff --git a/test/lib/run-in-scenario.js b/test/lib/run-in-scenario.js
deleted file mode 100644
index 14445c7..0000000
--- a/test/lib/run-in-scenario.js
+++ /dev/null
@@ -1,28 +0,0 @@
-var qfs = require('m-io/fs')
-
-/**
- * Remove "tmpDir", copy "scenario" recursively to "tmpDir",
- * chdir() to "tmpDir", execute "tester" and go back to the
- * previouse cwd.
- *
- * @param {string} scenario a directory containing the scenario (test-project)
- * @param {string} tmpDir the directory where the tests are executed
- * @param {function():Promise} tester a function executing the tests
- */
-module.exports = function (scenario, tmpDir, tester) {
- var oldCwd = process.cwd()
-
- if (!tmpDir.match(/testOutput|actual/)) {
- throw new Error(`${tmpDir} must be inside testOutput or the 'actual' directory of a scenario.`)
- // I don't want to risk deleting important files
- }
-
- return qfs.removeTree(tmpDir)
- .then(() => copy(scenario.input, scenario.actual))
- .then(() => process.chdir(scenario.actual))
- .then(() => tester())
- .then(() => process.chdir(oldCwd), (err) => {
- process.chdir(oldCwd)
- throw err
- })
-}
diff --git a/test/lib/scenarios.js b/test/lib/scenarios.js
index 613bf8e..5563efc 100644
--- a/test/lib/scenarios.js
+++ b/test/lib/scenarios.js
@@ -22,7 +22,6 @@ class Scenario {
* Prepare setup of the scenario
*/
prepare () {
- console.log("preparing actual", this.actual, "for input", this.input)
return qfs.removeTree(this.actual)
.then(() => copy(this.input, this.actual))
.then(() => this)
@@ -39,7 +38,7 @@ class Scenario {
try {
process.chdir(this.actual)
} catch (e) {
- if (e.code = 'ENOENT') {
+ if (e.code === 'ENOENT') {
throw new Error(this.actual + ' does not exist. Have you called ".prepare()"')
}
}
@@ -95,7 +94,6 @@ class Scenario {
readExpected (relativePath) {
return fs.readFileSync(path.join(this.expected, relativePath), 'utf-8')
}
-
}
Scenario.all = function () {
diff --git a/test/scenarios-spec.js b/test/scenarios-spec.js
index 3feb397..8ce4f04 100644
--- a/test/scenarios-spec.js
+++ b/test/scenarios-spec.js
@@ -12,7 +12,6 @@
var fs = require('fs')
var qfs = require('m-io/fs')
var deep = require('deep-aplus')(Promise)
-var copy = require('recursive-copy')
var path = require('path')
var chai = require('chai')
chai.use(require('chai-as-promised'))
@@ -21,7 +20,6 @@ var expect = chai.expect
var thought = require('../')
var Scenario = require('./lib/scenarios')
-
function listTreeRelative (baseDir, filter) {
return qfs.listTree(baseDir, filter)
.then((result) => {
@@ -58,10 +56,8 @@ describe('the integation test: ', function () {
this.timeout(10000)
Scenario.all().forEach((scenario) => {
describe(`In the scenario "${scenario.name}",`, function () {
-
if (scenario.expectFailure) {
it('running Thought should produce an error', function () {
-
// This scenario must be rejected
return expect(scenario.run(() => thought())).to.be.rejected
})