From 9ed5ac0ce2fed48e585a99c7c054fad789a48315 Mon Sep 17 00:00:00 2001 From: mariasergeenko Date: Tue, 24 Dec 2024 13:03:40 +0100 Subject: [PATCH] add tests --- .../common-actions/DatabasesActions.ts | 2 +- .../editor-view/EditDatabaseView.ts | 2 + .../components/editor-view/KeyDetailsView.ts | 24 ++++ .../components/tree-view/TreeView.ts | 37 +++++- tests/e2e/src/tests/browser/formatters.e2e.ts | 73 +++++++++++- tests/e2e/src/tests/browser/hash-key.e2e.ts | 37 ++++++ tests/e2e/src/tests/browser/json-key.e2e.ts | 16 +++ tests/e2e/src/tests/database/edit-db.e2e.ts | 31 ++++- .../tests/database/logical-database.e2e.ts | 108 ++++++++++++++++++ 9 files changed, 322 insertions(+), 8 deletions(-) create mode 100644 tests/e2e/src/tests/database/logical-database.e2e.ts diff --git a/tests/e2e/src/helpers/common-actions/DatabasesActions.ts b/tests/e2e/src/helpers/common-actions/DatabasesActions.ts index b0f32183..309f6c9f 100644 --- a/tests/e2e/src/helpers/common-actions/DatabasesActions.ts +++ b/tests/e2e/src/helpers/common-actions/DatabasesActions.ts @@ -79,7 +79,7 @@ export class DatabasesActions extends CommonDriverExtension { await treeView.switchToInnerViewFrame(InnerViews.TreeInnerView) if ( !(await treeView.isElementDisplayed( - treeView.getRefreshDatabaseBtnByName(databaseParameters.databaseName!), + treeView.getRefreshIndexedDatabaseBtnByName(databaseParameters.databaseName!), )) ) { await treeView.clickDatabaseByName(databaseParameters.databaseName!) diff --git a/tests/e2e/src/page-objects/components/editor-view/EditDatabaseView.ts b/tests/e2e/src/page-objects/components/editor-view/EditDatabaseView.ts index ad861c0c..3b4f15f3 100644 --- a/tests/e2e/src/page-objects/components/editor-view/EditDatabaseView.ts +++ b/tests/e2e/src/page-objects/components/editor-view/EditDatabaseView.ts @@ -12,4 +12,6 @@ export class EditDatabaseView extends DatabaseDetailsView { moduleBloomIcon = By.xpath(`//*[contains(@data-testid, 'RedisBloom')]`) moduleAIIcon = By.xpath(`//*[contains(@data-testid, 'RedisAI')]`) moduleGearsIcon = By.xpath(`//*[contains(@data-testid, 'RedisGears')]`) + removeCertificateButton = By.xpath(`//button[contains(@data-testid, 'delete-option-')]`) + confirmRemoveCertificateButton = By.xpath(`//vscode-button[contains(@data-testid, 'delete-option-')]`) } diff --git a/tests/e2e/src/page-objects/components/editor-view/KeyDetailsView.ts b/tests/e2e/src/page-objects/components/editor-view/KeyDetailsView.ts index 65c54852..2377a0df 100644 --- a/tests/e2e/src/page-objects/components/editor-view/KeyDetailsView.ts +++ b/tests/e2e/src/page-objects/components/editor-view/KeyDetailsView.ts @@ -7,6 +7,7 @@ import { import { CommonDriverExtension } from '@e2eSrc/helpers/CommonDriverExtension' import { WebView } from '@e2eSrc/page-objects/components/WebView' import { InputWithButtons } from '../common/InputWithButtons' +import { Key } from 'vscode-extension-tester' /** * Key details view @@ -16,9 +17,14 @@ export class KeyDetailsView extends WebView { keySize = By.xpath(`//div[@data-testid='key-size-text']`) keyLength = By.xpath(`//div[@data-testid='key-length-text']`) refreshKeyButton = By.xpath(`//*[@data-testid='key-refresh-btn']`) + refreshKeyArrow = By.xpath(`//*[@data-testid='key-auto-refresh-config-btn']`) + refreshKeyMessage = By.xpath(`//*[@data-testid='key-refresh-message']`) + autoRefreshInput= By.xpath(`//*[@data-testid='inline-item-editor']`) + autoRefreshCheckBox= By.xpath(`//*[contains(@class, 'popover-auto-refresh-content')]//label`) applyBtn = By.xpath( `//*[@class='key-details-body']//*[@data-testid='apply-btn']`, ) + applyRefreshButton = By.xpath(`//*[@data-testid='key-auto-refresh-rate-input']//*[@data-testid="apply-btn"]`) applyEditButton = By.xpath(`//*[@data-testid='apply-edit-btn']`) searchInput = By.xpath(`//*[@data-testid='search']`) clearSearchInput = By.xpath(`//*[@data-testid='decline-search-button']`) @@ -215,4 +221,22 @@ export class KeyDetailsView extends WebView { formatter, ) } + + /** + * Set auto-refresh + * @param rate The rate for refresh + */ + async setAutoRefresh(rate: number = 5): Promise { + await ButtonActions.clickElement(this.refreshKeyArrow) + await ButtonActions.clickElement(this.autoRefreshInput) + // clear the input + for (let i = 0; i < 3; i++) { + await InputActions.pressKey(this.autoRefreshInput, Key.BACK_SPACE) + } + await InputActions.typeText(this.autoRefreshInput, rate.toString()) + await ButtonActions.clickElement(this.autoRefreshInput) + await ButtonActions.clickElement(this.applyRefreshButton) + await ButtonActions.clickElement(this.autoRefreshCheckBox) + await ButtonActions.clickElement(this.refreshKeyButton) + } } diff --git a/tests/e2e/src/page-objects/components/tree-view/TreeView.ts b/tests/e2e/src/page-objects/components/tree-view/TreeView.ts index fc222e34..b0153956 100644 --- a/tests/e2e/src/page-objects/components/tree-view/TreeView.ts +++ b/tests/e2e/src/page-objects/components/tree-view/TreeView.ts @@ -103,10 +103,14 @@ export class TreeView extends WebView { By.xpath( `.//div[starts-with(@data-testid, 'database-')][.//*[text()='${name}']]/..//vscode-button[@data-testid='edit-database']`, ) - getRefreshDatabaseBtnByName = (name: string): Locator => + getRefreshIndexedDatabaseBtnByName = (name: string): Locator => By.xpath( `.//div[starts-with(@data-testid, 'database-')][.//*[text()='${name}']]/../..//button[@data-testid = 'refresh-keys-refresh-btn']`, ) + getRefreshDatabaseBtnByName = (name: string): Locator => + By.xpath( + `//div[starts-with(@data-testid, 'database-')][.//*[text()='${name}']]/..//vscode-button[@data-testid = 'refresh-databases']`, + ) getCLIDatabaseBtnByName = (name: string): Locator => By.xpath( `.//div[starts-with(@data-testid, 'database-')][.//*[text()='${name}']]/../..//vscode-button[@data-testid = 'terminal-button']`, @@ -121,7 +125,10 @@ export class TreeView extends WebView { By.xpath( `(//div[@role='treeitem']//div[starts-with(@data-testid, 'key-')])[position() <= ${number}]`, ) - + getIndexedDataBaseSummary = (number: number): Locator => + By.xpath( + `//div[contains(@data-testid, 'logical-database') and contains(@data-testid, '-${number}')]//div[@data-testid = 'keys-summary']`, + ) /** * Open key details of the key by name * @param keyName The name of the key @@ -228,11 +235,33 @@ export class TreeView extends WebView { * @param databaseName The name of the database */ async refreshDatabaseByName(databaseName: string): Promise { + await ButtonActions.clickElement( + this.getRefreshIndexedDatabaseBtnByName(databaseName), + ) + await this.waitForElementVisibility(this.loadingIndicator, 1000, true) + await this.waitForElementVisibility(this.loadingIndicator, 1000, false) + } + + /** + * Click on indexed database in list by its name + * @param index The index of the database + */ + async clickOnIndexedDb(index: number): Promise { + await ButtonActions.clickElement( + this.getIndexedDataBaseSummary(index), + ) + await this.waitForElementVisibility(this.loadingIndicator, 1000, true) + await this.waitForElementVisibility(this.loadingIndicator, 1000, false) + } + + /** + * Click on refresh database in list by its name + * @param databaseName The name of the database + */ + async refreshNotIndexedDatabaseByName(databaseName: string): Promise { await ButtonActions.clickElement( this.getRefreshDatabaseBtnByName(databaseName), ) - // Hover to CLI btn to not display refresh popover - await ButtonActions.hoverElement(this.getCLIDatabaseBtnByName(databaseName)) await this.waitForElementVisibility(this.loadingIndicator, 1000, true) await this.waitForElementVisibility(this.loadingIndicator, 1000, false) } diff --git a/tests/e2e/src/tests/browser/formatters.e2e.ts b/tests/e2e/src/tests/browser/formatters.e2e.ts index c97186c1..686e1336 100644 --- a/tests/e2e/src/tests/browser/formatters.e2e.ts +++ b/tests/e2e/src/tests/browser/formatters.e2e.ts @@ -18,7 +18,7 @@ import { TreeView, KeyDetailsView, HashKeyDetailsView, - StringKeyDetailsView, + StringKeyDetailsView, CliViewPanel, } from '@e2eSrc/page-objects/components' import { ButtonActions, @@ -73,6 +73,7 @@ describe('Formatters', () => { let hashKeyDetailsView: HashKeyDetailsView let stringKeyDetailsView: StringKeyDetailsView let doubleColumnKeyDetailsView: DoubleColumnKeyDetailsView + let cliViewPanel: CliViewPanel let keysData = keyTypesShort .map((object: any) => ({ ...object })) @@ -98,6 +99,7 @@ describe('Formatters', () => { hashKeyDetailsView = new HashKeyDetailsView() stringKeyDetailsView = new StringKeyDetailsView() doubleColumnKeyDetailsView = new DoubleColumnKeyDetailsView() + cliViewPanel = new CliViewPanel() await DatabasesActions.acceptLicenseTermsAndAddDatabaseApi( Config.ossStandaloneConfig, @@ -576,4 +578,73 @@ describe('Formatters', () => { } }) }) + it('Verify that Datatime is parse for Java', async function () { + const DataTimeValue1 = "ACED00057372000E6A6176612E7574696C2E44617465686A81014B5974190300007870770800000075371FBB0078" + const DataTimeValue2 = "ACED00057372000E6A6176612E7574696C2E44617465686A81014B59741903000078707708FFFFFF98C729B30078" + const expectedDate1 = '"1985-12-14T19:20:00.000Z"' + const expectedDate2 = '"1955-12-14T19:20:00.000Z"' + + let keyName = Common.generateWord(10) + + await KeyAPIRequests.addKeyApi( + { keyName: keyName, keyType: KeyTypesShort.Hash }, + Config.ossStandaloneConfig.databaseName, + ) + // Refresh database + await treeView.refreshDatabaseByName( + Config.ossStandaloneConfig.databaseName, + ) + + // Open Hash key details + await KeyDetailsActions.openKeyDetailsByKeyNameInIframe(keyName) + await keyDetailsView.selectFormatter(Formatters.HEX) + + await hashKeyDetailsView.editHashKeyValue(DataTimeValue1, 'test_field') + await keyDetailsView.selectFormatter(Formatters.Java) + + expect( + await hashKeyDetailsView.getElementText( + hashKeyDetailsView.hashValuesList,),).contains( + expectedDate1,'the value is not parsed') + + await keyDetailsView.selectFormatter(Formatters.HEX) + + await hashKeyDetailsView.editHashKeyValue(DataTimeValue2, 'test_field') + await keyDetailsView.selectFormatter(Formatters.Java) + + expect( + await hashKeyDetailsView.getElementText( + hashKeyDetailsView.hashValuesList,),).contains( + expectedDate2,'the value is not parsed') + }) + + it('Verify that UTF8 in PHP serialized', async function () { + const phpValueChinese = '测试' + const phpValueCRussian = 'Привет мир!' + let keyName = Common.generateWord(10) + const setValue =`SET ${keyName} "a:3:{s:4:\\"name\\";s:6:\\"${phpValueChinese}\\";s:3:\\"age\\";i:30;s:7:\\"message\\";s:20:\\"${phpValueCRussian}\\";}"` + + await treeView.switchBack() + await treeView.switchToInnerViewFrame(InnerViews.TreeInnerView) + await treeView.openCliByDatabaseName( + Config.ossStandaloneConfig.databaseName + ) + await treeView.switchBack() + await CommonDriverExtension.driverSleep(1000) + await cliViewPanel.switchToInnerViewFrame(InnerViews.CliInnerView) + await cliViewPanel.executeCommand(setValue) + await cliViewPanel.switchBack() + await treeView.switchToInnerViewFrame(InnerViews.TreeInnerView) + await treeView.refreshDatabaseByName(Config.ossStandaloneConfig.databaseName) + await KeyDetailsActions.openKeyDetailsByKeyNameInIframe(keyName) + await keyDetailsView.selectFormatter(Formatters.PHP) + + expect( + await stringKeyDetailsView.getStringKeyValue(),).contains( + phpValueChinese,'Chinese value is not parsed') + + expect( + await stringKeyDetailsView.getStringKeyValue(),).contains( + phpValueCRussian,'russian value is not parsed') + }) }) diff --git a/tests/e2e/src/tests/browser/hash-key.e2e.ts b/tests/e2e/src/tests/browser/hash-key.e2e.ts index eccf83b4..33403575 100644 --- a/tests/e2e/src/tests/browser/hash-key.e2e.ts +++ b/tests/e2e/src/tests/browser/hash-key.e2e.ts @@ -202,4 +202,41 @@ describe('Hash Key fields verification', () => { // Verify that details panel is closed for hash key after deletion await KeyDetailsActions.verifyDetailsPanelClosed() }) + + it('Verify that auto-refresh can be set', async function () { + keyName = Common.generateWord(10) + + const hashKeyParameters: HashKeyParameters = { + keyName: keyName, + fields: [ + { + field: 'field', + value: 'value', + }, + ], + } + await KeyAPIRequests.addHashKeyApi( + hashKeyParameters, + Config.ossStandaloneConfig.databaseName, + ) + // Refresh database + await treeView.refreshDatabaseByName( + Config.ossStandaloneConfig.databaseName, + ) + + // Open key details iframe + await KeyDetailsActions.openKeyDetailsByKeyNameInIframe(keyName) + await keyDetailsView.setAutoRefresh(1) + let elements = await keyDetailsView.getElements(keyDetailsView.refreshKeyMessage) + let text = await elements[0].getText() + expect(text).eql('1 s', 'value is not set') + + await ButtonActions.clickElement(keyDetailsView.refreshKeyArrow) + await ButtonActions.clickElement(keyDetailsView.autoRefreshCheckBox) + await ButtonActions.clickElement(keyDetailsView.refreshKeyButton) + + elements = await keyDetailsView.getElements(keyDetailsView.refreshKeyMessage) + text = await elements[0].getText() + expect(text).eql('now', 'value is still set') + }) }) diff --git a/tests/e2e/src/tests/browser/json-key.e2e.ts b/tests/e2e/src/tests/browser/json-key.e2e.ts index ac60806b..7dfc5d63 100644 --- a/tests/e2e/src/tests/browser/json-key.e2e.ts +++ b/tests/e2e/src/tests/browser/json-key.e2e.ts @@ -294,4 +294,20 @@ describe('Add JSON Key verification', () => { // Check the notification message that key added await NotificationActions.checkNotificationMessage(`Key has been added`) }) + it('Verify that user can add big int', async function () { + keyName = Common.generateWord(10) + const bigInt = '12345678998768' + const jsonStructure = `{"bigInt": ${bigInt}, "string":"${bigInt}"}` + const jsonKeyParameters: JsonKeyParameters = { + keyName: keyName, + data: jsonStructure, + } + await addJsonKeyView.addKey(jsonKeyParameters, KeyTypesShort.ReJSON) + await addJsonKeyView.switchBack() + await treeView.switchToInnerViewFrame(InnerViews.KeyDetailsInnerView) + await addJsonKeyView.waitForElementVisibility(keyDetailsView.jsonKeyValue) + const jsonValue = await keyDetailsView.getElementText(keyDetailsView.jsonKeyValue) + expect(jsonValue).contains(bigInt, 'the big int value is truncated') + expect(jsonValue).contains(`"${bigInt}"`, 'the big int value is not string') + }) }) diff --git a/tests/e2e/src/tests/database/edit-db.e2e.ts b/tests/e2e/src/tests/database/edit-db.e2e.ts index 5c6b54d1..43fe27f7 100644 --- a/tests/e2e/src/tests/database/edit-db.e2e.ts +++ b/tests/e2e/src/tests/database/edit-db.e2e.ts @@ -69,11 +69,11 @@ describe('Edit Databases', () => { ) expect(caCertFieldValue).not.contains( - 'NO_CA_CERT', + 'No CA Certificate', 'CA certificate is incorrect', ) expect(clientCertFieldValue).not.contains( - 'ADD_NEW', + 'Add new certificate', 'Client certificate is incorrect', ) @@ -85,4 +85,31 @@ describe('Edit Databases', () => { await editDatabaseView.switchBack() await DatabasesActions.verifyDatabaseEdited() }) + + it('Verify that user can remove certificates', async function () { + await ButtonActions.clickElement(editDatabaseView.caCertField) + await ButtonActions.clickElement(editDatabaseView.removeCertificateButton) + await ButtonActions.clickElement(editDatabaseView.confirmRemoveCertificateButton) + + await ButtonActions.clickElement(editDatabaseView.clientCertField) + await ButtonActions.clickElement(editDatabaseView.removeCertificateButton) + await ButtonActions.clickElement(editDatabaseView.confirmRemoveCertificateButton) + + const caCertFieldValue = await editDatabaseView.getElementText( + editDatabaseView.caCertField, + ) + const clientCertFieldValue = await editDatabaseView.getElementText( + editDatabaseView.clientCertField, + ) + + expect(caCertFieldValue).contains( + 'No CA Certificate', + 'CA certificate is not removed', + ) + expect(clientCertFieldValue).contains( + 'Add new certificate', + 'Client certificate is incorrect', + ) + await editDatabaseView.switchBack() + }) }) diff --git a/tests/e2e/src/tests/database/logical-database.e2e.ts b/tests/e2e/src/tests/database/logical-database.e2e.ts new file mode 100644 index 00000000..98f0a523 --- /dev/null +++ b/tests/e2e/src/tests/database/logical-database.e2e.ts @@ -0,0 +1,108 @@ +import { expect } from 'chai' +import { describe, it } from 'mocha' +import { beforeEach, after, afterEach } from 'vscode-extension-tester' +import { InnerViews } from '@e2eSrc/page-objects/components/WebView' +import { TreeView, CliViewPanel, ListKeyDetailsView } from '@e2eSrc/page-objects/components' +import { + ButtonActions, + DatabasesActions, +} from '@e2eSrc/helpers/common-actions' +import { Common, CommonDriverExtension, Config } from '@e2eSrc/helpers' +import { DatabaseAPIRequests, KeyAPIRequests } from '@e2eSrc/helpers/api'; + +describe('Logical Databases', () => { + let treeView: TreeView + let cliViewPanel: CliViewPanel + let listKeyDetailsView: ListKeyDetailsView + + const keyName1 = Common.generateString(10) + const keyName2 = Common.generateString(10) + + beforeEach(async () => { + cliViewPanel = new CliViewPanel() + treeView = new TreeView() + listKeyDetailsView = new ListKeyDetailsView() + + await DatabasesActions.acceptLicenseTermsAndAddDatabaseApi( + Config.ossStandaloneConfig, + ) + + await treeView.switchBack() + await treeView.switchToInnerViewFrame(InnerViews.TreeInnerView) + await treeView.openCliByDatabaseName( + Config.ossStandaloneConfig.databaseName, + ) + await treeView.switchBack() + await CommonDriverExtension.driverSleep(1000) + await cliViewPanel.switchToInnerViewFrame(InnerViews.CliInnerView) + await cliViewPanel.executeCommand('clear') + + }) + afterEach(async () => { + await treeView.switchBack() + await cliViewPanel.switchToInnerViewFrame(InnerViews.CliInnerView) + await cliViewPanel.executeCommand('flushdb') + await treeView.switchBack() + await DatabaseAPIRequests.deleteAllDatabasesApi() + }) + + it('Verify that user see logical db', async function () { + await treeView.switchBack() + await treeView.switchToInnerViewFrame(InnerViews.TreeInnerView) + + expect( + await treeView.isElementDisplayed( + treeView.getIndexedDataBaseSummary(0), + ), + ).eql(true, 'Indexed base is not displayed') + + await treeView.switchBack() + await cliViewPanel.switchToInnerViewFrame(InnerViews.CliInnerView) + await cliViewPanel.executeCommand(`SET ${keyName1} test1`) + await cliViewPanel.executeCommand('SELECT 2') + await cliViewPanel.executeCommand(`SET ${keyName2} test2`) + await cliViewPanel.switchBack() + + await treeView.switchToInnerViewFrame(InnerViews.TreeInnerView) + await treeView.refreshNotIndexedDatabaseByName(Config.ossStandaloneConfig.databaseName) + expect( + await treeView.isElementDisplayed( + treeView.getIndexedDataBaseSummary(2), + ), + ).eql(true, 'Indexed base is not displayed') + + await treeView.clickOnIndexedDb(2) + + expect(await treeView.isKeyIsDisplayedInTheList(keyName1)).eql( + false, + 'The key was found', + ) + await CommonDriverExtension.driverSleep(2000) + + expect(await treeView.isKeyIsDisplayedInTheList(keyName2)).eql( + true, + 'The key was not found', + ) + + await ButtonActions.clickElement(treeView.getIndexedDataBaseSummary(2)) + await treeView.clickOnIndexedDb(0) + + expect(await treeView.isKeyIsDisplayedInTheList(keyName1)).eql( + true, + 'The key was not found', + ) + expect(await treeView.isKeyIsDisplayedInTheList(keyName2)).eql( + false, + 'The key was not found', + ) + + await treeView.deleteFirstKeyFromList() + await treeView.refreshNotIndexedDatabaseByName(Config.ossStandaloneConfig.databaseName) + + expect( + await treeView.isElementDisplayed( + treeView.getIndexedDataBaseSummary(0), + ), + ).eql(false, 'Indexed base is displayed after removing the keys') + }) +})