121 lines
2.9 KiB
TypeScript
121 lines
2.9 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import {
|
|
createTextContextMenuTemplate,
|
|
type TextContextMenuContext,
|
|
} from '@electron/main/context-menu';
|
|
|
|
type ContextOverrides = {
|
|
isEditable?: boolean;
|
|
selectionText?: string;
|
|
editFlags?: Partial<Electron.EditFlags>;
|
|
};
|
|
|
|
function context(overrides: ContextOverrides = {}): TextContextMenuContext {
|
|
return {
|
|
isEditable: overrides.isEditable ?? false,
|
|
selectionText: overrides.selectionText ?? '',
|
|
editFlags: {
|
|
canUndo: false,
|
|
canRedo: false,
|
|
canCut: false,
|
|
canCopy: false,
|
|
canPaste: false,
|
|
canDelete: false,
|
|
canSelectAll: false,
|
|
canEditRichly: false,
|
|
...overrides.editFlags,
|
|
},
|
|
};
|
|
}
|
|
|
|
function enabledByRole(template: Electron.MenuItemConstructorOptions[] | null) {
|
|
return Object.fromEntries(
|
|
(template ?? [])
|
|
.filter((item) => item.role)
|
|
.map((item) => [item.role, item.enabled]),
|
|
);
|
|
}
|
|
|
|
describe('text context menu', () => {
|
|
it('does not create a menu for ordinary non-editable content', () => {
|
|
expect(createTextContextMenuTemplate(context())).toBeNull();
|
|
});
|
|
|
|
it('allows paste and select all in an editable control without a selection', () => {
|
|
const template = createTextContextMenuTemplate(context({
|
|
isEditable: true,
|
|
editFlags: {
|
|
canPaste: true,
|
|
canSelectAll: true,
|
|
},
|
|
}));
|
|
|
|
expect(template?.map((item) => item.label ?? item.type)).toEqual([
|
|
'剪切',
|
|
'复制',
|
|
'粘贴',
|
|
'separator',
|
|
'全选',
|
|
]);
|
|
expect(enabledByRole(template)).toEqual({
|
|
cut: false,
|
|
copy: false,
|
|
paste: true,
|
|
selectAll: true,
|
|
});
|
|
});
|
|
|
|
it('enables every requested action for an editable selection when supported', () => {
|
|
const template = createTextContextMenuTemplate(context({
|
|
isEditable: true,
|
|
selectionText: 'Makelore',
|
|
editFlags: {
|
|
canCut: true,
|
|
canCopy: true,
|
|
canPaste: true,
|
|
canSelectAll: true,
|
|
},
|
|
}));
|
|
|
|
expect(enabledByRole(template)).toEqual({
|
|
cut: true,
|
|
copy: true,
|
|
paste: true,
|
|
selectAll: true,
|
|
});
|
|
});
|
|
|
|
it('keeps cut and paste disabled for a read-only selection', () => {
|
|
const template = createTextContextMenuTemplate(context({
|
|
selectionText: 'Makelore',
|
|
editFlags: {
|
|
canCut: true,
|
|
canCopy: true,
|
|
canPaste: true,
|
|
canSelectAll: true,
|
|
},
|
|
}));
|
|
|
|
expect(enabledByRole(template)).toEqual({
|
|
cut: false,
|
|
copy: true,
|
|
paste: false,
|
|
selectAll: true,
|
|
});
|
|
});
|
|
|
|
it('respects disabled renderer editing capabilities', () => {
|
|
const template = createTextContextMenuTemplate(context({
|
|
isEditable: true,
|
|
selectionText: 'Makelore',
|
|
}));
|
|
|
|
expect(enabledByRole(template)).toEqual({
|
|
cut: false,
|
|
copy: false,
|
|
paste: false,
|
|
selectAll: false,
|
|
});
|
|
});
|
|
});
|