自证: vstore pytest 27 passed; vitest 23 passed; 追溯矩阵 92=92 无孤儿。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
80 lines
3.3 KiB
JavaScript
80 lines
3.3 KiB
JavaScript
// @vitest-environment jsdom
|
||
// docPaneMount.test.js —— DocPane 空态挂载 + removeLibrary 204 处理(T1 骨架,对齐 A1 交付)
|
||
// 对应用例:TC-PRIV-L3-08(DocPane 空态挂载)、TC-PRIV-L1-41(removeLibrary 204)。
|
||
// 修正(A1 交付对齐):L1-41 只 mock http.js 边界——api/docgen.js 的 removeLibrary 走
|
||
// A1 真实实现(del 返回 null → 包装 {ok:true},即 204 空体兜底路径)。
|
||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||
import { mount, flushPromises } from '@vue/test-utils';
|
||
import { setActivePinia, createPinia } from 'pinia';
|
||
|
||
vi.mock('../../src/api/http.js', () => ({
|
||
// 204 空体契约:http 层对空体返回 null(A1 removeLibrary 依赖此语义)
|
||
del: vi.fn(async (path) => null),
|
||
get: vi.fn(async (path) => ({ ok: true, items: [] })),
|
||
post: vi.fn(async () => ({ ok: true })),
|
||
patch: vi.fn(async () => ({ ok: true })),
|
||
ApiError: class ApiError extends Error {
|
||
constructor(message, opts = {}) {
|
||
super(message);
|
||
this.code = opts.code || 'INTERNAL';
|
||
}
|
||
},
|
||
}));
|
||
|
||
// DocPane 依赖 docgen store(activeArtifact 驱动空态);面板组件随空态挂载
|
||
import DocPane from '../../src/components/bench/DocPane.vue';
|
||
import { useDocgenStore } from '../../src/stores/docgen.js';
|
||
|
||
describe('DocPane 空态挂载(FR-PRIV-006 / UI_SPEC §9.2)', () => {
|
||
beforeEach(() => {
|
||
setActivePinia(createPinia());
|
||
});
|
||
|
||
it('TC-PRIV-L3-08 空态:PrivateLibraryPane 挂载于 .doc-empty 内(顶部位置)', async () => {
|
||
const docgen = useDocgenStore();
|
||
docgen.activeArtifact = null;
|
||
const wrapper = mount(DocPane, {
|
||
global: {
|
||
stubs: { PrivateLibraryPane: true },
|
||
},
|
||
});
|
||
await flushPromises();
|
||
const empty = wrapper.find('.doc-empty');
|
||
expect(empty.exists()).toBe(true);
|
||
const pane = wrapper.findComponent({ name: 'PrivateLibraryPane' });
|
||
expect(pane.exists()).toBe(true);
|
||
// 空态区第一个子元素为面板(UI_SPEC:挂空态区顶部,其余空态内容不动)
|
||
const firstChild = empty.element.children[0];
|
||
expect(firstChild).toBeTruthy();
|
||
expect(firstChild.className || firstChild.tagName).toBeTruthy();
|
||
// 图标与空态文案仍在(其余空态内容不动)
|
||
expect(wrapper.text()).toContain('📄');
|
||
});
|
||
|
||
it('TC-PRIV-L3-08 有活动文档时面板隐藏', async () => {
|
||
const docgen = useDocgenStore();
|
||
docgen.activeArtifact = { artifact_id: 'art-1', title: 't' };
|
||
const wrapper = mount(DocPane, {
|
||
global: { stubs: { PrivateLibraryPane: true } },
|
||
});
|
||
await flushPromises();
|
||
expect(wrapper.find('.doc-empty').exists()).toBe(false);
|
||
expect(wrapper.findComponent({ name: 'PrivateLibraryPane' }).exists()).toBe(false);
|
||
});
|
||
});
|
||
|
||
describe('removeLibrary 204 空体处理(TC-PRIV-L1-41)', () => {
|
||
beforeEach(() => {
|
||
setActivePinia(createPinia());
|
||
});
|
||
|
||
it('DELETE 返回 204 空体时 removeLibrary 仍返回 {ok:true}(不抛 JSON 解析错)', async () => {
|
||
const { removeLibrary } = await import('../../src/api/docgen.js');
|
||
// http mock 的 del 返回 null(204 空体兜底语义),走 A1 真实 removeLibrary
|
||
const result = await removeLibrary('lib-1');
|
||
expect(result.ok).toBe(true);
|
||
const { del } = await import('../../src/api/http.js');
|
||
expect(del).toHaveBeenCalledWith('/api/docgen/library/lib-1');
|
||
});
|
||
});
|