Skip to content

Commit

Permalink
feat(frontend): add websocket subscription for test run events (#2294)
Browse files Browse the repository at this point in the history
  • Loading branch information
jorgeepc committed Apr 5, 2023
1 parent 61fdf00 commit 7dd0217
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 16 deletions.
11 changes: 8 additions & 3 deletions web/src/components/RunEvents/RunEventsTrace.tsx
Expand Up @@ -11,13 +11,18 @@ import RunEventPolling from './RunEventPolling';
import {IPropsComponent} from './RunEvents';
import * as S from './RunEvents.styled';

const ComponentMap: Record<TraceEventType, (props: IPropsEvent) => React.ReactElement> = {
type TraceEventTypeWithoutFetching = Exclude<
TraceEventType,
TraceEventType.FETCHING_START | TraceEventType.FETCHING_ERROR | TraceEventType.FETCHING_SUCCESS
>;

const ComponentMap: Record<TraceEventTypeWithoutFetching, (props: IPropsEvent) => 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 = (
<>
Expand Down Expand Up @@ -66,7 +71,7 @@ const RunEventsTrace = ({events, state}: IPropsComponent) => {

<S.ListContainer>
{filteredEvents.map(event => {
const Component = ComponentMap[event.type as TraceEventType] ?? RunEvent;
const Component = ComponentMap[event.type as TraceEventTypeWithoutFetching] ?? RunEvent;
return <Component event={event} key={event.type} />;
})}
</S.ListContainer>
Expand Down
6 changes: 3 additions & 3 deletions web/src/components/TestResults/TestResults.tsx
Expand Up @@ -38,15 +38,15 @@ const TestResults = ({onDelete, onEdit, onRevert}: IProps) => {
<S.Container>
<Header selectedSpan={selectedSpan!} totalFailedSpecs={totalFailedSpecs} totalPassedSpecs={totalPassedSpecs} />

{(isLoading || !assertionResults) && (
{isLoading && (
<S.LoadingContainer>
<LoadingSpinner />
</S.LoadingContainer>
)}

{!isLoading && Boolean(assertionResults) && (
{!isLoading && (
<TestSpecs
assertionResults={assertionResults!}
assertionResults={assertionResults}
onDelete={onDelete}
onEdit={onEdit}
onOpen={handleOpen}
Expand Down
8 changes: 4 additions & 4 deletions web/src/components/TestSpecs/TestSpecs.tsx
Expand Up @@ -4,21 +4,21 @@ import Empty from './Empty';
import * as S from './TestSpecs.styled';

interface IProps {
assertionResults: AssertionResults;
assertionResults?: AssertionResults;
onDelete(selector: string): void;
onEdit(assertionResult: TAssertionResultEntry, name: string): void;
onOpen(selector: string): void;
onRevert(originalSelector: string): void;
}

const TestSpecs = ({assertionResults: {resultList}, onDelete, onEdit, onOpen, onRevert}: IProps) => {
if (!resultList.length) {
const TestSpecs = ({assertionResults, onDelete, onEdit, onOpen, onRevert}: IProps) => {
if (!assertionResults?.resultList?.length) {
return <Empty />;
}

return (
<S.Container data-cy="test-specs-container">
{resultList.map(specResult =>
{assertionResults?.resultList?.map(specResult =>
specResult.resultList.length ? (
<TestSpec
key={specResult.id}
Expand Down
3 changes: 3 additions & 0 deletions web/src/constants/TestRunEvents.constants.ts
Expand Up @@ -24,4 +24,7 @@ export enum LogLevel {
export enum TraceEventType {
DATA_STORE_CONNECTION_INFO = 'DATA_STORE_CONNECTION_INFO',
POLLING_ITERATION_INFO = 'POLLING_ITERATION_INFO',
FETCHING_START = 'FETCHING_START',
FETCHING_ERROR = 'FETCHING_ERROR',
FETCHING_SUCCESS = 'FETCHING_SUCCESS',
}
12 changes: 7 additions & 5 deletions web/src/redux/apis/endpoints/TestRun.endpoints.ts
Expand Up @@ -102,17 +102,19 @@ const TestRunEndpoint = (builder: TTestApiEndpointBuilder) => ({
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<TRawTestRun> = data => {
updateCachedData(() => TestRun(data.event));
async onCacheEntryAdded(arg, {cacheDataLoaded, cacheEntryRemoved, updateCachedData}) {
const listener: IListenerFunction<TRawTestRunEvent> = 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,
});
}, */
},
}),
});

Expand Down
16 changes: 15 additions & 1 deletion web/src/services/TestRun.service.ts
@@ -1,12 +1,26 @@
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 = () => ({
getTestRunEventsByStage(events: TestRunEvent[], stage: TestRunStage) {
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;
Expand Down

0 comments on commit 7dd0217

Please sign in to comment.