Просмотр исходного кода

Merge pull request #20399 from overleaf/mj-set-import-time

[web] Set importedAt when creating linked files

GitOrigin-RevId: 06a549a20620eee33f64608d17a91d2e893f8f8a
Mathias Jakobsen 2 лет назад
Родитель
Сommit
9719b3376c

+ 3 - 0
services/web/app/src/Features/LinkedFiles/LinkedFilesController.js

@@ -82,6 +82,7 @@ module.exports = LinkedFilesController = {
     }
 
     data.provider = provider
+    data.importedAt = new Date().toISOString()
 
     return Agent.createLinkedFile(
       projectId,
@@ -136,6 +137,8 @@ module.exports = LinkedFilesController = {
           return res.sendStatus(400)
         }
 
+        linkedFileData.importedAt = new Date().toISOString()
+
         Agent.refreshLinkedFile(
           projectId,
           linkedFileData,

+ 2 - 1
services/web/app/src/Features/LinkedFiles/ProjectFileAgent.js

@@ -215,7 +215,8 @@ module.exports = ProjectFileAgent = {
       'provider',
       'source_project_id',
       'v1_source_doc_id',
-      'source_entity_path'
+      'source_entity_path',
+      'importedAt'
     )
   },
 

+ 1 - 0
services/web/app/src/Features/LinkedFiles/ProjectOutputFileAgent.js

@@ -110,6 +110,7 @@ function _sanitizeData(data) {
     source_output_file_path: data.source_output_file_path,
     build_id: data.build_id,
     clsiServerId: data.clsiServerId,
+    importedAt: data.importedAt,
   }
 }
 

+ 1 - 0
services/web/app/src/Features/LinkedFiles/UrlAgent.js

@@ -63,6 +63,7 @@ function _sanitizeData(data) {
   return {
     provider: data.provider,
     url: UrlHelper.prependHttpIfNeeded(data.url),
+    importedAt: data.importedAt,
   }
 }
 

+ 14 - 0
services/web/test/acceptance/src/LinkedFilesTests.js

@@ -1,6 +1,7 @@
 const { expect } = require('chai')
 const _ = require('lodash')
 const fs = require('fs')
+const timekeeper = require('timekeeper')
 
 const Settings = require('@overleaf/settings')
 const User = require('./helpers/User').promises
