LinkedFilesController.test.mjs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. import { expect, vi } from 'vitest'
  2. import sinon from 'sinon'
  3. const modulePath =
  4. '../../../../app/src/Features/LinkedFiles/LinkedFilesController.mjs'
  5. describe('LinkedFilesController', function () {
  6. beforeEach(function (ctx) {
  7. ctx.fakeTime = new Date()
  8. ctx.clock = sinon.useFakeTimers(ctx.fakeTime.getTime())
  9. })
  10. afterEach(function (ctx) {
  11. ctx.clock.restore()
  12. })
  13. beforeEach(async function (ctx) {
  14. ctx.userId = 'user-id'
  15. ctx.Agent = {
  16. promises: {
  17. createLinkedFile: sinon.stub().resolves(),
  18. refreshLinkedFile: sinon.stub().resolves(),
  19. },
  20. }
  21. ctx.projectId = 'projectId'
  22. ctx.provider = 'provider'
  23. ctx.fileName = 'linked-file-name'
  24. ctx.data = { customAgentData: 'foo' }
  25. ctx.LinkedFilesHandler = {
  26. promises: {
  27. getFileById: sinon.stub(),
  28. },
  29. }
  30. ctx.AnalyticsManager = {}
  31. ctx.SessionManager = {
  32. getLoggedInUserId: sinon.stub().returns(ctx.userId),
  33. }
  34. ctx.EditorRealTimeController = {}
  35. ctx.ReferencesHandler = {}
  36. ctx.UrlAgent = {}
  37. ctx.ProjectFileAgent = {}
  38. ctx.ProjectOutputFileAgent = {}
  39. ctx.EditorController = {}
  40. ctx.ProjectLocator = {}
  41. ctx.logger = {
  42. error: sinon.stub(),
  43. }
  44. ctx.settings = { enabledLinkedFileTypes: [] }
  45. vi.doMock(
  46. '.../../../../app/src/Features/Authentication/SessionManager',
  47. () => ({
  48. default: ctx.SessionManager,
  49. })
  50. )
  51. vi.doMock(
  52. '../../../../app/src/Features/Analytics/AnalyticsManager',
  53. () => ({
  54. default: ctx.AnalyticsManager,
  55. })
  56. )
  57. vi.doMock(
  58. '../../../../app/src/Features/LinkedFiles/LinkedFilesHandler',
  59. () => ({
  60. default: ctx.LinkedFilesHandler,
  61. })
  62. )
  63. vi.doMock(
  64. '../../../../app/src/Features/Editor/EditorRealTimeController',
  65. () => ({
  66. default: ctx.EditorRealTimeController,
  67. })
  68. )
  69. vi.doMock(
  70. '../../../../app/src/Features/References/ReferencesHandler',
  71. () => ({
  72. default: ctx.ReferencesHandler,
  73. })
  74. )
  75. vi.doMock('../../../../app/src/Features/LinkedFiles/UrlAgent', () => ({
  76. default: ctx.UrlAgent,
  77. }))
  78. vi.doMock(
  79. '../../../../app/src/Features/LinkedFiles/ProjectFileAgent',
  80. () => ({
  81. default: ctx.ProjectFileAgent,
  82. })
  83. )
  84. vi.doMock(
  85. '../../../../app/src/Features/LinkedFiles/ProjectOutputFileAgent',
  86. () => ({
  87. default: ctx.ProjectOutputFileAgent,
  88. })
  89. )
  90. vi.doMock('../../../../app/src/Features/Editor/EditorController', () => ({
  91. default: ctx.EditorController,
  92. }))
  93. vi.doMock('../../../../app/src/Features/Project/ProjectLocator', () => ({
  94. default: ctx.ProjectLocator,
  95. }))
  96. vi.doMock('@overleaf/logger', () => ({
  97. default: ctx.logger,
  98. }))
  99. vi.doMock('@overleaf/settings', () => ({
  100. default: ctx.settings,
  101. }))
  102. ctx.LinkedFilesController = (await import(modulePath)).default
  103. ctx.LinkedFilesController._getAgent = sinon.stub().resolves(ctx.Agent)
  104. })
  105. describe('createLinkedFile', function () {
  106. beforeEach(function (ctx) {
  107. ctx.req = {
  108. params: { project_id: ctx.projectId },
  109. body: {
  110. name: ctx.fileName,
  111. provider: ctx.provider,
  112. data: ctx.data,
  113. },
  114. }
  115. ctx.next = sinon.stub()
  116. })
  117. it('sets importedAt timestamp on linkedFileData', async function (ctx) {
  118. await new Promise(resolve => {
  119. ctx.next = sinon.stub().callsFake(() => resolve('unexpected error'))
  120. ctx.res = {
  121. json: () => {
  122. expect(ctx.Agent.promises.createLinkedFile).to.have.been.calledWith(
  123. ctx.projectId,
  124. { ...ctx.data, importedAt: ctx.fakeTime.toISOString() },
  125. ctx.fileName,
  126. undefined,
  127. ctx.userId
  128. )
  129. resolve()
  130. },
  131. }
  132. ctx.LinkedFilesController.createLinkedFile(ctx.req, ctx.res, ctx.next)
  133. })
  134. })
  135. })
  136. describe('refreshLinkedFiles', function () {
  137. beforeEach(function (ctx) {
  138. ctx.data.provider = ctx.provider
  139. ctx.file = {
  140. name: ctx.fileName,
  141. linkedFileData: {
  142. ...ctx.data,
  143. importedAt: new Date(2020, 1, 1).toISOString(),
  144. },
  145. }
  146. ctx.LinkedFilesHandler.promises.getFileById
  147. .withArgs(ctx.projectId, 'file-id')
  148. .resolves({
  149. file: ctx.file,
  150. path: 'fake-path',
  151. parentFolder: {
  152. _id: 'parent-folder-id',
  153. },
  154. })
  155. ctx.req = {
  156. params: { project_id: ctx.projectId, file_id: 'file-id' },
  157. body: {},
  158. }
  159. ctx.next = sinon.stub()
  160. })
  161. it('resets importedAt timestamp on linkedFileData', async function (ctx) {
  162. await new Promise(resolve => {
  163. ctx.next = sinon.stub().callsFake(() => resolve('unexpected error'))
  164. ctx.res = {
  165. json: () => {
  166. expect(
  167. ctx.Agent.promises.refreshLinkedFile
  168. ).to.have.been.calledWith(
  169. ctx.projectId,
  170. {
  171. ...ctx.data,
  172. importedAt: ctx.fakeTime.toISOString(),
  173. },
  174. ctx.name,
  175. 'parent-folder-id',
  176. ctx.userId
  177. )
  178. resolve()
  179. },
  180. }
  181. ctx.LinkedFilesController.refreshLinkedFile(ctx.req, ctx.res, ctx.next)
  182. })
  183. })
  184. })
  185. })