Files
PlantAI-rag-new/tests/frontend/unit/edu/reformat.rules-summary.test.js
potaser e036301e1a feat(review): show format rules summary per target journal
- New summary row: shows the journal's rules (even if no diff applies)
- Fixes user confusion when switching journals yields same diff
- When all rules are null: 'no explicit format requirements'
- Vitest: add case for summary rendering
2026-10-13 11:22:52 +08:00

124 lines
4.8 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.
// tests/frontend/unit/edu/reformat.rules-summary.test.js
// 目标期刊规则摘要行(data-testid="rf-rules-summary"):
// 1) 有规则字段 + 有 diff → 摘要 + "已修改 N 处"
// 2) 规则全 null + diff=0 → "无强制约束" + "样本已满足该刊要求,无需修改"
// 背景:GB/BMC PB/Rice 规则相同、Frontiers 几乎无规则,用户切换期刊看不到 diff 差异,
// 即使 diff=0 也要展示"该刊要求什么",消除"没生效"错觉。
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { mount } from '@vue/test-utils';
import { createPinia, setActivePinia } from 'pinia';
import ReformatPanel from '../../../../ui/src/components/edu/panels/ReformatPanel.vue';
vi.mock('../../../../ui/src/api/review.js', async (importOriginal) => {
const actual = await importOriginal();
return {
...actual,
getJournals: vi.fn().mockResolvedValue({ ok: true, items: [] }),
getDirectory: vi.fn(),
reformatTex: vi.fn(),
compileTex: vi.fn(),
};
});
import { useEduStore } from '../../../../ui/src/stores/edu.js';
function mountWithResult(eduSeed) {
const pinia = createPinia();
setActivePinia(pinia);
const edu = useEduStore();
Object.assign(edu, eduSeed);
const wrapper = mount(ReformatPanel, { global: { plugins: [pinia] } });
return { wrapper, edu };
}
function resultWith(rules, changes) {
return {
ok: true,
job_id: 'abc123def456',
modified_tex: 'x',
changes,
warnings: [],
meta: {
filename: 'paper.tex',
journal_name: 'Molecular Plant',
rules_source: 'official',
rules_note: 'journals.json 期刊专属规则',
rules,
},
};
}
describe('ReformatPanel 目标期刊规则摘要', () => {
beforeEach(() => {
global.fetch = vi.fn().mockRejectedValue(new Error('no network'));
if (!URL.createObjectURL) URL.createObjectURL = vi.fn(() => 'blob:mock');
if (!URL.revokeObjectURL) URL.revokeObjectURL = vi.fn();
});
it('1) 有规则字段 + 有 diff → 摘要列出字段且标注"已修改 N 处"', async () => {
// Molecular Plant 真实规则形态:12pt / 1.5 / author_year(font/margin null 不显示)
const { wrapper } = mountWithResult({
reformatStatus: 'ready',
reformatResult: resultWith(
{
min_font_pt: 12, min_margin_mm: null, min_line_spacing: 1.5,
refs_style: 'author_year', max_pages: null, min_figures: null, max_fonts: null,
},
[
{ line: 1, original: 'a', modified: 'b', reason: 'r', rule_key: 'font_pt', action: 'modified' },
{ line: 3, original: 'a', modified: 'b', reason: 'r', rule_key: 'line_spacing', action: 'modified' },
{ line: 4, original: 'a', modified: 'b', reason: 'r', rule_key: 'bib_style', action: 'modified' },
],
),
});
await wrapper.vm.$nextTick();
const el = wrapper.find('[data-testid="rf-rules-summary"]');
expect(el.exists()).toBe(true);
const text = el.text();
expect(text).toContain('1.5 倍行距');
expect(text).toContain('作者-年份引用');
expect(text).toContain('字号 ≥12pt');
expect(text).not.toContain('null');
expect(text).not.toContain('边距'); // min_margin_mm=null → 不显示
expect(text).toContain('已修改 3 处');
});
it('2) 规则全 null + diff=0 → "无强制约束" + "样本已满足该刊要求,无需修改"', async () => {
const { wrapper } = mountWithResult({
reformatStatus: 'ready',
reformatResult: resultWith(
{
min_font_pt: null, min_margin_mm: null, min_line_spacing: null,
refs_style: null, max_pages: null, min_figures: null, max_fonts: null,
},
[],
),
});
await wrapper.vm.$nextTick();
const el = wrapper.find('[data-testid="rf-rules-summary"]');
expect(el.exists()).toBe(true);
const text = el.text();
expect(text).toContain('该刊官网未规定明确格式要求,无强制约束');
expect(text).toContain('样本已满足该刊要求,无需修改');
expect(text).not.toContain('已修改');
});
it('3) 双倍行距 + Vancouver(GB/BMC/Rice 形态)→ 正确映射中文标签', async () => {
const { wrapper } = mountWithResult({
reformatStatus: 'ready',
reformatResult: resultWith(
{
min_font_pt: null, min_margin_mm: null, min_line_spacing: 2.0,
refs_style: 'vancouver', max_pages: null, min_figures: null, max_fonts: null,
},
[{ line: 3, original: 'a', modified: 'b', reason: 'r', rule_key: 'line_spacing', action: 'modified' }],
),
});
await wrapper.vm.$nextTick();
const text = wrapper.find('[data-testid="rf-rules-summary"]').text();
expect(text).toContain('双倍行距');
expect(text).toContain('Vancouver 引用');
expect(text).toContain('已修改 1 处');
});
});