@@ -23,6 +24,14 @@ LinkedUrlProxy.get('/', (req, res, next) => {
 })
 
 describe('LinkedFiles', function () {
+  before(function () {
+    timekeeper.freeze(new Date())
+  })
+
+  after(function () {
+    timekeeper.reset()
+  })
+
   let projectOne, projectOneId, projectOneRootFolderId
   let projectTwo, projectTwoId, projectTwoRootFolderId
   const sourceDocName = 'test.txt'
@@ -129,6 +138,7 @@ describe('LinkedFiles', function () {
         provider: 'project_file',
         source_project_id: projectTwoId,
         source_entity_path: `/${sourceDocName}`,
+        importedAt: new Date().toISOString(),
       })
       expect(firstFile.name).to.equal('test-link.txt')
 
@@ -264,6 +274,7 @@ describe('LinkedFiles', function () {
       expect(file.linkedFileData).to.deep.equal({
         provider: 'url',
         url: 'http://example.com/foo',
+        importedAt: new Date().toISOString(),
       })
       ;({ response, body } = await owner.doRequest(
         'get',
@@ -303,6 +314,7 @@ describe('LinkedFiles', function () {
       expect(file.linkedFileData).to.deep.equal({
         provider: 'url',
         url: 'http://example.com/bar',
+        importedAt: new Date().toISOString(),
       })
       ;({ response, body } = await owner.doRequest(
         'get',
@@ -405,6 +417,7 @@ describe('LinkedFiles', function () {
       expect(file.linkedFileData).to.deep.equal({
         provider: 'url',
         url: 'http://example.com/foo',
+        importedAt: new Date().toISOString(),
       })
       ;({ response, body } = await owner.doRequest(
         'get',
@@ -460,6 +473,7 @@ describe('LinkedFiles', function () {
         source_project_id: projectTwoId,
         source_output_file_path: 'project.pdf',
         build_id: '1234-abcd',
+        importedAt: new Date().toISOString(),
       })
       expect(firstFile.name).to.equal('test.pdf')
 

+ 139 - 0
services/web/test/unit/src/LinkedFiles/LinkedFilesControllerTests.js

@@ -0,0 +1,139 @@
+const { expect } = require('chai')
+const SandboxedModule = require('sandboxed-module')
+const sinon = require('sinon')
+const modulePath =
+  '../../../../app/src/Features/LinkedFiles/LinkedFilesController'
+
+describe('LinkedFilesController', function () {
+  beforeEach(function () {
+    this.fakeTime = new Date()
+    this.clock = sinon.useFakeTimers(this.fakeTime.getTime())
+  })
+
+  afterEach(function () {
+    this.clock.restore()
+  })
+
+  beforeEach(function () {
+    this.userId = 'user-id'
+    this.Agent = {
+      createLinkedFile: sinon.stub().yields(),
+      refreshLinkedFile: sinon.stub().yields(),
+    }
+    this.projectId = 'projectId'
+    this.provider = 'provider'
+    this.name = 'linked-file-name'
+    this.data = { customAgentData: 'foo' }
+    this.LinkedFilesHandler = {
+      getFileById: sinon.stub(),
+    }
+    this.AnalyticsManager = {}
+    this.SessionManager = {
+      getLoggedInUserId: sinon.stub().returns(this.userId),
+    }
+    this.EditorRealTimeController = {}
+    this.ReferencesHandler = {}
+    this.UrlAgent = {}
+    this.ProjectFileAgent = {}
+    this.ProjectOutputFileAgent = {}
+    this.EditorController = {}
+    this.ProjectLocator = {}
+    this.logger = {}
+    this.settings = { enabledLinkedFileTypes: [] }
+    this.LinkedFilesController = SandboxedModule.require(modulePath, {
+      requires: {
+        '../Authentication/SessionManager': this.SessionManager,
+        '../../../../app/src/Features/Analytics/AnalyticsManager':
+          this.AnalyticsManager,
+        './LinkedFilesHandler': this.LinkedFilesHandler,
+        '../Editor/EditorRealTimeController': this.EditorRealTimeController,
+        '../References/ReferencesHandler': this.ReferencesHandler,
+        './UrlAgent': this.UrlAgent,
+        './ProjectFileAgent': this.ProjectFileAgent,
+        './ProjectOutputFileAgent': this.ProjectOutputFileAgent,
+        '../Editor/EditorController': this.EditorController,
+        '../Project/ProjectLocator': this.ProjectLocator,
+        '@overleaf/logger': this.logger,
+        '@overleaf/settings': this.settings,
+      },
+    })
+    this.LinkedFilesController._getAgent = sinon.stub().returns(this.Agent)
+  })
+
+  describe('createLinkedFile', function () {
+    beforeEach(function () {
+      this.req = {
+        params: { project_id: this.projectId },
+        body: {
+          name: this.name,
+          provider: this.provider,
+          data: this.data,
+        },
+      }
+      this.next = sinon.stub()
+    })
+
+    it('sets importedAt timestamp on linkedFileData', function (done) {
+      this.next = sinon.stub().callsFake(() => done('unexpected error'))
+      this.res = {
+        json: () => {
+          expect(this.Agent.createLinkedFile).to.have.been.calledWith(
+            this.projectId,
+            { ...this.data, importedAt: this.fakeTime.toISOString() },
+            this.name,
+            undefined,
+            this.userId
+          )
+          done()
+        },
+      }
+      this.LinkedFilesController.createLinkedFile(this.req, this.res, this.next)
+    })
+  })
+  describe('refreshLinkedFiles', function () {
+    beforeEach(function () {
+      this.data.provider = this.provider
+      this.file = {
+        name: this.name,
+        linkedFileData: {
+          ...this.data,
+          importedAt: new Date(2020, 1, 1).toISOString(),
+        },
+      }
+      this.LinkedFilesHandler.getFileById
+        .withArgs(this.projectId, 'file-id')
+        .yields(null, this.file, 'fake-path', {
+          _id: 'parent-folder-id',
+        })
+      this.req = {
+        params: { project_id: this.projectId, file_id: 'file-id' },
+        body: {},
+      }
+      this.next = sinon.stub()
+    })
+
+    it('resets importedAt timestamp on linkedFileData', function (done) {
+      this.next = sinon.stub().callsFake(() => done('unexpected error'))
+      this.res = {
+        json: () => {
+          expect(this.Agent.refreshLinkedFile).to.have.been.calledWith(
+            this.projectId,
+            {
+              ...this.data,
+              importedAt: this.fakeTime.toISOString(),
+            },
+            this.name,
+            'parent-folder-id',
+            this.userId
+          )
+          done()
+        },
+      }
+      this.LinkedFilesController.refreshLinkedFile(
+        this.req,
+        this.res,
+        this.next
+      )
+    })
+  })
+})