Skip to content

Commit 8f079b2

Browse files
[TSLA-8424] Whisker denied flows tab filter (#10017)
* upgrade to node v22.14.0
1 parent d7d6f1b commit 8f079b2

File tree

23 files changed

+279
-145
lines changed

23 files changed

+279
-145
lines changed

whisker/.nvmrc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v20.17.0
1+
v22.14.0

whisker/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ include ../lib.Makefile
1414
# Configure variables used by ci/cd common targets from lib.Makefile.
1515
BUILD_IMAGES=whisker
1616

17-
BUILD_IMAGE_NAME=node:20.17
17+
BUILD_IMAGE_NAME=node:22.14
1818

1919
DOCKER_RUN_RM:=docker run --rm \
2020
--env CYPRESS_CACHE_FOLDER=/code/.cache/Cypress \

whisker/jest.config.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,11 @@ export default {
3030
statements: 90,
3131
},
3232
},
33-
coveragePathIgnorePatterns: ['<rootDir>/src/theme', '<rootDir>/src/libs'],
33+
coveragePathIgnorePatterns: [
34+
'<rootDir>/src/theme',
35+
'<rootDir>/src/libs',
36+
'<rootDir>/src/icons/index.ts',
37+
'<rootDir>/src/components/index.ts',
38+
'<rootDir>/src/features/flowLogs/components/index.ts',
39+
],
3440
};

whisker/src/App.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ export const routes: RouteObject[] = [
3737
path: '',
3838
element: <FlowLogsContainer />,
3939
},
40-
// {
41-
// path: 'denied-flows',
42-
// element: <FlowLogsContainer />,
43-
// },
40+
{
41+
path: 'denied-flows',
42+
element: <FlowLogsContainer />,
43+
},
4444
],
4545
ErrorBoundary: FlowLogsErrorBoundary,
4646
},

whisker/src/api/__tests__/index.test.ts

+9
Original file line numberDiff line numberDiff line change
@@ -179,4 +179,13 @@ describe('useStream', () => {
179179
expect(mockEventSource.close).toHaveBeenCalled();
180180
expect(createEventSource).toHaveBeenCalledTimes(2);
181181
});
182+
183+
it('should call startStream with an updated path', () => {
184+
const newPath = 'new-path';
185+
const { result } = renderHook(() => useStream(''));
186+
187+
result.current.startStream(newPath);
188+
189+
expect(createEventSource).toHaveBeenCalledWith(newPath);
190+
});
182191
});

whisker/src/components/index.tsx

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import ChakraProvider from './core/ChakraProvider';
2-
import AppHeader from './layout/AppHeader';
32
import AppLayout from './layout/AppLayout';
43

5-
export { AppHeader, AppLayout, ChakraProvider };
4+
export { AppLayout, ChakraProvider };

whisker/src/features/flowLogs/api/__tests__/index.test.tsx

