diff --git a/ketcher-autotests/tests/Structure-Creating-&-Editing/Actions-With-Structures/Selection-Hover/simple-object-selection-and-hover.spec.ts b/ketcher-autotests/tests/Structure-Creating-&-Editing/Actions-With-Structures/Selection-Hover/simple-object-selection-and-hover.spec.ts new file mode 100644 index 0000000000..577abafe2b --- /dev/null +++ b/ketcher-autotests/tests/Structure-Creating-&-Editing/Actions-With-Structures/Selection-Hover/simple-object-selection-and-hover.spec.ts @@ -0,0 +1,45 @@ +import { Page, test } from '@playwright/test'; +import { + LeftPanelButton, + clickInTheMiddleOfTheScreen, + dragMouseTo, + getCoordinatesOfTheMiddleOfTheScreen, + selectLeftPanelButton, + takeEditorScreenshot, +} from '@utils'; + +test.describe('Selection and hover for simple objects', () => { + test.beforeEach(async ({ page }) => { + await page.goto(''); + }); + test.afterEach(async ({ page }) => { + await takeEditorScreenshot(page); + }); + + const ellipseWidth = 120; + const ellipseHeight = 100; + + const setupEllipse = async (page: Page) => { + await selectLeftPanelButton(LeftPanelButton.ShapeEllipse, page); + const { x, y } = await getCoordinatesOfTheMiddleOfTheScreen(page); + const ellipseCoordinates = { x: x + ellipseWidth, y: y + ellipseHeight }; + await clickInTheMiddleOfTheScreen(page); + await dragMouseTo(ellipseCoordinates.x, ellipseCoordinates.y, page); + return ellipseCoordinates; + }; + + test('Selection highlight appears immediately for simple objects', async ({ + page, + }) => { + await setupEllipse(page); + await clickInTheMiddleOfTheScreen(page); + }); + + test('Hover highlight appears immediately for simple objects', async ({ + page, + }) => { + const ellipseCoordinates = await setupEllipse(page); + await clickInTheMiddleOfTheScreen(page); + await page.mouse.move(ellipseCoordinates.x, ellipseCoordinates.y); + }); +}); diff --git a/ketcher-autotests/tests/Structure-Creating-&-Editing/Actions-With-Structures/Selection-Hover/simple-object-selection-and-hover.spec.ts-snapshots/Selection-and-hover-for-simple-objects-Hover-highlight-appears-immediately-for-simple-objects-1-chromium-linux.png b/ketcher-autotests/tests/Structure-Creating-&-Editing/Actions-With-Structures/Selection-Hover/simple-object-selection-and-hover.spec.ts-snapshots/Selection-and-hover-for-simple-objects-Hover-highlight-appears-immediately-for-simple-objects-1-chromium-linux.png new file mode 100644 index 0000000000..393cb37742 Binary files /dev/null and b/ketcher-autotests/tests/Structure-Creating-&-Editing/Actions-With-Structures/Selection-Hover/simple-object-selection-and-hover.spec.ts-snapshots/Selection-and-hover-for-simple-objects-Hover-highlight-appears-immediately-for-simple-objects-1-chromium-linux.png differ diff --git a/ketcher-autotests/tests/Structure-Creating-&-Editing/Actions-With-Structures/Selection-Hover/simple-object-selection-and-hover.spec.ts-snapshots/Selection-and-hover-for-simple-objects-Selection-highlight-appears-immediately-for-simple-objects-1-chromium-linux.png b/ketcher-autotests/tests/Structure-Creating-&-Editing/Actions-With-Structures/Selection-Hover/simple-object-selection-and-hover.spec.ts-snapshots/Selection-and-hover-for-simple-objects-Selection-highlight-appears-immediately-for-simple-objects-1-chromium-linux.png new file mode 100644 index 0000000000..195600f6bb Binary files /dev/null and b/ketcher-autotests/tests/Structure-Creating-&-Editing/Actions-With-Structures/Selection-Hover/simple-object-selection-and-hover.spec.ts-snapshots/Selection-and-hover-for-simple-objects-Selection-highlight-appears-immediately-for-simple-objects-1-chromium-linux.png differ diff --git a/packages/ketcher-core/__tests__/application/render/restruct/reobject.test.ts b/packages/ketcher-core/__tests__/application/render/restruct/reobject.test.ts new file mode 100644 index 0000000000..eb83b36c8d --- /dev/null +++ b/packages/ketcher-core/__tests__/application/render/restruct/reobject.test.ts @@ -0,0 +1,37 @@ +import ReObject from 'application/render/restruct/reobject'; + +it('should change selection style correctly for simple objects when selected', () => { + const reObject = new ReObject('simpleObject'); + reObject.selected = true; + const options = { + hoverStyle: { + stroke: '#0097A8', + fill: '#CCFFDD', + 'stroke-width': 20, + }, + }; + reObject.hovering = { + attr: jest.fn((style) => + expect(style.fill).not.toEqual(options.hoverStyle.fill), + ), + }; + + reObject.changeSelectionStyle(options); +}); + +it('should change selection style correctly for other objects when selected', () => { + const reObject = new ReObject('frag'); + reObject.selected = true; + const options = { + hoverStyle: { + fill: '#CCFFDD', + }, + }; + reObject.hovering = { + attr: jest.fn((style) => + expect(style.fill).toEqual(options.hoverStyle.fill), + ), + }; + + reObject.changeSelectionStyle(options); +}); diff --git a/packages/ketcher-core/__tests__/application/render/restruct/resimpleObject.test.ts b/packages/ketcher-core/__tests__/application/render/restruct/resimpleObject.test.ts new file mode 100644 index 0000000000..1382b37f62 --- /dev/null +++ b/packages/ketcher-core/__tests__/application/render/restruct/resimpleObject.test.ts @@ -0,0 +1,71 @@ +import { ReStruct, Render } from 'application/render'; +import { RenderOptions } from 'application/render/render.types'; +import ReSimpleObject from 'application/render/restruct/resimpleObject'; +import { SimpleObjectMode, Struct, Vec2 } from 'domain/entities'; + +const ellipse = { + mode: SimpleObjectMode.ellipse, + pos: [ + new Vec2({ + x: 5.025, + y: 9.600000000000001, + z: 0, + }), + new Vec2({ + x: 10.05, + y: 12.200000000000001, + z: 0, + }), + ], +}; +const rectangle = { + mode: SimpleObjectMode.ellipse, + pos: [ + new Vec2({ + x: 7.2250000000000005, + y: 10.3, + z: 0, + }), + new Vec2({ + x: 11.100000000000001, + y: 12.825000000000001, + z: 0, + }), + ], +}; +const line = { + mode: SimpleObjectMode.ellipse, + pos: [ + new Vec2({ + x: 7.7, + y: 9.125, + z: 0, + }), + new Vec2({ + x: 11.3, + y: 12.4, + z: 0, + }), + ], +}; +it('should get hover path and style for simple objects correctly', () => { + [ellipse, rectangle, line].forEach((simpleObject) => { + const reSimpleObject = new ReSimpleObject(simpleObject); + const option = { scale: 20, width: 100, height: 100 } as RenderOptions; + const render = new Render(document as unknown as HTMLElement, option); + const paths = reSimpleObject.hoverPath(render); + expect( + paths.filter((path) => path.path.attrs.fill === '#fff')?.length, + ).toBeGreaterThanOrEqual(1); + }); +}); + +it('should get selection plate for simple objects correctly with selection points in a separated set', () => { + const reSimpleObject = new ReSimpleObject(ellipse); + const initialPathLength = reSimpleObject.visel.paths.length; + const option = { scale: 20, width: 100, height: 100 } as RenderOptions; + const render = new Render(document as unknown as HTMLElement, option); + const restruct = new ReStruct(new Struct(), render); + reSimpleObject.makeSelectionPlate(restruct, render.paper, render.options); + expect(initialPathLength + 1).toEqual(reSimpleObject.visel.paths.length); +}); diff --git a/packages/ketcher-core/__tests__/application/render/restruct/restruct.test.ts b/packages/ketcher-core/__tests__/application/render/restruct/restruct.test.ts new file mode 100644 index 0000000000..9b8e970e9f --- /dev/null +++ b/packages/ketcher-core/__tests__/application/render/restruct/restruct.test.ts @@ -0,0 +1,34 @@ +import { ReSimpleObject, ReStruct, Render } from 'application/render'; +import { RenderOptions } from 'application/render/render.types'; +import { SimpleObjectMode, Struct, Vec2 } from 'domain/entities'; + +describe('show selection', () => { + const ellipse = { + mode: SimpleObjectMode.ellipse, + pos: [ + new Vec2({ + x: 5.025, + y: 9.600000000000001, + z: 0, + }), + new Vec2({ + x: 10.05, + y: 12.200000000000001, + z: 0, + }), + ], + }; + const reSimpleObject = new ReSimpleObject(ellipse); + reSimpleObject.togglePoints = jest.fn(); + const option = { scale: 20, width: 100, height: 100 } as RenderOptions; + const render = new Render(document as unknown as HTMLElement, option); + const restruct = new ReStruct(new Struct(), render); + it('should show selection simple objects correctly when selected', () => { + restruct.showItemSelection(reSimpleObject, true); + expect(reSimpleObject.togglePoints).toHaveBeenCalled(); + }); + it('should show selection simple objects correctly when unselected', () => { + restruct.showItemSelection(reSimpleObject, false); + expect(reSimpleObject.togglePoints).toHaveBeenCalled(); + }); +}); diff --git a/packages/ketcher-core/src/application/render/restruct/resimpleObject.ts b/packages/ketcher-core/src/application/render/restruct/resimpleObject.ts index 7b228f7e70..4e09fd1410 100644 --- a/packages/ketcher-core/src/application/render/restruct/resimpleObject.ts +++ b/packages/ketcher-core/src/application/render/restruct/resimpleObject.ts @@ -191,8 +191,12 @@ class ReSimpleObject extends ReObject { return refPoints; } - getHoverPathStyle(path: any, render: Render, type: boolean) { - if (type) { + getHoverPathStyle( + path: any, + render: Render, + isOuterShapeOfHoverPath: boolean, + ) { + if (isOuterShapeOfHoverPath) { return path.attr(render.options.hoverStyle); } else { return path.attr({ ...render.options.hoverStyle, fill: '#fff' }); diff --git a/packages/ketcher-core/src/application/render/restruct/restruct.ts b/packages/ketcher-core/src/application/render/restruct/restruct.ts index 387ee80b95..4b25a61e1d 100644 --- a/packages/ketcher-core/src/application/render/restruct/restruct.ts +++ b/packages/ketcher-core/src/application/render/restruct/restruct.ts @@ -748,6 +748,10 @@ class ReStruct { if (item.selectionPlate) { item.selectionPlate.show(); item.additionalInfo?.show(); + item.cip?.rectangle.attr({ + fill: '#7f7', + stroke: '#7f7', + }); if (item.togglePoints) item.togglePoints(true); } } else if (exists && item.selectionPlate) {