Skip to content

Commit 00ace7f

Browse files
committed
Merge branch 'main' into feature/RI-2743_Enhanced_overview
2 parents 233b9db + 1c302d4 commit 00ace7f

File tree

10 files changed

+190
-41
lines changed

10 files changed

+190
-41
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,6 @@ vendor
5858

5959
# Parcel
6060
.parcel-cache
61+
62+
# caches
63+
.temp_cache

configs/webpack.config.web.dev.babel.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* https://webpack.js.org/concepts/hot-module-replacement/
66
*/
77

8+
import path from 'path';
89
import webpack from 'webpack';
910
import { merge } from 'webpack-merge';
1011
import ip from 'ip';
@@ -21,6 +22,18 @@ export default merge(commonConfig, {
2122

2223
mode: 'development',
2324

25+
cache: {
26+
type: 'filesystem',
27+
allowCollectingMemory: true,
28+
cacheDirectory: path.resolve(__dirname, '../.temp_cache'),
29+
name: 'webpack',
30+
maxAge: 86_400_000, // 1 day
31+
buildDependencies: {
32+
// This makes all dependencies of this file - build dependencies
33+
config: [__filename],
34+
}
35+
},
36+
2437
devtool: 'source-map',
2538

2639
entry: [

redisinsight/ui/src/constants/browser.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@ export const TEXT_UNPRINTABLE_CHARACTERS = {
44
title: 'Non-printable characters have been detected',
55
text: 'Use Workbench or CLI to edit without data loss.',
66
}
7+
8+
export const TEXT_DISABLED_FORMATTER_EDITING = 'Cannot edit the value in this format'

redisinsight/ui/src/pages/browser/components/hash-details/HashDetails.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,13 @@ import { selectedKeyDataSelector, keysSelector, selectedKeySelector } from 'uiSr
4040
import { connectedInstanceSelector } from 'uiSrc/slices/instances/instances'
4141
import { SCAN_COUNT_DEFAULT } from 'uiSrc/constants/api'
4242
import HelpTexts from 'uiSrc/constants/help-texts'
43-
import { KeyTypes, OVER_RENDER_BUFFER_COUNT, TableCellAlignment, TEXT_UNPRINTABLE_CHARACTERS } from 'uiSrc/constants'
43+
import {
44+
KeyTypes,
45+
OVER_RENDER_BUFFER_COUNT,
46+
TableCellAlignment,
47+
TEXT_DISABLED_FORMATTER_EDITING,
48+
TEXT_UNPRINTABLE_CHARACTERS
49+
} from 'uiSrc/constants'
4450
import { getColumnWidth } from 'uiSrc/components/virtual-grid'
4551
import { StopPropagation } from 'uiSrc/components/virtual-table'
4652
import { stringToBuffer } from 'uiSrc/utils/formatters/bufferFormatters'
@@ -408,7 +414,7 @@ const HashDetails = (props: Props) => {
408414
return (
409415
<StopPropagation>
410416
<div className="value-table-actions">
411-
<EuiToolTip content={!isEditable ? 'Cannot change data in this format' : null}>
417+
<EuiToolTip content={!isEditable ? TEXT_DISABLED_FORMATTER_EDITING : null}>
412418
<EuiButtonIcon
413419
iconType="pencil"
414420
aria-label="Edit field"

redisinsight/ui/src/pages/browser/components/key-details-header/KeyDetailsHeader.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,15 @@ import AutoSizer from 'react-virtualized-auto-sizer'
1919

2020
import { GroupBadge } from 'uiSrc/components'
2121
import InlineItemEditor from 'uiSrc/components/inline-item-editor/InlineItemEditor'
22-
import { KEY_TYPES_ACTIONS, KeyTypes, LENGTH_NAMING_BY_TYPE, ModulesKeyTypes, STREAM_ADD_ACTION, TEXT_UNPRINTABLE_CHARACTERS } from 'uiSrc/constants'
22+
import {
23+
KEY_TYPES_ACTIONS,
24+
KeyTypes,
25+
LENGTH_NAMING_BY_TYPE,
26+
ModulesKeyTypes,
27+
STREAM_ADD_ACTION,
28+
TEXT_DISABLED_FORMATTER_EDITING,
29+
TEXT_UNPRINTABLE_CHARACTERS
30+
} from 'uiSrc/constants'
2331
import { AddCommonFieldsFormConfig } from 'uiSrc/pages/browser/components/add-key/constants/fields-config'
2432
import { initialKeyInfo, keysSelector, selectedKeyDataSelector, selectedKeySelector } from 'uiSrc/slices/browser/keys'
2533
import { streamSelector } from 'uiSrc/slices/browser/stream'
@@ -393,7 +401,7 @@ const KeyDetailsHeader = ({
393401
{KEY_TYPES_ACTIONS[keyType] && 'editItem' in KEY_TYPES_ACTIONS[keyType] && (
394402
<div className={styles.actionBtn}>
395403
<EuiToolTip
396-
content={!isEditable ? 'Cannot change data in this format' : null}
404+
content={!isEditable ? TEXT_DISABLED_FORMATTER_EDITING : null}
397405
>
398406
<EuiButtonIcon
399407
disabled={!isEditable}

redisinsight/ui/src/pages/browser/components/list-details/ListDetails.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,13 @@ import { SCAN_COUNT_DEFAULT } from 'uiSrc/constants/api'
2323
import { connectedInstanceSelector } from 'uiSrc/slices/instances/instances'
2424
import { RedisResponseBuffer } from 'uiSrc/slices/interfaces'
2525
import { sendEventTelemetry, TelemetryEvent, getBasedOnViewTypeEvent } from 'uiSrc/telemetry'
26-
import { KeyTypes, OVER_RENDER_BUFFER_COUNT, TableCellAlignment, TEXT_UNPRINTABLE_CHARACTERS } from 'uiSrc/constants'
26+
import {
27+
KeyTypes,
28+
OVER_RENDER_BUFFER_COUNT,
29+
TableCellAlignment,
30+
TEXT_DISABLED_FORMATTER_EDITING,
31+
TEXT_UNPRINTABLE_CHARACTERS
32+
} from 'uiSrc/constants'
2733
import {
2834
bufferToSerializedFormat,
2935
bufferToString,
@@ -354,7 +360,7 @@ const ListDetails = (props: Props) => {
354360
return (
355361
<StopPropagation>
356362
<div className="value-table-actions">
357-
<EuiToolTip content={!isEditable ? 'Cannot change data in this format' : null}>
363+
<EuiToolTip content={!isEditable ? TEXT_DISABLED_FORMATTER_EDITING : null}>
358364
<EuiButtonIcon
359365
iconType="pencil"
360366
aria-label="Edit element"

tests/e2e/pageObjects/browser-page.ts

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ export class BrowserPage {
8888
saveButton = Selector('[data-testid=save-btn]');
8989
bulkActionsButton = Selector('[data-testid=btn-bulk-actions]');
9090
editHashButton = Selector('[data-testid^=edit-hash-button-]');
91+
editZsetButton = Selector('[data-testid^=zset-edit-button-]');
92+
editListButton = Selector('[data-testid^=edit-list-button-]');
9193
//CONTAINERS
9294
streamGroupsContainer = Selector('[data-testid=stream-groups-container]');
9395
streamConsumersContainer = Selector('[data-testid=stream-consumers-container]');
@@ -129,7 +131,9 @@ export class BrowserPage {
129131
hashFieldValueInput = Selector('[data-testid=field-value]');
130132
hashFieldNameInput = Selector('[data-testid=field-name]');
131133
hashFieldValueEditor = Selector('[data-testid=hash-value-editor]');
134+
listElementEditor = Selector('[data-testid=hash-value-editor]');
132135
listKeyElementInput = Selector('[data-testid=element]');
136+
listKeyElementEditorInput = Selector('[data-testid=element-value-editor]');
133137
stringKeyValueInput = Selector('[data-testid=string-value]');
134138
jsonKeyValueInput = Selector('[data-testid=json-value]');
135139
setMemberInput = Selector('[data-testid=member-name]');
@@ -156,6 +160,7 @@ export class BrowserPage {
156160
claimIdleTimeInput = Selector('[data-testid=time-count]');
157161
claimRetryCountInput = Selector('[data-testid=retry-count]');
158162
lastIdInput = Selector('[data-testid=last-id-field]');
163+
inlineItemEditor = Selector('[data-testid=inline-item-editor]');
159164
//TEXT ELEMENTS
160165
keySizeDetails = Selector('[data-testid=key-size-text]');
161166
keyLengthDetails = Selector('[data-testid=key-length-text]');
@@ -193,7 +198,6 @@ export class BrowserPage {
193198
treeViewDeviceKyesCount = Selector('[data-testid^=count_device] span');
194199
ttlValueInKeysTable = Selector('[data-testid^=ttl-]');
195200
stringKeyValue = Selector('.key-details-body pre');
196-
keyDetailsValue = Selector('.key-details-body div div div');
197201
keyDetailsBadge = Selector('.key-details-header .euiBadge__text');
198202
treeViewKeysItem = Selector('[data-testid*="keys:keys:"]');
199203
treeViewNotPatternedKeys = Selector('[data-testid*="node-item_keys"]');
@@ -531,15 +535,31 @@ export class BrowserPage {
531535
*/
532536
async editStringKeyValue(value: string): Promise<void> {
533537
await t
534-
.click(this.keyDetailsValue)
538+
.click(this.stringKeyValueInput)
535539
.pressKey('ctrl+a delete')
536540
.typeText(this.stringKeyValueInput, value)
537541
.click(this.applyButton);
538542
}
539543

540-
//Get string key value from details
544+
//Get String key value from details
541545
async getStringKeyValue(): Promise<string> {
542-
return this.keyDetailsValue.textContent;
546+
return this.stringKeyValueInput.textContent;
547+
}
548+
549+
/**
550+
* Edit Zset key score from details
551+
* @param value The value of the key
552+
*/
553+
async editZsetKeyScore(value: string): Promise<void> {
554+
await t
555+
.click(this.editZsetButton)
556+
.typeText(this.inlineItemEditor, value, { replace: true, paste: true })
557+
.click(this.applyButton);
558+
}
559+
560+
//Get Zset key score from details
561+
async getZsetKeyScore(): Promise<string> {
562+
return this.zsetScoresList.textContent;
543563
}
544564

545565
/**
@@ -564,10 +584,47 @@ export class BrowserPage {
564584
async editHashKeyValue(value: string): Promise<void> {
565585
await t
566586
.click(this.editHashButton)
567-
.typeText(this.hashFieldValueEditor, value, {replace: true, paste: true})
587+
.typeText(this.hashFieldValueEditor, value, { replace: true, paste: true })
568588
.click(this.applyButton);
569589
}
570590

591+
//Get Hash key value from details
592+
async getHashKeyValue(): Promise<string> {
593+
return this.hashFieldValue.textContent;
594+
}
595+
596+
/**
597+
* Edit List key value from details
598+
* @param value The value of the key
599+
*/
600+
async editListKeyValue(value: string): Promise<void> {
601+
await t
602+
.click(this.editListButton)
603+
.typeText(this.listKeyElementEditorInput, value, { replace: true, paste: true })
604+
.click(this.applyButton);
605+
}
606+
607+
//Get List key value from details
608+
async getListKeyValue(): Promise<string> {
609+
return this.listElementsList.textContent;
610+
}
611+
612+
/**
613+
* Edit JSON key value from details
614+
* @param value The value of the key
615+
*/
616+
async editJsonKeyValue(value: string): Promise<void> {
617+
await t
618+
.click(this.jsonScalarValue)
619+
.typeText(this.inlineItemEditor, value, { replace: true, paste: true })
620+
.click(this.applyButton);
621+
}
622+
623+
//Get JSON key value from details
624+
async getJsonKeyValue(): Promise<string> {
625+
return this.jsonKeyValue.textContent;
626+
}
627+
571628
/**
572629
* Search by the value in the key details
573630
* @param value The value of the search parameter

tests/e2e/tests/critical-path/browser/formatters.e2e.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ notEditableFormattersSet.forEach(formatter => {
197197
// Hover on disabled button
198198
await t.hover(editBtn);
199199
// Verify tooltip content
200-
await t.expect(browserPage.tooltip.textContent).contains('Cannot change data in this format', 'Tooltip has wrong text');
200+
await t.expect(browserPage.tooltip.textContent).contains('Cannot edit the value in this format', 'Tooltip has wrong text');
201201
}
202202
}
203203
});

tests/e2e/tests/regression/browser/full-screen.e2e.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ test
4040
const widthAfterFullScreen = await browserPage.keyDetailsTable.clientWidth;
4141
await t.expect(widthAfterFullScreen).gt(widthBeforeFullScreen, 'Width after switching to full screen');
4242
await t.expect(browserPage.keyNameFormDetails.withExactText(keyName).exists).ok('Key Details Table');
43-
await t.expect(browserPage.keyDetailsValue.withExactText(keyValue).exists).ok('Key Value in Details');
43+
await t.expect(browserPage.stringKeyValueInput.withExactText(keyValue).exists).ok('Key Value in Details');
4444
// Verify that user can exit full screen in key details and two tables with keys and key details are displayed
4545
await t.click(browserPage.fullScreenModeButton);
4646
const widthAfterExitFullScreen = await browserPage.keyDetailsTable.clientWidth;
Lines changed: 82 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,95 @@
11
import { rte } from '../../../helpers/constants';
2-
import { deleteDatabase, acceptTermsAddDatabaseOrConnectToRedisStack } from '../../../helpers/database';
2+
import { acceptLicenseTermsAndAddDatabaseApi } from '../../../helpers/database';
33
import { BrowserPage } from '../../../pageObjects';
44
import { commonUrl, ossStandaloneConfig } from '../../../helpers/conf';
5-
import { Chance } from 'chance';
5+
import { Common } from '../../../helpers/common';
6+
import { deleteStandaloneDatabaseApi } from '../../../helpers/api/api-database';
67

78
const browserPage = new BrowserPage();
8-
const chance = new Chance();
9+
const common = new Common();
910

10-
let keyName = chance.word({ length: 10 });
11+
const keyTTL = '2147476121';
12+
const keyValueBefore = 'ValueBeforeEdit!';
13+
const keyValueAfter = 'ValueAfterEdit!';
14+
let keyName = common.generateWord(10);
1115

1216
fixture `Edit Key values verification`
13-
.meta({ type: 'smoke' })
17+
.meta({ type: 'smoke', rte: rte.standalone })
1418
.page(commonUrl)
15-
.beforeEach(async () => {
16-
await acceptTermsAddDatabaseOrConnectToRedisStack(ossStandaloneConfig, ossStandaloneConfig.databaseName);
19+
.beforeEach(async() => {
20+
await acceptLicenseTermsAndAddDatabaseApi(ossStandaloneConfig, ossStandaloneConfig.databaseName);
1721
})
18-
.afterEach(async () => {
22+
.afterEach(async() => {
1923
//Clear and delete database
2024
await browserPage.deleteKeyByName(keyName);
21-
await deleteDatabase(ossStandaloneConfig.databaseName);
22-
})
23-
test
24-
.meta({ rte: rte.standalone })
25-
('Verify that user can edit String value', async t => {
26-
keyName = chance.word({ length: 10 });
27-
const keyTTL = '2147476121';
28-
const keyValueBefore = 'StringValueBeforeEdit!';
29-
const keyValueAfter = 'StringValueBeforeEdit!';
30-
31-
//Add string key
32-
await browserPage.addStringKey(keyName, keyValueBefore, keyTTL);
33-
//Check the key value before edit
34-
let keyValueFromDetails = await browserPage.getStringKeyValue();
35-
await t.expect(keyValueFromDetails).contains(keyValueBefore, 'The value of the key');
36-
//Edit String key value
37-
await browserPage.editStringKeyValue(keyValueAfter);
38-
//Check the key value after edit
39-
keyValueFromDetails = await browserPage.getStringKeyValue();
40-
await t.expect(keyValueFromDetails).contains(keyValueAfter, 'The value of the key');
25+
await deleteStandaloneDatabaseApi(ossStandaloneConfig);
4126
});
27+
test('Verify that user can edit String value', async t => {
28+
keyName = common.generateWord(10);
29+
//Add string key
30+
await browserPage.addStringKey(keyName, keyValueBefore, keyTTL);
31+
//Check the key value before edit
32+
let keyValue = await browserPage.getStringKeyValue();
33+
await t.expect(keyValue).contains(keyValueBefore, 'The value is incorrect');
34+
//Edit String key value
35+
await browserPage.editStringKeyValue(keyValueAfter);
36+
//Check the key value after edit
37+
keyValue = await browserPage.getStringKeyValue();
38+
await t.expect(keyValue).contains(keyValueAfter, 'Edited value is incorrect');
39+
});
40+
test('Verify that user can edit Zset Key member', async t => {
41+
keyName = common.generateWord(10);
42+
const scoreBefore = '5';
43+
const scoreAfter = '10';
44+
//Add zset key
45+
await browserPage.addZSetKey(keyName, scoreBefore, keyTTL, keyValueBefore);
46+
//Check the key score before edit
47+
let zsetScore = await browserPage.getZsetKeyScore();
48+
await t.expect(zsetScore).eql(scoreBefore, 'Score is incorrect');
49+
//Edit Zset key score
50+
await browserPage.editZsetKeyScore(scoreAfter);
51+
//Check Zset key score after edit
52+
zsetScore = await browserPage.getZsetKeyScore();
53+
await t.expect(zsetScore).contains(scoreAfter, 'Score is not edited');
54+
});
55+
test('Verify that user can edit Hash Key field', async t => {
56+
const fieldName = 'test';
57+
keyName = common.generateWord(10);
58+
//Add Hash key
59+
await browserPage.addHashKey(keyName, keyTTL, fieldName, keyValueBefore);
60+
//Check the key value before edit
61+
let keyValue = await browserPage.getHashKeyValue();
62+
await t.expect(keyValue).eql(keyValueBefore, 'The value is incorrect');
63+
//Edit Hash key value
64+
await browserPage.editHashKeyValue(keyValueAfter);
65+
//Check Hash key value after edit
66+
keyValue = await browserPage.getHashKeyValue();
67+
await t.expect(keyValue).contains(keyValueAfter, 'Edited value is incorrect');
68+
});
69+
test('Verify that user can edit List Key element', async t => {
70+
keyName = common.generateWord(10);
71+
//Add List key
72+
await browserPage.addListKey(keyName, keyTTL, keyValueBefore);
73+
//Check the key value before edit
74+
let keyValue = await browserPage.getListKeyValue();
75+
await t.expect(keyValue).eql(keyValueBefore, 'The value is incorrect');
76+
//Edit List key value
77+
await browserPage.editListKeyValue(keyValueAfter);
78+
//Check List key value after edit
79+
keyValue = await browserPage.getListKeyValue();
80+
await t.expect(keyValue).contains(keyValueAfter, 'Edited value is incorrect');
81+
});
82+
test('Verify that user can edit JSON Key value', async t => {
83+
const jsonValueBefore = '{"name":"xyz"}';
84+
const jsonEditedValue = '"xyz test"';
85+
const jsonValueAfter = '{name:"xyz test"}';
86+
keyName = common.generateWord(10);
87+
//Add JSON key with json object
88+
await browserPage.addJsonKey(keyName, jsonValueBefore, keyTTL);
89+
//Check the key value before edit
90+
await t.expect(await browserPage.getJsonKeyValue()).eql('{name:"xyz"}', 'The value is incorrect');
91+
//Edit JSON key value
92+
await browserPage.editJsonKeyValue(jsonEditedValue);
93+
//Check JSON key value after edit
94+
await t.expect(await browserPage.getJsonKeyValue()).contains(jsonValueAfter, 'Edited value is incorrect');
95+
});

0 commit comments

Comments
 (0)