From f38d6221c6e5a527ba83381a47bdfc25cfe35fc4 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Fri, 19 Oct 2018 14:44:08 +0300 Subject: [PATCH] refactor(markdown) es2018-ify --- .../fixture/markdown}/markdown.html | 0 .../fixture/markdown}/markdown.md | 0 server/markdown.js | 74 +++++----- server/markdown.spec.js | 113 +++++++++++++++ test/server/markdown.js | 133 ------------------ 5 files changed, 153 insertions(+), 167 deletions(-) rename {test/server/fixture => server/fixture/markdown}/markdown.html (100%) rename {test/server/fixture => server/fixture/markdown}/markdown.md (100%) create mode 100644 server/markdown.spec.js delete mode 100644 test/server/markdown.js 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(); -}); -