diff --git a/ketcher-autotests/tests/Macromolecule-editor/Import-Saving-Files/import-saving-idt.spec.ts b/ketcher-autotests/tests/Macromolecule-editor/Import-Saving-Files/import-saving-idt.spec.ts index afc05bc86e..6ddac10580 100644 --- a/ketcher-autotests/tests/Macromolecule-editor/Import-Saving-Files/import-saving-idt.spec.ts +++ b/ketcher-autotests/tests/Macromolecule-editor/Import-Saving-Files/import-saving-idt.spec.ts @@ -1,4 +1,4 @@ -import { test, expect, Page } from '@playwright/test'; +import { test, expect, Page, chromium } from '@playwright/test'; import { TopPanelButton, openFileAndAddToCanvasMacro, @@ -8,8 +8,6 @@ import { saveToFile, openFile, receiveFileComparisonData, - // selectOptionInDropdown, - // pressButton, chooseFileFormat, readFileContents, moveMouseAway, @@ -20,6 +18,7 @@ import { pressButton, selectMacromoleculesPanelButton, MacromoleculesTopPanelButton, + selectClearCanvasTool, selectSingleBondTool, waitForRender, takePolymerEditorScreenshot, @@ -28,9 +27,13 @@ import { selectEraseTool, getKet, openFileAndAddToCanvasAsNewProject, + resetZoomLevelToDefault, } from '@utils'; +import { pageReload } from '@utils/common/helpers'; import { + chooseTab, enterSequence, + Tabs, turnOnMacromoleculesEditor, turnOnMicromoleculesEditor, } from '@utils/macromolecules'; @@ -40,9 +43,14 @@ import { togglePhosphatesAccordion, } from '@utils/macromolecules/rnaBuilder'; import { clickOnSequenceSymbol } from '@utils/macromolecules/sequence'; +import { + markResetToDefaultState, + processResetToDefaultState, +} from '@utils/testAnnotations/resetToDefaultState'; + +let page: Page; async function pasteFromClipboardAndAddToMacromoleculesCanvas( - page: Page, structureFormat: string, fillStructure: string, needToWait = true, @@ -70,21 +78,48 @@ async function pasteFromClipboardAndAddToMacromoleculesCanvas( function removeNotComparableData(file: string) { return file.replaceAll('\r', ''); } -test.describe('Import-Saving .idt Files', () => { - test.beforeEach(async ({ page }) => { - await waitForPageInit(page); - await turnOnMacromoleculesEditor(page); + +test.beforeAll(async ({ browser }) => { + let sharedContext; + try { + sharedContext = await browser.newContext(); + } catch (error) { + console.error('Error on creation browser context:', error); + console.log('Restarting browser...'); + await browser.close(); + browser = await chromium.launch(); + sharedContext = await browser.newContext(); + } + + // Reminder: do not pass page as async paramenter to test + page = await sharedContext.newPage(); + await waitForPageInit(page); + await turnOnMacromoleculesEditor(page); +}); + +test.afterEach(async ({ context: _ }, testInfo) => { + await selectClearCanvasTool(page); + await resetZoomLevelToDefault(page); + await processResetToDefaultState(testInfo, page); +}); + +test.afterAll(async ({ browser }) => { + const cntxt = page.context(); + await page.close(); + await cntxt.close(); + await browser.contexts().forEach((someContext) => { + someContext.close(); }); +}); - test(`Import .idt file`, async ({ page }) => { +test.describe('Import-Saving .idt Files', () => { + test(`Import .idt file`, async () => { await openFileAndAddToCanvasMacro('IDT/idt-a.idt', page); await moveMouseAway(page); await takeEditorScreenshot(page); }); - test('Check option "IDT" to the format dropdown menu of modal window Paste from the clipboard is exist', async ({ - page, - }) => { + test('Check option "IDT" to the format dropdown menu of modal window Paste from the clipboard is exist', async () => { /* Test case: Import/Saving files/#4495 Description: Option "IDT" to the format dropdown menu of modal window Paste from the clipboard is exist. @@ -106,9 +141,7 @@ test.describe('Import-Saving .idt Files', () => { } }); - test('Check option "IDT" to dropdown File format of modal window Save Structure is exist', async ({ - page, - }) => { + test('Check option "IDT" to dropdown File format of modal window Save Structure is exist', async () => { /* Test case: Import/Saving files/#4495 Description: Option "IDT" to dropdown File format of modal window Save Structure is exist. @@ -138,9 +171,7 @@ test.describe('Import-Saving .idt Files', () => { } }); - test('Check that in case of peptide monomers are on canvas, error "Peptide monomers are not supported in IDT" appear', async ({ - page, - }) => { + test('Check that in case of peptide monomers are on canvas, error "Peptide monomers are not supported in IDT" appear', async () => { /* Test case: Import/Saving files/#4495 Description: In case of peptide monomers are on canvas, error "Peptide monomers are not supported in IDT" appear. @@ -163,9 +194,7 @@ test.describe('Import-Saving .idt Files', () => { // await takeEditorScreenshot(page); // }); - test('Check import of .ket file and save in .idt format', async ({ - page, - }) => { + test('Check import of .ket file and save in .idt format', async () => { await openFileAndAddToCanvasMacro('KET/rna-a.ket', page); const expectedFile = await getIdt(page); await saveToFile('IDT/idt-rna-a.idt', expectedFile); @@ -184,9 +213,7 @@ test.describe('Import-Saving .idt Files', () => { await takeEditorScreenshot(page); }); - test('Check that empty file can be saved in .idt format', async ({ - page, - }) => { + test('Check that empty file can be saved in .idt format', async () => { const expectedFile = await getIdt(page); await saveToFile('IDT/idt-empty.idt', expectedFile); @@ -202,22 +229,20 @@ test.describe('Import-Saving .idt Files', () => { expect(idtFile).toEqual(idtFileExpected); }); - test('Check that system does not let importing empty .idt file', async ({ - page, - }) => { + test('Check that system does not let importing empty .idt file', async () => { await selectTopPanelButton(TopPanelButton.Open, page); await openFile('IDT/idt-empty.idt', page); await page.getByText('Add to Canvas').isDisabled(); }); - test('Check IDT aliases, where defined in the preview window for Phosphates section', async ({ - page, - }) => { + test('Check IDT aliases, where defined in the preview window for Phosphates section', async () => { /* Test case: Import/Saving files/#4380 Description: IDT aliases, where defined in the preview window for Phosphates. */ - await page.getByTestId('RNA-TAB').click(); + markResetToDefaultState('tabSelection'); + + await chooseTab(page, Tabs.Rna); await togglePhosphatesAccordion(page); await waitForRender(page, async () => { await page.getByTestId('P___Phosphate').hover(); @@ -236,14 +261,14 @@ test.describe('Import-Saving .idt Files', () => { ]; for (const monomer of rnaNucleotides) { - test(`Check IDT aliases, where defined in the preview window for RNA Nucleotides monomer ${monomer}`, async ({ - page, - }) => { + test(`Check IDT aliases, where defined in the preview window for RNA Nucleotides monomer ${monomer}`, async () => { /* Test case: Import/Saving files/#4380 Description: IDT aliases, where defined in the preview window for RNA monomers in library. */ - await page.getByTestId('RNA-TAB').click(); + markResetToDefaultState('tabSelection'); + + await chooseTab(page, Tabs.Rna); await toggleNucleotidesAccordion(page); await waitForRender(page, async () => { await page.getByTestId(monomer).hover(); @@ -261,14 +286,14 @@ test.describe('Import-Saving .idt Files', () => { ]; for (const monomer of rnaMonomers) { - test(`Check IDT aliases, where defined in the preview window for RNA monomer ${monomer}`, async ({ - page, - }) => { + test(`Check IDT aliases, where defined in the preview window for RNA monomer ${monomer}`, async () => { /* Test case: Import/Saving files/#4380 Description: IDT aliases, where defined in the preview window for RNA monomers in library. */ - await page.getByTestId('RNA-TAB').click(); + markResetToDefaultState('tabSelection'); + + await chooseTab(page, Tabs.Rna); await waitForRender(page, async () => { await page.getByTestId(monomer).hover(); }); @@ -289,9 +314,7 @@ test.describe('Import-Saving .idt Files', () => { // await takeEditorScreenshot(page); // }); - test('Should open .ket file and modify to .idt format in save modal textarea', async ({ - page, - }) => { + test('Should open .ket file and modify to .idt format in save modal textarea', async () => { await openFileAndAddToCanvasMacro('KET/rna-a.ket', page); await selectTopPanelButton(TopPanelButton.Save, page); await chooseFileFormat(page, 'IDT'); @@ -318,17 +341,19 @@ test.describe('Import-Saving .idt Files', () => { ]; for (const fileName of fileNames) { - test(`Verify import of ${fileName} sequence with modifications from IDT format using Open file (Sequence mode/Flex/Snake) `, async ({ - page, - }) => { + test(`Verify import of ${fileName} sequence with modifications from IDT format using Open file (Sequence mode/Flex/Snake) `, async () => { /* Test case: Import/Saving files/4310 Description: Structure is opening */ + markResetToDefaultState('defaultLayout'); + await openFileAndAddToCanvasMacro(`IDT/${fileName}.idt`, page); await takeEditorScreenshot(page); + await selectSequenceLayoutModeTool(page); await takeEditorScreenshot(page); + await selectSnakeLayoutModeTool(page); await takeEditorScreenshot(page); }); @@ -343,35 +368,34 @@ test.describe('Import-Saving .idt Files', () => { ]; for (const fileName of fileNames1) { - test(`Verify import of ${fileName} sequence with modifications from IDT format using Paste from Clipboard (Sequence mode/Flex/Snake) `, async ({ - page, - }) => { + test(`Verify import of ${fileName} sequence with modifications from IDT format using Paste from Clipboard (Sequence mode/Flex/Snake) `, async () => { /* Test case: Import/Saving files/4310 Description: Structure is opening */ + markResetToDefaultState('defaultLayout'); + await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, 'IDT', `${fileName}`, ); + await takeEditorScreenshot(page); + await selectSequenceLayoutModeTool(page); await takeEditorScreenshot(page); + await selectSnakeLayoutModeTool(page); await takeEditorScreenshot(page); }); } - test('Verify error handling for invalid sequences with modifications during import from Paste from Clipboard', async ({ - page, - }) => { + test('Verify error handling for invalid sequences with modifications during import from Paste from Clipboard', async () => { /* Test case: Import/Saving files/4310 Description: Error appears */ await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, 'IDT', `A*C*G*C*G*C*G*A*C*T* A*T*A*C*G*C*G*C*C*T`, @@ -380,15 +404,14 @@ test.describe('Import-Saving .idt Files', () => { await takeEditorScreenshot(page); }); - test('Validate that sequences with modifications can be edited after import', async ({ - page, - }) => { + test('Validate that sequences with modifications can be edited after import', async () => { /* Test case: Import/Saving files/4310 Description: Sequences with modifications can be edited after import */ + markResetToDefaultState('defaultLayout'); + await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, 'IDT', `A*C*G*C*G*C*G*A*C*T*A*T*A*C*G*C*G*C*C*T`, ); @@ -400,15 +423,14 @@ test.describe('Import-Saving .idt Files', () => { await takeEditorScreenshot(page); }); - test('Verify export of sequences with modifications from IDT format using API (getIdt)', async ({ - page, - }) => { + test('Verify export of sequences with modifications from IDT format using API (getIdt)', async () => { /* Test case: Import/Saving files/4310 Description: Sequences are exported by getIdt */ + markResetToDefaultState('defaultLayout'); + await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, 'IDT', `A*C*G*C*G*C*G*A*C*T*A*T*A*C*G*C*G*C*C*T`, ); @@ -429,15 +451,12 @@ test.describe('Import-Saving .idt Files', () => { await takeEditorScreenshot(page); }); - test('Verify export of sequences with modifications from IDT format using Save file(Flex mode)', async ({ - page, - }) => { + test('Verify export of sequences with modifications from IDT format using Save file(Flex mode)', async () => { /* Test case: Import/Saving files/4310 Description: IDT appears in save preview */ await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, 'IDT', `A*C*G*C*G*C*G*A*C*T*A*T*A*C*G*C*G*C*C*T`, ); @@ -446,15 +465,14 @@ test.describe('Import-Saving .idt Files', () => { await takeEditorScreenshot(page); }); - test('Verify export of sequences with modifications from IDT format using Save file(Sequence mode)', async ({ - page, - }) => { + test('Verify export of sequences with modifications from IDT format using Save file(Sequence mode)', async () => { /* Test case: Import/Saving files/4310 Description: IDT appears in save preview */ + markResetToDefaultState('defaultLayout'); + await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, 'IDT', `+G*+C*+G*C*G*A*C*T*A*T*A*C*G*+C*+G*+C`, ); @@ -464,15 +482,14 @@ test.describe('Import-Saving .idt Files', () => { await takeEditorScreenshot(page); }); - test('Test performance impact of importing large sequences with multiple modifications via Paste from Clipboard', async ({ - page, - }) => { + test('Test performance impact of importing large sequences with multiple modifications via Paste from Clipboard', async () => { /* Test case: Import/Saving files/4310 Description: Sequences are opened. */ + markResetToDefaultState('defaultLayout'); + await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, 'IDT', `A*C*G*C*G*C*G*A*C*T*A*T*A*C*G*C*G*C*C*T @@ -490,15 +507,14 @@ test.describe('Import-Saving .idt Files', () => { await takeEditorScreenshot(page); }); - test('Verify export of multiple sequences with modifications from IDT format using Save file(Sequence mode)', async ({ - page, - }) => { + test('Verify export of multiple sequences with modifications from IDT format using Save file(Sequence mode)', async () => { /* Test case: Import/Saving files/4310 Description: Sequences are appears at save preview window. */ + markResetToDefaultState('defaultLayout'); + await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, 'IDT', `A*C*G*C*G*C*G*A*C*T*A*T*A*C*G*C*G*C*C*T @@ -517,15 +533,12 @@ test.describe('Import-Saving .idt Files', () => { await takeEditorScreenshot(page); }); - test('Verify bonds establishment between monomers from R2 to R1 attachment points', async ({ - page, - }) => { + test('Verify bonds establishment between monomers from R2 to R1 attachment points', async () => { /* Test case: Import/Saving files/1899 Description: Bonds establishment between monomers from R2 to R1 attachment points. */ await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, 'IDT', `/52MOErA/*/i2MOErC/*/32MOErT/`, ); @@ -535,15 +548,14 @@ test.describe('Import-Saving .idt Files', () => { await takeEditorScreenshot(page); }); - test('Verify import of sequences with /5Phos/ and /3Phos/ modifications', async ({ - page, - }) => { + test('Verify import of sequences with /5Phos/ and /3Phos/ modifications', async () => { /* Test case: Import/Saving files/1899 Description: Sequences with /5Phos/ and /3Phos/ modifications imported. */ + markResetToDefaultState('defaultLayout'); + await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, 'IDT', `/5Phos/ACG/3Phos/`, ); @@ -552,15 +564,14 @@ test.describe('Import-Saving .idt Files', () => { await takeEditorScreenshot(page); }); - test('Verify export of known modified monomers with IDT alias and structure', async ({ - page, - }) => { + test('Verify export of known modified monomers with IDT alias and structure', async () => { /* Test case: Import/Saving files/1900 Description: Sequences are appears at save preview window. */ + markResetToDefaultState('defaultLayout'); + await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, 'IDT', `/52MOErA/*/i2MOErC/*/i2MOErG/*/i2MOErC/*/i2MOErG/*/iMe-dC/*G*A*/iMe-dC/*T*A*T*A*/iMe-dC/*G*/i2MOErC/*/i2MOErG/*/i2MOErC/*/i2MOErC/*/32MOErT/`, ); @@ -573,13 +584,16 @@ test.describe('Import-Saving .idt Files', () => { test( 'Verify error message when export of nucleotides split to submonomers with no IDT alias', { tag: ['@IncorrectResultBecauseOfBug'] }, - async ({ page }) => { + async () => { /* Test case: Import/Saving files/1900/1985 Description: Error message appeared: "This molecule has unsupported monomer and couldn't be exported to IDT notation". We have bug https://github.com/epam/Indigo/issues/1985 When it fixed we should update snapshot. */ + // Reload needed as monomer IDs increment in prior tests, affecting screenshots + await pageReload(page); + await openFileAndAddToCanvasMacro('KET/5formD-form5C-cm.ket', page); await selectTopPanelButton(TopPanelButton.Save, page); await chooseFileFormat(page, 'IDT'); @@ -587,15 +601,12 @@ test.describe('Import-Saving .idt Files', () => { }, ); - test('Verify that if * is specified, Phosphorothioate (sP) is included in nucleotide if not it is (P)', async ({ - page, - }) => { + test('Verify that if * is specified, Phosphorothioate (sP) is included in nucleotide if not it is (P)', async () => { /* Test case: Import/Saving files/1900 Description: If * is specified, Phosphorothioate (sP) is included in nucleotide if not it is (P). */ await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, 'IDT', `/52MOErA/*/i2MOErC/*/32MOErT/ @@ -608,13 +619,14 @@ test.describe('Import-Saving .idt Files', () => { await takeEditorScreenshot(page); }); - test('Open some expected IDT', async ({ page }) => { + test('Open some expected IDT', async () => { /* Test case: Import/Saving files/https://github.com/epam/Indigo/issues/1982 Description: Sequences are opened. */ + markResetToDefaultState('defaultLayout'); + await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, 'IDT', `/52MOErA/ /i2MOErA/ @@ -629,13 +641,14 @@ test.describe('Import-Saving .idt Files', () => { await takeEditorScreenshot(page); }); - test('Open some expected IDT (Part2)', async ({ page }) => { + test('Open some expected IDT (Part2)', async () => { /* Test case: Import/Saving files/https://github.com/epam/Indigo/issues/1982 Description: Sequences are opened. */ + markResetToDefaultState('defaultLayout'); + await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, 'IDT', `/32MOErA/ /52MOErA/*/32MOErC/ @@ -650,15 +663,12 @@ test.describe('Import-Saving .idt Files', () => { await takeEditorScreenshot(page); }); - test(`Verifiy it is not possible to load IDT data that have ' * ' if it is not between nucleotides or nucleosides and error should occure`, async ({ - page, - }) => { + test(`Verifiy it is not possible to load IDT data that have ' * ' if it is not between nucleotides or nucleosides and error should occure`, async () => { /* Test case: Import/Saving files/https://github.com/epam/Indigo/issues/1978 Description: Error appears */ await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, 'IDT', `/52MOErG/*/i2MOErG/*/3Phos/`, false, @@ -666,22 +676,19 @@ test.describe('Import-Saving .idt Files', () => { await takeEditorScreenshot(page); }); - test('Verify it is possible to load IDT data from clipboard having trailing spaces at the end of the IDT string', async ({ - page, - }) => { + test('Verify it is possible to load IDT data from clipboard having trailing spaces at the end of the IDT string', async () => { /* Test case: Import/Saving files/https://github.com/epam/Indigo/issues/1979 Description: Sequences are opened. */ await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, 'IDT', `/52MOErA/*/i2MOErC/*/i2MOErG/*G*+A*mT*A*T*rA*G*/i2MOErG/*/32MOErT/ `, ); await takeEditorScreenshot(page); }); - test('Validate 80 char formating for IDT export', async ({ page }) => { + test('Validate 80 char formating for IDT export', async () => { /* Test case: Import/Saving files/https://github.com/epam/Indigo/issues/1986 Description: It is possible save 80 char formating for IDT. @@ -698,7 +705,7 @@ test.describe('Import-Saving .idt Files', () => { test.fail( 'Check import of .ket file with unresolved monomers and save in .idt format ', { tag: ['@IncorrectResultBecauseOfBug'] }, - async ({ page }) => { + async () => { /* Test working not a proper way because we have a bug https://github.com/epam/Indigo/issues/2121 */ @@ -721,15 +728,14 @@ test.describe('Import-Saving .idt Files', () => { }, ); - test('Verify import of unresolved IDT monomers as "black box" in flex/snake modes and ? in sequence', async ({ - page, - }) => { + test('Verify import of unresolved IDT monomers as "black box" in flex/snake modes and ? in sequence', async () => { /* Test case: Import/Saving files/4431 Description: Unresolved IDT monomers imported as a "black box" in flex/snake modes and ? in sequence. */ + markResetToDefaultState('defaultLayout'); + await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, 'IDT', `/52MOErA/*/i2MOErC/*/i2MOErG/*/i2MOErC/*/i2MOErG/*/iMe-dC/*G*A*/iMe-dC/*T*A*T*A*/iMe-dC/*G*/i2MOErC/*/i2MOErG/*/i2MOErC/*/i2MOErC/*/32MOErT/`, ); @@ -740,15 +746,14 @@ test.describe('Import-Saving .idt Files', () => { await takeEditorScreenshot(page); }); - test('Verify hover preview contains IDT alias only for unresolved IDT monomers', async ({ - page, - }) => { + test('Verify hover preview contains IDT alias only for unresolved IDT monomers', async () => { /* Test case: Import/Saving files/4431 Description: Hover preview contains IDT alias only for unresolved IDT monomers. */ + markResetToDefaultState('defaultLayout'); + await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, 'IDT', `/52MOErA/*/i2MOErC/*/i2MOErG/*/i2MOErC/*/i2MOErG/*/iMe-dC/*G*A*/iMe-dC/*T*A*T*A*/iMe-dC/*G*/i2MOErC/*/i2MOErG/*/i2MOErC/*/i2MOErC/*/32MOErT/`, ); @@ -759,15 +764,12 @@ test.describe('Import-Saving .idt Files', () => { await takeEditorScreenshot(page); }); - test('Check that R1/R2 (backbone) and R3/R4 (sidechain) attachment points are available for unresolved IDT monomers', async ({ - page, - }) => { + test('Check that R1/R2 (backbone) and R3/R4 (sidechain) attachment points are available for unresolved IDT monomers', async () => { /* Test case: Import/Saving files/4431 Description: R1/R2 (backbone) and R3/R4 (sidechain) attachment points are available for unresolved IDT monomers. */ await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, 'IDT', `/52MOErA/*/i2MOErC/*/i2MOErG/*/i2MOErC/*/i2MOErG/*/iMe-dC/*G*A*/iMe-dC/*T*A*T*A*/iMe-dC/*G*/i2MOErC/*/i2MOErG/*/i2MOErC/*/i2MOErC/*/32MOErT/`, ); @@ -779,7 +781,7 @@ test.describe('Import-Saving .idt Files', () => { test( 'Connect unresolved IDT monomer to known monomers through R2/R1 connections', { tag: ['@IncorrectResultBecauseOfBug'] }, - async ({ page }) => { + async () => { /* Test case: Import/Saving files/4431 Description: Connect unresolved IDT monomer to known monomers through R2/R1 connections. @@ -790,11 +792,7 @@ test.describe('Import-Saving .idt Files', () => { const y = 400; const firstMonomer = await page.getByText('iMe-dC').locator('..'); const secondMonomer = await page.getByText('1Nal').locator('..').first(); - await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, - 'IDT', - `/iMe-dC/`, - ); + await pasteFromClipboardAndAddToMacromoleculesCanvas('IDT', `/iMe-dC/`); await page.getByTestId('1Nal___3-(1-naphthyl)-alanine').click(); await page.mouse.click(x, y); await bondTwoMonomersPointToPoint( @@ -810,13 +808,13 @@ test.describe('Import-Saving .idt Files', () => { }, ); - test('Connect unresolved IDT monomer to known monomers through R3/R4 connections', async ({ - page, - }) => { + test('Connect unresolved IDT monomer to known monomers through R3/R4 connections', async () => { /* Test case: Import/Saving files/4431 Description: Connect unresolved IDT monomer to known monomers through R3/R4 connections. */ + markResetToDefaultState('tabSelection'); + const x = 650; const y = 400; const firstMonomer = await page.getByText('iMe-dC').locator('..'); @@ -824,12 +822,8 @@ test.describe('Import-Saving .idt Files', () => { .getByText('Test-6-Ch') .locator('..') .first(); - await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, - 'IDT', - `/iMe-dC/`, - ); - await page.getByTestId('CHEM-TAB').click(); + await pasteFromClipboardAndAddToMacromoleculesCanvas('IDT', `/iMe-dC/`); + await chooseTab(page, Tabs.Chem); await page.getByTestId('Test-6-Ch___Test-6-AP-Chem').click(); await page.mouse.click(x, y); await bondTwoMonomersPointToPoint( @@ -844,20 +838,14 @@ test.describe('Import-Saving .idt Files', () => { await takeEditorScreenshot(page); }); - test('Delete bond between unresolved and known monomers connected through R2/R1 and Undo', async ({ - page, - }) => { + test('Delete bond between unresolved and known monomers connected through R2/R1 and Undo', async () => { const x = 650; const y = 400; const firstMonomer = await page.getByText('iMe-dC').locator('..'); const secondMonomer = await page.getByText('1Nal').locator('..').first(); const bondLine = page.locator('g[pointer-events="stroke"]').first(); - await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, - 'IDT', - `/iMe-dC/`, - ); + await pasteFromClipboardAndAddToMacromoleculesCanvas('IDT', `/iMe-dC/`); await page.getByTestId('1Nal___3-(1-naphthyl)-alanine').click(); await page.mouse.click(x, y); await bondTwoMonomersPointToPoint( @@ -881,13 +869,13 @@ test.describe('Import-Saving .idt Files', () => { await takeEditorScreenshot(page); }); - test('Delete bond between unresolved and known monomers connected through R3/R4 and Undo', async ({ - page, - }) => { + test('Delete bond between unresolved and known monomers connected through R3/R4 and Undo', async () => { /* Test case: Import/Saving files/4431 Description: Bond deleted and after pressing Undo appears. */ + markResetToDefaultState('tabSelection'); + const x = 650; const y = 400; const firstMonomer = await page.getByText('iMe-dC').locator('..'); @@ -896,12 +884,8 @@ test.describe('Import-Saving .idt Files', () => { .locator('..') .first(); const bondLine = page.locator('g[pointer-events="stroke"]').first(); - await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, - 'IDT', - `/iMe-dC/`, - ); - await page.getByTestId('CHEM-TAB').click(); + await pasteFromClipboardAndAddToMacromoleculesCanvas('IDT', `/iMe-dC/`); + await chooseTab(page, Tabs.Chem); await page.getByTestId('Test-6-Ch___Test-6-AP-Chem').click(); await page.mouse.click(x, y); await bondTwoMonomersPointToPoint( @@ -918,7 +902,7 @@ test.describe('Import-Saving .idt Files', () => { await takeEditorScreenshot(page); }); - test('Copy/Paste sequence with unresolved IDT monomers', async ({ page }) => { + test('Copy/Paste sequence with unresolved IDT monomers', async () => { /* Test case: Import/Saving files/4431 Description: Sequence with unresolved IDT monomers copied/pasted. @@ -926,7 +910,6 @@ test.describe('Import-Saving .idt Files', () => { const x = 0; const y = 600; await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, 'IDT', `/52MOErA/*/i2MOErC/*/i2MOErG/*/i2MOErC/*/i2MOErG/*/iMe-dC/*G*A*/iMe-dC/*T*A*T*A*/iMe-dC/`, ); @@ -937,20 +920,14 @@ test.describe('Import-Saving .idt Files', () => { await takeEditorScreenshot(page); }); - test('Verify modal window for AP selection when establishing bonds with unresolved monomers(Peptide)', async ({ - page, - }) => { + test('Verify modal window for AP selection when establishing bonds with unresolved monomers(Peptide)', async () => { /* Test case: Import/Saving files/4431 Description: Modal window for AP selection should be displayed anytime when user establishes bond with unknown monomer. */ const x = 650; const y = 400; - await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, - 'IDT', - `/iMe-dC/`, - ); + await pasteFromClipboardAndAddToMacromoleculesCanvas('IDT', `/iMe-dC/`); await page.getByTestId('1Nal___3-(1-naphthyl)-alanine').click(); await page.mouse.click(x, y); await selectSingleBondTool(page); @@ -961,20 +938,16 @@ test.describe('Import-Saving .idt Files', () => { await takeEditorScreenshot(page); }); - test('Verify bonds establishment for unresolved IDT monomers in snake mode', async ({ - page, - }) => { + test('Verify bonds establishment for unresolved IDT monomers in snake mode', async () => { /* Test case: Import/Saving files/4431 Description: Connection established. */ + markResetToDefaultState('defaultLayout'); + const x = 650; const y = 400; - await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, - 'IDT', - `/iMe-dC/`, - ); + await pasteFromClipboardAndAddToMacromoleculesCanvas('IDT', `/iMe-dC/`); await page.getByTestId('1Nal___3-(1-naphthyl)-alanine').click(); await page.mouse.click(x, y); await selectSnakeLayoutModeTool(page); @@ -986,21 +959,17 @@ test.describe('Import-Saving .idt Files', () => { await takeEditorScreenshot(page); }); - test('Verify modal window for AP selection when establishing bonds with unresolved monomers(CHEM)', async ({ - page, - }) => { + test('Verify modal window for AP selection when establishing bonds with unresolved monomers(CHEM)', async () => { /* Test case: Import/Saving files/4431 Description: Modal window for AP selection should be displayed anytime when user establishes bond with unknown monomer. */ + markResetToDefaultState('tabSelection'); + const x = 650; const y = 400; - await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, - 'IDT', - `/iMe-dC/`, - ); - await page.getByTestId('CHEM-TAB').click(); + await pasteFromClipboardAndAddToMacromoleculesCanvas('IDT', `/iMe-dC/`); + await chooseTab(page, Tabs.Chem); await page.getByTestId('Test-6-Ch___Test-6-AP-Chem').click(); await page.mouse.click(x, y); await selectSingleBondTool(page); @@ -1014,15 +983,15 @@ test.describe('Import-Saving .idt Files', () => { const testFormats: Array<'FASTA' | 'Sequence'> = ['FASTA', 'Sequence']; for (const format of testFormats) { - test(`Verify error message when saving macromolecules with unresolved monomers to non-IDT/KET format ${format}`, async ({ - page, - }) => { + test(`Verify error message when saving macromolecules with unresolved monomers to non-IDT/KET format ${format}`, async () => { /* Test case: Import/Saving files/#4431 Description: Error message appears when saving macromolecules with unresolved monomers to non-IDT/KET formats. */ + // Reload needed as monomer IDs increment in prior tests, affecting screenshots + await pageReload(page); + await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, 'IDT', `/52MOErA/*/i2MOErC/*/i2MOErG/*/i2MOErC/*/i2MOErG/*/iMe-dC/*G*A*/iMe-dC/*T*A*T*A*/iMe-dC/`, ); @@ -1032,15 +1001,15 @@ test.describe('Import-Saving .idt Files', () => { }); } - test('Verify saving of unresolved IDT monomers in KET format', async ({ - page, - }) => { + test('Verify saving of unresolved IDT monomers in KET format', async () => { /* Test case: #4531 Description: Unresolved IDT monomers saved in KET format. */ + // Reload needed as monomer IDs increment in prior tests, affecting screenshots + await pageReload(page); + await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, 'IDT', `/52MOErA/*/i2MOErC/*/i2MOErG/*/i2MOErC/*/i2MOErG/*/iMe-dC/*G*A*/iMe-dC/*T*A*T*A*/iMe-dC/`, ); @@ -1065,13 +1034,13 @@ test.describe('Import-Saving .idt Files', () => { await takeEditorScreenshot(page); }); - test('Verify opening of unresolved IDT monomers saved in KET format in Micro mode', async ({ - page, - }) => { + test('Verify opening of unresolved IDT monomers saved in KET format in Micro mode', async () => { /* Test case: #4531 Description: Unresolved IDT monomers saved in KET format opened in Micro mode. */ + markResetToDefaultState('macromoleculesEditor'); + await turnOnMicromoleculesEditor(page); await openFileAndAddToCanvasAsNewProject( 'KET/sequence-with-unresolved-idt-monomers-micro-mode-expected.ket', @@ -1080,15 +1049,14 @@ test.describe('Import-Saving .idt Files', () => { await takeEditorScreenshot(page); }); - test('Verify display of unresolved IDT monomers when switching from Macro mode to Micro mode', async ({ - page, - }) => { + test('Verify display of unresolved IDT monomers when switching from Macro mode to Micro mode', async () => { /* Test case: #4531 Description: Unresolved IDT monomers are displayed as abbreviation. */ + markResetToDefaultState('macromoleculesEditor'); + await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, 'IDT', `/52MOErA/*/i2MOErC/*/i2MOErG/*/i2MOErC/*/i2MOErG/*/iMe-dC/*G*A*/iMe-dC/*T*A*T*A*/iMe-dC/`, ); @@ -1096,15 +1064,12 @@ test.describe('Import-Saving .idt Files', () => { await takeEditorScreenshot(page); }); - test('Verify saving of unresolved IDT monomers in IDT format', async ({ - page, - }) => { + test('Verify saving of unresolved IDT monomers in IDT format', async () => { /* Test case: Import/Saving files/4431 Description: Unresolved IDT monomers saved and opened in IDT format */ await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, 'IDT', `/52MOErA/*/i2MOErC/*/i2MOErG/*/i2MOErC/*/i2MOErG/*/iMe-dC/*G*A*/iMe-dC/*T*A*T*A*/iMe-dC/`, ); @@ -1129,18 +1094,12 @@ test.describe('Import-Saving .idt Files', () => { await takeEditorScreenshot(page); }); - test('Verify deletion of unresolved IDT monomers from canvas', async ({ - page, - }) => { + test('Verify deletion of unresolved IDT monomers from canvas', async () => { /* Test case: Import/Saving files/4431 Description: Unresolved IDT monomers deleted from canvas. */ - await pasteFromClipboardAndAddToMacromoleculesCanvas( - page, - 'IDT', - `/iMe-dC/`, - ); + await pasteFromClipboardAndAddToMacromoleculesCanvas('IDT', `/iMe-dC/`); await takeEditorScreenshot(page); await selectEraseTool(page); await page.getByText('iMe-dC').locator('..').click(); diff --git a/ketcher-autotests/tests/utils/canvas/tools/helpers.ts b/ketcher-autotests/tests/utils/canvas/tools/helpers.ts index 6048820008..e51b04f3fd 100644 --- a/ketcher-autotests/tests/utils/canvas/tools/helpers.ts +++ b/ketcher-autotests/tests/utils/canvas/tools/helpers.ts @@ -131,9 +131,36 @@ export async function selectImageTool(page: Page) { await bondToolButton.click(); } -export async function selectClearCanvasTool(page: Page) { - const bondToolButton = page.getByTestId('clear-canvas'); - await bondToolButton.click(); +/** + * Attempts to click the 'Clear Canvas' button until the click becomes possible. + * It limits the attempts by a specified maximum number and presses the 'Escape' key to possibly close any modal overlays. + * If the maximum number of attempts is not provided, it defaults to 10. + * + * @param {Page} page - The Playwright page instance where the button is located. + * @param {number} [maxAttempts=5] - The maximum number of retry attempts to click the button. + * @throws {Error} Throws an error if the button cannot be clicked after the specified number of attempts. + */ +export async function selectClearCanvasTool( + page: Page, + maxAttempts: number = 10, +) { + const clearCanvasButton = page.getByTestId('clear-canvas'); + let attempts = 0; + + while (attempts < maxAttempts) { + try { + await clearCanvasButton.click({ force: false, timeout: 1000 }); + return; + } catch (error) { + attempts++; + await page.keyboard.press('Escape'); + await page.waitForTimeout(100); + } + } + + throw new Error( + `Unable to click the 'Clear Canvas' button after ${maxAttempts} attempts.`, + ); } export async function selectRectangleSelectionTool(page: Page) { diff --git a/ketcher-autotests/tests/utils/keyboard/index.ts b/ketcher-autotests/tests/utils/keyboard/index.ts index dab01d41d4..75b9fa9330 100644 --- a/ketcher-autotests/tests/utils/keyboard/index.ts +++ b/ketcher-autotests/tests/utils/keyboard/index.ts @@ -1,5 +1,10 @@ +import { Page } from '@playwright/test'; import { isMacOS } from '../os'; export function getControlModifier() { return isMacOS() ? 'Meta' : 'Control'; } + +export async function resetZoomLevelToDefault(page: Page) { + await page.keyboard.press('Control+0'); +} diff --git a/ketcher-autotests/tests/utils/macromolecules/index.ts b/ketcher-autotests/tests/utils/macromolecules/index.ts index 25496418ed..b9fa080935 100644 --- a/ketcher-autotests/tests/utils/macromolecules/index.ts +++ b/ketcher-autotests/tests/utils/macromolecules/index.ts @@ -4,6 +4,10 @@ import { MOLECULES_MODE, POLYMER_TOGGLER, LAYOUT_TOGGLER, + RNA_TAB, + PEPTIDES_TAB, + FAVORITES_TAB, + CHEM_TAB, } from '@constants/testIdConstants'; import { moveMouseToTheMiddleOfTheScreen, @@ -68,6 +72,20 @@ export async function chooseFileFormat( }); } +export const Tabs = { + Favorites: { displayName: 'Favorites', testId: FAVORITES_TAB }, + Peptides: { displayName: 'Peptides', testId: PEPTIDES_TAB }, + Rna: { displayName: 'RNA', testId: RNA_TAB }, + Chem: { displayName: 'CHEM', testId: CHEM_TAB }, +}; + +export async function chooseTab( + page: Page, + tab: (typeof Tabs)[keyof typeof Tabs], +) { + await page.getByTestId(tab.testId).click(); +} + export async function enterSequence(page: Page, sequence: string) { for (const nucleotide of sequence) { await page.keyboard.press(nucleotide); diff --git a/ketcher-autotests/tests/utils/testAnnotations/resetToDefaultState.ts b/ketcher-autotests/tests/utils/testAnnotations/resetToDefaultState.ts new file mode 100644 index 0000000000..e1b784de4b --- /dev/null +++ b/ketcher-autotests/tests/utils/testAnnotations/resetToDefaultState.ts @@ -0,0 +1,46 @@ +import { Page, test, TestInfo } from '@playwright/test'; +import { selectFlexLayoutModeTool } from '@utils/canvas'; +import { + chooseTab, + Tabs, + turnOnMacromoleculesEditor, + turnOnMicromoleculesEditor, +} from '@utils/macromolecules'; + +const resetStateTypes = { + defaultLayout: async (page: Page) => { + await selectFlexLayoutModeTool(page); + }, + tabSelection: async (page: Page) => { + await chooseTab(page, Tabs.Peptides); + }, + micromoleculesEditor: async (page: Page) => { + await turnOnMicromoleculesEditor(page); + }, + macromoleculesEditor: async (page: Page) => { + await turnOnMacromoleculesEditor(page); + }, +}; + +type ResetStateType = keyof typeof resetStateTypes; + +export const markResetToDefaultState = (resetStateType: ResetStateType) => { + test.info().annotations.push({ type: 'reset', description: resetStateType }); +}; + +export const processResetToDefaultState = async ( + testInfo: TestInfo, + page: Page, +) => { + const resetActions = testInfo.annotations + .filter((a) => a.type === 'reset') + .map((a) => a.description as ResetStateType); + + for (const resetTypeStr in resetStateTypes) { + const resetType = resetTypeStr as ResetStateType; + + if (resetActions.includes(resetType)) { + await resetStateTypes[resetType](page); + } + } +};