110 lines
4.7 KiB
JavaScript
110 lines
4.7 KiB
JavaScript
// tests/frontend/unit/edu/tracker.panel.test.js —— TrackerPanel v3(方案 A 极简台账)
|
||
// 1) 统计条 5 项计数
|
||
// 2) 表单含返修截止日/返修轮次字段
|
||
// 3) 卡片显示返修轮次+截止倒计时;无"已开启/未开始返修"联动徽章
|
||
// 4) "去写返修"仅 under_review/revision 显示;点击 → section 切 rebuttal + 期刊预填(无 linkSid 回写)
|
||
// 5) 空态文案
|
||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||
import { mount } from '@vue/test-utils';
|
||
import { createPinia, setActivePinia } from 'pinia';
|
||
import TrackerPanel from '../../../../ui/src/components/edu/panels/TrackerPanel.vue';
|
||
|
||
vi.mock('../../../../ui/src/api/review.js', () => ({
|
||
getJournals: vi.fn(),
|
||
getDirectory: vi.fn(),
|
||
getConferences: vi.fn(),
|
||
presubmit: vi.fn(),
|
||
recommend: vi.fn(),
|
||
formatCheck: vi.fn(),
|
||
formatErrorMessage: vi.fn(),
|
||
reformatTex: vi.fn(),
|
||
compileTex: vi.fn(),
|
||
reviewErrorMessage: vi.fn((e) => (e && e.message) || 'err'),
|
||
rebuttalCreateJob: vi.fn(),
|
||
rebuttalCreateFromPdf: vi.fn(),
|
||
rebuttalGetJob: vi.fn(),
|
||
rebuttalSaveResponse: vi.fn(),
|
||
rebuttalDraft: vi.fn(),
|
||
rebuttalStructure: vi.fn(),
|
||
rebuttalConfirm: vi.fn(),
|
||
rebuttalLetter: vi.fn(),
|
||
rebuttalDownloadLetterMd: vi.fn(),
|
||
rebuttalDeleteJob: vi.fn(),
|
||
}));
|
||
|
||
import { useEduStore } from '../../../../ui/src/stores/edu.js';
|
||
|
||
function seed(edu) {
|
||
edu.submissions = [
|
||
{ id: 's1', journal: 'Plant Cell', status: 'revision', submittedAt: '2026-09-01', updatedAt: '2026-10-01', notes: '', revisionDue: '2026-11-01', revisionRound: 2, rebuttalJobId: null },
|
||
{ id: 's2', journal: 'Mol Plant', status: 'accepted', submittedAt: '2026-08-01', updatedAt: '2026-09-15', notes: '' },
|
||
{ id: 's3', journal: 'GB', status: 'under_review', submittedAt: '2026-09-10', updatedAt: '2026-09-20', notes: '', rebuttalJobId: 'rbt_x1' },
|
||
{ id: 's4', journal: 'New Phytol', status: 'rejected', submittedAt: '2026-07-01', updatedAt: '2026-08-01', notes: '' },
|
||
];
|
||
}
|
||
|
||
describe('TrackerPanel v3', () => {
|
||
let wrapper;
|
||
let edu;
|
||
|
||
beforeEach(() => {
|
||
const pinia = createPinia();
|
||
setActivePinia(pinia);
|
||
edu = useEduStore();
|
||
seed(edu);
|
||
wrapper = mount(TrackerPanel, { global: { plugins: [pinia] } });
|
||
});
|
||
|
||
it('1) 统计条计数正确', () => {
|
||
const stats = wrapper.find('[data-testid="tk-stats"]');
|
||
expect(stats.text()).toContain('总投稿');
|
||
const b = stats.findAll('b').map((x) => x.text());
|
||
expect(b).toEqual(['4', '1', '1', '1', '1']); // total/active/revision/accepted/rejected
|
||
});
|
||
|
||
it('2) 表单含返修截止日与返修轮次字段', async () => {
|
||
await wrapper.find('.tk-add').trigger('click');
|
||
expect(wrapper.find('[data-testid="tk-revision-due"]').exists()).toBe(true);
|
||
expect(wrapper.find('[data-testid="tk-revision-round"]').exists()).toBe(true);
|
||
});
|
||
|
||
it('3) 卡片显示返修轮次+截止信息;无联动徽章', () => {
|
||
const rows = wrapper.findAll('[data-testid="tk-row"]');
|
||
expect(rows.length).toBe(4);
|
||
const rev = wrapper.find('[data-testid="tk-rev-info"]');
|
||
expect(rev.text()).toContain('第 2 轮返修');
|
||
expect(rev.text()).toContain('due 2026-11-01');
|
||
// 倒计时文案(今天 2026-10-12,due 2026-11-01 → 还剩 N 天)
|
||
expect(rev.text()).toMatch(/还剩 \d+ 天|今天截止|已逾期/);
|
||
// 方案 A:不再显示"已开启/未开始返修"联动徽章
|
||
expect(wrapper.find('[data-testid="tk-rebuttal-status"]').exists()).toBe(false);
|
||
expect(wrapper.text()).not.toContain('已开启返修任务');
|
||
expect(wrapper.text()).not.toContain('未开始返修');
|
||
});
|
||
|
||
it('4) 「去写返修」仅审稿中/返修中显示;点击只跳转+预填期刊(无回写)', () => {
|
||
// 按 updatedAt 倒序:s1(revision) → s3(under_review) → s2(accepted) → s4(rejected)
|
||
const btns = wrapper.findAll('[data-testid="tk-start-rebuttal"]');
|
||
expect(btns.length).toBe(2); // 仅 s1/s3
|
||
const rows = wrapper.findAll('[data-testid="tk-row"]');
|
||
expect(rows[2].text()).not.toContain('去写返修'); // s2 accepted
|
||
expect(rows[3].text()).not.toContain('去写返修'); // s4 rejected
|
||
btns[0].trigger('click');
|
||
return Promise.resolve().then(() => {
|
||
expect(edu.section).toBe('rebuttal');
|
||
expect(edu.rebuttal.prefillJournal).toBe('Plant Cell');
|
||
expect(edu.rebuttal.linkSid == null).toBe(true); // 方案 A:无回写联动
|
||
});
|
||
});
|
||
|
||
it('5) 空态文案', () => {
|
||
const pinia = createPinia();
|
||
setActivePinia(pinia);
|
||
const edu2 = useEduStore();
|
||
edu2.submissions = [];
|
||
const w = mount(TrackerPanel, { global: { plugins: [pinia] } });
|
||
expect(w.find('.tk-empty').text()).toContain('暂无投稿记录');
|
||
expect(w.find('.tk-empty').text()).toContain('新增投稿');
|
||
});
|
||
});
|