+10-7
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
} from '@/test-utils/helper';
77
import {
88
FilterHintTypes,
9-
ListOmniFilterParam,
9+
ListOmniFilterKeys,
1010
transformToFlowsFilterQuery,
1111
} from '@/utils/omniFilter';
1212
import {
@@ -65,7 +65,7 @@ describe('useInfiniteFilterQuery', () => {
6565

6666
const { result } = renderHookWithQueryClient(() =>
6767
useInfiniteFilterQuery(
68-
ListOmniFilterParam.source_namespace,
68+
ListOmniFilterKeys.source_namespace,
6969
filterString,
7070
),
7171
);
@@ -103,11 +103,14 @@ describe('useFlowLogsStream', () => {
103103
} as any);
104104
jest.mocked(transformToFlowsFilterQuery).mockReturnValue('');
105105

106-
const { rerender } = renderHook((props) => useFlowLogsStream(props), {
107-
initialProps: {
108-
source_name: [],
109-
} as any,
110-
});
106+
const { rerender } = renderHook(
107+
({ params, isDenied }) => useFlowLogsStream(params, isDenied),
108+
{
109+
initialProps: {
110+
source_name: [],
111+
} as any,
112+
},
113+
);
111114

112115
const updatedFilters = { source_name: ['foo'] } as any;
113116
jest.mocked(transformToFlowsFilterQuery).mockReturnValue('fake-query');

whisker/src/features/flowLogs/api/index.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
transformToFlowsFilterQuery,
1111
transformToQueryPage,
1212
FilterHintType,
13+
FilterKey,
1314
} from '@/utils/omniFilter';
1415
import { useInfiniteQuery, useQuery } from '@tanstack/react-query';
1516

@@ -70,8 +71,14 @@ export const useInfiniteFilterQuery = (
7071

7172
export const useFlowLogsStream = (
7273
filterValues: Record<OmniFilterParam, string[]>,
74+
filterDenied: boolean,
7375
) => {
74-
const filters = transformToFlowsFilterQuery(filterValues);
76+
const filters = transformToFlowsFilterQuery({
77+
...filterValues,
78+
...(filterDenied && {
79+
action: ['Deny'],
80+
}),
81+
} as Record<FilterKey, string[]>);
7582
const queryString = objToQueryStr({
7683
watch: true,
7784
filters,

whisker/src/features/flowLogs/components/FlowLogsList/styles.ts

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export const tableStyles = {
66
export const headerStyles = {
77
'>div>div': {
88
textTransform: 'none',
9+
py: 0,
910
},
1011
position: 'sticky',
1112
top: 0,

whisker/src/features/flowLogs/components/OmniFilters/__tests__/index.test.tsx

+23-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { fireEvent, render, screen, within } from '@/test-utils/helper';
22
import OmniFilters from '..';
3-
import { OmniFilterParam } from '@/utils/omniFilter';
3+
import { OmniFilterKeys } from '@/utils/omniFilter';
44

55
jest.mock(
66
'@/libs/tigera/ui-components/components/common/OmniFilter',
@@ -43,9 +43,13 @@ const PortOmniFilterMock = {
4343
jest.mock(
4444
'@/features/flowLogs/components/PortOmniFilter',
4545
() =>
46-
({ filterLabel, onChange }: any) => {
46+
({ filterLabel, onChange, port, protocol }: any) => {
4747
PortOmniFilterMock.onChange = onChange;
48-
return <div>{filterLabel}</div>;
48+
return (
49+
<div>
50+
{filterLabel} {port} {protocol}
51+
</div>
52+
);
4953
},
5054
);
5155

@@ -193,8 +197,23 @@ describe('<OmniFilters />', () => {
193197
PortOmniFilterMock.onChange(event);
194198

195199
expect(mockOnMultiChange).toHaveBeenCalledWith(
196-
[OmniFilterParam.protocol, OmniFilterParam.port],
200+
[OmniFilterKeys.protocol, OmniFilterKeys.port],
197201
[event.protocol, event.port],
198202
);
199203
});
204+
205+
it('should handle when port/ protocol values are provided', () => {
206+
const port = '1234';
207+
const protocol = 'tcp';
208+
const mockOnMultiChange = jest.fn();
209+
render(
210+
<OmniFilters
211+
{...defaultProps}
212+
onMultiChange={mockOnMultiChange}
213+
selectedValues={{ port: [port], protocol: [protocol] }}
214+
/>,
215+
);
216+
217+
expect(screen.getByText(`Port ${port} ${protocol}`));
218+
});
200219
});

whisker/src/features/flowLogs/components/OmniFilters/index.tsx

+13-12
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,22 @@ import { OmniFilterChangeEvent } from '@/libs/tigera/ui-components/components/co
77
import PortOmniFilter from '@/features/flowLogs/components/PortOmniFilter';
88
import { OmniFilterDataQuery } from '@/types/api';
99
import {
10-
CustomOmniFilterParam,
1110
ListOmniFilterParam,
12-
OmniFilterParam,
1311
OmniFilterProperties,
1412
ListOmniFiltersData,
1513
SelectedOmniFilterOptions,
1614
SelectedOmniFilters,
15+
OmniFilterKeys,
16+
CustomOmniFilterKeys,
17+
ListOmniFilterKeys,
1718
} from '@/utils/omniFilter';
1819
import React from 'react';
1920

20-
const listOmniFilterIds = Object.values(ListOmniFilterParam);
21+
const listOmniFilterIds = Object.values(ListOmniFilterKeys);
2122

2223
const omniFilterIds = [
2324
...listOmniFilterIds,
24-
...Object.values(CustomOmniFilterParam),
25+
...Object.values(CustomOmniFilterKeys),
2526
];
2627

2728
type OmniFiltersProps = {
@@ -67,7 +68,7 @@ const OmniFilters: React.FC<OmniFiltersProps> = ({
6768
<OmniFilter
6869
filterId={filterId}
6970
filterLabel={OmniFilterProperties[filterId].label}
70-
filters={omniFilterData?.[filterId].filters ?? []}
71+
filters={omniFilterData[filterId].filters ?? []}
7172
selectedFilters={selectedListOmniFilters[filterId]}
7273
onChange={onChange}
7374
onClear={() => handleClear(filterId)}
@@ -102,20 +103,20 @@ const OmniFilters: React.FC<OmniFiltersProps> = ({
102103
))}
103104

104105
<PortOmniFilter
105-
port={selectedValues?.port?.[0] ?? ''}
106-
protocol={selectedValues?.protocol?.[0] ?? ''}
106+
port={selectedValues.port?.[0] ?? ''}
107+
protocol={selectedValues.protocol?.[0] ?? ''}
107108
selectedFilters={[
108-
...(selectedValues?.port ?? []),
109-
...(selectedValues?.protocol ?? []),
109+
...(selectedValues.port ?? []),
110+
...(selectedValues.protocol ?? []),
110111
]}
111112
onChange={({ protocol, port }) =>
112113
onMultiChange(
113-
[OmniFilterParam.protocol, OmniFilterParam.port],
114+
[OmniFilterKeys.protocol, OmniFilterKeys.port],
114115
[protocol, port],
115116
)
116117
}
117-
filterId={CustomOmniFilterParam.port}
118-
filterLabel={OmniFilterProperties[OmniFilterParam.port].label}
118+
filterId={CustomOmniFilterKeys.port}
119+
filterLabel={OmniFilterProperties[OmniFilterKeys.port].label}
119120
/>
120121
</OmniFilterList>
121122
);

whisker/src/features/flowLogs/components/PortOmniFilter/__tests__/index.test.tsx

+47-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { render, screen, waitFor } from '@/test-utils/helper';
2-
import { CustomOmniFilterParam } from '@/utils/omniFilter';
2+
import {
3+
CustomOmniFilterKeys,
4+
CustomOmniFilterParam,
5+
} from '@/utils/omniFilter';
36
import userEvent from '@testing-library/user-event';
47
import PortOmniFilter from '..';
58

@@ -16,11 +19,11 @@ jest.mock(
1619
);
1720

1821
const defaultProps = {
19-
port: '',
20-
protocol: '',
22+
port: undefined as any,
23+
protocol: undefined as any,
2124
selectedFilters: null,
2225
filterLabel: '',
23-
filterId: CustomOmniFilterParam.port,
26+
filterId: CustomOmniFilterKeys.port as CustomOmniFilterParam,
2427
onChange: jest.fn(),
2528
};
2629

@@ -104,4 +107,44 @@ describe('<PortOmniFilter />', () => {
104107

105108
screen.getByRole('button', { name: 'Port = UDP:2020' });
106109
});
110+
111+
it('should change the protocol to Any', async () => {
112+
const mockOnChange = jest.fn();
113+
render(
114+
<PortOmniFilter
115+
{...defaultProps}
116+
onChange={mockOnChange}
117+
protocol='tcp'
118+
/>,
119+
);
120+
121+
userEvent.click(screen.getByRole('button', { name: 'Port = TCP' }));
122+
await screen.findByTestId('port-filter-popover-body');
123+
124+
MockSelect.onChange({ value: '' });
125+
126+
userEvent.click(screen.getByRole('button', { name: 'Apply filter' }));
127+
128+
await waitFor(() => {
129+
expect(mockOnChange).toHaveBeenCalledWith({
130+
port: null,
131+
protocol: null,
132+
});
133+
});
134+
});
135+
136+
it('should handle a bad port string', async () => {
137+
const mockOnChange = jest.fn();
138+
render(
139+
<PortOmniFilter
140+
{...defaultProps}
141+
onChange={mockOnChange}
142+
port='xyz'
143+
/>,
144+
);
145+
146+
expect(
147+
screen.getByRole('button', { name: 'Port' }),
148+
).toBeInTheDocument();
149+
});
107150
});

whisker/src/features/flowLogs/components/PortOmniFilter/index.tsx

+1-2
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,7 @@ const PortOmniFilter: React.FC<PortOmniFilterProps> = ({
128128
)}
129129
onChange={(option) =>
130130
field.onChange(
131-
option?.value ??
132-
'',
131+
option.value,
133132
)
134133
}
135134
/>

whisker/src/hooks/__tests__/omniFilters.test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
OmniFilterParam,
55
ListOmniFiltersData,
66
SelectedOmniFilterData,
7-
ListOmniFilterParam,
7+
ListOmniFilterKeys,
88
} from '@/utils/omniFilter';
99
import { useOmniFilterData } from '../omniFilters';
1010
import { useInfiniteFilterQuery } from '@/features/flowLogs/api';
@@ -233,7 +233,7 @@ describe('useOmniFilterData', () => {
233233

234234
const { result } = renderHook(() => useOmniFilterData());
235235

236-
result.current[1](ListOmniFilterParam.source_namespace, null);
236+
result.current[1](ListOmniFilterKeys.source_namespace, null);
237237

238238
expect(fetchNextPageMock).toHaveBeenCalledTimes(1);
239239
});

whisker/src/hooks/omniFilters.ts

+7-6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
ListOmniFiltersData,
88
SelectedOmniFilterData,
99
SelectedOmniFilterOptions,
10+
ListOmniFilterKeys,
1011
} from '@/utils/omniFilter';
1112
import React from 'react';
1213

@@ -16,7 +17,7 @@ export const useSelectedListOmniFilters = (
1617
selectedOmniFilterData: SelectedOmniFilterData,
1718
) => {
1819
const urlFilterValueKeys = Object.keys(urlFilterParams).filter(
19-
(key) => ListOmniFilterParam[key as ListOmniFilterParam],
20+
(key) => ListOmniFilterKeys[key as ListOmniFilterParam],
2021
);
2122

2223
return urlFilterValueKeys.reduce((accumulator, current) => {
@@ -88,13 +89,13 @@ export const useOmniFilterData = (): [
8889
(filterParam: ListOmniFilterParam, query: string | null) => void,
8990
] => {
9091
const dataQueries = {
91-
policy: useOmniFilterQuery(ListOmniFilterParam.policy),
92+
policy: useOmniFilterQuery(ListOmniFilterKeys.policy),
9293
source_namespace: useOmniFilterQuery(
93-
ListOmniFilterParam.source_namespace,
94+
ListOmniFilterKeys.source_namespace,
9495
),
95-
dest_namespace: useOmniFilterQuery(ListOmniFilterParam.dest_namespace),
96-
source_name: useOmniFilterQuery(ListOmniFilterParam.source_name),
97-
dest_name: useOmniFilterQuery(ListOmniFilterParam.dest_name),
96+
dest_namespace: useOmniFilterQuery(ListOmniFilterKeys.dest_namespace),
97+
source_name: useOmniFilterQuery(ListOmniFilterKeys.source_name),
98+
dest_name: useOmniFilterQuery(ListOmniFilterKeys.dest_name),
9899
};
99100

100101
const fetchData = (

whisker/src/icons/ArrowRightIcon.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { createIcon } from '@chakra-ui/icons';
22

3-
const CalicoCatIcon = createIcon({
3+
const ArrowRightIcon = createIcon({
44
displayName: 'ArrowRightIcon',
55
viewBox: '0 0 9 7',
66
path: (
77
<path d='M5.88672 0.515625L5.49609 0.90625C5.41797 1.00391 5.41797 1.14062 5.51562 1.23828L7.07812 2.74219H0.359375C0.222656 2.74219 0.125 2.85938 0.125 2.97656V3.52344C0.125 3.66016 0.222656 3.75781 0.359375 3.75781H7.07812L5.51562 5.28125C5.41797 5.37891 5.41797 5.51562 5.49609 5.61328L5.88672 6.00391C5.98438 6.08203 6.12109 6.08203 6.21875 6.00391L8.79688 3.42578C8.875 3.32812 8.875 3.19141 8.79688 3.09375L6.21875 0.515625C6.12109 0.4375 5.98438 0.4375 5.88672 0.515625Z' />
88
),
99
});
1010

11-
export default CalicoCatIcon;
11+
export default ArrowRightIcon;

0 commit comments

Comments
 (0)