follows.test.ts 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. import { ApolloServer } from 'apollo-server-express'
  2. import { Mongoose } from 'mongoose'
  3. import { Aggregates } from '../src/types'
  4. import { buildAggregates, connectMongoose, createServer } from '../src/server'
  5. import {
  6. FOLLOW_CHANNEL,
  7. FollowChannel,
  8. FollowChannelArgs,
  9. UNFOLLOW_CHANNEL,
  10. UnfollowChannel,
  11. UnfollowChannelArgs,
  12. GET_MOST_FOLLOWED_CHANNELS_CONNECTION,
  13. GetMostFollowedChannelsConnection,
  14. GetMostFollowedChannelsConnectionArgs,
  15. } from './queries/follows'
  16. import { ChannelFollowsInfo } from '../src/entities/ChannelFollowsInfo'
  17. import { ChannelEventsBucketModel } from '../src/models/ChannelEvent'
  18. import { TEST_BUCKET_SIZE } from './setup'
  19. import { createMutationFn, createQueryFn, MutationFn, QueryFn } from './helpers'
  20. const FIRST_CHANNEL_ID = '22'
  21. const SECOND_CHANNEL_ID = '23'
  22. describe('Channel follows resolver', () => {
  23. let server: ApolloServer
  24. let mongoose: Mongoose
  25. let aggregates: Aggregates
  26. let query: QueryFn
  27. let mutate: MutationFn
  28. beforeEach(async () => {
  29. mongoose = await connectMongoose(process.env.MONGO_URL!)
  30. aggregates = await buildAggregates()
  31. server = await createServer(mongoose, aggregates, process.env.ORION_QUERY_NODE_URL!)
  32. await server.start()
  33. query = createQueryFn(server)
  34. mutate = createMutationFn(server)
  35. })
  36. afterEach(async () => {
  37. await server.stop()
  38. await ChannelEventsBucketModel.deleteMany({})
  39. await mongoose.disconnect()
  40. })
  41. const followChannel = async (channelId: string) => {
  42. const followChannelResponse = await mutate<FollowChannel, FollowChannelArgs>({
  43. mutation: FOLLOW_CHANNEL,
  44. variables: { channelId },
  45. })
  46. expect(followChannelResponse.errors).toBeUndefined()
  47. return followChannelResponse.data?.followChannel
  48. }
  49. const unfollowChannel = async (channelId: string) => {
  50. const unfollowChannelResponse = await mutate<UnfollowChannel, UnfollowChannelArgs>({
  51. mutation: UNFOLLOW_CHANNEL,
  52. variables: { channelId },
  53. })
  54. expect(unfollowChannelResponse.errors).toBeUndefined()
  55. return unfollowChannelResponse.data?.unfollowChannel
  56. }
  57. const getMostFollowedChannels = async (periodDays: 7 | 30 | null) => {
  58. const mostFollowedChannelsResponse = await query<
  59. GetMostFollowedChannelsConnection,
  60. GetMostFollowedChannelsConnectionArgs
  61. >({
  62. query: GET_MOST_FOLLOWED_CHANNELS_CONNECTION,
  63. variables: { periodDays, limit: 10 },
  64. })
  65. expect(mostFollowedChannelsResponse.errors).toBeUndefined()
  66. return mostFollowedChannelsResponse.data?.mostFollowedChannelsConnection
  67. }
  68. it('should return null for unknown channel follows', async () => {
  69. const mostFollowedChannels = await getMostFollowedChannels(30)
  70. const mostFollowedChannelsAllTime = await getMostFollowedChannels(null)
  71. expect(mostFollowedChannels?.edges).toHaveLength(0)
  72. expect(mostFollowedChannelsAllTime?.edges).toHaveLength(0)
  73. })
  74. it('should properly handle channel follow', async () => {
  75. const expectedChannelFollows: ChannelFollowsInfo = {
  76. id: FIRST_CHANNEL_ID,
  77. follows: 1,
  78. }
  79. const expectedMostFollowedChannels = {
  80. edges: [expectedChannelFollows].map((follow) => ({ node: follow })),
  81. }
  82. let addChannelFollowData = await followChannel(FIRST_CHANNEL_ID)
  83. expect(addChannelFollowData).toEqual(expectedChannelFollows)
  84. let mostFollowedChannels = await getMostFollowedChannels(30)
  85. let mostFollowedChannelsAllTime = await getMostFollowedChannels(null)
  86. expect(mostFollowedChannels).toEqual(expectedMostFollowedChannels)
  87. expect(mostFollowedChannelsAllTime).toEqual(expectedMostFollowedChannels)
  88. expectedChannelFollows.follows++
  89. addChannelFollowData = await followChannel(FIRST_CHANNEL_ID)
  90. expect(addChannelFollowData).toEqual(expectedChannelFollows)
  91. mostFollowedChannels = await getMostFollowedChannels(30)
  92. mostFollowedChannelsAllTime = await getMostFollowedChannels(null)
  93. expect(mostFollowedChannels).toEqual(expectedMostFollowedChannels)
  94. expect(mostFollowedChannelsAllTime).toEqual(expectedMostFollowedChannels)
  95. })
  96. it('should properly handle channel unfollow', async () => {
  97. const expectedChannelFollows: ChannelFollowsInfo = {
  98. id: FIRST_CHANNEL_ID,
  99. follows: 5,
  100. }
  101. const expectedMostFollowedChannels = {
  102. edges: [expectedChannelFollows].map((follow) => ({ node: follow })),
  103. }
  104. await followChannel(FIRST_CHANNEL_ID)
  105. await followChannel(FIRST_CHANNEL_ID)
  106. await followChannel(FIRST_CHANNEL_ID)
  107. await followChannel(FIRST_CHANNEL_ID)
  108. await followChannel(FIRST_CHANNEL_ID)
  109. let mostFollowedChannels = await getMostFollowedChannels(30)
  110. let mostFollowedChannelsAllTime = await getMostFollowedChannels(null)
  111. expect(mostFollowedChannels).toEqual(expectedMostFollowedChannels)
  112. expect(mostFollowedChannelsAllTime).toEqual(expectedMostFollowedChannels)
  113. expectedChannelFollows.follows--
  114. const unfollowChannelData = await unfollowChannel(FIRST_CHANNEL_ID)
  115. expect(unfollowChannelData).toEqual(expectedChannelFollows)
  116. mostFollowedChannels = await getMostFollowedChannels(30)
  117. mostFollowedChannelsAllTime = await getMostFollowedChannels(null)
  118. expect(mostFollowedChannels).toEqual(expectedMostFollowedChannels)
  119. expect(mostFollowedChannelsAllTime).toEqual(expectedMostFollowedChannels)
  120. })
  121. it('should distinct follows of separate channels', async () => {
  122. const expectedFirstChannelFollows: ChannelFollowsInfo = {
  123. id: FIRST_CHANNEL_ID,
  124. follows: 1,
  125. }
  126. const expectedSecondChannelFollows: ChannelFollowsInfo = {
  127. id: SECOND_CHANNEL_ID,
  128. follows: 1,
  129. }
  130. const expectedMostFollowedChannels = {
  131. edges: [expectedFirstChannelFollows, expectedSecondChannelFollows].map((follow) => ({ node: follow })),
  132. }
  133. const firstChannelFollowData = await followChannel(FIRST_CHANNEL_ID)
  134. const secondChannelFollowData = await followChannel(SECOND_CHANNEL_ID)
  135. expect(firstChannelFollowData).toEqual(expectedFirstChannelFollows)
  136. expect(secondChannelFollowData).toEqual(expectedSecondChannelFollows)
  137. expectedFirstChannelFollows.follows++
  138. await followChannel(FIRST_CHANNEL_ID)
  139. const mostFollowedChannels = await getMostFollowedChannels(30)
  140. const mostFollowedChannelsAllTime = await getMostFollowedChannels(null)
  141. expect(mostFollowedChannels).toEqual(expectedMostFollowedChannels)
  142. expect(mostFollowedChannelsAllTime).toEqual(expectedMostFollowedChannels)
  143. })
  144. it('should properly rebuild the aggregate', async () => {
  145. const expectedFirstChannelFollows: ChannelFollowsInfo = {
  146. id: FIRST_CHANNEL_ID,
  147. follows: 3,
  148. }
  149. const expectedSecondChannelFollows: ChannelFollowsInfo = {
  150. id: SECOND_CHANNEL_ID,
  151. follows: 4,
  152. }
  153. const expectedMostFollowedChannels = {
  154. edges: [expectedFirstChannelFollows, expectedSecondChannelFollows].map((follow) => ({ node: follow })),
  155. }
  156. const checkFollows = async () => {
  157. const mostFollowedChannels = await getMostFollowedChannels(30)
  158. const mostFollowedChannelsAllTime = await getMostFollowedChannels(null)
  159. expect(mostFollowedChannels).toEqual(expectedMostFollowedChannels)
  160. expect(mostFollowedChannelsAllTime).toEqual(expectedMostFollowedChannels)
  161. }
  162. await followChannel(FIRST_CHANNEL_ID)
  163. await followChannel(FIRST_CHANNEL_ID)
  164. await followChannel(FIRST_CHANNEL_ID)
  165. await followChannel(SECOND_CHANNEL_ID)
  166. await followChannel(SECOND_CHANNEL_ID)
  167. await followChannel(SECOND_CHANNEL_ID)
  168. await followChannel(SECOND_CHANNEL_ID)
  169. await followChannel(SECOND_CHANNEL_ID)
  170. await unfollowChannel(SECOND_CHANNEL_ID)
  171. await checkFollows()
  172. await server.stop()
  173. aggregates = await buildAggregates()
  174. server = await createServer(mongoose, aggregates, process.env.ORION_QUERY_NODE_URL!)
  175. query = createQueryFn(server)
  176. mutate = createMutationFn(server)
  177. await checkFollows()
  178. })
  179. it('should properly handle saving events across buckets', async () => {
  180. const eventsCount = TEST_BUCKET_SIZE * 2 + 1
  181. const expectedChannelFollows: ChannelFollowsInfo = {
  182. id: FIRST_CHANNEL_ID,
  183. follows: eventsCount,
  184. }
  185. for (let i = 0; i < eventsCount; i++) {
  186. await followChannel(FIRST_CHANNEL_ID)
  187. }
  188. const expectedMostFollowedChannels = {
  189. edges: [expectedChannelFollows].map((follow) => ({ node: follow })),
  190. }
  191. const mostFollowedChannels = await getMostFollowedChannels(30)
  192. const mostFollowedChannelsAllTime = await getMostFollowedChannels(null)
  193. expect(mostFollowedChannels).toEqual(expectedMostFollowedChannels)
  194. expect(mostFollowedChannelsAllTime).toEqual(expectedMostFollowedChannels)
  195. })
  196. })