Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 58 additions & 10 deletions packages/ketcher-core/__tests__/application/editor/Editor.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CoreEditor, ToolName } from 'application/editor';
import { CoreEditor, EditorClassName, ToolName } from 'application/editor';
import { MonomerTool } from 'application/editor/tools/Monomer';
import { SelectBase } from 'application/editor/tools/select';
import { Vec2 } from 'domain/entities';
Expand Down Expand Up @@ -432,9 +432,14 @@ describe('CoreEditor', () => {
describe('context menu handling', () => {
let canvas: SVGSVGElement;
let editor: CoreEditor;
let editorRoot: HTMLDivElement;

beforeEach(() => {
editorRoot = document.createElement('div');
editorRoot.classList.add(EditorClassName);
document.body.appendChild(editorRoot);
canvas = createPolymerEditorCanvas();
editorRoot.appendChild(canvas);
editor = new CoreEditor({
canvas,
theme: polymerEditorTheme,
Expand All @@ -443,7 +448,7 @@ describe('CoreEditor', () => {

afterEach(() => {
editor.destroy();
canvas.remove();
editorRoot.remove();
});

it('should select monomer on right click when it was not selected', () => {
Expand All @@ -469,18 +474,20 @@ describe('CoreEditor', () => {
const monomerDomElement = document.createElement('div');
(monomerDomElement as unknown as { __data__: unknown }).__data__ =
monomer.renderer;
document.body.appendChild(monomerDomElement);
editorRoot.appendChild(monomerDomElement);

expect(monomer.selected).toBeFalsy();
monomerDomElement.dispatchEvent(
new MouseEvent('contextmenu', {
bubbles: true,
clientX: 0,
clientY: 0,
}),
);
const event = new MouseEvent('contextmenu', {
bubbles: true,
cancelable: true,
clientX: 0,
clientY: 0,
});

monomerDomElement.dispatchEvent(event);

expect(monomer.selected).toBeTruthy();
expect(event.defaultPrevented).toBeTruthy();
expect(rightClickSelectedMonomersHandler).toHaveBeenCalledWith(
expect.arrayContaining([expect.anything(), [monomer]]),
);
Expand All @@ -492,6 +499,47 @@ describe('CoreEditor', () => {
Reflect.deleteProperty(svgElementWithBBox, 'getBBox');
}
});

it('should ignore context menu events outside Ketcher root', () => {
const rightClickCanvasHandler = jest.fn();
const hostElement = document.createElement('div');

editor.events.rightClickCanvas.add(rightClickCanvasHandler);
document.body.appendChild(hostElement);

const event = new MouseEvent('contextmenu', {
bubbles: true,
cancelable: true,
});

hostElement.dispatchEvent(event);

expect(event.defaultPrevented).toBeFalsy();
expect(rightClickCanvasHandler).not.toHaveBeenCalled();

hostElement.remove();
});

it('should ignore context menu events when Ketcher root is removed', () => {
const rightClickCanvasHandler = jest.fn();
const hostElement = document.createElement('div');

editor.events.rightClickCanvas.add(rightClickCanvasHandler);
document.body.appendChild(hostElement);
editorRoot.remove();

const event = new MouseEvent('contextmenu', {
bubbles: true,
cancelable: true,
});

hostElement.dispatchEvent(event);

expect(event.defaultPrevented).toBeFalsy();
expect(rightClickCanvasHandler).not.toHaveBeenCalled();

hostElement.remove();
});
});

describe('remove autochain preview handling', () => {
Expand Down
19 changes: 19 additions & 0 deletions packages/ketcher-core/src/application/editor/Editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,25 @@ export class CoreEditor {

private setupContextMenuEvents() {
this.contextMenuEventHandler = (event) => {
const eventTarget = event.target;
let isEventInsideKetcher = false;

if (eventTarget instanceof Node) {
const connectedRoot = this.ketcherRootElement?.isConnected
? this.ketcherRootElement
: null;

if (connectedRoot) {
isEventInsideKetcher = connectedRoot.contains(eventTarget);
} else if (this.canvas.isConnected) {
isEventInsideKetcher = this.canvas.contains(eventTarget);
}
}

if (!isEventInsideKetcher) {
return;
}

event.preventDefault();

if (this.libraryItemDragState) {
Expand Down
Loading