Skip to content
34 changes: 32 additions & 2 deletions tests/e2e/pageObjects/browser-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ export class BrowserPage {
//*The following categories are ordered alphabetically (Alerts, Buttons, Checkboxes, etc.).
//-------------------------------------------------------------------------------------------
//BUTTONS
hashDeleteButton = Selector('[data-testid=hash-delete-btn]');
setDeleteButton = Selector('[data-testid=set-delete-btn]');
streamDeleteButton = Selector('[data-testid=stream-delete-btn]');
myRedisDbIcon = Selector('[data-testid=my-redis-db-icon]');
deleteKeyButton = Selector('[data-testid=delete-key-btn]');
confirmDeleteKeyButton = Selector('[data-testid=delete-key-confirm-btn]');
Expand Down Expand Up @@ -987,7 +990,7 @@ export class BrowserPage {

/**
* Verify that keys can be scanned more and results increased
*/
*/
async verifyScannningMore(): Promise<void> {
for (let i = 10; i < 100; i += 10) {
// Remember results value
Expand All @@ -1006,13 +1009,40 @@ export class BrowserPage {
/**
* Open Select Index droprown and select option
* @param index The name of format
*/
*/
async selectIndexByName(index: string): Promise<void> {
const option = Selector(`[data-test-subj="mode-option-type-${index}"]`);
await t
.click(this.selectIndexDdn)
.click(option);
}

/**
* Get text from first tree element
*/
async getTextFromNthTreeElement(number: number): Promise<string> {
return (await Selector(`[role="treeitem"]`).nth(number).find(`div`).textContent).replace(/\s/g, '');
}

/**
* Open tree folder with multiple level
* @param names folder names with sequence of subfolder
*/
async openTreeFolders(names: string[]): Promise<void> {
let base = `node-item_${names[0]}:`
await t.click(Selector(`[data-testid="${base}"]`));
if (names.length > 1) {
for (let i = 1; i < names.length; i++) {
base = base + `${names[i]}:`;
await t.click(Selector(`[data-testid="${base}"]`));
}
}
await t.click(Selector(`[data-testid="${base}keys:keys:"]`));

await t.expect(
Selector(`[data-testid="${base}keys:keys:"]`).visible)
.ok("Folder is not selected");
}
}

/**
Expand Down
14 changes: 14 additions & 0 deletions tests/e2e/pageObjects/cli-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,18 @@ export class CliPage {
await t.click(this.readMoreButton);
await t.expect(getPageUrl()).eql(url, 'The opened page not correct');
}

/**
* Create random index name with CLI and return
*/

async createIndexwithCLI(prefix: string): Promise<string> {
const word = common.generateWord(10);
const index = `idx:${word}`;
const commands = [
`FT.CREATE ${index} ON HASH PREFIX 1 ${prefix} SCHEMA "name" TEXT`,
];
await this.sendCommandsInCli(commands);
return index;
}
}
183 changes: 183 additions & 0 deletions tests/e2e/tests/critical-path/tree-view/tree-view-improvements.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
import { Selector, t } from 'testcafe';
import { acceptLicenseTermsAndAddDatabaseApi } from '../../../helpers/database';
import {
BrowserPage, CliPage
} from '../../../pageObjects';
import {
commonUrl,
ossStandaloneBigConfig,
ossStandaloneConfig
} from '../../../helpers/conf';
import { KeyTypesTexts, rte } from '../../../helpers/constants';
import { deleteStandaloneDatabaseApi } from '../../../helpers/api/api-database';
import { Common } from '../../../helpers/common';
import { verifyKeysDisplayedInTheList, verifyKeysNotDisplayedInTheList } from '../../../helpers/keys';

const browserPage = new BrowserPage();
const common = new Common();
const cliPage = new CliPage();
let keyNames: string[];
let keyName1: string;
let keyName2: string;
let keynameSingle: string;
let index: string;

fixture`Tree view navigations improvement tests`
.meta({ type: 'critical_path', rte: rte.standalone })
.page(commonUrl);
test
.before(async () => {
await acceptLicenseTermsAndAddDatabaseApi(ossStandaloneConfig, ossStandaloneConfig.databaseName);
})
.after(async () => {
await t.click(browserPage.patternModeBtn);
await browserPage.deleteKeysByNames(keyNames);
await deleteStandaloneDatabaseApi(ossStandaloneConfig);
})('Tree view preselected folder', async t => {
keyName1 = common.generateWord(10); // used to create index name
keyName2 = common.generateWord(10); // used to create index name
keynameSingle = common.generateWord(10);
keyNames = [`${keyName1}:1`, `${keyName1}:2`, `${keyName2}:1`, `${keyName2}:2`, keynameSingle];

const commands = [
`HSET ${keyNames[0]} field value`,
`HSET ${keyNames[1]} field value`,
`HSET ${keyNames[2]} field value`,
`HSET ${keyNames[3]} field value`,
`SADD ${keyNames[4]} value`
];

// Create 5 keys
await cliPage.sendCommandsInCli(commands);
await t.click(browserPage.treeViewButton);
// The folder without any patterns selected and the list of keys is displayed when there is a folder without any patterns
await verifyKeysDisplayedInTheList([keynameSingle]);

await browserPage.openTreeFolders([await browserPage.getTextFromNthTreeElement(1)]);
await browserPage.selectFilterGroupType(KeyTypesTexts.Set);
// The folder without any namespaces is selected (if exists) when folder does not exist after search/filter
await verifyKeysDisplayedInTheList([keynameSingle]);

await t.click(browserPage.setDeleteButton);
// The folder without any patterns selected and the list of keys is displayed when there is a folder without any patterns
await verifyKeysDisplayedInTheList([keynameSingle]);
await verifyKeysNotDisplayedInTheList([`${keyNames[0]}:1`, `${keyNames[2]}:2`]);

// switch between browser view and tree view
await t.click(browserPage.browserViewButton)
.click(browserPage.treeViewButton);
await browserPage.deleteKeyByName(keyNames[4]);
await t.click(browserPage.clearFilterButton);
// get first folder name
const firstTreeItemText = await browserPage.getTextFromNthTreeElement(0);
const firstTreeItemKeys = Selector(`[data-testid="node-item_${firstTreeItemText}:keys:keys:"]`); // keys after node item opened
// The first folder with namespaces is expanded and selected when there is no folder without any patterns
await t.expect(firstTreeItemKeys.visible)
.ok('First folder is not expanded');
await verifyKeysDisplayedInTheList([`${firstTreeItemText}:1`, `${firstTreeItemText}:2`]);

const commands1 = [
`HSET ${keyNames[4]} field value`
];

await cliPage.sendCommandsInCli(commands1);
await t.click(browserPage.refreshKeysButton);
// Refreshed Tree view preselected folder
await t.expect(firstTreeItemKeys.visible)
.ok('Folder is not selected');
await verifyKeysDisplayedInTheList([`${firstTreeItemText}:1`, `${firstTreeItemText}:2`]);

await browserPage.selectFilterGroupType(KeyTypesTexts.Hash);
await t.expect(firstTreeItemKeys.visible).ok('Folder is not selected after searching with HASH');
// Filterred Tree view preselected folder
await verifyKeysDisplayedInTheList([`${firstTreeItemText}:1`, `${firstTreeItemText}:2`]);

await browserPage.searchByKeyName('*');
// Search capability Filterred Tree view preselected folder
await t.expect(firstTreeItemKeys.visible).ok('Folder is not selected');
await verifyKeysDisplayedInTheList([`${firstTreeItemText}:1`, `${firstTreeItemText}:2`]);

await t.click(browserPage.clearFilterButton);
// Filterred Tree view preselected folder
await t.expect(firstTreeItemKeys.visible).ok('Folder is not selected');
await verifyKeysDisplayedInTheList([`${firstTreeItemText}:1`, `${firstTreeItemText}:2`]);

await browserPage.selectFilterGroupType(KeyTypesTexts.Stream);
// Filterred Tree view preselected folder
await t.expect(browserPage.keyListTable.textContent).contains('No results found.', 'Key is not found message not displayed');

await t.click(browserPage.streamDeleteButton); // clear stream from filter
// Filterred Tree view preselected folder
await t.expect(browserPage.keyListTable.textContent).notContains('No results found.', 'Key is not found message still displayed');
await t.expect(
firstTreeItemKeys.visible)
.notOk('First folder is expanded');
});

test
.before(async () => {
await acceptLicenseTermsAndAddDatabaseApi(ossStandaloneBigConfig, ossStandaloneBigConfig.databaseName);
})
.after(async () => {
await cliPage.sendCommandInCli(`FT.DROPINDEX ${index}`);
await deleteStandaloneDatabaseApi(ossStandaloneBigConfig);
})('Verify tree view navigation for index based search', async t => {
// generate index based on keyName
const folders = ['mobile', '2014'];
index = await cliPage.createIndexwithCLI(folders.join(':'));
await t.click(browserPage.redisearchModeBtn); // click redisearch button
await browserPage.selectIndexByName(index);
await t.click(browserPage.treeViewButton);
await t.click(Selector(`[data-testid="${`node-item_${folders[0]}:`}"]`)); // close folder
await browserPage.openTreeFolders(folders);
await t.click(browserPage.refreshKeysButton);
// Refreshed Tree view preselected folder for index based search
await t.expect(
Selector(`[data-testid="node-item_${folders[0]}:${folders[1]}:keys:keys:"]`).visible)
.ok('Folder is not selected');
});

test
.before(async () => {
await acceptLicenseTermsAndAddDatabaseApi(ossStandaloneConfig, ossStandaloneConfig.databaseName);
})
.after(async () => {
await t.click(browserPage.patternModeBtn);
await browserPage.deleteKeysByNames(keyNames.slice(1));
await deleteStandaloneDatabaseApi(ossStandaloneConfig);
})('Search capability Refreshed Tree view preselected folder', async t => {
keyName1 = common.generateWord(10); // used to create index name
keyName2 = common.generateWord(10); // used to create index name
keynameSingle = common.generateWord(10);
keyNames = [`${keyName1}:1`, `${keyName1}:2`, `${keyName2}:1`, `${keyName2}:2`, keynameSingle];
const commands = [
`HSET ${keyNames[0]} field value`,
`HSET ${keyNames[1]} field value`,
`RPUSH ${keyNames[2]} field`,
`RPUSH ${keyNames[3]} field`,
`SADD ${keyNames[4]} value`
];
await cliPage.sendCommandsInCli(commands);
await t.click(browserPage.treeViewButton);
// The folder without any patterns selected and the list of keys is displayed when there is a folder without any patterns
await verifyKeysDisplayedInTheList([keynameSingle]);

await browserPage.openTreeFolders([keyName1]); // Type: hash
await browserPage.openTreeFolders([keyName2]); // Type: list
await browserPage.selectFilterGroupType(KeyTypesTexts.Hash);
// The first folder with namespaces is expanded and selected when folder and folder without any namespaces does not exist after search/filter
await verifyKeysDisplayedInTheList([keyNames[0], keyNames[1]]);

await t.click(browserPage.hashDeleteButton);
await cliPage.sendCommandsInCli([`DEL ${keyNames[0]}`]);
await t.click(browserPage.refreshKeysButton); // refresh keys
// The previously selected folder is preselected when key does not exist after keys refresh
await verifyKeysDisplayedInTheList([keyNames[1]]);
await verifyKeysNotDisplayedInTheList([keyNames[0], keyNames[2], keyNames[3], keyNames[4]]);

await browserPage.searchByKeyName('*');
await t.click(browserPage.refreshKeysButton);
// Search capability Refreshed Tree view preselected folder
await verifyKeysDisplayedInTheList([keyNames[1]]);
await verifyKeysNotDisplayedInTheList([keyNames[0], keyNames[2], keyNames[3], keyNames[4]]);
});