Files
potaser da84dff9bb fix(review): persist uploaded .tex file in reformat panel
- File now stored in edu.js store (reformatFile)
- Switching target journal no longer requires re-upload
- Explicit reset button clears file
- Vitest: 4 cases
2026-10-13 11:20:33 +08:00

100 lines
4.1 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.file.test.js —— ReformatPanel 文件持久化(P3b 修复)
// bug:上传 .tex → 重排版 → 点"重新排版"换期刊 → 本地 file 被清空 → 要求重传。
// 修复:File 进 store(reformatFile,同 presubmitFile 模式);reset() 不清 file;
// 仅"×" removeFile 清空。
// 1) store 有 reformatFile → 挂载即回显文件名
// 2) 选择文件 → 切换目标期刊 → 文件仍在(store + DOM)
// 3) 有结果时点"重新排版"(reset)→ 回上传区且文件保留
// 4) "×" 移除 → store + 本地都清空
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: [{ id: 'gb', name: 'Genome Biology' }, { id: 'mp', name: 'Molecular Plant' }],
}),
getDirectory: vi.fn(),
reformatTex: vi.fn(),
compileTex: vi.fn(),
};
});
import { useEduStore } from '../../../../ui/src/stores/edu.js';
const TEX = new File(['\\documentclass{article}\\begin{document}Hi\\end{document}'], 'paper.tex', {
type: 'application/x-tex',
});
/** 先建 pinia → seed store → 再挂载(保证 mount 时读到 store 初值) */
function setup(seedFn) {
const pinia = createPinia();
setActivePinia(pinia);
const edu = useEduStore();
if (seedFn) seedFn(edu);
const wrapper = mount(ReformatPanel, { global: { plugins: [pinia] } });
return { wrapper, edu };
}
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) store 有 reformatFile → 挂载即回显文件名', async () => {
const { wrapper } = setup((edu) => { edu.reformatFile = TEX; });
await wrapper.vm.$nextTick();
expect(wrapper.find('.rf-file-name').text()).toContain('paper.tex');
});
it('2) 选择文件后切目标期刊 → 文件仍在(store + DOM)', async () => {
const { wrapper, edu } = setup();
const input = wrapper.find('input.rf-file-input');
Object.defineProperty(input.element, 'files', { value: [TEX], configurable: true });
await input.trigger('change');
await wrapper.vm.$nextTick();
expect(edu.reformatFile).toBe(TEX);
expect(wrapper.find('.rf-file-name').text()).toContain('paper.tex');
// 切换目标期刊(watch 只写 drafts,不清 file)
await wrapper.find('#rf-target').setValue('mp');
await wrapper.vm.$nextTick();
expect(edu.reformatFile).toBe(TEX);
expect(wrapper.find('.rf-file-name').text()).toContain('paper.tex');
expect(edu.drafts.reformatTarget).toBe('mp');
});
it('3) 有结果时点"重新排版" → 回上传区且文件保留', async () => {
const { wrapper, edu } = setup((e) => {
e.reformatFile = TEX;
e.reformatResult = {
ok: true, job_id: 'abc123def456', modified_tex: 'x', changes: [], warnings: [],
meta: { filename: 'paper.tex' },
};
e.reformatStatus = 'ready';
});
await wrapper.vm.$nextTick();
const again = wrapper.findAll('button').find((b) => b.text() === '重新排版');
expect(again).toBeTruthy();
await again.trigger('click');
await wrapper.vm.$nextTick();
expect(edu.reformatResult).toBeNull();
expect(edu.reformatFile).toBe(TEX); // store 保留
expect(wrapper.find('.rf-file-name').text()).toContain('paper.tex'); // DOM 回显
});
it('4) "×" 移除 → store + 本地都清空', async () => {
const { wrapper, edu } = setup((e) => { e.reformatFile = TEX; });
await wrapper.vm.$nextTick();
await wrapper.find('.rf-remove').trigger('click');
expect(edu.reformatFile).toBeNull();
expect(wrapper.find('.rf-file-name').exists()).toBe(false);
});
});