Skip to content

Commit 2e9856f

Browse files
committed
#RI-3903 - add tests, ui changes
1 parent 7b89ce1 commit 2e9856f

File tree

10 files changed

+211
-17
lines changed

10 files changed

+211
-17
lines changed

redisinsight/ui/src/components/import-databases-dialog/ImportDatabasesDialog.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import {
22
EuiButton,
33
EuiFilePicker,
44
EuiFlexGroup,
5-
EuiFlexItem, EuiIcon,
5+
EuiFlexItem,
6+
EuiIcon,
67
EuiLoadingSpinner,
78
EuiModal,
89
EuiModalBody,
@@ -49,11 +50,11 @@ const ImportDatabasesDialog = ({ onClose }: Props) => {
4950
}
5051

5152
const handleOnClose = () => {
52-
dispatch(resetImportInstances())
5353
if (data?.success?.length || data?.partial?.length) {
5454
dispatch(fetchInstancesAction())
5555
}
5656
onClose(!data)
57+
dispatch(resetImportInstances())
5758
}
5859

5960
const onSubmit = () => {
@@ -75,7 +76,7 @@ const ImportDatabasesDialog = ({ onClose }: Props) => {
7576
<EuiModalHeader>
7677
<EuiModalHeaderTitle>
7778
<EuiTitle size="xs" data-testid="import-dbs-dialog-title">
78-
<span>{(!data && !error) ? 'Import Database Connections' : 'Import results'}</span>
79+
<span>{(!data && !error) ? 'Import Database Connections' : 'Import Results'}</span>
7980
</EuiTitle>
8081
</EuiModalHeaderTitle>
8182
</EuiModalHeader>
@@ -113,9 +114,10 @@ const ImportDatabasesDialog = ({ onClose }: Props) => {
113114
{error && (
114115
<div className={styles.result} data-testid="result-failed">
115116
<EuiIcon type="crossInACircleFilled" size="xxl" color="danger" />
116-
<EuiText color="subdued" style={{ marginTop: 12 }}>
117+
<EuiText color="subdued" style={{ marginTop: 16 }}>
117118
Failed to add database connections
118119
</EuiText>
120+
<EuiText color="subdued">{error}</EuiText>
119121
</div>
120122
)}
121123
</EuiFlexItem>
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import React from 'react'
2+
import { render, screen, fireEvent, within } from 'uiSrc/utils/test-utils'
3+
import { ImportDatabasesData } from 'uiSrc/slices/interfaces'
4+
import { sendEventTelemetry, TelemetryEvent } from 'uiSrc/telemetry'
5+
import ResultsLog from './ResultsLog'
6+
7+
jest.mock('uiSrc/telemetry', () => ({
8+
...jest.requireActual('uiSrc/telemetry'),
9+
sendEventTelemetry: jest.fn(),
10+
}))
11+
12+
const mockedError = { statusCode: 400, message: 'message', error: 'error' }
13+
describe('ResultsLog', () => {
14+
it('should render', () => {
15+
const mockedData = { total: 0, fail: [], partial: [], success: [] }
16+
render(<ResultsLog data={mockedData} />)
17+
})
18+
19+
it('should be all collapsed nav groups', () => {
20+
const mockedData: ImportDatabasesData = {
21+
total: 3,
22+
fail: [{ index: 0, status: 'fail', errors: [mockedError] }],
23+
partial: [{ index: 2, status: 'fail', errors: [mockedError] }],
24+
success: [{ index: 1, status: 'success', port: 1233, host: 'localhost' }]
25+
}
26+
render(<ResultsLog data={mockedData} />)
27+
28+
expect(screen.getByTestId('success-results-closed')).toBeInTheDocument()
29+
expect(screen.getByTestId('partial-results-closed')).toBeInTheDocument()
30+
expect(screen.getByTestId('failed-results-closed')).toBeInTheDocument()
31+
})
32+
33+
it('should open and collapse other groups', () => {
34+
const mockedData: ImportDatabasesData = {
35+
total: 3,
36+
fail: [{ index: 0, status: 'fail', errors: [mockedError] }],
37+
partial: [{ index: 2, status: 'fail', errors: [mockedError] }],
38+
success: [{ index: 1, status: 'success', port: 1233, host: 'localhost' }]
39+
}
40+
render(<ResultsLog data={mockedData} />)
41+
42+
fireEvent.click(
43+
within(screen.getByTestId('success-results-closed')).getByRole('button')
44+
)
45+
expect(screen.getByTestId('success-results-open')).toBeInTheDocument()
46+
47+
expect(screen.getByTestId('partial-results-closed')).toBeInTheDocument()
48+
expect(screen.getByTestId('failed-results-closed')).toBeInTheDocument()
49+
50+
fireEvent.click(
51+
within(screen.getByTestId('failed-results-closed')).getByRole('button')
52+
)
53+
expect(screen.getByTestId('failed-results-open')).toBeInTheDocument()
54+
55+
expect(screen.getByTestId('partial-results-closed')).toBeInTheDocument()
56+
expect(screen.getByTestId('success-results-closed')).toBeInTheDocument()
57+
58+
fireEvent.click(
59+
within(screen.getByTestId('partial-results-closed')).getByRole('button')
60+
)
61+
expect(screen.getByTestId('partial-results-open')).toBeInTheDocument()
62+
63+
expect(screen.getByTestId('failed-results-closed')).toBeInTheDocument()
64+
expect(screen.getByTestId('success-results-closed')).toBeInTheDocument()
65+
})
66+
67+
it('should show proper items length', () => {
68+
const mockedData: ImportDatabasesData = {
69+
total: 4,
70+
fail: [{ index: 0, status: 'fail', errors: [mockedError] }],
71+
partial: [{ index: 2, status: 'fail', errors: [mockedError] }],
72+
success: [
73+
{ index: 1, status: 'success', port: 1233, host: 'localhost' },
74+
{ index: 3, status: 'success', port: 1233, host: 'localhost' }
75+
]
76+
}
77+
render(<ResultsLog data={mockedData} />)
78+
79+
expect(
80+
within(screen.getByTestId('success-results-closed')).getByTestId('number-of-dbs')
81+
).toHaveTextContent('2')
82+
expect(
83+
within(screen.getByTestId('partial-results-closed')).getByTestId('number-of-dbs')
84+
).toHaveTextContent('1')
85+
expect(
86+
within(screen.getByTestId('failed-results-closed')).getByTestId('number-of-dbs')
87+
).toHaveTextContent('1')
88+
})
89+
90+
it('should call proper telemetry event after click', () => {
91+
const sendEventTelemetryMock = jest.fn();
92+
(sendEventTelemetry as jest.Mock).mockImplementation(() => sendEventTelemetryMock)
93+
94+
const mockedData: ImportDatabasesData = {
95+
total: 3,
96+
fail: [{ index: 0, status: 'fail', errors: [mockedError] }],
97+
partial: [{ index: 2, status: 'fail', errors: [mockedError] }],
98+
success: [{ index: 1, status: 'success', port: 1233, host: 'localhost' }]
99+
}
100+
render(<ResultsLog data={mockedData} />)
101+
102+
fireEvent.click(
103+
within(screen.getByTestId('success-results-closed')).getByRole('button')
104+
)
105+
106+
expect(sendEventTelemetry).toBeCalledWith({
107+
event: TelemetryEvent.CONFIG_DATABASES_REDIS_IMPORT_LOG_VIEWED,
108+
eventData: {
109+
length: 1,
110+
name: 'success'
111+
}
112+
});
113+
114+
(sendEventTelemetry as jest.Mock).mockRestore()
115+
116+
fireEvent.click(
117+
within(screen.getByTestId('success-results-open')).getByRole('button')
118+
)
119+
120+
expect(sendEventTelemetry).not.toBeCalled()
121+
})
122+
})

redisinsight/ui/src/components/import-databases-dialog/components/ResultsLog/styles.module.scss

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,19 @@
2626

2727
&:global(.success) {
2828
&:before {
29-
background-color: #13A450;
29+
background-color: var(--successBorderColor);
3030
}
3131
}
3232

3333
&:global(.partial) {
3434
&:before {
35-
background-color: #9D6901;
35+
background-color: var(--warningBorderColor);
3636
}
3737
}
3838

3939
&:global(.failed) {
4040
&:before {
41-
background-color: #AD0017;
41+
background-color: var(--errorBorderColor);
4242
}
4343
}
4444

@@ -65,7 +65,7 @@
6565
background-color: var(--euiColorEmptyShade);
6666
padding: 12px 24px 12px 32px !important;
6767
border-radius: 4px;
68-
border: 1px solid #3D3D3D;
68+
border: 1px solid var(--separatorColor);
6969
}
7070
.euiCollapsibleNavGroup__children {
7171
padding: 0 !important;
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import React from 'react'
2+
import { render, screen } from 'uiSrc/utils/test-utils'
3+
import TableResult from './TableResult'
4+
5+
const mockedError = { statusCode: 400, message: 'message', error: 'error' }
6+
7+
describe('TableResult', () => {
8+
it('should render', () => {
9+
render(<TableResult data={[{ index: 0, status: 'success' }]} />)
10+
})
11+
12+
it('should not render table for empty data', () => {
13+
render(<TableResult data={[]} />)
14+
15+
expect(screen.queryByTestId('result-log-table')).not.toBeInTheDocument()
16+
})
17+
18+
it('should render table data with success messages', () => {
19+
render(
20+
<TableResult data={[
21+
{ index: 0, status: 'success', port: 1233, host: 'localhost' },
22+
{ index: 1, status: 'success', port: 5233, host: 'localhost2' },
23+
]}
24+
/>
25+
)
26+
27+
expect(screen.getByTestId('table-index-0')).toHaveTextContent('(0)')
28+
expect(screen.getByTestId('table-index-1')).toHaveTextContent('(1)')
29+
expect(screen.getByTestId('table-host-port-0')).toHaveTextContent('localhost:1233')
30+
expect(screen.getByTestId('table-host-port-1')).toHaveTextContent('localhost2:5233')
31+
expect(screen.getByTestId('table-result-0')).toHaveTextContent('Successful')
32+
expect(screen.getByTestId('table-result-1')).toHaveTextContent('Successful')
33+
})
34+
35+
it('should render table data with error messages', () => {
36+
render(
37+
<TableResult data={[
38+
{ index: 0, status: 'error', port: 1233, errors: [mockedError, mockedError] },
39+
{ index: 1, status: 'error', host: 'localhost2', errors: [mockedError] },
40+
]}
41+
/>
42+
)
43+
expect(screen.getByTestId('table-result-0')).toHaveTextContent([mockedError, mockedError].map((e) => e.message).join(''))
44+
expect(screen.getByTestId('table-result-1')).toHaveTextContent([mockedError].map((e) => e.message).join(''))
45+
})
46+
})

redisinsight/ui/src/slices/instances/instances.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,6 @@ export function uploadInstancesFile(
544544
} catch (error) {
545545
const errorMessage = getApiErrorMessage(error)
546546
dispatch(importInstancesFromFileFailure(errorMessage))
547-
dispatch(addErrorNotification(error))
548547
onFailAction?.()
549548
}
550549
}

redisinsight/ui/src/slices/tests/instances/instances.spec.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ import reducer, {
4747
importInstancesFromFileSuccess,
4848
importInstancesFromFileFailure,
4949
resetImportInstances,
50-
importInstancesSelector, uploadInstancesFile
50+
importInstancesSelector,
51+
uploadInstancesFile
5152
} from '../../instances/instances'
5253
import { addErrorNotification, addMessageNotification, IAddInstanceErrorPayload } from '../../app/notifications'
5354
import { ConnectionType, InitialStateInstances, Instance } from '../../interfaces'
@@ -542,9 +543,12 @@ describe('instances slice', () => {
542543
describe('importInstancesFromFileSuccess', () => {
543544
it('should properly set state', () => {
544545
// Arrange
546+
const mockedError = { statusCode: 400, message: 'message', error: 'error' }
545547
const data = {
546-
success: 3,
547-
total: 5
548+
total: 3,
549+
fail: [{ index: 0, status: 'fail', errors: [mockedError] }],
550+
partial: [{ index: 2, status: 'fail', errors: [mockedError] }],
551+
success: [{ index: 1, status: 'success', port: 1233, host: 'localhost' }]
548552
}
549553
const state = {
550554
...initialState.importInstances,
@@ -591,13 +595,16 @@ describe('instances slice', () => {
591595
describe('resetImportInstances', () => {
592596
it('should properly set state', () => {
593597
// Arrange
598+
const mockedError = { statusCode: 400, message: 'message', error: 'error' }
594599
const currentState = {
595600
...initialState,
596601
importInstances: {
597602
...initialState.importInstances,
598603
data: {
599-
success: 1,
600-
total: 2
604+
total: 3,
605+
fail: [{ index: 0, status: 'fail', errors: [mockedError] }],
606+
partial: [{ index: 2, status: 'fail', errors: [mockedError] }],
607+
success: [{ index: 1, status: 'success', port: 1233, host: 'localhost' }]
601608
}
602609
}
603610
}
@@ -1110,9 +1117,12 @@ describe('instances slice', () => {
11101117
it('should call proper actions on success', async () => {
11111118
// Arrange
11121119
const formData = new FormData()
1120+
const mockedError = { statusCode: 400, message: 'message', error: 'error' }
11131121
const data = {
1114-
success: 0,
1115-
total: 1
1122+
total: 3,
1123+
fail: [{ index: 0, status: 'fail', errors: [mockedError] }],
1124+
partial: [{ index: 2, status: 'fail', errors: [mockedError] }],
1125+
success: [{ index: 1, status: 'success', port: 1233, host: 'localhost' }]
11161126
}
11171127

11181128
const responsePayload = { data, status: 200 }
@@ -1150,7 +1160,6 @@ describe('instances slice', () => {
11501160
const expectedActions = [
11511161
importInstancesFromFile(),
11521162
importInstancesFromFileFailure(responsePayload.response.data.message),
1153-
addErrorNotification(responsePayload as AxiosError),
11541163
]
11551164
expect(store.getActions()).toEqual(expectedActions)
11561165
})

redisinsight/ui/src/styles/themes/dark_theme/_dark_theme.lazy.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,10 @@
131131

132132
--monacoBgColor: #{$monacoBgColor};
133133

134+
--successBorderColor: #{$successBorderColor};
135+
--warningBorderColor: #{$warningBorderColor};
136+
--errorBorderColor: #{$errorBorderColor};
137+
134138
// KeyTypes
135139
--typeHashColor: #{$typeHashColor};
136140
--typeListColor: #{$typeListColor};

redisinsight/ui/src/styles/themes/dark_theme/_theme_color.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ $overlayPromoNYColor: #0000001a;
9191

9292
$monacoBgColor: #111;
9393

94+
$successBorderColor: #13A450;
95+
$warningBorderColor: #9D6901;
96+
$errorBorderColor: #AD0017;
97+
9498
// Types colors
9599
$typeHashColor: #364cff;
96100
$typeListColor: #008556;

redisinsight/ui/src/styles/themes/light_theme/_light_theme.lazy.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,10 @@
133133

134134
--monacoBgColor: #{$monacoBgColor};
135135

136+
--successBorderColor: #{$successBorderColor};
137+
--warningBorderColor: #{$warningBorderColor};
138+
--errorBorderColor: #{$errorBorderColor};
139+
136140
// KeyTypes
137141
--typeHashColor: #{$typeHashColor};
138142
--typeListColor: #{$typeListColor};

redisinsight/ui/src/styles/themes/light_theme/_theme_color.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ $overlayPromoNYColor: #ffffff1a;
8888

8989
$monacoBgColor: #f0f2f7;
9090

91+
$successBorderColor: #5BC69B;
92+
$warningBorderColor: #FFAF2B;
93+
$errorBorderColor: #F74B57;
94+
9195
// Types colors
9296
$typeHashColor: #cdddf8;
9397
$typeListColor: #a5d4c3;

0 commit comments

Comments
 (0)