整理测试代码并清理文档引用
This commit is contained in:
@@ -1,117 +0,0 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { resolve } from "node:path";
|
||||
|
||||
const readAttachmentList = () => readFileSync(resolve(__dirname, "./AttachmentList.vue"), "utf8");
|
||||
|
||||
describe("AttachmentList permissions", () => {
|
||||
it("does not require project member list permission to render uploaders", () => {
|
||||
const source = readAttachmentList();
|
||||
|
||||
expect(source).not.toContain("listMembers");
|
||||
});
|
||||
|
||||
it("matches the contract-fee attachment table layout", () => {
|
||||
const source = readAttachmentList();
|
||||
|
||||
expect(source).toContain('prop="filename" :label="TEXT.common.labels.filename" min-width="360" show-overflow-tooltip');
|
||||
expect(source).toContain(':label="TEXT.common.labels.size" min-width="180"');
|
||||
expect(source).toContain(':label="TEXT.common.labels.uploader" min-width="180"');
|
||||
expect(source).toContain('prop="uploaded_at" :label="TEXT.common.labels.uploadedAt" min-width="180" show-overflow-tooltip');
|
||||
expect(source).toContain(':label="TEXT.common.labels.actions" min-width="180"');
|
||||
expect(source).not.toContain('width="160"');
|
||||
expect(source).toContain('class="attachment-actions"');
|
||||
expect(source).toContain("flex-wrap: nowrap;");
|
||||
expect(source).toContain("gap: 4px;");
|
||||
});
|
||||
|
||||
it("can aggregate multiple attachment entity types into one table with an attachment type column", () => {
|
||||
const source = readAttachmentList();
|
||||
|
||||
expect(source).toContain("entityGroups?: AttachmentEntityGroup[]");
|
||||
expect(source).toContain('v-if="hasEntityGroups"');
|
||||
expect(source).toContain('label="附件类型"');
|
||||
expect(source).toContain("scope.row.attachment_type_label");
|
||||
expect(source).toContain("fetchAttachments(props.studyId, group.entityType, props.entityId)");
|
||||
expect(source).toContain("attachment_type_label: group.label");
|
||||
expect(source).toContain("attachment_entity_type: group.entityType");
|
||||
});
|
||||
|
||||
it("can reload attachments when the parent refresh key changes", () => {
|
||||
const source = readAttachmentList();
|
||||
|
||||
expect(source).toContain("refreshKey?: number");
|
||||
expect(source).toContain("() => props.refreshKey");
|
||||
expect(source).toContain("load();");
|
||||
});
|
||||
|
||||
it("can hide the uploader while keeping the attachment table visible", () => {
|
||||
const source = readAttachmentList();
|
||||
|
||||
expect(source).toContain("hideUploader?: boolean");
|
||||
expect(source).toContain("canShowUploader");
|
||||
expect(source).toContain("!props.hideUploader && canCreate.value");
|
||||
});
|
||||
|
||||
it("hides the default attachment title row when uploader is hidden and no explicit title is provided", () => {
|
||||
const source = readAttachmentList();
|
||||
|
||||
expect(source).toContain("const showHeader = computed(() => !!props.title || canShowUploader.value)");
|
||||
expect(source).toContain('<div v-if="showHeader" class="header">');
|
||||
});
|
||||
|
||||
it("uses the shared upload implementation for table-mode immediate uploads", () => {
|
||||
const source = readAttachmentList();
|
||||
|
||||
expect(source).not.toContain("AttachmentUploader");
|
||||
expect(source).toContain(':http-request="uploadImmediate"');
|
||||
expect(source).toContain("const uploadImmediate = async");
|
||||
expect(source).toContain("await uploadFile(group, file, props.entityId)");
|
||||
expect(source).toContain("ElMessage.success(TEXT.common.messages.uploadSuccess)");
|
||||
expect(source).toContain("load();");
|
||||
});
|
||||
|
||||
it("supports upload-card mode without rendering the table header", () => {
|
||||
const source = readAttachmentList();
|
||||
|
||||
expect(source).toContain('mode?: "table" | "upload"');
|
||||
expect(source).toContain("displayMode");
|
||||
expect(source).toContain('v-if="displayMode === \'table\'"');
|
||||
expect(source).toContain("v-else");
|
||||
expect(source).toContain('class="attachment-upload-card"');
|
||||
expect(source).toContain(':auto-upload="false"');
|
||||
expect(source).toContain("queuePendingUpload(group.key, file)");
|
||||
expect(source).toContain("点击上传文件");
|
||||
});
|
||||
|
||||
it("allows create forms to choose attachments before the entity id exists", () => {
|
||||
const source = readAttachmentList();
|
||||
|
||||
expect(source).toContain("const pendingSnapshot = () =>");
|
||||
expect(source).toContain("const uploadPending = async");
|
||||
expect(source).toContain("const targetEntityId = entityId || props.entityId");
|
||||
expect(source).toContain("defineExpose({");
|
||||
expect(source).toContain("pendingSnapshot");
|
||||
expect(source).toContain("uploadPending");
|
||||
expect(source).toContain("pendingMap[group.key] = remainItems");
|
||||
expect(source).toContain("throw new Error(TEXT.common.messages.uploadFailed)");
|
||||
});
|
||||
|
||||
it("fails pending upload when selected files have no saved entity id", () => {
|
||||
const source = readAttachmentList();
|
||||
|
||||
expect(source).toContain("const hasPendingUploads = computed");
|
||||
expect(source).toContain("if (!targetEntityId && hasPendingUploads.value)");
|
||||
expect(source).toContain("throw new Error(TEXT.common.messages.uploadFailed)");
|
||||
});
|
||||
|
||||
it("uses entity groups as upload groups when an editor has multiple attachment types", () => {
|
||||
const source = readAttachmentList();
|
||||
|
||||
expect(source).toContain("const uploadGroups = computed");
|
||||
expect(source).toContain("props.entityGroups.map((group)");
|
||||
expect(source).toContain("key: group.entityType");
|
||||
expect(source).toContain("entityType: group.entityType");
|
||||
expect(source).toContain("uploadAttachment(props.studyId, group.entityType, targetEntityId, file");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user