LearnedWordsManagerTests.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. const sinon = require('sinon')
  2. const chai = require('chai')
  3. const { expect } = chai
  4. const SandboxedModule = require('sandboxed-module')
  5. const modulePath = require('path').join(
  6. __dirname,
  7. '../../../app/js/LearnedWordsManager'
  8. )
  9. const { assert } = require('chai')
  10. describe('LearnedWordsManager', function() {
  11. beforeEach(function() {
  12. this.token = 'a6b3cd919ge'
  13. this.callback = sinon.stub()
  14. this.db = {
  15. spellingPreferences: {
  16. update: sinon.stub().yields()
  17. }
  18. }
  19. this.cache = {
  20. get: sinon.stub(),
  21. set: sinon.stub(),
  22. del: sinon.stub()
  23. }
  24. this.LearnedWordsManager = SandboxedModule.require(modulePath, {
  25. globals: {
  26. console: console
  27. },
  28. requires: {
  29. './DB': this.db,
  30. './MongoCache': this.cache,
  31. 'logger-sharelatex': {
  32. log() {},
  33. err() {},
  34. info() {}
  35. },
  36. 'metrics-sharelatex': {
  37. timeAsyncMethod: sinon.stub(),
  38. inc: sinon.stub()
  39. }
  40. }
  41. })
  42. })
  43. describe('learnWord', function() {
  44. beforeEach(function() {
  45. this.word = 'instanton'
  46. this.LearnedWordsManager.learnWord(this.token, this.word, this.callback)
  47. })
  48. it('should insert the word in the word list in the database', function() {
  49. expect(
  50. this.db.spellingPreferences.update.calledWith(
  51. {
  52. token: this.token
  53. },
  54. {
  55. $addToSet: { learnedWords: this.word }
  56. },
  57. {
  58. upsert: true
  59. }
  60. )
  61. ).to.equal(true)
  62. })
  63. it('should call the callback', function() {
  64. expect(this.callback.called).to.equal(true)
  65. })
  66. })
  67. describe('unlearnWord', function() {
  68. beforeEach(function() {
  69. this.word = 'instanton'
  70. this.LearnedWordsManager.unlearnWord(this.token, this.word, this.callback)
  71. })
  72. it('should remove the word from the word list in the database', function() {
  73. expect(
  74. this.db.spellingPreferences.update.calledWith(
  75. {
  76. token: this.token
  77. },
  78. {
  79. $pull: { learnedWords: this.word }
  80. }
  81. )
  82. ).to.equal(true)
  83. })
  84. it('should call the callback', function() {
  85. expect(this.callback.called).to.equal(true)
  86. })
  87. })
  88. describe('getLearnedWords', function() {
  89. beforeEach(function() {
  90. this.wordList = ['apples', 'bananas', 'pears']
  91. this.wordListWithDuplicates = this.wordList.slice()
  92. this.wordListWithDuplicates.push('bananas')
  93. this.db.spellingPreferences.findOne = (conditions, callback) => {
  94. callback(null, { learnedWords: this.wordListWithDuplicates })
  95. }
  96. sinon.spy(this.db.spellingPreferences, 'findOne')
  97. this.LearnedWordsManager.getLearnedWords(this.token, this.callback)
  98. })
  99. it('should get the word list for the given user', function() {
  100. expect(
  101. this.db.spellingPreferences.findOne.calledWith({ token: this.token })
  102. ).to.equal(true)
  103. })
  104. it('should return the word list in the callback without duplicates', function() {
  105. expect(this.callback.calledWith(null, this.wordList)).to.equal(true)
  106. })
  107. })
  108. describe('caching the result', function() {
  109. it('should use the cache first if it is primed', function(done) {
  110. this.wordList = ['apples', 'bananas', 'pears']
  111. this.cache.get.returns(this.wordList)
  112. this.db.spellingPreferences.findOne = sinon.stub()
  113. this.LearnedWordsManager.getLearnedWords(this.token, (err, spellings) => {
  114. expect(err).not.to.exist
  115. this.db.spellingPreferences.findOne.called.should.equal(false)
  116. assert.deepEqual(this.wordList, spellings)
  117. done()
  118. })
  119. })
  120. it('should set the cache after hitting the db', function(done) {
  121. this.wordList = ['apples', 'bananas', 'pears']
  122. this.db.spellingPreferences.findOne = sinon
  123. .stub()
  124. .callsArgWith(1, null, { learnedWords: this.wordList })
  125. this.LearnedWordsManager.getLearnedWords(this.token, () => {
  126. this.cache.set.calledWith(this.token, this.wordList).should.equal(true)
  127. done()
  128. })
  129. })
  130. it('should break cache when update is called', function(done) {
  131. this.word = 'instanton'
  132. this.LearnedWordsManager.learnWord(this.token, this.word, () => {
  133. this.cache.del.calledWith(this.token).should.equal(true)
  134. done()
  135. })
  136. })
  137. })
  138. describe('deleteUsersLearnedWords', function() {
  139. beforeEach(function() {
  140. this.db.spellingPreferences.remove = sinon.stub().callsArgWith(1)
  141. })
  142. it('should get the word list for the given user', function(done) {
  143. this.LearnedWordsManager.deleteUsersLearnedWords(this.token, () => {
  144. this.db.spellingPreferences.remove
  145. .calledWith({ token: this.token })
  146. .should.equal(true)
  147. done()
  148. })
  149. })
  150. })
  151. })