Просмотр исходного кода

Merge pull request #53 from overleaf/ta-learn-word-no-duplicates

Ignore Duplicates Words
Timothée Alby 6 лет назад
Родитель
Сommit
49d1639c79

+ 8 - 2
services/spelling/app/js/LearnedWordsManager.js

@@ -15,7 +15,7 @@ const LearnedWordsManager = {
         token: userToken
         token: userToken
       },
       },
       {
       {
-        $push: { learnedWords: word }
+        $addToSet: { learnedWords: word }
       },
       },
       {
       {
         upsert: true
         upsert: true
@@ -60,8 +60,14 @@ const LearnedWordsManager = {
       if (error != null) {
       if (error != null) {
         return callback(error)
         return callback(error)
       }
       }
-      const words =
+      let words =
         (preferences != null ? preferences.learnedWords : undefined) || []
         (preferences != null ? preferences.learnedWords : undefined) || []
+      if (words) {
+        // remove duplicates
+        words = words.filter(
+          (value, index, self) => self.indexOf(value) === index
+        )
+      }
       mongoCache.set(userToken, words)
       mongoCache.set(userToken, words)
       callback(null, words)
       callback(null, words)
     })
     })

+ 26 - 5
services/spelling/test/acceptance/js/LearnTest.js

@@ -27,18 +27,39 @@ const unlearnWord = word =>
     })
     })
   })
   })
 
 
+const getDict = () =>
+  request.get({
+    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() {
-  it('should return status 204 when posting a word successfully', async function () {
+  afterEach(async function() {
+    await deleteDict()
+  })
+
+  it('should return status 204 when posting a word successfully', async function() {
     const response = await learnWord('abcd')
     const response = await learnWord('abcd')
     expect(response.statusCode).to.equal(204)
     expect(response.statusCode).to.equal(204)
   })
   })
 
 
-  it('should return no misspellings after a word is learnt', async function () {
+  it('should not learn the same word twice', async function() {
+    await learnWord('foobar')
+    const learnResponse = await learnWord('foobar')
+    expect(learnResponse.statusCode).to.equal(204)
+
+    const dictResponse = await getDict()
+    const responseBody = JSON.parse(dictResponse.body)
+    // the response from getlearnedwords filters out duplicates, so this test
+    // can succeed even if the word is stored twice in the database
+    expect(responseBody.length).to.equals(1)
+  })
+
+  it('should return no misspellings after a word is learnt', async function() {
     const response = await checkWord(['abv'])
     const response = await checkWord(['abv'])
     const responseBody = JSON.parse(response.body)
     const responseBody = JSON.parse(response.body)
     expect(responseBody.misspellings.length).to.equals(1)
     expect(responseBody.misspellings.length).to.equals(1)
@@ -50,7 +71,7 @@ describe('learning words', function() {
     expect(responseBody2.misspellings.length).to.equals(0)
     expect(responseBody2.misspellings.length).to.equals(0)
   })
   })
 
 
-  it('should return misspellings again after a personal dictionary is deleted', async function () {
+  it('should return misspellings again after a personal dictionary is deleted', async function() {
     await learnWord('bvc')
     await learnWord('bvc')
     await deleteDict()
     await deleteDict()
 
 
@@ -61,12 +82,12 @@ describe('learning words', function() {
 })
 })
 
 
 describe('unlearning words', function() {
 describe('unlearning words', function() {
-  it('should return status 204 when posting a word successfully', async function () {
+  it('should return status 204 when posting a word successfully', async function() {
     const response = await unlearnWord('anything')
     const response = await unlearnWord('anything')
     expect(response.statusCode).to.equal(204)
     expect(response.statusCode).to.equal(204)
   })
   })
 
 
-  it('should return misspellings after a word is unlearnt', async function () {
+  it('should return misspellings after a word is unlearnt', async function() {
     await learnWord('abv')
     await learnWord('abv')
 
 
     const response = await checkWord(['abv'])
     const response = await checkWord(['abv'])

+ 8 - 3
services/spelling/test/unit/js/LearnedWordsManagerTests.js

@@ -22,6 +22,9 @@ describe('LearnedWordsManager', function() {
       del: sinon.stub()
       del: sinon.stub()
     }
     }
     this.LearnedWordsManager = SandboxedModule.require(modulePath, {
     this.LearnedWordsManager = SandboxedModule.require(modulePath, {
+      globals: {
+        console: console
+      },
       requires: {
       requires: {
         './DB': this.db,
         './DB': this.db,
         './MongoCache': this.cache,
         './MongoCache': this.cache,
@@ -51,7 +54,7 @@ describe('LearnedWordsManager', function() {
             token: this.token
             token: this.token
           },
           },
           {
           {
-            $push: { learnedWords: this.word }
+            $addToSet: { learnedWords: this.word }
           },
           },
           {
           {
             upsert: true
             upsert: true
@@ -92,8 +95,10 @@ describe('LearnedWordsManager', function() {
   describe('getLearnedWords', function() {
   describe('getLearnedWords', function() {
     beforeEach(function() {
     beforeEach(function() {
       this.wordList = ['apples', 'bananas', 'pears']
       this.wordList = ['apples', 'bananas', 'pears']
+      this.wordListWithDuplicates = this.wordList.slice()
+      this.wordListWithDuplicates.push('bananas')
       this.db.spellingPreferences.findOne = (conditions, callback) => {
       this.db.spellingPreferences.findOne = (conditions, callback) => {
-        callback(null, { learnedWords: this.wordList })
+        callback(null, { learnedWords: this.wordListWithDuplicates })
       }
       }
       sinon.spy(this.db.spellingPreferences, 'findOne')
       sinon.spy(this.db.spellingPreferences, 'findOne')
       this.LearnedWordsManager.getLearnedWords(this.token, this.callback)
       this.LearnedWordsManager.getLearnedWords(this.token, this.callback)
@@ -105,7 +110,7 @@ describe('LearnedWordsManager', function() {
       ).to.equal(true)
       ).to.equal(true)
     })
     })
 
 
-    it('should return the word list in the callback', function() {
+    it('should return the word list in the callback without duplicates', function() {
       expect(this.callback.calledWith(null, this.wordList)).to.equal(true)
       expect(this.callback.calledWith(null, this.wordList)).to.equal(true)
     })
     })
   })
   })