mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-05-23 17:19:37 +02:00
Merge pull request #32892 from overleaf/mj-history-file-metadata
[history-v1] Add missing properties to zod schemas GitOrigin-RevId: e16faf56a9b294516152383585493b38685b8d15
This commit is contained in:
committed by
Copybot
parent
4ce5620b1d
commit
4173c98c48
@@ -8,21 +8,28 @@ const hexHashPattern = new RegExp(Blob.HEX_HASH_RX_STRING)
|
||||
const fileSchema = z
|
||||
.object({
|
||||
hash: z.string().optional(),
|
||||
rangesHash: z.string().optional(),
|
||||
byteLength: z.number().int().nullable().optional(),
|
||||
stringLength: z.number().int().nullable().optional(),
|
||||
metadata: z.object({}).passthrough().optional(),
|
||||
})
|
||||
.passthrough()
|
||||
|
||||
const snapshotSchema = z.object({
|
||||
files: z.record(z.string(), fileSchema),
|
||||
})
|
||||
|
||||
const v2DocVersionsSchema = z.object({
|
||||
pathname: z.string().optional(),
|
||||
v: z.number().int().optional(),
|
||||
})
|
||||
|
||||
const snapshotSchema = z.object({
|
||||
files: z.record(z.string(), fileSchema),
|
||||
projectVersion: z.string().optional(),
|
||||
v2DocVersions: z
|
||||
.record(z.string(), v2DocVersionsSchema)
|
||||
.nullable()
|
||||
.optional(),
|
||||
timestamp: z.string().optional(),
|
||||
})
|
||||
|
||||
const operationSchema = z
|
||||
.object({
|
||||
pathname: z.string().optional(),
|
||||
|
||||
@@ -22,6 +22,7 @@ const TextOperation = core.TextOperation
|
||||
const V2DocVersions = core.V2DocVersions
|
||||
|
||||
const knex = require('../../../../storage').knex
|
||||
const blobHash = require('../../../../storage/lib/blob_hash')
|
||||
|
||||
describe('history import', function () {
|
||||
beforeEach(cleanup.everything)
|
||||
@@ -513,6 +514,124 @@ describe('history import', function () {
|
||||
})
|
||||
})
|
||||
|
||||
it('preserves rangesHash when importing a file', async function () {
|
||||
const testProjectId = '1'
|
||||
const testFilePathname = 'main.tex'
|
||||
// hello.txt contains "Olá mundo\n" (10 UTF-8 chars).
|
||||
const rangesContent = JSON.stringify({
|
||||
comments: [
|
||||
{
|
||||
id: 'comment-1',
|
||||
ranges: [{ pos: 0, length: 3 }],
|
||||
resolved: false,
|
||||
},
|
||||
],
|
||||
trackedChanges: [
|
||||
{
|
||||
range: { pos: 4, length: 5 },
|
||||
tracking: {
|
||||
type: 'insert',
|
||||
userId: 'user-1',
|
||||
ts: '2024-01-01T00:00:00.000Z',
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
const testRangesHash = blobHash.fromString(rangesContent)
|
||||
const testFile = File.fromHash(testFiles.HELLO_TXT_HASH, testRangesHash)
|
||||
|
||||
const [contentResponse, rangesResponse] = await Promise.all([
|
||||
fetch(
|
||||
testServer.url(
|
||||
`/api/projects/${testProjectId}/blobs/${testFiles.HELLO_TXT_HASH}`
|
||||
),
|
||||
{
|
||||
method: 'PUT',
|
||||
body: fs.createReadStream(testFiles.path('hello.txt')),
|
||||
headers: { Authorization: testServer.basicAuthHeader },
|
||||
}
|
||||
),
|
||||
fetch(
|
||||
testServer.url(
|
||||
`/api/projects/${testProjectId}/blobs/${testRangesHash}`
|
||||
),
|
||||
{
|
||||
method: 'PUT',
|
||||
body: rangesContent,
|
||||
headers: { Authorization: testServer.basicAuthHeader },
|
||||
}
|
||||
),
|
||||
])
|
||||
expect(contentResponse.ok).to.be.true
|
||||
expect(rangesResponse.ok).to.be.true
|
||||
|
||||
const testSnapshot = new Snapshot()
|
||||
testSnapshot.addFile(testFilePathname, testFile)
|
||||
const importResponse =
|
||||
await basicAuthClient.apis.ProjectImport.importSnapshot1({
|
||||
project_id: testProjectId,
|
||||
snapshot: testSnapshot.toRaw(),
|
||||
})
|
||||
expect(importResponse.obj.projectId).to.equal(testProjectId)
|
||||
|
||||
const historyResponse =
|
||||
await clientForProject.apis.Project.getLatestHistory({
|
||||
project_id: testProjectId,
|
||||
})
|
||||
const chunk = ChunkResponse.fromRaw(historyResponse.obj).getChunk()
|
||||
const file = chunk.getSnapshot().getFile(testFilePathname)
|
||||
expect(file.getRangesHash()).to.equal(testRangesHash)
|
||||
})
|
||||
|
||||
it('preserves projectVersion, v2DocVersions and timestamp on snapshot import', async function () {
|
||||
const testProjectId = '1'
|
||||
const testFilePathname = 'empty.tex'
|
||||
const testDocId = '000000000000000000000001'
|
||||
const testProjectVersion = '12345.0'
|
||||
const testV2DocVersions = new V2DocVersions({
|
||||
[testDocId]: { pathname: testFilePathname, v: 123 },
|
||||
})
|
||||
const testTimestamp = new Date('2024-01-01T00:00:00.000Z')
|
||||
|
||||
const response = await fetch(
|
||||
testServer.url(
|
||||
`/api/projects/${testProjectId}/blobs/${File.EMPTY_FILE_HASH}`
|
||||
),
|
||||
{
|
||||
method: 'PUT',
|
||||
body: fs.createReadStream(testFiles.path('empty.tex')),
|
||||
headers: { Authorization: testServer.basicAuthHeader },
|
||||
}
|
||||
)
|
||||
expect(response.ok).to.be.true
|
||||
|
||||
const testSnapshot = new Snapshot()
|
||||
testSnapshot.addFile(testFilePathname, File.fromHash(File.EMPTY_FILE_HASH))
|
||||
testSnapshot.setProjectVersion(testProjectVersion)
|
||||
testSnapshot.setV2DocVersions(testV2DocVersions)
|
||||
testSnapshot.setTimestamp(testTimestamp)
|
||||
|
||||
const importResponse =
|
||||
await basicAuthClient.apis.ProjectImport.importSnapshot1({
|
||||
project_id: testProjectId,
|
||||
snapshot: testSnapshot.toRaw(),
|
||||
})
|
||||
expect(importResponse.obj.projectId).to.equal(testProjectId)
|
||||
|
||||
const historyResponse =
|
||||
await clientForProject.apis.Project.getLatestHistory({
|
||||
project_id: testProjectId,
|
||||
})
|
||||
const snapshot = ChunkResponse.fromRaw(historyResponse.obj)
|
||||
.getChunk()
|
||||
.getSnapshot()
|
||||
expect(snapshot.getProjectVersion()).to.equal(testProjectVersion)
|
||||
expect(snapshot.getV2DocVersions()).to.deep.equal(testV2DocVersions)
|
||||
expect(snapshot.getTimestamp()?.toISOString()).to.equal(
|
||||
testTimestamp.toISOString()
|
||||
)
|
||||
})
|
||||
|
||||
it('rejects text operations on binary files', function () {
|
||||
const testProjectId = '1'
|
||||
const testFilePathname = 'main.tex'
|
||||
|
||||
Reference in New Issue
Block a user