Files
Agent-System/internal/freedoc/create_document_test.go
T
weichen 88e33282db fix(freedoc): persist uploaded file metadata and text body server-side
上传文档跨端不可访问修复(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 全绿;
存量无元数据旧文档不可恢复(重新上传即可)。
2026-09-27 07:45:15 +00:00

164 lines
6.0 KiB
Go

package freedoc_test
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"chat-agent-system/internal/docrevision"
"chat-agent-system/internal/freedoc"
)
func TestCreateDocument_ClientKeyIdempotentAndBootstrapsLedger(t *testing.T) {
ctx := context.Background()
rev := docrevision.NewService(nil)
svc := freedoc.NewService(nil, nil)
svc.SetDocRevision(rev)
detail, err := svc.CreateDocument(ctx, 42, freedoc.CreateFreeformDocRequest{
ProjectID: 7,
Title: "超声探头规格.pdf",
ContentMarkdown: "# 超声探头规格\n\n上传正文基线\n",
Space: "my_private",
ClientKey: "doc-upload-1789263145197-0",
})
require.NoError(t, err)
require.NotNil(t, detail)
assert.True(t, len(detail.Document.DocID) > 0)
assert.True(t, detail.Document.DocID[:8] == "doc-free" || detail.Document.DocID[:9] == "doc-free-")
require.NotNil(t, detail.Document.ClientKey)
assert.Equal(t, "doc-upload-1789263145197-0", *detail.Document.ClientKey)
assert.Equal(t, "freeform", detail.Document.GovernanceMode)
// source_content_sha256 must remain content fingerprint — never client_key prefix
assert.NotContains(t, detail.Document.SourceContentSHA256, "doc-upload")
assert.NotContains(t, detail.Document.SourceContentSHA256, "client_key")
assert.Len(t, detail.Document.SourceContentSHA256, 64)
st, err := rev.GetRevisionState(ctx, detail.Document.DocID)
require.NoError(t, err)
assert.GreaterOrEqual(t, st.CurrentVersionNo, 1)
again, err := svc.CreateDocument(ctx, 42, freedoc.CreateFreeformDocRequest{
ProjectID: 7,
Title: "超声探头规格.pdf",
ContentMarkdown: "# 超声探头规格\n\n上传正文基线\n",
ClientKey: "doc-upload-1789263145197-0",
})
require.NoError(t, err)
assert.Equal(t, detail.Document.DocID, again.Document.DocID)
otherUser, err := svc.CreateDocument(ctx, 99, freedoc.CreateFreeformDocRequest{
ProjectID: 7,
Title: "他人同名键",
ContentMarkdown: "# other\n",
ClientKey: "doc-upload-1789263145197-0",
})
require.NoError(t, err)
assert.NotEqual(t, detail.Document.DocID, otherUser.Document.DocID)
}
func TestCreateDocument_AcceptsSnowflakeProjectID(t *testing.T) {
// projects.id is BIGINT; freeform must accept IDs above int4 max (regression: int4 encode 500).
const snowflakeProjectID int64 = 1789095399489
svc := freedoc.NewService(nil, nil)
detail, err := svc.CreateDocument(context.Background(), 42, freedoc.CreateFreeformDocRequest{
ProjectID: snowflakeProjectID,
Title: "snowflake.pdf",
ContentMarkdown: "# snowflake\n",
Space: "my_private",
})
require.NoError(t, err)
assert.Equal(t, snowflakeProjectID, detail.Document.ProjectID)
list, err := svc.ListDocuments(context.Background(), 42, snowflakeProjectID, "my_private")
require.NoError(t, err)
require.Len(t, list, 1)
assert.Equal(t, snowflakeProjectID, list[0].ProjectID)
}
func TestCreateDocument_RejectsEmptyContent(t *testing.T) {
svc := freedoc.NewService(nil, nil)
_, err := svc.CreateDocument(context.Background(), 1, freedoc.CreateFreeformDocRequest{
ProjectID: 1, Title: "x", ContentMarkdown: " ",
})
assert.ErrorIs(t, err, freedoc.ErrInvalidParam)
}
func TestCreateDocument_RequiresProjectIDAndPrivateSpace(t *testing.T) {
svc := freedoc.NewService(nil, nil)
_, err := svc.CreateDocument(context.Background(), 1, freedoc.CreateFreeformDocRequest{
ProjectID: 0, Title: "x", ContentMarkdown: "# x\n",
})
assert.ErrorIs(t, err, freedoc.ErrInvalidParam)
assert.Contains(t, err.Error(), "project_id")
_, err = svc.CreateDocument(context.Background(), 1, freedoc.CreateFreeformDocRequest{
ProjectID: 1, Title: "x", ContentMarkdown: "# x\n", Space: "project_shared",
})
assert.ErrorIs(t, err, freedoc.ErrInvalidParam)
assert.Contains(t, err.Error(), "my_private")
}
func TestCreateDocument_PersistsSourceFileMetadata(t *testing.T) {
ctx := context.Background()
svc := freedoc.NewService(nil, nil)
detail, err := svc.CreateDocument(ctx, 42, freedoc.CreateFreeformDocRequest{
ProjectID: 7,
Title: "upload-note",
ContentMarkdown: "# upload-note\n\n临床需求摘要占位\n",
Space: "my_private",
ClientKey: "doc-upload-meta-1",
SourceFilename: "upload-note.txt",
SourceMimeType: "text/plain",
SourceSizeBytes: 41,
SourceAssetID: 501,
})
require.NoError(t, err)
require.NotNil(t, detail)
assert.Equal(t, "upload-note.txt", detail.Document.SourceFilename)
assert.Equal(t, "text/plain", detail.Document.SourceMimeType)
assert.EqualValues(t, 41, detail.Document.SourceSizeBytes)
assert.EqualValues(t, 501, detail.Document.SourceAssetID)
// 列表概要同样带出上传元数据(前端跨端恢复预览路由的事实源)。
list, err := svc.ListDocuments(ctx, 42, 7, "my_private")
require.NoError(t, err)
require.Len(t, list, 1)
assert.Equal(t, "upload-note.txt", list[0].SourceFilename)
assert.EqualValues(t, 41, list[0].SourceSizeBytes)
assert.EqualValues(t, 501, list[0].SourceAssetID)
// 非上传文档元数据恒为零值,不影响既有编辑器路径。
plain, err := svc.CreateDocument(ctx, 42, freedoc.CreateFreeformDocRequest{
ProjectID: 7,
Title: "plain-note",
ContentMarkdown: "# plain\n",
ClientKey: "doc-upload-meta-2",
})
require.NoError(t, err)
assert.Empty(t, plain.Document.SourceFilename)
assert.EqualValues(t, 0, plain.Document.SourceSizeBytes)
}
func TestCreateDocument_RejectsNegativeSourceMetadata(t *testing.T) {
ctx := context.Background()
svc := freedoc.NewService(nil, nil)
_, err := svc.CreateDocument(ctx, 42, freedoc.CreateFreeformDocRequest{
ProjectID: 7,
Title: "bad",
ContentMarkdown: "# bad\n",
SourceSizeBytes: -1,
})
assert.ErrorIs(t, err, freedoc.ErrInvalidParam)
_, err = svc.CreateDocument(ctx, 42, freedoc.CreateFreeformDocRequest{
ProjectID: 7,
Title: "bad",
ContentMarkdown: "# bad\n",
SourceAssetID: -5,
})
assert.ErrorIs(t, err, freedoc.ErrInvalidParam)
}