summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorSamy Pessé <samypesse@gmail.com>2016-02-26 09:41:26 +0100
committerSamy Pessé <samypesse@gmail.com>2016-02-26 09:41:26 +0100
commitd3d64f636c859f7f01a64f7774cf70bd8ccdc562 (patch)
tree4f7731f37c3a793d187b0ab1cd77680e69534c6c /test
parent4cb9cbb5ae3aa8f9211ffa3ac5e3d34232c0ca4f (diff)
parenteef072693b17526347c37b66078a5059c71caa31 (diff)
downloadgitbook-d3d64f636c859f7f01a64f7774cf70bd8ccdc562.zip
gitbook-d3d64f636c859f7f01a64f7774cf70bd8ccdc562.tar.gz
gitbook-d3d64f636c859f7f01a64f7774cf70bd8ccdc562.tar.bz2
Merge pull request #1109 from GitbookIO/3.0.0
Version 3.0.0
Diffstat (limited to 'test')
-rw-r--r--test/all.js27
-rw-r--r--test/assertions.js29
-rw-r--r--test/assets-inliner.js86
-rw-r--r--test/books/basic/README.md3
-rw-r--r--test/books/basic/SUMMARY.md1
-rw-r--r--test/books/config-js/README.md1
-rw-r--r--test/books/config-js/SUMMARY.md1
-rw-r--r--test/books/config-js/book.js3
-rw-r--r--test/books/config-json/README.md1
-rw-r--r--test/books/config-json/SUMMARY.md1
-rw-r--r--test/books/config-json/book.json3
-rw-r--r--test/books/conrefs/README.md15
-rw-r--r--test/books/conrefs/SUMMARY.md1
-rw-r--r--test/books/conrefs/block.md1
-rw-r--r--test/books/conrefs/hello.md1
-rw-r--r--test/books/glossary/GLOSSARY.md13
-rw-r--r--test/books/glossary/README.md10
-rw-r--r--test/books/glossary/SUMMARY.md3
-rw-r--r--test/books/glossary/folder/PAGE.md3
-rw-r--r--test/books/headings/README.md3
-rw-r--r--test/books/headings/SUMMARY.md0
-rw-r--r--test/books/highlight/README.md16
-rw-r--r--test/books/highlight/SUMMARY.md1
-rw-r--r--test/books/images/README.md18
-rw-r--r--test/books/images/SUMMARY.md3
-rw-r--r--test/books/images/folder/PAGE.md3
-rw-r--r--test/books/images/test.svg11
-rw-r--r--test/books/init/.gitignore3
-rw-r--r--test/books/init/SUMMARY.md9
-rw-r--r--test/books/languages/LANGS.md4
-rw-r--r--test/books/languages/README.md1
-rw-r--r--test/books/languages/en/README.md1
-rw-r--r--test/books/languages/en/SUMMARY.md1
-rw-r--r--test/books/languages/fr/README.md1
-rw-r--r--test/books/languages/fr/SUMMARY.md1
-rw-r--r--test/books/links/README.md1
-rw-r--r--test/books/links/SUMMARY.md4
-rw-r--r--test/books/links/folder1/README.md3
-rw-r--r--test/books/links/folder2/README.md1
-rw-r--r--test/books/structure/README.adoc1
-rw-r--r--test/books/structure/README.md1
-rw-r--r--test/books/structure/SUMMARY.md1
-rw-r--r--test/books/structure/book.json5
-rw-r--r--test/books/structure/glossary.md5
-rw-r--r--test/books/style-print/README.md3
-rw-r--r--test/books/style-print/SUMMARY.md1
-rw-r--r--test/books/style-print/styles/print.css3
-rw-r--r--test/books/summary/PAGE1.md1
-rw-r--r--test/books/summary/README.md1
-rw-r--r--test/books/summary/SUMMARY.md5
-rw-r--r--test/books/summary/folder/PAGE2.md1
-rw-r--r--test/codehighlighting.js65
-rw-r--r--test/config.js137
-rw-r--r--test/configuration.js37
-rw-r--r--test/conrefs.js83
-rw-r--r--test/ebook.js70
-rw-r--r--test/format.js11
-rw-r--r--test/git.js76
-rw-r--r--test/glossary.js112
-rw-r--r--test/heading.js37
-rw-r--r--test/helper.js78
-rw-r--r--test/images.js58
-rw-r--r--test/init.js24
-rw-r--r--test/json.js92
-rw-r--r--test/langs.js46
-rw-r--r--test/languages.js37
-rw-r--r--test/links.js63
-rw-r--r--test/locate.js28
-rw-r--r--test/location.js55
-rw-r--r--test/mock.js116
-rw-r--r--test/navigation.js61
-rw-r--r--test/node_modules/gitbook-plugin-test-blocks/index.js21
-rw-r--r--test/node_modules/gitbook-plugin-test-blocks/package.json7
-rw-r--r--test/node_modules/gitbook-plugin-test-config/index.js (renamed from test/plugins/config/index.js)0
-rw-r--r--test/node_modules/gitbook-plugin-test-config/package.json21
-rw-r--r--test/node_modules/gitbook-plugin-test-filters/index.js21
-rw-r--r--test/node_modules/gitbook-plugin-test-filters/package.json7
-rw-r--r--test/node_modules/gitbook-plugin-test-hooks/index.js16
-rw-r--r--test/node_modules/gitbook-plugin-test-hooks/package.json7
-rw-r--r--test/node_modules/gitbook-plugin-test-resources/index.js12
-rw-r--r--test/node_modules/gitbook-plugin-test-resources/package.json7
-rw-r--r--test/output-ebook.js33
-rw-r--r--test/output-json.js49
-rw-r--r--test/output-website.js99
-rw-r--r--test/page.js399
-rw-r--r--test/parse.js59
-rw-r--r--test/paths.js17
-rw-r--r--test/plugins.js363
-rw-r--r--test/plugins/blocks/index.js61
-rw-r--r--test/plugins/blocks/package.json9
-rw-r--r--test/plugins/config/package.json21
-rw-r--r--test/plugins/empty/index.js1
-rw-r--r--test/plugins/empty/package.json9
-rw-r--r--test/plugins/filters/index.js10
-rw-r--r--test/plugins/filters/package.json9
-rw-r--r--test/plugins/invalid/index.js1
-rw-r--r--test/plugins/invalid/package.json9
-rw-r--r--test/plugins/replace_highlight/index.js14
-rw-r--r--test/plugins/replace_highlight/package.json9
-rw-r--r--test/plugins/resources/index.js12
-rw-r--r--test/plugins/resources/package.json9
-rw-r--r--test/readme.js43
-rw-r--r--test/resolve.js60
-rw-r--r--test/structure.js20
-rw-r--r--test/summary.js326
-rw-r--r--test/template.js54
-rw-r--r--test/templating.js33
-rw-r--r--test/website.js26
108 files changed, 1903 insertions, 1573 deletions
diff --git a/test/all.js b/test/all.js
new file mode 100644
index 0000000..9c82c91
--- /dev/null
+++ b/test/all.js
@@ -0,0 +1,27 @@
+
+// Utilities
+require('./location');
+require('./paths');
+
+// Parsing
+require('./locate');
+require('./config');
+require('./readme');
+require('./summary');
+require('./glossary');
+require('./langs');
+require('./parse');
+
+require('./git');
+require('./plugins');
+require('./template');
+require('./conrefs');
+
+// Page and HTML generation
+require('./page');
+
+// Output
+require('./assets-inliner');
+require('./output-json');
+require('./output-website');
+require('./output-ebook');
diff --git a/test/assertions.js b/test/assertions.js
index f9c4ba3..56da249 100644
--- a/test/assertions.js
+++ b/test/assertions.js
@@ -1,25 +1,18 @@
-var _ = require('lodash');
var fs = require('fs');
-var path = require('path');
-var should = require('should');
+var _ = require('lodash');
var cheerio = require('cheerio');
+var should = require('should');
-require('should-promised');
-
+// Assertions to test if an Output has generated a file
should.Assertion.add('file', function(file, description) {
- this.params = { actual: this.obj.toString(), operator: 'have file ' + file, message: description };
-
- this.obj.should.have.property('options').which.is.an.Object();
- this.obj.options.should.have.property('output').which.is.a.String();
- this.assert(fs.existsSync(path.resolve(this.obj.options.output, file)));
-});
-
-should.Assertion.add('jsonfile', function(file, description) {
- this.params = { actual: this.obj.toString(), operator: 'have valid jsonfile ' + file, message: description };
-
- this.obj.should.have.property('options').which.is.an.Object();
- this.obj.options.should.have.property('output').which.is.a.String();
- this.assert(JSON.parse(fs.readFileSync(path.resolve(this.obj.options.output, file), { encoding: 'utf-8' })));
+ this.params = {
+ actual: this.obj.root(),
+ operator: 'have file ' + file,
+ message: description
+ };
+
+ this.obj.should.have.property('resolve').which.is.a.Function;
+ this.assert(fs.existsSync(this.obj.resolve(file)));
});
should.Assertion.add('html', function(rules, description) {
diff --git a/test/assets-inliner.js b/test/assets-inliner.js
new file mode 100644
index 0000000..7ccabc5
--- /dev/null
+++ b/test/assets-inliner.js
@@ -0,0 +1,86 @@
+var cheerio = require('cheerio');
+var path = require('path');
+
+var mock = require('./mock');
+var AssetsInliner = require('../lib/output/assets-inliner')();
+
+describe('Assets Inliner Output', function() {
+ var output;
+
+ before(function() {
+ var SVG = '<svg xmlns="http://www.w3.org/2000/svg" width="200" height="100" version="1.1"><rect width="200" height="100" stroke="black" stroke-width="6" fill="green"/></svg>';
+
+ return mock.outputDefaultBook(AssetsInliner, {
+ 'README.md': '',
+
+ // SVGs
+ 'svg_file.md': '![image](test.svg)',
+ 'svg_inline.md': 'This is a svg: '+SVG,
+ 'test.svg': '<?xml version="1.0" encoding="UTF-8"?>' + SVG,
+
+ // Relative
+ 'folder/test.md': '![image](../test.svg)',
+
+ // Remote images
+ 'remote_png.md': '![image](https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png)',
+ 'remote_svg.md': '![image](https://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg)',
+
+ 'SUMMARY.md': '* [svg inline](svg_inline.md)\n' +
+ '* [svg file](svg_file.md)\n' +
+ '* [remote png file](remote_png.md)\n' +
+ '* [remote svg file](remote_svg.md)\n' +
+ '* [relative image](folder/test.md)\n' +
+ '\n\n'
+ })
+ .then(function(_output) {
+ output = _output;
+ });
+ });
+
+ function testImageInPage(filename) {
+ var page = output.book.getPage(filename);
+ var $ = cheerio.load(page.content);
+
+ // Is there an image?
+ var $img = $('img');
+ $img.length.should.equal(1);
+
+ // Does the file exists
+ var src = $img.attr('src');
+
+ // Resolve the filename
+ src = page.resolveLocal(src);
+
+ output.should.have.file(src);
+ path.extname(src).should.equal('.png');
+
+ return src;
+ }
+
+ describe('SVG', function() {
+ it('should correctly convert SVG files to PNG', function() {
+ testImageInPage('svg_file.md');
+ });
+
+ it('should correctly convert inline SVG to PNG', function() {
+ testImageInPage('svg_inline.md');
+ });
+ });
+
+ describe('Remote Assets', function() {
+ it('should correctly download a PNG file', function() {
+ testImageInPage('remote_png.md');
+ });
+
+ it('should correctly download then convert a remote SVG to PNG', function() {
+ testImageInPage('remote_svg.md');
+ });
+ });
+
+ describe('Relative Images', function() {
+ it('should correctly resolve image', function() {
+ testImageInPage('folder/test.md');
+ });
+ });
+});
+
diff --git a/test/books/basic/README.md b/test/books/basic/README.md
deleted file mode 100644
index 09ade40..0000000
--- a/test/books/basic/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Readme
-
-Default description for the book.
diff --git a/test/books/basic/SUMMARY.md b/test/books/basic/SUMMARY.md
deleted file mode 100644
index ac9323c..0000000
--- a/test/books/basic/SUMMARY.md
+++ /dev/null
@@ -1 +0,0 @@
-# Summary
diff --git a/test/books/config-js/README.md b/test/books/config-js/README.md
deleted file mode 100644
index f395431..0000000
--- a/test/books/config-js/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# Readme
diff --git a/test/books/config-js/SUMMARY.md b/test/books/config-js/SUMMARY.md
deleted file mode 100644
index ac9323c..0000000
--- a/test/books/config-js/SUMMARY.md
+++ /dev/null
@@ -1 +0,0 @@
-# Summary
diff --git a/test/books/config-js/book.js b/test/books/config-js/book.js
deleted file mode 100644
index 8731343..0000000
--- a/test/books/config-js/book.js
+++ /dev/null
@@ -1,3 +0,0 @@
-module.exports = {
- "title": "js-config"
-};
diff --git a/test/books/config-json/README.md b/test/books/config-json/README.md
deleted file mode 100644
index f395431..0000000
--- a/test/books/config-json/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# Readme
diff --git a/test/books/config-json/SUMMARY.md b/test/books/config-json/SUMMARY.md
deleted file mode 100644
index ac9323c..0000000
--- a/test/books/config-json/SUMMARY.md
+++ /dev/null
@@ -1 +0,0 @@
-# Summary
diff --git a/test/books/config-json/book.json b/test/books/config-json/book.json
deleted file mode 100644
index eda10bb..0000000
--- a/test/books/config-json/book.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "title": "json-config"
-}
diff --git a/test/books/conrefs/README.md b/test/books/conrefs/README.md
deleted file mode 100644
index 324ee1f..0000000
--- a/test/books/conrefs/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Readme
-
-<p id="test-plugin-block-shortcuts-1">$$test_block1$$</p>
-<p id="test-plugin-block-shortcuts-2">{% include "./block.md" %}</p>
-
-### Relative
-
-<p id="t1">{% include "./hello.md" %}</p>
-<p id="t2">{% include "/hello.md" %}</p>
-
-### Git
-
-<p id="t3">{% include "git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test.md" %}</p>
-<p id="t4">{% include "git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test2.md" %}</p>
-<p id="t5">{% include "git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test3.md" %}</p>
diff --git a/test/books/conrefs/SUMMARY.md b/test/books/conrefs/SUMMARY.md
deleted file mode 100644
index ac9323c..0000000
--- a/test/books/conrefs/SUMMARY.md
+++ /dev/null
@@ -1 +0,0 @@
-# Summary
diff --git a/test/books/conrefs/block.md b/test/books/conrefs/block.md
deleted file mode 100644
index 3910cb6..0000000
--- a/test/books/conrefs/block.md
+++ /dev/null
@@ -1 +0,0 @@
-$$test_block2$$
diff --git a/test/books/conrefs/hello.md b/test/books/conrefs/hello.md
deleted file mode 100644
index 557db03..0000000
--- a/test/books/conrefs/hello.md
+++ /dev/null
@@ -1 +0,0 @@
-Hello World
diff --git a/test/books/glossary/GLOSSARY.md b/test/books/glossary/GLOSSARY.md
deleted file mode 100644
index 18840d2..0000000
--- a/test/books/glossary/GLOSSARY.md
+++ /dev/null
@@ -1,13 +0,0 @@
-# Glossary
-
-## test
-
-Just a simple and easy to understand test.
-
-## hakunamatata
-
-This word is not present in the content.
-
-## test long
-
-This is a test with a longer text that the first entry to test order.
diff --git a/test/books/glossary/README.md b/test/books/glossary/README.md
deleted file mode 100644
index d46da8b..0000000
--- a/test/books/glossary/README.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# Readme
-
-The word test should be replaced by a glossary link.
-
-```
-But the word test should not be replaced in code blocks
-```
-
-The two words test long should be replaced by the correct glossary links.
-
diff --git a/test/books/glossary/SUMMARY.md b/test/books/glossary/SUMMARY.md
deleted file mode 100644
index deaea20..0000000
--- a/test/books/glossary/SUMMARY.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Summary
-
-* [Page](folder/PAGE.md)
diff --git a/test/books/glossary/folder/PAGE.md b/test/books/glossary/folder/PAGE.md
deleted file mode 100644
index 33b17c2..0000000
--- a/test/books/glossary/folder/PAGE.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Page
-
-Just a page in a sub-directory to test relative link to glossary.
diff --git a/test/books/headings/README.md b/test/books/headings/README.md
deleted file mode 100644
index b08c485..0000000
--- a/test/books/headings/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Hello World
-
-## Hello {#hello-custom}
diff --git a/test/books/headings/SUMMARY.md b/test/books/headings/SUMMARY.md
deleted file mode 100644
index e69de29..0000000
--- a/test/books/headings/SUMMARY.md
+++ /dev/null
diff --git a/test/books/highlight/README.md b/test/books/highlight/README.md
deleted file mode 100644
index f47ac83..0000000
--- a/test/books/highlight/README.md
+++ /dev/null
@@ -1,16 +0,0 @@
-# Readme
-
-Block without language
-
-```
-test 1
-```
-
-Block with a language
-
-```lang
-test 2
-```
-
-Inline code: `test 3`
-Inline code with html: `<test>` \ No newline at end of file
diff --git a/test/books/highlight/SUMMARY.md b/test/books/highlight/SUMMARY.md
deleted file mode 100644
index ac9323c..0000000
--- a/test/books/highlight/SUMMARY.md
+++ /dev/null
@@ -1 +0,0 @@
-# Summary
diff --git a/test/books/images/README.md b/test/books/images/README.md
deleted file mode 100644
index 484f410..0000000
--- a/test/books/images/README.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Tests for Images
-
-# SVG relative image
-
-
-### Convert SVG to PNG
-![test.svg](test.svg)
-
-### Should only convert it once
-![test.svg](test.svg)
-
-### Download remote images
-![remote image](http://upload.wikimedia.org/wikipedia/commons/b/b0/NewTux.svg)
-
-### Remote images with same filename
-![youtube1](http://img.youtube.com/vi/9bZkp7q19f0/0.jpg)
-![youtube2](http://img.youtube.com/vi/IkV2HQLAKHY/0.jpg)
-
diff --git a/test/books/images/SUMMARY.md b/test/books/images/SUMMARY.md
deleted file mode 100644
index ec0c4fc..0000000
--- a/test/books/images/SUMMARY.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Summary
-
-* [Page](./folder/PAGE.md)
diff --git a/test/books/images/folder/PAGE.md b/test/books/images/folder/PAGE.md
deleted file mode 100644
index 8beb060..0000000
--- a/test/books/images/folder/PAGE.md
+++ /dev/null
@@ -1,3 +0,0 @@
-### Images from other folder
-![test.svg](../test.svg)
-
diff --git a/test/books/images/test.svg b/test/books/images/test.svg
deleted file mode 100644
index 48bba70..0000000
--- a/test/books/images/test.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
-<svg version="1.1" baseProfile="tiny" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="svg-root" width="100%" height="100%" viewBox="0 0 480 360">
- <title id="test-title">basic SVG tiny doc</title>
- <g id="test-body-content">
- <text font-family="Arial" font-size="14" text-anchor="middle" x="225" y="25">hello world</text>
- </g>
- <text id="revision" x="10" y="340" font-size="40" stroke="none" fill="black">Revision: 1.1</text>
- <rect id="test-frame" x="1" y="1" width="478" height="358" fill="none" stroke="#000000"/>
-</svg>
-
diff --git a/test/books/init/.gitignore b/test/books/init/.gitignore
deleted file mode 100644
index 8a88b2a..0000000
--- a/test/books/init/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-*
-!SUMMARY.md
-!.gitignore
diff --git a/test/books/init/SUMMARY.md b/test/books/init/SUMMARY.md
deleted file mode 100644
index 31c1561..0000000
--- a/test/books/init/SUMMARY.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Summary
-
-* [Hello](hello.md)
-* [Hello 2](hello2.md)
-* Hello 3
- * [Hello 4](hello3/hello4.md)
- * Hello 5
- * [Hello 6](hello3/hello5/hello6.md)
-
diff --git a/test/books/languages/LANGS.md b/test/books/languages/LANGS.md
deleted file mode 100644
index 4267b3c..0000000
--- a/test/books/languages/LANGS.md
+++ /dev/null
@@ -1,4 +0,0 @@
-# Language
-
-* [English](en)
-* [French](fr)
diff --git a/test/books/languages/README.md b/test/books/languages/README.md
deleted file mode 100644
index f395431..0000000
--- a/test/books/languages/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# Readme
diff --git a/test/books/languages/en/README.md b/test/books/languages/en/README.md
deleted file mode 100644
index e965047..0000000
--- a/test/books/languages/en/README.md
+++ /dev/null
@@ -1 +0,0 @@
-Hello
diff --git a/test/books/languages/en/SUMMARY.md b/test/books/languages/en/SUMMARY.md
deleted file mode 100644
index ac9323c..0000000
--- a/test/books/languages/en/SUMMARY.md
+++ /dev/null
@@ -1 +0,0 @@
-# Summary
diff --git a/test/books/languages/fr/README.md b/test/books/languages/fr/README.md
deleted file mode 100644
index 632e4fe..0000000
--- a/test/books/languages/fr/README.md
+++ /dev/null
@@ -1 +0,0 @@
-Bonjour
diff --git a/test/books/languages/fr/SUMMARY.md b/test/books/languages/fr/SUMMARY.md
deleted file mode 100644
index ac9323c..0000000
--- a/test/books/languages/fr/SUMMARY.md
+++ /dev/null
@@ -1 +0,0 @@
-# Summary
diff --git a/test/books/links/README.md b/test/books/links/README.md
deleted file mode 100644
index f395431..0000000
--- a/test/books/links/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# Readme
diff --git a/test/books/links/SUMMARY.md b/test/books/links/SUMMARY.md
deleted file mode 100644
index a7debc2..0000000
--- a/test/books/links/SUMMARY.md
+++ /dev/null
@@ -1,4 +0,0 @@
-# Summary
-
-* [Folder1](folder1/README.md)
-* [Folder2](folder2/README.md) \ No newline at end of file
diff --git a/test/books/links/folder1/README.md b/test/books/links/folder1/README.md
deleted file mode 100644
index 99a83f6..0000000
--- a/test/books/links/folder1/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Folder 1
-
-[Link to folder2](../folder2/README.md)
diff --git a/test/books/links/folder2/README.md b/test/books/links/folder2/README.md
deleted file mode 100644
index aa2056a..0000000
--- a/test/books/links/folder2/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# Folder 2
diff --git a/test/books/structure/README.adoc b/test/books/structure/README.adoc
deleted file mode 100644
index 354647f..0000000
--- a/test/books/structure/README.adoc
+++ /dev/null
@@ -1 +0,0 @@
-== Readme for the bookk
diff --git a/test/books/structure/README.md b/test/books/structure/README.md
deleted file mode 100644
index 94f18a8..0000000
--- a/test/books/structure/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# Readme for GitHub
diff --git a/test/books/structure/SUMMARY.md b/test/books/structure/SUMMARY.md
deleted file mode 100644
index ac9323c..0000000
--- a/test/books/structure/SUMMARY.md
+++ /dev/null
@@ -1 +0,0 @@
-# Summary
diff --git a/test/books/structure/book.json b/test/books/structure/book.json
deleted file mode 100644
index 110e0ba..0000000
--- a/test/books/structure/book.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "structure": {
- "readme": "README.adoc"
- }
-} \ No newline at end of file
diff --git a/test/books/structure/glossary.md b/test/books/structure/glossary.md
deleted file mode 100644
index 8c6c0fd..0000000
--- a/test/books/structure/glossary.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# Glossary
-
-### Hello
-
-Hello world
diff --git a/test/books/style-print/README.md b/test/books/style-print/README.md
deleted file mode 100644
index 09ade40..0000000
--- a/test/books/style-print/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Readme
-
-Default description for the book.
diff --git a/test/books/style-print/SUMMARY.md b/test/books/style-print/SUMMARY.md
deleted file mode 100644
index ac9323c..0000000
--- a/test/books/style-print/SUMMARY.md
+++ /dev/null
@@ -1 +0,0 @@
-# Summary
diff --git a/test/books/style-print/styles/print.css b/test/books/style-print/styles/print.css
deleted file mode 100644
index b05faf8..0000000
--- a/test/books/style-print/styles/print.css
+++ /dev/null
@@ -1,3 +0,0 @@
-body {
- color: red;
-}
diff --git a/test/books/summary/PAGE1.md b/test/books/summary/PAGE1.md
deleted file mode 100644
index 9608001..0000000
--- a/test/books/summary/PAGE1.md
+++ /dev/null
@@ -1 +0,0 @@
-# Page 1
diff --git a/test/books/summary/README.md b/test/books/summary/README.md
deleted file mode 100644
index f395431..0000000
--- a/test/books/summary/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# Readme
diff --git a/test/books/summary/SUMMARY.md b/test/books/summary/SUMMARY.md
deleted file mode 100644
index 38d0f6b..0000000
--- a/test/books/summary/SUMMARY.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# Summary
-
-* [Page 1](./PAGE1.md)
-* [Page 2](./folder/PAGE2.md)
-* [Don't exists](./NOTFOUND.md)
diff --git a/test/books/summary/folder/PAGE2.md b/test/books/summary/folder/PAGE2.md
deleted file mode 100644
index f310be3..0000000
--- a/test/books/summary/folder/PAGE2.md
+++ /dev/null
@@ -1 +0,0 @@
-# Page 2
diff --git a/test/codehighlighting.js b/test/codehighlighting.js
deleted file mode 100644
index f167980..0000000
--- a/test/codehighlighting.js
+++ /dev/null
@@ -1,65 +0,0 @@
-var path = require('path');
-var fs = require('fs');
-
-var Plugin = require('../lib/plugin');
-var PLUGINS_ROOT = path.resolve(__dirname, 'plugins');
-
-describe('Code Highlighting', function () {
- var book, PAGE;
-
- before(function() {
- return books.generate('highlight', 'website', {
- prepare: function(_book) {
- book = _book;
-
- var plugin = new Plugin(book, 'replace_highlight');
- plugin.load('./replace_highlight', PLUGINS_ROOT);
-
- book.plugins.load(plugin);
- }
- })
- .then(function() {
- PAGE = fs.readFileSync(
- path.join(book.options.output, 'index.html'),
- { encoding: 'utf-8' }
- );
- });
- });
-
- it('should correctly replace highlighting', function() {
- PAGE.should.be.html({
- 'code': {
- index: 0,
- text: 'code_test 1\n_code'
- }
- });
- });
-
- it('should correctly replace highlighting with language', function() {
- PAGE.should.be.html({
- 'code': {
- index: 1,
- text: 'lang_test 2\n_lang'
- }
- });
- });
-
- it('should correctly replace highlighting for inline code', function() {
- PAGE.should.be.html({
- 'code': {
- index: 2,
- text: 'code_test 3_code'
- }
- });
- });
-
- it('should correctly replace highlighting for inline code with html tags', function() {
- PAGE.should.be.html({
- 'code': {
- index: 3,
- text: 'code_<test>_code'
- }
- });
- });
-});
-
diff --git a/test/config.js b/test/config.js
new file mode 100644
index 0000000..be28fc9
--- /dev/null
+++ b/test/config.js
@@ -0,0 +1,137 @@
+var should = require('should');
+var mock = require('./mock');
+var validator = require('../lib/config/validator');
+
+describe('Configuration', function() {
+
+ describe('Validation', function() {
+ it('should merge default', function() {
+ validator.validate({}).should.have.property('gitbook').which.equal('*');
+ });
+
+ it('should throw error for invalid configuration', function() {
+ should.throws(function() {
+ validator.validate({
+ direction: 'invalid'
+ });
+ });
+ });
+
+ it('should not throw error for non existing configuration', function() {
+ validator.validate({
+ style: {
+ 'pdf': 'test.css'
+ }
+ });
+ });
+
+ it('should validate plugins as an array', function() {
+ validator.validate({
+ plugins: ['hello']
+ });
+ });
+
+ it('should validate plugins as a string', function() {
+ validator.validate({
+ plugins: 'hello,world'
+ });
+ });
+
+ });
+
+ describe('No configuration', function() {
+ var book;
+
+ before(function() {
+ return mock.setupDefaultBook()
+ .then(function(_book) {
+ book = _book;
+ return book.config.load();
+ });
+ });
+
+ it('should signal that configuration is not defined', function() {
+ book.config.exists().should.not.be.ok();
+ });
+ });
+
+ describe('JSON file', function() {
+ var book;
+
+ before(function() {
+ return mock.setupDefaultBook({
+ 'book.json': { title: 'Hello World' }
+ })
+ .then(function(_book) {
+ book = _book;
+ return book.config.load();
+ });
+ });
+
+ it('should correctly extend configuration', function() {
+ book.config.get('title', '').should.equal('Hello World');
+ });
+ });
+
+ describe('JS file', function() {
+ var book;
+
+ before(function() {
+ return mock.setupDefaultBook({
+ 'book.js': 'module.exports = { title: "Hello World" };'
+ })
+ .then(function(_book) {
+ book = _book;
+ return book.config.load();
+ });
+ });
+
+ it('should correctly extend configuration', function() {
+ book.config.get('title', '').should.equal('Hello World');
+ });
+ });
+
+ describe('Multilingual', function() {
+ var book;
+
+ before(function() {
+ return mock.setupDefaultBook({
+ 'book.json': {
+ title: 'Hello World',
+ pluginsConfig: {
+ 'test': {
+ 'hello': true
+ }
+ }
+ },
+ 'LANGS.md': '# Languages\n\n'
+ + '* [en](./en)\n'
+ + '* [fr](./fr)\n\n',
+ 'en/README.md': '# Hello',
+ 'fr/README.md': '# Bonjour',
+ 'en/book.json': { description: 'In english' },
+ 'fr/book.json': { description: 'En francais' }
+ })
+ .then(function(_book) {
+ book = _book;
+ return book.parse();
+ });
+ });
+
+ it('should correctly extend configuration', function() {
+ book.config.get('title', '').should.equal('Hello World');
+ book.config.get('description', '').should.equal('');
+
+ var en = book.books[0];
+ en.config.get('title', '').should.equal('Hello World');
+ en.config.get('description', '').should.equal('In english');
+ en.config.get('pluginsConfig.test.hello').should.equal(true);
+
+ var fr = book.books[1];
+ fr.config.get('title', '').should.equal('Hello World');
+ fr.config.get('description', '').should.equal('En francais');
+ fr.config.get('pluginsConfig.test.hello').should.equal(true);
+ });
+ });
+});
+
diff --git a/test/configuration.js b/test/configuration.js
deleted file mode 100644
index d30fd61..0000000
--- a/test/configuration.js
+++ /dev/null
@@ -1,37 +0,0 @@
-describe('Configuration', function () {
- it('should extract default title from README', function() {
- return books.parse('basic')
- .then(function(book) {
- book.options.title.should.be.equal('Readme');
- });
- });
-
- it('should extract default description from README', function() {
- return books.parse('basic')
- .then(function(book) {
- book.options.description.should.be.equal('Default description for the book.');
- });
- });
-
- it('should correctly load from json (book.json)', function() {
- return books.parse('config-json')
- .then(function(book) {
- book.options.title.should.be.equal('json-config');
- });
- });
-
- it('should correctly load from JavaScript (book.js)', function() {
- return books.parse('config-js')
- .then(function(book) {
- book.options.title.should.be.equal('js-config');
- });
- });
-
- it('should provide configuration on book.config.get', function() {
- return books.parse('basic')
- .then(function(book) {
- book.config.get('description').should.be.equal('Default description for the book.');
- book.getConfig('description').should.be.equal('Default description for the book.');
- });
- });
-});
diff --git a/test/conrefs.js b/test/conrefs.js
index 32e4058..6500709 100644
--- a/test/conrefs.js
+++ b/test/conrefs.js
@@ -1,68 +1,49 @@
-var fs = require('fs');
-var path = require('path');
+var mock = require('./mock');
+var ConrefsLoader = require('../lib/output/conrefs')();
-describe('ConRefs', function () {
- var book, readme;
+
+describe('Conrefs Loader', function() {
+ var output;
before(function() {
- return books.generate('conrefs', 'website')
- .then(function(_book) {
- book = _book;
+ return mock.outputDefaultBook(ConrefsLoader, {
+ 'test.md': 'World'
+ })
+ .then(function(_output) {
+ output = _output;
+ });
+ });
+
- readme = fs.readFileSync(
- path.join(book.options.output, 'index.html'),
- { encoding: 'utf-8' }
- );
- });
+ it('should include a local file', function() {
+ return output.template.renderString('Hello {% include "./test.md" %}')
+ .should.be.fulfilledWith('Hello World');
});
- it('should handle local references', function() {
- readme.should.be.html({
- '.page-inner p#t1': {
- count: 1,
- text: 'Hello World',
- trim: true
- }
- });
+ it('should include a git url', function() {
+ return output.template.renderString('Hello {% include "./test.md" %}')
+ .should.be.fulfilledWith('Hello World');
});
- it('should handle local references with absolute paths', function() {
- readme.should.be.html({
- '.page-inner p#t2': {
- count: 1,
- text: 'Hello World',
- trim: true
- }
- });
+ it('should reject file out of scope', function() {
+ return output.template.renderString('Hello {% include "../test.md" %}')
+ .should.be.rejected();
});
- it('should correctly include file from git reference', function() {
- readme.should.be.html({
- '.page-inner p#t3': {
- count: 1,
- text: 'Hello from git',
- trim: true
- }
+ describe('Git Urls', function() {
+ it('should include a file from a git repo', function() {
+ return output.template.renderString('{% include "git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test.md" %}')
+ .should.be.fulfilledWith('Hello from git');
});
- });
- it('should correctly handle deep include in git reference', function() {
- readme.should.be.html({
- '.page-inner p#t4': {
- count: 1,
- text: 'First Hello. Hello from git',
- trim: true
- }
+ it('should handle deep inclusion (1)', function() {
+ return output.template.renderString('{% include "git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test2.md" %}')
+ .should.be.fulfilledWith('First Hello. Hello from git');
});
- });
- it('should correctly handle absolute include in git reference', function() {
- readme.should.be.html({
- '.page-inner p#t5': {
- count: 1,
- text: 'First Hello. Hello from git',
- trim: true
- }
+ it('should handle deep inclusion (2)', function() {
+ return output.template.renderString('{% include "git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test3.md" %}')
+ .should.be.fulfilledWith('First Hello. Hello from git');
});
});
});
diff --git a/test/ebook.js b/test/ebook.js
deleted file mode 100644
index 5caf28b..0000000
--- a/test/ebook.js
+++ /dev/null
@@ -1,70 +0,0 @@
-var fs = require('fs');
-var path = require('path');
-
-describe('eBook generator', function () {
- describe('Basic Book', function() {
- var book;
-
- before(function() {
- return books.generate('basic', 'ebook')
- .then(function(_book) {
- book = _book;
- });
- });
-
- it('should correctly output a SUMMARY.html', function() {
- book.should.have.file('SUMMARY.html');
- });
-
- it('should correctly copy assets', function() {
- book.should.have.file('gitbook');
- book.should.have.file('gitbook/ebook.css');
- });
-
- it('should not copy website assets', function() {
- book.should.not.have.file('gitbook/style.css');
- });
- });
-
- describe('Custom styles', function() {
- var book;
-
- before(function() {
- return books.generate('style-print', 'ebook')
- .then(function(_book) {
- book = _book;
- });
- });
-
- it('should correctly copy print.css', function() {
- book.should.have.file('styles');
- book.should.have.file('styles/print.css');
- });
-
- it('should remove default print.css', function() {
- var PAGE = fs.readFileSync(
- path.join(book.options.output, 'index.html'),
- { encoding: 'utf-8' }
- );
-
- // There are 2 styles (one from plugin-highlight and the new style)
- PAGE.should.be.html({
- 'link': {
- count: 2
- }
- });
-
- PAGE.should.be.html({
- 'link[href=\'./styles/print.css\']': {
- count: 1
- }
- });
-
- PAGE.should.be.html({
- 'link[href="gitbook/plugins/gitbook-plugin-highlight/ebook.css"]': {
- count: 1
- }
- });
- });
- });
-});
diff --git a/test/format.js b/test/format.js
deleted file mode 100644
index 2ec1a6f..0000000
--- a/test/format.js
+++ /dev/null
@@ -1,11 +0,0 @@
-describe('Formatting', function () {
- it('should provide formatting with book.formatString', function() {
- return books.parse('basic')
- .then(function(book) {
- return book.formatString('markdown', 'this is a **test**');
- })
- .then(function(content) {
- content.should.equal('<p>this is a <strong>test</strong></p>\n');
- });
- });
-});
diff --git a/test/git.js b/test/git.js
index 6fd6b41..9fd7490 100644
--- a/test/git.js
+++ b/test/git.js
@@ -1,31 +1,61 @@
-var should = require("should");
-var git = require("../lib/utils/git");
+var should = require('should');
+var path = require('path');
+var os = require('os');
-describe("GIT parser and getter", function () {
- it("should correctly parse an https url", function() {
- var parts = git.parseUrl("git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test.md");
+var Git = require('../lib/utils/git');
- should.exist(parts);
- parts.host.should.be.equal("https://gist.github.com/69ea4542e4c8967d2fa7.git");
- parts.ref.should.be.equal("master");
- parts.filepath.should.be.equal("test.md");
- });
+describe('Git', function() {
- it("should correctly parse an https url with a reference", function() {
- var parts = git.parseUrl("git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test.md#0.1.2");
+ describe('URL parsing', function() {
- should.exist(parts);
- parts.host.should.be.equal("https://gist.github.com/69ea4542e4c8967d2fa7.git");
- parts.ref.should.be.equal("0.1.2");
- parts.filepath.should.be.equal("test.md");
- });
+ it('should correctly validate git urls', function() {
+ // HTTPS
+ Git.isUrl('git+https://github.com/Hello/world.git').should.be.ok();
+
+ // SSH
+ Git.isUrl('git+git@github.com:GitbookIO/gitbook.git/directory/README.md#e1594cde2c32e4ff48f6c4eff3d3d461743d74e1').should.be.ok;
+
+ // Non valid
+ Git.isUrl('https://github.com/Hello/world.git').should.not.be.ok();
+ Git.isUrl('README.md').should.not.be.ok();
+ });
+
+ it('should parse HTTPS urls', function() {
+ var parts = Git.parseUrl('git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test.md');
+
+ should.exist(parts);
+ parts.host.should.be.equal('https://gist.github.com/69ea4542e4c8967d2fa7.git');
+ should(parts.ref).be.equal(null);
+ parts.filepath.should.be.equal('test.md');
+ });
- it("should correctly parse an ssh url", function() {
- var parts = git.parseUrl("git+git@github.com:GitbookIO/gitbook.git/directory/README.md#e1594cde2c32e4ff48f6c4eff3d3d461743d74e1");
+ it('should parse HTTPS urls with a reference', function() {
+ var parts = Git.parseUrl('git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test.md#1.0.0');
- should.exist(parts);
- parts.host.should.be.equal("git@github.com:GitbookIO/gitbook.git");
- parts.ref.should.be.equal("e1594cde2c32e4ff48f6c4eff3d3d461743d74e1");
- parts.filepath.should.be.equal("directory/README.md");
+ should.exist(parts);
+ parts.host.should.be.equal('https://gist.github.com/69ea4542e4c8967d2fa7.git');
+ parts.ref.should.be.equal('1.0.0');
+ parts.filepath.should.be.equal('test.md');
+ });
+
+ it('should parse SSH urls', function() {
+ var parts = Git.parseUrl('git+git@github.com:GitbookIO/gitbook.git/directory/README.md#e1594cde2c32e4ff48f6c4eff3d3d461743d74e1');
+
+ should.exist(parts);
+ parts.host.should.be.equal('git@github.com:GitbookIO/gitbook.git');
+ parts.ref.should.be.equal('e1594cde2c32e4ff48f6c4eff3d3d461743d74e1');
+ parts.filepath.should.be.equal('directory/README.md');
+ });
});
+
+ describe('Cloning and resolving', function() {
+ it('should clone an HTTPS url', function() {
+ var git = new Git(path.join(os.tmpdir(), 'test-git-'+Date.now()));
+ return git.resolve('git+https://gist.github.com/69ea4542e4c8967d2fa7.git/test.md')
+ .then(function(filename) {
+ path.extname(filename).should.equal('.md');
+ });
+ });
+ });
+
});
diff --git a/test/glossary.js b/test/glossary.js
index f0f31a5..d6d1af6 100644
--- a/test/glossary.js
+++ b/test/glossary.js
@@ -1,87 +1,71 @@
-var fs = require("fs");
-var path = require("path");
+var should = require('should');
+var mock = require('./mock');
-describe("Glossary", function () {
- describe("Parsing", function() {
- var book;
+describe('Glossary', function() {
+ it('should parse empty glossary', function() {
+ return mock.setupDefaultBook({
+ 'GLOSSARY.md': ''
+ })
+ .then(function(book) {
+ return book.config.load()
- before(function() {
- return books.parse("glossary")
- .then(function(_book) {
- book = _book;
- });
- });
-
- it("should correctly list items", function() {
- book.should.have.property("glossary");
- book.glossary.should.have.lengthOf(3);
+ .then(function() {
+ return book.glossary.load();
+ })
+ .then(function() {
+ book.glossary.isEmpty().should.be.true();
+ });
});
});
- describe("Generation", function() {
+ describe('Non-empty glossary', function() {
var book;
before(function() {
- return books.generate("glossary", "website")
- .then(function(_book) {
- book = _book;
- });
+ return mock.setupDefaultBook({
+ 'GLOSSARY.md': '# Glossary\n\n## Hello World\n\nThis is an entry'
+ })
+ .then(function(_book) {
+ book = _book;
+ return book.config.load();
+ })
+ .then(function() {
+ return book.glossary.load();
+ });
});
- it("should correctly generate a GLOSSARY.html", function() {
- book.should.have.file("GLOSSARY.html");
+ it('should not be empty', function() {
+ book.glossary.isEmpty().should.be.false();
});
- describe("Page Integration", function() {
- var readme, page;
-
- before(function() {
- readme = fs.readFileSync(
- path.join(book.options.output, "index.html"),
- { encoding: "utf-8" }
- );
- page = fs.readFileSync(
- path.join(book.options.output, "folder/PAGE.html"),
- { encoding: "utf-8" }
- );
- });
+ describe('glossary.get', function() {
+ it('should return an existing entry', function() {
+ var entry = book.glossary.get('hello_world');
+ should.exist(entry);
- it("should correctly replaced terms by links", function() {
- readme.should.be.html({
- ".page-inner a[href=\"GLOSSARY.html#test\"]": {
- count: 1,
- text: "test",
- attributes: {
- title: "Just a simple and easy to understand test."
- }
- }
- });
+ entry.name.should.equal('Hello World');
+ entry.description.should.equal('This is an entry');
+ entry.id.should.equal('hello_world');
});
- it("should correctly replaced terms by links (relative)", function() {
- page.should.be.html({
- ".page-inner a[href=\"../GLOSSARY.html#test\"]": {
- count: 1
- }
- });
+ it('should undefined return non existing entry', function() {
+ var entry = book.glossary.get('cool');
+ should.not.exist(entry);
});
+ });
- it("should not replace terms in codeblocks", function() {
- readme.should.be.html({
- ".page-inner code a": {
- count: 0
- }
- });
+ describe('glossary.find', function() {
+ it('should return an existing entry', function() {
+ var entry = book.glossary.find('HeLLo World');
+ should.exist(entry);
+ entry.id.should.equal('hello_world');
});
- it("should correctly select the longest term", function() {
- readme.should.be.html({
- ".page-inner a[href=\"GLOSSARY.html#test_long\"]": {
- count: 1,
- text: "test long"
- }
- });
+ it('should return undefined for non existing entry', function() {
+ var entry = book.glossary.find('Hello');
+ should.not.exist(entry);
});
});
});
});
+
diff --git a/test/heading.js b/test/heading.js
deleted file mode 100644
index f6d65c3..0000000
--- a/test/heading.js
+++ /dev/null
@@ -1,37 +0,0 @@
-var path = require('path');
-var fs = require('fs');
-
-describe('Headings', function () {
- var book, PAGE;
-
- before(function() {
- return books.generate('headings', 'website')
- .then(function(_book) {
- book = _book;
-
- PAGE = fs.readFileSync(
- path.join(book.options.output, 'index.html'),
- { encoding: 'utf-8' }
- );
- });
- });
-
- describe('IDs', function() {
- it('should correctly generate an ID', function() {
- PAGE.should.be.html({
- 'h1#hello-world': {
- count: 1
- }
- });
- });
-
- it('should correctly accept custom ID', function() {
- PAGE.should.be.html({
- 'h2#hello-custom': {
- count: 1
- }
- });
- });
- });
-});
-
diff --git a/test/helper.js b/test/helper.js
deleted file mode 100644
index bbe82de..0000000
--- a/test/helper.js
+++ /dev/null
@@ -1,78 +0,0 @@
-var os = require('os');
-var path = require('path');
-var Q = require('q');
-var _ = require('lodash');
-
-var fsUtil = require('../lib/utils/fs');
-var Book = require('../').Book;
-var LOG_LEVELS = require('../').LOG_LEVELS;
-
-require('./assertions');
-
-
-var BOOKS = {};
-var TMPDIR = os.tmpdir();
-
-
-// Generate and return a book
-function generateBook(bookId, test, opts) {
- opts = _.defaults(opts || {}, {
- prepare: function() {}
- });
-
- return parseBook(bookId, test, opts)
- .then(function(book) {
-
- return Q(opts.prepare(book))
- .then(function() {
- return book.generate(test);
- })
- .thenResolve(book);
- });
-}
-
-// Generate and return a book
-function parseBook(bookId, test, opts) {
- opts = _.defaults(opts || {}, {
- testId: ''
- });
-
- test = test || 'website';
- var testId = [test, opts.testId].join('-');
-
- BOOKS[bookId] = BOOKS[bookId] || {};
- if (BOOKS[bookId][testId]) return Q(BOOKS[bookId][testId]);
-
- BOOKS[bookId][testId] = new Book(path.resolve(__dirname, 'books', bookId), {
- logLevel: LOG_LEVELS.DISABLED,
- config: {
- output: path.resolve(TMPDIR, bookId+'-'+testId)
- }
- });
-
- return BOOKS[bookId][testId].parse()
- .then(function() {
- return BOOKS[bookId][testId];
- });
-}
-
-
-global.books = {
- parse: parseBook,
- generate: generateBook
-};
-
-// Cleanup all tests
-after(function() {
- return _.chain(BOOKS)
- .map(function(types) {
- return _.values(types);
- })
- .flatten()
- .reduce(function(prev, book) {
- return prev.then(function() {
- return fsUtil.remove(book.options.output);
- });
- }, Q())
- .value();
-});
diff --git a/test/images.js b/test/images.js
deleted file mode 100644
index de45066..0000000
--- a/test/images.js
+++ /dev/null
@@ -1,58 +0,0 @@
-var fs = require("fs");
-var _ = require("lodash");
-var path = require("path");
-var cheerio = require("cheerio");
-
-describe("Images", function () {
- var book, readme, $, $img, srcs;
-
- before(function() {
- return books.generate("images", "ebook")
- .then(function(_book) {
- book = _book;
-
- readme = fs.readFileSync(
- path.join(book.options.output, "index.html"),
- { encoding: "utf-8" }
- );
- $ = cheerio.load(readme);
- $img = $("img");
- srcs = $img.map(function() {
- return $(this).attr("src");
- });
- });
- });
-
- it("should detect all images", function() {
- _.uniq(srcs).should.have.lengthOf(4);
- });
-
- it("should keep image tags", function() {
- srcs.should.have.lengthOf(5);
- });
-
- it("should not have .svg files", function() {
- _.each(srcs, function(src) {
- path.extname(src).should.not.equal(".svg");
- });
- });
-
- it("should correctly convert svg images to png", function() {
- _.each(srcs, function(src) {
- book.should.have.file(src);
- });
- });
-
- it("should handle relative paths", function() {
- var PAGE = fs.readFileSync(
- path.join(book.options.output, "folder/PAGE.html"),
- { encoding: "utf-8" }
- );
-
- PAGE.should.be.html({
- "img[src=\"../test.png\"]": {
- count: 1
- }
- });
- });
-});
diff --git a/test/init.js b/test/init.js
deleted file mode 100644
index 625d77c..0000000
--- a/test/init.js
+++ /dev/null
@@ -1,24 +0,0 @@
-var fs = require('fs');
-var path = require('path');
-var should = require('should');
-
-var Book = require('../').Book;
-var LOG_LEVELS = require('../').LOG_LEVELS;
-
-describe('Init Books', function () {
- var initRoot;
-
- before(function() {
- initRoot = path.resolve(__dirname, 'books/init');
- return Book.init(initRoot, {
- logLevel: LOG_LEVELS.DISABLED
- });
- });
-
- it('should create all chapters', function() {
- should(fs.existsSync(path.resolve(initRoot, 'hello.md'))).be.ok();
- should(fs.existsSync(path.resolve(initRoot, 'hello2.md'))).be.ok();
- should(fs.existsSync(path.resolve(initRoot, 'hello3/hello4.md'))).be.ok();
- should(fs.existsSync(path.resolve(initRoot, 'hello3/hello5/hello6.md'))).be.ok();
- });
-});
diff --git a/test/json.js b/test/json.js
deleted file mode 100644
index 60baf9a..0000000
--- a/test/json.js
+++ /dev/null
@@ -1,92 +0,0 @@
-var fs = require('fs');
-var path = require('path');
-
-describe('JSON generator', function () {
- describe('Basic Book', function() {
- var book;
-
- before(function() {
- return books.generate('basic', 'json')
- .then(function(_book) {
- book = _book;
- });
- });
-
- it('should correctly output a README.json', function() {
- book.should.have.file('README.json');
- });
-
- it('should output a valid json', function() {
- book.should.have.jsonfile('README.json');
- });
-
- describe('Page Format', function() {
- var page;
-
- before(function() {
- page = JSON.parse(
- fs.readFileSync(
- path.join(book.options.output, 'README.json'),
- { encoding: 'utf-8' }
- )
- );
- });
-
- it('should contains valid section', function() {
- page.should.have.property('sections').with.lengthOf(1);
- page.sections[0].should.have.property('content').which.is.a.String();
- page.sections[0].should.have.property('type', 'normal');
- });
-
- it('should contains valid progress', function() {
- page.should.have.property('progress');
- page.progress.should.have.property('chapters').with.lengthOf(1);
- page.progress.should.have.property('current');
- });
-
- it('should contains no languages', function() {
- page.should.have.property('langs').with.lengthOf(0);
- });
- });
- });
-
- describe('Multilingual Book', function() {
- var book;
-
- before(function() {
- return books.generate('languages', 'json')
- .then(function(_book) {
- book = _book;
- });
- });
-
- it('should correctly output READMEs', function() {
- book.should.have.file('README.json');
- book.should.have.file('en/README.json');
- book.should.have.file('fr/README.json');
- });
-
- it('should output valid json', function() {
- book.should.have.jsonfile('README.json');
- book.should.have.jsonfile('en/README.json');
- book.should.have.jsonfile('fr/README.json');
- });
-
- describe('Page Format', function() {
- var page;
-
- before(function() {
- page = JSON.parse(
- fs.readFileSync(
- path.join(book.options.output, 'README.json'),
- { encoding: 'utf-8' }
- )
- );
- });
-
- it('should contains no languages', function() {
- page.should.have.property('langs').with.lengthOf(2);
- });
- });
- });
-});
diff --git a/test/langs.js b/test/langs.js
new file mode 100644
index 0000000..91dbd5a
--- /dev/null
+++ b/test/langs.js
@@ -0,0 +1,46 @@
+var mock = require('./mock');
+
+describe('Langs', function() {
+ it('should parse empty langs', function() {
+ return mock.setupDefaultBook({
+ 'LANGS.md': ''
+ })
+ .then(function(book) {
+ return book.config.load()
+
+ .then(function() {
+ return book.langs.load();
+ })
+
+ .then(function() {
+ book.langs.count().should.equal(0);
+ });
+ });
+ });
+
+ describe('Non-empty languages list', function() {
+ var book;
+
+ before(function() {
+ return mock.setupDefaultBook({
+ 'LANGS.md': '# Languages\n\n'
+ + '* [en](./en)\n'
+ + '* [fr](./fr)\n\n'
+ })
+ .then(function(_book) {
+ book = _book;
+
+ return book.langs.load();
+ });
+ });
+
+ it('should correctly count languages', function() {
+ book.langs.count().should.equal(2);
+ });
+
+ it('should correctly define book as multilingual', function() {
+ book.isMultilingual().should.equal(true);
+ });
+ });
+});
+
diff --git a/test/languages.js b/test/languages.js
deleted file mode 100644
index 0bde347..0000000
--- a/test/languages.js
+++ /dev/null
@@ -1,37 +0,0 @@
-describe("Languages", function () {
- describe("Parsing", function() {
- var book;
-
- before(function() {
- return books.parse("languages")
- .then(function(_book) {
- book = _book;
- });
- });
-
- it("should correctly list languages", function() {
- book.should.have.property("books");
- book.books.should.have.lengthOf(2);
-
- book.books[0].options.language.should.be.equal("en");
- book.books[1].options.language.should.be.equal("fr");
- });
- });
-
- describe("Generation", function() {
- var book;
-
- before(function() {
- return books.generate("languages", "website")
- .then(function(_book) {
- book = _book;
- });
- });
-
- it("should correctly create books", function() {
- book.should.have.file("index.html");
- book.should.have.file("en/index.html");
- book.should.have.file("fr/index.html");
- });
- });
-});
diff --git a/test/links.js b/test/links.js
deleted file mode 100644
index baca9d1..0000000
--- a/test/links.js
+++ /dev/null
@@ -1,63 +0,0 @@
-var fs = require("fs");
-var path = require("path");
-var cheerio = require("cheerio");
-
-var links = require("../lib/utils/links");
-
-describe("Links", function () {
- it("should correctly test external links", function() {
- links.isExternal("http://google.fr").should.be.exactly(true);
- links.isExternal("https://google.fr").should.be.exactly(true);
- links.isExternal("test.md").should.be.exactly(false);
- links.isExternal("folder/test.md").should.be.exactly(false);
- links.isExternal("/folder/test.md").should.be.exactly(false);
- });
-
- it("should correctly detect anchor links", function() {
- links.isAnchor("#test").should.be.exactly(true);
- links.isAnchor(" #test").should.be.exactly(true);
- links.isAnchor("https://google.fr#test").should.be.exactly(false);
- links.isAnchor("test.md#test").should.be.exactly(false);
- });
-
- describe("toAbsolute", function() {
- it("should correctly transform as absolute", function() {
- links.toAbsolute("http://google.fr").should.be.equal("http://google.fr");
- links.toAbsolute("test.md", "./", "./").should.be.equal("test.md");
- links.toAbsolute("folder/test.md", "./", "./").should.be.equal("folder/test.md");
- });
-
- it("should correctly handle windows path", function() {
- links.toAbsolute("folder\\test.md", "./", "./").should.be.equal("folder/test.md");
- });
-
- it("should correctly handle absolute path", function() {
- links.toAbsolute("/test.md", "./", "./").should.be.equal("test.md");
- links.toAbsolute("/test.md", "test", "test").should.be.equal("../test.md");
- links.toAbsolute("/sub/test.md", "test", "test").should.be.equal("../sub/test.md");
- });
- });
-
- describe("page", function() {
- var book;
-
- before(function() {
- return books.generate("links", "website")
- .then(function(_book) {
- book = _book;
- });
- });
-
- it("should correctly replace relative links", function() {
- var readme = fs.readFileSync(
- path.join(book.options.output, "folder1/index.html"),
- { encoding: "utf-8" }
- );
- var $ = cheerio.load(readme);
- var $a = $(".page-inner a");
-
- $a.attr("href").should.be.exactly("../folder2/index.html");
- });
- });
-
-});
diff --git a/test/locate.js b/test/locate.js
new file mode 100644
index 0000000..609f2da
--- /dev/null
+++ b/test/locate.js
@@ -0,0 +1,28 @@
+var path = require('path');
+
+var Book = require('../').Book;
+var mock = require('./mock');
+
+describe('Locate', function() {
+ it('should use root folder if no .gitbook', function() {
+ return mock.setupFS({
+ 'README.md': '# Hello'
+ })
+ .then(function(root) {
+ return Book.locate(mock.fs, root)
+ .should.be.fulfilledWith(root);
+ });
+ });
+
+ it('should use resolve using .gitbook', function() {
+ return mock.setupFS({
+ 'README.md': '# Hello',
+ '.gitbook': './docs'
+ })
+ .then(function(root) {
+ return Book.locate(mock.fs, root)
+ .should.be.fulfilledWith(path.resolve(root, 'docs'));
+ });
+ });
+
+});
diff --git a/test/location.js b/test/location.js
new file mode 100644
index 0000000..3e2294e
--- /dev/null
+++ b/test/location.js
@@ -0,0 +1,55 @@
+var location = require('../lib/utils/location');
+
+describe('Location', function() {
+ it('should correctly test external location', function() {
+ location.isExternal('http://google.fr').should.be.exactly(true);
+ location.isExternal('https://google.fr').should.be.exactly(true);
+ location.isExternal('test.md').should.be.exactly(false);
+ location.isExternal('folder/test.md').should.be.exactly(false);
+ location.isExternal('/folder/test.md').should.be.exactly(false);
+ });
+
+ it('should correctly detect anchor location', function() {
+ location.isAnchor('#test').should.be.exactly(true);
+ location.isAnchor(' #test').should.be.exactly(true);
+ location.isAnchor('https://google.fr#test').should.be.exactly(false);
+ location.isAnchor('test.md#test').should.be.exactly(false);
+ });
+
+ describe('.relative', function() {
+ it('should resolve to a relative path (same folder)', function() {
+ location.relative('links/', 'links/test.md').should.equal('test.md');
+ });
+
+ it('should resolve to a relative path (parent folder)', function() {
+ location.relative('links/', 'test.md').should.equal('../test.md');
+ });
+
+ it('should resolve to a relative path (child folder)', function() {
+ location.relative('links/', 'links/hello/test.md').should.equal('hello/test.md');
+ });
+ });
+
+ describe('.toAbsolute', function() {
+ it('should correctly transform as absolute', function() {
+ location.toAbsolute('http://google.fr').should.be.equal('http://google.fr');
+ location.toAbsolute('test.md', './', './').should.be.equal('test.md');
+ location.toAbsolute('folder/test.md', './', './').should.be.equal('folder/test.md');
+ });
+
+ it('should correctly handle windows path', function() {
+ location.toAbsolute('folder\\test.md', './', './').should.be.equal('folder/test.md');
+ });
+
+ it('should correctly handle absolute path', function() {
+ location.toAbsolute('/test.md', './', './').should.be.equal('test.md');
+ location.toAbsolute('/test.md', 'test', 'test').should.be.equal('../test.md');
+ location.toAbsolute('/sub/test.md', 'test', 'test').should.be.equal('../sub/test.md');
+ location.toAbsolute('/test.png', 'folder', '').should.be.equal('test.png');
+ });
+
+ it('should correctly handle absolute path (windows)', function() {
+ location.toAbsolute('\\test.png', 'folder', '').should.be.equal('test.png');
+ });
+ });
+});
diff --git a/test/mock.js b/test/mock.js
new file mode 100644
index 0000000..5ff9f63
--- /dev/null
+++ b/test/mock.js
@@ -0,0 +1,116 @@
+/* eslint-disable no-console */
+
+var Q = require('q');
+var _ = require('lodash');
+var tmp = require('tmp');
+var path = require('path');
+
+var Book = require('../').Book;
+var NodeFS = require('../lib/fs/node');
+var fs = require('../lib/utils/fs');
+
+require('./assertions');
+
+// Create filesystem instance for testing
+var nodeFS = new NodeFS();
+
+function setupFS(files) {
+ return Q.nfcall(tmp.dir.bind(tmp)).get(0)
+ .then(function(rootFolder) {
+ return _.chain(_.pairs(files))
+ .sortBy(0)
+ .reduce(function(prev, pair) {
+ return prev.then(function() {
+ var filename = path.resolve(rootFolder, pair[0]);
+ var buf = pair[1];
+
+ if (_.isObject(buf)) buf = JSON.stringify(buf);
+ if (_.isString(buf)) buf = new Buffer(buf, 'utf-8');
+
+ return fs.mkdirp(path.dirname(filename))
+ .then(function() {
+ return fs.writeFile(filename, buf);
+ });
+ });
+ }, Q())
+ .value()
+ .then(function() {
+ return rootFolder;
+ });
+ });
+}
+
+// Setup a mock book for testing using a map of files
+function setupBook(files, opts) {
+ opts = opts || {};
+ opts.log = function() { };
+
+ return setupFS(files)
+ .then(function(folder) {
+ opts.fs = nodeFS;
+ opts.root = folder;
+
+ return new Book(opts);
+ });
+}
+
+// Setup a book with default README/SUMMARY
+function setupDefaultBook(files, summary, opts) {
+ var summaryContent = '# Summary \n\n' +
+ _.map(summary, function(article) {
+ return '* [' + article.title +'](' + article.path + ')';
+ })
+ .join('\n');
+
+ return setupBook(_.defaults(files || {}, {
+ 'README.md': 'Hello',
+ 'SUMMARY.md': summaryContent
+ }), opts);
+}
+
+// Output a book with a specific generator
+function outputDefaultBook(Output, files, summary, opts) {
+ return setupDefaultBook(files, summary, opts)
+ .then(function(book) {
+ // Parse the book
+ return book.parse()
+
+ // Start generation
+ .then(function() {
+ var output = new Output(book);
+ return output.generate()
+ .thenResolve(output);
+ });
+ });
+}
+
+// Output a book with a specific generator
+function outputBook(Output, files, opts) {
+ return setupBook(files, opts)
+ .then(function(book) {
+ // Parse the book
+ return book.parse()
+
+ // Start generation
+ .then(function() {
+ var output = new Output(book);
+ return output.generate()
+ .thenResolve(output);
+ });
+ });
+}
+
+// Log an error
+function logError(err) {
+ console.log(err.stack || err);
+}
+
+module.exports = {
+ fs: nodeFS,
+ setupFS: setupFS,
+ setupBook: setupBook,
+ outputBook: outputBook,
+ setupDefaultBook: setupDefaultBook,
+ outputDefaultBook: outputDefaultBook,
+ logError: logError
+};
diff --git a/test/navigation.js b/test/navigation.js
deleted file mode 100644
index 9118b3c..0000000
--- a/test/navigation.js
+++ /dev/null
@@ -1,61 +0,0 @@
-var should = require("should");
-
-describe("Navigation", function () {
- var book;
-
- before(function() {
- return books.parse("summary")
- .then(function(_book) {
- book = _book;
- });
- });
-
- it("should correctly parse navigation as a map", function() {
- book.should.have.property("navigation");
- book.navigation.should.have.property("README.md");
- book.navigation.should.have.property("README.md");
- });
-
- it("should correctly include filenames", function() {
- book.navigation.should.have.property("README.md");
- book.navigation.should.have.property("PAGE1.md");
- book.navigation.should.have.property("folder/PAGE2.md");
- book.navigation.should.not.have.property("NOTFOUND.md");
- });
-
- it("should correctly detect next/prev for README", function() {
- var README = book.navigation["README.md"];
-
- README.index.should.equal(0);
- README.should.have.property("next");
- should(README.prev).not.be.ok();
-
- README.next.should.have.property("path");
- README.next.path.should.equal("PAGE1.md");
- });
-
- it("should correctly detect next/prev a page", function() {
- var PAGE = book.navigation["PAGE1.md"];
-
- PAGE.index.should.equal(1);
- PAGE.should.have.property("next");
- PAGE.should.have.property("prev");
-
- PAGE.prev.should.have.property("path");
- PAGE.prev.path.should.equal("README.md");
-
- PAGE.next.should.have.property("path");
- PAGE.next.path.should.equal("folder/PAGE2.md");
- });
-
- it("should correctly detect next/prev for last page", function() {
- var PAGE = book.navigation["folder/PAGE2.md"];
-
- PAGE.index.should.equal(2);
- PAGE.should.have.property("prev");
- should(PAGE.next).not.be.ok();
-
- PAGE.prev.should.have.property("path");
- PAGE.prev.path.should.equal("PAGE1.md");
- });
-});
diff --git a/test/node_modules/gitbook-plugin-test-blocks/index.js b/test/node_modules/gitbook-plugin-test-blocks/index.js
new file mode 100644
index 0000000..7104006
--- /dev/null
+++ b/test/node_modules/gitbook-plugin-test-blocks/index.js
@@ -0,0 +1,21 @@
+var should = require('should');
+
+module.exports = {
+ blocks: {
+ // Simple test
+ hello: function(blk) {
+ return 'Hello ' + blk.body + '!';
+ },
+
+ // Test using the conetxt "this"
+ testContext: function(s) {
+ this.should.have.property('config');
+ this.should.have.property('log');
+ this.should.have.property('options');
+ this.should.have.property('resolve').which.is.a.function;
+ this.should.have.property('book').which.equal(this);
+
+ return 'Hello ' + s + '!';
+ }
+ }
+};
diff --git a/test/node_modules/gitbook-plugin-test-blocks/package.json b/test/node_modules/gitbook-plugin-test-blocks/package.json
new file mode 100644
index 0000000..a756fb5
--- /dev/null
+++ b/test/node_modules/gitbook-plugin-test-blocks/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "gitbook-plugin-test-blocks",
+ "version": "1.0.0",
+ "engines": {
+ "gitbook": "*"
+ }
+} \ No newline at end of file
diff --git a/test/plugins/config/index.js b/test/node_modules/gitbook-plugin-test-config/index.js
index f053ebf..f053ebf 100644
--- a/test/plugins/config/index.js
+++ b/test/node_modules/gitbook-plugin-test-config/index.js
diff --git a/test/node_modules/gitbook-plugin-test-config/package.json b/test/node_modules/gitbook-plugin-test-config/package.json
new file mode 100644
index 0000000..74bb953
--- /dev/null
+++ b/test/node_modules/gitbook-plugin-test-config/package.json
@@ -0,0 +1,21 @@
+{
+ "name": "gitbook-plugin-test-config",
+ "version": "1.0.0",
+ "engines": {
+ "gitbook": "*"
+ },
+ "gitbook": {
+ "properties": {
+ "myProperty": {
+ "type": "string",
+ "required": true,
+ "title": "This is a required property"
+ },
+ "myDefaultProperty": {
+ "type": "string",
+ "default": "hello",
+ "title": "This is a required property"
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/node_modules/gitbook-plugin-test-filters/index.js b/test/node_modules/gitbook-plugin-test-filters/index.js
new file mode 100644
index 0000000..71f2752
--- /dev/null
+++ b/test/node_modules/gitbook-plugin-test-filters/index.js
@@ -0,0 +1,21 @@
+var should = require('should');
+
+module.exports = {
+ filters: {
+ // Simple test
+ hello: function(s) {
+ return 'Hello ' + s + '!';
+ },
+
+ // Test using the conetxt "this"
+ testContext: function(s) {
+ this.should.have.property('config');
+ this.should.have.property('log');
+ this.should.have.property('options');
+ this.should.have.property('resolve').which.is.a.function;
+ this.should.have.property('book').which.equal(this);
+
+ return 'Hello ' + s + '!';
+ }
+ }
+};
diff --git a/test/node_modules/gitbook-plugin-test-filters/package.json b/test/node_modules/gitbook-plugin-test-filters/package.json
new file mode 100644
index 0000000..d555d06
--- /dev/null
+++ b/test/node_modules/gitbook-plugin-test-filters/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "gitbook-plugin-test-filters",
+ "version": "1.0.0",
+ "engines": {
+ "gitbook": "*"
+ }
+} \ No newline at end of file
diff --git a/test/node_modules/gitbook-plugin-test-hooks/index.js b/test/node_modules/gitbook-plugin-test-hooks/index.js
new file mode 100644
index 0000000..c0666ca
--- /dev/null
+++ b/test/node_modules/gitbook-plugin-test-hooks/index.js
@@ -0,0 +1,16 @@
+var should = require('should');
+
+module.exports = {
+ hooks: {
+ 'init': function() {
+ global._hooks = [];
+ global._hooks.push('init');
+ },
+ 'finish': function() {
+ global._hooks.push('finish');
+ },
+ 'finish:before': function() {
+ global._hooks.push('finish:before');
+ }
+ }
+};
diff --git a/test/node_modules/gitbook-plugin-test-hooks/package.json b/test/node_modules/gitbook-plugin-test-hooks/package.json
new file mode 100644
index 0000000..adb12a8
--- /dev/null
+++ b/test/node_modules/gitbook-plugin-test-hooks/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "gitbook-plugin-test-hooks",
+ "version": "1.0.0",
+ "engines": {
+ "gitbook": "*"
+ }
+} \ No newline at end of file
diff --git a/test/node_modules/gitbook-plugin-test-resources/index.js b/test/node_modules/gitbook-plugin-test-resources/index.js
new file mode 100644
index 0000000..e95e411
--- /dev/null
+++ b/test/node_modules/gitbook-plugin-test-resources/index.js
@@ -0,0 +1,12 @@
+module.exports = {
+ book: {
+ assets: './assets',
+ js: [
+ 'myfile.js',
+ 'https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js'
+ ],
+ css: [
+ 'myfile.css'
+ ]
+ }
+};
diff --git a/test/node_modules/gitbook-plugin-test-resources/package.json b/test/node_modules/gitbook-plugin-test-resources/package.json
new file mode 100644
index 0000000..606de31
--- /dev/null
+++ b/test/node_modules/gitbook-plugin-test-resources/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "gitbook-plugin-test-resources",
+ "version": "1.0.0",
+ "engines": {
+ "gitbook": "*"
+ }
+} \ No newline at end of file
diff --git a/test/output-ebook.js b/test/output-ebook.js
new file mode 100644
index 0000000..c43fc55
--- /dev/null
+++ b/test/output-ebook.js
@@ -0,0 +1,33 @@
+var mock = require('./mock');
+var EbookOutput = require('../lib/output/ebook');
+
+describe('Ebook Output', function() {
+ describe('Sample Book', function() {
+ var output;
+
+ before(function() {
+ return mock.outputDefaultBook(EbookOutput)
+ .then(function(_output) {
+ output = _output;
+ });
+ });
+
+ it('should correctly generate an index.html', function() {
+ output.should.have.file('index.html');
+ });
+
+ it('should correctly generate a SUMMARY.html', function() {
+ output.should.have.file('index.html');
+ });
+
+ it('should correctly copy assets', function() {
+ output.should.have.file('gitbook/ebook.css');
+ });
+
+ it('should correctly copy plugins', function() {
+ output.should.have.file('gitbook/gitbook-plugin-highlight/ebook.css');
+ });
+
+ });
+
+});
diff --git a/test/output-json.js b/test/output-json.js
new file mode 100644
index 0000000..1006dab
--- /dev/null
+++ b/test/output-json.js
@@ -0,0 +1,49 @@
+var mock = require('./mock');
+var JSONOutput = require('../lib/output/json');
+
+describe('JSON Output', function() {
+
+ describe('Sample book', function() {
+ var output;
+
+ before(function() {
+ return mock.outputDefaultBook(JSONOutput)
+ .then(function(_output) {
+ output = _output;
+ });
+ });
+
+ it('should correctly generate a README.json', function() {
+ output.should.have.file('README.json');
+ });
+
+ });
+
+ describe('Multilingual Book', function() {
+ var output;
+
+ before(function() {
+ return mock.outputBook(JSONOutput, {
+ 'LANGS.md': '# Languages\n\n'
+ + '* [en](./en)\n'
+ + '* [fr](./fr)\n\n',
+ 'en/README.md': '# Hello',
+ 'fr/README.md': '# Bonjour'
+
+ })
+ .then(function(_output) {
+ output = _output;
+ });
+ });
+
+ it('should correctly generate a README.json for each language', function() {
+ output.should.have.file('en/README.json');
+ output.should.have.file('fr/README.json');
+ });
+
+ it('should correctly generate a README.json for the whole book', function() {
+ output.should.have.file('README.json');
+ });
+ });
+});
+
diff --git a/test/output-website.js b/test/output-website.js
new file mode 100644
index 0000000..19459b3
--- /dev/null
+++ b/test/output-website.js
@@ -0,0 +1,99 @@
+var mock = require('./mock');
+var WebsiteOutput = require('../lib/output/website');
+
+describe('Website Output', function() {
+
+ describe('Sample Book', function() {
+ var output;
+
+ before(function() {
+ return mock.outputDefaultBook(WebsiteOutput)
+ .then(function(_output) {
+ output = _output;
+ });
+ });
+
+ it('should correctly generate an index.html', function() {
+ output.should.have.file('index.html');
+ });
+
+ it('should correctly copy assets', function() {
+ output.should.have.file('gitbook/app.js');
+ output.should.have.file('gitbook/images/favicon.ico');
+ });
+
+ it('should correctly copy plugins', function() {
+ output.should.have.file('gitbook/gitbook-plugin-highlight/website.css');
+ });
+ });
+
+ describe('Book with chapters', function() {
+ var output;
+
+ before(function() {
+ return mock.outputDefaultBook(WebsiteOutput, {
+ 'hello/README.md': '# Hello',
+ 'hello/test.md': '# Test'
+ }, [
+ {
+ title: 'Hello',
+ path: 'hello/README.md'
+ },
+ {
+ title: 'Test',
+ path: 'hello/test.md'
+ }
+ ])
+ .then(function(_output) {
+ output = _output;
+ });
+ });
+
+ it('should correctly generate an index.html', function() {
+ output.should.have.file('index.html');
+ });
+
+ it('should correctly generate files in folder', function() {
+ output.should.have.file('hello/index.html');
+ output.should.have.file('hello/test.html');
+ });
+ });
+
+ describe('Multilingual Book', function() {
+ var output;
+
+ before(function() {
+ return mock.outputBook(WebsiteOutput, {
+ 'LANGS.md': '# Languages\n\n'
+ + '* [en](./en)\n'
+ + '* [fr](./fr)\n\n',
+ 'en/README.md': '# Hello',
+ 'fr/README.md': '# Bonjour'
+
+ })
+ .then(function(_output) {
+ output = _output;
+ });
+ });
+
+ it('should correctly generate an index.html for each language', function() {
+ output.should.have.file('en/index.html');
+ output.should.have.file('fr/index.html');
+ });
+
+ it('should correctly copy assets', function() {
+ output.should.have.file('gitbook/app.js');
+ });
+
+ it('should not copy assets for each language', function() {
+ output.should.have.not.file('en/gitbook/app.js');
+ output.should.have.not.file('fr/gitbook/app.js');
+ });
+
+ it('should correctly generate an index.html', function() {
+ output.should.have.file('index.html');
+ });
+ });
+
+});
+
diff --git a/test/page.js b/test/page.js
new file mode 100644
index 0000000..ae36660
--- /dev/null
+++ b/test/page.js
@@ -0,0 +1,399 @@
+var mock = require('./mock');
+var Output = require('../lib/output/base');
+
+describe('Page', function() {
+ var book, output;
+
+ before(function() {
+ return mock.setupDefaultBook({
+ 'README.md': ' # Hello World\n\nThis is a description',
+ 'heading.md': '# Hello\n\n## World',
+ 'description.md': '# This is a title\n\nThis is the short description.\n\nNot this one.',
+ 'frontmatter.md': '---\ndescription: Hello World\n---\n\n# This is a title\n\nThis is not the description',
+
+ 'links.md': '[link](hello.md) [link 2](variables/page/next.md) [readme](README.md)',
+ 'links/relative.md': '[link](../hello.md) [link 2](/variables/page/next.md) [readme](../README.md)',
+
+ 'images.md': '![this is an image](test.png) ![this is an absolute image](/test2.png) ![this is a remote image](https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png)',
+ 'images/relative.md': '![this is an image](test.png) ![this is an absolute image](/test2.png)',
+
+ 'annotations/simple.md': 'A magicien say abracadabra!',
+ 'annotations/code.md': 'A magicien say `abracadabra`!',
+ 'annotations/class.md': 'A magicien say <div class="no-glossary"><b>abracadabra</b>, right?</div>!',
+
+ 'codes/simple.md': '```hello world```',
+ 'codes/lang.md': '```js\nhello world\n```',
+ 'codes/lang.adoc': '```js\nhello world\n```',
+
+ 'folder/paths.md': '',
+
+ 'variables/file/mtime.md': '{{ file.mtime }}',
+ 'variables/file/path.md': '{{ file.path }}',
+ 'variables/page/title.md': '{{ page.title }}',
+ 'variables/page/previous.md': '{{ page.previous.title }} {{ page.previous.path }}',
+ 'variables/page/next.md': '{{ page.next.title }} {{ page.next.path }}',
+ 'variables/page/dir/ltr.md': 'This is english: {{ page.dir }}',
+ 'variables/page/dir/rtl.md': 'بسيطة {{ page.dir }}',
+ 'variables/config/title.md': '{{ config.title}}',
+
+ 'GLOSSARY.md': '# Glossary\n\n\n## abracadabra\n\nthis is the description'
+ }, [
+ {
+ title: 'Test page.next',
+ path: 'variables/page/next.md'
+ },
+ {
+ title: 'Test Variables',
+ path: 'variables/page/title.md'
+ },
+ {
+ title: 'Test page.previous',
+ path: 'variables/page/previous.md'
+ }
+ ])
+ .then(function(_book) {
+ book = _book;
+ output = new Output(book);
+
+ return book.parse();
+ });
+ });
+
+ describe('.resolveLocal', function() {
+ it('should correctly resolve path to file', function() {
+ var page = book.addPage('heading.md');
+
+ page.resolveLocal('test.png').should.equal('test.png');
+ page.resolveLocal('/test.png').should.equal('test.png');
+ page.resolveLocal('test/hello.png').should.equal('test/hello.png');
+ page.resolveLocal('/test/hello.png').should.equal('test/hello.png');
+ });
+
+ it('should correctly resolve path to file (2)', function() {
+ var page = book.addPage('folder/paths.md');
+
+ page.resolveLocal('test.png').should.equal('folder/test.png');
+ page.resolveLocal('/test.png').should.equal('test.png');
+ page.resolveLocal('test/hello.png').should.equal('folder/test/hello.png');
+ page.resolveLocal('/test/hello.png').should.equal('test/hello.png');
+ });
+ });
+
+ describe('.relative', function() {
+ it('should correctly resolve absolute path in the book', function() {
+ var page = book.addPage('heading.md');
+ page.relative('/test.png').should.equal('test.png');
+ page.relative('test.png').should.equal('test.png');
+
+ var page2 = book.addPage('folder/paths.md');
+ page2.relative('/test.png').should.equal('../test.png');
+ page2.relative('test.png').should.equal('../test.png');
+ });
+ });
+
+ describe('.resolve', function() {
+ var page;
+
+ before(function() {
+ page = book.addPage('links/relative.md');
+ });
+
+ it('should resolve to a relative path (same folder)', function() {
+ page.relative('links/test.md').should.equal('test.md');
+ });
+
+ it('should resolve to a relative path (parent folder)', function() {
+ page.relative('test.md').should.equal('../test.md');
+ page.relative('hello/test.md').should.equal('../hello/test.md');
+ });
+
+ it('should resolve to a relative path (child folder)', function() {
+ page.relative('links/hello/test.md').should.equal('hello/test.md');
+ });
+ });
+
+ describe('Headings', function() {
+ it('should add a default ID to headings', function() {
+ var page = book.addPage('heading.md');
+
+ return page.toHTML(output)
+ .then(function() {
+ page.content.should.be.html({
+ 'h1#hello': {
+ count: 1
+ },
+ 'h2#world': {
+ count: 1
+ }
+ });
+ });
+ });
+ });
+
+ describe('Description', function() {
+ it('should extratc page description from content', function() {
+ var page = book.addPage('description.md');
+
+ return page.toHTML(output)
+ .then(function() {
+ page.description.should.equal('This is the short description.');
+ });
+ });
+ });
+
+ describe('Font-Matter', function() {
+ it('should extratc page description from front matter', function() {
+ var page = book.addPage('frontmatter.md');
+
+ return page.toHTML(output)
+ .then(function() {
+ page.description.should.equal('Hello World');
+ });
+ });
+ });
+
+ describe('Code Blocks', function() {
+ var page;
+
+ before(function() {
+ output.template.addBlock('code', function(blk) {
+ return (blk.kwargs.language || '') + blk.body + 'test';
+ });
+ });
+
+ it('should apply "code" block', function() {
+ page = book.addPage('codes/simple.md');
+ return page.toHTML(output)
+ .should.be.fulfilledWith('<p><code>hello worldtest</code></p>\n');
+ });
+
+ it('should add language as kwargs', function() {
+ page = book.addPage('codes/lang.md');
+ return page.toHTML(output)
+ .should.be.fulfilledWith('<pre><code class="lang-js">jshello world\ntest</code></pre>\n');
+ });
+
+ it('should add language as kwargs (asciidoc)', function() {
+ page = book.addPage('codes/lang.adoc');
+ return page.toHTML(output)
+ .should.be.fulfilledWith('<div class="listingblock">\n<div class="content">\n<pre class="highlight"><code class="language-js" data-lang="js">jshello worldtest</code></pre>\n</div>\n</div>');
+ });
+ });
+
+ describe('Links', function() {
+ describe('From base directory', function() {
+ var page;
+
+ before(function() {
+ page = book.addPage('links.md');
+ return page.toHTML(output);
+ });
+
+ it('should replace links to page to .html', function() {
+ page.content.should.be.html({
+ 'a[href="variables/page/next.html"]': {
+ count: 1
+ }
+ });
+ });
+
+ it('should use directory urls when file is a README', function() {
+ page.content.should.be.html({
+ 'a[href="./"]': {
+ count: 1
+ }
+ });
+ });
+
+ it('should not replace links to file not in SUMMARY', function() {
+ page.content.should.be.html({
+ 'a[href="hello.md"]': {
+ count: 1
+ }
+ });
+ });
+ });
+
+ describe('From sub-directory', function() {
+ var page;
+
+ before(function() {
+ page = book.addPage('links/relative.md');
+ return page.toHTML(output);
+ });
+
+ it('should replace links to page to .html', function() {
+ page.content.should.be.html({
+ 'a[href="../variables/page/next.html"]': {
+ count: 1
+ }
+ });
+ });
+
+ it('should use directory urls when file is a README', function() {
+ page.content.should.be.html({
+ 'a[href="../"]': {
+ count: 1
+ }
+ });
+ });
+
+ it('should not replace links to file not in SUMMARY', function() {
+ page.content.should.be.html({
+ 'a[href="../hello.md"]': {
+ count: 1
+ }
+ });
+ });
+ });
+ });
+
+ describe('Images', function() {
+ describe('From base directory', function() {
+ var page;
+
+ before(function() {
+ page = book.addPage('images.md');
+ return page.toHTML(output);
+ });
+
+ it('should resolve relative images', function() {
+ page.content.should.be.html({
+ 'img[src="test.png"]': {
+ count: 1
+ }
+ });
+ });
+
+ it('should resolve absolute images', function() {
+ page.content.should.be.html({
+ 'img[src="test2.png"]': {
+ count: 1
+ }
+ });
+ });
+
+ it('should keep external images path', function() {
+ page.content.should.be.html({
+ 'img[src="https:/upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png"]': {
+ count: 1
+ }
+ });
+ });
+ });
+
+ describe('From sub-directory', function() {
+ var page;
+
+ before(function() {
+ page = book.addPage('images/relative.md');
+ return page.toHTML(output);
+ });
+
+ it('should resolve relative images', function() {
+ page.content.should.be.html({
+ 'img[src="test.png"]': {
+ count: 1
+ }
+ });
+ });
+
+ it('should resolve absolute images', function() {
+ page.content.should.be.html({
+ 'img[src="../test2.png"]': {
+ count: 1
+ }
+ });
+ });
+ });
+ });
+
+ describe('Templating Context', function() {
+ it('should set file.mtime', function() {
+ var page = book.addPage('variables/file/mtime.md');
+ return page.toHTML(output)
+ .then(function(content) {
+ // A date ends with "(CET)" or "(UTC)""
+ content.should.endWith(')</p>\n');
+ });
+ });
+
+ it('should set file.path', function() {
+ var page = book.addPage('variables/file/path.md');
+ return page.toHTML(output)
+ .should.be.fulfilledWith('<p>variables/file/path.md</p>\n');
+ });
+
+ it('should set page.title when page is in summary', function() {
+ var page = book.getPage('variables/page/title.md');
+ return page.toHTML(output)
+ .should.be.fulfilledWith('<p>Test Variables</p>\n');
+ });
+
+ it('should set page.previous when possible', function() {
+ var page = book.getPage('variables/page/previous.md');
+ return page.toHTML(output)
+ .should.be.fulfilledWith('<p>Test Variables variables/page/title.md</p>\n');
+ });
+
+ it('should set page.next when possible', function() {
+ var page = book.getPage('variables/page/next.md');
+ return page.toHTML(output)
+ .should.be.fulfilledWith('<p>Test Variables variables/page/title.md</p>\n');
+ });
+
+ it('should set config.title', function() {
+ var page = book.addPage('variables/config/title.md');
+ return page.toHTML(output)
+ .should.be.fulfilledWith('<p>Hello World</p>\n');
+ });
+
+ describe('page.dir', function() {
+ it('should detect ltr', function() {
+ var page = book.addPage('variables/page/dir/ltr.md');
+ return page.toHTML(output)
+ .should.be.fulfilledWith('<p>This is english: ltr</p>\n');
+ });
+
+ it('should detect rtl', function() {
+ var page = book.addPage('variables/page/dir/rtl.md');
+ return page.toHTML(output)
+ .should.be.fulfilledWith('<p>&#x628;&#x633;&#x64A;&#x637;&#x629; rtl</p>\n');
+ });
+ });
+ });
+
+ describe('Annotations / Glossary', function() {
+ it('should replace glossary terms', function() {
+ return book.addPage('annotations/simple.md').toHTML(output)
+ .should.finally.be.html({
+ '.glossary-term': {
+ count: 1,
+ text: 'abracadabra',
+ attributes: {
+ title: 'this is the description',
+ href: '../GLOSSARY.html#abracadabra'
+ }
+ }
+ });
+ });
+
+ it('should not replace terms in code blocks', function() {
+ return book.addPage('annotations/code.md').toHTML(output)
+ .should.finally.be.html({
+ '.glossary-term': {
+ count: 0
+ }
+ });
+ });
+
+ it('should not replace terms in ".no-glossary"', function() {
+ return book.addPage('annotations/class.md').toHTML(output)
+ .should.finally.be.html({
+ '.glossary-term': {
+ count: 0
+ }
+ });
+ });
+ });
+});
diff --git a/test/parse.js b/test/parse.js
new file mode 100644
index 0000000..63565ee
--- /dev/null
+++ b/test/parse.js
@@ -0,0 +1,59 @@
+var mock = require('./mock');
+
+describe('Parsing', function() {
+ it('should not fail without SUMMARY', function() {
+ return mock.setupBook({
+ 'README.md': ''
+ })
+ .then(function(book) {
+ return book.parse().should.be.fulfilled();
+ });
+ });
+
+ it('should fail without README', function() {
+ return mock.setupBook({
+ 'SUMMARY.md': ''
+ })
+ .then(function(book) {
+ return book.parse().should.be.rejected;
+ });
+ });
+
+ it('should add GLOSSARY as a page', function() {
+ return mock.setupDefaultBook({
+ 'GLOSSARY.md': ''
+ })
+ .then(function(book) {
+ return book.parse()
+ .then(function() {
+ book.hasPage('GLOSSARY.md').should.equal(true);
+ });
+ });
+ });
+
+ describe('Multilingual book', function() {
+ var book;
+
+ before(function() {
+ return mock.setupBook({
+ 'LANGS.md': '# Languages\n\n'
+ + '* [English](./en)\n'
+ + '* [French](./fr)\n\n',
+ 'en/README.md': '# English',
+ 'en/SUMMARY.md': '# Summary',
+ 'fr/README.md': '# French',
+ 'fr/SUMMARY.md': '# Summary'
+ })
+ .then(function(_book) {
+ book = _book;
+ return book.parse();
+ });
+ });
+
+ it('should list language books', function() {
+ book.isMultilingual().should.equal(true);
+ book.books.should.have.lengthOf(2);
+ });
+ });
+});
+
diff --git a/test/paths.js b/test/paths.js
new file mode 100644
index 0000000..339da51
--- /dev/null
+++ b/test/paths.js
@@ -0,0 +1,17 @@
+var path = require('path');
+var pathUtils = require('../lib/utils/path');
+
+describe('Paths', function() {
+
+ describe('setExtension', function() {
+ it('should correctly change extension of filename', function() {
+ pathUtils.setExtension('test.md', '.html').should.be.equal('test.html');
+ pathUtils.setExtension('test.md', '.json').should.be.equal('test.json');
+ });
+
+ it('should correctly change extension of path', function() {
+ pathUtils.setExtension('hello/test.md', '.html').should.be.equal(path.normalize('hello/test.html'));
+ pathUtils.setExtension('hello/test.md', '.json').should.be.equal(path.normalize('hello/test.json'));
+ });
+ });
+});
diff --git a/test/plugins.js b/test/plugins.js
index 1600d0d..4d9cdf1 100644
--- a/test/plugins.js
+++ b/test/plugins.js
@@ -1,84 +1,103 @@
var _ = require('lodash');
-var fs = require('fs');
-var should = require('should');
var path = require('path');
-var Plugin = require('../lib/plugin');
-var parsers = require('gitbook-parsers');
-var PLUGINS_ROOT = path.resolve(__dirname, 'plugins');
+var mock = require('./mock');
+var registry = require('../lib/plugins/registry');
+var Output = require('../lib/output/base');
+var PluginsManager = require('../lib/plugins');
+var BookPlugin = require('../lib/plugins/plugin');
-describe('Plugins', function () {
+var PLUGINS_ROOT = path.resolve(__dirname, 'node_modules');
+
+describe('Plugins', function() {
var book;
before(function() {
- return books.parse('basic')
+ return mock.setupBook({})
.then(function(_book) {
book = _book;
});
});
- describe('Invalid', function() {
- var plugin;
-
- before(function() {
- plugin = new Plugin(book, 'invalid');
- plugin.load('./invalid', PLUGINS_ROOT);
- });
-
- it('should be detected', function() {
- should(plugin.isValid()).be.exactly(false);
+ describe('Resolve Version', function() {
+ it('should resolve a plugin version', function() {
+ return registry.resolve('ga')
+ .should.be.fulfilled();
});
});
- describe('Empty', function() {
- var plugin;
-
- before(function() {
- plugin = new Plugin(book, 'empty');
- plugin.load('./empty', PLUGINS_ROOT);
+ describe('Installation', function() {
+ it('should install a plugin from NPM without a specific version', function() {
+ return registry.install(book, 'ga')
+ .should.be.fulfilled();
});
- it('should valid a plugin', function() {
- should(plugin.isValid()).be.exactly(true);
+ it('should install a plugin from NPM with a specific version', function() {
+ return registry.install(book, 'ga', '1.0.0')
+ .should.be.fulfilled();
});
- it('should return an empty list of resources', function() {
- return plugin.getResources()
- .then(function(resources) {
- _.each(Plugin.RESOURCES, function(resName) {
- resources[resName].should.have.lengthOf(0);
- });
+ it('should correctly install all dependencies (if none)', function() {
+ return mock.setupBook({})
+ .then(function(book) {
+ var plugins = new PluginsManager(book);
+ return plugins.install()
+ .should.be.fulfilledWith(0);
});
});
- });
- describe('Configuration', function() {
- var plugin;
-
- before(function() {
- plugin = new Plugin(book, 'testconfig');
- plugin.load('./config', PLUGINS_ROOT);
- });
-
- it('should throw error for invalid configuration', function() {
- return plugin.validateConfig({})
- .should.be.rejectedWith('Configuration Error: pluginsConfig.testconfig.testRequired is required');
+ it('should correctly install all dependencies (if any)', function() {
+ return mock.setupBook({
+ 'book.json': {
+ plugins: ['ga']
+ }
+ })
+ .then(function(book) {
+ return book.config.load()
+ .then(function() {
+ var plugins = new PluginsManager(book);
+ return plugins.install();
+ });
+ })
+ .should.be.fulfilledWith(1);
});
+ });
- it('should throw error for invalid types', function() {
- return plugin.validateConfig({
- testRequired: 'hello'
- })
- .should.be.rejectedWith('Configuration Error: pluginsConfig.testconfig.testRequired is not of a type(s) number');
+ describe('Loading', function() {
+ it('should load default plugins', function() {
+ return mock.outputDefaultBook(Output)
+ .then(function(output) {
+ output.plugins.count().should.be.greaterThan(0);
+ });
});
+ });
- it('should extend with default values', function() {
- return plugin.validateConfig({
- testRequired: 12
+ describe('Configuration', function() {
+ it('should fail loading a plugin with an invalid configuration', function() {
+ var plugin = new BookPlugin(book, 'test-config');
+ return plugin.load(PLUGINS_ROOT)
+ .should.be.rejectedWith('Error with book\'s configuration: pluginsConfig.test-config.myProperty is required');
+ });
+
+ it('should extend configuration with default properties', function() {
+ return mock.setupBook({
+ 'book.json': {
+ pluginsConfig: {
+ 'test-config': {
+ 'myProperty': 'world'
+ }
+ }
+ }
})
- .should.be.fulfilledWith({
- hello: 'world',
- testRequired: 12
+ .then(function(book2) {
+ return book2.config.load()
+ .then(function() {
+ var plugin = new BookPlugin(book2, 'test-config');
+ return plugin.load(PLUGINS_ROOT);
+ })
+ .then(function() {
+ book2.config.get('pluginsConfig.test-config.myDefaultProperty', '').should.equal('hello');
+ });
});
});
});
@@ -87,243 +106,89 @@ describe('Plugins', function () {
var plugin;
before(function() {
- plugin = new Plugin(book, 'resources');
- plugin.load('./resources', PLUGINS_ROOT);
-
- return book.plugins.load(plugin);
- });
-
- it('should valid a plugin', function() {
- should(plugin.isValid()).be.exactly(true);
+ plugin = new BookPlugin(book, 'test-resources');
+ return plugin.load(PLUGINS_ROOT);
});
- describe('Website', function() {
- it('should return a valid list of resources', function() {
- return plugin.getResources('website')
- .then(function(resources) {
- resources.js.should.have.lengthOf(1);
- });
- });
- it('should extend books plugins', function() {
- var resources = book.plugins.resources('website');
- resources.js.should.have.lengthOf(5);
- });
- });
-
- describe('eBook', function() {
- it('should return a valid list of resources', function() {
- return plugin.getResources('ebook')
- .then(function(resources) {
- resources.css.should.have.lengthOf(1);
- });
- });
+ it('should list all resources for website', function() {
+ return plugin.getResources('website')
+ .then(function(resources) {
+ resources.assets.should.equal('./assets');
- it('should extend books plugins', function() {
- var resources = book.plugins.resources('ebook');
+ resources.js.should.have.lengthOf(2);
+ resources.js[0].path.should.equal('gitbook-plugin-test-resources/myfile.js');
+ resources.js[1].url.should.equal('https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js');
- // There is resources from highlight plugin and this plugin
- resources.css.should.have.lengthOf(2);
- should.exist(_.find(resources.css, {
- path: 'gitbook-plugin-resources/test'
- }));
+ resources.css.should.have.lengthOf(1);
+ resources.css[0].path.should.equal('gitbook-plugin-test-resources/myfile.css');
});
});
});
describe('Filters', function() {
- var plugin;
+ var plugin, filters;
before(function() {
- plugin = new Plugin(book, 'filters');
- plugin.load('./filters', PLUGINS_ROOT);
+ plugin = new BookPlugin(book, 'test-filters');
+ return plugin.load(PLUGINS_ROOT)
- return book.plugins.load(plugin);
- });
-
- it('should valid a plugin', function() {
- should(plugin.isValid()).be.exactly(true);
+ .then(function() {
+ filters = plugin.getFilters();
+ });
});
- it('should return a map of filters', function() {
- var filters = plugin.getFilters();
-
+ it('should list all filters', function() {
_.size(filters).should.equal(2);
- filters.should.have.property('hello');
- filters.should.have.property('helloCtx');
});
- it('should correctly extend template filters', function() {
- return book.template.renderString('{{ \'World\'|hello }}')
- .then(function(content) {
- content.should.equal('Hello World');
- });
+ it('should correctly execute a filter', function() {
+ filters.hello('World').should.equal('Hello World!');
});
- it('should correctly set book as context', function() {
- return book.template.renderString('{{ \'root\'|helloCtx }}')
- .then(function(content) {
- content.should.equal('root:'+book.root);
- });
+ it('should correctly set contexts for filter', function() {
+ filters.testContext('Hello');
});
});
describe('Blocks', function() {
- var plugin;
+ var plugin, blocks;
before(function() {
- plugin = new Plugin(book, 'blocks');
- plugin.load('./blocks', PLUGINS_ROOT);
-
- return book.plugins.load(plugin);
- });
-
- var testTpl = function(str, args, options) {
- return book.template.renderString(str, args, options)
- .then(book.template.postProcess);
- };
-
- it('should valid a plugin', function() {
- should(plugin.isValid()).be.exactly(true);
- });
+ plugin = new BookPlugin(book, 'test-blocks');
+ return plugin.load(PLUGINS_ROOT)
- it('should correctly extend template blocks', function() {
- return testTpl('{% test %}hello{% endtest %}')
- .then(function(content) {
- content.should.equal('testhellotest');
- });
- });
-
- describe('Shortcuts', function() {
- it('should correctly accept shortcuts', function() {
- return testTpl('$$hello$$', {}, {
- type: 'markdown'
- })
- .then(function(content) {
- content.should.equal('testhellotest');
- });
- });
-
- it('should correctly apply shortcuts to included file', function() {
- return books.generate('conrefs', 'website', {
- testId: 'include-plugins',
- prepare: function(bookConref) {
- plugin = new Plugin(bookConref, 'blocks');
- plugin.load('./blocks', PLUGINS_ROOT);
-
- return bookConref.plugins.load(plugin);
- }
- })
- .then(function(bookConref) {
- var readme = fs.readFileSync(
- path.join(bookConref.options.output, 'index.html'),
- { encoding: 'utf-8' }
- );
-
- readme.should.be.html({
- '.page-inner p#test-plugin-block-shortcuts-1': {
- count: 1,
- text: 'testtest_block1test',
- trim: true
- },
- '.page-inner p#test-plugin-block-shortcuts-2': {
- count: 1,
- text: 'testtest_block2test',
- trim: true
- }
- });
- });
+ .then(function() {
+ blocks = plugin.getBlocks();
});
});
-
- it('should correctly extend template blocks with defined end', function() {
- return testTpl('{% test2 %}hello{% endtest2end %}')
- .then(function(content) {
- content.should.equal('test2hellotest2');
- });
+ it('should list all blocks', function() {
+ _.size(blocks).should.equal(2);
});
- it('should correctly extend template blocks with sub-blocks', function() {
- return testTpl('{% test3join separator=";" %}hello{% also %}world{% endtest3join %}')
- .then(function(content) {
- content.should.equal('hello;world');
- });
+ it('should correctly normalize block', function() {
+ blocks.hello.process({ body: 'World' }).should.equal('Hello World!');
});
- it('should correctly extend template blocks with different sub-blocks', function() {
- return testTpl('{% test4join separator=";" %}hello{% also %}the{% finally %}world{% endtest4join %}')
- .then(function(content) {
- content.should.equal('hello;the;world');
- });
- });
-
- it('should correctly extend template blocks with arguments (1)', function() {
- return testTpl('{% test5args "a" %}{% endtest5args %}')
- .then(function(content) {
- content.should.equal('test5atest5');
- });
- });
-
- it('should correctly extend template blocks with arguments (2)', function() {
- return testTpl('{% test5args "a", "b" %}{% endtest5args %}')
- .then(function(content) {
- content.should.equal('test5a,btest5');
- });
- });
-
- it('should correctly extend template blocks with arguments (3)', function() {
- return testTpl('{% test5args "a", "b", "c" %}{% endtest5args %}')
- .then(function(content) {
- content.should.equal('test5a,b,ctest5');
- });
- });
-
- it('should correctly extend template blocks with args and kwargs', function() {
- return testTpl('{% test5kwargs "a", "b", "c", d="test", e="test2" %}{% endtest5kwargs %}')
- .then(function(content) {
- content.should.equal('test5a,b,c,d:test,e:test2,__keywords:truetest5');
- });
- });
-
- it('should correctly extend template blocks with access to context', function() {
- return testTpl('{% set name = "john" %}{% test6context %}{% endtest6context %}', {})
- .then(function(content) {
- content.should.equal('test6johntest6');
- });
+ it('should correctly set contexts for filter', function() {
+ blocks.testContext.process({ body: 'Hello' });
});
});
- describe('Blocks without parsing', function() {
+ describe('Hooks', function() {
var plugin;
before(function() {
- plugin = new Plugin(book, 'blocks');
- plugin.load('./blocks', PLUGINS_ROOT);
-
- return book.plugins.load(plugin);
+ plugin = new BookPlugin(book, 'test-hooks');
+ return plugin.load(PLUGINS_ROOT);
});
- var testTpl = function(markup, str, args, options) {
- var filetype = parsers.get(markup);
-
- return book.template.renderString(str, args, options)
- .then(filetype.page).get('sections').get(0).get('content')
- .then(book.template.postProcess);
- };
-
- it('should correctly process unparsable for markdown', function() {
- return testTpl('.md', '{% test %}**hello**{% endtest %}')
- .then(function(content) {
- content.should.equal('<p>test**hello**test</p>\n');
- });
- });
-
- it('should correctly process unparsable for asciidoc', function() {
- return testTpl('.adoc', '{% test %}**hello**{% endtest %}')
- .then(function(content) {
- content.should.equal('<div class="paragraph">\n<p>test**hello**test</p>\n</div>');
- });
+ it('can call a hook', function() {
+ return plugin.hook('init')
+ .then(function() {
+ global._hooks.should.deepEqual(['init']);
+ });
});
});
});
diff --git a/test/plugins/blocks/index.js b/test/plugins/blocks/index.js
deleted file mode 100644
index 9bdbe86..0000000
--- a/test/plugins/blocks/index.js
+++ /dev/null
@@ -1,61 +0,0 @@
-var assert = require("assert");
-
-module.exports = {
- blocks: {
- "test": {
- shortcuts: {
- parsers: ["markdown"],
- start: "$$",
- end: "$$"
- },
- process: function(blk) {
- return "test"+blk.body+"test";
- }
- },
- "test2": {
- end: "endtest2end",
- process: function(blk) {
- return "test2"+blk.body+"test2";
- }
- },
- "test3join": {
- blocks: [
- "also"
- ],
- process: function(blk) {
- return [blk.body, blk.blocks[0].body].join(blk.kwargs.separator);
- }
- },
- "test4join": {
- blocks: [
- "also", "finally"
- ],
- process: function(blk) {
- assert(blk.blocks.length, 2);
- assert(blk.blocks[0].name, "also");
- assert(blk.blocks[1].name, "finally");
- return [blk.body, blk.blocks[0].body, blk.blocks[1].body].join(blk.kwargs.separator);
- }
- },
- "test5args": {
- process: function(blk) {
- return "test5"+blk.args.join(",")+"test5";
- }
- },
- "test5kwargs": {
- process: function(blk) {
- var s = blk.args.join(",");
- for (var key in blk.kwargs) {
- s = s + ","+key+":"+blk.kwargs[key];
- }
-
- return "test5"+s+"test5";
- }
- },
- "test6context": {
- process: function() {
- return "test6"+(this.ctx.name)+"test6";
- }
- },
- }
-}; \ No newline at end of file
diff --git a/test/plugins/blocks/package.json b/test/plugins/blocks/package.json
deleted file mode 100644
index 7c41fd3..0000000
--- a/test/plugins/blocks/package.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "name": "gitbook-plugin-blocks",
- "description": "Test blocks",
- "main": "index.js",
- "version": "0.0.1",
- "engines": {
- "gitbook": "*"
- }
-} \ No newline at end of file
diff --git a/test/plugins/config/package.json b/test/plugins/config/package.json
deleted file mode 100644
index 03ef744..0000000
--- a/test/plugins/config/package.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
- "name": "gitbook-plugin-testconfig",
- "description": "Test plugin configuration",
- "main": "index.js",
- "version": "0.0.1",
- "engines": {
- "gitbook": "*"
- },
- "gitbook": {
- "properties": {
- "hello": {
- "type": "string",
- "default": "world"
- },
- "testRequired": {
- "type": "number",
- "required": true
- }
- }
- }
-} \ No newline at end of file
diff --git a/test/plugins/empty/index.js b/test/plugins/empty/index.js
deleted file mode 100644
index a099545..0000000
--- a/test/plugins/empty/index.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = {}; \ No newline at end of file
diff --git a/test/plugins/empty/package.json b/test/plugins/empty/package.json
deleted file mode 100644
index 78c7e72..0000000
--- a/test/plugins/empty/package.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "name": "gitbook-plugin-empty",
- "description": "Test empty plugin",
- "main": "index.js",
- "version": "0.0.1",
- "engines": {
- "gitbook": "*"
- }
-} \ No newline at end of file
diff --git a/test/plugins/filters/index.js b/test/plugins/filters/index.js
deleted file mode 100644
index 2cf53b1..0000000
--- a/test/plugins/filters/index.js
+++ /dev/null
@@ -1,10 +0,0 @@
-module.exports = {
- filters: {
- hello: function(text) {
- return "Hello "+text;
- },
- helloCtx: function(text) {
- return text+":"+this.book.root;
- }
- }
-}; \ No newline at end of file
diff --git a/test/plugins/filters/package.json b/test/plugins/filters/package.json
deleted file mode 100644
index f1d4e45..0000000
--- a/test/plugins/filters/package.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "name": "gitbook-plugin-filters",
- "description": "Test filters",
- "main": "index.js",
- "version": "0.0.1",
- "engines": {
- "gitbook": "*"
- }
-} \ No newline at end of file
diff --git a/test/plugins/invalid/index.js b/test/plugins/invalid/index.js
deleted file mode 100644
index a099545..0000000
--- a/test/plugins/invalid/index.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = {}; \ No newline at end of file
diff --git a/test/plugins/invalid/package.json b/test/plugins/invalid/package.json
deleted file mode 100644
index da34090..0000000
--- a/test/plugins/invalid/package.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "name": "gitbook-plugin-invalid",
- "description": "Test invalid plugin",
- "main": "index.js",
- "version": "0.0.1",
- "engines": {
- "gitbook": "<2.0.0"
- }
-} \ No newline at end of file
diff --git a/test/plugins/replace_highlight/index.js b/test/plugins/replace_highlight/index.js
deleted file mode 100644
index 8586486..0000000
--- a/test/plugins/replace_highlight/index.js
+++ /dev/null
@@ -1,14 +0,0 @@
-module.exports = {
- blocks: {
- "code": {
- process: function(blk) {
- var lang = blk.kwargs.language || "code";
-
- return {
- body: lang+"_"+blk.body+"_"+lang,
- html: false
- };
- }
- }
- }
-}; \ No newline at end of file
diff --git a/test/plugins/replace_highlight/package.json b/test/plugins/replace_highlight/package.json
deleted file mode 100644
index 72d1033..0000000
--- a/test/plugins/replace_highlight/package.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "name": "gitbook-plugin-replace_highlight",
- "description": "Test replacing default code highlighter",
- "main": "index.js",
- "version": "0.0.1",
- "engines": {
- "gitbook": "*"
- }
-} \ No newline at end of file
diff --git a/test/plugins/resources/index.js b/test/plugins/resources/index.js
deleted file mode 100644
index bafa54b..0000000
--- a/test/plugins/resources/index.js
+++ /dev/null
@@ -1,12 +0,0 @@
-module.exports = {
- website: {
- js: [
- "https://cdn.mathjax.org/mathjax/2.4-latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"
- ]
- },
- ebook: {
- css: [
- "test"
- ]
- }
-};
diff --git a/test/plugins/resources/package.json b/test/plugins/resources/package.json
deleted file mode 100644
index ab4320d..0000000
--- a/test/plugins/resources/package.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "name": "gitbook-plugin-resources",
- "description": "Test resources plugin",
- "main": "index.js",
- "version": "0.0.1",
- "engines": {
- "gitbook": "*"
- }
-} \ No newline at end of file
diff --git a/test/readme.js b/test/readme.js
new file mode 100644
index 0000000..0cf66ff
--- /dev/null
+++ b/test/readme.js
@@ -0,0 +1,43 @@
+var mock = require('./mock');
+
+describe('Readme', function() {
+ it('should parse empty readme', function() {
+ return mock.setupDefaultBook({
+ 'README.md': ''
+ })
+ .then(function(book) {
+ return book.config.load()
+
+ .then(function() {
+ return book.readme.load();
+ });
+ });
+ });
+
+ it('should parse readme', function() {
+ return mock.setupDefaultBook({
+ 'README.md': '# Hello World\nThis is my book'
+ })
+ .then(function(book) {
+ return book.readme.load()
+ .then(function() {
+ book.readme.title.should.equal('Hello World');
+ book.readme.description.should.equal('This is my book');
+ });
+ });
+ });
+
+ it('should parse AsciiDoc readme', function() {
+ return mock.setupBook({
+ 'README.adoc': '# Hello World\n\nThis is my book\n'
+ })
+ .then(function(book) {
+ return book.readme.load()
+ .then(function() {
+ book.readme.title.should.equal('Hello World');
+ book.readme.description.should.equal('This is my book');
+ });
+ });
+ });
+});
+
diff --git a/test/resolve.js b/test/resolve.js
deleted file mode 100644
index e474ed0..0000000
--- a/test/resolve.js
+++ /dev/null
@@ -1,60 +0,0 @@
-var path = require("path");
-
-describe("Resolve Files", function () {
- var book;
-
- before(function() {
- return books.parse("basic")
- .then(function(_book) {
- book = _book;
- });
- });
-
- describe("book.fileIsInBook", function() {
- it("should return true for correct paths", function() {
- book.fileIsInBook(path.join(book.root, "README.md")).should.equal(true);
- book.fileIsInBook(path.join(book.root, "styles/website.css")).should.equal(true);
- });
-
- it("should return true for root folder", function() {
- book.fileIsInBook(path.join(book.root, "./")).should.equal(true);
- book.fileIsInBook(book.root).should.equal(true);
- });
-
- it("should return false for files out of scope", function() {
- book.fileIsInBook(path.join(book.root, "../")).should.equal(false);
- book.fileIsInBook("README.md").should.equal(false);
- book.fileIsInBook(path.resolve(book.root, "../README.md")).should.equal(false);
- });
-
- it("should correctly handle windows paths", function() {
- book.fileIsInBook(path.join(book.root, "\\styles\\website.css")).should.equal(true);
- });
- });
-
- describe("book.resolve", function() {
- it("should resolve a file to its absolute path", function() {
- book.resolve("README.md").should.equal(path.resolve(book.root, "README.md"));
- book.resolve("website/README.md").should.equal(path.resolve(book.root, "website/README.md"));
- });
-
- it("should correctly handle windows paths", function() {
- book.resolve("styles\\website.css").should.equal(path.resolve(book.root, "styles\\website.css"));
- });
-
- it("should correctly resolve all arguments", function() {
- book.resolve("test", "hello", "..", "README.md").should.equal(path.resolve(book.root, "test/README.md"));
- });
-
- it("should correctly resolve to root folder", function() {
- book.resolve("test", "/README.md").should.equal(path.resolve(book.root, "README.md"));
- book.resolve("test", "\\README.md").should.equal(path.resolve(book.root, "README.md"));
- });
-
- it("should throw an error for file out of book", function() {
- (function() {
- return book.resolve("../README.md");
- }).should.throw();
- });
- });
-});
diff --git a/test/structure.js b/test/structure.js
deleted file mode 100644
index 90413cb..0000000
--- a/test/structure.js
+++ /dev/null
@@ -1,20 +0,0 @@
-describe('Structure', function () {
- var book;
-
- before(function() {
- return books.parse('structure')
- .then(function(_book) {
- book = _book;
- });
- });
-
-
- it('should prioritize structure defined in book.json', function() {
- book.readmeFile.should.equal('README.adoc');
- });
-
- it('should be case incensitive', function() {
- book.glossaryFile.should.equal('glossary.md');
- book.glossary.should.have.lengthOf(1);
- });
-});
diff --git a/test/summary.js b/test/summary.js
index 2d3a248..08b9db8 100644
--- a/test/summary.js
+++ b/test/summary.js
@@ -1,70 +1,300 @@
-var fs = require("fs");
-var path = require("path");
+var should = require('should');
-describe("Summary", function () {
- describe("Parsing", function() {
+var mock = require('./mock');
+
+function mockSummary(files, summary) {
+ return mock.setupDefaultBook(files, summary)
+ .then(function(book) {
+ return book.readme.load()
+ .then(function() {
+ return book.summary.load();
+ })
+ .thenResolve(book);
+ });
+}
+
+describe('Summary / Table of contents', function() {
+ describe('Empty summary list', function() {
var book;
before(function() {
- return books.parse("summary")
- .then(function(_book) {
- book = _book;
- });
+ return mockSummary({})
+ .then(function(_book) {
+ book = _book;
+ });
});
- it("should correctly list items", function() {
- book.should.have.property("summary");
- book.summary.should.have.property("chapters");
- book.summary.chapters.should.have.lengthOf(4);
+ it('should add README as first entry', function() {
+ should(book.summary.getArticle('README.md')).be.ok();
});
- it("should correctly mark non-existant entries", function() {
- book.summary.chapters[0].exists.should.have.equal(true);
- book.summary.chapters[1].exists.should.have.equal(true);
- book.summary.chapters[2].exists.should.have.equal(true);
- book.summary.chapters[3].exists.should.have.equal(false);
+ it('should correctly count articles', function() {
+ book.summary.count().should.equal(1);
});
});
- describe("Generation", function() {
+ describe('Non-existant summary', function() {
var book;
before(function() {
- return books.generate("summary", "website")
- .then(function(_book) {
- book = _book;
+ return mock.setupBook({
+ 'README.md': 'Hello'
+ })
+ .then(function(_book) {
+ book = _book;
+
+ return book.readme.load()
+ .then(function() {
+ return book.summary.load();
});
+ });
+ });
+
+ it('should add README as first entry', function() {
+ should(book.summary.getArticle('README.md')).be.ok();
+ });
+
+ it('should correctly count articles', function() {
+ book.summary.count().should.equal(1);
+ });
+ });
+
+ describe('Non-empty summary list', function() {
+ var book;
+
+ before(function() {
+ return mockSummary({
+ 'SUMMARY.md': '# Summary\n\n'
+ + '* [Hello](./hello.md)\n'
+ + '* [World](./world.md)\n\n'
+ })
+ .then(function(_book) {
+ book = _book;
+ });
+ });
+
+ it('should correctly count articles', function() {
+ book.summary.count().should.equal(3);
+ });
+ });
+
+ describe('Levels', function() {
+ var book;
+
+ before(function() {
+ return mockSummary({
+ 'SUMMARY.md': '# Summary\n\n'
+ + '* [Hello](./hello.md)\n'
+ + ' * [Hello 2](./hello2.md)\n'
+ + '* [World](./world.md)\n\n'
+ + '## Part 2\n\n'
+ + '* [Hello 3](./hello.md)\n'
+ + ' * [Hello 4](./hello2.md)\n'
+ })
+ .then(function(_book) {
+ book = _book;
+ });
});
- it("should create files according to summary", function() {
- book.should.have.file("index.html");
- book.should.have.file("PAGE1.html");
- book.should.have.file("folder/PAGE2.html");
- });
-
- it("should correctly output summary", function() {
- var PAGE = fs.readFileSync(
- path.join(book.options.output, "index.html"),
- { encoding: "utf-8" }
- );
-
- PAGE.should.be.html({
- ".book-summary .chapter[data-level=\"0\"] a": {
- attributes: {
- href: "./index.html"
- }
- },
- ".book-summary .chapter[data-level=\"1\"] a": {
- attributes: {
- href: "./PAGE1.html"
- }
- },
- ".book-summary .chapter[data-level=\"2\"] a": {
- attributes: {
- href: "./folder/PAGE2.html"
- }
+ it('should correctly index levels', function() {
+ book.summary.getArticleByLevel('0').title.should.equal('Introduction');
+ book.summary.getArticleByLevel('1.1').title.should.equal('Hello');
+ book.summary.getArticleByLevel('1.1.1').title.should.equal('Hello 2');
+ book.summary.getArticleByLevel('1.2').title.should.equal('World');
+
+ book.summary.getArticleByLevel('2.1').title.should.equal('Hello 3');
+ book.summary.getArticleByLevel('2.1.1').title.should.equal('Hello 4');
+ });
+
+ it('should correctly calcul depth', function() {
+ book.summary.getArticleByLevel('0').depth().should.equal(1);
+ book.summary.getArticleByLevel('1.1').depth().should.equal(2);
+ book.summary.getArticleByLevel('1.1.1').depth().should.equal(3);
+ });
+ });
+
+ describe('External', function() {
+ var book;
+
+ before(function() {
+ return mockSummary({}, [
+ {
+ title: 'Google',
+ path: 'https://www.google.fr'
}
+ ])
+ .then(function(_book) {
+ book = _book;
});
});
+
+ it('should correctly count articles', function() {
+ book.summary.count().should.equal(2);
+ });
+
+ it('should correctly signal it as external', function() {
+ var article = book.summary.getArticleByLevel('1');
+
+ should(article).be.ok();
+ should(article.path).not.be.ok();
+
+ article.title.should.equal('Google');
+ article.ref.should.equal('https://www.google.fr');
+ article.isExternal().should.be.ok;
+ });
+ });
+
+ describe('Next / Previous', function() {
+ var book;
+
+ before(function() {
+ return mockSummary({
+ 'SUMMARY.md': '# Summary\n\n' +
+ '* [Hello](hello.md)\n' +
+ '* [Hello 2](hello2.md)\n' +
+ ' * [Hello 3](hello3.md)\n' +
+ ' * [Hello 4](hello4.md)\n' +
+ ' * [Hello 5](hello5.md)\n' +
+ '* [Hello 6](hello6.md)\n\n\n' +
+ '### Part 2\n\n' +
+ '* [Hello 7](hello7.md)\n' +
+ ' * [Hello 8](hello8.md)\n\n' +
+ '### Part 3\n\n' +
+ '* [Hello 9](hello9.md)\n' +
+ '* [Hello 10](hello10.md)\n\n'
+ })
+ .then(function(_book) {
+ book = _book;
+ });
+ });
+
+ it('should only return a next for the readme', function() {
+ var article = book.summary.getArticle('README.md');
+
+ var prev = article.prev();
+ var next = article.next();
+
+ should(prev).not.be.ok();
+ should(next).be.ok();
+
+ next.path.should.equal('hello.md');
+ });
+
+ it('should return next/prev for a first level page', function() {
+ var article = book.summary.getArticle('hello.md');
+
+ var prev = article.prev();
+ var next = article.next();
+
+ should(prev).be.ok();
+ should(next).be.ok();
+
+ prev.path.should.equal('README.md');
+ next.path.should.equal('hello2.md');
+ });
+
+ it('should return next/prev for a joint -> child', function() {
+ var article = book.summary.getArticle('hello2.md');
+
+ var prev = article.prev();
+ var next = article.next();
+
+ should(prev).be.ok();
+ should(next).be.ok();
+
+ prev.path.should.equal('hello.md');
+ next.path.should.equal('hello3.md');
+ });
+
+ it('should return next/prev for a joint <- child', function() {
+ var article = book.summary.getArticle('hello3.md');
+
+ var prev = article.prev();
+ var next = article.next();
+
+ should(prev).be.ok();
+ should(next).be.ok();
+
+ prev.path.should.equal('hello2.md');
+ next.path.should.equal('hello4.md');
+ });
+
+ it('should return next/prev for a children', function() {
+ var article = book.summary.getArticle('hello4.md');
+
+ var prev = article.prev();
+ var next = article.next();
+
+ should(prev).be.ok();
+ should(next).be.ok();
+
+ prev.path.should.equal('hello3.md');
+ next.path.should.equal('hello5.md');
+ });
+
+ it('should return next/prev for a joint -> parent', function() {
+ var article = book.summary.getArticle('hello5.md');
+
+ var prev = article.prev();
+ var next = article.next();
+
+ should(prev).be.ok();
+ should(next).be.ok();
+
+ prev.path.should.equal('hello4.md');
+ next.path.should.equal('hello6.md');
+ });
+
+ it('should return next/prev for a joint -> parts', function() {
+ var article = book.summary.getArticle('hello6.md');
+
+ var prev = article.prev();
+ var next = article.next();
+
+ should(prev).be.ok();
+ should(next).be.ok();
+
+ prev.path.should.equal('hello5.md');
+ next.path.should.equal('hello7.md');
+ });
+
+ it('should return next/prev for a joint <- parts', function() {
+ var article = book.summary.getArticle('hello7.md');
+
+ var prev = article.prev();
+ var next = article.next();
+
+ should(prev).be.ok();
+ should(next).be.ok();
+
+ prev.path.should.equal('hello6.md');
+ next.path.should.equal('hello8.md');
+ });
+
+ it('should return next and prev', function() {
+ var article = book.summary.getArticle('hello8.md');
+
+ var prev = article.prev();
+ var next = article.next();
+
+ should(prev).be.ok();
+ should(next).be.ok();
+
+ prev.path.should.equal('hello7.md');
+ next.path.should.equal('hello9.md');
+ });
+
+ it('should return only prev for last', function() {
+ var article = book.summary.getArticle('hello10.md');
+
+ var prev = article.prev();
+ var next = article.next();
+
+ should(prev).be.ok();
+ should(next).be.not.ok();
+
+ prev.path.should.equal('hello9.md');
+ });
});
});
+
diff --git a/test/template.js b/test/template.js
new file mode 100644
index 0000000..6eb2278
--- /dev/null
+++ b/test/template.js
@@ -0,0 +1,54 @@
+var mock = require('./mock');
+var Output = require('../lib/output/base');
+
+describe('Template', function() {
+ var output;
+
+ before(function() {
+ return mock.outputDefaultBook(Output, {})
+ .then(function(_output) {
+ output = _output;
+ });
+ });
+
+ describe('.renderString', function() {
+ it('should render a simple string', function() {
+ return output.template.renderString('Hello World')
+ .should.be.fulfilledWith('Hello World');
+ });
+
+ it('should render with variable', function() {
+ return output.template.renderString('Hello {{ world }}', { world: 'World'})
+ .should.be.fulfilledWith('Hello World');
+ });
+ });
+
+ describe('Blocks', function() {
+ it('should correctly add a block', function() {
+ output.template.addBlock('sayhello', function(blk) {
+ return 'Hello ' + blk.body + '!';
+ });
+
+ return output.template.renderString('{% sayhello %}World{% endsayhello %}')
+ .should.be.fulfilledWith('Hello World!');
+ });
+
+ it('should correctly add a block with args', function() {
+ output.template.addBlock('sayhello_args', function(blk) {
+ return 'Hello ' + blk.args[0] + '!';
+ });
+
+ return output.template.renderString('{% sayhello_args "World" %}{% endsayhello_args %}')
+ .should.be.fulfilledWith('Hello World!');
+ });
+
+ it('should correctly add a block with kwargs', function() {
+ output.template.addBlock('sayhello_kwargs', function(blk) {
+ return 'Hello ' + blk.kwargs.name + '!';
+ });
+
+ return output.template.renderString('{% sayhello_kwargs name="World" %}{% endsayhello_kwargs %}')
+ .should.be.fulfilledWith('Hello World!');
+ });
+ });
+});
diff --git a/test/templating.js b/test/templating.js
deleted file mode 100644
index f92154b..0000000
--- a/test/templating.js
+++ /dev/null
@@ -1,33 +0,0 @@
-var pkg = require("../package.json");
-
-describe("Templating", function () {
- var book;
-
- before(function() {
- return books.parse("basic")
- .then(function(_book) {
- book = _book;
- });
- });
-
- var testTpl = function(str, args, options) {
- return book.template.renderString(str, args, options)
- .then(book.template.postProcess);
- };
-
- describe("Context", function() {
- it("should correctly have access to generator", function() {
- return testTpl("{{ gitbook.generator }}")
- .then(function(content) {
- content.should.equal("website");
- });
- });
-
- it("should correctly have access to gitbook version", function() {
- return testTpl("{{ gitbook.version }}")
- .then(function(content) {
- content.should.equal(pkg.version.toString());
- });
- });
- });
-});
diff --git a/test/website.js b/test/website.js
deleted file mode 100644
index 6a0fd1c..0000000
--- a/test/website.js
+++ /dev/null
@@ -1,26 +0,0 @@
-describe('Website generator', function () {
- describe('Basic Book', function() {
- var book;
-
- before(function() {
- return books.generate('basic', 'website')
- .then(function(_book) {
- book = _book;
- });
- });
-
- it('should correctly output an index.html', function() {
- book.should.have.file('index.html');
- });
-
- it('should correctly copy assets', function() {
- book.should.have.file('gitbook');
- book.should.have.file('gitbook/app.js');
- book.should.have.file('gitbook/style.css');
- });
-
- it('should not copy ebook assets', function() {
- book.should.not.have.file('gitbook/ebook.css');
- });
- });
-});