LearnedWordsManagerTests.js 4.6 KB

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