diff --git a/redisinsight/ui/src/utils/monacoUtils.ts b/redisinsight/ui/src/utils/monacoUtils.ts index 1fa6c6b6fc..36a97b4aa6 100644 --- a/redisinsight/ui/src/utils/monacoUtils.ts +++ b/redisinsight/ui/src/utils/monacoUtils.ts @@ -187,6 +187,7 @@ export const createSyntaxWidget = (text: string, shortcutText: string) => { const shortcut = document.createElement('span') shortcut.classList.add('monaco-widget__shortcut') + widget.setAttribute('data-testid', 'monaco-widget') shortcut.innerHTML = shortcutText widget.append(title, shortcut) diff --git a/tests/e2e/pageObjects/workbench-page.ts b/tests/e2e/pageObjects/workbench-page.ts index af7db6b2e8..65a134fe45 100644 --- a/tests/e2e/pageObjects/workbench-page.ts +++ b/tests/e2e/pageObjects/workbench-page.ts @@ -76,6 +76,9 @@ export class WorkbenchPage { preselectCreateHashIndex: Selector commandExecutionResult: Selector commandExecutionResultFailed: Selector + monacoWidget: Selector + cancelButton: Selector + applyButton: Selector constructor() { //CSS selectors @@ -123,6 +126,8 @@ export class WorkbenchPage { this.enablementAreaPagination = Selector('[data-testid=enablement-area__pagination-popover-btn]'); this.paginationPopoverButtons = Selector('[data-testid=enablement-area__pagination-popover] button'); this.fullScreenButton = Selector('[data-testid=toggle-full-screen]'); + this.cancelButton = Selector('[data-testid=cancel-btn]'); + this.applyButton = Selector('[data-testid=apply-btn]'); // TEXT INPUTS (also referred to as 'Text fields') this.queryInput = Selector('[data-testid=query-input-container]'); this.scriptsLines = Selector('[data-testid=query-input-container] .view-lines'); @@ -157,6 +162,7 @@ export class WorkbenchPage { this.customPluginsViewType = Selector('[data-test-subj*=clients-list]'); this.commandExecutionResult = Selector('[data-testid=query-common-result]'); this.commandExecutionResultFailed = Selector('[data-testid=cli-output-response-fail]'); + this.monacoWidget = Selector('[data-testid=monaco-widget]'); } /** diff --git a/tests/e2e/tests/critical-path/workbench/cypher.e2e.ts b/tests/e2e/tests/critical-path/workbench/cypher.e2e.ts new file mode 100644 index 0000000000..e31d49ad7f --- /dev/null +++ b/tests/e2e/tests/critical-path/workbench/cypher.e2e.ts @@ -0,0 +1,55 @@ +import { rte } from '../../../helpers/constants'; +import { acceptLicenseTermsAndAddDatabase, deleteDatabase } from '../../../helpers/database'; +import { MyRedisDatabasePage, WorkbenchPage } from '../../../pageObjects'; +import { commonUrl, ossStandaloneConfig } from '../../../helpers/conf'; + +const myRedisDatabasePage = new MyRedisDatabasePage(); +const workbenchPage = new WorkbenchPage(); + +fixture `Cypher syntax at Workbench` + .meta({type: 'critical_path'}) + .page(commonUrl) + .beforeEach(async t => { + await acceptLicenseTermsAndAddDatabase(ossStandaloneConfig, ossStandaloneConfig.databaseName); + //Go to Workbench page + await t.click(myRedisDatabasePage.workbenchButton); + }) + .afterEach(async() => { + //Drop database + await deleteDatabase(ossStandaloneConfig.databaseName); + }) +test + .meta({ rte: rte.standalone }) + ('Verify that user can see popover Editor when clicks on “Use Cypher Syntax” popover in the Editor or “Shift+Space”', async t => { + const command = 'GRAPH.QUERY graph'; + //Type command and put the cursor inside + await t.typeText(workbenchPage.queryInput, `${command} "query"`, { replace: true }); + await t.pressKey('left'); + //Open popover editor by clicks on “Use Cypher Syntax” + await t.click(workbenchPage.monacoWidget); + await t.expect(await workbenchPage.queryInput.nth(1).visible).ok('The user can see opened popover Editor'); + //Close popover editor and re-open by shortcut + await t.pressKey('esc'); + await t.expect(await workbenchPage.queryInput.nth(1).visible).notOk('The popover Editor is closed'); + await t.pressKey('shift+space'); + await t.expect(await workbenchPage.queryInput.nth(1).visible).ok('The user can see opened popover Editor'); + }); +test + .meta({ rte: rte.standalone }) + ('Verify that popover Editor is populated with the script that was detected between the quotes or it is blank if quotes were empty', async t => { + const command = 'GRAPH.QUERY graph'; + const script = 'query' + //Type command with empty script and open popover + await t.typeText(workbenchPage.queryInput, `${command} ""`, { replace: true }); + await t.pressKey('left'); + await t.click(workbenchPage.monacoWidget); + //Verify that the Editor is blank + await t.expect(workbenchPage.scriptsLines.nth(1).textContent).eql('', 'The user can see blank Editor'); + //Close popover editor and re-open with added script + await t.pressKey('esc'); + await t.typeText(workbenchPage.queryInput, `${command} "${script}`, { replace: true }); + await t.pressKey('left'); + await t.click(workbenchPage.monacoWidget); + //Verify that the Editor is populated with the script + await t.expect(workbenchPage.scriptsLines.nth(1).textContent).eql(script, 'The user can see editor populated with the script that was detected between the quotes'); + }); diff --git a/tests/e2e/tests/regression/workbench/cypher.e2e.ts b/tests/e2e/tests/regression/workbench/cypher.e2e.ts new file mode 100644 index 0000000000..9c99be4318 --- /dev/null +++ b/tests/e2e/tests/regression/workbench/cypher.e2e.ts @@ -0,0 +1,86 @@ +import { rte } from '../../../helpers/constants'; +import { acceptLicenseTermsAndAddDatabase, deleteDatabase } from '../../../helpers/database'; +import { MyRedisDatabasePage, WorkbenchPage } from '../../../pageObjects'; +import { commonUrl, ossStandaloneConfig } from '../../../helpers/conf'; + +const myRedisDatabasePage = new MyRedisDatabasePage(); +const workbenchPage = new WorkbenchPage(); + +fixture `Cypher syntax at Workbench` + .meta({type: 'regression'}) + .page(commonUrl) + .beforeEach(async t => { + await acceptLicenseTermsAndAddDatabase(ossStandaloneConfig, ossStandaloneConfig.databaseName); + //Go to Workbench page + await t.click(myRedisDatabasePage.workbenchButton); + }) + .afterEach(async() => { + //Drop database + await deleteDatabase(ossStandaloneConfig.databaseName); + }) +test + .meta({ rte: rte.standalone }) + ('Verify that user can see popover “Use Cypher Syntax” when cursor is inside the query argument double/single quotes in the GRAPH command', async t => { + const command = 'GRAPH.QUERY graph'; + //Type command and put the cursor inside + await t.typeText(workbenchPage.queryInput, `${command} "query"`, { replace: true }); + await t.pressKey('left'); + //Check that user can see popover + await t.expect(await workbenchPage.monacoWidget.textContent).contains('Use Cypher Editor', 'The user can see popover Use Cypher Syntax'); + await t.expect(await workbenchPage.monacoWidget.textContent).contains('Shift+Space', 'The user can see shortcut for Cypher Syntax'); + //Verify the popover with single quotes + await t.typeText(workbenchPage.queryInput, `${command} ''`, { replace: true }); + await t.pressKey('left'); + await t.expect(await workbenchPage.monacoWidget.textContent).contains('Use Cypher Editor', 'The user can see popover Use Cypher Syntax'); + }); +test + .meta({ rte: rte.standalone }) + ('Verify that when user clicks on the “X” control or use shortcut “ESC” popover Editor is closed and changes are not saved', async t => { + const command = 'GRAPH.QUERY graph "query"'; + //Type command and open the popover editor + await t.typeText(workbenchPage.queryInput, command, { replace: true }); + await t.pressKey('left'); + await t.click(workbenchPage.monacoWidget); + //Do some changes in the Editor and close by “X” control + await t.typeText(workbenchPage.queryInput.nth(1), 'test', { replace: true }); + await t.click(workbenchPage.cancelButton); + //Verify that editor is closed and changes are not saved + let commandAfter = await workbenchPage.scriptsLines.textContent; + await t.expect(workbenchPage.queryInput.nth(1).exists).notOk('The popover Editor is closed'); + await t.expect(commandAfter.replace(/\s/g, ' ')).eql(command, 'The changes are not saved from the Editor'); + //Re-open the Editor and do some changes and close by shortcut “ESC” + await t.click(workbenchPage.monacoWidget); + await t.typeText(workbenchPage.queryInput.nth(1), 'test', { replace: true }); + await t.pressKey('esc'); + //Verify that editor is closed and changes are not saved + commandAfter = await workbenchPage.scriptsLines.textContent; + await t.expect(commandAfter.replace(/\s/g, ' ')).eql(command, 'The changes are not saved from the Editor'); + }); +test + .meta({ rte: rte.standalone }) + ('Verify that when user use shortcut “CTRL+ENTER” or clicks on the “V” control popover Editor is closed and changes are saved', async t => { + let script = 'query'; + const command = 'GRAPH.QUERY graph'; + //Type command and open the popover editor + await t.typeText(workbenchPage.queryInput, `${command} "${script}`, { replace: true }); + await t.pressKey('left'); + await t.click(workbenchPage.monacoWidget); + //Do some changes in the Editor and click on the “V” control + script = 'test'; + await t.pressKey('ctrl+a'); + await t.typeText(workbenchPage.queryInput.nth(1), script, { replace: true }); + await t.click(workbenchPage.applyButton); + //Verify that editor is closed and changes are saved + let commandAfter = await workbenchPage.scriptsLines.textContent; + await t.expect(workbenchPage.queryInput.nth(1).exists).notOk('The popover Editor is closed'); + await t.expect(commandAfter.replace(/\s/g, ' ')).eql(`${command} "${script}"`, 'The changes are not saved from the Editor'); + //Re-open the Editor and do some changes and use keyboard shortcut “CTRL+ENTER” + await t.click(workbenchPage.monacoWidget); + script = 'test2'; + await t.pressKey('ctrl+a'); + await t.typeText(workbenchPage.queryInput.nth(1), 'test2', { paste: true, replace: true }); + await t.pressKey('ctrl+enter'); + //Verify that editor is closed and changes are not saved + commandAfter = await workbenchPage.scriptsLines.textContent; + await t.expect(commandAfter.replace(/\s/g, ' ')).eql(`${command} "${script}"`, 'The changes are not saved from the Editor'); + });