diff --git a/test/server/fixture/markdown.html b/server/fixture/markdown/markdown.html
similarity index 100%
rename from test/server/fixture/markdown.html
rename to server/fixture/markdown/markdown.html
diff --git a/test/server/fixture/markdown.md b/server/fixture/markdown/markdown.md
similarity index 100%
rename from test/server/fixture/markdown.md
rename to server/fixture/markdown/markdown.md
diff --git a/server/markdown.js b/server/markdown.js
index 8a512500..9d0efff9 100644
--- a/server/markdown.js
+++ b/server/markdown.js
@@ -2,63 +2,69 @@
const DIR_ROOT = __dirname + '/../';
const fs = require('fs');
+const {
+ callbackify,
+ promisify,
+} = require('util');
-const pullout = require('pullout');
+const pullout = promisify(require('pullout'));
const ponse = require('ponse');
const markdown = require('markdown-it')();
+const readFile = promisify(fs.readFile);
+
const root = require('./root');
-module.exports = (name, request, callback) => {
- check(name, request, callback);
+module.exports = callbackify(async (name, request) => {
+ check(name, request);
- const method = request.method;
- const query = ponse.getQuery(request);
+ const {method} = request;
switch(method) {
case 'GET':
- name = name.replace('/markdown', '');
-
- if (query === 'relative')
- name = DIR_ROOT + name;
- else
- name = root(name);
-
- fs.readFile(name, 'utf8', (error, data) => {
- if (error)
- return callback(error);
-
- parse(data, callback);
- });
- break;
-
+ return onGET(request, name);
+
case 'PUT':
- pullout(request, 'string', (error, data) => {
- if (error)
- return callback(error);
-
- parse(data, callback);
- });
- break;
+ return onPUT(request);
}
-};
+});
-function parse(data, callback) {
+function parseName(query, name) {
+ const shortName = name.replace('/markdown', '');
+
+ if (query === 'relative')
+ return DIR_ROOT + shortName;
+
+ return root(shortName);
+}
+
+async function onGET(request, name) {
+ const query = ponse.getQuery(request);
+ const fileName = parseName(query, name);
+ const data = await readFile(fileName, 'utf8');
+
+ return parse(data);
+}
+
+async function onPUT(request) {
+ const data = await pullout(request, 'string');
+
+ return parse(data);
+}
+
+const parse = promisify((data, callback) => {
process.nextTick(() => {
const md = markdown.render(data);
callback(null, md);
});
-}
+});
-function check(name, request, callback) {
+function check(name, request) {
if (typeof name !== 'string')
throw Error('name should be string!');
if (!request)
throw Error('request could not be empty!');
-
- if (typeof callback !== 'function')
- throw Error('callback should be function!');
}
diff --git a/server/markdown.spec.js b/server/markdown.spec.js
new file mode 100644
index 00000000..fa2f6852
--- /dev/null
+++ b/server/markdown.spec.js
@@ -0,0 +1,113 @@
+'use strict';
+
+const fs = require('fs');
+const path = require('path');
+const test = require('tape');
+const {promisify} = require('es6-promisify');
+const pullout = require('pullout');
+const request = require('request');
+const tryToCatch = require('try-to-catch');
+
+const markdown = require('./markdown');
+const before = require('../test/before');
+const {connect} = before;
+
+const _pullout = promisify(pullout);
+const _markdown = promisify(markdown);
+
+const fixtureDir = path.join(__dirname, 'fixture', 'markdown');
+
+const get = promisify((url, fn) => {
+ fn(null, request(url));
+});
+
+test('cloudcmd: markdown: error', async (t) => {
+ const {port, done} = await connect();
+
+ const [error, data] = await tryToCatch(get, `http://localhost:${port}/api/v1/markdown/not-found`)
+ const result = await _pullout(data, 'string');
+
+ await done();
+
+ t.notOk(error, 'should not be error');
+ t.ok(/ENOENT/.test(result), 'should not found');
+ t.end();
+});
+
+test('cloudcmd: markdown: relative: error', async (t) => {
+ const {port, done} = await connect();
+ const [e, data] = await tryToCatch(get, `http://localhost:${port}/api/v1/markdown/not-found?relative`)
+ const result = await _pullout(data, 'string');
+
+ await done();
+ t.ok(/ENOENT/.test(result), 'should not found');
+ t.end();
+});
+
+test('cloudcmd: markdown: relative', async (t) => {
+ const {port, done} = await connect();
+ const data = await get(`http://localhost:${port}/api/v1/markdown/HELP.md?relative`)
+ const result = await _pullout(data, 'string');
+
+ await done();
+
+ t.notOk(/ENOENT/.test(result), 'should not return error');
+ t.end();
+});
+
+test('cloudcmd: markdown: put', async (t) => {
+ const md = path.join(fixtureDir, 'markdown.md');
+ const html = path.join(fixtureDir, 'markdown.html');
+
+ const mdStream = fs.createReadStream(md);
+ const htmlFile = fs.readFileSync(html, 'utf8');
+
+ const {port, done} = await connect();
+ const url = `http://localhost:${port}/api/v1/markdown`;
+
+ const putStream = mdStream
+ .pipe(request.put(url));
+
+ const [error, result] = await tryToCatch(_pullout, putStream, 'string');
+
+ await done();
+
+ t.notOk(error, 'shoud not be error');
+ t.equal(result, htmlFile, 'should render markdown input to html');
+ t.end();
+});
+
+test('cloudcmd: markdown: put: error', (t) => {
+ const md = path.join(fixtureDir, 'markdown-not-exist.md');
+
+ const name = 'hello';
+ const mdStream = fs.createReadStream(md);
+
+ mdStream.url = 'http://hello.world';
+ mdStream.method = 'PUT';
+
+ _markdown(name, mdStream)
+ .then((result) => {
+ t.fail(`should fail but: ${result}`);
+ t.end();
+ })
+ .catch((error) => {
+ t.ok(error.message.includes('ENOENT: no such file or directory'), 'should emit error');
+ t.end();
+ });
+});
+
+test('cloudcmd: markdown: no name', async (t) => {
+ const [e] = await tryToCatch(_markdown);
+
+ t.equal(e.message, 'name should be string!', 'should throw when no name');
+ t.end();
+});
+
+test('cloudcmd: markdown: no request', async (t) => {
+ const [e] = await tryToCatch(_markdown, 'hello');
+
+ t.equal(e.message, 'request could not be empty!', 'should throw when no request');
+ t.end();
+});
+
diff --git a/test/server/markdown.js b/test/server/markdown.js
deleted file mode 100644
index 631e2bf3..00000000
--- a/test/server/markdown.js
+++ /dev/null
@@ -1,133 +0,0 @@
-'use strict';
-
-const fs = require('fs');
-const path = require('path');
-const test = require('tape');
-const {promisify} = require('es6-promisify');
-const pullout = require('pullout');
-const request = require('request');
-
-const markdown = require('../../server/markdown');
-
-const before = require('../before');
-
-const warp = (fn, ...a) => (...b) => fn(...b, ...a);
-const _pullout = promisify(pullout);
-const _markdown = promisify(markdown);
-
-const get = promisify((url, fn) => {
- fn(null, request(url));
-});
-
-test('cloudcmd: markdown: error', (t) => {
- before((port, after) => {
- get(`http://localhost:${port}/api/v1/markdown/not-found`)
- .then(warp(_pullout, 'string'))
- .then((result) => {
- t.ok(/ENOENT/.test(result), 'should not found');
- t.end();
- after();
- })
- .catch((error) => {
- console.log(error);
- });
- });
-});
-
-test('cloudcmd: markdown: relative: error', (t) => {
- before((port, after) => {
- get(`http://localhost:${port}/api/v1/markdown/not-found?relative`)
- .then(warp(_pullout, 'string'))
- .then((result) => {
- t.ok(/ENOENT/.test(result), 'should not found');
- t.end();
- after();
- })
- .catch((error) => {
- console.log(error);
- });
- });
-});
-
-test('cloudcmd: markdown: relative', (t) => {
- before((port, after) => {
- get(`http://localhost:${port}/api/v1/markdown/HELP.md?relative`)
- .then(warp(_pullout, 'string'))
- .then((result) => {
- t.notOk(/ENOENT/.test(result), 'should not return error');
- t.end();
- after();
- })
- .catch((error) => {
- console.log(error);
- });
- });
-});
-
-test('cloudcmd: markdown: put', (t) => {
- const dir = path.join(__dirname, 'fixture');
- const md = path.join(dir, 'markdown.md');
- const html = path.join(dir, 'markdown.html');
-
- const mdStream = fs.createReadStream(md);
- const htmlFile = fs.readFileSync(html, 'utf8');
-
- before((port, after) => {
- const url = `http://localhost:${port}/api/v1/markdown`;
-
- const putStream = mdStream
- .pipe(request.put(url));
-
- _pullout(putStream, 'string')
- .then((result) => {
- t.equal(result, htmlFile, 'should render markdown input to html');
- t.end();
- after();
- })
- .catch((error) => {
- t.fail(error.message);
- t.end();
- });
- });
-});
-
-test('cloudcmd: markdown: put: error', (t) => {
- const dir = path.join(__dirname, 'fixture');
- const md = path.join(dir, 'markdown-not-exist.md');
-
- const name = 'hello';
- const mdStream = fs.createReadStream(md);
-
- mdStream.url = 'http://hello.world';
- mdStream.method = 'PUT';
-
- _markdown(name, mdStream)
- .then((result) => {
- t.fail(`should fail but: ${result}`);
- t.end();
- })
- .catch((error) => {
- t.ok(error.message.includes('ENOENT: no such file or directory'), 'should emit error');
- t.end();
- });
-});
-
-test('cloudcmd: markdown: no name', (t) => {
- t.throws(markdown, /name should be string!/, 'should throw when no name');
- t.end();
-});
-
-test('cloudcmd: markdown: no request', (t) => {
- const fn = () => markdown('hello');
-
- t.throws(fn, /request could not be empty!/, 'should throw when no request');
- t.end();
-});
-
-test('cloudcmd: markdown: no function', (t) => {
- const fn = () => markdown('hello', {});
-
- t.throws(fn, /callback should be function!/, 'should throw when no callback');
- t.end();
-});
-