Files
PlantAI-rag-new/ui/tests/private_docs/components.private.test.js
2026-09-07 22:41:36 +08:00

90 lines
3.5 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// @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);
});
});