LinkedFilesController.test.mjs 5.3 KB

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