From 7dd0217c1de1f3e191082783433da1070c565b97 Mon Sep 17 00:00:00 2001 From: Jorge Padilla Date: Wed, 5 Apr 2023 14:32:13 -0500 Subject: [PATCH] feat(frontend): add websocket subscription for test run events (#2294) --- web/src/components/RunEvents/RunEventsTrace.tsx | 11 ++++++++--- web/src/components/TestResults/TestResults.tsx | 6 +++--- web/src/components/TestSpecs/TestSpecs.tsx | 8 ++++---- web/src/constants/TestRunEvents.constants.ts | 3 +++ .../redux/apis/endpoints/TestRun.endpoints.ts | 12 +++++++----- web/src/services/TestRun.service.ts | 16 +++++++++++++++- 6 files changed, 40 insertions(+), 16 deletions(-) diff --git a/web/src/components/RunEvents/RunEventsTrace.tsx b/web/src/components/RunEvents/RunEventsTrace.tsx index 069b4295b1..681bb5b273 100644 --- a/web/src/components/RunEvents/RunEventsTrace.tsx +++ b/web/src/components/RunEvents/RunEventsTrace.tsx @@ -11,13 +11,18 @@ import RunEventPolling from './RunEventPolling'; import {IPropsComponent} from './RunEvents'; import * as S from './RunEvents.styled'; -const ComponentMap: Record React.ReactElement> = { +type TraceEventTypeWithoutFetching = Exclude< + TraceEventType, + TraceEventType.FETCHING_START | TraceEventType.FETCHING_ERROR | TraceEventType.FETCHING_SUCCESS +>; + +const ComponentMap: Record React.ReactElement> = { [TraceEventType.DATA_STORE_CONNECTION_INFO]: RunEventDataStore, [TraceEventType.POLLING_ITERATION_INFO]: RunEventPolling, }; const RunEventsTrace = ({events, state}: IPropsComponent) => { - const filteredEvents = TestRunService.getTestRunEventsWithLastPolling(events); + const filteredEvents = TestRunService.getTestRunTraceEvents(events); const loadingHeader = ( <> @@ -66,7 +71,7 @@ const RunEventsTrace = ({events, state}: IPropsComponent) => { {filteredEvents.map(event => { - const Component = ComponentMap[event.type as TraceEventType] ?? RunEvent; + const Component = ComponentMap[event.type as TraceEventTypeWithoutFetching] ?? RunEvent; return ; })} diff --git a/web/src/components/TestResults/TestResults.tsx b/web/src/components/TestResults/TestResults.tsx index be161d8a0d..d4526b17c0 100644 --- a/web/src/components/TestResults/TestResults.tsx +++ b/web/src/components/TestResults/TestResults.tsx @@ -38,15 +38,15 @@ const TestResults = ({onDelete, onEdit, onRevert}: IProps) => {
- {(isLoading || !assertionResults) && ( + {isLoading && ( )} - {!isLoading && Boolean(assertionResults) && ( + {!isLoading && ( { - if (!resultList.length) { +const TestSpecs = ({assertionResults, onDelete, onEdit, onOpen, onRevert}: IProps) => { + if (!assertionResults?.resultList?.length) { return ; } return ( - {resultList.map(specResult => + {assertionResults?.resultList?.map(specResult => specResult.resultList.length ? ( ({ query: ({runId, testId}) => `/tests/${testId}/run/${runId}/events`, providesTags: [{type: TracetestApiTags.TEST_RUN, id: 'EVENTS'}], transformResponse: (rawTestRunEvent: TRawTestRunEvent[]) => rawTestRunEvent.map(event => TestRunEvent(event)), - /* async onCacheEntryAdded(arg, {cacheDataLoaded, cacheEntryRemoved, updateCachedData}) { - const listener: IListenerFunction = data => { - updateCachedData(() => TestRun(data.event)); + async onCacheEntryAdded(arg, {cacheDataLoaded, cacheEntryRemoved, updateCachedData}) { + const listener: IListenerFunction = data => { + updateCachedData(draft => { + draft.push(TestRunEvent(data.event)); + }); }; await WebSocketService.initWebSocketSubscription({ listener, - resource: `test/${arg.testId}/run/${arg.runId}`, + resource: `test/${arg.testId}/run/${arg.runId}/event`, waitToCleanSubscription: cacheEntryRemoved, waitToInitSubscription: cacheDataLoaded, }); - }, */ + }, }), }); diff --git a/web/src/services/TestRun.service.ts b/web/src/services/TestRun.service.ts index 0e5ab5fa92..f7ea83ed18 100644 --- a/web/src/services/TestRun.service.ts +++ b/web/src/services/TestRun.service.ts @@ -1,5 +1,5 @@ import {TestRunStage, TraceEventType} from 'constants/TestRunEvents.constants'; -import {filter, findLastIndex} from 'lodash'; +import {filter, findLastIndex, flow} from 'lodash'; import TestRunEvent from 'models/TestRunEvent.model'; const TestRunService = () => ({ @@ -7,6 +7,20 @@ const TestRunService = () => ({ return events.filter(event => event.stage === stage); }, + getTestRunTraceEvents(events: TestRunEvent[]): TestRunEvent[] { + return flow([this.getTestRunEventsWithoutFetching, this.getTestRunEventsWithLastPolling])(events); + }, + + getTestRunEventsWithoutFetching(events: TestRunEvent[]) { + return filter( + events, + event => + !( + [TraceEventType.FETCHING_START, TraceEventType.FETCHING_ERROR, TraceEventType.FETCHING_SUCCESS] as string[] + ).includes(event.type) + ); + }, + getTestRunEventsWithLastPolling(events: TestRunEvent[]) { const lastPollingIndex = findLastIndex(events, event => event.type === TraceEventType.POLLING_ITERATION_INFO); if (lastPollingIndex === -1) return events;