From 3df43b4872faecf9731e8553f6ceb9fc56cdeb67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20GOUIN?= Date: Thu, 20 Jun 2019 14:18:49 +0200 Subject: [PATCH] Article rendering tests --- src/app.js | 38 ++++++++++++++-------- src/file_walker.js | 6 ++-- test/app.test.js | 69 ++++++++++++++++++++++++++++++++++++++++ test/file_walker.test.js | 32 +++++++++---------- 4 files changed, 112 insertions(+), 33 deletions(-) diff --git a/src/app.js b/src/app.js index 4b3d7bb..f7c2495 100644 --- a/src/app.js +++ b/src/app.js @@ -29,12 +29,13 @@ module.exports = (config) => { * @param callback */ const reload = (callback) => { - fw.fetchArticles((err, list) => { + fw.fetchArticles((err, dict) => { if (err) { callback(false); return console.error(cons.error, 'loading articles : ' + err); } - articles.splice(0, articles.length, ...list); + Object.keys(articles).forEach((key) => delete articles[key]); + Object.keys(dict).forEach((key) => articles[key] = dict[key]); const nb = Object.keys(articles).length; if (nb > 0) console.log(cons.ok, `loaded ${nb} article${nb > 1 ? 's' : ''}`); @@ -49,15 +50,15 @@ module.exports = (config) => { /** * Render the page with the view engine and catch errors * @param res - * @param path - path of the view + * @param vPath - path of the view * @param data - data to pass to the view * @param code - code to send along the page */ - const render = (res, path, data, code = 200) => { - res.render(path, data, (err, html) => { + const render = (res, vPath, data, code = 200) => { + res.render(vPath, data, (err, html) => { if (err) { res.sendStatus(500); - console.log(cons.error, `failed to render ${path} : ${err}`); + console.log(cons.error, `failed to render ${vPath} : ${err}`); } else res.status(code).send(html); }); @@ -92,21 +93,24 @@ module.exports = (config) => { // catch all article urls and render them app.get('*', (req, res, next) => { - if (req.path.test(/^\/\d{4}\/\d{2}\/\d{2}\/(\w*\/)?$/)) { - const articlePath = req.path.substr(0, 11); + if (/^\/\d{4}\/\d{2}\/\d{2}\/(\w*\/)?$/.test(req.path)) { + const articlePath = req.path.substr(1, 10); const article = articles[articlePath]; if (!article) showError(req.path, 404, res); else { - renderer.render(article.realPath, (err, html) => { - if (err) + renderer.render(path.join(article.realPath, config['article']['index']), (err, html) => { + if (err) { + console.log(cons.error, `failed to render article ${req.path} : ${err}`); return showError(req.path, 500, res); + } article.content = html; - const templatePath = path.join(config['data_dir'], config['home']['index']); + const templatePath = path.join(config['data_dir'], config['article']['template']); fs.access(templatePath, fs.constants.R_OK, (err) => { - if (err) - showError(req.path, 404, res); - else + if (err) { + console.log(cons.error, `no template found at ${templatePath}`); + showError(req.path, 500, res); + } else render(res, templatePath, {article: article}); }); }); @@ -136,6 +140,12 @@ module.exports = (config) => { res.status(400).send('bad request'); }); + app.use((err, req, res, next) => { + console.log(cons.error, `error when handling ${req.path} request : ${err}`); + console.error(err.stack); + next(err); + }); + // must be use in a server.js to start the server app.start = () => { reload((res) => { diff --git a/src/file_walker.js b/src/file_walker.js index ac30e12..d336b7d 100644 --- a/src/file_walker.js +++ b/src/file_walker.js @@ -75,7 +75,7 @@ module.exports = (config) => { .map((path) => path.match(/^\/(\d{4})\/(\d{2})\/(\d{2})\/$/)) .filter((matches) => matches && matches.length > 1); if (paths.length === 0) - cb(null, []); + cb(null, {}); const articles = {}; let remaining = 0; paths.forEach((matches) => { @@ -94,8 +94,8 @@ module.exports = (config) => { article.title = info.title || config['article']['default_title']; article.thumbnail = info.thumbnail ? path.join(article.path, info.thumbnail) : config['article']['default_thumbnail']; article.escapedTitle = article.title.toLowerCase().replace(/[^\w]/gm, ' ').trim().replace(/ /gm, '_'); - article.url = path.join(article.path, article.escapedTitle)+'/'; - articles[article.path]=article; + article.url = '/' + path.join(article.path, article.escapedTitle) + '/'; + articles[article.path] = article; remaining--; if (remaining === 0) cb(null, articles); diff --git a/test/app.test.js b/test/app.test.js index ae3b5de..ccc5953 100644 --- a/test/app.test.js +++ b/test/app.test.js @@ -7,6 +7,7 @@ const utils = require('./test_utils'); const dataDir = 'test_data'; const testIndex = 'testindex.ejs'; const testError = 'testerror.ejs'; +const testTemplate = 'testtemplate.ejs'; const config = { 'test': true, @@ -19,10 +20,12 @@ const config = { }, 'article': { 'index': 'index.md', + 'template' : testTemplate, 'thumbnail_tag': 'thumbnail', 'default_title': 'Untitled', 'default_thumbnail': null }, + 'showdown' : {} }; const app = require('../src/app')(config); @@ -83,6 +86,72 @@ describe('Test root path', () => { }); }); +describe('Test articles rendering', () => { + test('404 article not found', (done) =>{ + request(app).get('/2019/05/06/untitled/').then((response) =>{ + expect(response.statusCode).toBe(404); + done(); + }); + }); + + test('500 no template', (done) =>{ + utils.createEmptyDirs([path.join(dataDir, '2019', '05', '05'),]); + fs.writeFileSync(path.join(dataDir, '2019', '05', '05','index.md'), '# Hello'); + app.reload((res) => { + expect(res).toBe(true); + request(app).get('/2019/05/05/hello/').then((response) =>{ + expect(response.statusCode).toBe(500); + done(); + }); + }); + }); + + test('200 rendered article', (done) =>{ + utils.createEmptyDirs([path.join(dataDir, '2019', '05', '05'),]); + fs.writeFileSync(path.join(dataDir, '2019', '05', '05','index.md'), '# Hello'); + fs.writeFileSync(path.join(dataDir, testTemplate), '<%- article.content %><%- `reload` %>'); + app.reload((res) => { + expect(res).toBe(true); + request(app).get('/2019/05/05/hello/').then((response) =>{ + expect(response.statusCode).toBe(200); + expect(response.text).toBe('

Hello

reload'); + done(); + }); + }); + }); + + test('200 other url', (done) =>{ + utils.createEmptyDirs([path.join(dataDir, '2019', '05', '05'),]); + utils.createEmptyFiles([ + path.join(dataDir, '2019', '05', '05','index.md'), + path.join(dataDir, testTemplate) + ]); + app.reload((res) => { + expect(res).toBe(true); + request(app).get('/2019/05/05/anything/').then((response) =>{ + expect(response.statusCode).toBe(200); + done(); + }); + }); + }); + + test('200 other url 2', (done) =>{ + utils.createEmptyDirs([path.join(dataDir, '2019', '05', '05'),]); + utils.createEmptyFiles([ + path.join(dataDir, '2019', '05', '05','index.md'), + path.join(dataDir, testTemplate) + ]); + app.reload((res) => { + expect(res).toBe(true); + request(app).get('/2019/05/05/').then((response) =>{ + expect(response.statusCode).toBe(200); + done(); + }); + }); + }); +}); + + describe('Test static files', () => { test('404 invalid file no error page', (done) =>{ request(app).get('/somefile.txt').then((response) =>{ diff --git a/test/file_walker.test.js b/test/file_walker.test.js index 70abf86..a3e9cd5 100644 --- a/test/file_walker.test.js +++ b/test/file_walker.test.js @@ -191,10 +191,10 @@ describe('Test article fetching', () => { }); }); test('empty data dir', (done) => { - fw.fetchArticles((err, list) => { + fw.fetchArticles((err, dict) => { expect(err).toBeNull(); - expect(list).toBeDefined(); - expect(list.length).toBe(0); + expect(dict).toBeDefined(); + expect(Object.keys(dict).length).toBe(0); done(); }); }); @@ -208,10 +208,10 @@ describe('Test article fetching', () => { path.join(dataDir, 'test', 'test', testIndex), path.join(dataDir, '2019', '05', testIndex) ]); - fw.fetchArticles((err, list) => { + fw.fetchArticles((err, dict) => { expect(err).toBeNull(); - expect(list).toBeDefined(); - expect(list.length).toBe(0); + expect(dict).toBeDefined(); + expect(Object.keys(dict).length).toBe(0); done(); }); }); @@ -220,11 +220,11 @@ describe('Test article fetching', () => { const file = path.join(dir, testIndex); utils.createEmptyDirs([dir]); utils.createEmptyFiles([file]); - fw.fetchArticles((err, list) => { + fw.fetchArticles((err, dict) => { expect(err).toBeNull(); - expect(list).toBeDefined(); - expect(list.length).toBe(1); - expect(list[0]).toEqual({ + expect(dict).toBeDefined(); + expect(Object.keys(dict).length).toBe(1); + expect(dict[path.join('2019', '05', '05')]).toEqual({ path: path.join('2019', '05', '05'), realPath: dir, year: 2019, @@ -234,7 +234,7 @@ describe('Test article fetching', () => { title: 'Untitled', thumbnail: 'default.png', escapedTitle: 'untitled', - url: path.join('2019', '05', '05', 'untitled')+'/', + url: '/'+path.join('2019', '05', '05', 'untitled')+'/', }); done(); }); @@ -248,11 +248,11 @@ describe('Test article fetching', () => { ![thumbnail](./thumbnail.jpg) this is some text `); - fw.fetchArticles((err, list) => { + fw.fetchArticles((err, dict) => { expect(err).toBeNull(); - expect(list).toBeDefined(); - expect(list.length).toBe(1); - expect(list[0]).toEqual({ + expect(dict).toBeDefined(); + expect(Object.keys(dict).length).toBe(1); + expect(dict[path.join('2019', '05', '05')]).toEqual({ path: path.join('2019', '05', '05'), realPath: dir, year: 2019, @@ -262,7 +262,7 @@ describe('Test article fetching', () => { title: 'Title with : info !', thumbnail: path.join('2019', '05', '05', './thumbnail.jpg'), escapedTitle: 'title_with___info', - url: path.join('2019', '05', '05', 'title_with___info')+'/', + url: '/'+path.join('2019', '05', '05', 'title_with___info')+'/', }); done(); });