Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#2370 - erase tool for macromolecules editor #3217

Merged
merged 2 commits into from
Sep 13, 2023
Merged
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
2 changes: 1 addition & 1 deletion example/src/PolymerToggler/PolymerToggler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export interface PolymerTogglerProps {

const PolymerToggler = ({ toggle }: PolymerTogglerProps): JSX.Element => {
return (
<label className={styles.switch} data-testid="PolymerToggler">
<label className={styles.switch} data-testid="polymer-toggler">
<input type="checkbox" onChange={(e) => toggle(e.target.checked)} />
<span className={styles.slider} />
</label>
Expand Down
2 changes: 1 addition & 1 deletion ketcher-autotests/constants/testIdConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const PEPTIDES_TAB = 'PEPTIDES_TAB';
const RNA_TAB = 'RNA_TAB';
const CHEM_TAB = 'CHEM_TAB';
const FAVORITES_TAB = 'FAVORITES_TAB';
const POLYMER_TOGGLER = 'PolymerToggler';
const POLYMER_TOGGLER = 'polymer-toggler';
const SUGAR = 'rna-builder-slot--sugar';
const BASE = 'rna-builder-slot--base';
const PHOSPHATE = 'rna-builder-slot--phosphate';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { test } from '@playwright/test';
import {
addMonomerToCanvas,
selectEraseTool,
selectSingleBondTool,
takeEditorScreenshot,
} from '@utils';
import { turnOnMacromoleculesEditor } from '@utils/macromolecules';
import { bondTwoMonomers } from '@utils/macromolecules/polymerBond';
/* eslint-disable no-magic-numbers */

test.describe('Erase Tool', () => {
test.beforeEach(async ({ page }) => {
await page.goto('');
await turnOnMacromoleculesEditor(page);
});
test.skip('Delete monomer bonded with another monomers', async ({ page }) => {
/*
Test case: #2370 - "Erase" tool for macromolecules editor
Description: Erase Tool
*/

// Create 4 peptides on canvas
const MONOMER_NAME = 'Tza___3-thiazolylalanine';
const MONOMER_ALIAS = 'Tza';
await addMonomerToCanvas(page, MONOMER_NAME, 300, 300);
await addMonomerToCanvas(page, MONOMER_NAME, 400, 400);
await addMonomerToCanvas(page, MONOMER_NAME, 500, 500);
await addMonomerToCanvas(page, MONOMER_NAME, 500, 200);

// Get 4 peptides locators
const peptides = await page.getByText(MONOMER_ALIAS).locator('..');
const peptide1 = peptides.nth(0);
const peptide2 = peptides.nth(1);
const peptide3 = peptides.nth(2);
const peptide4 = peptides.nth(3);

// Select bond tool
await selectSingleBondTool(page);

// Create bonds between peptides
await bondTwoMonomers(page, peptide1, peptide2);
await bondTwoMonomers(page, peptide3, peptide2);
await bondTwoMonomers(page, peptide3, peptide4);

await takeEditorScreenshot(page);

await selectEraseTool(page);

// Delete peptide linked with two other peptides by bonds
await peptide3.click();

await takeEditorScreenshot(page);
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { test, expect } from '@playwright/test';
import { test } from '@playwright/test';
import { selectSingleBondTool, waitForPageInit } from '@utils';
import { turnOnMacromoleculesEditor } from '@utils/macromolecules';
/* eslint-disable no-magic-numbers */

test.describe('Polymer Bond Tool', () => {
Expand All @@ -12,8 +13,7 @@ test.describe('Polymer Bond Tool', () => {
Description: Polymer bond tool
*/

await expect(page.getByTestId('PolymerToggler')).toBeVisible();
await page.getByTestId('PolymerToggler').click();
await turnOnMacromoleculesEditor(page);

// Choose peptide
await page.getByText('Tza').click();
Expand All @@ -25,7 +25,7 @@ test.describe('Polymer Bond Tool', () => {
await page.mouse.click(500, 200);

// Get 4 peptides locators
const peptides = await page.getByText('Tza');
const peptides = await page.getByText('Tza').locator('..');
const peptide1 = peptides.nth(0);
const peptide2 = peptides.nth(1);
const peptide3 = peptides.nth(2);
Expand Down Expand Up @@ -69,8 +69,7 @@ test.describe('Polymer Bond Tool', () => {
Description: Polymer bond tool
*/

await expect(page.getByTestId('PolymerToggler')).toBeVisible();
await page.getByTestId('PolymerToggler').click();
await turnOnMacromoleculesEditor(page);

// Choose chems
await page.getByText('CHEM').click();
Expand All @@ -81,7 +80,7 @@ test.describe('Polymer Bond Tool', () => {
await page.mouse.click(400, 400);

// Get 2 chems locators
const chems = await page.getByText('hxy');
const chems = await page.getByText('hxy').locator('..');
const chem1 = chems.nth(0);
const chem2 = chems.nth(1);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { test, expect } from '@playwright/test';
import { turnOnMacromoleculesEditor } from '@utils/macromolecules';
import { test } from '@playwright/test';
import { waitForPageInit } from '@utils/common';

test.describe('Macromolecules default presets', () => {
Expand All @@ -10,8 +11,7 @@ test.describe('Macromolecules default presets', () => {
Test case: #2934 - rna builder: add default presets
Description: Switch to Polymer Editor
*/
await expect(page.getByTestId('PolymerToggler')).toBeVisible();
await page.getByTestId('PolymerToggler').click();
await turnOnMacromoleculesEditor(page);
await page.getByText('RNA').click();

await page.getByTestId('cancel-btn').click();
Expand All @@ -25,8 +25,7 @@ test.describe('Macromolecules default presets', () => {
/*
Test case: #2507 - Add RNA monomers to canvas (by click)
*/
await expect(page.getByTestId('PolymerToggler')).toBeVisible();
await page.getByTestId('PolymerToggler').click();
await turnOnMacromoleculesEditor(page);
await page.getByText('RNA').click();
await page.getByTestId('cancel-btn').click();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { test } from '@playwright/test';
import {
addMonomerToCanvas,
selectEraseTool,
selectRectangleArea,
selectRectangleSelectionTool,
selectSingleBondTool,
} from '@utils';
import { turnOnMacromoleculesEditor } from '@utils/macromolecules';
import { bondTwoMonomers } from '@utils/macromolecules/polymerBond';
/* eslint-disable no-magic-numbers */

test.describe('Rectangle Selection Tool', () => {
test.beforeEach(async ({ page }) => {
await page.goto('');
await turnOnMacromoleculesEditor(page);
});
test.skip('Select monomer and bonds and then erase', async ({ page }) => {
/*
Test case: #2360 - "Select" tool for Macromolecules editor
Description: Rectangle Selection Tool
*/

// Create 4 peptides on canvas
const MONOMER_NAME = 'Tza___3-thiazolylalanine';
const MONOMER_ALIAS = 'Tza';
await addMonomerToCanvas(page, MONOMER_NAME, 300, 300);
await addMonomerToCanvas(page, MONOMER_NAME, 400, 400);
await addMonomerToCanvas(page, MONOMER_NAME, 500, 500);
await addMonomerToCanvas(page, MONOMER_NAME, 500, 200);

// Get 4 peptides locators
const peptides = await page.getByText(MONOMER_ALIAS).locator('..');
const peptide1 = peptides.nth(0);
const peptide2 = peptides.nth(1);
const peptide3 = peptides.nth(2);
const peptide4 = peptides.nth(3);

// Select bond tool
await selectSingleBondTool(page);

// Create bonds between peptides
await bondTwoMonomers(page, peptide1, peptide2);
await bondTwoMonomers(page, peptide3, peptide2);
await bondTwoMonomers(page, peptide3, peptide4);

await page.screenshot({
path: 'tests/Macromolecule-editor/screenshots/rectangle-selection-tool.png',
});

await selectRectangleSelectionTool(page);

// Coordinates for rectangle selection
const startX = 100;
const startY = 100;
const endX = 500;
const endY = 500;

await selectRectangleArea(page, startX, startY, endX, endY);

await page.screenshot({
path: 'tests/Macromolecule-editor/screenshots/rectangle-selection-tool2.png',
});

// Erase selected elements
await selectEraseTool(page);

await page.screenshot({
path: 'tests/Macromolecule-editor/screenshots/rectangle-selection-tool3.png',
});
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions ketcher-autotests/tests/utils/canvas/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,13 @@ export async function resetAllSettingsToDefault(page: Page) {
await pressButton(page, 'Reset');
await pressButton(page, 'Apply');
}

export async function addMonomerToCanvas(
page: Page,
monomerFullName: string,
positionX: number,
positionY: number,
) {
await page.getByTestId(monomerFullName).click();
await page.mouse.click(positionX, positionY);
}
24 changes: 24 additions & 0 deletions ketcher-autotests/tests/utils/canvas/tools/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,30 @@ export async function selectSingleBondTool(page: Page) {
await bondToolButton.click();
}

export async function selectEraseTool(page: Page) {
const bondToolButton = page.locator(`button[title*="Erase"]`);
await bondToolButton.click();
}

export async function selectRectangleSelectionTool(page: Page) {
const bondToolButton = page.locator(`button[title*="select-rectangle"]`);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My proposal is to avoid using locators by title and use page.getByTestId

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All tools buttons are done in that way. Let's keep it in one style for now.

await bondToolButton.click();
}

export async function selectRectangleArea(
page: Page,
startX: number,
startY: number,
endX: number,
endY: number,
) {
await selectRectangleSelectionTool(page);
await page.mouse.move(startX, startY);
await page.mouse.down();
await page.mouse.move(endX, endY);
await page.mouse.up();
}

export async function selectTopPanelButton(
buttonName: TopPanelButton,
page: Page,
Expand Down
7 changes: 7 additions & 0 deletions ketcher-autotests/tests/utils/macromolecules/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { expect, Page } from '@playwright/test';
import { POLYMER_TOGGLER } from '@constants/testIdConstants';

export async function turnOnMacromoleculesEditor(page: Page) {
await expect(page.getByTestId(POLYMER_TOGGLER)).toBeVisible();
await page.getByTestId(POLYMER_TOGGLER).click();
}
12 changes: 12 additions & 0 deletions ketcher-autotests/tests/utils/macromolecules/polymerBond.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Locator, Page } from '@playwright/test';

export async function bondTwoMonomers(
page: Page,
firstMonomerElement: Locator,
secondMonomerElement: Locator,
) {
await firstMonomerElement.hover();
await page.mouse.down();
await secondMonomerElement.hover();
await page.mouse.up();
}
4 changes: 4 additions & 0 deletions packages/ketcher-core/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
{
"root": false,
"extends": "plugin:jest/recommended",
"rules": {
"@typescript-eslint/no-empty-function": "off",
"no-useless-constructor": "off"
},
"overrides": [
{
"files": [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { CoreEditor } from 'application/editor';
import { PeptideRenderer } from 'application/render/renderers/PeptideRenderer';
import {
getFinishedPolymerBond,
peptideMonomerItem,
polymerEditorTheme,
} from '../../../mock-data';
import { createPolymerEditorCanvas } from '../../../helpers/dom';
import { SelectRectangle } from 'application/editor/tools/SelectRectangle';

jest.mock('d3', () => {
return {
brush() {
return {
on() {},
};
},
select() {
return {
call() {
return this;
},
insert() {
return this;
},
select() {
return this;
},
attr() {
return this;
},
style() {
return this;
},
};
},
};
});

describe('Select Rectangle Tool', () => {
it('should select drawing entity on mousedown', () => {
const polymerBond = getFinishedPolymerBond(0, 0, 10, 10);
const event = {
target: {
__data__: polymerBond.renderer,
},
};
const selectRectangleTool = new SelectRectangle(
new CoreEditor({
theme: polymerEditorTheme,
canvas: createPolymerEditorCanvas(),
}),
);

expect(polymerBond.selected).toBeFalsy();
selectRectangleTool.mousedown(event);
expect(polymerBond.selected).toBeTruthy();
});

it('should initiate the render of peptide mousedown', () => {
const canvas: SVGSVGElement = createPolymerEditorCanvas();
const editor: CoreEditor = new CoreEditor({
canvas,
theme: polymerEditorTheme,
});
const onShow = jest.fn();
jest.spyOn(PeptideRenderer.prototype, 'show').mockImplementation(onShow);
editor.events.selectMonomer.dispatch(peptideMonomerItem);
canvas.dispatchEvent(new Event('mouseover', { bubbles: true }));
expect(onShow).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ exports[`PeptideRenderer should render peptide 1`] = `
id="polymer-editor-canvas"
width="500"
>
<defs />
<g
transform="translate(0, 0) scale(1)"
transition="transform 0.2s"
Expand All @@ -20,6 +21,7 @@ exports[`PeptideRenderer should render peptide 1`] = `
font-size="12px"
font-weight="700"
line-height="12px"
pointer-events="none"
style="cursor: pointer; user-select: none;"
x="0"
y="10"
Expand Down
Loading
Loading