Skip to content

Commit

Permalink
tech: migrate Tests and Test Suites slices to Zustand (#837)
Browse files Browse the repository at this point in the history
* tech: migrate Tests to Zustand store
   - replace Redux slice with Zustand store
* tech: migrate Test Suites to Zustand store
   - replace Redux slice with Zustand store
  • Loading branch information
rangoo94 authored Aug 18, 2023
1 parent 1ca4c27 commit c9371d0
Show file tree
Hide file tree
Showing 18 changed files with 152 additions and 241 deletions.
8 changes: 8 additions & 0 deletions src/AppRoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ import {useAppDispatch} from '@redux/hooks';
import {useApiEndpoint} from '@services/apiEndpoint';
import {useGetClusterConfigQuery} from '@services/config';

import {initializeTestSuitesStore} from '@store/testSuites';
import {initializeTestsStore} from '@store/tests';

import {useTelemetry, useTelemetryValue} from '@telemetry/hooks';

import anonymizeQueryString from '@utils/anonymizeQueryString';
Expand All @@ -47,6 +50,9 @@ const AppRoot: React.FC = () => {
const telemetry = useTelemetry();
const apiEndpoint = useApiEndpoint();

const [TestsProvider] = initializeTestsStore();
const [TestSuitesProvider] = initializeTestSuitesStore();

const {currentData: clusterConfig, refetch: refetchClusterConfig} = useGetClusterConfigQuery();

// Pause/resume telemetry based on the cluster settings
Expand Down Expand Up @@ -116,6 +122,8 @@ const AppRoot: React.FC = () => {
.append(DashboardContext.Provider, {value: dashboardValue})
.append(PermissionsProvider, {scope: permissionsScope, resolver: permissionsResolver})
.append(MainContext.Provider, {value: mainContextValue})
.append(TestsProvider, {})
.append(TestSuitesProvider, {})
.append(ModalHandler, {})
.append(ModalOutletProvider, {})
.render(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {StyledFiltersSection} from './EntityListContent.styled';

const EntityListContent: React.FC<EntityListBlueprint> = props => {
const {
itemKey,
pageTitle,
pageTitleAddon,
pageDescription: PageDescription,
Expand All @@ -53,7 +54,7 @@ const EntityListContent: React.FC<EntityListBlueprint> = props => {
const [isApplyingFilters, setIsApplyingFilters] = useState(false);
const [isLoadingNext, setIsLoadingNext] = useState(false);

const {dispatch, isClusterAvailable} = useContext(MainContext);
const {isClusterAvailable} = useContext(MainContext);
const {setModalConfig, setModalOpen} = useContext(ModalContext);
const apiEndpoint = useApiEndpoint();
const mayCreate = usePermission(Permissions.createEntity);
Expand All @@ -67,7 +68,7 @@ const EntityListContent: React.FC<EntityListBlueprint> = props => {
selector: searchParams.get('selector')?.split(',').filter(Boolean) ?? undefined,
});
if (!isEqual(filters, queryFilters)) {
dispatch(setQueryFilters(filters));
setQueryFilters(filters);
}
}, []);

Expand All @@ -92,12 +93,12 @@ const EntityListContent: React.FC<EntityListBlueprint> = props => {
}, [queryFilters]);

const resetFilters = () => {
dispatch(setQueryFilters(initialFiltersState));
setQueryFilters(initialFiltersState);
};

const onScrollBottom = () => {
setIsLoadingNext(true);
dispatch(setQueryFilters({...queryFilters, pageSize: queryFilters.pageSize + initialPageSize}));
setQueryFilters({...queryFilters, pageSize: queryFilters.pageSize + initialPageSize});
};

useEffect(() => {
Expand Down Expand Up @@ -159,7 +160,7 @@ const EntityListContent: React.FC<EntityListBlueprint> = props => {
</PageHeader>

<EntityGrid
itemKey="dataItem.name"
itemKey={itemKey}
maxColumns={2}
data={data}
Component={CardComponent}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import {useContext, useEffect, useState} from 'react';
import {useEffect, useState} from 'react';

import {FilterFilled} from '@ant-design/icons';

import {MainContext} from '@contexts';

import {Button, Input, Title} from '@custom-antd';

import usePressEnter from '@hooks/usePressEnter';
Expand All @@ -28,8 +26,6 @@ const defaultKeyValuePair: Entity = {
const LabelsFilter: React.FC<FilterProps> = props => {
const {setFilters, filters, isFiltersDisabled, width} = props;

const {dispatch} = useContext(MainContext);

const [isVisible, setVisibilityState] = useState(false);
const [labelsMapping, setLabelsMapping] = useState<EntityArray>([]);

Expand Down Expand Up @@ -133,14 +129,14 @@ const LabelsFilter: React.FC<FilterProps> = props => {
return;
}

dispatch(setFilters({...filters, selector: resultedFilters, pageSize: initialPageSize}));
setFilters({...filters, selector: resultedFilters, pageSize: initialPageSize});
onOpenChange(false);
};

const resetFilters = () => {
setLabelsMapping([defaultKeyValuePair]);
onOpenChange(false);
dispatch(setFilters({...filters, selector: [], pageSize: initialPageSize}));
setFilters({...filters, selector: [], pageSize: initialPageSize});
};

const menu = (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import {useCallback, useContext, useMemo, useState} from 'react';
import {useCallback, useMemo, useState} from 'react';

import {FilterFilled} from '@ant-design/icons';

import {capitalize} from 'lodash';

import {MainContext} from '@contexts';

import {FilterProps} from '@models/filters';

import {
Expand All @@ -26,8 +24,6 @@ const statusList = ['queued', 'running', 'passed', 'failed', 'aborted'];
const StatusFilter: React.FC<FilterProps> = props => {
const {filters, setFilters, isFiltersDisabled} = props;

const {dispatch} = useContext(MainContext);

const [isVisible, setVisibilityState] = useState(false);

const onOpenChange = (flag: boolean) => {
Expand All @@ -37,19 +33,17 @@ const StatusFilter: React.FC<FilterProps> = props => {
const handleClick = useCallback(
(status: string) => {
if (filters.status.includes(status)) {
dispatch(
setFilters({
...filters,
status: filters.status.filter((currentStatus: string) => {
return status !== currentStatus;
}),
})
);
setFilters({
...filters,
status: filters.status.filter((currentStatus: string) => {
return status !== currentStatus;
}),
});
} else {
dispatch(setFilters({...filters, status: [...filters.status, status], pageSize: initialPageSize}));
setFilters({...filters, status: [...filters.status, status], pageSize: initialPageSize});
}
},
[dispatch, setFilters, filters]
[setFilters, filters]
);

const renderedStatuses = useMemo(() => {
Expand All @@ -69,7 +63,7 @@ const StatusFilter: React.FC<FilterProps> = props => {
}, [filters.status, handleClick]);

const resetFilter = () => {
dispatch(setFilters({...filters, status: [], pageSize: initialPageSize}));
setFilters({...filters, status: [], pageSize: initialPageSize});
onOpenChange(false);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import {useContext, useEffect, useState} from 'react';
import {useEffect, useState} from 'react';
import {useDebounce} from 'react-use';

import {SearchOutlined} from '@ant-design/icons';
import {Input} from 'antd';

import {MainContext} from '@contexts';

import {FilterProps} from '@models/filters';

import {initialPageSize} from '@redux/initialState';
Expand All @@ -15,8 +13,6 @@ import Colors from '@styles/Colors';
const TextSearchFilter: React.FC<FilterProps> = props => {
const {filters, setFilters, isFiltersDisabled} = props;

const {dispatch} = useContext(MainContext);

const [inputValue, setInputValue] = useState(filters.textSearch);

const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
Expand All @@ -25,7 +21,7 @@ const TextSearchFilter: React.FC<FilterProps> = props => {

const [, cancel] = useDebounce(
() => {
dispatch(setFilters({...filters, textSearch: inputValue, pageSize: initialPageSize}));
setFilters({...filters, textSearch: inputValue, pageSize: initialPageSize});
},
300,
[inputValue]
Expand Down
10 changes: 5 additions & 5 deletions src/components/pages/TestSuites/TestSuitesList/TestSuiteCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {MainContext} from '@contexts';

import useInViewport from '@hooks/useInViewport';

import {TestSuiteWithExecutionRedux} from '@models/testSuite';
import {TestSuiteWithExecution} from '@models/testSuite';

import EntityGridItemPure, {Item} from '@molecules/EntityGrid/EntityGridItemPure';

Expand All @@ -13,26 +13,26 @@ import {useGetTestSuiteExecutionMetricsQuery} from '@services/testSuiteExecution
import {PollingIntervals} from '@utils/numbers';

export interface TestSuiteCardProps {
item: TestSuiteWithExecutionRedux;
item: TestSuiteWithExecution;
onClick: (item: Item) => void;
onAbort: (item: Item) => void;
}

const TestSuiteCard: FC<TestSuiteCardProps> = ({item: {dataItem, latestExecution}, onClick, onAbort}) => {
const TestSuiteCard: FC<TestSuiteCardProps> = ({item: {testSuite, latestExecution}, onClick, onAbort}) => {
const {isClusterAvailable} = useContext(MainContext);

const ref = useRef(null);
const isInViewport = useInViewport(ref);

const {data: metrics} = useGetTestSuiteExecutionMetricsQuery(
{id: dataItem.name, last: 7, limit: 13},
{id: testSuite.name, last: 7, limit: 13},
{skip: !isInViewport || !isClusterAvailable, pollingInterval: PollingIntervals.halfMin}
);

return (
<EntityGridItemPure
ref={ref}
item={dataItem}
item={testSuite}
latestExecution={latestExecution}
onClick={onClick}
onAbort={onAbort}
Expand Down
39 changes: 17 additions & 22 deletions src/components/pages/TestSuites/TestSuitesList/TestSuitesList.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {FC, useCallback, useContext, useEffect} from 'react';
import {FC, useCallback, useContext} from 'react';

import {MainContext} from '@contexts';
import {ModalConfig} from '@contexts/ModalContext';
Expand All @@ -13,17 +13,10 @@ import {EntityListContent} from '@organisms';

import {usePluginSlot} from '@plugins/hooks';

import {useAppSelector} from '@redux/hooks';
import {initialTestSuitesFiltersState} from '@redux/initialState';
import {
selectTestSuites,
selectTestSuitesFilters,
setTestSuites,
setTestSuitesFilters,
} from '@redux/reducers/testSuitesSlice';

import {useAbortAllTestSuiteExecutionsMutation, useGetTestSuitesQuery} from '@services/testSuites';

import {initialFilters, useTestSuitesField, useTestSuitesSync} from '@store/testSuites';

import {PollingIntervals} from '@utils/numbers';

import EmptyTestSuites from './EmptyTestSuites';
Expand All @@ -41,17 +34,18 @@ const createModal: ModalConfig = {
};

const TestSuitesList: FC = () => {
const {dispatch, isClusterAvailable} = useContext(MainContext);
const queryFilters = useAppSelector(selectTestSuitesFilters);

const {data, isLoading, isFetching} = useGetTestSuitesQuery(queryFilters || null, {
const {isClusterAvailable} = useContext(MainContext);
const [filters, setFilters] = useTestSuitesField('filters');

const {
data: testSuites,
isLoading,
isFetching,
} = useGetTestSuitesQuery(filters || null, {
pollingInterval: PollingIntervals.everySecond,
skip: !isClusterAvailable,
});

useEffect(() => {
dispatch(setTestSuites(data || []));
}, [data]);
useTestSuitesSync({testSuites});

const [abortAll] = useAbortAllTestSuiteExecutionsMutation();
const onItemClick = useDashboardNavigate((item: TestSuite) => `/test-suites/${item.name}`);
Expand All @@ -65,6 +59,7 @@ const TestSuitesList: FC = () => {

return (
<EntityListContent
itemKey="testSuite.name"
CardComponent={TestSuiteCard}
onItemClick={onItemClick}
onItemAbort={onItemAbort}
Expand All @@ -74,11 +69,11 @@ const TestSuitesList: FC = () => {
addEntityButtonText="Add a new test suite"
pageDescription={PageDescription}
emptyDataComponent={EmptyTestSuites}
initialFiltersState={initialTestSuitesFiltersState}
initialFiltersState={initialFilters}
dataTest="add-a-new-test-suite-btn"
queryFilters={queryFilters}
setQueryFilters={setTestSuitesFilters}
data={useAppSelector(selectTestSuites)}
queryFilters={filters}
setQueryFilters={setFilters}
data={testSuites}
isLoading={isLoading}
isFetching={isFetching}
createModalConfig={createModal}
Expand Down
10 changes: 5 additions & 5 deletions src/components/pages/Tests/TestsList/TestCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {MainContext} from '@contexts';

import useInViewport from '@hooks/useInViewport';

import {TestWithExecutionRedux} from '@models/test';
import {TestWithExecution} from '@models/test';

import EntityGridItemPure, {Item} from '@molecules/EntityGrid/EntityGridItemPure';

Expand All @@ -13,26 +13,26 @@ import {useGetTestExecutionMetricsQuery} from '@services/tests';
import {PollingIntervals} from '@utils/numbers';

export interface TestCardProps {
item: TestWithExecutionRedux;
item: TestWithExecution;
onClick: (item: Item) => void;
onAbort: (item: Item) => void;
}

const TestCard: FC<TestCardProps> = ({item: {dataItem, latestExecution}, onClick, onAbort}) => {
const TestCard: FC<TestCardProps> = ({item: {test, latestExecution}, onClick, onAbort}) => {
const {isClusterAvailable} = useContext(MainContext);

const ref = useRef(null);
const isInViewport = useInViewport(ref);

const {data: metrics} = useGetTestExecutionMetricsQuery(
{id: dataItem.name, last: 7, limit: 13},
{id: test.name, last: 7, limit: 13},
{skip: !isInViewport || !isClusterAvailable, pollingInterval: PollingIntervals.halfMin}
);

return (
<EntityGridItemPure
ref={ref}
item={dataItem}
item={test}
latestExecution={latestExecution}
onClick={onClick}
onAbort={onAbort}
Expand Down
Loading

0 comments on commit c9371d0

Please sign in to comment.