Files

90 lines
3.5 KiB
JavaScript
Raw Permalink Normal View History

// @vitest-environment jsdom
// components.private.test.js —— AssistantMessage private_doc 块渲染(T1 骨架,对齐 A1 交付)
// 对应用例:TC-PRIV-L3-01 ~ TC-PRIV-L3-03(docs/team/TEST_CASES_PRIVATE.md)
// 风格:沿用 tests/frontend/unit/b2/components.test.js(mount + DOM 断言)。
// A1 交付类名对齐:.private-doc-block / .private-doc-answer / .private-doc-item[data-private-item]。
import { describe, it, expect, beforeEach } from 'vitest';
import { mount } from '@vue/test-utils';
import { setActivePinia, createPinia } from 'pinia';
import AssistantMessage from '../../src/components/chat/AssistantMessage.vue';
function messageWithBlock(block) {
return {
id: 'm1',
role: 'assistant',
kind: 'qa',
status: 'done',
blocks: [
{ type: 'pipeline', status: 'done', steps: [] },
block,
],
raw: null,
created_at: '2026-09-01T00:00:00Z',
updated_at: '2026-09-01T00:00:01Z',
};
}
const BASE_BLOCK = {
type: 'private_doc',
answer: '依据[资料1],水稻SPL家族共19个成员。',
items: [
{ ref: 1, name: '水稻SPL资料.pdf', score: 0.92, snippet: '水稻SPL家族共有19个成员……' },
],
};
describe('AssistantMessage private_doc 块渲染(FR-PRIV-005)', () => {
beforeEach(() => {
setActivePinia(createPinia());
});
it('TC-PRIV-L3-01 卡体/标题/条目齐全', () => {
const wrapper = mount(AssistantMessage, {
props: { message: messageWithBlock(BASE_BLOCK) },
});
expect(wrapper.find('.private-doc-block').exists()).toBe(true);
expect(wrapper.text()).toContain('私有资料参考');
// 短答经 markdown 渲染为 HTML 后展示(引用编号文本)
expect(wrapper.find('.private-doc-answer').exists()).toBe(true);
expect(wrapper.text()).toContain('依据[资料1]');
// 条目:编号/名称/相关度(两位小数)/片段(A1 实现)
const itemEl = wrapper.find('.private-doc-item[data-private-item]');
expect(itemEl.exists()).toBe(true);
expect(itemEl.text()).toContain('[资料1]');
expect(itemEl.text()).toContain('水稻SPL资料.pdf');
expect(itemEl.text()).toContain('0.92');
expect(itemEl.text()).toContain('水稻SPL家族共有19个成员');
});
it('TC-PRIV-L3-02 answer 为空仅显示条目列表(无空白答区)', () => {
const block = { ...BASE_BLOCK, answer: '' };
const wrapper = mount(AssistantMessage, {
props: { message: messageWithBlock(block) },
});
expect(wrapper.find('.private-doc-block').exists()).toBe(true);
// UI_SPEC §9.1 空答态:不渲染空白答区(A1:v-if="b.answer")
expect(wrapper.find('.private-doc-answer').exists()).toBe(false);
expect(wrapper.find('.private-doc-item[data-private-item]').exists()).toBe(true);
});
it('TC-PRIV-L3-03 markdown 消毒:script 移除、**加粗** 渲染', () => {
const block = {
...BASE_BLOCK,
answer: '结论**成立**。<script>alert(1)</script>',
};
const wrapper = mount(AssistantMessage, {
props: { message: messageWithBlock(block) },
});
const html = wrapper.find('.private-doc-block').html();
expect(html).not.toContain('<script');
expect(html).not.toContain('alert(1)');
expect(html).toContain('<strong>成立</strong>');
});
it('无 private_doc 块的消息不渲染该卡(零回归)', () => {
const wrapper = mount(AssistantMessage, {
props: { message: messageWithBlock({ type: 'text', html: '<p>普通答案</p>' }) },
});
expect(wrapper.find('.private-doc-block').exists()).toBe(false);
});
});