- {`${fullName}*`}
-
+
+ {`${fullName + delimiterView}*`}
+ {delimiters.length > 1 && (
+
+ {delimiters.map((delimiter) => (
+ {delimiter}
+ ))}
+
+ )}
+
{`${keyCount} key(s) (${Math.round(keyApproximate * 100) / 100}%)`}
>
)
diff --git a/redisinsight/ui/src/pages/browser/components/virtual-tree/components/Node/styles.module.scss b/redisinsight/ui/src/pages/browser/components/virtual-tree/components/Node/styles.module.scss
index dd3be8344d..f9093b0fa6 100644
--- a/redisinsight/ui/src/pages/browser/components/virtual-tree/components/Node/styles.module.scss
+++ b/redisinsight/ui/src/pages/browser/components/virtual-tree/components/Node/styles.module.scss
@@ -140,3 +140,29 @@
.deletePopover {
max-width: 400px !important;
}
+
+.folderTooltipHeader {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ word-break: break-all;
+}
+
+.delimiters {
+ display: inline-flex;
+ flex-wrap: wrap;
+}
+
+.folderPattern {
+ font-weight: bold;
+ margin-right: 4px;
+ white-space: normal;
+}
+
+.delimiter {
+ margin-bottom: 2px;
+ padding: 2px 5px;
+ margin-right: 4px;
+ border-radius: 2px;
+ background-color: var(--euiColorLightestShade);
+}
diff --git a/redisinsight/ui/src/pages/browser/components/virtual-tree/interfaces.ts b/redisinsight/ui/src/pages/browser/components/virtual-tree/interfaces.ts
index 119c843d29..0f54655e27 100644
--- a/redisinsight/ui/src/pages/browser/components/virtual-tree/interfaces.ts
+++ b/redisinsight/ui/src/pages/browser/components/virtual-tree/interfaces.ts
@@ -50,6 +50,7 @@ export interface TreeData extends FixedSizeNodeData {
nestingLevel: number
deleting: boolean
isSelected: boolean
+ delimiters: string[]
children?: TreeData[]
updateStatusOpen: (fullName: string, value: boolean) => void
updateStatusSelected: (key: RedisString) => void
diff --git a/redisinsight/ui/src/services/index.ts b/redisinsight/ui/src/services/index.ts
index a35cf5a229..432c379246 100644
--- a/redisinsight/ui/src/services/index.ts
+++ b/redisinsight/ui/src/services/index.ts
@@ -1,5 +1,6 @@
/* eslint-disable import/first */
export * from './storage'
+export * from './migrateStorageData'
import apiService from './apiService'
import resourcesService from './resourcesService'
diff --git a/redisinsight/ui/src/services/migrateStorageData.ts b/redisinsight/ui/src/services/migrateStorageData.ts
new file mode 100644
index 0000000000..9a950e4e69
--- /dev/null
+++ b/redisinsight/ui/src/services/migrateStorageData.ts
@@ -0,0 +1,26 @@
+import { isString } from 'lodash'
+import { BrowserStorageItem } from 'uiSrc/constants'
+import { getDBConfigStorageField, localStorageService, setDBConfigStorageField } from './storage'
+
+export const migrateLocalStorageData = () => {
+ migrateDelimiterTreeView()
+}
+
+const migrateDelimiterTreeView = () => {
+ const prefix = 'dbConfig_'
+ const storage = localStorageService.getAll()
+
+ // Iterate over all keys and filter for the dbConfig_ prefix
+ Object.keys(storage).forEach((key) => {
+ if (key.startsWith(prefix)) {
+ const instanceId = key.replace(prefix, '')
+
+ const treeViewDelimiter = getDBConfigStorageField(instanceId, BrowserStorageItem.treeViewDelimiter)
+
+ // Check if treeViewDelimiter is a string and needs transform to array
+ if (isString(treeViewDelimiter)) {
+ setDBConfigStorageField(instanceId, BrowserStorageItem.treeViewDelimiter, [{ label: treeViewDelimiter }])
+ }
+ }
+ })
+}
diff --git a/redisinsight/ui/src/slices/app/context.ts b/redisinsight/ui/src/slices/app/context.ts
index 4421886dff..842a5e4fb5 100644
--- a/redisinsight/ui/src/slices/app/context.ts
+++ b/redisinsight/ui/src/slices/app/context.ts
@@ -1,4 +1,5 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
+import { EuiComboBoxOptionOption } from '@elastic/eui'
import { RelativeWidthSizes } from 'uiSrc/components/virtual-table/interfaces'
import { CapabilityStorageItem, ConfigDBStorageItem } from 'uiSrc/constants/storage'
import { Maybe, Nullable } from 'uiSrc/utils'
@@ -37,7 +38,7 @@ export const initialState: StateAppContext = {
contextRdiInstanceId: '',
lastPage: '',
dbConfig: {
- treeViewDelimiter: DEFAULT_DELIMITER,
+ treeViewDelimiter: [DEFAULT_DELIMITER],
treeViewSort: DEFAULT_TREE_SORTING,
slowLogDurationUnit: DEFAULT_SLOWLOG_DURATION_UNIT,
showHiddenRecommendations: DEFAULT_SHOW_HIDDEN_RECOMMENDATIONS,
@@ -56,7 +57,6 @@ export const initialState: StateAppContext = {
},
panelSizes: {},
tree: {
- delimiter: DEFAULT_DELIMITER,
openNodes: {},
selectedLeaf: null,
},
@@ -127,7 +127,7 @@ const appContextSlice = createSlice({
state.workspace = payload || AppWorkspace.Databases
},
setDbConfig: (state, { payload }) => {
- state.dbConfig.treeViewDelimiter = payload?.treeViewDelimiter ?? DEFAULT_DELIMITER
+ state.dbConfig.treeViewDelimiter = payload?.treeViewDelimiter ?? [DEFAULT_DELIMITER]
state.dbConfig.treeViewSort = payload?.treeViewSort ?? DEFAULT_TREE_SORTING
state.dbConfig.slowLogDurationUnit = payload?.slowLogDurationUnit ?? DEFAULT_SLOWLOG_DURATION_UNIT
state.dbConfig.showHiddenRecommendations = payload?.showHiddenRecommendations
@@ -136,8 +136,8 @@ const appContextSlice = createSlice({
state.dbConfig.slowLogDurationUnit = payload
setDBConfigStorageField(state.contextInstanceId, ConfigDBStorageItem.slowLogDurationUnit, payload)
},
- setBrowserTreeDelimiter: (state, { payload }: { payload: string }) => {
- state.dbConfig.treeViewDelimiter = payload
+ setBrowserTreeDelimiter: (state, { payload }: { payload: EuiComboBoxOptionOption[] }) => {
+ state.dbConfig.treeViewDelimiter = payload as any
setDBConfigStorageField(state.contextInstanceId, BrowserStorageItem.treeViewDelimiter, payload)
},
setBrowserTreeSort: (state, { payload }: PayloadAction) => {
diff --git a/redisinsight/ui/src/slices/interfaces/app.ts b/redisinsight/ui/src/slices/interfaces/app.ts
index 994b3c41e2..f1ca5bec56 100644
--- a/redisinsight/ui/src/slices/interfaces/app.ts
+++ b/redisinsight/ui/src/slices/interfaces/app.ts
@@ -1,4 +1,5 @@
import { AxiosError } from 'axios'
+import { EuiComboBoxOptionOption } from '@elastic/eui'
import { RelativeWidthSizes } from 'uiSrc/components/virtual-table/interfaces'
import { Nullable } from 'uiSrc/utils'
import { DurationUnits, FeatureFlags, ICommands, SortOrder } from 'uiSrc/constants'
@@ -64,7 +65,7 @@ export interface StateAppContext {
contextRdiInstanceId: string
lastPage: string
dbConfig: {
- treeViewDelimiter: string
+ treeViewDelimiter: EuiComboBoxOptionOption[]
treeViewSort: SortOrder
slowLogDurationUnit: DurationUnits
showHiddenRecommendations: boolean
@@ -85,7 +86,6 @@ export interface StateAppContext {
[key: string]: number
}
tree: {
- delimiter: string
openNodes: {
[key: string]: boolean
}
diff --git a/redisinsight/ui/src/styles/base/_inputs.scss b/redisinsight/ui/src/styles/base/_inputs.scss
index ab4bd8d69b..df1938840e 100644
--- a/redisinsight/ui/src/styles/base/_inputs.scss
+++ b/redisinsight/ui/src/styles/base/_inputs.scss
@@ -51,3 +51,42 @@ input[name='sshPassphrase'] ~ .euiFormControlLayoutIcons {
width: 34px !important;
height: 29px !important;
}
+
+.euiComboBox.euiComboBox-isOpen .euiComboBox__inputWrap {
+ background-image: none !important;
+ border-bottom: solid 2px var(--euiColorPrimary) !important;
+}
+.euiComboBox .euiComboBox__inputWrap {
+ .euiComboBoxPill {
+ background-color: var(--buttonDarkenBgColor) !important;
+ }
+ .euiBadge__iconButton {
+ margin-top: 1px;
+ margin-left: 8px;
+ margin-right: 3px;
+ border-radius: 50%;
+ background-color: var(--euiColorPrimary);
+ color: var(--rdiSecondaryBgColor);
+ width: 13px;
+ height: 13px;
+
+ &:hover {
+ transform: translateY(-1px);
+ }
+ &:active {
+ transform: translateY(1px);
+ }
+
+ svg {
+ width: 10px;
+ height: 10px;
+
+ &:focus {
+ background: inherit;
+ }
+ }
+ }
+ .euiComboBox__input > input {
+ color: var(--inputTextColor) !important;
+ }
+}
diff --git a/redisinsight/ui/src/utils/tests/transformers/browser.spec.ts b/redisinsight/ui/src/utils/tests/transformers/browser.spec.ts
new file mode 100644
index 0000000000..ebe90f832a
--- /dev/null
+++ b/redisinsight/ui/src/utils/tests/transformers/browser.spec.ts
@@ -0,0 +1,16 @@
+import { comboBoxToArray } from 'uiSrc/utils'
+
+const getOutputForFormatToTextTests: any[] = [
+ [[], []],
+ [[{ label: '123' }, { label: 'test' }], ['123', 'test']],
+ [[{ label1: '123' }], []],
+ [[{ label: '123' }, { label: 'test' }], ['123', 'test']],
+]
+
+describe('formatToText', () => {
+ it.each(getOutputForFormatToTextTests)('for input: %s (reply), should be output: %s',
+ (reply, expected) => {
+ const result = comboBoxToArray(reply)
+ expect(result).toEqual(expected)
+ })
+})
diff --git a/redisinsight/ui/src/utils/transformers/browser.ts b/redisinsight/ui/src/utils/transformers/browser.ts
new file mode 100644
index 0000000000..586a8da02f
--- /dev/null
+++ b/redisinsight/ui/src/utils/transformers/browser.ts
@@ -0,0 +1,3 @@
+import { EuiComboBoxOptionOption } from '@elastic/eui'
+
+export const comboBoxToArray = (items: EuiComboBoxOptionOption[]) => [...items].map(({ label }) => label)
diff --git a/redisinsight/ui/src/utils/transformers/index.ts b/redisinsight/ui/src/utils/transformers/index.ts
index acbecc0489..013d674df3 100644
--- a/redisinsight/ui/src/utils/transformers/index.ts
+++ b/redisinsight/ui/src/utils/transformers/index.ts
@@ -11,6 +11,7 @@ export * from './extrapolation'
export * from './transformQueryParams'
export * from './getTruncatedName'
export * from './transformRdiPipeline'
+export * from './browser'
export {
replaceSpaces,
diff --git a/tests/e2e/common-actions/browser-actions.ts b/tests/e2e/common-actions/browser-actions.ts
index a778c03e31..a3ebb2a5bc 100644
--- a/tests/e2e/common-actions/browser-actions.ts
+++ b/tests/e2e/common-actions/browser-actions.ts
@@ -70,10 +70,10 @@ export class BrowserActions {
}
/**
- * Verify that not patterned keys not visible with delimiter
+ * Verify that not patterned keys not displayed with delimiter
* @param delimiter string with delimiter value
*/
- async verifyNotPatternedKeys(delimiter: string): Promise {
+ async verifyNotPatternedKeysNotDisplayed(delimiter: string): Promise {
const notPatternedKeys = Selector('[data-testid^="badge"]').parent('[data-testid^="node-item_"]');
const notPatternedKeysNumber = await notPatternedKeys.count;
@@ -88,9 +88,8 @@ export class BrowserActions {
* @param folderName name of folder
* @param delimiter string with delimiter value
*/
- getNodeName(startFolder: string, folderName: string, delimiter: string): string {
- return startFolder + folderName + delimiter;
-
+ getNodeName(startFolder: string, folderName: string, delimiter?: string): string {
+ return delimiter ? `${startFolder}${delimiter}${folderName}` : `${startFolder}${folderName}`;
}
/**
@@ -106,29 +105,31 @@ export class BrowserActions {
* @param folders name of folders for tree view build
* @param delimiter string with delimiter value
*/
- async checkTreeViewFoldersStructure(folders: string[][], delimiter: string): Promise {
- // Verify not patterned keys
- await this.verifyNotPatternedKeys(delimiter);
-
- const foldersNumber = folders.length;
+ async checkTreeViewFoldersStructure(folders: string[][], delimiters: string[]): Promise {
+ await this.verifyNotPatternedKeysNotDisplayed(delimiters[0]);
- for (let i = 0; i < foldersNumber; i++) {
- const innerFoldersNumber = folders[i].length;
- let prevNodeSelector = '';
+ for (let i = 0; i < folders.length; i++) {
+ const delimiter = delimiters.length > 1 ? '-' : delimiters[0];
+ let prevNodeName = '';
+ let prevDelimiter = '';
- for (let j = 0; j < innerFoldersNumber; j++) {
- const nodeName = this.getNodeName(prevNodeSelector, folders[i][j], delimiter);
+ // Expand subfolders
+ for (let j = 0; j < folders[i].length; j++) {
+ const nodeName = this.getNodeName(prevNodeName, folders[i][j], prevDelimiter);
const node = this.getNodeSelector(nodeName);
const fullTestIdSelector = await node.getAttribute('data-testid');
+
if (!fullTestIdSelector?.includes('expanded')) {
await t.click(node);
}
- prevNodeSelector = nodeName;
+
+ prevNodeName = nodeName;
+ prevDelimiter = delimiter;
}
// Verify that the last folder level contains required keys
const foundKeyName = `${folders[i].join(delimiter)}`;
- const firstFolderName = this.getNodeName('', folders[i][0], delimiter);
+ const firstFolderName = this.getNodeName('', folders[i][0]);
const firstFolder = this.getNodeSelector(firstFolderName);
await t
.expect(Selector(`[data-testid*="node-item_${foundKeyName}"]`).find('[data-testid^="key-"]').exists).ok('Specific key not found')
diff --git a/tests/e2e/pageObjects/components/browser/tree-view.ts b/tests/e2e/pageObjects/components/browser/tree-view.ts
index 1a5c7d473c..709623152d 100644
--- a/tests/e2e/pageObjects/components/browser/tree-view.ts
+++ b/tests/e2e/pageObjects/components/browser/tree-view.ts
@@ -1,7 +1,10 @@
import { Selector, t } from 'testcafe';
import { Common } from '../../../helpers/common';
+import { FiltersDialog } from '../../dialogs';
export class TreeView {
+ FiltersDialog = new FiltersDialog();
+
//-------------------------------------------------------------------------------------------
//DECLARATION OF SELECTORS
//*Declare all elements/components of the relevant page.
@@ -10,17 +13,10 @@ export class TreeView {
//-------------------------------------------------------------------------------------------
//BUTTONS
treeViewSettingsBtn = Selector('[data-testid=tree-view-settings-btn]');
- treeViewDelimiterValueSave = Selector('[data-testid=tree-view-apply-btn]');
- treeViewDelimiterValueCancel = Selector('[data-testid=tree-view-cancel-btn]');
- sortingBtn = Selector('[data-testid=tree-view-sorting-select]');
- sortingASCoption = Selector('[id=ASC]');
- sortingDESCoption = Selector('[id=DESC]');
sortingProgressBar = Selector('[data-testid=progress-key-tree]');
// TEXT ELEMENTS
treeViewKeysNumber = Selector('[data-testid^=count_]');
treeViewDeviceFolder = Selector('[data-testid^=node-item_device] div');
- //INPUTS
- treeViewDelimiterInput = Selector('[data-testid=tree-view-delimiter-input]');
/**
* Get folder selector by folder name
@@ -51,15 +47,16 @@ export class TreeView {
/**
* Change delimiter value
- * @delimiter string with delimiter value
+ * @param delimiter string with delimiter value
*/
async changeDelimiterInTreeView(delimiter: string): Promise {
// Open delimiter popup
await t.click(this.treeViewSettingsBtn);
+ await this.FiltersDialog.clearDelimiterCombobox();
// Apply new value to the field
- await t.typeText(this.treeViewDelimiterInput, delimiter, { replace: true, paste: true });
+ await this.FiltersDialog.addDelimiterItem(delimiter);
// Click on save button
- await t.click(this.treeViewDelimiterValueSave);
+ await t.click(this.FiltersDialog.treeViewDelimiterValueSave);
}
/**
@@ -69,13 +66,13 @@ export class TreeView {
async changeOrderingInTreeView(order: string): Promise {
// Open settings popup
await t.click(this.treeViewSettingsBtn);
- await t.click(this.sortingBtn);
+ await t.click(this.FiltersDialog.sortingBtn);
order === 'ASC'
- ? await t.click(this.sortingASCoption)
- : await t.click(this.sortingDESCoption);
+ ? await t.click(this.FiltersDialog.sortingASCoption)
+ : await t.click(this.FiltersDialog.sortingDESCoption);
// Click on save button
- await t.click(this.treeViewDelimiterValueSave);
+ await t.click(this.FiltersDialog.treeViewDelimiterValueSave);
await Common.waitForElementNotVisible(this.sortingProgressBar);
}
diff --git a/tests/e2e/pageObjects/dialogs/filters-dialog.ts b/tests/e2e/pageObjects/dialogs/filters-dialog.ts
new file mode 100644
index 0000000000..f640a60ad8
--- /dev/null
+++ b/tests/e2e/pageObjects/dialogs/filters-dialog.ts
@@ -0,0 +1,57 @@
+import { Selector, t } from 'testcafe';
+
+export class FiltersDialog {
+ // INPUTS
+ delimiterCombobox = Selector('[data-testid=delimiter-combobox]');
+ delimiterComboboxInput = Selector('[data-test-subj=comboBoxSearchInput]');
+ // BUTTONS
+ treeViewDelimiterValueCancel = Selector('[data-testid=tree-view-cancel-btn]');
+ treeViewDelimiterValueSave = Selector('[data-testid=tree-view-apply-btn]');
+ sortingBtn = Selector('[data-testid=tree-view-sorting-select]');
+ sortingASCoption = Selector('[id=ASC]');
+ sortingDESCoption = Selector('[id=DESC]');
+
+ /**
+ * Get Delimiter badge selector by title
+ * @param delimiterTitle title of the delimiter item
+ */
+ getDelimiterBadgeByTitle(delimiterTitle: string): Selector {
+ return this.delimiterCombobox.find(`span[title='${delimiterTitle}']`);
+ }
+
+ /**
+ * Get Delimiter close button selector by title
+ * @param delimiterTitle title of the delimiter item
+ */
+ getDelimiterCloseBtnByTitle(delimiterTitle: string): Selector {
+ return this.getDelimiterBadgeByTitle(delimiterTitle).find('button');
+ }
+
+ /**
+ * Add new delimiter
+ * @param delimiterName name of the delimiter item
+ */
+ async addDelimiterItem(delimiterName: string): Promise {
+ await t.click(this.delimiterComboboxInput);
+ await t.typeText(this.delimiterComboboxInput, delimiterName, { paste: true })
+ }
+
+ /**
+ * Delete existing delimiter
+ * @param delimiterName name of the delimiter item
+ */
+ async removeDelimiterItem(delimiterName: string): Promise {
+ await t.click(this.getDelimiterCloseBtnByTitle(delimiterName));
+ }
+
+ /**
+ * Remove all existing delimiters in combobox
+ */
+ async clearDelimiterCombobox(): Promise {
+ const delimiters = this.delimiterCombobox.find('button');
+ const count = await delimiters.count;
+ for (let i = 0; i < count; i++) {
+ await t.click(delimiters.nth(i));
+ }
+ }
+}
diff --git a/tests/e2e/pageObjects/dialogs/index.ts b/tests/e2e/pageObjects/dialogs/index.ts
index c96a11a7c2..73c4d96b82 100644
--- a/tests/e2e/pageObjects/dialogs/index.ts
+++ b/tests/e2e/pageObjects/dialogs/index.ts
@@ -1,7 +1,9 @@
import { OnboardingCardsDialog } from './onboarding-cards-dialog';
+import { FiltersDialog } from './filters-dialog';
import { UserAgreementDialog } from './user-agreement-dialog';
export {
OnboardingCardsDialog,
+ FiltersDialog,
UserAgreementDialog
};
diff --git a/tests/e2e/tests/web/critical-path/tree-view/delimiter.e2e.ts b/tests/e2e/tests/web/critical-path/tree-view/delimiter.e2e.ts
index db1e2ffa7c..78aee90bd8 100644
--- a/tests/e2e/tests/web/critical-path/tree-view/delimiter.e2e.ts
+++ b/tests/e2e/tests/web/critical-path/tree-view/delimiter.e2e.ts
@@ -1,22 +1,27 @@
import { BrowserPage } from '../../../../pageObjects';
-import { commonUrl, ossStandaloneBigConfig } from '../../../../helpers/conf';
+import { commonUrl, ossStandaloneBigConfig, ossStandaloneV8Config } from '../../../../helpers/conf';
import { rte } from '../../../../helpers/constants';
import { DatabaseHelper } from '../../../../helpers/database';
import { DatabaseAPIRequests } from '../../../../helpers/api/api-database';
import { BrowserActions } from '../../../../common-actions/browser-actions';
+import { APIKeyRequests } from '../../../../helpers/api/api-keys';
+import { HashKeyParameters } from '../../../../pageObjects/browser-page';
const browserPage = new BrowserPage();
const browserActions = new BrowserActions();
const databaseHelper = new DatabaseHelper();
const databaseAPIRequests = new DatabaseAPIRequests();
+const apiKeyRequests = new APIKeyRequests();
+
+let keyNames: string[];
fixture `Delimiter tests`
.meta({ type: 'critical_path', rte: rte.standalone })
.page(commonUrl)
- .beforeEach(async() => {
+ .beforeEach(async () => {
await databaseHelper.acceptLicenseTermsAndAddDatabaseApi(ossStandaloneBigConfig);
})
- .afterEach(async() => {
+ .afterEach(async () => {
await databaseAPIRequests.deleteStandaloneDatabaseApi(ossStandaloneBigConfig);
});
test('Verify that user can see that input is not saved when the Cancel button is clicked', async t => {
@@ -24,18 +29,72 @@ test('Verify that user can see that input is not saved when the Cancel button is
await t.click(browserPage.treeViewButton);
await t.click(browserPage.TreeView.treeViewSettingsBtn);
// Check the default delimiter value
- await t.expect(browserPage.TreeView.treeViewDelimiterInput.value).eql(':', 'Default delimiter not applied');
+ await t.expect(browserPage.TreeView.FiltersDialog.getDelimiterBadgeByTitle(':').exists).eql(true, 'Default delimiter not applied');
// Apply new value to the field
- await t.typeText(browserPage.TreeView.treeViewDelimiterInput, 'test', { replace: true });
+ await browserPage.TreeView.FiltersDialog.removeDelimiterItem(':');
+ await browserPage.TreeView.FiltersDialog.addDelimiterItem('test');
// Click on Cancel button
- await t.click(browserPage.TreeView.treeViewDelimiterValueCancel);
+ await t.click(browserPage.TreeView.FiltersDialog.treeViewDelimiterValueCancel);
// Check the previous delimiter value
await t.click(browserPage.TreeView.treeViewSettingsBtn);
- await t.expect(browserPage.TreeView.treeViewDelimiterInput.value).eql(':', 'Previous delimiter not applied');
- await t.click(browserPage.TreeView.treeViewDelimiterValueCancel);
+ await t.expect(browserPage.TreeView.FiltersDialog.getDelimiterBadgeByTitle(':').exists).eql(true, 'Previous delimiter not applied');
+ await t.expect(browserPage.TreeView.FiltersDialog.getDelimiterBadgeByTitle('test').exists).eql(false, 'Previous delimiter not applied');
+ await t.click(browserPage.TreeView.FiltersDialog.treeViewDelimiterValueCancel);
// Change delimiter
await browserPage.TreeView.changeDelimiterInTreeView('-');
// Verify that when user changes the delimiter and clicks on Save button delimiter is applied
- await browserActions.checkTreeViewFoldersStructure([['device_us', 'west'], ['mobile_eu', 'central'], ['mobile_us', 'east'], ['user_us', 'west'], ['device_eu', 'central'], ['user_eu', 'central']], '-');
+ await browserActions.checkTreeViewFoldersStructure([['device_us', 'west'], ['mobile_eu', 'central'], ['mobile_us', 'east'], ['user_us', 'west'], ['device_eu', 'central'], ['user_eu', 'central']], ['-']);
});
+test
+ .before(async () => {
+ await databaseHelper.acceptLicenseTermsAndAddDatabaseApi(ossStandaloneV8Config);
+ keyNames = [
+ `device:common-dev`,
+ `device-common:dev`,
+ `device:common:dev`,
+ `device-common-dev`,
+ `device:common-stage`,
+ `device:common1-stage`,
+ `mobile:common-dev`,
+ `mobile:common-stage`
+ ];
+ for (const keyName of keyNames) {
+ let hashKeyParameters: HashKeyParameters = {
+ keyName: keyName,
+ fields: [
+ {
+ field: 'field',
+ value: 'value',
+ },
+ ],
+ }
+ await apiKeyRequests.addHashKeyApi(
+ hashKeyParameters,
+ ossStandaloneV8Config,
+ )
+ }
+ await browserPage.reloadPage();
+ })
+ .after(async () => {
+ for (const keyName of keyNames) {
+ await apiKeyRequests.deleteKeyByNameApi(keyName, ossStandaloneV8Config.databaseName);
+ }
+ await databaseAPIRequests.deleteStandaloneDatabaseApi(ossStandaloneV8Config);
+ })('Verify that user can set multiple delimiters in the tree view', async t => {
+ // Switch to tree view
+ await t.click(browserPage.treeViewButton);
+ // Verify folders ordering with default delimiter
+ await browserActions.checkTreeViewFoldersStructure([['device', 'common'], ['device-common'], ['mobile']], [':']);
+ await t.click(browserPage.TreeView.treeViewSettingsBtn);
+ // Apply new value to the field
+ await browserPage.TreeView.FiltersDialog.addDelimiterItem('-');
+ await t.click(browserPage.TreeView.FiltersDialog.treeViewDelimiterValueSave);
+ // Verify that when user changes the delimiter and clicks on Save button delimiter is applied
+ await browserActions.checkTreeViewFoldersStructure([['device', 'common'], ['device', 'common1'], ['mobile', 'common']], [':', '-']);
+
+ // Verify that namespace names tooltip contains valid names and delimiter
+ await t.click(browserActions.getNodeSelector('device'));
+ await t.hover(browserActions.getNodeSelector('device-common'));
+ await browserActions.verifyTooltipContainsText('device-common-*\n:\n-\n5 key(s)', true);
+ });
diff --git a/tests/e2e/tests/web/regression/tree-view/tree-view.e2e.ts b/tests/e2e/tests/web/regression/tree-view/tree-view.e2e.ts
index 08be4a8c69..56c8249460 100644
--- a/tests/e2e/tests/web/regression/tree-view/tree-view.e2e.ts
+++ b/tests/e2e/tests/web/regression/tree-view/tree-view.e2e.ts
@@ -133,7 +133,7 @@ test('Verify that when user deletes the key he can see the key is removed from t
await t.click(browserPage.treeViewButton);
// Verify the default separator
await t.click(browserPage.TreeView.treeViewSettingsBtn);
- await t.expect(browserPage.TreeView.treeViewDelimiterInput.value).eql(':', 'The “:” (colon) not used as a default separator for namespaces');
+ await t.expect(browserPage.TreeView.FiltersDialog.getDelimiterBadgeByTitle(':').exists).eql(true, 'The “:” (colon) not used as a default separator for namespaces');
// Verify that user can see that “:” (colon) used as a default separator for namespaces and see the number of keys found per each namespace
await t.expect(browserPage.TreeView.treeViewKeysNumber.visible).ok('The user can not see the number of keys');