diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index b03577a69..0206ac75e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -43,6 +43,20 @@ jobs: cache: 'yarn' - uses: bahmutov/npm-install@v1 - run: yarn eslint:check + type-check: + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [16.x, 18.x] + steps: + - uses: actions/checkout@v3 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + cache: 'yarn' + - uses: bahmutov/npm-install@v1 + - run: yarn type-check test: runs-on: ubuntu-latest strategy: diff --git a/locales/en/common.json b/locales/en/common.json index 40b0b737b..8034aa683 100644 --- a/locales/en/common.json +++ b/locales/en/common.json @@ -22,6 +22,7 @@ "DOWNLOAD": "Download", "EDIT": "Edit", "FILTER_NAME": "Name", + "FILTER_TOPIC": "Topic", "HELP": "Help", "HOUR": "Hour", "HOUR_one": "Hour", diff --git a/package.json b/package.json index 2249b52bb..477328359 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "itest": "wait-on -lt 60000 http://localhost:9091 && jest --testMatch='**/itest/**/*.test.(ts|tsx)'", "license:check": "license-check-and-add check -f license-config.json", "license:apply": "license-check-and-add add -f license-config.json", - "lint": "concurrently -c 'auto' 'yarn:format' 'yarn:eslint'", + "lint": "concurrently -c 'auto' 'yarn:format' 'yarn:eslint' 'yarn:type-check'", "localize": "i18next \"src/**/*.{js,jsx,ts,tsx,json}\" -c ./i18next-parser.config.js", "format": "yarn format:check", "format:check": "concurrently -c 'auto' 'yarn:license:check' 'yarn:prettier:check'", @@ -33,7 +33,8 @@ "build:bundle-analyze": "webpack-bundle-analyzer ./stats.json dist", "build:bundle-profile-analyze": "concurrently -c 'auto' 'yarn:build:bundle-*'", "yarn:install": "yarn install", - "yarn:frzinstall": "yarn install --immutable" + "yarn:frzinstall": "yarn install --immutable", + "type-check": "tsc --noEmit" }, "devDependencies": { "@testing-library/dom": "^9.3.1", diff --git a/src/app/Dashboard/AutomatedAnalysis/AutomatedAnalysisCard.tsx b/src/app/Dashboard/AutomatedAnalysis/AutomatedAnalysisCard.tsx index f3dac704a..57b6f4cb4 100644 --- a/src/app/Dashboard/AutomatedAnalysis/AutomatedAnalysisCard.tsx +++ b/src/app/Dashboard/AutomatedAnalysis/AutomatedAnalysisCard.tsx @@ -144,14 +144,14 @@ export const AutomatedAnalysisCard: DashboardCardFC const [showListView, setShowListView] = React.useState(false); const targetAutomatedAnalysisFilters = useSelector((state: RootState) => { - const filters = state.automatedAnalysisFilters.state.targetFilters.filter( + const filters = state.automatedAnalysisFilters.targetFilters.filter( (targetFilter: TargetAutomatedAnalysisFilters) => targetFilter.target === targetConnectURL ); return filters.length > 0 ? filters[0].filters : emptyAutomatedAnalysisFilters; }) as AutomatedAnalysisFiltersCategories; const targetAutomatedAnalysisGlobalFilters = useSelector((state: RootState) => { - return state.automatedAnalysisFilters.state.globalFilters.filters; + return state.automatedAnalysisFilters.globalFilters.filters; }) as AutomatedAnalysisGlobalFiltersCategories; const categorizeEvaluation = React.useCallback( diff --git a/src/app/Dashboard/AutomatedAnalysis/AutomatedAnalysisFilters.tsx b/src/app/Dashboard/AutomatedAnalysis/AutomatedAnalysisFilters.tsx index c0294967a..e60d73737 100644 --- a/src/app/Dashboard/AutomatedAnalysis/AutomatedAnalysisFilters.tsx +++ b/src/app/Dashboard/AutomatedAnalysis/AutomatedAnalysisFilters.tsx @@ -51,16 +51,22 @@ export interface AutomatedAnalysisFiltersProps { updateFilters: (target: string, updateFilterOptions: UpdateFilterOptions) => void; } -export const AutomatedAnalysisFilters: React.FC = ({ updateFilters, ...props }) => { +export const AutomatedAnalysisFilters: React.FC = ({ + updateFilters, + target, + evaluations, + filters, + ..._props +}) => { const dispatch = useDispatch(); const { t } = useTranslation(); const currentCategory = useSelector((state: RootState) => { - const targetAutomatedAnalysisFilters = state.automatedAnalysisFilters.state.targetFilters.filter( - (targetFilter) => targetFilter.target === props.target + const targetAutomatedAnalysisFilters = state.automatedAnalysisFilters.targetFilters.filter( + (targetFilter) => targetFilter.target === target ); if (!targetAutomatedAnalysisFilters.length) { - return t('FILTER_NAME', { ns: 'common' }); + return 'Name'; } // Target is not yet loaded return targetAutomatedAnalysisFilters[0].selectedCategory; }); @@ -74,33 +80,47 @@ export const AutomatedAnalysisFilters: React.FC = const onCategorySelect = React.useCallback( (category) => { setIsCategoryDropdownOpen(false); - dispatch(automatedAnalysisUpdateCategoryIntent(props.target, category)); + dispatch(automatedAnalysisUpdateCategoryIntent(target, category)); }, - [dispatch, setIsCategoryDropdownOpen, props.target] + [dispatch, setIsCategoryDropdownOpen, target] ); const onDelete = React.useCallback( (category: string | ToolbarChipGroup, value) => - updateFilters(props.target, { filterKey: category as string, filterValue: value, deleted: true }), - [updateFilters, props.target] + updateFilters(target, { filterKey: category as string, filterValue: value, deleted: true }), + [updateFilters, target] ); const onDeleteGroup = React.useCallback( (category: string | ToolbarChipGroup) => - updateFilters(props.target, { filterKey: category as string, deleted: true, deleteOptions: { all: true } }), - [updateFilters, props.target] + updateFilters(target, { filterKey: category as string, deleted: true, deleteOptions: { all: true } }), + [updateFilters, target] ); const onNameInput = React.useCallback( - (inputName: string) => updateFilters(props.target, { filterKey: currentCategory, filterValue: inputName }), - [updateFilters, currentCategory, props.target] + (inputName: string) => updateFilters(target, { filterKey: currentCategory, filterValue: inputName }), + [updateFilters, currentCategory, target] ); const onTopicInput = React.useCallback( (inputTopic: string) => { - updateFilters(props.target, { filterKey: currentCategory, filterValue: inputTopic }); + updateFilters(target, { filterKey: currentCategory, filterValue: inputTopic }); }, - [updateFilters, currentCategory, props.target] + [updateFilters, currentCategory, target] + ); + + const getCategoryDisplay = React.useCallback( + (category: string) => { + switch (category) { + case 'Name': + return t('FILTER_NAME', { ns: 'common' }); + case 'Topic': + return t('FILTER_TOPIC', { ns: 'common' }); + default: + throw new Error(`Unknown Automated Analysis Filter Category: ${category}`); + } + }, + [t] ); const categoryDropdown = React.useMemo(() => { @@ -110,7 +130,7 @@ export const AutomatedAnalysisFilters: React.FC = position={DropdownPosition.left} toggle={ - {currentCategory} + {getCategoryDisplay(currentCategory)} } isOpen={isCategoryDropdownOpen} @@ -121,24 +141,24 @@ export const AutomatedAnalysisFilters: React.FC = ))} /> ); - }, [isCategoryDropdownOpen, currentCategory, onCategoryToggle, onCategorySelect]); + }, [isCategoryDropdownOpen, currentCategory, onCategoryToggle, onCategorySelect, getCategoryDisplay]); const filterDropdownItems = React.useMemo( () => [ , , + />, ], - [props.evaluations, props.filters.Name, props.filters.Topic, onNameInput, onTopicInput] + [evaluations, filters.Name, filters.Topic, onNameInput, onTopicInput] ); return ( @@ -146,12 +166,12 @@ export const AutomatedAnalysisFilters: React.FC = {categoryDropdown} - {Object.keys(props.filters) + {Object.keys(filters) .filter((f) => f !== 'Score') .map((filterKey, i) => ( (); const { t } = useTranslation(); const currentScore = useSelector((state: RootState) => { - const filters = state.automatedAnalysisFilters.state.globalFilters.filters; + const filters = state.automatedAnalysisFilters.globalFilters.filters; if (!filters) return 0; return filters.Score; }); diff --git a/src/app/Dashboard/Dashboard.tsx b/src/app/Dashboard/Dashboard.tsx index 370d6b322..1f1de0dbc 100644 --- a/src/app/Dashboard/Dashboard.tsx +++ b/src/app/Dashboard/Dashboard.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ import { FeatureFlag } from '@app/Shared/FeatureFlag/FeatureFlag'; -import { DashboardConfigState } from '@app/Shared/Redux/Configurations/DashboardConfigSlice'; +import { DashboardConfig } from '@app/Shared/Redux/Configurations/DashboardConfigSlice'; import { dashboardConfigDeleteCardIntent, dashboardConfigFirstRunIntent, @@ -47,7 +47,7 @@ export const Dashboard: React.FC = (_) => { const serviceContext = React.useContext(ServiceContext); const dispatch = useDispatch(); const { t } = useTranslation(); - const dashboardConfigs: DashboardConfigState = useSelector((state: RootState) => state.dashboardConfigs); + const dashboardConfigs: DashboardConfig = useSelector((state: RootState) => state.dashboardConfigs); const jfrChartController = React.useRef( new JFRMetricsChartController( serviceContext.api, @@ -65,7 +65,7 @@ export const Dashboard: React.FC = (_) => { }, [dashboardConfigs]); React.useEffect(() => { - const layouts = getFromLocalStorage('DASHBOARD_CFG', {}) as DashboardConfigState; + const layouts = getFromLocalStorage('DASHBOARD_CFG', {}) as DashboardConfig; if (layouts._version === undefined) { dispatch(dashboardConfigFirstRunIntent()); } diff --git a/src/app/Recordings/RecordingFilters.tsx b/src/app/Recordings/RecordingFilters.tsx index dd683544c..3d08d3eef 100644 --- a/src/app/Recordings/RecordingFilters.tsx +++ b/src/app/Recordings/RecordingFilters.tsx @@ -64,7 +64,7 @@ export const categoryIsDate = (fieldKey: string) => /date/i.test(fieldKey); export interface RecordingFiltersProps { target: string; - breakpoint: 'md' | 'lg' | 'xl' | '2xl'; + breakpoint?: 'md' | 'lg' | 'xl' | '2xl'; isArchived: boolean; recordings: Recording[]; filters: RecordingFiltersCategories; diff --git a/src/app/Settings/Language.tsx b/src/app/Settings/Language.tsx index 7a70f2cdc..2209deaee 100644 --- a/src/app/Settings/Language.tsx +++ b/src/app/Settings/Language.tsx @@ -47,7 +47,7 @@ const Component = () => { aria-label={t('SETTINGS.LANGUAGE.ARIA_LABELS.SELECT') || ''} onToggle={handleLanguageToggle} onSelect={handleLanguageSelect} - selections={localeReadable(i18n.language)} + selections={i18n.language} isFlipEnabled menuAppendTo="parent" > diff --git a/src/app/Settings/SettingsUtils.ts b/src/app/Settings/SettingsUtils.ts index 0b830d193..48d65db94 100644 --- a/src/app/Settings/SettingsUtils.ts +++ b/src/app/Settings/SettingsUtils.ts @@ -19,7 +19,7 @@ import { hashCode } from '@app/utils/utils'; export interface _TransformedUserSetting extends Omit { title: string; description: React.ReactNode; - element: React.FC>; + element: React.ReactNode; orderInGroup: number; featureLevel: FeatureLevel; } diff --git a/src/app/Shared/Redux/Configurations/DashboardConfigSlice.tsx b/src/app/Shared/Redux/Configurations/DashboardConfigSlice.tsx index ec0781f08..107a0c4f4 100644 --- a/src/app/Shared/Redux/Configurations/DashboardConfigSlice.tsx +++ b/src/app/Shared/Redux/Configurations/DashboardConfigSlice.tsx @@ -26,7 +26,7 @@ import { gridSpans } from '@patternfly/react-core'; import { createAction, createReducer } from '@reduxjs/toolkit'; import { getPersistedState } from '../utils'; -export const _dashboardConfigVersion = '4'; +export const _version = '4'; // Common action string format: "resource(s)/action" export enum DashboardConfigAction { @@ -231,7 +231,7 @@ export const dashboardConfigTemplateHistoryClearIntent = createAction( }) ); -export interface DashboardConfigState { +export interface DashboardConfig { layouts: DashboardLayout[]; customTemplates: LayoutTemplate[]; templateHistory: LayoutTemplateRecord[]; @@ -241,20 +241,23 @@ export interface DashboardConfigState { export const TEMPLATE_HISTORY_LIMIT = 5; -const INITIAL_STATE: DashboardConfigState = getPersistedState('DASHBOARD_CFG', _dashboardConfigVersion, { +export const defaultDashboardConfigs: DashboardConfig = { layouts: [ { name: 'Default', cards: [], favorite: true, }, - ] as DashboardLayout[], - customTemplates: [] as LayoutTemplate[], - templateHistory: [] as LayoutTemplateRecord[], + ], + customTemplates: [], + templateHistory: [], current: 0, -}); + _version: _version, +}; + +const INITIAL_STATE: DashboardConfig = getPersistedState('DASHBOARD_CFG', _version, defaultDashboardConfigs); -const getTemplateHistoryIndexForMutation = (state: DashboardConfigState, templateName: string) => { +const getTemplateHistoryIndexForMutation = (state: DashboardConfig, templateName: string) => { const idx = state.templateHistory.findIndex((t) => t.name === templateName && t.vendor === LayoutTemplateVendor.USER); return idx; }; diff --git a/src/app/Shared/Redux/Configurations/TopologyConfigSlice.tsx b/src/app/Shared/Redux/Configurations/TopologyConfigSlice.tsx index c62e96f62..eabcf5e1e 100644 --- a/src/app/Shared/Redux/Configurations/TopologyConfigSlice.tsx +++ b/src/app/Shared/Redux/Configurations/TopologyConfigSlice.tsx @@ -80,31 +80,33 @@ export interface TopologyConfig { displayOptions: DisplayOptions; } -export const defaultDisplayOptions: DisplayOptions = { - show: { - connectionUrl: false, - badge: true, - status: true, - icon: true, - }, - groupings: { - realmOnly: false, - collapseSingles: false, +export const defaultTopologyConfig: TopologyConfig = { + viewMode: 'graph', + displayOptions: { + show: { + connectionUrl: false, + badge: true, + status: true, + icon: true, + }, + groupings: { + realmOnly: false, + collapseSingles: false, + }, }, }; -export const showOptions: [string, string][] = Object.keys(defaultDisplayOptions.show).map((k) => { +export const showOptions: [string, string][] = Object.keys(defaultTopologyConfig.displayOptions.show).map((k) => { return [getDisplayFieldName(k), k]; }); -export const groupingOptions: [string, string][] = Object.keys(defaultDisplayOptions.groupings).map((k) => { - return [getDisplayFieldName(k), k]; -}); +export const groupingOptions: [string, string][] = Object.keys(defaultTopologyConfig.displayOptions.groupings).map( + (k) => { + return [getDisplayFieldName(k), k]; + } +); -const INITIAL_STATE: TopologyConfig = getPersistedState('TOPOLOGY_CONFIG', _version, { - viewMode: 'graph', - displayOptions: defaultDisplayOptions, -}); +const INITIAL_STATE: TopologyConfig = getPersistedState('TOPOLOGY_CONFIG', _version, defaultTopologyConfig); export const topologyConfigReducer: ReducerWithInitialState = createReducer( INITIAL_STATE, diff --git a/src/app/Shared/Redux/Filters/AutomatedAnalysisFilterSlice.tsx b/src/app/Shared/Redux/Filters/AutomatedAnalysisFilterSlice.tsx index 204741a5e..899c2f69c 100644 --- a/src/app/Shared/Redux/Filters/AutomatedAnalysisFilterSlice.tsx +++ b/src/app/Shared/Redux/Filters/AutomatedAnalysisFilterSlice.tsx @@ -23,7 +23,7 @@ import { WritableDraft } from 'immer/dist/internal'; import { getPersistedState } from '../utils'; import { UpdateFilterOptions } from './Common'; -const _version = '1'; +const _version = '2'; // Common action string format: "resource(s)/action" export enum AutomatedAnalysisFilterAction { @@ -48,7 +48,7 @@ export const allowedAutomatedAnalysisFilters = Object.keys(emptyAutomatedAnalysi export interface AutomatedAnalysisFilterActionPayload { target: string; - category?: string; + category: string; filter?: unknown; } @@ -99,7 +99,7 @@ export const automatedAnalysisDeleteAllFiltersIntent = createAction( (target: string) => ({ payload: { target: target, - } as AutomatedAnalysisFilterActionPayload, + } as Pick, }) ); @@ -109,7 +109,7 @@ export const automatedAnalysisUpdateCategoryIntent = createAction( payload: { target: target, category: category, - } as AutomatedAnalysisFilterActionPayload, + } as Pick, }) ); @@ -118,7 +118,7 @@ export const automatedAnalysisAddTargetIntent = createAction( (target: string) => ({ payload: { target: target, - } as AutomatedAnalysisFilterActionPayload, + } as Pick, }) ); @@ -127,20 +127,21 @@ export const automatedAnalysisDeleteTargetIntent = createAction( (target: string) => ({ payload: { target: target, - } as AutomatedAnalysisFilterActionPayload, + } as Pick, }) ); -export interface AutomatedAnalysisFilterState { +export interface AutomatedAnalysisFilters { targetFilters: TargetAutomatedAnalysisFilters[]; globalFilters: TargetAutomatedAnalysisGlobalFilters; + readonly _version: string; } export interface TargetAutomatedAnalysisGlobalFilters { filters: AutomatedAnalysisGlobalFiltersCategories; } export interface TargetAutomatedAnalysisFilters { target: string; // connectURL - selectedCategory?: string; + selectedCategory: string; filters: AutomatedAnalysisFiltersCategories; } @@ -208,18 +209,19 @@ export const deleteAllAutomatedAnalysisFilters = (automatedAnalysisFilter: Targe }; }; -const INITIAL_STATE = getPersistedState('AUTOMATED_ANALYSIS_FILTERS', _version, { - state: { - targetFilters: [], - globalFilters: { filters: { Score: 0 } }, - } as AutomatedAnalysisFilterState, -}); +export const defaultAutomatedAnalysisFilters: AutomatedAnalysisFilters = { + targetFilters: [], + globalFilters: { filters: { Score: 0 } }, + _version: _version, +}; + +const INITIAL_STATE = getPersistedState('AUTOMATED_ANALYSIS_FILTERS', _version, defaultAutomatedAnalysisFilters); export const automatedAnalysisFilterReducer = createReducer(INITIAL_STATE, (builder) => { builder .addCase(automatedAnalysisAddGlobalFilterIntent, (state, { payload }) => { - const oldAutomatedAnalysisGlobalFilter = getAutomatedAnalysisGlobalFilter(state.state); - state.state.globalFilters = { + const oldAutomatedAnalysisGlobalFilter = getAutomatedAnalysisGlobalFilter(state); + state.globalFilters = { filters: createOrUpdateAutomatedAnalysisGlobalFilter(oldAutomatedAnalysisGlobalFilter.filters, { filterKey: payload.category, filterValue: payload.filter, @@ -227,7 +229,7 @@ export const automatedAnalysisFilterReducer = createReducer(INITIAL_STATE, (buil }; }) .addCase(automatedAnalysisAddFilterIntent, (state, { payload }) => { - const oldAutomatedAnalysisFilter = getAutomatedAnalysisFilter(state.state, payload.target); + const oldAutomatedAnalysisFilter = getAutomatedAnalysisFilter(state, payload.target); const newAutomatedAnalysisFilter: TargetAutomatedAnalysisFilters = { ...oldAutomatedAnalysisFilter, selectedCategory: payload.category, @@ -236,13 +238,13 @@ export const automatedAnalysisFilterReducer = createReducer(INITIAL_STATE, (buil filterValue: payload.filter, }), }; - state.state.targetFilters = state.state.targetFilters.filter( + state.targetFilters = state.targetFilters.filter( (targetFilters) => targetFilters.target !== newAutomatedAnalysisFilter.target ); - state.state.targetFilters.push(newAutomatedAnalysisFilter); + state.targetFilters.push(newAutomatedAnalysisFilter); }) .addCase(automatedAnalysisDeleteFilterIntent, (state, { payload }) => { - const oldAutomatedAnalysisFilter = getAutomatedAnalysisFilter(state.state, payload.target); + const oldAutomatedAnalysisFilter = getAutomatedAnalysisFilter(state, payload.target); const newAutomatedAnalysisFilter: TargetAutomatedAnalysisFilters = { ...oldAutomatedAnalysisFilter, @@ -254,13 +256,13 @@ export const automatedAnalysisFilterReducer = createReducer(INITIAL_STATE, (buil }), }; - state.state.targetFilters = state.state.targetFilters.filter( + state.targetFilters = state.targetFilters.filter( (targetFilters) => targetFilters.target !== newAutomatedAnalysisFilter.target ); - state.state.targetFilters.push(newAutomatedAnalysisFilter); + state.targetFilters.push(newAutomatedAnalysisFilter); }) .addCase(automatedAnalysisDeleteCategoryFiltersIntent, (state, { payload }) => { - const oldAutomatedAnalysisFilter = getAutomatedAnalysisFilter(state.state, payload.target); + const oldAutomatedAnalysisFilter = getAutomatedAnalysisFilter(state, payload.target); const newAutomatedAnalysisFilter: TargetAutomatedAnalysisFilters = { ...oldAutomatedAnalysisFilter, @@ -271,41 +273,37 @@ export const automatedAnalysisFilterReducer = createReducer(INITIAL_STATE, (buil deleteOptions: { all: true }, }), }; - state.state.targetFilters = state.state.targetFilters.filter( + state.targetFilters = state.targetFilters.filter( (targetFilters) => targetFilters.target !== newAutomatedAnalysisFilter.target ); - state.state.targetFilters.push(newAutomatedAnalysisFilter); + state.targetFilters.push(newAutomatedAnalysisFilter); }) .addCase(automatedAnalysisDeleteAllFiltersIntent, (state, { payload }) => { - const oldAutomatedAnalysisFilter = getAutomatedAnalysisFilter(state.state, payload.target); + const oldAutomatedAnalysisFilter = getAutomatedAnalysisFilter(state, payload.target); const newAutomatedAnalysisFilter = deleteAllAutomatedAnalysisFilters(oldAutomatedAnalysisFilter); - state.state.targetFilters = state.state.targetFilters.filter( + state.targetFilters = state.targetFilters.filter( (targetFilters) => targetFilters.target !== newAutomatedAnalysisFilter.target ); - state.state.targetFilters.push(newAutomatedAnalysisFilter); + state.targetFilters.push(newAutomatedAnalysisFilter); }) .addCase(automatedAnalysisUpdateCategoryIntent, (state, { payload }) => { - const oldAutomatedAnalysisFilter = getAutomatedAnalysisFilter(state.state, payload.target); + const oldAutomatedAnalysisFilter = getAutomatedAnalysisFilter(state, payload.target); const newAutomatedAnalysisFilter = { ...oldAutomatedAnalysisFilter }; newAutomatedAnalysisFilter.selectedCategory = payload.category; - state.state.targetFilters = state.state.targetFilters.filter( + state.targetFilters = state.targetFilters.filter( (targetFilters) => targetFilters.target !== newAutomatedAnalysisFilter.target ); - state.state.targetFilters.push(newAutomatedAnalysisFilter); + state.targetFilters.push(newAutomatedAnalysisFilter); }) .addCase(automatedAnalysisAddTargetIntent, (state, { payload }) => { - const AutomatedAnalysisFilter = getAutomatedAnalysisFilter(state.state, payload.target); - state.state.targetFilters = state.state.targetFilters.filter( - (targetFilters) => targetFilters.target !== payload.target - ); - state.state.targetFilters.push(AutomatedAnalysisFilter); + const AutomatedAnalysisFilter = getAutomatedAnalysisFilter(state, payload.target); + state.targetFilters = state.targetFilters.filter((targetFilters) => targetFilters.target !== payload.target); + state.targetFilters.push(AutomatedAnalysisFilter); }) .addCase(automatedAnalysisDeleteTargetIntent, (state, { payload }) => { - state.state.targetFilters = state.state.targetFilters.filter( - (targetFilters) => targetFilters.target !== payload.target - ); + state.targetFilters = state.targetFilters.filter((targetFilters) => targetFilters.target !== payload.target); }); }); diff --git a/src/app/Shared/Redux/Filters/RecordingFilterSlice.tsx b/src/app/Shared/Redux/Filters/RecordingFilterSlice.tsx index b7e4b8225..a1ccdaff9 100644 --- a/src/app/Shared/Redux/Filters/RecordingFilterSlice.tsx +++ b/src/app/Shared/Redux/Filters/RecordingFilterSlice.tsx @@ -55,7 +55,7 @@ export const allowedArchivedRecordingFilters = Object.keys(emptyArchivedRecordin export interface RecordingFilterActionPayload { target: string; - category?: string; + category: string; filter?: unknown; isArchived?: boolean; } @@ -101,7 +101,7 @@ export const recordingDeleteAllFiltersIntent = createAction( payload: { target: target, isArchived: isArchived, - } as RecordingFilterActionPayload, + } as Pick, }) ); @@ -119,25 +119,25 @@ export const recordingUpdateCategoryIntent = createAction( export const recordingAddTargetIntent = createAction(RecordingFilterAction.TARGET_ADD, (target: string) => ({ payload: { target: target, - } as RecordingFilterActionPayload, + } as Pick, })); export const recordingDeleteTargetIntent = createAction(RecordingFilterAction.TARGET_DELETE, (target: string) => ({ payload: { target: target, - } as RecordingFilterActionPayload, + } as Pick, })); export interface TargetRecordingFilters { target: string; // connectURL active: { // active recordings - selectedCategory?: string; + selectedCategory: string; filters: RecordingFiltersCategories; }; archived: { // archived recordings - selectedCategory?: string; + selectedCategory: string; filters: RecordingFiltersCategories; }; } @@ -207,9 +207,17 @@ export const deleteAllTargetRecordingFilters = (targetRecordingFilter: TargetRec }; }; -const INITIAL_STATE = getPersistedState('TARGET_RECORDING_FILTERS', _version, { +export interface RecordingFilters { + list: TargetRecordingFilters[]; + readonly _version: string; +} + +export const defaultRecordingFilters: RecordingFilters = { list: [] as TargetRecordingFilters[], -}); + _version: _version, +}; + +const INITIAL_STATE = getPersistedState('TARGET_RECORDING_FILTERS', _version, defaultRecordingFilters); export const recordingFilterReducer = createReducer(INITIAL_STATE, (builder) => { builder diff --git a/src/app/Shared/Redux/ReduxStore.tsx b/src/app/Shared/Redux/ReduxStore.tsx index f54853f02..d348d7c40 100644 --- a/src/app/Shared/Redux/ReduxStore.tsx +++ b/src/app/Shared/Redux/ReduxStore.tsx @@ -38,6 +38,7 @@ export const { dashboardConfigDeleteTemplateIntent, dashboardConfigTemplateHistoryPushIntent, dashboardConfigTemplateHistoryClearIntent, + defaultDashboardConfigs, } = dashboardConfigSlice; export const { recordingAddFilterIntent, @@ -47,6 +48,7 @@ export const { recordingDeleteCategoryFiltersIntent, recordingUpdateCategoryIntent, recordingDeleteAllFiltersIntent, + defaultRecordingFilters, } = recordingFilterSlice; export const { automatedAnalysisAddGlobalFilterIntent, @@ -57,9 +59,11 @@ export const { automatedAnalysisDeleteFilterIntent, automatedAnalysisDeleteTargetIntent, automatedAnalysisUpdateCategoryIntent, + defaultAutomatedAnalysisFilters, } = automatedAnalysisFilterSlice; -export const { topologyConfigSetViewModeIntent, topologyDisplayOptionsSetIntent } = topologyConfigSlice; +export const { topologyConfigSetViewModeIntent, topologyDisplayOptionsSetIntent, defaultTopologyConfig } = + topologyConfigSlice; export const { topologyUpdateCategoryTypeIntent, @@ -68,6 +72,7 @@ export const { topologyDeleteAllFiltersIntent, topologyDeleteCategoryFiltersIntent, topologyDeleteFilterIntent, + defaultTopologyFilters, } = topologyFilterSlice; export const rootReducer = combineReducers({ diff --git a/src/app/Shared/Redux/utils.tsx b/src/app/Shared/Redux/utils.ts similarity index 83% rename from src/app/Shared/Redux/utils.tsx rename to src/app/Shared/Redux/utils.ts index d2cb17535..79ebedf5f 100644 --- a/src/app/Shared/Redux/utils.tsx +++ b/src/app/Shared/Redux/utils.ts @@ -16,8 +16,7 @@ import { getFromLocalStorage, LocalStorageKeyStrings } from '@app/utils/LocalStorage'; -/* eslint-disable-next-line @typescript-eslint/no-explicit-any */ -export const getPersistedState = (key: LocalStorageKeyStrings, _version: string, defaultConfig: any): any => { +export const getPersistedState = (key: LocalStorageKeyStrings, _version: string, defaultConfig: T): T => { const persisted = getFromLocalStorage(key, undefined); if (!persisted || persisted._version !== _version) { return { diff --git a/src/app/Topology/Shared/utils.tsx b/src/app/Topology/Shared/utils.tsx index 1117da9fd..9274600e9 100644 --- a/src/app/Topology/Shared/utils.tsx +++ b/src/app/Topology/Shared/utils.tsx @@ -214,7 +214,9 @@ export class SearchExprService { searchExpression({ debounceMs = DEFAULT_MATCH_EXPR_DEBOUNCE_TIME, - immediateFn = (_: string) => undefined, + immediateFn = (_: string) => { + /* do nothing */ + }, } = {}): Observable { return this._state$.asObservable().pipe(tap(immediateFn), debounceTime(debounceMs)); } diff --git a/src/test/Common.tsx b/src/test/Common.tsx index 39a44226f..fa74b75a6 100644 --- a/src/test/Common.tsx +++ b/src/test/Common.tsx @@ -15,7 +15,15 @@ */ import { NotificationsContext, NotificationsInstance } from '@app/Notifications/Notifications'; -import { setupStore } from '@app/Shared/Redux/ReduxStore'; +import { + defaultAutomatedAnalysisFilters, + defaultDashboardConfigs, + defaultRecordingFilters, + defaultTopologyConfig, + defaultTopologyFilters, + RootState, + setupStore, +} from '@app/Shared/Redux/ReduxStore'; import { defaultServices, ServiceContext } from '@app/Shared/Services/Services'; import { render } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; @@ -25,6 +33,7 @@ import React, { PropsWithChildren } from 'react'; import '@i18n/config'; import { Provider } from 'react-redux'; import { Router } from 'react-router-dom'; + // userEvent functions are recommended to be called in tests (i.e it()). // See https://testing-library.com/docs/user-event/intro#writing-tests-with-userevent @@ -229,3 +238,11 @@ export const mockMediaQueryList: MediaQueryList = { removeEventListener: jest.fn(), dispatchEvent: jest.fn(), }; + +export const basePreloadedState: RootState = { + dashboardConfigs: defaultDashboardConfigs, + recordingFilters: defaultRecordingFilters, + automatedAnalysisFilters: defaultAutomatedAnalysisFilters, + topologyConfigs: defaultTopologyConfig, + topologyFilters: defaultTopologyFilters, +}; diff --git a/src/test/Dashboard/AutomatedAnalysis/AutomatedAnalysisCard.test.tsx b/src/test/Dashboard/AutomatedAnalysis/AutomatedAnalysisCard.test.tsx index f81d2a712..1b257c208 100644 --- a/src/test/Dashboard/AutomatedAnalysis/AutomatedAnalysisCard.test.tsx +++ b/src/test/Dashboard/AutomatedAnalysis/AutomatedAnalysisCard.test.tsx @@ -14,15 +14,6 @@ * limitations under the License. */ import { AutomatedAnalysisCard } from '@app/Dashboard/AutomatedAnalysis/AutomatedAnalysisCard'; -import { LayoutTemplate, LayoutTemplateRecord } from '@app/Dashboard/dashboard-utils'; -import { DashboardConfigState } from '@app/Shared/Redux/Configurations/DashboardConfigSlice'; -import { TopologyConfig } from '@app/Shared/Redux/Configurations/TopologyConfigSlice'; -import { - emptyActiveRecordingFilters, - emptyArchivedRecordingFilters, - TargetRecordingFilters, -} from '@app/Shared/Redux/Filters/RecordingFilterSlice'; -import { TopologyFilters } from '@app/Shared/Redux/Filters/TopologyFilterSlice'; import { RootState } from '@app/Shared/Redux/ReduxStore'; import { ArchivedRecording, @@ -41,7 +32,7 @@ import '@testing-library/jest-dom'; import { cleanup, screen, waitFor } from '@testing-library/react'; import * as React from 'react'; import { of } from 'rxjs'; -import { renderWithServiceContextAndReduxStore, testT } from '../../Common'; +import { basePreloadedState, renderWithServiceContextAndReduxStore, testT } from '../../Common'; jest.mock('@app/Dashboard/AutomatedAnalysis/AutomatedAnalysisCardList', () => { return { @@ -167,46 +158,16 @@ describe('', () => { beforeEach(() => { preloadedState = { - dashboardConfigs: { - layouts: [ - { - name: 'Default', - cards: [], - favorite: false, - }, - ], - current: 0, - _version: '0', - customTemplates: [] as LayoutTemplate[], - templateHistory: [] as LayoutTemplateRecord[], - } as DashboardConfigState, - recordingFilters: { - list: [ - { - target: mockTarget.connectUrl, - active: { - selectedCategory: 'Labels', - filters: emptyActiveRecordingFilters, - }, - archived: { - selectedCategory: 'Name', - filters: emptyArchivedRecordingFilters, - }, - } as TargetRecordingFilters, - ], - }, + ...basePreloadedState, automatedAnalysisFilters: { - state: { - targetFilters: [], - globalFilters: { - filters: { - Score: 100, - }, + targetFilters: [], + globalFilters: { + filters: { + Score: 100, }, }, + _version: '0', }, - topologyConfigs: {} as TopologyConfig, - topologyFilters: {} as TopologyFilters, }; }); @@ -364,12 +325,10 @@ describe('', () => { const newPreloadedState = { ...preloadedState, automatedAnalysisFilters: { - state: { - targetFilters: [], - globalFilters: { - filters: { - Score: 0, - }, + targetFilters: [], + globalFilters: { + filters: { + Score: 0, }, }, }, diff --git a/src/test/Dashboard/AutomatedAnalysis/Filters/AutomatedAnalysisScoreFilter.test.tsx b/src/test/Dashboard/AutomatedAnalysis/Filters/AutomatedAnalysisScoreFilter.test.tsx index 2e13feefa..73b0bad85 100644 --- a/src/test/Dashboard/AutomatedAnalysis/Filters/AutomatedAnalysisScoreFilter.test.tsx +++ b/src/test/Dashboard/AutomatedAnalysis/Filters/AutomatedAnalysisScoreFilter.test.tsx @@ -15,52 +15,28 @@ */ import { AutomatedAnalysisScoreFilter } from '@app/Dashboard/AutomatedAnalysis/Filters/AutomatedAnalysisScoreFilter'; -import { - emptyActiveRecordingFilters, - emptyArchivedRecordingFilters, - TargetRecordingFilters, -} from '@app/Shared/Redux/Filters/RecordingFilterSlice'; + import { RootState } from '@app/Shared/Redux/ReduxStore'; import { cleanup, screen } from '@testing-library/react'; import React from 'react'; -import { renderWithReduxStore } from '../../../Common'; - -const mockTargetConnectUrl = 'service:jmx:rmi://someUrl'; +import { basePreloadedState, renderWithReduxStore } from '../../../Common'; -const onlyShowingText = (value) => `Only showing analysis results with severity scores ≥ ${value}:`; +const onlyShowingText = (value: number) => `Only showing analysis results with severity scores ≥ ${value}:`; describe('', () => { let preloadedState: RootState; beforeEach(() => { preloadedState = { - dashboardConfigs: { - layouts: [], - }, - recordingFilters: { - list: [ - { - target: mockTargetConnectUrl, - active: { - selectedCategory: 'Labels', - filters: emptyActiveRecordingFilters, - }, - archived: { - selectedCategory: 'Name', - filters: emptyArchivedRecordingFilters, - }, - } as TargetRecordingFilters, - ], - }, + ...basePreloadedState, automatedAnalysisFilters: { - state: { - targetFilters: [], - globalFilters: { - filters: { - Score: 100, - }, + targetFilters: [], + globalFilters: { + filters: { + Score: 100, }, }, + _version: '0', }, }; }); diff --git a/src/test/Dashboard/Charts/mbean/__snapshots__/MBeanMetricsChartCard.test.tsx.snap b/src/test/Dashboard/Charts/mbean/__snapshots__/MBeanMetricsChartCard.test.tsx.snap new file mode 100644 index 000000000..e00c69e7c --- /dev/null +++ b/src/test/Dashboard/Charts/mbean/__snapshots__/MBeanMetricsChartCard.test.tsx.snap @@ -0,0 +1,4786 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` renders correctly: with-content 1`] = ` +
+
+
+
+
+
+ Process CPU Load (last 120s, every 10s) +
+
+ +
+
+
+
+
+
+ + + + + + + + 12:00:00 AM + + + + + + + + + % + + + + + + + + 0.20 + + + + + + + + + 0.40 + + + + + + + + + 0.60 + + + + + + + + + 0.80 + + + + + + + + + 1.0 + + + + + + + + + +
+ +
+
+
+
+
+
+
+
+`; + +exports[` renders correctly: with-content 2`] = ` +
+
+
+
+
+
+ System Load Average (last 120s, every 10s) +
+
+ +
+
+
+
+
+
+ + + + + + + + 12:00:00 AM + + + + + + + + + + + + 0.20 + + + + + + + + + 0.40 + + + + + + + + + 0.60 + + + + + + + + + 0.80 + + + + + + + + + 1.0 + + + + + + + + + +
+ +
+
+
+
+
+
+
+
+`; + +exports[` renders correctly: with-content 3`] = ` +
+
+
+
+
+
+ System CPU Load (last 120s, every 10s) +
+
+ +
+
+
+
+
+
+ + + + + + + + 12:00:00 AM + + + + + + + + + % + + + + + + + + 0.20 + + + + + + + + + 0.40 + + + + + + + + + 0.60 + + + + + + + + + 0.80 + + + + + + + + + 1.0 + + + + + + + + + +
+ +
+
+
+
+
+
+
+
+`; + +exports[` renders correctly: with-content 4`] = ` +
+
+
+
+
+
+ Physical Memory (last 120s, every 10s) +
+
+ +
+
+
+
+
+
+ + + + + + + + 12:00:00 AM + + + + + + + + + MiB + + + + + + + + 0.20 + + + + + + + + + 0.40 + + + + + + + + + 0.60 + + + + + + + + + 0.80 + + + + + + + + + 1.0 + + + + + + + + + +
+ +
+
+
+
+
+
+
+
+`; + +exports[` renders correctly: with-content 5`] = ` +
+
+
+
+
+
+ Heap Memory Usage (last 120s, every 10s) +
+
+ +
+
+
+
+
+
+ + + + + + + + 12:00:00 AM + + + + + + + + + MiB + + + + + + + + 0.20 + + + + + + + + + 0.40 + + + + + + + + + 0.60 + + + + + + + + + 0.80 + + + + + + + + + 1.0 + + + + + + + + + +
+ +
+
+
+
+
+
+
+
+`; + +exports[` renders correctly: with-content 6`] = ` +
+
+
+
+
+
+ Heap Usage Percentage (last 120s, every 10s) +
+
+ +
+
+
+
+
+
+ + + + + + + + 0.00% + + + +
+ +
+
+
+
+
+
+
+
+`; + +exports[` renders correctly: with-content 7`] = ` +
+
+
+
+
+
+ Non-Heap Memory Usage (last 120s, every 10s) +
+
+ +
+
+
+
+
+
+ + + + + + + + 12:00:00 AM + + + + + + + + + MiB + + + + + + + + 0.20 + + + + + + + + + 0.40 + + + + + + + + + 0.60 + + + + + + + + + 0.80 + + + + + + + + + 1.0 + + + + + + + + + +
+ +
+
+
+
+
+
+
+
+`; + +exports[` renders correctly: with-content 8`] = ` +
+
+
+
+
+
+ Heap Usage Percentage (last 120s, every 10s) +
+
+ +
+
+
+
+
+
+ + + + + + + + 0.00% + + + +
+ +
+
+
+
+
+
+
+
+`; + +exports[` renders loading state correctly: loading-view 1`] = ` +
+
+
+
+
+
+ Process CPU Load (last 120s, every 10s) +
+
+ +
+
+
+
+
+
+ + + + + + + + 12:00:00 AM + + + + + + + + + % + + + + + + + + 0.20 + + + + + + + + + 0.40 + + + + + + + + + 0.60 + + + + + + + + + 0.80 + + + + + + + + + 1.0 + + + + + + + + + +
+ +
+
+
+
+
+
+
+
+`; diff --git a/src/test/DateTimePicker/DateTimePicker.test.tsx b/src/test/DateTimePicker/DateTimePicker.test.tsx index a2e7e6637..6b1705957 100644 --- a/src/test/DateTimePicker/DateTimePicker.test.tsx +++ b/src/test/DateTimePicker/DateTimePicker.test.tsx @@ -42,7 +42,7 @@ describe('', () => { ); - const dateTab = screen.getByRole('tab', { name: testT('DATE', 'common') }); + const dateTab = screen.getByRole('tab', { name: testT('DATE', { ns: 'common' }) }); expect(dateTab).toBeInTheDocument(); expect(dateTab).toBeVisible(); expect(dateTab.getAttribute('aria-selected')).toBe('true'); @@ -84,7 +84,7 @@ describe('', () => { await user.click(selectedDate); - const timeTab = screen.getByRole('tab', { name: testT('TIME', 'common') }); + const timeTab = screen.getByRole('tab', { name: testT('TIME', { ns: 'common' }) }); expect(timeTab).toBeInTheDocument(); expect(timeTab).toBeVisible(); expect(timeTab.getAttribute('aria-selected')).toBe('true'); @@ -101,7 +101,7 @@ describe('', () => { await user.click(selectedDate); // Switched to time now - const mInput = within(screen.getByLabelText(testT('MINUTE', 'common'))).getByLabelText( + const mInput = within(screen.getByLabelText(testT('MINUTE', { ns: 'common' }))).getByLabelText( testT('TimeSpinner.INPUT_MINUTE_VALUE') ); expect(mInput).toBeInTheDocument(); @@ -120,7 +120,7 @@ describe('', () => { ); - const submitButton = screen.getByText(testT('SELECT', 'common')); + const submitButton = screen.getByText(testT('SELECT', { ns: 'common' })); expect(submitButton).toBeInTheDocument(); expect(submitButton).toBeVisible(); @@ -135,7 +135,7 @@ describe('', () => { ); - const dismissButton = screen.getByText(testT('CANCEL', 'common')); + const dismissButton = screen.getByText(testT('CANCEL', { ns: 'common' })); expect(dismissButton).toBeInTheDocument(); expect(dismissButton).toBeVisible(); diff --git a/src/test/DateTimePicker/MeridiemPicker.test.tsx b/src/test/DateTimePicker/MeridiemPicker.test.tsx index eaf0f9407..e9cd96f0c 100644 --- a/src/test/DateTimePicker/MeridiemPicker.test.tsx +++ b/src/test/DateTimePicker/MeridiemPicker.test.tsx @@ -40,7 +40,7 @@ describe('', () => { it('should select a meridiem when click', async () => { const { user } = renderDefault(); - const pm = screen.getByText(testT('MERIDIEM_PM', 'common')); + const pm = screen.getByText(testT('MERIDIEM_PM', { ns: 'common' })); expect(pm).toBeInTheDocument(); expect(pm).toBeVisible(); diff --git a/src/test/DateTimePicker/TimePicker.test.tsx b/src/test/DateTimePicker/TimePicker.test.tsx index f5d07dd60..7d067600d 100644 --- a/src/test/DateTimePicker/TimePicker.test.tsx +++ b/src/test/DateTimePicker/TimePicker.test.tsx @@ -79,21 +79,21 @@ describe('', () => { await user.click(switchenable24h); - const hInput = within(screen.getByLabelText(testT('HOUR', 'common'))).getByLabelText( + const hInput = within(screen.getByLabelText(testT('HOUR', { ns: 'common' }))).getByLabelText( testT('TimeSpinner.INPUT_HOUR12_VALUE') ); expect(hInput).toBeInTheDocument(); expect(hInput).toBeVisible(); expect(hInput.getAttribute('value')).toBe(format2Digit(mockSelectedIn12hr.hour12)); - const mInput = within(screen.getByLabelText(testT('MINUTE', 'common'))).getByLabelText( + const mInput = within(screen.getByLabelText(testT('MINUTE', { ns: 'common' }))).getByLabelText( testT('TimeSpinner.INPUT_MINUTE_VALUE') ); expect(mInput).toBeInTheDocument(); expect(mInput).toBeVisible(); expect(mInput.getAttribute('value')).toBe(format2Digit(mockSelectedIn12hr.minute)); - const sInput = within(screen.getByLabelText(testT('SECOND', 'common'))).getByLabelText( + const sInput = within(screen.getByLabelText(testT('SECOND', { ns: 'common' }))).getByLabelText( testT('TimeSpinner.INPUT_SECOND_VALUE') ); expect(sInput).toBeInTheDocument(); @@ -116,7 +116,7 @@ describe('', () => { /> ); - const upHour = within(screen.getByLabelText(testT('HOUR', 'common'))).getByLabelText( + const upHour = within(screen.getByLabelText(testT('HOUR', { ns: 'common' }))).getByLabelText( testT('TimeSpinner.INCREMENT_HOUR24_VALUE') ); expect(upHour).toBeInTheDocument(); @@ -127,7 +127,7 @@ describe('', () => { expect(onHourSelect).toHaveBeenCalledTimes(1); expect(onHourSelect).toHaveBeenCalledWith(14); - const downHour = within(screen.getByLabelText(testT('HOUR', 'common'))).getByLabelText( + const downHour = within(screen.getByLabelText(testT('HOUR', { ns: 'common' }))).getByLabelText( testT('TimeSpinner.DECREMENT_HOUR24_VALUE') ); expect(downHour).toBeInTheDocument(); @@ -138,7 +138,7 @@ describe('', () => { expect(onHourSelect).toHaveBeenCalledTimes(2); expect(onHourSelect).toHaveBeenLastCalledWith(12); - const upMinute = within(screen.getByLabelText(testT('MINUTE', 'common'))).getByLabelText( + const upMinute = within(screen.getByLabelText(testT('MINUTE', { ns: 'common' }))).getByLabelText( testT('TimeSpinner.INCREMENT_MINUTE_VALUE') ); expect(upMinute).toBeInTheDocument(); @@ -149,7 +149,7 @@ describe('', () => { expect(onMinuteSelect).toHaveBeenCalledTimes(1); expect(onMinuteSelect).toHaveBeenCalledWith(12); - const downMinute = within(screen.getByLabelText(testT('MINUTE', 'common'))).getByLabelText( + const downMinute = within(screen.getByLabelText(testT('MINUTE', { ns: 'common' }))).getByLabelText( testT('TimeSpinner.DECREMENT_MINUTE_VALUE') ); expect(downMinute).toBeInTheDocument(); @@ -160,7 +160,7 @@ describe('', () => { expect(onMinuteSelect).toHaveBeenCalledTimes(2); expect(onMinuteSelect).toHaveBeenCalledWith(10); - const upSecond = within(screen.getByLabelText(testT('SECOND', 'common'))).getByLabelText( + const upSecond = within(screen.getByLabelText(testT('SECOND', { ns: 'common' }))).getByLabelText( testT('TimeSpinner.INCREMENT_SECOND_VALUE') ); expect(upSecond).toBeInTheDocument(); @@ -171,7 +171,7 @@ describe('', () => { expect(onSecondSelect).toHaveBeenCalledTimes(1); expect(onSecondSelect).toHaveBeenCalledWith(12); - const downSecond = within(screen.getByLabelText(testT('SECOND', 'common'))).getByLabelText( + const downSecond = within(screen.getByLabelText(testT('SECOND', { ns: 'common' }))).getByLabelText( testT('TimeSpinner.DECREMENT_SECOND_VALUE') ); expect(downSecond).toBeInTheDocument(); @@ -193,7 +193,7 @@ describe('', () => { /> ); - const hInput = within(screen.getByLabelText(testT('HOUR', 'common'))).getByLabelText( + const hInput = within(screen.getByLabelText(testT('HOUR', { ns: 'common' }))).getByLabelText( testT('TimeSpinner.INPUT_HOUR24_VALUE') ); expect(hInput).toBeInTheDocument(); @@ -203,7 +203,7 @@ describe('', () => { expect(onHourSelect).toHaveBeenCalledTimes(1); expect(onHourSelect).toHaveBeenLastCalledWith(1); - const mInput = within(screen.getByLabelText(testT('MINUTE', 'common'))).getByLabelText( + const mInput = within(screen.getByLabelText(testT('MINUTE', { ns: 'common' }))).getByLabelText( testT('TimeSpinner.INPUT_MINUTE_VALUE') ); expect(mInput).toBeInTheDocument(); @@ -213,7 +213,7 @@ describe('', () => { expect(onHourSelect).toHaveBeenCalledTimes(1); expect(onHourSelect).toHaveBeenLastCalledWith(1); - const sInput = within(screen.getByLabelText(testT('SECOND', 'common'))).getByLabelText( + const sInput = within(screen.getByLabelText(testT('SECOND', { ns: 'common' }))).getByLabelText( testT('TimeSpinner.INPUT_SECOND_VALUE') ); expect(sInput).toBeInTheDocument(); diff --git a/src/test/Recordings/ActiveRecordingsTable.test.tsx b/src/test/Recordings/ActiveRecordingsTable.test.tsx index 62f64ed5c..c5023e5b4 100644 --- a/src/test/Recordings/ActiveRecordingsTable.test.tsx +++ b/src/test/Recordings/ActiveRecordingsTable.test.tsx @@ -14,7 +14,6 @@ * limitations under the License. */ import '@testing-library/jest-dom'; -import { DashboardLayout } from '@app/Dashboard/dashboard-utils'; import { authFailMessage } from '@app/ErrorView/ErrorView'; import { DeleteActiveRecordings, DeleteOrDisableWarningType } from '@app/Modal/DeleteWarningUtils'; import { ActiveRecordingsTable } from '@app/Recordings/ActiveRecordingsTable'; @@ -33,7 +32,12 @@ import { act, cleanup, screen, within } from '@testing-library/react'; import { createMemoryHistory } from 'history'; import * as React from 'react'; import { of, Subject } from 'rxjs'; -import { DEFAULT_DIMENSIONS, renderWithServiceContextAndReduxStoreWithRouter, resize } from '../Common'; +import { + basePreloadedState, + DEFAULT_DIMENSIONS, + renderWithServiceContextAndReduxStoreWithRouter, + resize, +} from '../Common'; const mockConnectUrl = 'service:jmx:rmi://someUrl'; const mockTarget = { connectUrl: mockConnectUrl, alias: 'fooTarget' }; @@ -159,9 +163,7 @@ describe('', () => { mockRecording.state = RecordingState.RUNNING; history.go(-history.length); preloadedState = { - dashboardConfigs: { - layouts: [] as DashboardLayout[], - }, + ...basePreloadedState, recordingFilters: { list: [ { @@ -176,18 +178,9 @@ describe('', () => { }, } as TargetRecordingFilters, ], + _version: '0', }, - automatedAnalysisFilters: { - state: { - targetFilters: [], - globalFilters: { - filters: { - Score: 100, - }, - }, - }, - }, - } as RootState; + }; }); afterAll(() => { diff --git a/src/test/Recordings/ArchivedRecordingsTable.test.tsx b/src/test/Recordings/ArchivedRecordingsTable.test.tsx index 542ff3d8b..f50ce87e1 100644 --- a/src/test/Recordings/ArchivedRecordingsTable.test.tsx +++ b/src/test/Recordings/ArchivedRecordingsTable.test.tsx @@ -15,7 +15,6 @@ */ import { DeleteArchivedRecordings, DeleteOrDisableWarningType } from '@app/Modal/DeleteWarningUtils'; import { ArchivedRecordingsTable } from '@app/Recordings/ArchivedRecordingsTable'; -import { DashboardLayout } from '@app/Shared/Redux/Configurations/DashboardConfigSlice'; import { emptyActiveRecordingFilters, emptyArchivedRecordingFilters, @@ -32,7 +31,12 @@ import { screen, within, cleanup } from '@testing-library/react'; import { createMemoryHistory } from 'history'; import * as React from 'react'; import { of, Subject } from 'rxjs'; -import { DEFAULT_DIMENSIONS, renderWithServiceContextAndReduxStoreWithRouter, resize } from '../Common'; +import { + basePreloadedState, + DEFAULT_DIMENSIONS, + renderWithServiceContextAndReduxStoreWithRouter, + resize, +} from '../Common'; const mockConnectUrl = 'service:jmx:rmi://someUrl'; const mockTarget = { connectUrl: mockConnectUrl, alias: 'fooTarget' }; @@ -152,9 +156,7 @@ describe('', () => { beforeEach(() => { history.go(-history.length); preloadedState = { - dashboardConfigs: { - layouts: [] as DashboardLayout[], - }, + ...basePreloadedState, recordingFilters: { list: [ { @@ -169,18 +171,9 @@ describe('', () => { }, } as TargetRecordingFilters, ], + _version: '0', }, - automatedAnalysisFilters: { - state: { - targetFilters: [], - globalFilters: { - filters: { - Score: 100, - }, - }, - }, - }, - } as RootState; + }; }); afterEach(cleanup); diff --git a/src/test/Recordings/RecordingFilters.test.tsx b/src/test/Recordings/RecordingFilters.test.tsx index 1f4222fb3..f130b5090 100644 --- a/src/test/Recordings/RecordingFilters.test.tsx +++ b/src/test/Recordings/RecordingFilters.test.tsx @@ -35,7 +35,7 @@ import { cleanup, screen, within } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; import { of } from 'rxjs'; -import { renderWithReduxStore } from '../Common'; +import { basePreloadedState, renderWithReduxStore } from '../Common'; const mockFooTarget: Target = { connectUrl: 'service:jmx:rmi://someFooUrl', @@ -110,9 +110,7 @@ describe('', () => { } as RecordingFiltersCategories; preloadedState = { - dashboardConfigs: { - layouts: [], - }, + ...basePreloadedState, recordingFilters: { list: [ { @@ -127,16 +125,16 @@ describe('', () => { }, } as TargetRecordingFilters, ], + _version: '0', }, automatedAnalysisFilters: { - state: { - targetFilters: [], - globalFilters: { - filters: { - Score: 100, - }, + targetFilters: [], + globalFilters: { + filters: { + Score: 100, }, }, + _version: '0', }, }; }); diff --git a/src/test/Rules/CreateRule.test.tsx b/src/test/Rules/CreateRule.test.tsx index 32f35e9d7..44dae1fd9 100644 --- a/src/test/Rules/CreateRule.test.tsx +++ b/src/test/Rules/CreateRule.test.tsx @@ -73,7 +73,7 @@ jest.mock('react-router-dom', () => ({ jest.spyOn(defaultServices.api, 'doGet').mockReturnValue(of([mockEventTemplate])); jest.spyOn(defaultServices.targets, 'targets').mockReturnValue(of([mockTarget])); -jest.spyOn(defaultServices.api, 'matchTargetsWithExpr').mockImplementation((matchExpression, targets) => { +jest.spyOn(defaultServices.api, 'matchTargetsWithExpr').mockImplementation((matchExpression, _targets) => { switch (matchExpression) { case mockRule.matchExpression: return of([mockTarget]); diff --git a/src/test/Shared/Services/Login.service.test.tsx b/src/test/Shared/Services/Login.service.test.tsx index 7a05d4dd9..a2755e960 100644 --- a/src/test/Shared/Services/Login.service.test.tsx +++ b/src/test/Shared/Services/Login.service.test.tsx @@ -24,7 +24,7 @@ import { fromFetch } from 'rxjs/fetch'; jest.mock('rxjs/fetch', () => { return { - fromFetch: jest.fn((url: any, opts: any): any => undefined), + fromFetch: jest.fn((_url: unknown, _opts: unknown): unknown => undefined), }; }); diff --git a/tsconfig.json b/tsconfig.json index 8c062821a..abfa755e2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -25,7 +25,8 @@ "@test/*": ["src/test/*"], "@i18n/*": ["src/i18n/*"], "@assets/*": ["node_modules/@patternfly/react-core/dist/styles/assets/*"] - } + }, + "skipLibCheck": true }, "include": [ "src/**/*.ts",