Skip to content

Commit

Permalink
feat(frontend): add error handling for trigger section (#2274)
Browse files Browse the repository at this point in the history
  • Loading branch information
jorgeepc committed Mar 31, 2023
1 parent de26d24 commit 174a398
Show file tree
Hide file tree
Showing 19 changed files with 311 additions and 103 deletions.
29 changes: 0 additions & 29 deletions web/src/components/FailedTrace/FailedTrace.styled.ts

This file was deleted.

30 changes: 0 additions & 30 deletions web/src/components/FailedTrace/FailedTrace.tsx

This file was deleted.

8 changes: 0 additions & 8 deletions web/src/components/FailedTrace/__tests__/FailedTrace.test.tsx

This file was deleted.

4 changes: 2 additions & 2 deletions web/src/components/RunDetailLayout/RunDetailLayout.tsx
Expand Up @@ -33,7 +33,7 @@ const renderTab = (title: string, testId: string, runId: string, mode: string) =
const RunDetailLayout = ({test: {id, name, trigger, version = 1}, test}: IProps) => {
const {mode = RunDetailModes.TRIGGER} = useParams();
const {showNotification} = useNotification();
const {isError, run} = useTestRun();
const {isError, run, runEvents} = useTestRun();
const [prevState, setPrevState] = useState(run.state);
useDocumentTitle(`${name} - ${run.state}`);

Expand Down Expand Up @@ -69,7 +69,7 @@ const RunDetailLayout = ({test: {id, name, trigger, version = 1}, test}: IProps)
destroyInactiveTabPane
>
<Tabs.TabPane tab={renderTab('Trigger', id, run.id, mode)} key={RunDetailModes.TRIGGER}>
<RunDetailTrigger test={test} run={run} isError={isError} />
<RunDetailTrigger test={test} run={run} runEvents={runEvents} isError={isError} />
</Tabs.TabPane>
<Tabs.TabPane tab={renderTab('Trace', id, run.id, mode)} key={RunDetailModes.TRACE}>
<RunDetailTrace run={run} testId={id} />
Expand Down
8 changes: 5 additions & 3 deletions web/src/components/RunDetailTrigger/RunDetailTrigger.tsx
@@ -1,19 +1,21 @@
import EditTest from 'components/EditTest';
import FailedTrace from 'components/FailedTrace';
import RunDetailTriggerResponseFactory from 'components/RunDetailTriggerResponse/RunDetailTriggerResponseFactory';
import RunEvents from 'components/RunEvents';
import {TriggerTypes} from 'constants/Test.constants';
import {TestState} from 'constants/TestRun.constants';
import Test from 'models/Test.model';
import TestRun from 'models/TestRun.model';
import TestRunEvent, {TestRunStage} from 'models/TestRunEvent.model';
import * as S from './RunDetailTrigger.styled';

interface IProps {
test: Test;
run: TestRun;
runEvents: TestRunEvent[];
isError: boolean;
}

const RunDetailTrigger = ({test, run: {state, triggerResult, triggerTime}, run, isError}: IProps) => {
const RunDetailTrigger = ({test, run: {state, triggerResult, triggerTime}, runEvents, isError}: IProps) => {
const shouldDisplayError = isError || state === TestState.FAILED;

return (
Expand All @@ -23,7 +25,7 @@ const RunDetailTrigger = ({test, run: {state, triggerResult, triggerTime}, run,
</S.SectionLeft>
<S.SectionRight>
{shouldDisplayError ? (
<FailedTrace isDisplayingError={shouldDisplayError} run={run} />
<RunEvents events={runEvents} stage={TestRunStage.Trigger} />
) : (
<RunDetailTriggerResponseFactory
state={state}
Expand Down
Expand Up @@ -48,16 +48,12 @@ export const StatusText = styled(Typography.Text)`
`;

export const LoadingResponseBody = styled.div`
margin-top: 25px;
margin-top: 24px;
display: flex;
flex-direction: column;
justify-items: center;
gap: 8px;
height: 100px;
gap: 16px;
padding: 0.4em 0.6em;
background: ${({theme}) => theme.color.background};
border: ${({theme}) => `1px solid ${theme.color.borderLight}`};
font-size: ${({theme}) => theme.size.sm};
`;

export const TextHolder = styled.div<{$width?: number}>`
Expand All @@ -71,7 +67,7 @@ export const TextHolder = styled.div<{$width?: number}>`
}
animation: skeleton-loading 1s linear infinite alternate;
height: 8px;
height: 16px;
border-radius: 2px;
width: ${({$width = 100}) => $width}%;
`;
Expand Down
Expand Up @@ -3,11 +3,11 @@ import * as S from './RunDetailTriggerResponse.styled';
const SkeletonResponse = () => {
return (
<S.LoadingResponseBody>
<S.TextHolder $width={80} />
<S.TextHolder $width={90} />
<S.TextHolder $width={50} />
<S.TextHolder $width={100} />
<S.TextHolder $width={100} />
<S.TextHolder $width={60} />
<S.TextHolder $width={100} />
<S.TextHolder $width={80} />
</S.LoadingResponseBody>
);
};
Expand Down
17 changes: 17 additions & 0 deletions web/src/components/RunEvents/RunEvent.tsx
@@ -0,0 +1,17 @@
import {Typography} from 'antd';
import TestRunEvent from 'models/TestRunEvent.model';
import * as S from './RunEvents.styled';

interface IProps {
event: TestRunEvent;
}

const RunEvent = ({event}: IProps) => (
<S.EventContainer>
<S.Dot $logLevel={event.logLevel} />
<Typography.Title level={3}>{event.title}</Typography.Title>
<Typography.Text>{event.description}</Typography.Text>
</S.EventContainer>
);

export default RunEvent;
55 changes: 55 additions & 0 deletions web/src/components/RunEvents/RunEvents.styled.ts
@@ -0,0 +1,55 @@
import {CloseCircleFilled} from '@ant-design/icons';
import {Typography} from 'antd';
import styled, {DefaultTheme} from 'styled-components';

import {LogLevel} from 'models/TestRunEvent.model';

function getLogLevelColor(logLevel: LogLevel, theme: DefaultTheme): string {
if (logLevel === LogLevel.Error) return theme.color.error;
if (logLevel === LogLevel.Success) return theme.color.success;
if (logLevel === LogLevel.Warning) return theme.color.warningYellow;
return theme.color.textLight;
}

export const Container = styled.div`
align-items: center;
display: flex;
flex-direction: column;
justify-content: center;
padding: 70px 120px;
`;

export const Dot = styled.div<{$logLevel?: LogLevel}>`
background: #ffffff;
border: 2px solid ${({theme, $logLevel = LogLevel.Info}) => getLogLevelColor($logLevel, theme)};
border-radius: 50%;
left: -5px;
height: 10px;
position: absolute;
top: 0;
width: 10px;
`;

export const ErrorIcon = styled(CloseCircleFilled)`
color: ${({theme}) => theme.color.error};
font-size: 32px;
margin-bottom: 26px;
`;

export const EventContainer = styled.div`
border-left: 1px solid ${({theme}) => theme.color.textLight};
padding: 0 20px 20px;
position: relative;
`;

export const Link = styled(Typography.Link)`
font-weight: bold;
`;

export const ListContainer = styled.div`
padding: 24px 0;
`;

export const Paragraph = styled(Typography.Paragraph)`
text-align: center;
`;
26 changes: 26 additions & 0 deletions web/src/components/RunEvents/RunEvents.tsx
@@ -0,0 +1,26 @@
import TestRunEvent, {TestRunStage} from 'models/TestRunEvent.model';
import TestRunService from 'services/TestRun.service';
import RunEventsTrigger from './RunEventsTrigger';

export interface IPropsComponent {
events: TestRunEvent[];
}

interface IProps extends IPropsComponent {
stage: TestRunStage;
}

const ComponentMap: Record<TestRunStage, (props: IPropsComponent) => React.ReactElement> = {
[TestRunStage.Trigger]: RunEventsTrigger,
[TestRunStage.Trace]: RunEventsTrigger,
[TestRunStage.Test]: RunEventsTrigger,
};

const RunEvents = ({events, stage}: IProps) => {
const Component = ComponentMap[stage];
const filteredEvents = TestRunService.getTestRunEventsByStage(events, stage);

return <Component events={filteredEvents} />;
};

export default RunEvents;
37 changes: 37 additions & 0 deletions web/src/components/RunEvents/RunEventsTrigger.tsx
@@ -0,0 +1,37 @@
import {Typography} from 'antd';

import {DISCORD_URL, GITHUB_ISSUES_URL} from 'constants/Common.constants';
import RunEvent from './RunEvent';
import {IPropsComponent} from './RunEvents';
import * as S from './RunEvents.styled';

const RunEventsTrigger = ({events}: IPropsComponent) => (
<S.Container>
<S.ErrorIcon />
<Typography.Title level={2}>Test Run Failed</Typography.Title>
<S.Paragraph>
We prepared the breakdown of diagnostic steps and tips to help identify the source of the issue:
</S.Paragraph>

<S.ListContainer>
{events.map(event => (
<RunEvent event={event} key={event.type} />
))}
</S.ListContainer>

<S.Paragraph>
<Typography.Text type="secondary">
<S.Link href={GITHUB_ISSUES_URL} target="_blank">
Create an issue
</S.Link>{' '}
or contact us via{' '}
<S.Link href={DISCORD_URL} target="_blank">
Discord
</S.Link>
. We will check it out and will help you rectify the issue.
</Typography.Text>
</S.Paragraph>
</S.Container>
);

export default RunEventsTrigger;
@@ -1,2 +1,2 @@
// eslint-disable-next-line no-restricted-exports
export {default} from './FailedTrace';
export {default} from './RunEvents';

0 comments on commit 174a398

Please sign in to comment.