MongoHelper.mjs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. import { expect } from 'chai'
  2. import mongodb from 'mongodb-legacy'
  3. import mongoose from 'mongoose'
  4. import { User as UserModel } from '../../../app/src/models/User.mjs'
  5. import { db } from '../../../app/src/infrastructure/mongodb.mjs'
  6. import MongoHelpers from '../../../app/src/Features/Helpers/Mongo.mjs'
  7. import UserHelper from './helpers/User.mjs'
  8. const { normalizeQuery, normalizeMultiQuery } = MongoHelpers
  9. const User = UserHelper.promises
  10. const NativeObjectId = mongodb.ObjectId
  11. const MongooseObjectId = mongoose.Types.ObjectId
  12. describe('MongoTests', function () {
  13. let userIdAsString, userEmail, userIds
  14. beforeEach(async function setUpUsers() {
  15. // the first user in the db should not match the target user
  16. const otherUser = new User()
  17. await otherUser.ensureUserExists()
  18. const user = new User()
  19. await user.ensureUserExists()
  20. userIdAsString = user.id
  21. userEmail = user.email
  22. // the last user in the db should not match the target user
  23. const yetAnotherUser = new User()
  24. await yetAnotherUser.ensureUserExists()
  25. userIds = [otherUser.id, user.id, yetAnotherUser.id]
  26. })
  27. describe('normalizeQuery', function () {
  28. async function expectToWork(blob) {
  29. const query = normalizeQuery(blob)
  30. expect(query).to.exist
  31. expect(query._id).to.be.instanceof(NativeObjectId)
  32. expect(query._id).to.deep.equal(new NativeObjectId(userIdAsString))
  33. const user = await db.users.findOne(query)
  34. expect(user).to.exist
  35. expect(user.email).to.equal(userEmail)
  36. }
  37. it('should work with the user id as string', async function () {
  38. await expectToWork(userIdAsString)
  39. })
  40. it('should work with the user id in an object', async function () {
  41. await expectToWork({ _id: userIdAsString })
  42. })
  43. it('should pass back the object with id', function () {
  44. const inputQuery = { _id: userIdAsString, other: 1 }
  45. const query = normalizeMultiQuery(inputQuery)
  46. expect(inputQuery).to.equal(query)
  47. })
  48. describe('with an ObjectId from mongoose', function () {
  49. let user
  50. beforeEach(async function getUser() {
  51. user = await UserModel.findById(userIdAsString).exec()
  52. expect(user).to.exist
  53. expect(user._id).to.exist
  54. expect(user.email).to.equal(userEmail)
  55. })
  56. it('should have a mongoose ObjectId', function () {
  57. expect(user._id).to.be.instanceof(MongooseObjectId)
  58. })
  59. it('should work with the users _id field', async function () {
  60. await expectToWork(user._id)
  61. })
  62. })
  63. describe('with an ObjectId from the native driver', function () {
  64. let user
  65. beforeEach(async function getUser() {
  66. user = await db.users.findOne({
  67. _id: new NativeObjectId(userIdAsString),
  68. })
  69. expect(user).to.exist
  70. expect(user._id).to.exist
  71. expect(user.email).to.equal(userEmail)
  72. })
  73. it('should have a native ObjectId', function () {
  74. expect(user._id).to.be.instanceof(NativeObjectId)
  75. })
  76. it('should work with the users _id field', async function () {
  77. await expectToWork(user._id)
  78. })
  79. })
  80. })
  81. describe('normalizeMultiQuery', function () {
  82. let ghost
  83. beforeEach(async function addGhost() {
  84. // add a user which is not part of the initial three users
  85. ghost = new User()
  86. ghost.emails[0].email = ghost.email = 'ghost@ghost.com'
  87. await ghost.ensureUserExists()
  88. })
  89. async function expectToFindTheThreeUsers(query) {
  90. const users = await db.users.find(query).toArray()
  91. expect(users).to.have.length(3)
  92. expect(users.map(user => user._id.toString()).sort()).to.deep.equal(
  93. userIds.sort()
  94. )
  95. }
  96. describe('with an array as query', function () {
  97. function expectInQueryWithNativeObjectIds(query) {
  98. expect(query).to.exist
  99. expect(query._id).to.exist
  100. expect(query._id.$in).to.exist
  101. expect(
  102. query._id.$in.map(id => id instanceof NativeObjectId)
  103. ).to.deep.equal([true, true, true])
  104. }
  105. it('should transform all strings to native ObjectIds', function () {
  106. const query = normalizeMultiQuery(userIds)
  107. expectInQueryWithNativeObjectIds(query)
  108. })
  109. it('should transform all Mongoose ObjectIds to native ObjectIds', function () {
  110. const query = normalizeMultiQuery(
  111. userIds.map(userId => new NativeObjectId(userId))
  112. )
  113. expectInQueryWithNativeObjectIds(query)
  114. })
  115. it('should leave all native Objects as native ObjectIds', function () {
  116. const query = normalizeMultiQuery(
  117. userIds.map(userId => new NativeObjectId(userId))
  118. )
  119. expectInQueryWithNativeObjectIds(query)
  120. })
  121. it('should find the three users from string ids', async function () {
  122. const query = normalizeMultiQuery(userIds)
  123. await expectToFindTheThreeUsers(query)
  124. })
  125. it('should find the three users from Mongoose ObjectIds', async function () {
  126. const query = normalizeMultiQuery(
  127. userIds.map(userId => new NativeObjectId(userId))
  128. )
  129. await expectToFindTheThreeUsers(query)
  130. })
  131. it('should find the three users from native ObjectIds', async function () {
  132. const query = normalizeMultiQuery(
  133. userIds.map(userId => new NativeObjectId(userId))
  134. )
  135. await expectToFindTheThreeUsers(query)
  136. })
  137. })
  138. describe('with an object as query', function () {
  139. const signUpDate = new Date('2025-11-03T16:38:17.320Z')
  140. beforeEach(async function addHiddenFlag() {
  141. // add a mongo field that does not exist on the other users
  142. await ghost.mongoUpdate({ $set: { signUpDate } })
  143. })
  144. it('should pass through the query', function () {
  145. const inputQuery = { complex: 1 }
  146. const query = normalizeMultiQuery(inputQuery)
  147. expect(inputQuery).to.equal(query)
  148. })
  149. describe('when searching for hidden users', function () {
  150. it('should match the ghost only', async function () {
  151. const query = normalizeMultiQuery({ signUpDate })
  152. const users = await db.users.find(query).toArray()
  153. expect(users).to.have.length(1)
  154. expect(users[0]._id.toString()).to.equal(ghost.id)
  155. })
  156. })
  157. describe('when searching for non hidden users', function () {
  158. it('should find the three users', async function () {
  159. const query = normalizeMultiQuery({ signUpDate: { $ne: signUpDate } })
  160. await expectToFindTheThreeUsers(query)
  161. })
  162. })
  163. })
  164. })
  165. })