上传文档跨端不可访问修复(ISSUE-20260927-upload-doc-cross-device): - 迁移 00076:freeform_documents 增加 source_filename/mime/size_bytes/asset_id - freedoc:Create/Get/List 读写源文件元数据,负值拒绝 - 前端:注册前全部附件先登记 CAS 并预读文本正文;文本正文嵌入注册 markdown;跨端恢复 sourceType/fileMeta 路由回文件预览器 - 大小显示 formatFileSize(<512B 不再显示 0 KB) - E2E 新增 FS-UPLOAD-02 跨浏览器上下文可访问性用例 回归:go vet/arch-check/go test -short(隔离 PG)+ web npm test/build 全绿; 存量无元数据旧文档不可恢复(重新上传即可)。
75 lines
2.5 KiB
TypeScript
75 lines
2.5 KiB
TypeScript
import { describe, it } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { deliverableFromServerSummary } from './freeformDocSync';
|
|
import type { FreeformDocSummary } from '../api/freeformDoc';
|
|
|
|
function summary(overrides: Partial<FreeformDocSummary> = {}): FreeformDocSummary {
|
|
return {
|
|
doc_id: 'doc-free-1-2',
|
|
project_id: 7,
|
|
owner_user_id: 2,
|
|
title: 'upload-note',
|
|
space: 'my_private',
|
|
current_version_id: 1,
|
|
current_sha256: 'x',
|
|
created_at: '2026-09-27T07:46:45Z',
|
|
updated_at: '2026-09-27T07:46:45Z',
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
const user = { id: 2, name: 'E2E编制-mui2xpg2' };
|
|
|
|
describe('deliverableFromServerSummary', () => {
|
|
it('restores uploaded file routing metadata from server facts', () => {
|
|
const d = deliverableFromServerSummary(
|
|
summary({
|
|
source_filename: 'upload-mui2xpg2.txt',
|
|
source_mime_type: 'text/plain',
|
|
source_size_bytes: 41,
|
|
source_asset_id: 501,
|
|
}),
|
|
7,
|
|
user,
|
|
);
|
|
assert.equal(d.sourceType, 'uploaded_file');
|
|
assert.equal(d.fileMeta?.originalName, 'upload-mui2xpg2.txt');
|
|
// 回归:<512B 文件不得再显示 0 KB;字节数直接来自服务端事实源。
|
|
assert.equal(d.fileMeta?.size, '41 B');
|
|
assert.equal(d.fileMeta?.sizeBytes, 41);
|
|
assert.equal(d.fileMeta?.mimeType, 'text/plain');
|
|
assert.equal(d.fileMeta?.extension, 'txt');
|
|
assert.equal(d.fileMeta?.assetId, 501);
|
|
assert.equal(d.governanceMode, 'freeform');
|
|
assert.equal(d.space, 'my_private');
|
|
});
|
|
|
|
it('keeps plain freeform docs without upload metadata on the editor path', () => {
|
|
const d = deliverableFromServerSummary(summary(), 7, user);
|
|
assert.equal(d.sourceType, undefined);
|
|
assert.equal(d.fileMeta, undefined);
|
|
assert.equal(d.taskKey, 'freeform_doc');
|
|
});
|
|
|
|
it('handles legacy rows with filename but zero size gracefully', () => {
|
|
const d = deliverableFromServerSummary(
|
|
summary({ source_filename: 'old.bin', source_size_bytes: 0 }),
|
|
7,
|
|
user,
|
|
);
|
|
assert.equal(d.sourceType, 'uploaded_file');
|
|
assert.equal(d.fileMeta?.size, '未知大小');
|
|
assert.equal(d.fileMeta?.assetId, undefined);
|
|
});
|
|
|
|
it('maps shared space to shared category', () => {
|
|
const d = deliverableFromServerSummary(
|
|
summary({ space: 'project_shared', source_filename: 'shared.txt', source_size_bytes: 2048 }),
|
|
7,
|
|
user,
|
|
);
|
|
assert.equal(d.category, 'shared');
|
|
assert.equal(d.fileMeta?.size, '2 KB');
|
|
});
|
|
});
|