This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
import { readFileSync } from 'node:fs';
|
||||
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import {
|
||||
ARCHIVE_API_BASE,
|
||||
archiveErrorText,
|
||||
normalizeArchiveFileDetail,
|
||||
normalizeArchivePackage,
|
||||
} from '../src/api/archive';
|
||||
|
||||
describe('archive R4 frontend contracts', () => {
|
||||
it('uses the documented plural archive API prefix', () => {
|
||||
expect(ARCHIVE_API_BASE).toBe('/archives');
|
||||
});
|
||||
|
||||
it('normalizes nullable archive response collections and action allowlists', () => {
|
||||
const packageView = normalizeArchivePackage({
|
||||
allowedActions: null,
|
||||
items: [{ allowedActions: null }],
|
||||
objectSnapshots: null,
|
||||
actions: undefined,
|
||||
} as any);
|
||||
const detail = normalizeArchiveFileDetail({
|
||||
file: { allowedActions: null },
|
||||
versions: null,
|
||||
borrows: [{ allowedActions: undefined }],
|
||||
} as any);
|
||||
|
||||
expect(packageView).toMatchObject({
|
||||
allowedActions: [],
|
||||
items: [{ allowedActions: [] }],
|
||||
objectSnapshots: [],
|
||||
actions: [],
|
||||
});
|
||||
expect(detail).toMatchObject({ file: { allowedActions: [] }, versions: [], borrows: [{ allowedActions: [] }] });
|
||||
});
|
||||
|
||||
it('renders actionable error classes without dropping server field errors', () => {
|
||||
expect(archiveErrorText({ status: 401 }, '失败')).toContain('登录会话已失效');
|
||||
expect(archiveErrorText({ status: 403 }, '失败')).toContain('没有访问');
|
||||
expect(archiveErrorText({ status: 404 }, '失败')).toContain('不存在');
|
||||
expect(archiveErrorText({ status: 409 }, '失败')).toContain('数据已发生变化');
|
||||
expect(archiveErrorText({ status: 422, fieldErrors: { dueAt: '日期无效' } }, '失败')).toContain('日期无效');
|
||||
expect(archiveErrorText({ status: 503 }, '失败')).toContain('服务处理失败');
|
||||
});
|
||||
|
||||
it('keeps downloaded blob URLs alive until the browser consumes them', () => {
|
||||
const page = readFileSync(new URL('../src/pages/archives/ArchiveFilesPage.vue', import.meta.url), 'utf8');
|
||||
expect(page).toContain('window.setTimeout(() => URL.revokeObjectURL(url), 60_000)');
|
||||
});
|
||||
|
||||
it('exposes a recoverable workflow for quarantined archive files', () => {
|
||||
const api = readFileSync(new URL('../src/api/archive.ts', import.meta.url), 'utf8');
|
||||
const page = readFileSync(new URL('../src/pages/archives/ArchiveFilesPage.vue', import.meta.url), 'utf8');
|
||||
const rescanPath = '`$' + '{ARCHIVE_API_BASE}/files/$' + '{publicId}/rescan`';
|
||||
expect(api).toContain('export function rescanArchiveFile');
|
||||
expect(api).toContain(rescanPath);
|
||||
expect(api).toContain("commandHeaders('archive-file-rescan'");
|
||||
expect(page).toContain("row.allowedActions.includes('RESCAN')");
|
||||
expect(page).toContain('@click="rescanFile(row)"');
|
||||
expect(page).toContain("fileFilters.scanStatus = 'QUARANTINED'");
|
||||
expect(page).toContain('文件已通过安全检查并恢复可用');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user