diff --git a/services/spelling/.eslintrc b/services/spelling/.eslintrc index dd8590b563..984a32e882 100644 --- a/services/spelling/.eslintrc +++ b/services/spelling/.eslintrc @@ -14,7 +14,12 @@ "chai-friendly" ], "env": { - "node": true + "node": true, + "mocha": true + }, + "globals": { + "expect": true, + "define": true }, "rules": { // Add some mocha specific rules diff --git a/services/spelling/app.js b/services/spelling/app.js index c9daa45d7e..30024dc230 100644 --- a/services/spelling/app.js +++ b/services/spelling/app.js @@ -34,25 +34,21 @@ server.get('/status', (req, res) => res.send({ status: 'spelling api is up' })) server.get('/health_check', HealthCheckController.healthCheck) -const host = - __guard__( - Settings.internal != null ? Settings.internal.spelling : undefined, - x => x.host - ) || 'localhost' -const port = - __guard__( - Settings.internal != null ? Settings.internal.spelling : undefined, - x1 => x1.port - ) || 3005 -server.listen(port, host, function(error) { - if (error != null) { - throw error - } - return logger.info(`spelling starting up, listening on ${host}:${port}`) -}) - -function __guard__(value, transform) { - return typeof value !== 'undefined' && value !== null - ? transform(value) +const settings = + Settings.internal && Settings.internal.spelling + ? Settings.internal.spelling : undefined +const host = settings && settings.host ? settings.host : 'localhost' +const port = settings && settings.port ? settings.port : 3005 + +if (!module.parent) { + // application entry point, called directly + server.listen(port, host, function(error) { + if (error != null) { + throw error + } + return logger.info(`spelling starting up, listening on ${host}:${port}`) + }) } + +module.exports = server diff --git a/services/spelling/test/acceptance/js/CheckTest.js b/services/spelling/test/acceptance/js/CheckTest.js new file mode 100644 index 0000000000..981d64b563 --- /dev/null +++ b/services/spelling/test/acceptance/js/CheckTest.js @@ -0,0 +1,81 @@ +const { expect } = require('chai') +const request = require('./helpers/request') + +const USER_ID = 101 + +const checkWord = words => + request.post({ + url: `/user/${USER_ID}/check`, + body: JSON.stringify({ + words + }) + }) + +describe('checking words', () => { + let response + + describe('on successful response', () => { + beforeEach(async () => { + response = await checkWord(['anather']) + }) + + it('should return status 200', async () => { + expect(response.statusCode).to.equal(200) + }) + + it('should return the list of misspellings', async () => { + const body = JSON.parse(response.body) + expect(body).to.deep.equal({ + misspellings: [{ index: 0, suggestions: ['anther', 'another'] }] + }) + }) + }) + + describe('when multiple words are submitted', () => { + beforeEach(async () => { + response = await checkWord(['anather', 'anather', 'theorie']) + }) + + it('should return the misspellings for all the words', async () => { + const body = JSON.parse(response.body) + expect(body.misspellings.length).to.equal(3) + }) + + it('should have misspelling suggestions with consecutive indexes', async () => { + const body = JSON.parse(response.body) + const indexes = body.misspellings.map(mspl => mspl.index) + expect(indexes).to.deep.equal([0, 1, 2]) + }) + + it('should return identical suggestions for the same entry', async () => { + const body = JSON.parse(response.body) + expect(body.misspellings[0].suggestions).to.deep.equal( + body.misspellings[1].suggestions + ) + }) + }) + + describe('when a very long list of words if submitted', () => { + beforeEach(async () => { + let words = [] + for (let i = 0; i <= 20000; i++) { + words.push('anather') + } + response = await checkWord(words) + }) + + it('should return misspellings for the first 10K results only', async () => { + const body = JSON.parse(response.body) + expect(body.misspellings.length).to.equal(10000) + }) + + it('should have misspelling suggestions with consecutive indexes', async () => { + const body = JSON.parse(response.body) + const indexList = body.misspellings.map(mspl => mspl.index) + expect(indexList.length).to.equal(10000) // avoid testing over an incorrect array + for (let i = 0; i < indexList.length - 1; i++) { + expect(indexList[i] + 1).to.equal(indexList[i + 1]) + } + }) + }) +}) diff --git a/services/spelling/test/acceptance/js/HealthCheckTest.js b/services/spelling/test/acceptance/js/HealthCheckTest.js new file mode 100644 index 0000000000..b4b3ef37b8 --- /dev/null +++ b/services/spelling/test/acceptance/js/HealthCheckTest.js @@ -0,0 +1,9 @@ +const { expect } = require('chai') +const request = require('./helpers/request') + +describe('/health_check', () => { + it('should return 200', async () => { + const response = await request.get('/health_check') + expect(response.statusCode).to.equal(200) + }) +}) diff --git a/services/spelling/test/acceptance/js/Init.js b/services/spelling/test/acceptance/js/Init.js new file mode 100644 index 0000000000..b3c281423b --- /dev/null +++ b/services/spelling/test/acceptance/js/Init.js @@ -0,0 +1,4 @@ +const App = require('../../../app.js') +const { PORT } = require('./helpers/request') + +before(done => App.listen(PORT, 'localhost', done)) diff --git a/services/spelling/test/acceptance/js/LearnTest.js b/services/spelling/test/acceptance/js/LearnTest.js new file mode 100644 index 0000000000..6f6bc21a2e --- /dev/null +++ b/services/spelling/test/acceptance/js/LearnTest.js @@ -0,0 +1,53 @@ +const { expect } = require('chai') +const request = require('./helpers/request') + +const USER_ID = 101 + +const checkWord = words => + request.post({ + url: `/user/${USER_ID}/check`, + body: JSON.stringify({ + words + }) + }) + +const learnWord = word => + request.post({ + url: `/user/${USER_ID}/learn`, + body: JSON.stringify({ + word + }) + }) + +const deleteDict = () => + request.del({ + url: `/user/${USER_ID}` + }) + +describe('learning words', () => { + it('should return status 200 when posting a word successfully', async () => { + const response = await learnWord('abcd') + expect(response.statusCode).to.equal(200) + }) + + it('should return no misspellings after a word is learnt', async () => { + const response = await checkWord(['abv']) + const responseBody = JSON.parse(response.body) + expect(responseBody.misspellings.length).to.equals(1) + + await learnWord('abv') + + const response2 = await checkWord(['abv']) + const responseBody2 = JSON.parse(response2.body) + expect(responseBody2.misspellings.length).to.equals(0) + }) + + it('should return misspellings again after a personal dictionary is deleted', async () => { + await learnWord('bvc') + await deleteDict() + + const response = await checkWord(['bvc']) + const responseBody = JSON.parse(response.body) + expect(responseBody.misspellings.length).to.equals(1) + }) +}) diff --git a/services/spelling/test/acceptance/js/StatusTest.js b/services/spelling/test/acceptance/js/StatusTest.js new file mode 100644 index 0000000000..bfed8033a2 --- /dev/null +++ b/services/spelling/test/acceptance/js/StatusTest.js @@ -0,0 +1,9 @@ +const { expect } = require('chai') +const request = require('./helpers/request') + +describe('/status', () => { + it('should return 200', async () => { + const response = await request.get('/health_check') + expect(response.statusCode).to.equal(200) + }) +}) diff --git a/services/spelling/test/acceptance/js/helpers/request.js b/services/spelling/test/acceptance/js/helpers/request.js new file mode 100644 index 0000000000..538e29f1b6 --- /dev/null +++ b/services/spelling/test/acceptance/js/helpers/request.js @@ -0,0 +1,21 @@ +const { promisify } = require('util') + +const PORT = 3005 + +const BASE_URL = `http://${process.env['HTTP_TEST_HOST'] || + 'localhost'}:${PORT}` + +const request = require('request').defaults({ + baseUrl: BASE_URL, + headers: { + 'Content-Type': 'application/json' + }, + followRedirect: false +}) + +module.exports = { + PORT, + get: promisify(request.get), + post: promisify(request.post), + del: promisify(request.del) +}