From 3109db5f587e327e6beea100966f0339847ace52 Mon Sep 17 00:00:00 2001 From: PengxiWPix Date: Wed, 17 Apr 2024 10:29:02 +0800 Subject: [PATCH 01/25] ADM-927:[frontend]feat: add retry button --- frontend/src/containers/MetricsStep/index.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frontend/src/containers/MetricsStep/index.tsx b/frontend/src/containers/MetricsStep/index.tsx index dbddd57045..a0e7e76fca 100644 --- a/frontend/src/containers/MetricsStep/index.tsx +++ b/frontend/src/containers/MetricsStep/index.tsx @@ -110,7 +110,8 @@ const MetricsStep = () => { {isShowCrewsAndRealDone && ( {isLoading && } - Board configuration + Board configuration {Retry} + {isEmpty(errorMessage) ? ( <> @@ -154,7 +155,7 @@ const MetricsStep = () => { requiredData.includes(REQUIRED_DATA.LEAD_TIME_FOR_CHANGES) || requiredData.includes(REQUIRED_DATA.DEV_MEAN_TIME_TO_RECOVERY)) && ( - Pipeline configuration + Pipeline configuration {Retry} )} From b242616f20de4718fc003103f04ea4aa5743e034 Mon Sep 17 00:00:00 2001 From: weiraneve <907221539@qq.com> Date: Wed, 17 Apr 2024 11:10:34 +0800 Subject: [PATCH 02/25] ADM-927:[frontend]feat: http client handle 5xx error with special route --- frontend/src/clients/HttpClient.ts | 9 ++++++++- frontend/src/containers/MetricsStep/index.tsx | 8 ++++++-- frontend/src/hooks/useGetBoardInfo.ts | 5 +++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/frontend/src/clients/HttpClient.ts b/frontend/src/clients/HttpClient.ts index 8be0eaf00e..d50b1025af 100644 --- a/frontend/src/clients/HttpClient.ts +++ b/frontend/src/clients/HttpClient.ts @@ -38,9 +38,16 @@ export class HttpClient { case HttpStatusCode.Forbidden: throw new ForbiddenError(errorMessage, HttpStatusCode.Forbidden, description); default: - if (status >= 500) { + // todo need refactor + if ( + status >= 500 && + response.config.url != '/boards/jira/info' && + response.config.url != 'pipelines/buildkite/info' + ) { window.location.href = ROUTE.ERROR_PAGE; throw new InternalServerError(errorMessage, status, description); + } else { + throw new InternalServerError(errorMessage, status, description); } throw new UnknownError(); } diff --git a/frontend/src/containers/MetricsStep/index.tsx b/frontend/src/containers/MetricsStep/index.tsx index a0e7e76fca..14260d2ca8 100644 --- a/frontend/src/containers/MetricsStep/index.tsx +++ b/frontend/src/containers/MetricsStep/index.tsx @@ -110,7 +110,9 @@ const MetricsStep = () => { {isShowCrewsAndRealDone && ( {isLoading && } - Board configuration {Retry} + + Board configuration {Retry}{' '} + {isEmpty(errorMessage) ? ( <> @@ -155,7 +157,9 @@ const MetricsStep = () => { requiredData.includes(REQUIRED_DATA.LEAD_TIME_FOR_CHANGES) || requiredData.includes(REQUIRED_DATA.DEV_MEAN_TIME_TO_RECOVERY)) && ( - Pipeline configuration {Retry} + + Pipeline configuration {Retry}{' '} + )} diff --git a/frontend/src/hooks/useGetBoardInfo.ts b/frontend/src/hooks/useGetBoardInfo.ts index bf31629aa2..dde8ec3df7 100644 --- a/frontend/src/hooks/useGetBoardInfo.ts +++ b/frontend/src/hooks/useGetBoardInfo.ts @@ -49,6 +49,11 @@ const codeMapping = (code: string | number) => { message: BOARD_CONFIG_INFO_ERROR.RETRY, code: AXIOS_REQUEST_ERROR_CODE.TIMEOUT, }, + [HttpStatusCode.InternalServerError]: { + title: BOARD_CONFIG_INFO_TITLE.GENERAL_ERROR, + message: BOARD_CONFIG_INFO_ERROR.GENERAL_ERROR, + code: HttpStatusCode.InternalServerError, + }, }; return get(codes, code); }; From f28d0b38f7e641e2163abcd31c0bffd052a86174 Mon Sep 17 00:00:00 2001 From: PengxiWPix Date: Wed, 17 Apr 2024 11:31:15 +0800 Subject: [PATCH 03/25] ADM-927:[frontend]feat: add failed status for retry --- frontend/src/containers/MetricsStep/index.tsx | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/frontend/src/containers/MetricsStep/index.tsx b/frontend/src/containers/MetricsStep/index.tsx index 14260d2ca8..2b7a0560b2 100644 --- a/frontend/src/containers/MetricsStep/index.tsx +++ b/frontend/src/containers/MetricsStep/index.tsx @@ -33,9 +33,9 @@ import { combineBoardInfo, sortDateRanges } from '@src/utils/util'; import { CycleTime } from '@src/containers/MetricsStep/CycleTime'; import { RealDone } from '@src/containers/MetricsStep/RealDone'; import EmptyContent from '@src/components/Common/EmptyContent'; +import { useCallback, useLayoutEffect, useState } from 'react'; import { useAppDispatch, useAppSelector } from '@src/hooks'; import { Crews } from '@src/containers/MetricsStep/Crews'; -import { useCallback, useLayoutEffect } from 'react'; import { Loading } from '@src/components/Loading'; import ReworkSettings from './ReworkSettings'; import { Advance } from './Advance/Advance'; @@ -66,6 +66,8 @@ const MetricsStep = () => { const { getBoardInfo, isLoading, errorMessage } = useGetBoardInfoEffect(); const shouldLoad = useAppSelector(shouldMetricsLoad); const shouldGetBoardConfig = useAppSelector(selectShouldGetBoardConfig); + const [partialFailed, setPartialFailed] = useState(false); + const [allFailed, setAllFailed] = useState(false); const getInfo = useCallback( async () => { @@ -73,6 +75,16 @@ const MetricsStep = () => { ...boardConfig, dateRanges, }).then((res) => { + if (res) { + const errorRequests = res.filter((data) => !data.data); + if (errorRequests.length == res.length) setAllFailed(true); + else if (errorRequests.length > 0) setPartialFailed(true); + else { + setAllFailed(false); + setPartialFailed(false); + } + } + if (res && res[0].data) { const boardInfo = res?.map((r) => r.data); const commonPayload = combineBoardInfo(boardInfo!); @@ -111,7 +123,8 @@ const MetricsStep = () => { {isLoading && } - Board configuration {Retry}{' '} + Board configuration{' '} + {(partialFailed || allFailed) && Retry}{' '} {isEmpty(errorMessage) ? ( @@ -157,9 +170,7 @@ const MetricsStep = () => { requiredData.includes(REQUIRED_DATA.LEAD_TIME_FOR_CHANGES) || requiredData.includes(REQUIRED_DATA.DEV_MEAN_TIME_TO_RECOVERY)) && ( - - Pipeline configuration {Retry}{' '} - + Pipeline configuration )} From 5b5e2ef521694541a670749cdc80d73a3d05205e Mon Sep 17 00:00:00 2001 From: PengxiWPix Date: Wed, 17 Apr 2024 14:20:19 +0800 Subject: [PATCH 04/25] ADM-927:[frontend]feat: add notification pop up when partial failed --- frontend/src/constants/resources.ts | 2 ++ frontend/src/containers/MetricsStep/index.tsx | 21 +++++++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/frontend/src/constants/resources.ts b/frontend/src/constants/resources.ts index af2c76bf3a..e0fbc06fb2 100644 --- a/frontend/src/constants/resources.ts +++ b/frontend/src/constants/resources.ts @@ -282,6 +282,8 @@ export const MESSAGE = { 'Failed to get Classification data, please go back to previous page and try again!', FAILED_TO_EXPORT_CSV: 'Failed to export csv.', FAILED_TO_REQUEST: 'Failed to request!', + BOARD_INFO_REQUEST_PARTIAL_FAILED: + 'Failed to get partial Board configuration, please click "Retry", or click "Next" button to go to Report page.', }; export const METRICS_CYCLE_SETTING_TABLE_HEADER_BY_COLUMN = [ diff --git a/frontend/src/containers/MetricsStep/index.tsx b/frontend/src/containers/MetricsStep/index.tsx index 2b7a0560b2..2e19b47121 100644 --- a/frontend/src/containers/MetricsStep/index.tsx +++ b/frontend/src/containers/MetricsStep/index.tsx @@ -22,9 +22,15 @@ import { StyledErrorMessage, StyledRetryButton, } from '@src/containers/MetricsStep/style'; -import { AXIOS_REQUEST_ERROR_CODE, CYCLE_TIME_SETTINGS_TYPES, DONE, REQUIRED_DATA } from '@src/constants/resources'; +import { + AXIOS_REQUEST_ERROR_CODE, + CYCLE_TIME_SETTINGS_TYPES, + DONE, + MESSAGE, + REQUIRED_DATA, +} from '@src/constants/resources'; import { DeploymentFrequencySettings } from '@src/containers/MetricsStep/DeploymentFrequencySettings'; -import { closeAllNotifications } from '@src/context/notification/NotificationSlice'; +import { addNotification, closeAllNotifications } from '@src/context/notification/NotificationSlice'; import { Classification } from '@src/containers/MetricsStep/Classification'; import { shouldMetricsLoad } from '@src/context/stepper/StepperSlice'; import DateRangeViewer from '@src/components/Common/DateRangeViewer'; @@ -78,8 +84,15 @@ const MetricsStep = () => { if (res) { const errorRequests = res.filter((data) => !data.data); if (errorRequests.length == res.length) setAllFailed(true); - else if (errorRequests.length > 0) setPartialFailed(true); - else { + else if (errorRequests.length > 0) { + setPartialFailed(true); + dispatch( + addNotification({ + type: 'warning', + message: MESSAGE.BOARD_INFO_REQUEST_PARTIAL_FAILED, + }), + ); + } else { setAllFailed(false); setPartialFailed(false); } From 8f316a29d2edf2fd07a664742166704438e84612 Mon Sep 17 00:00:00 2001 From: PengxiWPix Date: Wed, 17 Apr 2024 14:59:47 +0800 Subject: [PATCH 05/25] ADM-927:[frontend]feat: implemented all no cards and all 4xx error cases --- frontend/src/containers/MetricsStep/index.tsx | 6 ++++-- frontend/src/hooks/useGetBoardInfo.ts | 17 ++++++++++++----- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/frontend/src/containers/MetricsStep/index.tsx b/frontend/src/containers/MetricsStep/index.tsx index 2e19b47121..bc5c7f1ff3 100644 --- a/frontend/src/containers/MetricsStep/index.tsx +++ b/frontend/src/containers/MetricsStep/index.tsx @@ -81,10 +81,12 @@ const MetricsStep = () => { ...boardConfig, dateRanges, }).then((res) => { + // console.log(res); if (res) { const errorRequests = res.filter((data) => !data.data); - if (errorRequests.length == res.length) setAllFailed(true); - else if (errorRequests.length > 0) { + if (errorRequests.length == res.length) { + setAllFailed(true); + } else if (errorRequests.length > 0) { setPartialFailed(true); dispatch( addNotification({ diff --git a/frontend/src/hooks/useGetBoardInfo.ts b/frontend/src/hooks/useGetBoardInfo.ts index dde8ec3df7..3b6634d2dc 100644 --- a/frontend/src/hooks/useGetBoardInfo.ts +++ b/frontend/src/hooks/useGetBoardInfo.ts @@ -88,11 +88,7 @@ export const useGetBoardInfoEffect = (): useGetBoardInfoInterface => { .getBoardInfo(boardInfoRequest) .then((res) => { if (!res.data) { - setErrorMessage({ - title: BOARD_CONFIG_INFO_TITLE.NO_CONTENT, - message: BOARD_CONFIG_INFO_ERROR.NOT_CONTENT, - code: HttpStatusCode.NoContent, - }); + res.status = HttpStatusCode.NoContent; } return res; }) @@ -105,6 +101,17 @@ export const useGetBoardInfoEffect = (): useGetBoardInfoInterface => { return Promise.all(allBoardData) .then((res) => { + console.log(res); + if (res.filter((error) => error.status == HttpStatusCode.NoContent).length == res.length) { + setErrorMessage({ + title: BOARD_CONFIG_INFO_TITLE.NO_CONTENT, + message: BOARD_CONFIG_INFO_ERROR.NOT_CONTENT, + code: HttpStatusCode.NoContent, + }); + } else { + setErrorMessage(codeMapping(HttpStatusCode.BadRequest)); + } + return res; }) .finally(() => setIsLoading(false)); From 98f077f86cb4e1af271f80488aa35e2faa99eac7 Mon Sep 17 00:00:00 2001 From: PengxiWPix Date: Wed, 17 Apr 2024 16:14:37 +0800 Subject: [PATCH 06/25] ADM-927:[frontend]feat: map correct api result to board --- frontend/src/containers/MetricsStep/index.tsx | 5 +++-- frontend/src/hooks/useGetBoardInfo.ts | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/frontend/src/containers/MetricsStep/index.tsx b/frontend/src/containers/MetricsStep/index.tsx index bc5c7f1ff3..e07200744d 100644 --- a/frontend/src/containers/MetricsStep/index.tsx +++ b/frontend/src/containers/MetricsStep/index.tsx @@ -100,8 +100,9 @@ const MetricsStep = () => { } } - if (res && res[0].data) { - const boardInfo = res?.map((r) => r.data); + if (res) { + const data = res.filter((r) => r.data); + const boardInfo = data?.map((r) => r.data); const commonPayload = combineBoardInfo(boardInfo!); dispatch(updateBoardVerifyState(true)); dispatch(updateJiraVerifyResponse(commonPayload)); diff --git a/frontend/src/hooks/useGetBoardInfo.ts b/frontend/src/hooks/useGetBoardInfo.ts index 3b6634d2dc..244f7aff79 100644 --- a/frontend/src/hooks/useGetBoardInfo.ts +++ b/frontend/src/hooks/useGetBoardInfo.ts @@ -101,13 +101,14 @@ export const useGetBoardInfoEffect = (): useGetBoardInfoInterface => { return Promise.all(allBoardData) .then((res) => { - console.log(res); if (res.filter((error) => error.status == HttpStatusCode.NoContent).length == res.length) { setErrorMessage({ title: BOARD_CONFIG_INFO_TITLE.NO_CONTENT, message: BOARD_CONFIG_INFO_ERROR.NOT_CONTENT, code: HttpStatusCode.NoContent, }); + } else if (res.filter((error) => error.status == HttpStatusCode.Ok).length > 0) { + setErrorMessage({}); } else { setErrorMessage(codeMapping(HttpStatusCode.BadRequest)); } From d8eba6674dab4a3e0e8289e45d9c14de6a43502b Mon Sep 17 00:00:00 2001 From: weiraneve <907221539@qq.com> Date: Thu, 18 Apr 2024 14:04:04 +0800 Subject: [PATCH 07/25] ADM-927:[frontend]refactor: restore the http client handle 500 logic --- frontend/src/clients/HttpClient.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/frontend/src/clients/HttpClient.ts b/frontend/src/clients/HttpClient.ts index d50b1025af..8be0eaf00e 100644 --- a/frontend/src/clients/HttpClient.ts +++ b/frontend/src/clients/HttpClient.ts @@ -38,16 +38,9 @@ export class HttpClient { case HttpStatusCode.Forbidden: throw new ForbiddenError(errorMessage, HttpStatusCode.Forbidden, description); default: - // todo need refactor - if ( - status >= 500 && - response.config.url != '/boards/jira/info' && - response.config.url != 'pipelines/buildkite/info' - ) { + if (status >= 500) { window.location.href = ROUTE.ERROR_PAGE; throw new InternalServerError(errorMessage, status, description); - } else { - throw new InternalServerError(errorMessage, status, description); } throw new UnknownError(); } From a968268f12f54309fee004bd395945e79f1cb60a Mon Sep 17 00:00:00 2001 From: PengxiWPix Date: Thu, 18 Apr 2024 14:28:32 +0800 Subject: [PATCH 08/25] ADM-927:[frontend]fix: refactor from cr comments --- frontend/src/constants/commons.ts | 6 ++++++ frontend/src/containers/MetricsStep/index.tsx | 16 ++++++++-------- frontend/src/hooks/useGetBoardInfo.ts | 15 +++++++-------- 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/frontend/src/constants/commons.ts b/frontend/src/constants/commons.ts index a6ac392633..72ef6ed3e4 100644 --- a/frontend/src/constants/commons.ts +++ b/frontend/src/constants/commons.ts @@ -87,3 +87,9 @@ export const GRID_CONFIG = { HALF: { XS: 6, MAX_INDEX: 2, FLEX: 1 }, FULL: { XS: 12, MAX_INDEX: 4, FLEX: 0.25 }, }; + +export const BOARD_INFO_FAIL_STATUS = { + NOT_FAILED: 0, + PARTIAL_FAILED: 1, + ALL_FAILED: 2 +}; diff --git a/frontend/src/containers/MetricsStep/index.tsx b/frontend/src/containers/MetricsStep/index.tsx index e07200744d..2edf49d5fd 100644 --- a/frontend/src/containers/MetricsStep/index.tsx +++ b/frontend/src/containers/MetricsStep/index.tsx @@ -48,6 +48,7 @@ import { Advance } from './Advance/Advance'; import isEmpty from 'lodash/isEmpty'; import { theme } from '@src/theme'; import merge from 'lodash/merge'; +import { BOARD_INFO_FAIL_STATUS } from "@src/constants/commons"; const MetricsStep = () => { const boardConfig = useAppSelector(selectBoard); @@ -72,8 +73,8 @@ const MetricsStep = () => { const { getBoardInfo, isLoading, errorMessage } = useGetBoardInfoEffect(); const shouldLoad = useAppSelector(shouldMetricsLoad); const shouldGetBoardConfig = useAppSelector(selectShouldGetBoardConfig); - const [partialFailed, setPartialFailed] = useState(false); - const [allFailed, setAllFailed] = useState(false); + + const [boardInfoFailedStatus, setBoardInfoFailedStatus] = useState(BOARD_INFO_FAIL_STATUS.NOT_FAILED); const getInfo = useCallback( async () => { @@ -81,13 +82,13 @@ const MetricsStep = () => { ...boardConfig, dateRanges, }).then((res) => { - // console.log(res); if (res) { + console.log(res); const errorRequests = res.filter((data) => !data.data); if (errorRequests.length == res.length) { - setAllFailed(true); + setBoardInfoFailedStatus(BOARD_INFO_FAIL_STATUS.ALL_FAILED); } else if (errorRequests.length > 0) { - setPartialFailed(true); + setBoardInfoFailedStatus(BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED); dispatch( addNotification({ type: 'warning', @@ -95,8 +96,7 @@ const MetricsStep = () => { }), ); } else { - setAllFailed(false); - setPartialFailed(false); + setBoardInfoFailedStatus(BOARD_INFO_FAIL_STATUS.NOT_FAILED); } } @@ -140,7 +140,7 @@ const MetricsStep = () => { {isLoading && } Board configuration{' '} - {(partialFailed || allFailed) && Retry}{' '} + {(boardInfoFailedStatus == 2) && Retry}{' '} {isEmpty(errorMessage) ? ( diff --git a/frontend/src/hooks/useGetBoardInfo.ts b/frontend/src/hooks/useGetBoardInfo.ts index 244f7aff79..7a4d5d06ae 100644 --- a/frontend/src/hooks/useGetBoardInfo.ts +++ b/frontend/src/hooks/useGetBoardInfo.ts @@ -1,11 +1,10 @@ -import { BOARD_CONFIG_INFO_ERROR, BOARD_CONFIG_INFO_TITLE } from '@src/constants/resources'; -import { boardInfoClient } from '@src/clients/board/BoardInfoClient'; -import { BoardInfoConfigDTO } from '@src/clients/board/dto/request'; -import { AXIOS_REQUEST_ERROR_CODE } from '@src/constants/resources'; -import { AxiosResponse, HttpStatusCode } from 'axios'; -import { ReactNode, useState } from 'react'; -import get from 'lodash/get'; -import dayjs from 'dayjs'; +import { AXIOS_REQUEST_ERROR_CODE, BOARD_CONFIG_INFO_ERROR, BOARD_CONFIG_INFO_TITLE } from "@src/constants/resources"; +import { boardInfoClient } from "@src/clients/board/BoardInfoClient"; +import { BoardInfoConfigDTO } from "@src/clients/board/dto/request"; +import { AxiosResponse, HttpStatusCode } from "axios"; +import { ReactNode, useState } from "react"; +import get from "lodash/get"; +import dayjs from "dayjs"; export type JiraColumns = Record[]; export type TargetFields = Record[]; From b46ccb939a114dd85a414d75f8f99be5ba51a9bb Mon Sep 17 00:00:00 2001 From: weiraneve <907221539@qq.com> Date: Thu, 18 Apr 2024 14:31:51 +0800 Subject: [PATCH 09/25] ADM-927:[frontend]refactor: adapt code style --- frontend/src/constants/commons.ts | 2 +- frontend/src/containers/MetricsStep/index.tsx | 11 +++++++---- frontend/src/hooks/useGetBoardInfo.ts | 14 +++++++------- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/frontend/src/constants/commons.ts b/frontend/src/constants/commons.ts index 72ef6ed3e4..1c3724d021 100644 --- a/frontend/src/constants/commons.ts +++ b/frontend/src/constants/commons.ts @@ -91,5 +91,5 @@ export const GRID_CONFIG = { export const BOARD_INFO_FAIL_STATUS = { NOT_FAILED: 0, PARTIAL_FAILED: 1, - ALL_FAILED: 2 + ALL_FAILED: 2, }; diff --git a/frontend/src/containers/MetricsStep/index.tsx b/frontend/src/containers/MetricsStep/index.tsx index 2edf49d5fd..7342f8b25d 100644 --- a/frontend/src/containers/MetricsStep/index.tsx +++ b/frontend/src/containers/MetricsStep/index.tsx @@ -38,6 +38,7 @@ import { useGetBoardInfoEffect } from '@src/hooks/useGetBoardInfo'; import { combineBoardInfo, sortDateRanges } from '@src/utils/util'; import { CycleTime } from '@src/containers/MetricsStep/CycleTime'; import { RealDone } from '@src/containers/MetricsStep/RealDone'; +import { BOARD_INFO_FAIL_STATUS } from '@src/constants/commons'; import EmptyContent from '@src/components/Common/EmptyContent'; import { useCallback, useLayoutEffect, useState } from 'react'; import { useAppDispatch, useAppSelector } from '@src/hooks'; @@ -48,7 +49,6 @@ import { Advance } from './Advance/Advance'; import isEmpty from 'lodash/isEmpty'; import { theme } from '@src/theme'; import merge from 'lodash/merge'; -import { BOARD_INFO_FAIL_STATUS } from "@src/constants/commons"; const MetricsStep = () => { const boardConfig = useAppSelector(selectBoard); @@ -74,7 +74,9 @@ const MetricsStep = () => { const shouldLoad = useAppSelector(shouldMetricsLoad); const shouldGetBoardConfig = useAppSelector(selectShouldGetBoardConfig); - const [boardInfoFailedStatus, setBoardInfoFailedStatus] = useState(BOARD_INFO_FAIL_STATUS.NOT_FAILED); + const [boardInfoFailedStatus, setBoardInfoFailedStatus] = useState( + BOARD_INFO_FAIL_STATUS.NOT_FAILED, + ); const getInfo = useCallback( async () => { @@ -83,7 +85,7 @@ const MetricsStep = () => { dateRanges, }).then((res) => { if (res) { - console.log(res); + // todo need refactor const errorRequests = res.filter((data) => !data.data); if (errorRequests.length == res.length) { setBoardInfoFailedStatus(BOARD_INFO_FAIL_STATUS.ALL_FAILED); @@ -101,6 +103,7 @@ const MetricsStep = () => { } if (res) { + // todo need refactor const data = res.filter((r) => r.data); const boardInfo = data?.map((r) => r.data); const commonPayload = combineBoardInfo(boardInfo!); @@ -140,7 +143,7 @@ const MetricsStep = () => { {isLoading && } Board configuration{' '} - {(boardInfoFailedStatus == 2) && Retry}{' '} + {boardInfoFailedStatus == 2 && Retry}{' '} {isEmpty(errorMessage) ? ( diff --git a/frontend/src/hooks/useGetBoardInfo.ts b/frontend/src/hooks/useGetBoardInfo.ts index 7a4d5d06ae..2cbcc0cb90 100644 --- a/frontend/src/hooks/useGetBoardInfo.ts +++ b/frontend/src/hooks/useGetBoardInfo.ts @@ -1,10 +1,10 @@ -import { AXIOS_REQUEST_ERROR_CODE, BOARD_CONFIG_INFO_ERROR, BOARD_CONFIG_INFO_TITLE } from "@src/constants/resources"; -import { boardInfoClient } from "@src/clients/board/BoardInfoClient"; -import { BoardInfoConfigDTO } from "@src/clients/board/dto/request"; -import { AxiosResponse, HttpStatusCode } from "axios"; -import { ReactNode, useState } from "react"; -import get from "lodash/get"; -import dayjs from "dayjs"; +import { AXIOS_REQUEST_ERROR_CODE, BOARD_CONFIG_INFO_ERROR, BOARD_CONFIG_INFO_TITLE } from '@src/constants/resources'; +import { boardInfoClient } from '@src/clients/board/BoardInfoClient'; +import { BoardInfoConfigDTO } from '@src/clients/board/dto/request'; +import { AxiosResponse, HttpStatusCode } from 'axios'; +import { ReactNode, useState } from 'react'; +import get from 'lodash/get'; +import dayjs from 'dayjs'; export type JiraColumns = Record[]; export type TargetFields = Record[]; From c75b29ae26f5a3ecab35b1c78bc4bc92f1054258 Mon Sep 17 00:00:00 2001 From: weiraneve <907221539@qq.com> Date: Thu, 18 Apr 2024 14:47:53 +0800 Subject: [PATCH 10/25] ADM-927:[frontend]refactor: remove retry for board info --- frontend/src/containers/MetricsStep/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/src/containers/MetricsStep/index.tsx b/frontend/src/containers/MetricsStep/index.tsx index 7342f8b25d..4e7a77e4a9 100644 --- a/frontend/src/containers/MetricsStep/index.tsx +++ b/frontend/src/containers/MetricsStep/index.tsx @@ -143,7 +143,6 @@ const MetricsStep = () => { {isLoading && } Board configuration{' '} - {boardInfoFailedStatus == 2 && Retry}{' '} {isEmpty(errorMessage) ? ( From 4aa0d77f4c3bf18887ed049f72e1eb8f4b47bf00 Mon Sep 17 00:00:00 2001 From: weiraneve <907221539@qq.com> Date: Fri, 19 Apr 2024 17:41:05 +0800 Subject: [PATCH 11/25] ADM-927:[frontend]feat: add board info failed status ability --- frontend/src/clients/HttpClient.ts | 2 +- frontend/src/constants/commons.ts | 14 +- frontend/src/constants/resources.ts | 7 +- frontend/src/containers/MetricsStep/index.tsx | 64 +++++---- frontend/src/hooks/useGetBoardInfo.ts | 124 ++++++++++++------ 5 files changed, 131 insertions(+), 80 deletions(-) diff --git a/frontend/src/clients/HttpClient.ts b/frontend/src/clients/HttpClient.ts index 8be0eaf00e..5ac54b6ee0 100644 --- a/frontend/src/clients/HttpClient.ts +++ b/frontend/src/clients/HttpClient.ts @@ -10,7 +10,7 @@ import { TimeoutError } from '@src/errors/TimeoutError'; import { ROUTE } from '@src/constants/router'; export class HttpClient { - protected httpTimeout = 300000; + protected httpTimeout = 7000; protected axiosInstance: AxiosInstance; constructor() { diff --git a/frontend/src/constants/commons.ts b/frontend/src/constants/commons.ts index 1c3724d021..6303591630 100644 --- a/frontend/src/constants/commons.ts +++ b/frontend/src/constants/commons.ts @@ -88,8 +88,12 @@ export const GRID_CONFIG = { FULL: { XS: 12, MAX_INDEX: 4, FLEX: 0.25 }, }; -export const BOARD_INFO_FAIL_STATUS = { - NOT_FAILED: 0, - PARTIAL_FAILED: 1, - ALL_FAILED: 2, -}; +export enum BOARD_INFO_FAIL_STATUS { + NOT_FAILED, + PARTIAL_FAILED_4XX, + PARTIAL_FAILED_TIMEOUT, + PARTIAL_FAILED_NO_CARDS, + ALL_FAILED_4XX, + ALL_FAILED_TIMEOUT, + ALL_FAILED_NO_CARDS, +} diff --git a/frontend/src/constants/resources.ts b/frontend/src/constants/resources.ts index e0fbc06fb2..575d4c9c6f 100644 --- a/frontend/src/constants/resources.ts +++ b/frontend/src/constants/resources.ts @@ -282,8 +282,10 @@ export const MESSAGE = { 'Failed to get Classification data, please go back to previous page and try again!', FAILED_TO_EXPORT_CSV: 'Failed to export csv.', FAILED_TO_REQUEST: 'Failed to request!', - BOARD_INFO_REQUEST_PARTIAL_FAILED: - 'Failed to get partial Board configuration, please click "Retry", or click "Next" button to go to Report page.', + BOARD_INFO_REQUEST_PARTIAL_FAILED_4XX: + 'Failed to get partial Board configuration, please go back to the previous page and check your board info, or click "Next" button to go to Report page.', + BOARD_INFO_REQUEST_PARTIAL_FAILED_OTHERS: + 'Failed to get partial Board configuration, you can click "Next" button to go to Report page.', }; export const METRICS_CYCLE_SETTING_TABLE_HEADER_BY_COLUMN = [ @@ -336,6 +338,7 @@ export const NO_PIPELINE_STEP_ERROR = 'No steps for this pipeline!'; export enum AXIOS_REQUEST_ERROR_CODE { TIMEOUT = 'NETWORK_TIMEOUT', + NO_CARDS = 'NO_CARDS', } export const BOARD_CONFIG_INFO_TITLE = { diff --git a/frontend/src/containers/MetricsStep/index.tsx b/frontend/src/containers/MetricsStep/index.tsx index 4e7a77e4a9..6b3cd2f61c 100644 --- a/frontend/src/containers/MetricsStep/index.tsx +++ b/frontend/src/containers/MetricsStep/index.tsx @@ -39,8 +39,8 @@ import { combineBoardInfo, sortDateRanges } from '@src/utils/util'; import { CycleTime } from '@src/containers/MetricsStep/CycleTime'; import { RealDone } from '@src/containers/MetricsStep/RealDone'; import { BOARD_INFO_FAIL_STATUS } from '@src/constants/commons'; +import { useCallback, useEffect, useLayoutEffect } from 'react'; import EmptyContent from '@src/components/Common/EmptyContent'; -import { useCallback, useLayoutEffect, useState } from 'react'; import { useAppDispatch, useAppSelector } from '@src/hooks'; import { Crews } from '@src/containers/MetricsStep/Crews'; import { Loading } from '@src/components/Loading'; @@ -70,38 +70,16 @@ const MetricsStep = () => { const isShowRealDone = cycleTimeSettingsType === CYCLE_TIME_SETTINGS_TYPES.BY_COLUMN && cycleTimeSettings.filter((e) => e.value === DONE).length > 1; - const { getBoardInfo, isLoading, errorMessage } = useGetBoardInfoEffect(); + const { getBoardInfo, isLoading, errorMessage, isDataLoading, boardInfoFailedStatus } = useGetBoardInfoEffect(); const shouldLoad = useAppSelector(shouldMetricsLoad); const shouldGetBoardConfig = useAppSelector(selectShouldGetBoardConfig); - const [boardInfoFailedStatus, setBoardInfoFailedStatus] = useState( - BOARD_INFO_FAIL_STATUS.NOT_FAILED, - ); - const getInfo = useCallback( async () => { getBoardInfo({ ...boardConfig, dateRanges, }).then((res) => { - if (res) { - // todo need refactor - const errorRequests = res.filter((data) => !data.data); - if (errorRequests.length == res.length) { - setBoardInfoFailedStatus(BOARD_INFO_FAIL_STATUS.ALL_FAILED); - } else if (errorRequests.length > 0) { - setBoardInfoFailedStatus(BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED); - dispatch( - addNotification({ - type: 'warning', - message: MESSAGE.BOARD_INFO_REQUEST_PARTIAL_FAILED, - }), - ); - } else { - setBoardInfoFailedStatus(BOARD_INFO_FAIL_STATUS.NOT_FAILED); - } - } - if (res) { // todo need refactor const data = res.filter((r) => r.data); @@ -119,6 +97,34 @@ const MetricsStep = () => { [], ); + const popup = useCallback(() => { + console.log('boardInfoFailedStatus' + boardInfoFailedStatus); + if (boardInfoFailedStatus === BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_4XX) { + dispatch( + addNotification({ + type: 'warning', + message: MESSAGE.BOARD_INFO_REQUEST_PARTIAL_FAILED_4XX, + }), + ); + } else if ( + boardInfoFailedStatus === BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_NO_CARDS || + boardInfoFailedStatus === BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_TIMEOUT + ) { + dispatch( + addNotification({ + type: 'warning', + message: MESSAGE.BOARD_INFO_REQUEST_PARTIAL_FAILED_OTHERS, + }), + ); + } + }, [boardInfoFailedStatus, dispatch]); + + useEffect(() => { + if (!isDataLoading) { + popup(); + } + }, [isDataLoading, popup]); + useLayoutEffect(() => { if (!shouldLoad) return; dispatch(closeAllNotifications()); @@ -137,15 +143,15 @@ const MetricsStep = () => { /> )} - {isShowCrewsAndRealDone && ( {isLoading && } - - Board configuration{' '} - + Board configuration - {isEmpty(errorMessage) ? ( + {isEmpty(errorMessage) || + (boardInfoFailedStatus != BOARD_INFO_FAIL_STATUS.ALL_FAILED_4XX && + boardInfoFailedStatus != BOARD_INFO_FAIL_STATUS.ALL_FAILED_TIMEOUT && + boardInfoFailedStatus != BOARD_INFO_FAIL_STATUS.ALL_FAILED_NO_CARDS) ? ( <> diff --git a/frontend/src/hooks/useGetBoardInfo.ts b/frontend/src/hooks/useGetBoardInfo.ts index 2cbcc0cb90..b87af0703c 100644 --- a/frontend/src/hooks/useGetBoardInfo.ts +++ b/frontend/src/hooks/useGetBoardInfo.ts @@ -1,8 +1,9 @@ import { AXIOS_REQUEST_ERROR_CODE, BOARD_CONFIG_INFO_ERROR, BOARD_CONFIG_INFO_TITLE } from '@src/constants/resources'; import { boardInfoClient } from '@src/clients/board/BoardInfoClient'; import { BoardInfoConfigDTO } from '@src/clients/board/dto/request'; +import { BOARD_INFO_FAIL_STATUS } from '@src/constants/commons'; +import { ReactNode, useEffect, useState } from 'react'; import { AxiosResponse, HttpStatusCode } from 'axios'; -import { ReactNode, useState } from 'react'; import get from 'lodash/get'; import dayjs from 'dayjs'; @@ -19,51 +20,70 @@ export interface useGetBoardInfoInterface { getBoardInfo: (data: BoardInfoConfigDTO) => Promise[]> | undefined>; isLoading: boolean; errorMessage: Record; + isDataLoading: boolean; + boardInfoFailedStatus: BOARD_INFO_FAIL_STATUS; } +const boardInfoFailedStatusMapping = (code: string | number) => { + const numericCode = typeof code === 'string' ? parseInt(code, 10) : code; + if (numericCode >= HttpStatusCode.BadRequest || numericCode < HttpStatusCode.InternalServerError) { + return BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_4XX; + } else { + return BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_TIMEOUT; + } +}; -const codeMapping = (code: string | number) => { - const codes = { - [HttpStatusCode.BadRequest]: { - title: BOARD_CONFIG_INFO_TITLE.GENERAL_ERROR, - message: BOARD_CONFIG_INFO_ERROR.GENERAL_ERROR, - code: HttpStatusCode.BadRequest, - }, - [HttpStatusCode.Unauthorized]: { - title: BOARD_CONFIG_INFO_TITLE.GENERAL_ERROR, - message: BOARD_CONFIG_INFO_ERROR.GENERAL_ERROR, - code: HttpStatusCode.Unauthorized, - }, - [HttpStatusCode.Forbidden]: { - title: BOARD_CONFIG_INFO_TITLE.GENERAL_ERROR, - message: BOARD_CONFIG_INFO_ERROR.GENERAL_ERROR, - code: HttpStatusCode.Forbidden, +const errorStatusMap = (status: BOARD_INFO_FAIL_STATUS) => { + const errorStatusMap = { + [BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_4XX]: { + errorMessage: { + title: BOARD_CONFIG_INFO_TITLE.GENERAL_ERROR, + message: BOARD_CONFIG_INFO_ERROR.GENERAL_ERROR, + code: HttpStatusCode.BadRequest, + }, + newStatus: BOARD_INFO_FAIL_STATUS.ALL_FAILED_4XX, }, - [HttpStatusCode.NotFound]: { - title: BOARD_CONFIG_INFO_TITLE.GENERAL_ERROR, - message: BOARD_CONFIG_INFO_ERROR.GENERAL_ERROR, - code: HttpStatusCode.NotFound, + [BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_TIMEOUT]: { + errorMessage: { + title: BOARD_CONFIG_INFO_TITLE.EMPTY, + message: BOARD_CONFIG_INFO_ERROR.RETRY, + code: AXIOS_REQUEST_ERROR_CODE.TIMEOUT, + }, + newStatus: BOARD_INFO_FAIL_STATUS.ALL_FAILED_TIMEOUT, }, - [AXIOS_REQUEST_ERROR_CODE.TIMEOUT]: { - title: BOARD_CONFIG_INFO_TITLE.EMPTY, - message: BOARD_CONFIG_INFO_ERROR.RETRY, - code: AXIOS_REQUEST_ERROR_CODE.TIMEOUT, + [BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_NO_CARDS]: { + errorMessage: { + title: BOARD_CONFIG_INFO_TITLE.EMPTY, + message: BOARD_CONFIG_INFO_ERROR.RETRY, + code: AXIOS_REQUEST_ERROR_CODE.NO_CARDS, + }, + newStatus: BOARD_INFO_FAIL_STATUS.ALL_FAILED_NO_CARDS, }, - [HttpStatusCode.InternalServerError]: { - title: BOARD_CONFIG_INFO_TITLE.GENERAL_ERROR, - message: BOARD_CONFIG_INFO_ERROR.GENERAL_ERROR, - code: HttpStatusCode.InternalServerError, + [BOARD_INFO_FAIL_STATUS.ALL_FAILED_NO_CARDS]: { + errorMessage: { + title: BOARD_CONFIG_INFO_TITLE.NO_CONTENT, + message: BOARD_CONFIG_INFO_ERROR.NOT_CONTENT, + code: AXIOS_REQUEST_ERROR_CODE.NO_CARDS, + }, + newStatus: BOARD_INFO_FAIL_STATUS.ALL_FAILED_NO_CARDS, }, }; - return get(codes, code); + return get(errorStatusMap, status); }; export const useGetBoardInfoEffect = (): useGetBoardInfoInterface => { const [isLoading, setIsLoading] = useState(false); + const [isDataLoading, setIsDataLoading] = useState(true); const [errorMessage, setErrorMessage] = useState({}); + const [boardInfoFailedStatus, setBoardInfoFailedStatus] = useState(BOARD_INFO_FAIL_STATUS.NOT_FAILED); + useEffect(() => { + console.log('boardInfoFailedStatus--hook' + boardInfoFailedStatus); + }, [boardInfoFailedStatus]); const getBoardInfo = async (data: BoardInfoConfigDTO) => { setIsLoading(true); setErrorMessage({}); + let errorCount = 0; + let localBoardInfoFailedStatus: BOARD_INFO_FAIL_STATUS; if (data.dateRanges) { const dateRangeCopy = Array.from(data.dateRanges); @@ -87,39 +107,57 @@ export const useGetBoardInfoEffect = (): useGetBoardInfoInterface => { .getBoardInfo(boardInfoRequest) .then((res) => { if (!res.data) { - res.status = HttpStatusCode.NoContent; + errorCount++; + localBoardInfoFailedStatus = BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_NO_CARDS; + setBoardInfoFailedStatus(BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_NO_CARDS); } return res; }) .catch((err) => { const { code } = err; - setErrorMessage(codeMapping(code)); + errorCount++; + localBoardInfoFailedStatus = boardInfoFailedStatusMapping(code); + console.log('localBoardInfoFailedStatus' + localBoardInfoFailedStatus); + setBoardInfoFailedStatus(localBoardInfoFailedStatus); return err; }); }); return Promise.all(allBoardData) .then((res) => { - if (res.filter((error) => error.status == HttpStatusCode.NoContent).length == res.length) { - setErrorMessage({ - title: BOARD_CONFIG_INFO_TITLE.NO_CONTENT, - message: BOARD_CONFIG_INFO_ERROR.NOT_CONTENT, - code: HttpStatusCode.NoContent, - }); - } else if (res.filter((error) => error.status == HttpStatusCode.Ok).length > 0) { - setErrorMessage({}); - } else { - setErrorMessage(codeMapping(HttpStatusCode.BadRequest)); + if (localBoardInfoFailedStatus == BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_NO_CARDS) { + localBoardInfoFailedStatus = BOARD_INFO_FAIL_STATUS.ALL_FAILED_NO_CARDS; + } + const config = errorStatusMap(localBoardInfoFailedStatus); + console.log(res); + console.log('errorCount' + errorCount); + console.log('config' + config); + if (errorCount == res.length) { + if (config) { + console.log('all failed'); + setErrorMessage(config.errorMessage); + setBoardInfoFailedStatus(config.newStatus); + } + } else if (errorCount != 0) { + console.log('partial failed'); + if (config) { + setErrorMessage(config.errorMessage); + } } return res; }) - .finally(() => setIsLoading(false)); + .finally(() => { + setIsLoading(false); + setIsDataLoading(false); + }); } }; return { getBoardInfo, errorMessage, isLoading, + isDataLoading, + boardInfoFailedStatus, }; }; From a533f5344592aefd0bd5fc6ca26067eb8b27e1fc Mon Sep 17 00:00:00 2001 From: weiraneve <907221539@qq.com> Date: Mon, 22 Apr 2024 10:37:10 +0800 Subject: [PATCH 12/25] ADM-927:[frontend]refactor: adapt all no cards --- frontend/src/clients/HttpClient.ts | 2 +- frontend/src/containers/MetricsStep/index.tsx | 58 +++++++++---------- frontend/src/hooks/useGetBoardInfo.ts | 26 +-------- 3 files changed, 33 insertions(+), 53 deletions(-) diff --git a/frontend/src/clients/HttpClient.ts b/frontend/src/clients/HttpClient.ts index 5ac54b6ee0..8be0eaf00e 100644 --- a/frontend/src/clients/HttpClient.ts +++ b/frontend/src/clients/HttpClient.ts @@ -10,7 +10,7 @@ import { TimeoutError } from '@src/errors/TimeoutError'; import { ROUTE } from '@src/constants/router'; export class HttpClient { - protected httpTimeout = 7000; + protected httpTimeout = 300000; protected axiosInstance: AxiosInstance; constructor() { diff --git a/frontend/src/containers/MetricsStep/index.tsx b/frontend/src/containers/MetricsStep/index.tsx index 6b3cd2f61c..6aa802432e 100644 --- a/frontend/src/containers/MetricsStep/index.tsx +++ b/frontend/src/containers/MetricsStep/index.tsx @@ -84,12 +84,14 @@ const MetricsStep = () => { // todo need refactor const data = res.filter((r) => r.data); const boardInfo = data?.map((r) => r.data); - const commonPayload = combineBoardInfo(boardInfo!); - dispatch(updateBoardVerifyState(true)); - dispatch(updateJiraVerifyResponse(commonPayload)); - dispatch(updateMetricsState(merge(commonPayload, { isProjectCreated: isProjectCreated }))); - dispatch(updateShouldGetBoardConfig(false)); - dispatch(updateFirstTimeRoadMetricsBoardData(false)); + if (boardInfo?.length) { + const commonPayload = combineBoardInfo(boardInfo); + dispatch(updateBoardVerifyState(true)); + dispatch(updateJiraVerifyResponse(commonPayload)); + dispatch(updateMetricsState(merge(commonPayload, { isProjectCreated: isProjectCreated }))); + dispatch(updateShouldGetBoardConfig(false)); + dispatch(updateFirstTimeRoadMetricsBoardData(false)); + } } }); }, @@ -97,33 +99,31 @@ const MetricsStep = () => { [], ); - const popup = useCallback(() => { - console.log('boardInfoFailedStatus' + boardInfoFailedStatus); - if (boardInfoFailedStatus === BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_4XX) { - dispatch( - addNotification({ - type: 'warning', - message: MESSAGE.BOARD_INFO_REQUEST_PARTIAL_FAILED_4XX, - }), - ); - } else if ( - boardInfoFailedStatus === BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_NO_CARDS || - boardInfoFailedStatus === BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_TIMEOUT - ) { - dispatch( - addNotification({ - type: 'warning', - message: MESSAGE.BOARD_INFO_REQUEST_PARTIAL_FAILED_OTHERS, - }), - ); - } - }, [boardInfoFailedStatus, dispatch]); - useEffect(() => { + const popup = () => { + if (boardInfoFailedStatus === BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_4XX) { + dispatch( + addNotification({ + type: 'warning', + message: MESSAGE.BOARD_INFO_REQUEST_PARTIAL_FAILED_4XX, + }), + ); + } else if ( + boardInfoFailedStatus === BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_NO_CARDS || + boardInfoFailedStatus === BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_TIMEOUT + ) { + dispatch( + addNotification({ + type: 'warning', + message: MESSAGE.BOARD_INFO_REQUEST_PARTIAL_FAILED_OTHERS, + }), + ); + } + }; if (!isDataLoading) { popup(); } - }, [isDataLoading, popup]); + }, [boardInfoFailedStatus, dispatch, isDataLoading]); useLayoutEffect(() => { if (!shouldLoad) return; diff --git a/frontend/src/hooks/useGetBoardInfo.ts b/frontend/src/hooks/useGetBoardInfo.ts index b87af0703c..46ea2e3afc 100644 --- a/frontend/src/hooks/useGetBoardInfo.ts +++ b/frontend/src/hooks/useGetBoardInfo.ts @@ -2,8 +2,8 @@ import { AXIOS_REQUEST_ERROR_CODE, BOARD_CONFIG_INFO_ERROR, BOARD_CONFIG_INFO_TI import { boardInfoClient } from '@src/clients/board/BoardInfoClient'; import { BoardInfoConfigDTO } from '@src/clients/board/dto/request'; import { BOARD_INFO_FAIL_STATUS } from '@src/constants/commons'; -import { ReactNode, useEffect, useState } from 'react'; import { AxiosResponse, HttpStatusCode } from 'axios'; +import { ReactNode, useState } from 'react'; import get from 'lodash/get'; import dayjs from 'dayjs'; @@ -23,7 +23,7 @@ export interface useGetBoardInfoInterface { isDataLoading: boolean; boardInfoFailedStatus: BOARD_INFO_FAIL_STATUS; } -const boardInfoFailedStatusMapping = (code: string | number) => { +const boardInfoPartialFailedStatusMapping = (code: string | number) => { const numericCode = typeof code === 'string' ? parseInt(code, 10) : code; if (numericCode >= HttpStatusCode.BadRequest || numericCode < HttpStatusCode.InternalServerError) { return BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_4XX; @@ -51,14 +51,6 @@ const errorStatusMap = (status: BOARD_INFO_FAIL_STATUS) => { newStatus: BOARD_INFO_FAIL_STATUS.ALL_FAILED_TIMEOUT, }, [BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_NO_CARDS]: { - errorMessage: { - title: BOARD_CONFIG_INFO_TITLE.EMPTY, - message: BOARD_CONFIG_INFO_ERROR.RETRY, - code: AXIOS_REQUEST_ERROR_CODE.NO_CARDS, - }, - newStatus: BOARD_INFO_FAIL_STATUS.ALL_FAILED_NO_CARDS, - }, - [BOARD_INFO_FAIL_STATUS.ALL_FAILED_NO_CARDS]: { errorMessage: { title: BOARD_CONFIG_INFO_TITLE.NO_CONTENT, message: BOARD_CONFIG_INFO_ERROR.NOT_CONTENT, @@ -75,9 +67,6 @@ export const useGetBoardInfoEffect = (): useGetBoardInfoInterface => { const [isDataLoading, setIsDataLoading] = useState(true); const [errorMessage, setErrorMessage] = useState({}); const [boardInfoFailedStatus, setBoardInfoFailedStatus] = useState(BOARD_INFO_FAIL_STATUS.NOT_FAILED); - useEffect(() => { - console.log('boardInfoFailedStatus--hook' + boardInfoFailedStatus); - }, [boardInfoFailedStatus]); const getBoardInfo = async (data: BoardInfoConfigDTO) => { setIsLoading(true); @@ -116,8 +105,7 @@ export const useGetBoardInfoEffect = (): useGetBoardInfoInterface => { .catch((err) => { const { code } = err; errorCount++; - localBoardInfoFailedStatus = boardInfoFailedStatusMapping(code); - console.log('localBoardInfoFailedStatus' + localBoardInfoFailedStatus); + localBoardInfoFailedStatus = boardInfoPartialFailedStatusMapping(code); setBoardInfoFailedStatus(localBoardInfoFailedStatus); return err; }); @@ -125,21 +113,13 @@ export const useGetBoardInfoEffect = (): useGetBoardInfoInterface => { return Promise.all(allBoardData) .then((res) => { - if (localBoardInfoFailedStatus == BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_NO_CARDS) { - localBoardInfoFailedStatus = BOARD_INFO_FAIL_STATUS.ALL_FAILED_NO_CARDS; - } const config = errorStatusMap(localBoardInfoFailedStatus); - console.log(res); - console.log('errorCount' + errorCount); - console.log('config' + config); if (errorCount == res.length) { if (config) { - console.log('all failed'); setErrorMessage(config.errorMessage); setBoardInfoFailedStatus(config.newStatus); } } else if (errorCount != 0) { - console.log('partial failed'); if (config) { setErrorMessage(config.errorMessage); } From 2c847b6eacfb68d72abf67dc17626c36ecf676f3 Mon Sep 17 00:00:00 2001 From: weiraneve <907221539@qq.com> Date: Mon, 22 Apr 2024 10:51:14 +0800 Subject: [PATCH 13/25] ADM-927:[frontend]refactor: move board info response filter and map to hook --- frontend/src/containers/MetricsStep/index.tsx | 19 +++++++------------ frontend/src/hooks/useGetBoardInfo.ts | 8 ++++---- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/frontend/src/containers/MetricsStep/index.tsx b/frontend/src/containers/MetricsStep/index.tsx index 6aa802432e..f45fc69b5f 100644 --- a/frontend/src/containers/MetricsStep/index.tsx +++ b/frontend/src/containers/MetricsStep/index.tsx @@ -80,18 +80,13 @@ const MetricsStep = () => { ...boardConfig, dateRanges, }).then((res) => { - if (res) { - // todo need refactor - const data = res.filter((r) => r.data); - const boardInfo = data?.map((r) => r.data); - if (boardInfo?.length) { - const commonPayload = combineBoardInfo(boardInfo); - dispatch(updateBoardVerifyState(true)); - dispatch(updateJiraVerifyResponse(commonPayload)); - dispatch(updateMetricsState(merge(commonPayload, { isProjectCreated: isProjectCreated }))); - dispatch(updateShouldGetBoardConfig(false)); - dispatch(updateFirstTimeRoadMetricsBoardData(false)); - } + if (res && res.length) { + const commonPayload = combineBoardInfo(res); + dispatch(updateBoardVerifyState(true)); + dispatch(updateJiraVerifyResponse(commonPayload)); + dispatch(updateMetricsState(merge(commonPayload, { isProjectCreated: isProjectCreated }))); + dispatch(updateShouldGetBoardConfig(false)); + dispatch(updateFirstTimeRoadMetricsBoardData(false)); } }); }, diff --git a/frontend/src/hooks/useGetBoardInfo.ts b/frontend/src/hooks/useGetBoardInfo.ts index 46ea2e3afc..ca7f3fc519 100644 --- a/frontend/src/hooks/useGetBoardInfo.ts +++ b/frontend/src/hooks/useGetBoardInfo.ts @@ -2,8 +2,8 @@ import { AXIOS_REQUEST_ERROR_CODE, BOARD_CONFIG_INFO_ERROR, BOARD_CONFIG_INFO_TI import { boardInfoClient } from '@src/clients/board/BoardInfoClient'; import { BoardInfoConfigDTO } from '@src/clients/board/dto/request'; import { BOARD_INFO_FAIL_STATUS } from '@src/constants/commons'; -import { AxiosResponse, HttpStatusCode } from 'axios'; import { ReactNode, useState } from 'react'; +import { HttpStatusCode } from 'axios'; import get from 'lodash/get'; import dayjs from 'dayjs'; @@ -17,7 +17,7 @@ export interface BoardInfoResponse { users: Users; } export interface useGetBoardInfoInterface { - getBoardInfo: (data: BoardInfoConfigDTO) => Promise[]> | undefined>; + getBoardInfo: (data: BoardInfoConfigDTO) => Promise | undefined>; isLoading: boolean; errorMessage: Record; isDataLoading: boolean; @@ -124,8 +124,8 @@ export const useGetBoardInfoEffect = (): useGetBoardInfoInterface => { setErrorMessage(config.errorMessage); } } - - return res; + const data = res.filter((r) => r.data); + return data?.map((r) => r.data); }) .finally(() => { setIsLoading(false); From d13e741d3b3379ffebaeeab8cc0f541f3390ca03 Mon Sep 17 00:00:00 2001 From: weiraneve <907221539@qq.com> Date: Mon, 22 Apr 2024 15:05:30 +0800 Subject: [PATCH 14/25] ADM-927:[frontend]test: fix test --- frontend/__tests__/containers/MetricsStep/MetricsStep.test.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/__tests__/containers/MetricsStep/MetricsStep.test.tsx b/frontend/__tests__/containers/MetricsStep/MetricsStep.test.tsx index 73383b92fa..5506bb164b 100644 --- a/frontend/__tests__/containers/MetricsStep/MetricsStep.test.tsx +++ b/frontend/__tests__/containers/MetricsStep/MetricsStep.test.tsx @@ -195,7 +195,6 @@ describe('MetricsStep', () => { { key: 'done', value: { name: 'Done', statuses: ['PRE-DONE,', 'DONE', 'CANCEL'] } }, ]; - store.dispatch(updateShouldGetBoardConfig(true)); store.dispatch(updateMetrics(REQUIRED_DATA_LIST)); store.dispatch(updateCycleTimeSettings(cycleTimeSettingsWithTwoDoneValue)); store.dispatch(saveDoneColumn(doneColumn)); @@ -286,6 +285,7 @@ describe('MetricsStep', () => { }); it('should be render no card container when get board card when no data', async () => { + store.dispatch(updateShouldGetBoardConfig(true)); server.use( rest.post(MOCK_BOARD_INFO_URL, (_, res, ctx) => { return res(ctx.status(HttpStatusCode.Ok)); @@ -374,6 +374,7 @@ describe('MetricsStep', () => { }); it('should show retry button when call get info timeout', async () => { + store.dispatch(updateShouldGetBoardConfig(true)); server.use( rest.post(MOCK_BOARD_INFO_URL, (_, res) => { return res.networkError('NETWORK_TIMEOUT'); From c82dc3acb6ebede0ed11a10e6b2a758f43dd133a Mon Sep 17 00:00:00 2001 From: weiraneve <907221539@qq.com> Date: Mon, 22 Apr 2024 17:47:08 +0800 Subject: [PATCH 15/25] ADM-927:[frontend]refactor: rename status and remove unnecessary variable --- .../__tests__/hooks/useGetBoardInfo.test.tsx | 61 +++++++++++++++++++ frontend/src/containers/MetricsStep/index.tsx | 6 +- frontend/src/hooks/useGetBoardInfo.ts | 18 +++--- 3 files changed, 72 insertions(+), 13 deletions(-) diff --git a/frontend/__tests__/hooks/useGetBoardInfo.test.tsx b/frontend/__tests__/hooks/useGetBoardInfo.test.tsx index 0430c7a6fe..cdc6edca4f 100644 --- a/frontend/__tests__/hooks/useGetBoardInfo.test.tsx +++ b/frontend/__tests__/hooks/useGetBoardInfo.test.tsx @@ -81,4 +81,65 @@ describe('use get board info', () => { }); expect(result.current.errorMessage.message).toEqual(message); }); + + it('should get data', async () => { + server.use( + rest.post(MOCK_BOARD_INFO_URL, (_, res, ctx) => { + return res( + ctx.status(HttpStatusCode.Ok), + ctx.json({ + ignoredTargetFields: [ + { + key: 'description', + name: 'Description', + flag: false, + }, + ], + jiraColumns: [ + { + key: 'To Do', + value: { + name: 'TODO', + statuses: ['TODO'], + }, + }, + ], + targetFields: [ + { + key: 'issuetype', + name: 'Issue Type', + flag: false, + }, + ], + users: ['heartbeat user'], + }), + ); + }), + ); + const { result } = renderHook(() => useGetBoardInfoEffect()); + await act(() => { + result.current.getBoardInfo(mockBoardConfig); + }); + + await waitFor(() => { + expect(result.current.errorMessage.title).toEqual(undefined); + }); + expect(result.current.errorMessage.message).toEqual(undefined); + + server.use( + rest.post(MOCK_BOARD_INFO_URL, (_, res, ctx) => { + return res(ctx.status(HttpStatusCode.BadRequest)); + }), + ); + await act(() => { + result.current.getBoardInfo(mockBoardConfig); + }); + + await waitFor(() => { + expect(result.current.errorMessage.title).toEqual('Failed to get the board configuration!'); + }); + expect(result.current.errorMessage.message).toEqual( + 'Please go back to the previous page to check your board info, or change your time range!', + ); + }); }); diff --git a/frontend/src/containers/MetricsStep/index.tsx b/frontend/src/containers/MetricsStep/index.tsx index f45fc69b5f..3c36c284a1 100644 --- a/frontend/src/containers/MetricsStep/index.tsx +++ b/frontend/src/containers/MetricsStep/index.tsx @@ -70,7 +70,7 @@ const MetricsStep = () => { const isShowRealDone = cycleTimeSettingsType === CYCLE_TIME_SETTINGS_TYPES.BY_COLUMN && cycleTimeSettings.filter((e) => e.value === DONE).length > 1; - const { getBoardInfo, isLoading, errorMessage, isDataLoading, boardInfoFailedStatus } = useGetBoardInfoEffect(); + const { getBoardInfo, isLoading, errorMessage, boardInfoFailedStatus } = useGetBoardInfoEffect(); const shouldLoad = useAppSelector(shouldMetricsLoad); const shouldGetBoardConfig = useAppSelector(selectShouldGetBoardConfig); @@ -115,10 +115,10 @@ const MetricsStep = () => { ); } }; - if (!isDataLoading) { + if (!isLoading) { popup(); } - }, [boardInfoFailedStatus, dispatch, isDataLoading]); + }, [boardInfoFailedStatus, dispatch, isLoading]); useLayoutEffect(() => { if (!shouldLoad) return; diff --git a/frontend/src/hooks/useGetBoardInfo.ts b/frontend/src/hooks/useGetBoardInfo.ts index ca7f3fc519..861244ca84 100644 --- a/frontend/src/hooks/useGetBoardInfo.ts +++ b/frontend/src/hooks/useGetBoardInfo.ts @@ -20,16 +20,17 @@ export interface useGetBoardInfoInterface { getBoardInfo: (data: BoardInfoConfigDTO) => Promise | undefined>; isLoading: boolean; errorMessage: Record; - isDataLoading: boolean; boardInfoFailedStatus: BOARD_INFO_FAIL_STATUS; } const boardInfoPartialFailedStatusMapping = (code: string | number) => { + if (code == AXIOS_REQUEST_ERROR_CODE.TIMEOUT) { + return BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_TIMEOUT; + } const numericCode = typeof code === 'string' ? parseInt(code, 10) : code; if (numericCode >= HttpStatusCode.BadRequest || numericCode < HttpStatusCode.InternalServerError) { return BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_4XX; - } else { - return BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_TIMEOUT; } + return BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_4XX; }; const errorStatusMap = (status: BOARD_INFO_FAIL_STATUS) => { @@ -40,7 +41,7 @@ const errorStatusMap = (status: BOARD_INFO_FAIL_STATUS) => { message: BOARD_CONFIG_INFO_ERROR.GENERAL_ERROR, code: HttpStatusCode.BadRequest, }, - newStatus: BOARD_INFO_FAIL_STATUS.ALL_FAILED_4XX, + elevateStatus: BOARD_INFO_FAIL_STATUS.ALL_FAILED_4XX, }, [BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_TIMEOUT]: { errorMessage: { @@ -48,7 +49,7 @@ const errorStatusMap = (status: BOARD_INFO_FAIL_STATUS) => { message: BOARD_CONFIG_INFO_ERROR.RETRY, code: AXIOS_REQUEST_ERROR_CODE.TIMEOUT, }, - newStatus: BOARD_INFO_FAIL_STATUS.ALL_FAILED_TIMEOUT, + elevateStatus: BOARD_INFO_FAIL_STATUS.ALL_FAILED_TIMEOUT, }, [BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_NO_CARDS]: { errorMessage: { @@ -56,7 +57,7 @@ const errorStatusMap = (status: BOARD_INFO_FAIL_STATUS) => { message: BOARD_CONFIG_INFO_ERROR.NOT_CONTENT, code: AXIOS_REQUEST_ERROR_CODE.NO_CARDS, }, - newStatus: BOARD_INFO_FAIL_STATUS.ALL_FAILED_NO_CARDS, + elevateStatus: BOARD_INFO_FAIL_STATUS.ALL_FAILED_NO_CARDS, }, }; return get(errorStatusMap, status); @@ -64,7 +65,6 @@ const errorStatusMap = (status: BOARD_INFO_FAIL_STATUS) => { export const useGetBoardInfoEffect = (): useGetBoardInfoInterface => { const [isLoading, setIsLoading] = useState(false); - const [isDataLoading, setIsDataLoading] = useState(true); const [errorMessage, setErrorMessage] = useState({}); const [boardInfoFailedStatus, setBoardInfoFailedStatus] = useState(BOARD_INFO_FAIL_STATUS.NOT_FAILED); @@ -117,7 +117,7 @@ export const useGetBoardInfoEffect = (): useGetBoardInfoInterface => { if (errorCount == res.length) { if (config) { setErrorMessage(config.errorMessage); - setBoardInfoFailedStatus(config.newStatus); + setBoardInfoFailedStatus(config.elevateStatus); } } else if (errorCount != 0) { if (config) { @@ -129,7 +129,6 @@ export const useGetBoardInfoEffect = (): useGetBoardInfoInterface => { }) .finally(() => { setIsLoading(false); - setIsDataLoading(false); }); } }; @@ -137,7 +136,6 @@ export const useGetBoardInfoEffect = (): useGetBoardInfoInterface => { getBoardInfo, errorMessage, isLoading, - isDataLoading, boardInfoFailedStatus, }; }; From d9f631493c07f49c33315e3f8065e8a0a19fae6d Mon Sep 17 00:00:00 2001 From: PengxiWPix Date: Tue, 23 Apr 2024 16:52:25 +0800 Subject: [PATCH 16/25] ADM-927:[frontend]feat: fixed test coverage --- .../MetricsStep/MetricsStep.test.tsx | 41 ++++++++++ ...MetricsStepPopupTestPartialFailed.test.tsx | 63 ++++++++++++++ ...etricsStepPopupTestPartialNoCards.test.tsx | 63 ++++++++++++++ .../__tests__/hooks/useGetBoardInfo.test.tsx | 82 +++++++++++++++---- frontend/src/constants/resources.ts | 4 +- 5 files changed, 236 insertions(+), 17 deletions(-) create mode 100644 frontend/__tests__/containers/MetricsStep/MetricsStepPopupTestPartialFailed.test.tsx create mode 100644 frontend/__tests__/containers/MetricsStep/MetricsStepPopupTestPartialNoCards.test.tsx diff --git a/frontend/__tests__/containers/MetricsStep/MetricsStep.test.tsx b/frontend/__tests__/containers/MetricsStep/MetricsStep.test.tsx index 5506bb164b..6140ab011c 100644 --- a/frontend/__tests__/containers/MetricsStep/MetricsStep.test.tsx +++ b/frontend/__tests__/containers/MetricsStep/MetricsStep.test.tsx @@ -53,6 +53,19 @@ const setup = () => , ); +// const { getBoardInfo, isLoading, errorMessage, boardInfoFailedStatus } = useGetBoardInfoEffect(); + +// jest.mock('@src/hooks/useGetBoardInfo', () => ({ +// ...jest.requireActual('@src/hooks/useGetBoardInfo'), +// +// useGetBoardInfoEffect: jest.fn().mockReturnValue({ +// getBoardInfo: result.current.getBoardInfo, +// isLoading: useGetBoardInfoEffect().isLoading, +// errorMessage: useGetBoardInfoEffect().errorMessage, +// boardInfoFailedStatus: 1, +// }), +// })); + describe('MetricsStep', () => { beforeAll(() => server.listen()); afterAll(() => server.close()); @@ -304,7 +317,35 @@ describe('MetricsStep', () => { ).toBeInTheDocument(); }); + it('should be render Failed message container when get 4xx error', async () => { + store.dispatch(updateShouldGetBoardConfig(true)); + server.use( + rest.post(MOCK_BOARD_INFO_URL, (_, res, ctx) => { + return res(ctx.status(HttpStatusCode.BadRequest)); + }), + ); + + setup(); + + await waitFor(() => { + expect(screen.getByText('Failed to get Board configuration!')).toBeInTheDocument(); + }); + expect(screen.getByText('Please go back to the previous page and check your board info!')).toBeInTheDocument(); + }); + + it('should be render popup when get partial 4xx error', async () => { + store.dispatch(updateShouldGetBoardConfig(true)); + + setup(); + + await waitFor(() => { + expect(screen.getByText('Failed to get Board configuration!')).toBeInTheDocument(); + }); + expect(screen.getByText('Please go back to the previous page and check your board info!')).toBeInTheDocument(); + }); + it('should be render form container when got board card success', async () => { + store.dispatch(updateShouldGetBoardConfig(true)); server.use( rest.post(MOCK_BOARD_INFO_URL, (_, res, ctx) => { return res( diff --git a/frontend/__tests__/containers/MetricsStep/MetricsStepPopupTestPartialFailed.test.tsx b/frontend/__tests__/containers/MetricsStep/MetricsStepPopupTestPartialFailed.test.tsx new file mode 100644 index 0000000000..4596ba690a --- /dev/null +++ b/frontend/__tests__/containers/MetricsStep/MetricsStepPopupTestPartialFailed.test.tsx @@ -0,0 +1,63 @@ +import { render, waitFor } from '@testing-library/react'; +import { setupStore } from '../../utils/setupStoreUtil'; +import MetricsStep from '@src/containers/MetricsStep'; +import { Provider } from 'react-redux'; +import { setupServer } from 'msw/node'; +import { rest } from 'msw'; + +import { MOCK_BUILD_KITE_GET_INFO_RESPONSE, MOCK_PIPELINE_GET_INFO_URL, MOCK_BOARD_INFO_URL } from '../../fixtures'; +import { addNotification } from '@src/context/notification/NotificationSlice'; +import { HttpStatusCode } from 'axios'; + +let store = setupStore(); +const server = setupServer( + rest.post(MOCK_PIPELINE_GET_INFO_URL, (req, res, ctx) => + res(ctx.status(200), ctx.body(JSON.stringify(MOCK_BUILD_KITE_GET_INFO_RESPONSE))), + ), +); + +const setup = () => + render( + + + , + ); + +jest.mock('@src/context/notification/NotificationSlice', () => ({ + ...jest.requireActual('@src/context/notification/NotificationSlice'), + addNotification: jest.fn().mockReturnValue({ type: 'ADD_NEW_NOTIFICATION' }), +})); + +jest.mock('@src/hooks/useGetBoardInfo', () => ({ + ...jest.requireActual('@src/hooks/useGetBoardInfo'), + useGetBoardInfoEffect: jest.fn().mockReturnValue({ + boardInfoFailedStatus: 1, + }), +})); + +describe('MetricsStep', () => { + beforeAll(() => server.listen()); + afterAll(() => server.close()); + + beforeEach(() => { + store = setupStore(); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should show 4xx popup when call get partial 4xx error', async () => { + server.use( + rest.post(MOCK_BOARD_INFO_URL, (_, res, ctx) => { + return res.once(ctx.status(HttpStatusCode.BadRequest)); + }), + ); + + setup(); + + await waitFor(() => { + expect(addNotification).toHaveBeenCalled(); + }); + }); +}); diff --git a/frontend/__tests__/containers/MetricsStep/MetricsStepPopupTestPartialNoCards.test.tsx b/frontend/__tests__/containers/MetricsStep/MetricsStepPopupTestPartialNoCards.test.tsx new file mode 100644 index 0000000000..3593eea771 --- /dev/null +++ b/frontend/__tests__/containers/MetricsStep/MetricsStepPopupTestPartialNoCards.test.tsx @@ -0,0 +1,63 @@ +import { render, waitFor } from '@testing-library/react'; +import { setupStore } from '../../utils/setupStoreUtil'; +import MetricsStep from '@src/containers/MetricsStep'; +import { Provider } from 'react-redux'; +import { setupServer } from 'msw/node'; +import { rest } from 'msw'; + +import { MOCK_BUILD_KITE_GET_INFO_RESPONSE, MOCK_PIPELINE_GET_INFO_URL, MOCK_BOARD_INFO_URL } from '../../fixtures'; +import { addNotification } from '@src/context/notification/NotificationSlice'; +import { HttpStatusCode } from 'axios'; + +let store = setupStore(); +const server = setupServer( + rest.post(MOCK_PIPELINE_GET_INFO_URL, (req, res, ctx) => + res(ctx.status(200), ctx.body(JSON.stringify(MOCK_BUILD_KITE_GET_INFO_RESPONSE))), + ), +); + +const setup = () => + render( + + + , + ); + +jest.mock('@src/context/notification/NotificationSlice', () => ({ + ...jest.requireActual('@src/context/notification/NotificationSlice'), + addNotification: jest.fn().mockReturnValue({ type: 'ADD_NEW_NOTIFICATION' }), +})); + +jest.mock('@src/hooks/useGetBoardInfo', () => ({ + ...jest.requireActual('@src/hooks/useGetBoardInfo'), + useGetBoardInfoEffect: jest.fn().mockReturnValue({ + boardInfoFailedStatus: 3, + }), +})); + +describe('MetricsStep', () => { + beforeAll(() => server.listen()); + afterAll(() => server.close()); + + beforeEach(() => { + store = setupStore(); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should show no cards popup when call get partial no cards error', async () => { + server.use( + rest.post(MOCK_BOARD_INFO_URL, (_, res, ctx) => { + return res.once(ctx.status(HttpStatusCode.BadRequest)); + }), + ); + + setup(); + + await waitFor(() => { + expect(addNotification).toHaveBeenCalled(); + }); + }); +}); diff --git a/frontend/__tests__/hooks/useGetBoardInfo.test.tsx b/frontend/__tests__/hooks/useGetBoardInfo.test.tsx index cdc6edca4f..94da0d2548 100644 --- a/frontend/__tests__/hooks/useGetBoardInfo.test.tsx +++ b/frontend/__tests__/hooks/useGetBoardInfo.test.tsx @@ -1,4 +1,5 @@ import { MOCK_BOARD_INFO_URL, FAKE_TOKEN, FAKE_DATE_EARLIER, FAKE_DATE_LATER } from '@test/fixtures'; +import { AXIOS_REQUEST_ERROR_CODE } from '@src/constants/resources'; import { useGetBoardInfoEffect } from '@src/hooks/useGetBoardInfo'; import { renderHook, act, waitFor } from '@testing-library/react'; import { setupServer } from 'msw/node'; @@ -46,23 +47,23 @@ describe('use get board info', () => { ], [ HttpStatusCode.BadRequest, - 'Failed to get the board configuration!', - 'Please go back to the previous page to check your board info, or change your time range!', + 'Failed to get Board configuration!', + 'Please go back to the previous page and check your board info!', ], [ HttpStatusCode.Unauthorized, - 'Failed to get the board configuration!', - 'Please go back to the previous page to check your board info, or change your time range!', + 'Failed to get Board configuration!', + 'Please go back to the previous page and check your board info!', ], [ HttpStatusCode.Forbidden, - 'Failed to get the board configuration!', - 'Please go back to the previous page to check your board info, or change your time range!', + 'Failed to get Board configuration!', + 'Please go back to the previous page and check your board info!', ], [ HttpStatusCode.NotFound, - 'Failed to get the board configuration!', - 'Please go back to the previous page to check your board info, or change your time range!', + 'Failed to get Board configuration!', + 'Please go back to the previous page and check your board info!', ], ])('should got error message when got code is %s', async (code, title, message) => { server.use( @@ -82,11 +83,11 @@ describe('use get board info', () => { expect(result.current.errorMessage.message).toEqual(message); }); - it('should get data', async () => { + it('should get data when mock 4xx error', async () => { server.use( rest.post(MOCK_BOARD_INFO_URL, (_, res, ctx) => { return res( - ctx.status(HttpStatusCode.Ok), + ctx.status(HttpStatusCode.BadRequest), ctx.json({ ignoredTargetFields: [ { @@ -122,24 +123,75 @@ describe('use get board info', () => { }); await waitFor(() => { - expect(result.current.errorMessage.title).toEqual(undefined); + expect(result.current.errorMessage.title).toEqual('Failed to get Board configuration!'); }); - expect(result.current.errorMessage.message).toEqual(undefined); + expect(result.current.errorMessage.message).toEqual( + 'Please go back to the previous page and check your board info!', + ); + }); + it('should get data when mock 3xx error', async () => { server.use( rest.post(MOCK_BOARD_INFO_URL, (_, res, ctx) => { - return res(ctx.status(HttpStatusCode.BadRequest)); + return res( + ctx.status(HttpStatusCode.Unused), + ctx.json({ + code: AXIOS_REQUEST_ERROR_CODE.TIMEOUT, + }), + ); }), ); + const { result } = renderHook(() => useGetBoardInfoEffect()); await act(() => { result.current.getBoardInfo(mockBoardConfig); }); await waitFor(() => { - expect(result.current.errorMessage.title).toEqual('Failed to get the board configuration!'); + expect(result.current.errorMessage.title).toEqual('Failed to get Board configuration!'); }); expect(result.current.errorMessage.message).toEqual( - 'Please go back to the previous page to check your board info, or change your time range!', + 'Please go back to the previous page and check your board info!', ); }); + + // TODO: here + it('should get data when status is OK', async () => { + server.use( + rest.post(MOCK_BOARD_INFO_URL, (_, res, ctx) => { + return res.once( + ctx.status(HttpStatusCode.Ok), + ctx.json({ + ignoredTargetFields: [ + { + key: 'description', + name: 'Description', + flag: false, + }, + ], + jiraColumns: [ + { + key: 'To Do', + value: { + name: 'TODO', + statuses: ['TODO'], + }, + }, + ], + targetFields: [ + { + key: 'issuetype', + name: 'Issue Type', + flag: false, + }, + ], + users: ['heartbeat user'], + }), + ); + }), + ); + const { result } = renderHook(() => useGetBoardInfoEffect()); + await act(() => { + result.current.getBoardInfo(mockBoardConfig); + }); + }); }); diff --git a/frontend/src/constants/resources.ts b/frontend/src/constants/resources.ts index 575d4c9c6f..8a33895883 100644 --- a/frontend/src/constants/resources.ts +++ b/frontend/src/constants/resources.ts @@ -347,7 +347,7 @@ export const BOARD_CONFIG_INFO_TITLE = { UNAUTHORIZED_REQUEST: 'Unauthorized request!', NOT_FOUND: 'Not found!', NO_CONTENT: 'No card within selected date range!', - GENERAL_ERROR: 'Failed to get the board configuration!', + GENERAL_ERROR: 'Failed to get Board configuration!', EMPTY: '', }; @@ -355,7 +355,7 @@ export const BOARD_CONFIG_INFO_ERROR = { FORBIDDEN: 'Please go back to the previous page and change your board token with correct access permission.', NOT_FOUND: 'Please go back to the previous page and check your board info!', NOT_CONTENT: 'Please go back to the previous page and change your collection date, or check your board info!', - GENERAL_ERROR: 'Please go back to the previous page to check your board info, or change your time range!', + GENERAL_ERROR: 'Please go back to the previous page and check your board info!', RETRY: 'Data loading failed, please', }; From edf648e3e692989b9fe314db57f2c56577b6b571 Mon Sep 17 00:00:00 2001 From: PengxiWPix Date: Tue, 23 Apr 2024 17:37:50 +0800 Subject: [PATCH 17/25] ADM-927:[frontend]fix: fix coverage to 100 by delete useless code --- frontend/src/hooks/useGetBoardInfo.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/hooks/useGetBoardInfo.ts b/frontend/src/hooks/useGetBoardInfo.ts index 861244ca84..3a3b9b4487 100644 --- a/frontend/src/hooks/useGetBoardInfo.ts +++ b/frontend/src/hooks/useGetBoardInfo.ts @@ -26,7 +26,7 @@ const boardInfoPartialFailedStatusMapping = (code: string | number) => { if (code == AXIOS_REQUEST_ERROR_CODE.TIMEOUT) { return BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_TIMEOUT; } - const numericCode = typeof code === 'string' ? parseInt(code, 10) : code; + const numericCode = code as number; if (numericCode >= HttpStatusCode.BadRequest || numericCode < HttpStatusCode.InternalServerError) { return BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_4XX; } From 0701d12590d0e18be231cddd11bd238e8d28b77a Mon Sep 17 00:00:00 2001 From: weiraneve <907221539@qq.com> Date: Thu, 25 Apr 2024 09:49:11 +0800 Subject: [PATCH 18/25] ADM-927:[frontend]feat: add partial error popup for metrics step --- frontend/src/constants/commons.ts | 2 +- frontend/src/constants/resources.ts | 4 +++ .../PipelineMetricSelection/index.tsx | 30 ++++++++++++++++- frontend/src/containers/MetricsStep/index.tsx | 14 ++++---- frontend/src/hooks/useGetBoardInfo.ts | 32 +++++++++---------- .../src/hooks/useGetMetricsStepsEffect.ts | 19 +++++++++-- 6 files changed, 74 insertions(+), 27 deletions(-) diff --git a/frontend/src/constants/commons.ts b/frontend/src/constants/commons.ts index 6303591630..544b38c54c 100644 --- a/frontend/src/constants/commons.ts +++ b/frontend/src/constants/commons.ts @@ -88,7 +88,7 @@ export const GRID_CONFIG = { FULL: { XS: 12, MAX_INDEX: 4, FLEX: 0.25 }, }; -export enum BOARD_INFO_FAIL_STATUS { +export enum METRICS_DATA_FAIL_STATUS { NOT_FAILED, PARTIAL_FAILED_4XX, PARTIAL_FAILED_TIMEOUT, diff --git a/frontend/src/constants/resources.ts b/frontend/src/constants/resources.ts index 8a33895883..ca181adb75 100644 --- a/frontend/src/constants/resources.ts +++ b/frontend/src/constants/resources.ts @@ -286,6 +286,10 @@ export const MESSAGE = { 'Failed to get partial Board configuration, please go back to the previous page and check your board info, or click "Next" button to go to Report page.', BOARD_INFO_REQUEST_PARTIAL_FAILED_OTHERS: 'Failed to get partial Board configuration, you can click "Next" button to go to Report page.', + PIPELINE_STEP_REQUEST_PARTIAL_FAILED_4XX: + 'Failed to get partial Pipeline configuration, please go back to the previous page and change your pipeline token with correct access permission, or click "Next" button to go to Report page.', + PIPELINE_STEP_REQUEST_PARTIAL_FAILED_OTHERS: + 'Failed to get partial Pipeline configuration, you can click "Next" button to go to Report page.', }; export const METRICS_CYCLE_SETTING_TABLE_HEADER_BY_COLUMN = [ diff --git a/frontend/src/containers/MetricsStep/DeploymentFrequencySettings/PipelineMetricSelection/index.tsx b/frontend/src/containers/MetricsStep/DeploymentFrequencySettings/PipelineMetricSelection/index.tsx index 00611b70e7..c2da87bd2e 100644 --- a/frontend/src/containers/MetricsStep/DeploymentFrequencySettings/PipelineMetricSelection/index.tsx +++ b/frontend/src/containers/MetricsStep/DeploymentFrequencySettings/PipelineMetricSelection/index.tsx @@ -22,10 +22,12 @@ import { BranchSelection } from '@src/containers/MetricsStep/DeploymentFrequency import { ButtonWrapper, PipelineMetricSelectionWrapper, RemoveButton, WarningMessage } from './style'; import { WarningNotification } from '@src/components/Common/WarningNotification'; import { useGetMetricsStepsEffect } from '@src/hooks/useGetMetricsStepsEffect'; +import { addNotification } from '@src/context/notification/NotificationSlice'; import { uniqPipelineListCrews, updateResponseCrews } from '@src/utils/util'; import { MESSAGE, NO_PIPELINE_STEP_ERROR } from '@src/constants/resources'; import { ErrorNotification } from '@src/components/ErrorNotification'; import { shouldMetricsLoad } from '@src/context/stepper/StepperSlice'; +import { METRICS_DATA_FAIL_STATUS } from '@src/constants/commons'; import { useAppDispatch, useAppSelector } from '@src/hooks'; import { useEffect, useRef, useState } from 'react'; import { Loading } from '@src/components/Loading'; @@ -62,7 +64,7 @@ export const PipelineMetricSelection = ({ }: pipelineMetricSelectionProps) => { const { id, organization, pipelineName, step } = pipelineSetting; const dispatch = useAppDispatch(); - const { isLoading, errorMessage, getSteps } = useGetMetricsStepsEffect(); + const { isLoading, errorMessage, getSteps, stepFailedStatus } = useGetMetricsStepsEffect(); const storeContext = store.getState(); const organizationNameOptions = selectPipelineOrganizations(storeContext); const pipelineNameOptions = selectPipelineNames(storeContext, organization); @@ -130,6 +132,32 @@ export const PipelineMetricSelection = ({ }); }; + useEffect(() => { + const popup = () => { + if (stepFailedStatus === METRICS_DATA_FAIL_STATUS.PARTIAL_FAILED_4XX) { + dispatch( + addNotification({ + type: 'warning', + message: MESSAGE.PIPELINE_STEP_REQUEST_PARTIAL_FAILED_4XX, + }), + ); + } else if ( + stepFailedStatus === METRICS_DATA_FAIL_STATUS.PARTIAL_FAILED_NO_CARDS || + stepFailedStatus === METRICS_DATA_FAIL_STATUS.PARTIAL_FAILED_TIMEOUT + ) { + dispatch( + addNotification({ + type: 'warning', + message: MESSAGE.PIPELINE_STEP_REQUEST_PARTIAL_FAILED_OTHERS, + }), + ); + } + }; + if (!isLoading) { + popup(); + } + }, [stepFailedStatus, dispatch, isLoading]); + return ( {organizationWarningMessage && } diff --git a/frontend/src/containers/MetricsStep/index.tsx b/frontend/src/containers/MetricsStep/index.tsx index 3c36c284a1..62c14dd589 100644 --- a/frontend/src/containers/MetricsStep/index.tsx +++ b/frontend/src/containers/MetricsStep/index.tsx @@ -37,8 +37,8 @@ import DateRangeViewer from '@src/components/Common/DateRangeViewer'; import { useGetBoardInfoEffect } from '@src/hooks/useGetBoardInfo'; import { combineBoardInfo, sortDateRanges } from '@src/utils/util'; import { CycleTime } from '@src/containers/MetricsStep/CycleTime'; +import { METRICS_DATA_FAIL_STATUS } from '@src/constants/commons'; import { RealDone } from '@src/containers/MetricsStep/RealDone'; -import { BOARD_INFO_FAIL_STATUS } from '@src/constants/commons'; import { useCallback, useEffect, useLayoutEffect } from 'react'; import EmptyContent from '@src/components/Common/EmptyContent'; import { useAppDispatch, useAppSelector } from '@src/hooks'; @@ -96,7 +96,7 @@ const MetricsStep = () => { useEffect(() => { const popup = () => { - if (boardInfoFailedStatus === BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_4XX) { + if (boardInfoFailedStatus === METRICS_DATA_FAIL_STATUS.PARTIAL_FAILED_4XX) { dispatch( addNotification({ type: 'warning', @@ -104,8 +104,8 @@ const MetricsStep = () => { }), ); } else if ( - boardInfoFailedStatus === BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_NO_CARDS || - boardInfoFailedStatus === BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_TIMEOUT + boardInfoFailedStatus === METRICS_DATA_FAIL_STATUS.PARTIAL_FAILED_NO_CARDS || + boardInfoFailedStatus === METRICS_DATA_FAIL_STATUS.PARTIAL_FAILED_TIMEOUT ) { dispatch( addNotification({ @@ -144,9 +144,9 @@ const MetricsStep = () => { Board configuration {isEmpty(errorMessage) || - (boardInfoFailedStatus != BOARD_INFO_FAIL_STATUS.ALL_FAILED_4XX && - boardInfoFailedStatus != BOARD_INFO_FAIL_STATUS.ALL_FAILED_TIMEOUT && - boardInfoFailedStatus != BOARD_INFO_FAIL_STATUS.ALL_FAILED_NO_CARDS) ? ( + (boardInfoFailedStatus != METRICS_DATA_FAIL_STATUS.ALL_FAILED_4XX && + boardInfoFailedStatus != METRICS_DATA_FAIL_STATUS.ALL_FAILED_TIMEOUT && + boardInfoFailedStatus != METRICS_DATA_FAIL_STATUS.ALL_FAILED_NO_CARDS) ? ( <> diff --git a/frontend/src/hooks/useGetBoardInfo.ts b/frontend/src/hooks/useGetBoardInfo.ts index 3a3b9b4487..3eb8701175 100644 --- a/frontend/src/hooks/useGetBoardInfo.ts +++ b/frontend/src/hooks/useGetBoardInfo.ts @@ -1,7 +1,7 @@ import { AXIOS_REQUEST_ERROR_CODE, BOARD_CONFIG_INFO_ERROR, BOARD_CONFIG_INFO_TITLE } from '@src/constants/resources'; import { boardInfoClient } from '@src/clients/board/BoardInfoClient'; import { BoardInfoConfigDTO } from '@src/clients/board/dto/request'; -import { BOARD_INFO_FAIL_STATUS } from '@src/constants/commons'; +import { METRICS_DATA_FAIL_STATUS } from '@src/constants/commons'; import { ReactNode, useState } from 'react'; import { HttpStatusCode } from 'axios'; import get from 'lodash/get'; @@ -20,44 +20,44 @@ export interface useGetBoardInfoInterface { getBoardInfo: (data: BoardInfoConfigDTO) => Promise | undefined>; isLoading: boolean; errorMessage: Record; - boardInfoFailedStatus: BOARD_INFO_FAIL_STATUS; + boardInfoFailedStatus: METRICS_DATA_FAIL_STATUS; } const boardInfoPartialFailedStatusMapping = (code: string | number) => { if (code == AXIOS_REQUEST_ERROR_CODE.TIMEOUT) { - return BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_TIMEOUT; + return METRICS_DATA_FAIL_STATUS.PARTIAL_FAILED_TIMEOUT; } const numericCode = code as number; if (numericCode >= HttpStatusCode.BadRequest || numericCode < HttpStatusCode.InternalServerError) { - return BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_4XX; + return METRICS_DATA_FAIL_STATUS.PARTIAL_FAILED_4XX; } - return BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_4XX; + return METRICS_DATA_FAIL_STATUS.PARTIAL_FAILED_4XX; }; -const errorStatusMap = (status: BOARD_INFO_FAIL_STATUS) => { +const errorStatusMap = (status: METRICS_DATA_FAIL_STATUS) => { const errorStatusMap = { - [BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_4XX]: { + [METRICS_DATA_FAIL_STATUS.PARTIAL_FAILED_4XX]: { errorMessage: { title: BOARD_CONFIG_INFO_TITLE.GENERAL_ERROR, message: BOARD_CONFIG_INFO_ERROR.GENERAL_ERROR, code: HttpStatusCode.BadRequest, }, - elevateStatus: BOARD_INFO_FAIL_STATUS.ALL_FAILED_4XX, + elevateStatus: METRICS_DATA_FAIL_STATUS.ALL_FAILED_4XX, }, - [BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_TIMEOUT]: { + [METRICS_DATA_FAIL_STATUS.PARTIAL_FAILED_TIMEOUT]: { errorMessage: { title: BOARD_CONFIG_INFO_TITLE.EMPTY, message: BOARD_CONFIG_INFO_ERROR.RETRY, code: AXIOS_REQUEST_ERROR_CODE.TIMEOUT, }, - elevateStatus: BOARD_INFO_FAIL_STATUS.ALL_FAILED_TIMEOUT, + elevateStatus: METRICS_DATA_FAIL_STATUS.ALL_FAILED_TIMEOUT, }, - [BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_NO_CARDS]: { + [METRICS_DATA_FAIL_STATUS.PARTIAL_FAILED_NO_CARDS]: { errorMessage: { title: BOARD_CONFIG_INFO_TITLE.NO_CONTENT, message: BOARD_CONFIG_INFO_ERROR.NOT_CONTENT, code: AXIOS_REQUEST_ERROR_CODE.NO_CARDS, }, - elevateStatus: BOARD_INFO_FAIL_STATUS.ALL_FAILED_NO_CARDS, + elevateStatus: METRICS_DATA_FAIL_STATUS.ALL_FAILED_NO_CARDS, }, }; return get(errorStatusMap, status); @@ -66,13 +66,13 @@ const errorStatusMap = (status: BOARD_INFO_FAIL_STATUS) => { export const useGetBoardInfoEffect = (): useGetBoardInfoInterface => { const [isLoading, setIsLoading] = useState(false); const [errorMessage, setErrorMessage] = useState({}); - const [boardInfoFailedStatus, setBoardInfoFailedStatus] = useState(BOARD_INFO_FAIL_STATUS.NOT_FAILED); + const [boardInfoFailedStatus, setBoardInfoFailedStatus] = useState(METRICS_DATA_FAIL_STATUS.NOT_FAILED); const getBoardInfo = async (data: BoardInfoConfigDTO) => { setIsLoading(true); setErrorMessage({}); let errorCount = 0; - let localBoardInfoFailedStatus: BOARD_INFO_FAIL_STATUS; + let localBoardInfoFailedStatus: METRICS_DATA_FAIL_STATUS; if (data.dateRanges) { const dateRangeCopy = Array.from(data.dateRanges); @@ -97,8 +97,8 @@ export const useGetBoardInfoEffect = (): useGetBoardInfoInterface => { .then((res) => { if (!res.data) { errorCount++; - localBoardInfoFailedStatus = BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_NO_CARDS; - setBoardInfoFailedStatus(BOARD_INFO_FAIL_STATUS.PARTIAL_FAILED_NO_CARDS); + localBoardInfoFailedStatus = METRICS_DATA_FAIL_STATUS.PARTIAL_FAILED_NO_CARDS; + setBoardInfoFailedStatus(METRICS_DATA_FAIL_STATUS.PARTIAL_FAILED_NO_CARDS); } return res; }) diff --git a/frontend/src/hooks/useGetMetricsStepsEffect.ts b/frontend/src/hooks/useGetMetricsStepsEffect.ts index ed2e679931..7affd93c85 100644 --- a/frontend/src/hooks/useGetMetricsStepsEffect.ts +++ b/frontend/src/hooks/useGetMetricsStepsEffect.ts @@ -1,9 +1,9 @@ import { updateShouldRetryPipelineConfig } from '@src/context/Metrics/metricsSlice'; import { IStepsParams, IStepsRes, metricsClient } from '@src/clients/MetricsClient'; +import { METRICS_DATA_FAIL_STATUS, DURATION } from '@src/constants/commons'; import { useAppDispatch } from '@src/hooks/useAppDispatch'; import { TimeoutError } from '@src/errors/TimeoutError'; import { MESSAGE } from '@src/constants/resources'; -import { DURATION } from '@src/constants/commons'; import { useState } from 'react'; export interface useGetMetricsStepsEffectInterface { @@ -16,6 +16,7 @@ export interface useGetMetricsStepsEffectInterface { ) => Promise; isLoading: boolean; errorMessage: string; + stepFailedStatus: METRICS_DATA_FAIL_STATUS; } const TIMEOUT = 'timeout'; @@ -30,6 +31,7 @@ export const useGetMetricsStepsEffect = (): useGetMetricsStepsEffectInterface => const dispatch = useAppDispatch(); const [isLoading, setIsLoading] = useState(false); const [errorMessage, setErrorMessage] = useState(''); + const [stepFailedStatus, setStepFailedStatus] = useState(METRICS_DATA_FAIL_STATUS.NOT_FAILED); const getSteps = async ( params: IStepsParams[], @@ -44,6 +46,19 @@ export const useGetMetricsStepsEffect = (): useGetMetricsStepsEffectInterface => return metricsClient.getSteps(param, organizationId, buildId, pipelineType, token); }), ); + console.log(allStepsRes); + const hasRejected = allStepsRes.some((stepInfo) => stepInfo.status === 'rejected'); + const hasFulfilled = allStepsRes.some((stepInfo) => stepInfo.status === 'fulfilled'); + if (!hasRejected) { + setStepFailedStatus(METRICS_DATA_FAIL_STATUS.NOT_FAILED); + } else if (hasRejected && hasFulfilled) { + const rejectedStep = allStepsRes.find((stepInfo) => stepInfo.status === 'rejected'); + if ((rejectedStep as PromiseRejectedResult).reason.code == 400) { + setStepFailedStatus(METRICS_DATA_FAIL_STATUS.PARTIAL_FAILED_4XX); + } else { + setStepFailedStatus(METRICS_DATA_FAIL_STATUS.PARTIAL_FAILED_TIMEOUT); + } + } setIsLoading(false); if (allStepsRes.every((stepInfo) => stepInfo.status === 'rejected')) { if (isAllTimeoutError(allStepsRes)) { @@ -83,5 +98,5 @@ export const useGetMetricsStepsEffect = (): useGetMetricsStepsEffectInterface => }, DURATION.ERROR_MESSAGE_TIME); }; - return { isLoading, getSteps, errorMessage }; + return { isLoading, getSteps, errorMessage, stepFailedStatus }; }; From eb6bbc742234fe44428d0fdf12f47ae8b4bedc83 Mon Sep 17 00:00:00 2001 From: PengxiWPix Date: Thu, 25 Apr 2024 10:46:47 +0800 Subject: [PATCH 19/25] ADM-927:[frontend]fix: combined two tests using mockImplementation --- ...MetricsStepPopupTestPartialFailed.test.tsx | 26 +++++++- ...etricsStepPopupTestPartialNoCards.test.tsx | 63 ------------------- 2 files changed, 24 insertions(+), 65 deletions(-) delete mode 100644 frontend/__tests__/containers/MetricsStep/MetricsStepPopupTestPartialNoCards.test.tsx diff --git a/frontend/__tests__/containers/MetricsStep/MetricsStepPopupTestPartialFailed.test.tsx b/frontend/__tests__/containers/MetricsStep/MetricsStepPopupTestPartialFailed.test.tsx index 4596ba690a..de35bb7a92 100644 --- a/frontend/__tests__/containers/MetricsStep/MetricsStepPopupTestPartialFailed.test.tsx +++ b/frontend/__tests__/containers/MetricsStep/MetricsStepPopupTestPartialFailed.test.tsx @@ -28,10 +28,16 @@ jest.mock('@src/context/notification/NotificationSlice', () => ({ addNotification: jest.fn().mockReturnValue({ type: 'ADD_NEW_NOTIFICATION' }), })); +let boardInfoFailStatus = 1; + jest.mock('@src/hooks/useGetBoardInfo', () => ({ ...jest.requireActual('@src/hooks/useGetBoardInfo'), - useGetBoardInfoEffect: jest.fn().mockReturnValue({ - boardInfoFailedStatus: 1, + + + useGetBoardInfoEffect: jest.fn().mockImplementation( () =>{ + return { + boardInfoFailedStatus: boardInfoFailStatus, + } }), })); @@ -48,6 +54,22 @@ describe('MetricsStep', () => { }); it('should show 4xx popup when call get partial 4xx error', async () => { + boardInfoFailStatus = 1 + server.use( + rest.post(MOCK_BOARD_INFO_URL, (_, res, ctx) => { + return res.once(ctx.status(HttpStatusCode.BadRequest)); + }), + ); + + setup(); + + await waitFor(() => { + expect(addNotification).toHaveBeenCalled(); + }); + }); + + it('should show no cards popup when call get partial no cards error', async () => { + boardInfoFailStatus = 3; server.use( rest.post(MOCK_BOARD_INFO_URL, (_, res, ctx) => { return res.once(ctx.status(HttpStatusCode.BadRequest)); diff --git a/frontend/__tests__/containers/MetricsStep/MetricsStepPopupTestPartialNoCards.test.tsx b/frontend/__tests__/containers/MetricsStep/MetricsStepPopupTestPartialNoCards.test.tsx deleted file mode 100644 index 3593eea771..0000000000 --- a/frontend/__tests__/containers/MetricsStep/MetricsStepPopupTestPartialNoCards.test.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import { render, waitFor } from '@testing-library/react'; -import { setupStore } from '../../utils/setupStoreUtil'; -import MetricsStep from '@src/containers/MetricsStep'; -import { Provider } from 'react-redux'; -import { setupServer } from 'msw/node'; -import { rest } from 'msw'; - -import { MOCK_BUILD_KITE_GET_INFO_RESPONSE, MOCK_PIPELINE_GET_INFO_URL, MOCK_BOARD_INFO_URL } from '../../fixtures'; -import { addNotification } from '@src/context/notification/NotificationSlice'; -import { HttpStatusCode } from 'axios'; - -let store = setupStore(); -const server = setupServer( - rest.post(MOCK_PIPELINE_GET_INFO_URL, (req, res, ctx) => - res(ctx.status(200), ctx.body(JSON.stringify(MOCK_BUILD_KITE_GET_INFO_RESPONSE))), - ), -); - -const setup = () => - render( - - - , - ); - -jest.mock('@src/context/notification/NotificationSlice', () => ({ - ...jest.requireActual('@src/context/notification/NotificationSlice'), - addNotification: jest.fn().mockReturnValue({ type: 'ADD_NEW_NOTIFICATION' }), -})); - -jest.mock('@src/hooks/useGetBoardInfo', () => ({ - ...jest.requireActual('@src/hooks/useGetBoardInfo'), - useGetBoardInfoEffect: jest.fn().mockReturnValue({ - boardInfoFailedStatus: 3, - }), -})); - -describe('MetricsStep', () => { - beforeAll(() => server.listen()); - afterAll(() => server.close()); - - beforeEach(() => { - store = setupStore(); - }); - - afterEach(() => { - jest.clearAllMocks(); - }); - - it('should show no cards popup when call get partial no cards error', async () => { - server.use( - rest.post(MOCK_BOARD_INFO_URL, (_, res, ctx) => { - return res.once(ctx.status(HttpStatusCode.BadRequest)); - }), - ); - - setup(); - - await waitFor(() => { - expect(addNotification).toHaveBeenCalled(); - }); - }); -}); From cb3dc79d299549f5498320b7b28365067e633e3c Mon Sep 17 00:00:00 2001 From: weiraneve <907221539@qq.com> Date: Thu, 25 Apr 2024 11:19:14 +0800 Subject: [PATCH 20/25] ADM-927:[frontend]fix: use and logic for error code mapping --- frontend/src/hooks/useGetBoardInfo.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/hooks/useGetBoardInfo.ts b/frontend/src/hooks/useGetBoardInfo.ts index 3eb8701175..169e44c1dc 100644 --- a/frontend/src/hooks/useGetBoardInfo.ts +++ b/frontend/src/hooks/useGetBoardInfo.ts @@ -27,7 +27,7 @@ const boardInfoPartialFailedStatusMapping = (code: string | number) => { return METRICS_DATA_FAIL_STATUS.PARTIAL_FAILED_TIMEOUT; } const numericCode = code as number; - if (numericCode >= HttpStatusCode.BadRequest || numericCode < HttpStatusCode.InternalServerError) { + if (numericCode >= HttpStatusCode.BadRequest && numericCode < HttpStatusCode.InternalServerError) { return METRICS_DATA_FAIL_STATUS.PARTIAL_FAILED_4XX; } return METRICS_DATA_FAIL_STATUS.PARTIAL_FAILED_4XX; From 57ccc62663dd3072794e5b1963b0571be51cc52c Mon Sep 17 00:00:00 2001 From: weiraneve <907221539@qq.com> Date: Thu, 25 Apr 2024 11:24:13 +0800 Subject: [PATCH 21/25] ADM-927:[frontend]fix: fix code space --- .../MetricsStep/MetricsStepPopupTestPartialFailed.test.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/frontend/__tests__/containers/MetricsStep/MetricsStepPopupTestPartialFailed.test.tsx b/frontend/__tests__/containers/MetricsStep/MetricsStepPopupTestPartialFailed.test.tsx index de35bb7a92..245ead79f3 100644 --- a/frontend/__tests__/containers/MetricsStep/MetricsStepPopupTestPartialFailed.test.tsx +++ b/frontend/__tests__/containers/MetricsStep/MetricsStepPopupTestPartialFailed.test.tsx @@ -33,11 +33,10 @@ let boardInfoFailStatus = 1; jest.mock('@src/hooks/useGetBoardInfo', () => ({ ...jest.requireActual('@src/hooks/useGetBoardInfo'), - - useGetBoardInfoEffect: jest.fn().mockImplementation( () =>{ + useGetBoardInfoEffect: jest.fn().mockImplementation(() => { return { boardInfoFailedStatus: boardInfoFailStatus, - } + }; }), })); @@ -54,7 +53,7 @@ describe('MetricsStep', () => { }); it('should show 4xx popup when call get partial 4xx error', async () => { - boardInfoFailStatus = 1 + boardInfoFailStatus = 1; server.use( rest.post(MOCK_BOARD_INFO_URL, (_, res, ctx) => { return res.once(ctx.status(HttpStatusCode.BadRequest)); From 69d699f4d4b715dc259cda2a059694d644f31bac Mon Sep 17 00:00:00 2001 From: weiraneve <907221539@qq.com> Date: Thu, 25 Apr 2024 11:25:12 +0800 Subject: [PATCH 22/25] ADM-927:[frontend]refactor: refactor pipeline info request error title --- frontend/src/clients/pipeline/PipelineToolClient.ts | 10 +++++++++- frontend/src/constants/resources.ts | 2 ++ frontend/src/hooks/useGetMetricsStepsEffect.ts | 1 - 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/frontend/src/clients/pipeline/PipelineToolClient.ts b/frontend/src/clients/pipeline/PipelineToolClient.ts index ee74a0affc..a272da0470 100644 --- a/frontend/src/clients/pipeline/PipelineToolClient.ts +++ b/frontend/src/clients/pipeline/PipelineToolClient.ts @@ -3,6 +3,7 @@ import { PIPELINE_TOOL_GET_INFO_ERROR_CASE_TEXT_MAPPING, PIPELINE_TOOL_GET_INFO_ERROR_MESSAGE, UNKNOWN_ERROR_TITLE, + PIPELINE_CONFIG_TITLE, } from '@src/constants/resources'; import { IPipelineVerifyRequestDTO, PipelineInfoRequestDTO } from '@src/clients/pipeline/dto/request'; import { IPipelineInfoResponseDTO } from '@src/clients/pipeline/dto/response'; @@ -64,7 +65,14 @@ export class PipelineToolClient extends HttpClient { if (isAppError(e)) { const exception = e as IAppError; result.code = exception.code; - result.errorTitle = PIPELINE_TOOL_GET_INFO_ERROR_CASE_TEXT_MAPPING[`${exception.code}`] || UNKNOWN_ERROR_TITLE; + if ( + (exception.code as number) >= HttpStatusCode.BadRequest && + (exception.code as number) < HttpStatusCode.InternalServerError + ) { + result.errorTitle = PIPELINE_CONFIG_TITLE; + } else { + result.errorTitle = UNKNOWN_ERROR_TITLE; + } } result.errorMessage = PIPELINE_TOOL_GET_INFO_ERROR_MESSAGE; diff --git a/frontend/src/constants/resources.ts b/frontend/src/constants/resources.ts index ca181adb75..5a06599746 100644 --- a/frontend/src/constants/resources.ts +++ b/frontend/src/constants/resources.ts @@ -355,6 +355,8 @@ export const BOARD_CONFIG_INFO_TITLE = { EMPTY: '', }; +export const PIPELINE_CONFIG_TITLE = 'Failed to get Pipeline configuration!'; + export const BOARD_CONFIG_INFO_ERROR = { FORBIDDEN: 'Please go back to the previous page and change your board token with correct access permission.', NOT_FOUND: 'Please go back to the previous page and check your board info!', diff --git a/frontend/src/hooks/useGetMetricsStepsEffect.ts b/frontend/src/hooks/useGetMetricsStepsEffect.ts index 7affd93c85..0c54841eac 100644 --- a/frontend/src/hooks/useGetMetricsStepsEffect.ts +++ b/frontend/src/hooks/useGetMetricsStepsEffect.ts @@ -46,7 +46,6 @@ export const useGetMetricsStepsEffect = (): useGetMetricsStepsEffectInterface => return metricsClient.getSteps(param, organizationId, buildId, pipelineType, token); }), ); - console.log(allStepsRes); const hasRejected = allStepsRes.some((stepInfo) => stepInfo.status === 'rejected'); const hasFulfilled = allStepsRes.some((stepInfo) => stepInfo.status === 'fulfilled'); if (!hasRejected) { From 6c74104b35461eafb9332663a9c77a690e6974dc Mon Sep 17 00:00:00 2001 From: weiraneve <907221539@qq.com> Date: Thu, 25 Apr 2024 15:45:47 +0800 Subject: [PATCH 23/25] ADM-927:[frontend]test: add pipeline failed status test --- .../client/PipelineToolClient.test.ts | 8 +- ...icSelectionPopupTestPartialFailed.test.tsx | 85 +++++++++++++++++++ .../MetricsStep/MetricsStep.test.tsx | 13 --- ...MetricsStepPopupTestPartialFailed.test.tsx | 32 +------ .../__tests__/hooks/useGetBoardInfo.test.tsx | 1 - .../hooks/useGetMetricsStepsEffect.test.tsx | 39 +++++++++ 6 files changed, 132 insertions(+), 46 deletions(-) create mode 100644 frontend/__tests__/containers/MetricsStep/DeploymentFrequencySettings/PipelineMetricSelectionPopupTestPartialFailed.test.tsx diff --git a/frontend/__tests__/client/PipelineToolClient.test.ts b/frontend/__tests__/client/PipelineToolClient.test.ts index ed50cd7c95..acf485b6ec 100644 --- a/frontend/__tests__/client/PipelineToolClient.test.ts +++ b/frontend/__tests__/client/PipelineToolClient.test.ts @@ -79,22 +79,22 @@ describe('PipelineToolClient', () => { }, { code: HttpStatusCode.BadRequest, - errorTitle: 'Invalid input!', + errorTitle: 'Failed to get Pipeline configuration!', errorMessage, }, { code: HttpStatusCode.Unauthorized, - errorTitle: 'Unauthorized request!', + errorTitle: 'Failed to get Pipeline configuration!', errorMessage, }, { code: HttpStatusCode.Forbidden, - errorTitle: 'Forbidden request!', + errorTitle: 'Failed to get Pipeline configuration!', errorMessage, }, { code: HttpStatusCode.NotFound, - errorTitle: 'Not found!', + errorTitle: 'Failed to get Pipeline configuration!', errorMessage, }, ]; diff --git a/frontend/__tests__/containers/MetricsStep/DeploymentFrequencySettings/PipelineMetricSelectionPopupTestPartialFailed.test.tsx b/frontend/__tests__/containers/MetricsStep/DeploymentFrequencySettings/PipelineMetricSelectionPopupTestPartialFailed.test.tsx new file mode 100644 index 0000000000..ce9032322d --- /dev/null +++ b/frontend/__tests__/containers/MetricsStep/DeploymentFrequencySettings/PipelineMetricSelectionPopupTestPartialFailed.test.tsx @@ -0,0 +1,85 @@ +import { render, waitFor } from '@testing-library/react'; +import { setupStore } from '@test/utils/setupStoreUtil'; +import { Provider } from 'react-redux'; + +import { PipelineMetricSelection } from '@src/containers/MetricsStep/DeploymentFrequencySettings/PipelineMetricSelection'; +import { IPipelineConfig, updateShouldGetPipelineConfig } from '@src/context/Metrics/metricsSlice'; +import { addNotification } from '@src/context/notification/NotificationSlice'; +import { METRICS_DATA_FAIL_STATUS } from '@src/constants/commons'; +import { PIPELINE_SETTING_TYPES } from '@test/fixtures'; + +const store = setupStore(); +let stepFailStatus = METRICS_DATA_FAIL_STATUS.NOT_FAILED; + +jest.mock('@src/context/notification/NotificationSlice', () => ({ + ...jest.requireActual('@src/context/notification/NotificationSlice'), + addNotification: jest.fn().mockReturnValue({ type: 'ADD_NEW_NOTIFICATION' }), +})); + +jest.mock('@src/hooks/useGetMetricsStepsEffect', () => ({ + ...jest.requireActual('@src/hooks/useGetMetricsStepsEffect'), + + useGetMetricsStepsEffect: jest.fn().mockImplementation(() => { + return { + stepFailedStatus: stepFailStatus, + }; + }), +})); + +describe('PipelineMetricSelection', () => { + const deploymentFrequencySetting = { + id: 0, + organization: '', + pipelineName: '', + step: '', + branches: [], + }; + const mockHandleClickRemoveButton = jest.fn(); + const mockUpdatePipeline = jest.fn(); + const mockSetLoadingCompletedNumber = jest.fn(); + + const setup = async ( + deploymentFrequencySetting: IPipelineConfig, + isShowRemoveButton: boolean, + isDuplicated: boolean, + ) => { + store.dispatch(updateShouldGetPipelineConfig(true)); + return render( + + + , + ); + }; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should show 4xx popup when call pipeline step to get partial 4xx error', async () => { + stepFailStatus = METRICS_DATA_FAIL_STATUS.PARTIAL_FAILED_4XX; + await setup(deploymentFrequencySetting, true, false); + + await waitFor(() => { + expect(addNotification).toHaveBeenCalled(); + }); + }); + + it('should show timeout popup when call pipeline step to get partial timeout error', async () => { + stepFailStatus = METRICS_DATA_FAIL_STATUS.PARTIAL_FAILED_TIMEOUT; + await setup(deploymentFrequencySetting, true, false); + + await waitFor(() => { + expect(addNotification).toHaveBeenCalled(); + }); + }); +}); diff --git a/frontend/__tests__/containers/MetricsStep/MetricsStep.test.tsx b/frontend/__tests__/containers/MetricsStep/MetricsStep.test.tsx index 6140ab011c..03dd5de96e 100644 --- a/frontend/__tests__/containers/MetricsStep/MetricsStep.test.tsx +++ b/frontend/__tests__/containers/MetricsStep/MetricsStep.test.tsx @@ -53,19 +53,6 @@ const setup = () => , ); -// const { getBoardInfo, isLoading, errorMessage, boardInfoFailedStatus } = useGetBoardInfoEffect(); - -// jest.mock('@src/hooks/useGetBoardInfo', () => ({ -// ...jest.requireActual('@src/hooks/useGetBoardInfo'), -// -// useGetBoardInfoEffect: jest.fn().mockReturnValue({ -// getBoardInfo: result.current.getBoardInfo, -// isLoading: useGetBoardInfoEffect().isLoading, -// errorMessage: useGetBoardInfoEffect().errorMessage, -// boardInfoFailedStatus: 1, -// }), -// })); - describe('MetricsStep', () => { beforeAll(() => server.listen()); afterAll(() => server.close()); diff --git a/frontend/__tests__/containers/MetricsStep/MetricsStepPopupTestPartialFailed.test.tsx b/frontend/__tests__/containers/MetricsStep/MetricsStepPopupTestPartialFailed.test.tsx index 245ead79f3..4fd87aebd2 100644 --- a/frontend/__tests__/containers/MetricsStep/MetricsStepPopupTestPartialFailed.test.tsx +++ b/frontend/__tests__/containers/MetricsStep/MetricsStepPopupTestPartialFailed.test.tsx @@ -2,20 +2,11 @@ import { render, waitFor } from '@testing-library/react'; import { setupStore } from '../../utils/setupStoreUtil'; import MetricsStep from '@src/containers/MetricsStep'; import { Provider } from 'react-redux'; -import { setupServer } from 'msw/node'; -import { rest } from 'msw'; -import { MOCK_BUILD_KITE_GET_INFO_RESPONSE, MOCK_PIPELINE_GET_INFO_URL, MOCK_BOARD_INFO_URL } from '../../fixtures'; import { addNotification } from '@src/context/notification/NotificationSlice'; -import { HttpStatusCode } from 'axios'; +import { METRICS_DATA_FAIL_STATUS } from '@src/constants/commons'; let store = setupStore(); -const server = setupServer( - rest.post(MOCK_PIPELINE_GET_INFO_URL, (req, res, ctx) => - res(ctx.status(200), ctx.body(JSON.stringify(MOCK_BUILD_KITE_GET_INFO_RESPONSE))), - ), -); - const setup = () => render( @@ -28,7 +19,7 @@ jest.mock('@src/context/notification/NotificationSlice', () => ({ addNotification: jest.fn().mockReturnValue({ type: 'ADD_NEW_NOTIFICATION' }), })); -let boardInfoFailStatus = 1; +let boardInfoFailStatus = METRICS_DATA_FAIL_STATUS.NOT_FAILED; jest.mock('@src/hooks/useGetBoardInfo', () => ({ ...jest.requireActual('@src/hooks/useGetBoardInfo'), @@ -41,9 +32,6 @@ jest.mock('@src/hooks/useGetBoardInfo', () => ({ })); describe('MetricsStep', () => { - beforeAll(() => server.listen()); - afterAll(() => server.close()); - beforeEach(() => { store = setupStore(); }); @@ -53,13 +41,7 @@ describe('MetricsStep', () => { }); it('should show 4xx popup when call get partial 4xx error', async () => { - boardInfoFailStatus = 1; - server.use( - rest.post(MOCK_BOARD_INFO_URL, (_, res, ctx) => { - return res.once(ctx.status(HttpStatusCode.BadRequest)); - }), - ); - + boardInfoFailStatus = METRICS_DATA_FAIL_STATUS.PARTIAL_FAILED_4XX; setup(); await waitFor(() => { @@ -68,13 +50,7 @@ describe('MetricsStep', () => { }); it('should show no cards popup when call get partial no cards error', async () => { - boardInfoFailStatus = 3; - server.use( - rest.post(MOCK_BOARD_INFO_URL, (_, res, ctx) => { - return res.once(ctx.status(HttpStatusCode.BadRequest)); - }), - ); - + boardInfoFailStatus = METRICS_DATA_FAIL_STATUS.PARTIAL_FAILED_NO_CARDS; setup(); await waitFor(() => { diff --git a/frontend/__tests__/hooks/useGetBoardInfo.test.tsx b/frontend/__tests__/hooks/useGetBoardInfo.test.tsx index 94da0d2548..750b0ea271 100644 --- a/frontend/__tests__/hooks/useGetBoardInfo.test.tsx +++ b/frontend/__tests__/hooks/useGetBoardInfo.test.tsx @@ -154,7 +154,6 @@ describe('use get board info', () => { ); }); - // TODO: here it('should get data when status is OK', async () => { server.use( rest.post(MOCK_BOARD_INFO_URL, (_, res, ctx) => { diff --git a/frontend/__tests__/hooks/useGetMetricsStepsEffect.test.tsx b/frontend/__tests__/hooks/useGetMetricsStepsEffect.test.tsx index 8f2ceb4c23..d16ab83f6f 100644 --- a/frontend/__tests__/hooks/useGetMetricsStepsEffect.test.tsx +++ b/frontend/__tests__/hooks/useGetMetricsStepsEffect.test.tsx @@ -1,6 +1,7 @@ import { useGetMetricsStepsEffect } from '@src/hooks/useGetMetricsStepsEffect'; import { AXIOS_REQUEST_ERROR_CODE } from '@src/constants/resources'; import { act, renderHook, waitFor } from '@testing-library/react'; +import { METRICS_DATA_FAIL_STATUS } from '@src/constants/commons'; import { metricsClient } from '@src/clients/MetricsClient'; import { setupStore } from '@test/utils/setupStoreUtil'; import { TimeoutError } from '@src/errors/TimeoutError'; @@ -67,6 +68,44 @@ describe('use get steps effect', () => { }); }); + it('should get the steps failed status partial 4xx from steps res', async () => { + metricsClient.getSteps = jest + .fn() + .mockReturnValueOnce({ + response: ['a', 'b', 'c'], + haveStep: true, + branches: ['branchA', 'branchB'], + pipelineCrews: ['crewA', 'crewB'], + }) + .mockRejectedValue({ + code: 400, + }); + const { result } = renderHook(() => useGetMetricsStepsEffect()); + await act(async () => { + await result.current.getSteps(params, buildId, organizationId, pipelineType, token); + }); + expect(result.current.stepFailedStatus).toEqual(METRICS_DATA_FAIL_STATUS.PARTIAL_FAILED_4XX); + }); + + it('should get the steps failed status partial timeout from steps res', async () => { + metricsClient.getSteps = jest + .fn() + .mockReturnValueOnce({ + response: ['a', 'b', 'c'], + haveStep: true, + branches: ['branchA', 'branchB'], + pipelineCrews: ['crewA', 'crewB'], + }) + .mockRejectedValue({ + code: 'NETWORK_TIMEOUT', + }); + const { result } = renderHook(() => useGetMetricsStepsEffect()); + await act(async () => { + await result.current.getSteps(params, buildId, organizationId, pipelineType, token); + }); + expect(result.current.stepFailedStatus).toEqual(METRICS_DATA_FAIL_STATUS.PARTIAL_FAILED_TIMEOUT); + }); + it('should set error message when get steps throw error', async () => { jest.useFakeTimers(); metricsClient.getSteps = jest.fn().mockImplementation(() => { From fae697f128de77c62901c1b3ee44c34214cb2670 Mon Sep 17 00:00:00 2001 From: weiraneve <907221539@qq.com> Date: Thu, 25 Apr 2024 16:50:11 +0800 Subject: [PATCH 24/25] ADM-927:[frontend]test: rename test --- frontend/__tests__/hooks/useGetMetricsStepsEffect.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/__tests__/hooks/useGetMetricsStepsEffect.test.tsx b/frontend/__tests__/hooks/useGetMetricsStepsEffect.test.tsx index d16ab83f6f..f979b73669 100644 --- a/frontend/__tests__/hooks/useGetMetricsStepsEffect.test.tsx +++ b/frontend/__tests__/hooks/useGetMetricsStepsEffect.test.tsx @@ -68,7 +68,7 @@ describe('use get steps effect', () => { }); }); - it('should get the steps failed status partial 4xx from steps res', async () => { + it('should get the steps failed status when partial 4xx response from steps res', async () => { metricsClient.getSteps = jest .fn() .mockReturnValueOnce({ @@ -87,7 +87,7 @@ describe('use get steps effect', () => { expect(result.current.stepFailedStatus).toEqual(METRICS_DATA_FAIL_STATUS.PARTIAL_FAILED_4XX); }); - it('should get the steps failed status partial timeout from steps res', async () => { + it('should get the steps failed status when partial timeout response from steps res', async () => { metricsClient.getSteps = jest .fn() .mockReturnValueOnce({ From eb200b1ec6eb5975ad30c5ee2bee18e73dcbd494 Mon Sep 17 00:00:00 2001 From: weiraneve <907221539@qq.com> Date: Fri, 26 Apr 2024 10:24:48 +0800 Subject: [PATCH 25/25] ADM-927:[frontend]test: rename test --- frontend/__tests__/containers/MetricsStep/MetricsStep.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/__tests__/containers/MetricsStep/MetricsStep.test.tsx b/frontend/__tests__/containers/MetricsStep/MetricsStep.test.tsx index 03dd5de96e..c1af8a8fc1 100644 --- a/frontend/__tests__/containers/MetricsStep/MetricsStep.test.tsx +++ b/frontend/__tests__/containers/MetricsStep/MetricsStep.test.tsx @@ -304,7 +304,7 @@ describe('MetricsStep', () => { ).toBeInTheDocument(); }); - it('should be render Failed message container when get 4xx error', async () => { + it('should be render failed message container when get 4xx error', async () => { store.dispatch(updateShouldGetBoardConfig(true)); server.use( rest.post(MOCK_BOARD_INFO_URL, (_, res, ctx) => {