From ba36dac0aa88b4892535ed732e1a4e59106e56a0 Mon Sep 17 00:00:00 2001 From: zhou-yinyuan Date: Tue, 3 Sep 2024 14:20:12 +0800 Subject: [PATCH 1/3] ADM-999 [frontend][backend]: try to fix e2e test --- frontend/e2e/pages/metrics/metrics-step.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/e2e/pages/metrics/metrics-step.ts b/frontend/e2e/pages/metrics/metrics-step.ts index 8f9c84ad2..5014e4d07 100644 --- a/frontend/e2e/pages/metrics/metrics-step.ts +++ b/frontend/e2e/pages/metrics/metrics-step.ts @@ -227,9 +227,9 @@ export class MetricsStep { this.homeIcon = page.getByLabel('Home'); this.sourceControlSettingSection = page.getByLabel('Source Control Configuration Section'); - this.sourceControlOrganizationSelect = this.sourceControlSettingSection.getByLabel('Organization *'); - this.sourceControlRepoSelect = this.sourceControlSettingSection.getByLabel('Repo *'); - this.sourceControlBranchSelect = this.sourceControlSettingSection.getByLabel('Branches *'); + this.sourceControlOrganizationSelect = this.sourceControlSettingSection.getByLabel('Organization *').first(); + this.sourceControlRepoSelect = this.sourceControlSettingSection.getByLabel('Repo *').first(); + this.sourceControlBranchSelect = this.sourceControlSettingSection.getByLabel('Branches *').first(); this.sourceControlDefaultBranchSelectContainer = this.sourceControlSettingSection.getByLabel( 'Source control Branch AutoComplete', ); From 8938c86509c209aa30ebdafa11a6b6eb27e93a78 Mon Sep 17 00:00:00 2001 From: zhou-yinyuan Date: Tue, 3 Sep 2024 16:21:47 +0800 Subject: [PATCH 2/3] ADM-999 [frontend][backend]: fix e2e test and change the logic --- .../__tests__/context/metricsSlice.test.ts | 34 +-------- .../SouceControlConfiguration/index.tsx | 2 +- frontend/src/context/Metrics/metricsSlice.ts | 70 +++++++++---------- frontend/src/context/config/configSlice.ts | 4 ++ ...SourceControlConfigurationBranchEffect.tsx | 8 +-- ...ControlConfigurationOrganizationEffect.tsx | 20 +++--- ...etSourceControlConfigurationRepoEffect.tsx | 9 +-- 7 files changed, 57 insertions(+), 90 deletions(-) diff --git a/frontend/__tests__/context/metricsSlice.test.ts b/frontend/__tests__/context/metricsSlice.test.ts index 02b9e5d28..23a8ccab6 100644 --- a/frontend/__tests__/context/metricsSlice.test.ts +++ b/frontend/__tests__/context/metricsSlice.test.ts @@ -1638,11 +1638,8 @@ describe('saveMetricsSetting reducer', () => { expect(savedMetricsSetting.sourceControlConfigurationSettings).toEqual(expectedSourceControlConfigurationSettings); }); - it('should return source control settings when handle updateSourceControlConfigurationSettingsFirstInto and isProjectCreated is true and setting is empty', () => { - const expectedSourceControlConfigurationSettings = [ - { id: 0, organization: '', repo: '', branches: [] }, - { id: 1, organization: '', repo: '', branches: [] }, - ]; + it('should return source control settings when handle updateSourceControlConfigurationSettingsFirstInto and setting is empty', () => { + const expectedSourceControlConfigurationSettings = [{ id: 0, organization: '', repo: '', branches: [] }]; const savedMetricsSetting = saveMetricsSettingReducer( initState, updateSourceControlConfigurationSettingsFirstInto({ @@ -1655,31 +1652,7 @@ describe('saveMetricsSetting reducer', () => { expect(savedMetricsSetting.sourceControlConfigurationSettings).toEqual(expectedSourceControlConfigurationSettings); }); - it('should return source control settings when handle updateSourceControlConfigurationSettingsFirstInto and isProjectCreated is true and setting is not empty', () => { - const existedSourceControlConfigurationSettings = [ - { id: 1, organization: 'test-org1', repo: 'test-repo1', branches: ['test-branch1'] }, - ]; - const expectedSourceControlConfigurationSettings = [ - { id: 1, organization: 'test-org1', repo: 'test-repo1', branches: ['test-branch1'] }, - ]; - const state = { - ...initState, - sourceControlConfigurationSettings: existedSourceControlConfigurationSettings, - }; - - const savedMetricsSetting = saveMetricsSettingReducer( - state, - updateSourceControlConfigurationSettingsFirstInto({ - name: ['test1', 'test2'], - isProjectCreated: true, - type: 'organization', - }), - ); - - expect(savedMetricsSetting.sourceControlConfigurationSettings).toEqual(expectedSourceControlConfigurationSettings); - }); - - it('should return source control settings when handle updateSourceControlConfigurationSettingsFirstInto and isProjectCreated is false and setting is empty', () => { + it('should return source control settings when handle updateSourceControlConfigurationSettingsFirstInto and setting is empty', () => { const existedImportedSourceControlSettings = [ { id: 1, organization: 'test-org1', repo: 'test-repo1', branches: ['test-branch1'] }, { id: 2, organization: 'test-org2', repo: 'test-repo2', branches: ['test-branch2'] }, @@ -1698,7 +1671,6 @@ describe('saveMetricsSetting reducer', () => { state, updateSourceControlConfigurationSettingsFirstInto({ name: ['test-org1', 'test2'], - isProjectCreated: false, type: 'organization', }), ); diff --git a/frontend/src/containers/MetricsStep/SouceControlConfiguration/index.tsx b/frontend/src/containers/MetricsStep/SouceControlConfiguration/index.tsx index c6c873a49..6aa22b101 100644 --- a/frontend/src/containers/MetricsStep/SouceControlConfiguration/index.tsx +++ b/frontend/src/containers/MetricsStep/SouceControlConfiguration/index.tsx @@ -94,7 +94,7 @@ export const SourceControlConfiguration = () => { setLoadingCompletedNumber={setLoadingCompletedNumber} /> ))} - + {shouldShowCrews && ( { - const { name, isProjectCreated, type } = action.payload; + const { name, type } = action.payload; const sourceControlConfigurationSettings = state.sourceControlConfigurationSettings; - if (isProjectCreated) { - state.sourceControlConfigurationSettings = - sourceControlConfigurationSettings.length > 0 - ? sourceControlConfigurationSettings - : name.map((it: string, index: number) => ({ - id: index, + + let validSourceControlConfigurationSettings = + sourceControlConfigurationSettings.length > 0 + ? sourceControlConfigurationSettings + : state.importedData.importedSourceControlSettings + .filter((it) => it.id !== undefined) + .map((it) => ({ + id: it.id, + organization: it.organization, + repo: it.repo, + branches: it.branches, + })); + validSourceControlConfigurationSettings = + validSourceControlConfigurationSettings.length > 0 + ? validSourceControlConfigurationSettings + : [ + { + id: 0, organization: '', repo: '', branches: [], - })); - } else { - let validSourceControlConfigurationSettings = - sourceControlConfigurationSettings.length > 0 - ? sourceControlConfigurationSettings - : state.importedData.importedSourceControlSettings - .filter((it) => it.id !== undefined) - .map((it) => ({ - id: it.id, - organization: it.organization, - repo: it.repo, - branches: it.branches, - })); - - if (type === 'organization') { - validSourceControlConfigurationSettings = validSourceControlConfigurationSettings.filter( - (it) => it['organization'] === '' || name.includes(it['organization']), - ); - } else if (type === 'repo') { - validSourceControlConfigurationSettings = validSourceControlConfigurationSettings.filter( - (it) => it['repo'] === '' || name.includes(it['repo']), - ); - } else { - validSourceControlConfigurationSettings = validSourceControlConfigurationSettings.filter( - (it) => it['branches'].length === 0 || it['branches'].filter((branch) => name.includes(branch)), - ); - } + }, + ]; - state.sourceControlConfigurationSettings = validSourceControlConfigurationSettings; + if (type === 'organization') { + validSourceControlConfigurationSettings = validSourceControlConfigurationSettings.filter( + (it) => it['organization'] === '' || name.includes(it['organization']), + ); + } else if (type === 'repo') { + validSourceControlConfigurationSettings = validSourceControlConfigurationSettings.filter( + (it) => it['repo'] === '' || name.includes(it['repo']), + ); + } else { + validSourceControlConfigurationSettings = validSourceControlConfigurationSettings.filter( + (it) => it['branches'].length === 0 || it['branches'].filter((branch) => name.includes(branch)), + ); } + + state.sourceControlConfigurationSettings = validSourceControlConfigurationSettings; }, updateShouldGetBoardConfig: (state, action) => { diff --git a/frontend/src/context/config/configSlice.ts b/frontend/src/context/config/configSlice.ts index 6a87a198b..42c4476fd 100644 --- a/frontend/src/context/config/configSlice.ts +++ b/frontend/src/context/config/configSlice.ts @@ -220,6 +220,9 @@ export const configSlice = createSlice({ updateSourceControl: (state, action) => { state.sourceControl.config = action.payload; }, + clearSourceControlVerifiedResponse: (state) => { + state.sourceControl.verifiedResponse.repoList = { name: 'root', value: '-1', children: [] }; + }, updateSourceControlVerifiedResponse: (state, action) => { const namesList = ['organization', 'repo', 'branch', 'time', 'crew']; const matchedRepoList = state.sourceControl.verifiedResponse.repoList; @@ -249,6 +252,7 @@ export const { updatePipelineTool, updatePipelineToolVerifyResponse, updateSourceControl, + clearSourceControlVerifiedResponse, updateSourceControlVerifiedResponse, updatePipelineToolVerifyResponseSteps, resetImportedData, diff --git a/frontend/src/hooks/useGetSourceControlConfigurationBranchEffect.tsx b/frontend/src/hooks/useGetSourceControlConfigurationBranchEffect.tsx index edb46de62..5f81e68c5 100644 --- a/frontend/src/hooks/useGetSourceControlConfigurationBranchEffect.tsx +++ b/frontend/src/hooks/useGetSourceControlConfigurationBranchEffect.tsx @@ -1,8 +1,4 @@ -import { - selectIsProjectCreated, - selectSourceControl, - updateSourceControlVerifiedResponse, -} from '@src/context/config/configSlice'; +import { selectSourceControl, updateSourceControlVerifiedResponse } from '@src/context/config/configSlice'; import { updateSourceControlConfigurationSettingsFirstInto } from '@src/context/Metrics/metricsSlice'; import { sourceControlClient } from '@src/clients/sourceControl/SourceControlClient'; import { useAppDispatch, useAppSelector } from '@src/hooks/index'; @@ -20,7 +16,6 @@ export const useGetSourceControlConfigurationBranchEffect = (): IUseGetSourceCon const [isLoading, setIsLoading] = useState(false); const [isGetBranch, setIsGetBranch] = useState(false); const restoredSourceControlInfo = useAppSelector(selectSourceControl); - const isProjectCreated = useAppSelector(selectIsProjectCreated); function getEnumKeyByEnumValue(enumValue: string): SourceControlTypes { return Object.entries(SourceControlTypes) @@ -57,7 +52,6 @@ export const useGetSourceControlConfigurationBranchEffect = (): IUseGetSourceCon dispatch( updateSourceControlConfigurationSettingsFirstInto({ ...response.data, - isProjectCreated, type: 'branch', }), ); diff --git a/frontend/src/hooks/useGetSourceControlConfigurationOrganizationEffect.tsx b/frontend/src/hooks/useGetSourceControlConfigurationOrganizationEffect.tsx index 5fb71c04d..41ba36313 100644 --- a/frontend/src/hooks/useGetSourceControlConfigurationOrganizationEffect.tsx +++ b/frontend/src/hooks/useGetSourceControlConfigurationOrganizationEffect.tsx @@ -1,12 +1,12 @@ import { - selectShouldGetSourceControlConfig, - updateSourceControlConfigurationSettingsFirstInto, -} from '@src/context/Metrics/metricsSlice'; -import { - selectIsProjectCreated, + clearSourceControlVerifiedResponse, selectSourceControl, updateSourceControlVerifiedResponse, } from '@src/context/config/configSlice'; +import { + selectShouldGetSourceControlConfig, + updateSourceControlConfigurationSettingsFirstInto, +} from '@src/context/Metrics/metricsSlice'; import { ISourceControlGetOrganizationResponseDTO } from '@src/clients/sourceControl/dto/response'; import { sourceControlClient } from '@src/clients/sourceControl/SourceControlClient'; import { useAppDispatch, useAppSelector } from '@src/hooks/index'; @@ -20,6 +20,7 @@ export interface IUseGetSourceControlConfigurationStateInterface { readonly info: ISourceControlGetOrganizationResponseDTO; readonly isFirstFetch: boolean; } + export const useGetSourceControlConfigurationOrganizationEffect = (): IUseGetSourceControlConfigurationStateInterface => { const defaultInfoStructure = { @@ -34,7 +35,6 @@ export const useGetSourceControlConfigurationOrganizationEffect = const restoredSourceControlInfo = useAppSelector(selectSourceControl); const shouldGetSourceControlConfig = useAppSelector(selectShouldGetSourceControlConfig); const [isFirstFetch, setIsFirstFetch] = useState(shouldGetSourceControlConfig); - const isProjectCreated = useAppSelector(selectIsProjectCreated); function getEnumKeyByEnumValue(enumValue: string): SourceControlTypes { return Object.entries(SourceControlTypes) @@ -61,7 +61,6 @@ export const useGetSourceControlConfigurationOrganizationEffect = dispatch( updateSourceControlConfigurationSettingsFirstInto({ ...response.data, - isProjectCreated, type: 'organization', }), ); @@ -70,7 +69,7 @@ export const useGetSourceControlConfigurationOrganizationEffect = setIsLoading(false); setIsFirstFetch(false); } - }, [dispatch, restoredSourceControlInfo.token, restoredSourceControlInfo.type, isProjectCreated]); + }, [dispatch, restoredSourceControlInfo.token, restoredSourceControlInfo.type]); useEffect(() => { if (!apiTouchedRef.current && !isLoading) { @@ -78,6 +77,11 @@ export const useGetSourceControlConfigurationOrganizationEffect = getSourceControlInfo(); } }, [getSourceControlInfo, isLoading]); + + useEffect(() => { + dispatch(clearSourceControlVerifiedResponse()); + }, [dispatch, restoredSourceControlInfo.token]); + return { isLoading, getSourceControlInfo, diff --git a/frontend/src/hooks/useGetSourceControlConfigurationRepoEffect.tsx b/frontend/src/hooks/useGetSourceControlConfigurationRepoEffect.tsx index 61c947a0a..9f38920bf 100644 --- a/frontend/src/hooks/useGetSourceControlConfigurationRepoEffect.tsx +++ b/frontend/src/hooks/useGetSourceControlConfigurationRepoEffect.tsx @@ -1,9 +1,4 @@ -import { - DateRange, - selectIsProjectCreated, - selectSourceControl, - updateSourceControlVerifiedResponse, -} from '@src/context/config/configSlice'; +import { DateRange, selectSourceControl, updateSourceControlVerifiedResponse } from '@src/context/config/configSlice'; import { updateSourceControlConfigurationSettingsFirstInto } from '@src/context/Metrics/metricsSlice'; import { sourceControlClient } from '@src/clients/sourceControl/SourceControlClient'; import { FULFILLED, SourceControlTypes } from '@src/constants/resources'; @@ -21,7 +16,6 @@ export const useGetSourceControlConfigurationRepoEffect = (): IUseGetSourceContr const [isLoading, setIsLoading] = useState(false); const [isGetRepo, setIsGetRepo] = useState(false); const restoredSourceControlInfo = useAppSelector(selectSourceControl); - const isProjectCreated = useAppSelector(selectIsProjectCreated); function getEnumKeyByEnumValue(enumValue: string): SourceControlTypes { return Object.entries(SourceControlTypes) @@ -58,7 +52,6 @@ export const useGetSourceControlConfigurationRepoEffect = (): IUseGetSourceContr dispatch( updateSourceControlConfigurationSettingsFirstInto({ ...response.value.data, - isProjectCreated, type: 'repo', }), ); From 4b1db2500d3590756844ab4488d640e68af4d7d9 Mon Sep 17 00:00:00 2001 From: zhou-yinyuan Date: Wed, 4 Sep 2024 11:31:53 +0800 Subject: [PATCH 3/3] ADM-999 [frontend]: fix bug and fix e2e test --- .../SourceControlMetricSelection.test.tsx | 14 +++- .../__tests__/context/metricsSlice.test.ts | 20 ++++-- ...eControlConfigurationBranchEffect.test.tsx | 2 +- ...rceControlConfigurationRepoEffect.test.tsx | 2 +- .../e2e/fixtures/create-new/report-result.ts | 26 +++---- .../fixtures/import-file/unhappy-path-file.ts | 10 +-- .../unhappy-path-config-file.template.json | 2 +- .../containers/MetricsStep/Crews/index.tsx | 6 ++ .../SourceControlMetricSelection/index.tsx | 25 ++++--- frontend/src/context/Metrics/metricsSlice.ts | 68 ++++++++++++++----- ...SourceControlConfigurationBranchEffect.tsx | 7 +- ...etSourceControlConfigurationRepoEffect.tsx | 5 +- 12 files changed, 126 insertions(+), 61 deletions(-) diff --git a/frontend/__tests__/containers/MetricsStep/SourceControlConfiguration/SourceControlMetricSelection.test.tsx b/frontend/__tests__/containers/MetricsStep/SourceControlConfiguration/SourceControlMetricSelection.test.tsx index f262d4341..4b89988c6 100644 --- a/frontend/__tests__/containers/MetricsStep/SourceControlConfiguration/SourceControlMetricSelection.test.tsx +++ b/frontend/__tests__/containers/MetricsStep/SourceControlConfiguration/SourceControlMetricSelection.test.tsx @@ -28,6 +28,12 @@ let mockRepoEffectResponse: IUseGetSourceControlConfigurationRepoInterface = moc let mockBranchEffectResponse: IUseGetSourceControlConfigurationBranchInterface = mockInitBranchEffectResponse; let mockCrewEffectResponse: IUseGetSourceControlConfigurationCrewInterface = mockInitCrewEffectResponse; +const mockInitSelectSourceControlRepos = ['mockRepoName', 'mockRepoName1']; +let mockSelectSourceControlRepos = mockInitSelectSourceControlRepos; + +const mockInitSelectSourceControlBranches = ['mockBranchName', 'mockBranchName1']; +let mockSelectSourceControlBranches = mockInitSelectSourceControlBranches; + jest.mock('@src/hooks/useGetSourceControlConfigurationRepoEffect', () => { return { useGetSourceControlConfigurationRepoEffect: () => mockRepoEffectResponse, @@ -54,8 +60,8 @@ jest.mock('@src/context/Metrics/metricsSlice', () => ({ jest.mock('@src/context/config/configSlice', () => ({ ...jest.requireActual('@src/context/config/configSlice'), selectSourceControlOrganizations: jest.fn().mockReturnValue(['mockOrgName', 'mockOrgName1']), - selectSourceControlRepos: jest.fn().mockImplementation(() => ['mockRepoName', 'mockRepoName1']), - selectSourceControlBranches: jest.fn().mockImplementation(() => ['mockBranchName', 'mockBranchName1']), + selectSourceControlRepos: jest.fn().mockImplementation(() => mockSelectSourceControlRepos), + selectSourceControlBranches: jest.fn().mockImplementation(() => mockSelectSourceControlBranches), selectDateRange: jest.fn().mockReturnValue([ { startDate: '2024-07-31T00:00:00.000+08:00', endDate: '2024-08-02T23:59:59.999+08:00' }, { startDate: '2024-07-15T00:00:00.000+08:00', endDate: '2024-07-28T23:59:59.999+08:00' }, @@ -69,6 +75,8 @@ describe('SourceControlMetricSelection', () => { mockRepoEffectResponse = mockInitRepoEffectResponse; mockBranchEffectResponse = mockInitBranchEffectResponse; mockCrewEffectResponse = mockInitCrewEffectResponse; + mockSelectSourceControlBranches = mockInitSelectSourceControlBranches; + mockSelectSourceControlRepos = mockInitSelectSourceControlRepos; }); const onUpdateSourceControl = jest.fn(); const setup = (isDuplicated: boolean = false) => { @@ -110,6 +118,7 @@ describe('SourceControlMetricSelection', () => { }); it('should call getSourceControlRepoInfo function when isGetRepo is false and organization exists', () => { + mockSelectSourceControlRepos = []; const getSourceControlRepoInfoFunction = jest.fn(); mockRepoEffectResponse = { ...mockInitRepoEffectResponse, @@ -122,6 +131,7 @@ describe('SourceControlMetricSelection', () => { }); it('should call getSourceControlBranchInfo function when isGetBranch is false and organization and repo exist', () => { + mockSelectSourceControlBranches = []; const getSourceControlBranchInfoFunction = jest.fn(); mockBranchEffectResponse = { ...mockBranchEffectResponse, diff --git a/frontend/__tests__/context/metricsSlice.test.ts b/frontend/__tests__/context/metricsSlice.test.ts index 23a8ccab6..717644563 100644 --- a/frontend/__tests__/context/metricsSlice.test.ts +++ b/frontend/__tests__/context/metricsSlice.test.ts @@ -1612,8 +1612,8 @@ describe('saveMetricsSetting reducer', () => { { id: 3, organization: 'test-org3', repo: 'test-repo3', branches: ['test-branch3-1', 'test-branch3-2'] }, ]; const expectedSourceControlConfigurationSettings = [ - { id: 1, organization: 'test-org-update1', repo: 'test-repo1', branches: ['test-branch1-1', 'test-branch1-2'] }, - { id: 2, organization: 'test-org2', repo: 'test-repo-update2', branches: ['test-branch2-1', 'test-branch2-2'] }, + { id: 1, organization: 'test-org-update1', repo: '', branches: [] }, + { id: 2, organization: 'test-org2', repo: 'test-repo-update2', branches: [] }, { id: 3, organization: 'test-org3', repo: 'test-repo3', branches: ['test-branch-update3-1'] }, ]; @@ -1644,7 +1644,6 @@ describe('saveMetricsSetting reducer', () => { initState, updateSourceControlConfigurationSettingsFirstInto({ name: ['test1', 'test2'], - isProjectCreated: true, type: 'organization', }), ); @@ -1652,13 +1651,14 @@ describe('saveMetricsSetting reducer', () => { expect(savedMetricsSetting.sourceControlConfigurationSettings).toEqual(expectedSourceControlConfigurationSettings); }); - it('should return source control settings when handle updateSourceControlConfigurationSettingsFirstInto and setting is empty', () => { + it('should return source control settings when handle updateSourceControlConfigurationSettingsFirstInto and import data is not empty', () => { const existedImportedSourceControlSettings = [ { id: 1, organization: 'test-org1', repo: 'test-repo1', branches: ['test-branch1'] }, { id: 2, organization: 'test-org2', repo: 'test-repo2', branches: ['test-branch2'] }, ]; const expectedSourceControlConfigurationSettings = [ { id: 1, organization: 'test-org1', repo: 'test-repo1', branches: ['test-branch1'] }, + { id: 2, organization: '', repo: '', branches: [] }, ]; const state = { ...initState, @@ -1678,7 +1678,14 @@ describe('saveMetricsSetting reducer', () => { savedMetricsSetting, updateSourceControlConfigurationSettingsFirstInto({ name: ['test-repo1', 'test2'], - isProjectCreated: false, + type: 'repo', + id: 1, + }), + ); + savedMetricsSetting = saveMetricsSettingReducer( + savedMetricsSetting, + updateSourceControlConfigurationSettingsFirstInto({ + name: ['test-repo1', 'test2'], type: 'repo', }), ); @@ -1686,8 +1693,7 @@ describe('saveMetricsSetting reducer', () => { savedMetricsSetting, updateSourceControlConfigurationSettingsFirstInto({ name: ['test-branch1'], - isProjectCreated: false, - type: 'branch', + type: 'branches', }), ); diff --git a/frontend/__tests__/hooks/useGetSourceControlConfigurationBranchEffect.test.tsx b/frontend/__tests__/hooks/useGetSourceControlConfigurationBranchEffect.test.tsx index b0ef19913..a205803f4 100644 --- a/frontend/__tests__/hooks/useGetSourceControlConfigurationBranchEffect.test.tsx +++ b/frontend/__tests__/hooks/useGetSourceControlConfigurationBranchEffect.test.tsx @@ -50,7 +50,7 @@ describe('use get source control configuration branch info side effect', () => { const mockRepo = 'mockRepo'; await act(async () => { - result.current.getSourceControlBranchInfo(mockOrganization, mockRepo); + result.current.getSourceControlBranchInfo(mockOrganization, mockRepo, 1); }); await waitFor(() => { diff --git a/frontend/__tests__/hooks/useGetSourceControlConfigurationRepoEffect.test.tsx b/frontend/__tests__/hooks/useGetSourceControlConfigurationRepoEffect.test.tsx index c5b0bd472..71513b29f 100644 --- a/frontend/__tests__/hooks/useGetSourceControlConfigurationRepoEffect.test.tsx +++ b/frontend/__tests__/hooks/useGetSourceControlConfigurationRepoEffect.test.tsx @@ -57,7 +57,7 @@ describe('use get source control configuration repo info side effect', () => { ]; await act(async () => { - result.current.getSourceControlRepoInfo(mockOrganization, mockDateRanges); + result.current.getSourceControlRepoInfo(mockOrganization, mockDateRanges, 1); }); await waitFor(() => { diff --git a/frontend/e2e/fixtures/create-new/report-result.ts b/frontend/e2e/fixtures/create-new/report-result.ts index 9333e1dc2..69275fda9 100644 --- a/frontend/e2e/fixtures/create-new/report-result.ts +++ b/frontend/e2e/fixtures/create-new/report-result.ts @@ -36,14 +36,14 @@ export interface IBoardClassificationDetailItem { export interface ICsvComparedLines extends Record {} export const BOARD_METRICS_RESULT: IBoardMetricsResult = { - velocity: '7.5', - throughput: '5', - averageCycleTimeForSP: '4.49', - averageCycleTimeForCard: '6.73', - totalReworkTimes: '2', - totalReworkCards: '2', - reworkCardsRatio: '0.4000', - reworkThroughput: '5', + velocity: '14', + throughput: '6', + averageCycleTimeForSP: '1.13', + averageCycleTimeForCard: '2.64', + totalReworkTimes: '0', + totalReworkCards: '0', + reworkCardsRatio: '0.0000', + reworkThroughput: '6', }; export const BOARD_METRICS_RESULT_MULTIPLE_RANGES: IBoardMetricsResult[] = [ @@ -765,12 +765,12 @@ export const FLAG_AS_BLOCK_PROJECT_BOARD_METRICS_RESULT: IBoardMetricsResult = { export const DORA_METRICS_RESULT = { PrLeadTime: '0.00', - PipelineLeadTime: '22.72', - TotalLeadTime: '22.72', - DeploymentFrequency: '0.20', - FailureRate: '0.00% (0/1)', + PipelineLeadTime: '0.00', + TotalLeadTime: '0.00', + DeploymentFrequency: '0.00', + FailureRate: '100.00% (1/1)', DevMeanTimeToRecovery: '0.00', - DeploymentTimes: '1', + DeploymentTimes: '0', }; export const DORA_METRICS_RESULT_MULTIPLE_RANGES: IDoraMetricsResultItem[] = [ diff --git a/frontend/e2e/fixtures/import-file/unhappy-path-file.ts b/frontend/e2e/fixtures/import-file/unhappy-path-file.ts index 7f6303aed..af257e0b2 100644 --- a/frontend/e2e/fixtures/import-file/unhappy-path-file.ts +++ b/frontend/e2e/fixtures/import-file/unhappy-path-file.ts @@ -86,7 +86,7 @@ export const importInputWrongProjectFromFile = { { id: 0, organization: 'Heartbeat-backup', - pipelineName: 'Heartbeat-E2E', + pipelineName: 'Heartbeat', step: ':rocket: Run e2e', branches: ['main'], isStepEmptyString: false, @@ -96,10 +96,10 @@ export const importInputWrongProjectFromFile = { export const importModifiedCorrectConfig = { projectName: 'Heartbeat Metrics', - deletedBranch: 'ADM-747', + deletedBranch: 'ADM-998', dateRange: { - startDate: '2024-06-03T00:00:00.000+08:00', - endDate: '2024-06-07T23:59:59.999+08:00', + startDate: '2024-08-12T00:00:00.000+08:00', + endDate: '2024-09-02T23:59:59.999+08:00', }, board: { type: 'Jira', @@ -117,7 +117,7 @@ export const importModifiedCorrectConfig = { type: 'GitHub', token: process.env.E2E_TOKEN_GITHUB as string, }, - crews: ['Man Tang', 'heartbeat user', 'Qiuhong Lei', 'Chao Wang', 'YinYuan Zhou'], + crews: ['Man Tang', 'YinYuan Zhou'], assigneeFilter: 'lastAssignee', cycleTime: { type: 'byColumn', diff --git a/frontend/e2e/fixtures/input-files/unhappy-path-config-file.template.json b/frontend/e2e/fixtures/input-files/unhappy-path-config-file.template.json index b53da3057..b3cc0aed4 100644 --- a/frontend/e2e/fixtures/input-files/unhappy-path-config-file.template.json +++ b/frontend/e2e/fixtures/input-files/unhappy-path-config-file.template.json @@ -106,7 +106,7 @@ { "id": 0, "organization": "Heartbeat-backup", - "pipelineName": "Heartbeat-E2E", + "pipelineName": "Heartbeat", "step": ":rocket: Run e2e", "branches": ["main", "ADM-747"] } diff --git a/frontend/src/containers/MetricsStep/Crews/index.tsx b/frontend/src/containers/MetricsStep/Crews/index.tsx index d5a55204d..31acb6b0c 100644 --- a/frontend/src/containers/MetricsStep/Crews/index.tsx +++ b/frontend/src/containers/MetricsStep/Crews/index.tsx @@ -36,6 +36,12 @@ export const Crews = ({ options, title, label, type = 'board' }: crewsProps) => const isAllSelected = options.length > 0 && selectedCrews.length === options.length; const isEmptyCrewData = selectedCrews.length === 0; + useEffect(() => { + if (isSourceControl) { + setSelectedCrews(getValidSelectedCrews(sourceControlCrews, options)); + } + }, [isSourceControl, options, sourceControlCrews]); + useEffect(() => { const crews = isSourceControl ? sourceControlCrews : pipelineCrews; setSelectedCrews(isBoardCrews ? users : crews); diff --git a/frontend/src/containers/MetricsStep/SouceControlConfiguration/SourceControlMetricSelection/index.tsx b/frontend/src/containers/MetricsStep/SouceControlConfiguration/SourceControlMetricSelection/index.tsx index 9dcb8cfe4..cc42ee1eb 100644 --- a/frontend/src/containers/MetricsStep/SouceControlConfiguration/SourceControlMetricSelection/index.tsx +++ b/frontend/src/containers/MetricsStep/SouceControlConfiguration/SourceControlMetricSelection/index.tsx @@ -77,16 +77,24 @@ export const SourceControlMetricSelection = ({ }; useEffect(() => { - if (!isGetRepo && organization) { - getSourceControlRepoInfo(organization, dateRanges); + if (!isGetRepo && organization && repoNameOptions.length === 0) { + getSourceControlRepoInfo(organization, dateRanges, id); } - }, [dateRanges, getSourceControlRepoInfo, isGetRepo, organization]); + }, [dateRanges, getSourceControlRepoInfo, id, isGetRepo, organization, repoNameOptions.length]); useEffect(() => { - if (!isGetBranch && organization && repo) { - getSourceControlBranchInfo(organization, repo); + if (!isGetBranch && organization && repo && branchNameOptions.length === 0) { + getSourceControlBranchInfo(organization, repo, id); } - }, [getSourceControlBranchInfo, getSourceControlRepoInfo, isGetBranch, organization, repo]); + }, [ + branchNameOptions.length, + getSourceControlBranchInfo, + getSourceControlRepoInfo, + id, + isGetBranch, + organization, + repo, + ]); useEffect(() => { if (!isGetAllCrews && organization && repo && selectedBranches) { @@ -105,12 +113,12 @@ export const SourceControlMetricSelection = ({ const handleOnUpdateOrganization = (id: number, label: string, value: string | []): void => { onUpdateSourceControl(id, label, value); - getSourceControlRepoInfo(value.toString(), dateRanges); + getSourceControlRepoInfo(value.toString(), dateRanges, id); }; const handleOnUpdateRepo = (id: number, label: string, value: string | []): void => { onUpdateSourceControl(id, label, value); - getSourceControlBranchInfo(organization, value.toString()); + getSourceControlBranchInfo(organization, value.toString(), id); }; const handleOnUpdateBranches = (id: number, label: string, value: string[]): void => { @@ -118,6 +126,7 @@ export const SourceControlMetricSelection = ({ onUpdateSourceControl(id, label, value); branchNeedGetCrews.forEach((branch) => getSourceControlCrewInfo(organization, repo, branch, dateRanges)); }; + useEffect(() => { if (isGetAllCrews) { setLoadingCompletedNumber((value) => Math.min(totalSourceControlNumber, value + 1)); diff --git a/frontend/src/context/Metrics/metricsSlice.ts b/frontend/src/context/Metrics/metricsSlice.ts index fded23aae..6ee330d53 100644 --- a/frontend/src/context/Metrics/metricsSlice.ts +++ b/frontend/src/context/Metrics/metricsSlice.ts @@ -401,17 +401,34 @@ export const metricsSlice = createSlice({ const { updateId, label, value } = action.payload; const sourceControlConfigurationSettings = state.sourceControlConfigurationSettings; state.sourceControlConfigurationSettings = sourceControlConfigurationSettings.map((it) => { - return it.id !== updateId - ? it - : { + if (it.id !== updateId) { + return it; + } else { + if (label === 'organization') { + return { + ...it, + organization: value, + repo: '', + branches: [], + }; + } else if (label === 'repo') { + return { ...it, - [label]: value, + repo: value, + branches: [], }; + } else { + return { + ...it, + branches: value, + }; + } + } }); }, updateSourceControlConfigurationSettingsFirstInto: (state, action) => { - const { name, type } = action.payload; + const { name, type, id } = action.payload; const sourceControlConfigurationSettings = state.sourceControlConfigurationSettings; @@ -438,19 +455,34 @@ export const metricsSlice = createSlice({ }, ]; - if (type === 'organization') { - validSourceControlConfigurationSettings = validSourceControlConfigurationSettings.filter( - (it) => it['organization'] === '' || name.includes(it['organization']), - ); - } else if (type === 'repo') { - validSourceControlConfigurationSettings = validSourceControlConfigurationSettings.filter( - (it) => it['repo'] === '' || name.includes(it['repo']), - ); - } else { - validSourceControlConfigurationSettings = validSourceControlConfigurationSettings.filter( - (it) => it['branches'].length === 0 || it['branches'].filter((branch) => name.includes(branch)), - ); - } + const func = (type: string, it: ISourceControlConfig) => { + if (type === 'organization') { + if (name.includes(it['organization'])) { + return it['organization']; + } else { + return ''; + } + } else if (type === 'repo') { + if (name.includes(it['repo'])) { + return it['repo']; + } else { + return ''; + } + } else { + return it.branches.filter((branch) => name.includes(branch)); + } + }; + + validSourceControlConfigurationSettings = validSourceControlConfigurationSettings.map((it) => { + if (id !== undefined && id !== it.id) { + return it; + } + const newValue = func(type, it); + return { + ...it, + [type]: newValue, + }; + }); state.sourceControlConfigurationSettings = validSourceControlConfigurationSettings; }, diff --git a/frontend/src/hooks/useGetSourceControlConfigurationBranchEffect.tsx b/frontend/src/hooks/useGetSourceControlConfigurationBranchEffect.tsx index 5f81e68c5..2f2e5cfbb 100644 --- a/frontend/src/hooks/useGetSourceControlConfigurationBranchEffect.tsx +++ b/frontend/src/hooks/useGetSourceControlConfigurationBranchEffect.tsx @@ -8,7 +8,7 @@ import { useState } from 'react'; export interface IUseGetSourceControlConfigurationBranchInterface { readonly isLoading: boolean; - readonly getSourceControlBranchInfo: (organization: string, repo: string) => Promise; + readonly getSourceControlBranchInfo: (organization: string, repo: string, id: number) => Promise; readonly isGetBranch: boolean; } export const useGetSourceControlConfigurationBranchEffect = (): IUseGetSourceControlConfigurationBranchInterface => { @@ -23,7 +23,7 @@ export const useGetSourceControlConfigurationBranchEffect = (): IUseGetSourceCon .map((it) => it[1])[0]; } - const getSourceControlBranchInfo = async (organization: string, repo: string) => { + const getSourceControlBranchInfo = async (organization: string, repo: string, id: number) => { const params = { type: getEnumKeyByEnumValue(restoredSourceControlInfo.type), token: restoredSourceControlInfo.token, @@ -52,7 +52,8 @@ export const useGetSourceControlConfigurationBranchEffect = (): IUseGetSourceCon dispatch( updateSourceControlConfigurationSettingsFirstInto({ ...response.data, - type: 'branch', + id, + type: 'branches', }), ); } diff --git a/frontend/src/hooks/useGetSourceControlConfigurationRepoEffect.tsx b/frontend/src/hooks/useGetSourceControlConfigurationRepoEffect.tsx index 9f38920bf..a807ac51f 100644 --- a/frontend/src/hooks/useGetSourceControlConfigurationRepoEffect.tsx +++ b/frontend/src/hooks/useGetSourceControlConfigurationRepoEffect.tsx @@ -8,7 +8,7 @@ import dayjs from 'dayjs'; export interface IUseGetSourceControlConfigurationRepoInterface { readonly isLoading: boolean; - readonly getSourceControlRepoInfo: (value: string, dateRanges: DateRange[]) => Promise; + readonly getSourceControlRepoInfo: (value: string, dateRanges: DateRange[], id: number) => Promise; readonly isGetRepo: boolean; } export const useGetSourceControlConfigurationRepoEffect = (): IUseGetSourceControlConfigurationRepoInterface => { @@ -23,7 +23,7 @@ export const useGetSourceControlConfigurationRepoEffect = (): IUseGetSourceContr .map((it) => it[1])[0]; } - const getSourceControlRepoInfo = async (organization: string, dateRanges: DateRange[]) => { + const getSourceControlRepoInfo = async (organization: string, dateRanges: DateRange[], id: number) => { setIsLoading(true); const allRepoRes = await Promise.allSettled( dateRanges.flatMap((dateRange) => { @@ -52,6 +52,7 @@ export const useGetSourceControlConfigurationRepoEffect = (): IUseGetSourceContr dispatch( updateSourceControlConfigurationSettingsFirstInto({ ...response.value.data, + id, type: 'repo', }), );