Skip to content

Commit

Permalink
feat: Run Source (#3391)
Browse files Browse the repository at this point in the history
  • Loading branch information
xoscar committed Nov 22, 2023
1 parent 48f9b2a commit 34ac84d
Show file tree
Hide file tree
Showing 15 changed files with 191 additions and 85 deletions.
1 change: 0 additions & 1 deletion api/tests.yaml
@@ -1,7 +1,6 @@
openapi: 3.0.0
components:
schemas:

TestResourceList:
type: object
properties:
Expand Down
7 changes: 6 additions & 1 deletion cli/runner/orchestrator.go
Expand Up @@ -335,16 +335,21 @@ func (a orchestrator) writeJUnitReport(ctx context.Context, r Runner, result Run
return err
}

var source = "cli"

func getMetadata() map[string]string {
ci := cienvironment.DetectCIEnvironment()
if ci == nil {
return map[string]string{}
return map[string]string{
"source": source,
}
}

metadata := map[string]string{
"name": ci.Name,
"url": ci.URL,
"buildNumber": ci.BuildNumber,
"source": source,
}

if ci.Git != nil {
Expand Down
2 changes: 1 addition & 1 deletion server/executor/test_suite_runner.go
Expand Up @@ -94,7 +94,7 @@ func (r persistentTransactionRunner) ProcessItem(ctx context.Context, job Job) {
}

func (r persistentTransactionRunner) runTransactionStep(ctx context.Context, tr testsuite.TestSuiteRun, step int, testObj test.Test) (testsuite.TestSuiteRun, error) {
testRun := r.testRunner.Run(ctx, testObj, tr.Metadata, tr.VariableSet, tr.RequiredGates)
testRun := r.testRunner.Run(ctx, testObj, tr.RunMetadata(step), tr.VariableSet, tr.RequiredGates)
tr, err := r.updateStepRun(ctx, tr, step, testRun)
if err != nil {
return testsuite.TestSuiteRun{}, fmt.Errorf("could not update transaction run: %w", err)
Expand Down
9 changes: 9 additions & 0 deletions server/testsuite/testsuite_run_entities.go
Expand Up @@ -68,3 +68,12 @@ func (tr TestSuiteRun) StepsGatesValidation() bool {

return true
}

func (tr TestSuiteRun) RunMetadata(step int) test.RunMetadata {
tr.Metadata["step"] = fmt.Sprintf("%d", step+1)
tr.Metadata["testsuite_run_id"] = fmt.Sprintf("%d", tr.ID)
tr.Metadata["testsuite_id"] = string(tr.TestSuiteID)
tr.Metadata["testsuite_version"] = fmt.Sprintf("%d", tr.TestSuiteVersion)

return tr.Metadata
}
22 changes: 7 additions & 15 deletions web/src/components/RunCard/TestRunCard.tsx
Expand Up @@ -27,7 +27,7 @@ const TestRunCard = ({
state,
createdAt,
testVersion,
metadata,
metadata: {name, buildNumber, branch, url, source},
testSuiteId,
testSuiteRunId,
linter,
Expand All @@ -37,10 +37,6 @@ const TestRunCard = ({
linkTo,
}: IProps) => {
const {navigate} = useDashboard();
const metadataName = metadata?.name;
const metadataBuildNumber = metadata?.buildNumber;
const metadataBranch = metadata?.branch;
const metadataUrl = metadata?.url;

const handleResultClick = (
event: React.MouseEvent<HTMLDivElement, MouseEvent>,
Expand All @@ -64,13 +60,14 @@ const TestRunCard = ({
</Tooltip>

{isRunStateFinished(state) && <S.Text>&nbsp;• {executionTime}s</S.Text>}
{source && <S.Text>&nbsp;• Run via {source.toUpperCase()}</S.Text>}

{metadataName && (
<a href={metadataUrl} target="_blank" onClick={event => event.stopPropagation()}>
<S.Text $hasLink={Boolean(metadataUrl)}>&nbsp;• {`${metadataName} ${metadataBuildNumber}`}</S.Text>
{name && (
<a href={url} target="_blank" onClick={event => event.stopPropagation()}>
<S.Text $hasLink={Boolean(url)}>&nbsp;• {`${name} ${buildNumber}`}</S.Text>
</a>
)}
{metadataBranch && <S.Text>&nbsp;• Branch: {metadataBranch}</S.Text>}
{branch && <S.Text>&nbsp;• Branch: {branch}</S.Text>}
</S.Row>
</S.Info>

Expand Down Expand Up @@ -108,12 +105,7 @@ const TestRunCard = ({
)}

<div>
<RunActionsMenu
resultId={runId}
testId={testId}
testSuiteRunId={testSuiteRunId}
testSuiteId={testSuiteId}
/>
<RunActionsMenu resultId={runId} testId={testId} testSuiteRunId={testSuiteRunId} testSuiteId={testSuiteId} />
</div>
</S.Container>
</Link>
Expand Down
117 changes: 60 additions & 57 deletions web/src/components/RunCard/TestSuiteRunCard.tsx
Expand Up @@ -15,68 +15,71 @@ interface IProps {
}

const TestSuiteRunCard = ({
run: {id: runId, createdAt, state, metadata, version, pass, fail, allStepsRequiredGatesPassed},
run: {
id: runId,
createdAt,
state,
metadata: {name, buildNumber, branch, url, source},
version,
pass,
fail,
allStepsRequiredGatesPassed,
},
testSuiteId,
linkTo,
}: IProps) => {
const metadataName = metadata?.name;
const metadataBuildNumber = metadata?.buildNumber;
const metadataBranch = metadata?.branch;
const metadataUrl = metadata?.url;

return (
<Link to={linkTo}>
<S.Container $isWhite>
<TestSuiteRunStatusIcon state={state} hasFailedTests={!allStepsRequiredGatesPassed} />
<S.Info>
<div>
<S.Title>v{version}</S.Title>
</div>
<S.Row>
<Tooltip title={Date.format(createdAt)}>
<S.Text>{Date.getTimeAgo(createdAt)}</S.Text>
</Tooltip>
{/* Adding this latter when is available */}
{/* <S.Text>&nbsp;• 0s (executionTime missing from API)</S.Text> */}

{metadataName && (
<a href={metadataUrl} target="_blank" onClick={event => event.stopPropagation()}>
<S.Text $hasLink={Boolean(metadataUrl)}>&nbsp;• {`${metadataName} ${metadataBuildNumber}`}</S.Text>
</a>
)}
{metadataBranch && <S.Text>&nbsp;• Branch: {metadataBranch}</S.Text>}
</S.Row>
</S.Info>

{state !== TestStateEnum.FAILED && state !== TestStateEnum.FINISHED && (
<div>
<TestState testState={state} />
</div>
)}
}: IProps) => (
<Link to={linkTo}>
<S.Container $isWhite>
<TestSuiteRunStatusIcon state={state} hasFailedTests={!allStepsRequiredGatesPassed} />
<S.Info>
<div>
<S.Title>v{version}</S.Title>
</div>
<S.Row>
<Tooltip title={Date.format(createdAt)}>
<S.Text>{Date.getTimeAgo(createdAt)}</S.Text>
</Tooltip>
{source && <S.Text>&nbsp;• Run via {source.toUpperCase()}</S.Text>}
{/* Adding this latter when is available */}
{/* <S.Text>&nbsp;• 0s (executionTime missing from API)</S.Text> */}

{(state === TestStateEnum.FAILED || state === TestStateEnum.FINISHED) && (
<S.Row>
<Tooltip title="Passed assertions">
<S.HeaderDetail>
<S.HeaderDot $passed />
{pass}
</S.HeaderDetail>
</Tooltip>
<Tooltip title="Failed assertions">
<S.HeaderDetail>
<S.HeaderDot $passed={false} />
{fail}
</S.HeaderDetail>
</Tooltip>
</S.Row>
)}
{name && (
<a href={url} target="_blank" onClick={event => event.stopPropagation()}>
<S.Text $hasLink={Boolean(url)}>&nbsp;• {`${name} ${buildNumber}`}</S.Text>
</a>
)}
{branch && <S.Text>&nbsp;• Branch: {branch}</S.Text>}
</S.Row>
</S.Info>

{state !== TestStateEnum.FAILED && state !== TestStateEnum.FINISHED && (
<div>
<TestSuiteRunActionsMenu runId={runId} testSuiteId={testSuiteId} />
<TestState testState={state} />
</div>
</S.Container>
</Link>
);
};
)}

{(state === TestStateEnum.FAILED || state === TestStateEnum.FINISHED) && (
<S.Row>
<Tooltip title="Passed assertions">
<S.HeaderDetail>
<S.HeaderDot $passed />
{pass}
</S.HeaderDetail>
</Tooltip>
<Tooltip title="Failed assertions">
<S.HeaderDetail>
<S.HeaderDot $passed={false} />
{fail}
</S.HeaderDetail>
</Tooltip>
</S.Row>
)}

<div>
<TestSuiteRunActionsMenu runId={runId} testSuiteId={testSuiteId} />
</div>
</S.Container>
</Link>
);

export default TestSuiteRunCard;
21 changes: 16 additions & 5 deletions web/src/components/RunDetailLayout/HeaderLeft.tsx
Expand Up @@ -18,8 +18,19 @@ interface IProps {
}

const HeaderLeft = ({name, triggerType, origin}: IProps) => {
const {run: {createdAt, testSuiteId, testSuiteRunId, executionTime, trace, traceId, testVersion} = {}, run} =
useTestRun();
const {
run: {
createdAt,
testSuiteId,
testSuiteRunId,
executionTime,
trace,
traceId,
testVersion,
metadata: {source} = {},
} = {},
run,
} = useTestRun();
const {onEdit, isEditLoading: isLoading, test} = useTest();
const createdTimeAgo = Date.getTimeAgo(createdAt ?? '');
const {navigate} = useDashboard();
Expand All @@ -33,8 +44,8 @@ const HeaderLeft = ({name, triggerType, origin}: IProps) => {
const description = useMemo(() => {
return (
<>
v{testVersion}{triggerType} • Ran {createdTimeAgo}
{testSuiteId && testSuiteRunId && (
v{testVersion}{triggerType} • Ran {createdTimeAgo}{source && <>Run via {source.toUpperCase()}</>}
{testSuiteId && !!testSuiteRunId && (
<>
{' '}
{' '}
Expand All @@ -45,7 +56,7 @@ const HeaderLeft = ({name, triggerType, origin}: IProps) => {
)}
</>
);
}, [triggerType, createdTimeAgo, testSuiteId, testSuiteRunId, testVersion]);
}, [testVersion, triggerType, createdTimeAgo, source, testSuiteId, testSuiteRunId]);

return (
<S.Section $justifyContent="flex-start">
Expand Down
31 changes: 31 additions & 0 deletions web/src/components/RunDetailTriggerResponse/ResponseMetadata.tsx
@@ -0,0 +1,31 @@
import {useTestRun} from 'providers/TestRun/TestRun.provider';
import {useMemo} from 'react';
import * as S from './RunDetailTriggerResponse.styled';
import KeyValueRow from '../KeyValueRow';

const ResponseMetadata = () => {
const {
run: {metadata},
} = useTestRun();

const entries = useMemo(() => Object.entries(metadata).filter(([, value]) => !!value), [metadata]);

if (!entries.length) {
return (
<S.EmptyContainer>
<S.EmptyIcon />
<S.EmptyTitle>There are no metadata entries used in this test</S.EmptyTitle>
</S.EmptyContainer>
);
}

return (
<S.ResponseVarsContainer>
{entries.map(([key, value]) => (
<KeyValueRow key={key} keyName={key} value={value} />
))}
</S.ResponseVarsContainer>
);
};

export default ResponseMetadata;
Expand Up @@ -18,11 +18,13 @@ import ResponseVariableSet from './ResponseVariableSet';
import ResponseHeaders from './ResponseHeaders';
import * as S from './RunDetailTriggerResponse.styled';
import {IPropsComponent} from './RunDetailTriggerResponseFactory';
import ResponseMetadata from './ResponseMetadata';

const TabsKeys = {
Body: 'body',
Headers: 'headers',
VariableSet: 'variable-set',
Metadata: 'metadata',
};

const tracetestTriggerSelector = 'span[tracetest.span.type="general" name="Tracetest trigger"]';
Expand Down Expand Up @@ -146,6 +148,9 @@ const RunDetailTriggerResponse = ({
<Tabs.TabPane key={TabsKeys.VariableSet} tab="Variable Set">
<ResponseVariableSet />
</Tabs.TabPane>
<Tabs.TabPane key={TabsKeys.Metadata} tab="Metadata">
<ResponseMetadata />
</Tabs.TabPane>
</Tabs>
</S.TabsContainer>
</S.Container>
Expand Down
1 change: 0 additions & 1 deletion web/src/components/VariableSet/VariableSetForm.tsx
Expand Up @@ -31,7 +31,6 @@ const VariableSetForm = ({form, initialValues, onSubmit, onValidate}: IProps) =>
<Form.Item
label="Description"
name="description"
rules={[{required: true, message: 'Please input a description'}]}
>
<Input />
</Form.Item>
Expand Down
44 changes: 44 additions & 0 deletions web/src/models/RunMetadata.model.ts
@@ -0,0 +1,44 @@
import {Model} from 'types/Common.types';

export type TRawRunMetadata = Record<string, string>;

export enum KnownSources {
WEB = 'web',
CLI = 'cli',
API = 'api',
K6 = 'k6',
UNKNOWN = 'unknown',
}

type TKnownSources = KnownSources | string;

type RunMetadata = Model<
Record<string, string>,
{
name: string;
buildNumber: string;
branch: string;
url: string;
source: TKnownSources;
}
>;

function RunMetadata({
name = '',
buildNumber = '',
branch = '',
url = '',
source = '',
...rest
}: TRawRunMetadata): RunMetadata {
return {
name,
buildNumber,
branch,
url,
source,
...rest,
};
}

export default RunMetadata;

0 comments on commit 34ac84d

Please sign in to comment.