import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
import { applyFieldsCommand, inspectFieldsCommand } from '../../src/onlyoffice/commands';
|
|
function control(tag: string, kind: 'checkbox' | 'date' | 'multiline' | 'select' | 'text', initial: boolean | string) {
|
let value = initial;
|
const options = [
|
{ GetText: () => '合格', GetValue: () => 'qualified' },
|
{ GetText: () => '不合格', GetValue: () => 'unqualified' },
|
];
|
return {
|
GetTag: () => tag,
|
GetAlias: () => '字段',
|
GetInternalId: () => `id-${tag}`,
|
GetRange: () => ({ GetText: () => (typeof value === 'boolean' ? (value ? '☒' : '☐') : value) }),
|
IsCheckBox: () => kind === 'checkbox',
|
IsComboBox: () => kind === 'select',
|
IsDropDownList: () => false,
|
IsDatePicker: () => kind === 'date',
|
IsBlockLevel: () => kind === 'multiline',
|
GetDropdownList: () => ({ GetElementsCount: () => options.length, GetItem: (index: number) => options[index] }),
|
SetCheckBoxChecked(next: boolean) { value = next; return true; },
|
SelectListItem(next: string) { value = options.find((item) => item.GetValue() === next)?.GetText() ?? ''; return true; },
|
SetDate(next: Date) { value = `${next.getFullYear()}-${String(next.getMonth() + 1).padStart(2, '0')}-${String(next.getDate()).padStart(2, '0')}`; return true; },
|
RemoveAllElements() { value = ''; return true; },
|
AddElement(item: { text?: string }) {
|
const text = item.text ?? '';
|
value = kind === 'multiline' && value !== '' ? `${value}\n${text}` : `${value}${text}`;
|
return true;
|
},
|
};
|
}
|
|
function install(controls: unknown[], changes: unknown[] = []) {
|
const createParagraph = vi.fn(() => ({ text: '', AddElement(item: { text: string }) { this.text += item.text; return true; } }));
|
vi.stubGlobal('Asc', { scope: { elnTemplateFillInspect: {}, elnTemplateFillChanges: changes } });
|
vi.stubGlobal('Api', {
|
GetDocument: () => ({ GetAllContentControls: () => controls }),
|
CreateRun: () => ({ text: '', AddText(value: string) { this.text = value; return true; } }),
|
CreateParagraph: createParagraph,
|
});
|
return { createParagraph };
|
}
|
|
function serializeCommand(command: () => string): () => string {
|
return Function(`"use strict"; return (${command.toString()});`)() as () => string;
|
}
|
|
describe('ONLYOFFICE fill commands', () => {
|
afterEach(() => vi.unstubAllGlobals());
|
|
it('inspects typed ELN controls and ignores other tags', () => {
|
install([control('eln.field.name', 'text', 'A'), control('eln.field.ok', 'checkbox', false), control('other', 'text', 'x')]);
|
const result = JSON.parse(inspectFieldsCommand());
|
expect(result.fields).toHaveLength(2);
|
expect(result.fields[1]).toMatchObject({ tag: 'eln.field.ok', type: 'checkbox', currentValue: false });
|
});
|
|
it('inspects fields after ONLYOFFICE serializes the command without module closures', () => {
|
install([control('eln.field.name', 'text', 'A')]);
|
|
expect(JSON.parse(serializeCommand(inspectFieldsCommand)())).toMatchObject({
|
ok: true,
|
fields: [{ tag: 'eln.field.name', type: 'text', currentValue: 'A' }],
|
});
|
});
|
|
it('applies text, checkbox, select and date values', () => {
|
const controls = [
|
control('eln.field.name', 'text', ''), control('eln.field.ok', 'checkbox', false),
|
control('eln.field.result', 'select', '合格'), control('eln.field.date', 'date', '2026-08-12'),
|
];
|
install(controls, [
|
{ tag: 'eln.field.name', type: 'text', value: '样品' }, { tag: 'eln.field.ok', type: 'checkbox', value: true },
|
{ tag: 'eln.field.result', type: 'select', value: 'unqualified' }, { tag: 'eln.field.date', type: 'date', value: '2026-08-13' },
|
]);
|
expect(JSON.parse(applyFieldsCommand()).results).toEqual([
|
{ tag: 'eln.field.name', ok: true }, { tag: 'eln.field.ok', ok: true },
|
{ tag: 'eln.field.result', ok: true }, { tag: 'eln.field.date', ok: true },
|
]);
|
});
|
|
it('applies fields after ONLYOFFICE serializes the command without module closures', () => {
|
const item = control('eln.field.name', 'text', '');
|
install([item], [{ tag: 'eln.field.name', type: 'text', value: '样品' }]);
|
|
expect(JSON.parse(serializeCommand(applyFieldsCommand)()).results).toEqual([{ tag: 'eln.field.name', ok: true }]);
|
expect(item.GetRange().GetText()).toBe('样品');
|
});
|
|
it('rejects unknown select values without changing the field', () => {
|
const item = control('eln.field.result', 'select', '合格');
|
install([item], [{ tag: 'eln.field.result', type: 'select', value: 'missing' }]);
|
const result = JSON.parse(applyFieldsCommand()).results[0];
|
expect(result).toMatchObject({ tag: 'eln.field.result', ok: false, error: '下拉值不在文档选项中' });
|
expect(item.GetRange().GetText()).toBe('合格');
|
});
|
|
it('writes multiline values as one paragraph per line', () => {
|
const item = control('eln.field.notes', 'multiline', '');
|
const { createParagraph } = install([item], [{ tag: 'eln.field.notes', type: 'multiline', value: '第一行\n第二行' }]);
|
|
expect(JSON.parse(applyFieldsCommand()).results).toEqual([{ tag: 'eln.field.notes', ok: true }]);
|
expect(createParagraph).toHaveBeenCalledTimes(2);
|
expect(item.GetRange().GetText()).toBe('第一行\n第二行');
|
});
|
|
it('continues applying later fields after one field fails', () => {
|
const select = control('eln.field.result', 'select', '合格');
|
const text = control('eln.field.name', 'text', '');
|
install([select, text], [
|
{ tag: 'eln.field.result', type: 'select', value: 'missing' },
|
{ tag: 'eln.field.name', type: 'text', value: '样品' },
|
]);
|
|
expect(JSON.parse(applyFieldsCommand()).results).toEqual([
|
{ tag: 'eln.field.result', ok: false, error: '下拉值不在文档选项中' },
|
{ tag: 'eln.field.name', ok: true },
|
]);
|
expect(text.GetRange().GetText()).toBe('样品');
|
});
|
});
|