mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
[misc] run format_fix and lint:fix
This commit is contained in:
parent
95df66924a
commit
58eafb1583
20 changed files with 125 additions and 131 deletions
|
@ -55,7 +55,7 @@ if (!module.parent) {
|
||||||
return logger.info(`spelling starting up, listening on ${host}:${port}`)
|
return logger.info(`spelling starting up, listening on ${host}:${port}`)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch(err => {
|
||||||
logger.fatal({ err }, 'Cannot connect to mongo. Exiting.')
|
logger.fatal({ err }, 'Cannot connect to mongo. Exiting.')
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
})
|
})
|
||||||
|
|
|
@ -41,7 +41,7 @@ const cacheDump = setInterval(function () {
|
||||||
logger.log(OError.tag(err, 'error writing cache file'))
|
logger.log(OError.tag(err, 'error writing cache file'))
|
||||||
fs.unlink(cacheFsPathTmp, () => {})
|
fs.unlink(cacheFsPathTmp, () => {})
|
||||||
} else {
|
} else {
|
||||||
fs.rename(cacheFsPathTmp, cacheFsPath, (err) => {
|
fs.rename(cacheFsPathTmp, cacheFsPath, err => {
|
||||||
if (err) {
|
if (err) {
|
||||||
logger.error(OError.tag(err, 'error renaming cache file'))
|
logger.error(OError.tag(err, 'error renaming cache file'))
|
||||||
} else {
|
} else {
|
||||||
|
@ -100,7 +100,7 @@ class ASpellRunner {
|
||||||
{
|
{
|
||||||
hits,
|
hits,
|
||||||
total: words.length,
|
total: words.length,
|
||||||
hitrate: (hits / words.length).toFixed(2)
|
hitrate: (hits / words.length).toFixed(2),
|
||||||
},
|
},
|
||||||
'cache hit rate'
|
'cache hit rate'
|
||||||
)
|
)
|
||||||
|
@ -176,11 +176,11 @@ const ASpell = {
|
||||||
const runner = new ASpellRunner()
|
const runner = new ASpellRunner()
|
||||||
return runner.checkWords(language, words, callback)
|
return runner.checkWords(language, words, callback)
|
||||||
},
|
},
|
||||||
ASPELL_TIMEOUT: 10000
|
ASPELL_TIMEOUT: 10000,
|
||||||
}
|
}
|
||||||
|
|
||||||
const promises = {
|
const promises = {
|
||||||
checkWords: promisify(ASpell.checkWords)
|
checkWords: promisify(ASpell.checkWords),
|
||||||
}
|
}
|
||||||
|
|
||||||
ASpell.promises = promises
|
ASpell.promises = promises
|
||||||
|
|
|
@ -25,7 +25,7 @@ class ASpellWorker {
|
||||||
'-t',
|
'-t',
|
||||||
'--encoding=utf-8',
|
'--encoding=utf-8',
|
||||||
'-d',
|
'-d',
|
||||||
language
|
language,
|
||||||
])
|
])
|
||||||
logger.info(
|
logger.info(
|
||||||
{ process: this.pipe.pid, lang: this.language },
|
{ process: this.pipe.pid, lang: this.language },
|
||||||
|
@ -40,7 +40,7 @@ class ASpellWorker {
|
||||||
)
|
)
|
||||||
metrics.inc('aspellWorker', 1, {
|
metrics.inc('aspellWorker', 1, {
|
||||||
status: 'exit',
|
status: 'exit',
|
||||||
method: this.language
|
method: this.language,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
this.pipe.on('close', () => {
|
this.pipe.on('close', () => {
|
||||||
|
@ -58,14 +58,14 @@ class ASpellWorker {
|
||||||
stderr: error.slice(-1024),
|
stderr: error.slice(-1024),
|
||||||
workerState: this.state,
|
workerState: this.state,
|
||||||
previousWorkerState,
|
previousWorkerState,
|
||||||
closeReason: this.closeReason
|
closeReason: this.closeReason,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
this.callback(err, [])
|
this.callback(err, [])
|
||||||
this.callback = null
|
this.callback = null
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.pipe.on('error', (err) => {
|
this.pipe.on('error', err => {
|
||||||
const previousWorkerState = this.state
|
const previousWorkerState = this.state
|
||||||
if (this.state !== 'killed') {
|
if (this.state !== 'killed') {
|
||||||
this.state = 'error'
|
this.state = 'error'
|
||||||
|
@ -77,7 +77,7 @@ class ASpellWorker {
|
||||||
lang: this.language,
|
lang: this.language,
|
||||||
workerState: this.state,
|
workerState: this.state,
|
||||||
previousWorkerState,
|
previousWorkerState,
|
||||||
closeReason: this.closeReason
|
closeReason: this.closeReason,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (this.callback != null) {
|
if (this.callback != null) {
|
||||||
|
@ -87,7 +87,7 @@ class ASpellWorker {
|
||||||
logger.warn(err)
|
logger.warn(err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.pipe.stdin.on('error', (err) => {
|
this.pipe.stdin.on('error', err => {
|
||||||
const previousWorkerState = this.state
|
const previousWorkerState = this.state
|
||||||
if (this.state !== 'killed') {
|
if (this.state !== 'killed') {
|
||||||
this.state = 'error'
|
this.state = 'error'
|
||||||
|
@ -100,7 +100,7 @@ class ASpellWorker {
|
||||||
lang: this.language,
|
lang: this.language,
|
||||||
workerState: this.state,
|
workerState: this.state,
|
||||||
previousWorkerState,
|
previousWorkerState,
|
||||||
closeReason: this.closeReason
|
closeReason: this.closeReason,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (this.callback != null) {
|
if (this.callback != null) {
|
||||||
|
@ -114,7 +114,7 @@ class ASpellWorker {
|
||||||
this.pipe.stdout.setEncoding('utf8') // ensure utf8 output is handled correctly
|
this.pipe.stdout.setEncoding('utf8') // ensure utf8 output is handled correctly
|
||||||
var output = ''
|
var output = ''
|
||||||
const endMarkerRegex = new RegExp('^[a-z][a-z]', 'gm')
|
const endMarkerRegex = new RegExp('^[a-z][a-z]', 'gm')
|
||||||
this.pipe.stdout.on('data', (data) => {
|
this.pipe.stdout.on('data', data => {
|
||||||
// We receive the language code from Aspell as the end of data marker in
|
// We receive the language code from Aspell as the end of data marker in
|
||||||
// the data. The input is a utf8 encoded string.
|
// the data. The input is a utf8 encoded string.
|
||||||
const oldPos = output.length
|
const oldPos = output.length
|
||||||
|
@ -133,7 +133,7 @@ class ASpellWorker {
|
||||||
{
|
{
|
||||||
process: this.pipe.pid,
|
process: this.pipe.pid,
|
||||||
lang: this.language,
|
lang: this.language,
|
||||||
workerState: this.state
|
workerState: this.state,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -144,7 +144,7 @@ class ASpellWorker {
|
||||||
})
|
})
|
||||||
|
|
||||||
var error = ''
|
var error = ''
|
||||||
this.pipe.stderr.on('data', (chunk) => {
|
this.pipe.stderr.on('data', chunk => {
|
||||||
return (error = error + chunk)
|
return (error = error + chunk)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -168,7 +168,7 @@ class ASpellWorker {
|
||||||
new OError('Aspell callback already in use - SHOULD NOT HAPPEN', {
|
new OError('Aspell callback already in use - SHOULD NOT HAPPEN', {
|
||||||
process: this.pipe.pid,
|
process: this.pipe.pid,
|
||||||
lang: this.language,
|
lang: this.language,
|
||||||
workerState: this.state
|
workerState: this.state,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,9 +56,7 @@ class ASpellWorkerPool {
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
const active = this.PROCESS_POOL.filter(
|
const active = this.PROCESS_POOL.filter(worker => worker.state !== 'killed')
|
||||||
(worker) => worker.state !== 'killed'
|
|
||||||
)
|
|
||||||
this.PROCESS_POOL = active
|
this.PROCESS_POOL = active
|
||||||
return metrics.gauge('aspellWorkerPool-size', this.PROCESS_POOL.length)
|
return metrics.gauge('aspellWorkerPool-size', this.PROCESS_POOL.length)
|
||||||
}
|
}
|
||||||
|
@ -68,7 +66,7 @@ class ASpellWorkerPool {
|
||||||
let worker
|
let worker
|
||||||
const availableWorker = _.find(
|
const availableWorker = _.find(
|
||||||
this.PROCESS_POOL,
|
this.PROCESS_POOL,
|
||||||
(cached) => cached.language === language && cached.isReady()
|
cached => cached.language === language && cached.isReady()
|
||||||
)
|
)
|
||||||
if (availableWorker == null) {
|
if (availableWorker == null) {
|
||||||
worker = this.create(language)
|
worker = this.create(language)
|
||||||
|
|
|
@ -9,9 +9,9 @@ module.exports = {
|
||||||
url: `http://localhost:3005/user/${settings.healthCheckUserId}/check`,
|
url: `http://localhost:3005/user/${settings.healthCheckUserId}/check`,
|
||||||
json: {
|
json: {
|
||||||
words: ['helllo'],
|
words: ['helllo'],
|
||||||
language: 'en'
|
language: 'en',
|
||||||
},
|
},
|
||||||
timeout: 1000 * 20
|
timeout: 1000 * 20,
|
||||||
}
|
}
|
||||||
return request.post(opts, function (err, response, body) {
|
return request.post(opts, function (err, response, body) {
|
||||||
if (err != null) {
|
if (err != null) {
|
||||||
|
@ -35,5 +35,5 @@ module.exports = {
|
||||||
res.sendStatus(500)
|
res.sendStatus(500)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,13 +13,13 @@ const LearnedWordsManager = {
|
||||||
mongoCache.del(userToken)
|
mongoCache.del(userToken)
|
||||||
return db.spellingPreferences.updateOne(
|
return db.spellingPreferences.updateOne(
|
||||||
{
|
{
|
||||||
token: userToken
|
token: userToken,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
$addToSet: { learnedWords: word }
|
$addToSet: { learnedWords: word },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
upsert: true
|
upsert: true,
|
||||||
},
|
},
|
||||||
callback
|
callback
|
||||||
)
|
)
|
||||||
|
@ -32,10 +32,10 @@ const LearnedWordsManager = {
|
||||||
mongoCache.del(userToken)
|
mongoCache.del(userToken)
|
||||||
return db.spellingPreferences.updateOne(
|
return db.spellingPreferences.updateOne(
|
||||||
{
|
{
|
||||||
token: userToken
|
token: userToken,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
$pull: { learnedWords: word }
|
$pull: { learnedWords: word },
|
||||||
},
|
},
|
||||||
callback
|
callback
|
||||||
)
|
)
|
||||||
|
@ -54,24 +54,24 @@ const LearnedWordsManager = {
|
||||||
metrics.inc('mongoCache', 0.1, { status: 'miss' })
|
metrics.inc('mongoCache', 0.1, { status: 'miss' })
|
||||||
logger.info({ userToken }, 'mongoCache miss')
|
logger.info({ userToken }, 'mongoCache miss')
|
||||||
|
|
||||||
db.spellingPreferences.findOne({ token: userToken }, function (
|
db.spellingPreferences.findOne(
|
||||||
error,
|
{ token: userToken },
|
||||||
preferences
|
function (error, preferences) {
|
||||||
) {
|
if (error != null) {
|
||||||
if (error != null) {
|
return callback(OError.tag(error))
|
||||||
return callback(OError.tag(error))
|
}
|
||||||
|
let words =
|
||||||
|
(preferences != null ? preferences.learnedWords : undefined) || []
|
||||||
|
if (words) {
|
||||||
|
// remove duplicates
|
||||||
|
words = words.filter(
|
||||||
|
(value, index, self) => self.indexOf(value) === index
|
||||||
|
)
|
||||||
|
}
|
||||||
|
mongoCache.set(userToken, words)
|
||||||
|
callback(null, words)
|
||||||
}
|
}
|
||||||
let words =
|
)
|
||||||
(preferences != null ? preferences.learnedWords : undefined) || []
|
|
||||||
if (words) {
|
|
||||||
// remove duplicates
|
|
||||||
words = words.filter(
|
|
||||||
(value, index, self) => self.indexOf(value) === index
|
|
||||||
)
|
|
||||||
}
|
|
||||||
mongoCache.set(userToken, words)
|
|
||||||
callback(null, words)
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
|
|
||||||
deleteUsersLearnedWords(userToken, callback) {
|
deleteUsersLearnedWords(userToken, callback) {
|
||||||
|
@ -79,7 +79,7 @@ const LearnedWordsManager = {
|
||||||
callback = () => {}
|
callback = () => {}
|
||||||
}
|
}
|
||||||
db.spellingPreferences.deleteOne({ token: userToken }, callback)
|
db.spellingPreferences.deleteOne({ token: userToken }, callback)
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const promises = {
|
const promises = {
|
||||||
|
@ -88,13 +88,13 @@ const promises = {
|
||||||
getLearnedWords: promisify(LearnedWordsManager.getLearnedWords),
|
getLearnedWords: promisify(LearnedWordsManager.getLearnedWords),
|
||||||
deleteUsersLearnedWords: promisify(
|
deleteUsersLearnedWords: promisify(
|
||||||
LearnedWordsManager.deleteUsersLearnedWords
|
LearnedWordsManager.deleteUsersLearnedWords
|
||||||
)
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
LearnedWordsManager.promises = promises
|
LearnedWordsManager.promises = promises
|
||||||
|
|
||||||
module.exports = LearnedWordsManager
|
module.exports = LearnedWordsManager
|
||||||
;['learnWord', 'unlearnWord', 'getLearnedWords'].map((method) =>
|
;['learnWord', 'unlearnWord', 'getLearnedWords'].map(method =>
|
||||||
metrics.timeAsyncMethod(
|
metrics.timeAsyncMethod(
|
||||||
LearnedWordsManager,
|
LearnedWordsManager,
|
||||||
method,
|
method,
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
const LRU = require('lru-cache')
|
const LRU = require('lru-cache')
|
||||||
const cacheOpts = {
|
const cacheOpts = {
|
||||||
max: 15000,
|
max: 15000,
|
||||||
maxAge: 1000 * 60 * 60 * 10
|
maxAge: 1000 * 60 * 60 * 10,
|
||||||
}
|
}
|
||||||
|
|
||||||
const cache = new LRU(cacheOpts)
|
const cache = new LRU(cacheOpts)
|
||||||
|
|
|
@ -26,7 +26,7 @@ module.exports = {
|
||||||
logger.error(
|
logger.error(
|
||||||
OError.tag(error, 'error processing spelling request', {
|
OError.tag(error, 'error processing spelling request', {
|
||||||
user_id: token,
|
user_id: token,
|
||||||
wordCount
|
wordCount,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
return res.sendStatus(500)
|
return res.sendStatus(500)
|
||||||
|
@ -74,7 +74,7 @@ module.exports = {
|
||||||
const token = req.params ? req.params.user_id : undefined
|
const token = req.params ? req.params.user_id : undefined
|
||||||
logger.info(
|
logger.info(
|
||||||
{
|
{
|
||||||
token
|
token,
|
||||||
},
|
},
|
||||||
'getting user dictionary'
|
'getting user dictionary'
|
||||||
)
|
)
|
||||||
|
@ -84,5 +84,5 @@ module.exports = {
|
||||||
}
|
}
|
||||||
res.send(words)
|
res.send(words)
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ const SpellingAPIManager = {
|
||||||
|
|
||||||
getDic(token, callback) {
|
getDic(token, callback) {
|
||||||
return LearnedWordsManager.getLearnedWords(token, callback)
|
return LearnedWordsManager.getLearnedWords(token, callback)
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const promises = {
|
const promises = {
|
||||||
|
@ -71,7 +71,7 @@ const promises = {
|
||||||
const learnedWords = await LearnedWordsManager.promises.getLearnedWords(
|
const learnedWords = await LearnedWordsManager.promises.getLearnedWords(
|
||||||
token
|
token
|
||||||
)
|
)
|
||||||
const notLearntMisspellings = misspellings.filter((m) => {
|
const notLearntMisspellings = misspellings.filter(m => {
|
||||||
const word = wordSlice[m.index]
|
const word = wordSlice[m.index]
|
||||||
return (
|
return (
|
||||||
learnedWords.indexOf(word) === -1 &&
|
learnedWords.indexOf(word) === -1 &&
|
||||||
|
@ -82,7 +82,7 @@ const promises = {
|
||||||
} else {
|
} else {
|
||||||
return { misspellings }
|
return { misspellings }
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
SpellingAPIManager.runRequest = callbackify(promises.runRequest)
|
SpellingAPIManager.runRequest = callbackify(promises.runRequest)
|
||||||
|
|
|
@ -24,5 +24,5 @@ async function setupDb() {
|
||||||
module.exports = {
|
module.exports = {
|
||||||
db,
|
db,
|
||||||
ObjectId,
|
ObjectId,
|
||||||
waitForDb
|
waitForDb,
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,18 +4,18 @@ module.exports = {
|
||||||
internal: {
|
internal: {
|
||||||
spelling: {
|
spelling: {
|
||||||
port: 3005,
|
port: 3005,
|
||||||
host: process.env.LISTEN_ADDRESS || 'localhost'
|
host: process.env.LISTEN_ADDRESS || 'localhost',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
mongo: {
|
mongo: {
|
||||||
options: {
|
options: {
|
||||||
useUnifiedTopology:
|
useUnifiedTopology:
|
||||||
(process.env.MONGO_USE_UNIFIED_TOPOLOGY || 'true') === 'true'
|
(process.env.MONGO_USE_UNIFIED_TOPOLOGY || 'true') === 'true',
|
||||||
},
|
},
|
||||||
url:
|
url:
|
||||||
process.env.MONGO_CONNECTION_STRING ||
|
process.env.MONGO_CONNECTION_STRING ||
|
||||||
`mongodb://${process.env.MONGO_HOST || 'localhost'}/sharelatex`
|
`mongodb://${process.env.MONGO_HOST || 'localhost'}/sharelatex`,
|
||||||
},
|
},
|
||||||
|
|
||||||
cacheDir: Path.resolve('cache'),
|
cacheDir: Path.resolve('cache'),
|
||||||
|
@ -32,10 +32,10 @@ module.exports = {
|
||||||
'LaTeX',
|
'LaTeX',
|
||||||
'http',
|
'http',
|
||||||
'https',
|
'https',
|
||||||
'www'
|
'www',
|
||||||
],
|
],
|
||||||
|
|
||||||
sentry: {
|
sentry: {
|
||||||
dsn: process.env.SENTRY_DSN
|
dsn: process.env.SENTRY_DSN,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,8 @@ const checkWord = (words, language) =>
|
||||||
url: `/user/${USER_ID}/check`,
|
url: `/user/${USER_ID}/check`,
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
words,
|
words,
|
||||||
language
|
language,
|
||||||
})
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('checking words', function () {
|
describe('checking words', function () {
|
||||||
|
@ -27,7 +27,7 @@ describe('checking words', function () {
|
||||||
it('should return the list of misspellings', async function () {
|
it('should return the list of misspellings', async function () {
|
||||||
const body = JSON.parse(response.body)
|
const body = JSON.parse(response.body)
|
||||||
expect(body).to.deep.equal({
|
expect(body).to.deep.equal({
|
||||||
misspellings: [{ index: 0, suggestions: ['anther', 'another'] }]
|
misspellings: [{ index: 0, suggestions: ['anther', 'another'] }],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -44,7 +44,7 @@ describe('checking words', function () {
|
||||||
|
|
||||||
it('should have misspelling suggestions with consecutive indexes', async function () {
|
it('should have misspelling suggestions with consecutive indexes', async function () {
|
||||||
const body = JSON.parse(response.body)
|
const body = JSON.parse(response.body)
|
||||||
const indexes = body.misspellings.map((mspl) => mspl.index)
|
const indexes = body.misspellings.map(mspl => mspl.index)
|
||||||
expect(indexes).to.deep.equal([0, 1, 2])
|
expect(indexes).to.deep.equal([0, 1, 2])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ describe('checking words', function () {
|
||||||
|
|
||||||
it('should have misspelling suggestions with consecutive indexes', async function () {
|
it('should have misspelling suggestions with consecutive indexes', async function () {
|
||||||
const body = JSON.parse(response.body)
|
const body = JSON.parse(response.body)
|
||||||
const indexList = body.misspellings.map((mspl) => mspl.index)
|
const indexList = body.misspellings.map(mspl => mspl.index)
|
||||||
expect(indexList.length).to.equal(10000) // avoid testing over an incorrect array
|
expect(indexList.length).to.equal(10000) // avoid testing over an incorrect array
|
||||||
for (let i = 0; i < indexList.length - 1; i++) {
|
for (let i = 0; i < indexList.length - 1; i++) {
|
||||||
expect(indexList[i] + 1).to.equal(indexList[i + 1])
|
expect(indexList[i] + 1).to.equal(indexList[i + 1])
|
||||||
|
@ -96,7 +96,7 @@ describe('checking words', function () {
|
||||||
|
|
||||||
it('should have misspelling suggestions with consecutive indexes', async function () {
|
it('should have misspelling suggestions with consecutive indexes', async function () {
|
||||||
const body = JSON.parse(response.body)
|
const body = JSON.parse(response.body)
|
||||||
const indexList = body.misspellings.map((mspl) => mspl.index)
|
const indexList = body.misspellings.map(mspl => mspl.index)
|
||||||
expect(indexList.length).to.equal(10000) // avoid testing over an incorrect array
|
expect(indexList.length).to.equal(10000) // avoid testing over an incorrect array
|
||||||
for (let i = 0; i < indexList.length - 1; i++) {
|
for (let i = 0; i < indexList.length - 1; i++) {
|
||||||
expect(indexList[i] + 1).to.equal(indexList[i + 1])
|
expect(indexList[i] + 1).to.equal(indexList[i + 1])
|
||||||
|
@ -116,7 +116,7 @@ describe('checking words', function () {
|
||||||
|
|
||||||
it('should have misspelling suggestions with consecutive indexes', async function () {
|
it('should have misspelling suggestions with consecutive indexes', async function () {
|
||||||
const body = JSON.parse(response.body)
|
const body = JSON.parse(response.body)
|
||||||
const indexes = body.misspellings.map((mspl) => mspl.index)
|
const indexes = body.misspellings.map(mspl => mspl.index)
|
||||||
expect(indexes).to.deep.equal([0, 1, 2, 3])
|
expect(indexes).to.deep.equal([0, 1, 2, 3])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -3,38 +3,38 @@ const request = require('./helpers/request')
|
||||||
|
|
||||||
const USER_ID = 101
|
const USER_ID = 101
|
||||||
|
|
||||||
const checkWord = (words) =>
|
const checkWord = words =>
|
||||||
request.post({
|
request.post({
|
||||||
url: `/user/${USER_ID}/check`,
|
url: `/user/${USER_ID}/check`,
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
words
|
words,
|
||||||
})
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
const learnWord = (word) =>
|
const learnWord = word =>
|
||||||
request.post({
|
request.post({
|
||||||
url: `/user/${USER_ID}/learn`,
|
url: `/user/${USER_ID}/learn`,
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
word
|
word,
|
||||||
})
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
const unlearnWord = (word) =>
|
const unlearnWord = word =>
|
||||||
request.post({
|
request.post({
|
||||||
url: `/user/${USER_ID}/unlearn`,
|
url: `/user/${USER_ID}/unlearn`,
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
word
|
word,
|
||||||
})
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
const getDict = () =>
|
const getDict = () =>
|
||||||
request.get({
|
request.get({
|
||||||
url: `/user/${USER_ID}`
|
url: `/user/${USER_ID}`,
|
||||||
})
|
})
|
||||||
|
|
||||||
const deleteDict = () =>
|
const deleteDict = () =>
|
||||||
request.del({
|
request.del({
|
||||||
url: `/user/${USER_ID}`
|
url: `/user/${USER_ID}`,
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('learning words', function () {
|
describe('learning words', function () {
|
||||||
|
|
|
@ -7,14 +7,14 @@ const BASE_URL = `http://${process.env.HTTP_TEST_HOST || 'localhost'}:${PORT}`
|
||||||
const request = require('request').defaults({
|
const request = require('request').defaults({
|
||||||
baseUrl: BASE_URL,
|
baseUrl: BASE_URL,
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
followRedirect: false
|
followRedirect: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
PORT,
|
PORT,
|
||||||
get: promisify(request.get),
|
get: promisify(request.get),
|
||||||
post: promisify(request.post),
|
post: promisify(request.post),
|
||||||
del: promisify(request.del)
|
del: promisify(request.del),
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,8 +14,8 @@ SandboxedModule.configure({
|
||||||
warn() {},
|
warn() {},
|
||||||
err() {},
|
err() {},
|
||||||
error() {},
|
error() {},
|
||||||
fatal() {}
|
fatal() {},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
globals: { Buffer, JSON, console, process }
|
globals: { Buffer, JSON, console, process },
|
||||||
})
|
})
|
||||||
|
|
|
@ -24,7 +24,7 @@ const wordlist = fs
|
||||||
.readFileSync(WORDS)
|
.readFileSync(WORDS)
|
||||||
.toString()
|
.toString()
|
||||||
.split('\n')
|
.split('\n')
|
||||||
.filter((w) => w.match(/^[a-z]+$/))
|
.filter(w => w.match(/^[a-z]+$/))
|
||||||
|
|
||||||
const generateCorrectWords = function (n) {
|
const generateCorrectWords = function (n) {
|
||||||
const words = []
|
const words = []
|
||||||
|
@ -154,7 +154,7 @@ q.drain = () => console.log('all items have been processed')
|
||||||
for (let i = 0; i <= 1000; i++) {
|
for (let i = 0; i <= 1000; i++) {
|
||||||
q.push({
|
q.push({
|
||||||
correct: Math.floor(30 * Math.random()) + 1,
|
correct: Math.floor(30 * Math.random()) + 1,
|
||||||
incorrect: Math.floor(3 * Math.random())
|
incorrect: Math.floor(3 * Math.random()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// if Math.random() < 0.1
|
// if Math.random() < 0.1
|
||||||
|
|
|
@ -18,9 +18,9 @@ describe('ASpell', function () {
|
||||||
requires: {
|
requires: {
|
||||||
'@overleaf/metrics': {
|
'@overleaf/metrics': {
|
||||||
gauge() {},
|
gauge() {},
|
||||||
inc() {}
|
inc() {},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
afterEach(function () {
|
afterEach(function () {
|
||||||
|
@ -111,7 +111,7 @@ describe('ASpell', function () {
|
||||||
|
|
||||||
return describe('when the request times out', function () {
|
return describe('when the request times out', function () {
|
||||||
beforeEach(function (done) {
|
beforeEach(function (done) {
|
||||||
const words = __range__(0, 1000, true).map((i) => 'abcdefg')
|
const words = __range__(0, 1000, true).map(i => 'abcdefg')
|
||||||
this.ASpell.ASPELL_TIMEOUT = 1
|
this.ASpell.ASPELL_TIMEOUT = 1
|
||||||
this.start = Date.now()
|
this.start = Date.now()
|
||||||
return this.ASpell.checkWords('en', words, (error, result) => {
|
return this.ASpell.checkWords('en', words, (error, result) => {
|
||||||
|
|
|
@ -16,10 +16,10 @@ describe('ASpellWorker', function () {
|
||||||
requires: {
|
requires: {
|
||||||
'@overleaf/metrics': {
|
'@overleaf/metrics': {
|
||||||
gauge() {},
|
gauge() {},
|
||||||
inc() {}
|
inc() {},
|
||||||
},
|
},
|
||||||
child_process: this.child_process
|
child_process: this.child_process,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
|
@ -31,7 +31,7 @@ describe('ASpellWorker', function () {
|
||||||
stderr: { on: sinon.stub() },
|
stderr: { on: sinon.stub() },
|
||||||
stdin: { on: sinon.stub() },
|
stdin: { on: sinon.stub() },
|
||||||
on: sinon.stub(),
|
on: sinon.stub(),
|
||||||
pid: 12345
|
pid: 12345,
|
||||||
}
|
}
|
||||||
this.child_process.spawn = sinon.stub().returns(this.pipe)
|
this.child_process.spawn = sinon.stub().returns(this.pipe)
|
||||||
this.pipe.stdout.setEncoding = sinon.stub()
|
this.pipe.stdout.setEncoding = sinon.stub()
|
||||||
|
@ -92,7 +92,7 @@ describe('ASpellWorker', function () {
|
||||||
describe('with everything split across chunks', function () {
|
describe('with everything split across chunks', function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
this.callback = worker.callback = sinon.stub()
|
this.callback = worker.callback = sinon.stub()
|
||||||
'& hello\n& world\nen\n& goodbye'.split('').forEach((x) => {
|
'& hello\n& world\nen\n& goodbye'.split('').forEach(x => {
|
||||||
this.pipe.stdout.emit('data', x)
|
this.pipe.stdout.emit('data', x)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -12,13 +12,13 @@ describe('LearnedWordsManager', function () {
|
||||||
this.callback = sinon.stub()
|
this.callback = sinon.stub()
|
||||||
this.db = {
|
this.db = {
|
||||||
spellingPreferences: {
|
spellingPreferences: {
|
||||||
updateOne: sinon.stub().yields()
|
updateOne: sinon.stub().yields(),
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
this.cache = {
|
this.cache = {
|
||||||
get: sinon.stub(),
|
get: sinon.stub(),
|
||||||
set: sinon.stub(),
|
set: sinon.stub(),
|
||||||
del: sinon.stub()
|
del: sinon.stub(),
|
||||||
}
|
}
|
||||||
this.LearnedWordsManager = SandboxedModule.require(modulePath, {
|
this.LearnedWordsManager = SandboxedModule.require(modulePath, {
|
||||||
requires: {
|
requires: {
|
||||||
|
@ -26,9 +26,9 @@ describe('LearnedWordsManager', function () {
|
||||||
'./MongoCache': this.cache,
|
'./MongoCache': this.cache,
|
||||||
'@overleaf/metrics': {
|
'@overleaf/metrics': {
|
||||||
timeAsyncMethod: sinon.stub(),
|
timeAsyncMethod: sinon.stub(),
|
||||||
inc: sinon.stub()
|
inc: sinon.stub(),
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -42,13 +42,13 @@ describe('LearnedWordsManager', function () {
|
||||||
expect(
|
expect(
|
||||||
this.db.spellingPreferences.updateOne.calledWith(
|
this.db.spellingPreferences.updateOne.calledWith(
|
||||||
{
|
{
|
||||||
token: this.token
|
token: this.token,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
$addToSet: { learnedWords: this.word }
|
$addToSet: { learnedWords: this.word },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
upsert: true
|
upsert: true,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
).to.equal(true)
|
).to.equal(true)
|
||||||
|
@ -69,10 +69,10 @@ describe('LearnedWordsManager', function () {
|
||||||
expect(
|
expect(
|
||||||
this.db.spellingPreferences.updateOne.calledWith(
|
this.db.spellingPreferences.updateOne.calledWith(
|
||||||
{
|
{
|
||||||
token: this.token
|
token: this.token,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
$pull: { learnedWords: this.word }
|
$pull: { learnedWords: this.word },
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
).to.equal(true)
|
).to.equal(true)
|
||||||
|
|
|
@ -9,7 +9,7 @@ const modulePath = require('path').join(
|
||||||
'../../../app/js/SpellingAPIManager'
|
'../../../app/js/SpellingAPIManager'
|
||||||
)
|
)
|
||||||
|
|
||||||
const promiseStub = (val) => new Promise((resolve) => resolve(val))
|
const promiseStub = val => new Promise(resolve => resolve(val))
|
||||||
|
|
||||||
describe('SpellingAPIManager', function () {
|
describe('SpellingAPIManager', function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
|
@ -21,16 +21,16 @@ describe('SpellingAPIManager', function () {
|
||||||
learnWord: sinon.stub().callsArg(2),
|
learnWord: sinon.stub().callsArg(2),
|
||||||
unlearnWord: sinon.stub().callsArg(2),
|
unlearnWord: sinon.stub().callsArg(2),
|
||||||
promises: {
|
promises: {
|
||||||
getLearnedWords: sinon.stub().returns(promiseStub(this.learnedWords))
|
getLearnedWords: sinon.stub().returns(promiseStub(this.learnedWords)),
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
this.SpellingAPIManager = SandboxedModule.require(modulePath, {
|
this.SpellingAPIManager = SandboxedModule.require(modulePath, {
|
||||||
requires: {
|
requires: {
|
||||||
'./ASpell': this.ASpell,
|
'./ASpell': this.ASpell,
|
||||||
'@overleaf/settings': { ignoredMisspellings: ['ShareLaTeX'] },
|
'@overleaf/settings': { ignoredMisspellings: ['ShareLaTeX'] },
|
||||||
'./LearnedWordsManager': this.LearnedWordsManager
|
'./LearnedWordsManager': this.LearnedWordsManager,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -43,14 +43,14 @@ describe('SpellingAPIManager', function () {
|
||||||
'are',
|
'are',
|
||||||
'speled',
|
'speled',
|
||||||
'rong',
|
'rong',
|
||||||
'lerned'
|
'lerned',
|
||||||
]
|
]
|
||||||
this.allWords = this.nonLearnedWords.concat(this.learnedWords)
|
this.allWords = this.nonLearnedWords.concat(this.learnedWords)
|
||||||
this.misspellings = [
|
this.misspellings = [
|
||||||
{ index: 2, suggestions: ['that'] },
|
{ index: 2, suggestions: ['that'] },
|
||||||
{ index: 4, suggestions: ['spelled'] },
|
{ index: 4, suggestions: ['spelled'] },
|
||||||
{ index: 5, suggestions: ['wrong', 'ring'] },
|
{ index: 5, suggestions: ['wrong', 'ring'] },
|
||||||
{ index: 6, suggestions: ['learned'] }
|
{ index: 6, suggestions: ['learned'] },
|
||||||
]
|
]
|
||||||
this.misspellingsWithoutLearnedWords = this.misspellings.slice(0, 3)
|
this.misspellingsWithoutLearnedWords = this.misspellings.slice(0, 3)
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ describe('SpellingAPIManager', function () {
|
||||||
callback(null, this.misspellings)
|
callback(null, this.misspellings)
|
||||||
}
|
}
|
||||||
this.ASpell.promises = {
|
this.ASpell.promises = {
|
||||||
checkWords: sinon.stub().returns(promiseStub(this.misspellings))
|
checkWords: sinon.stub().returns(promiseStub(this.misspellings)),
|
||||||
}
|
}
|
||||||
sinon.spy(this.ASpell, 'checkWords')
|
sinon.spy(this.ASpell, 'checkWords')
|
||||||
})
|
})
|
||||||
|
@ -140,7 +140,7 @@ describe('SpellingAPIManager', function () {
|
||||||
this.token,
|
this.token,
|
||||||
{
|
{
|
||||||
words: this.allWords,
|
words: this.allWords,
|
||||||
language: this.language
|
language: this.language,
|
||||||
},
|
},
|
||||||
(error, result) => {
|
(error, result) => {
|
||||||
this.result = result
|
this.result = result
|
||||||
|
@ -181,7 +181,7 @@ describe('SpellingAPIManager', function () {
|
||||||
describe('learnWord', function () {
|
describe('learnWord', function () {
|
||||||
describe('without a token', function () {
|
describe('without a token', function () {
|
||||||
beforeEach(function (done) {
|
beforeEach(function (done) {
|
||||||
this.SpellingAPIManager.learnWord(null, { word: 'banana' }, (error) => {
|
this.SpellingAPIManager.learnWord(null, { word: 'banana' }, error => {
|
||||||
this.error = error
|
this.error = error
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
|
@ -196,7 +196,7 @@ describe('SpellingAPIManager', function () {
|
||||||
|
|
||||||
describe('without a word', function () {
|
describe('without a word', function () {
|
||||||
beforeEach(function (done) {
|
beforeEach(function (done) {
|
||||||
this.SpellingAPIManager.learnWord(this.token, {}, (error) => {
|
this.SpellingAPIManager.learnWord(this.token, {}, error => {
|
||||||
this.error = error
|
this.error = error
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
|
@ -215,7 +215,7 @@ describe('SpellingAPIManager', function () {
|
||||||
this.SpellingAPIManager.learnWord(
|
this.SpellingAPIManager.learnWord(
|
||||||
this.token,
|
this.token,
|
||||||
{ word: this.word },
|
{ word: this.word },
|
||||||
(error) => {
|
error => {
|
||||||
this.error = error
|
this.error = error
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
|
@ -233,14 +233,10 @@ describe('SpellingAPIManager', function () {
|
||||||
describe('unlearnWord', function () {
|
describe('unlearnWord', function () {
|
||||||
describe('without a token', function () {
|
describe('without a token', function () {
|
||||||
beforeEach(function (done) {
|
beforeEach(function (done) {
|
||||||
this.SpellingAPIManager.unlearnWord(
|
this.SpellingAPIManager.unlearnWord(null, { word: 'banana' }, error => {
|
||||||
null,
|
this.error = error
|
||||||
{ word: 'banana' },
|
done()
|
||||||
(error) => {
|
})
|
||||||
this.error = error
|
|
||||||
done()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should return an error', function () {
|
it('should return an error', function () {
|
||||||
|
@ -252,7 +248,7 @@ describe('SpellingAPIManager', function () {
|
||||||
|
|
||||||
describe('without a word', function () {
|
describe('without a word', function () {
|
||||||
beforeEach(function (done) {
|
beforeEach(function (done) {
|
||||||
this.SpellingAPIManager.unlearnWord(this.token, {}, (error) => {
|
this.SpellingAPIManager.unlearnWord(this.token, {}, error => {
|
||||||
this.error = error
|
this.error = error
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
|
@ -271,7 +267,7 @@ describe('SpellingAPIManager', function () {
|
||||||
this.SpellingAPIManager.unlearnWord(
|
this.SpellingAPIManager.unlearnWord(
|
||||||
this.token,
|
this.token,
|
||||||
{ word: this.word },
|
{ word: this.word },
|
||||||
(error) => {
|
error => {
|
||||||
this.error = error
|
this.error = error
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue