-
Notifications
You must be signed in to change notification settings - Fork 72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feature(frontend): adding test spec snippets #2366
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
import React, {useCallback, useEffect, useMemo, useRef} from 'react'; | ||
import {CaretDownOutlined} from '@ant-design/icons'; | ||
import {Dropdown, Menu} from 'antd'; | ||
import SpanService from 'services/Span.service'; | ||
import Span from 'models/Span.model'; | ||
import {TEST_SPEC_SNIPPETS, TSnippet} from 'constants/TestSpecs.constants'; | ||
import * as S from './TestResults.styled'; | ||
import {useTestSpecForm} from '../TestSpecForm/TestSpecForm.provider'; | ||
|
||
interface IProps { | ||
selectedSpan: Span; | ||
visibleByDefault?: boolean; | ||
} | ||
|
||
const AddTestSpecButton = ({selectedSpan, visibleByDefault = false}: IProps) => { | ||
const {open} = useTestSpecForm(); | ||
const caretRef = useRef<HTMLElement>(null); | ||
const handleEmptyTestSpec = useCallback(() => { | ||
const selector = SpanService.getSelectorInformation(selectedSpan); | ||
|
||
open({ | ||
isEditing: false, | ||
selector, | ||
defaultValues: { | ||
selector, | ||
}, | ||
}); | ||
}, [open, selectedSpan]); | ||
|
||
const onSnippetClick = useCallback( | ||
(snippet: TSnippet) => { | ||
open({ | ||
isEditing: false, | ||
selector: snippet.selector, | ||
defaultValues: snippet, | ||
}); | ||
}, | ||
[open] | ||
); | ||
|
||
useEffect(() => { | ||
if (visibleByDefault && caretRef.current) { | ||
caretRef.current?.click(); | ||
} | ||
}, [visibleByDefault]); | ||
|
||
const menu = useMemo( | ||
() => ( | ||
<Menu | ||
items={[ | ||
{ | ||
label: 'Try these snippets for quick testing:', | ||
key: 'test', | ||
type: 'group', | ||
children: TEST_SPEC_SNIPPETS.map(snippet => ({ | ||
label: snippet.name, | ||
key: snippet.name, | ||
onClick: () => onSnippetClick(snippet), | ||
})), | ||
}, | ||
{type: 'divider'}, | ||
{ | ||
label: 'Empty Test Spec', | ||
key: 'empty-test-spec', | ||
onClick: handleEmptyTestSpec, | ||
}, | ||
]} | ||
/> | ||
), | ||
[handleEmptyTestSpec, onSnippetClick] | ||
); | ||
|
||
return ( | ||
<Dropdown.Button | ||
overlay={menu} | ||
trigger={['click']} | ||
placement="bottomRight" | ||
onClick={handleEmptyTestSpec} | ||
type="primary" | ||
buttonsRender={([leftButton]) => [ | ||
React.cloneElement(leftButton as React.ReactElement<any, string>, {'data-cy': 'add-test-spec-button'}), | ||
<S.CaretDropdownButton ref={caretRef} type="primary" data-cy="create-button"> | ||
<CaretDownOutlined /> | ||
</S.CaretDropdownButton>, | ||
]} | ||
> | ||
Add Test Spec | ||
</Dropdown.Button> | ||
); | ||
}; | ||
|
||
export default AddTestSpecButton; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import {IValues} from 'components/TestSpecForm/TestSpecForm'; | ||
|
||
export type TSnippet = Required<IValues>; | ||
|
||
export const HTTP_SPANS_STATUS_CODE: TSnippet = { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here's where we can continue adding snippets, you can add it manually using the UI and then copy the details in this file @kdhamric |
||
name: 'All HTTP Spans: Status code is 200', | ||
selector: 'span[tracetest.span.type="http"]', | ||
assertions: [ | ||
{ | ||
left: 'attr:http.status_code', | ||
comparator: '=', | ||
right: '200', | ||
}, | ||
], | ||
}; | ||
|
||
export const TRIGGER_SPAN_RESPONSE_TIME: TSnippet = { | ||
name: 'Trigger Span: Response time is less than 200ms', | ||
selector: 'span[tracetest.span.type="general" name="Tracetest trigger"]', | ||
assertions: [ | ||
{ | ||
left: 'attr:tracetest.span.duration', | ||
comparator: '<', | ||
right: '200ms', | ||
}, | ||
], | ||
}; | ||
|
||
export const DB_SPANS_RESPONSE_TIME: TSnippet = { | ||
name: 'All Database Spans: Processing time is less than 100ms', | ||
selector: 'span[tracetest.span.type="database"]', | ||
assertions: [ | ||
{ | ||
left: 'attr:tracetest.span.duration', | ||
comparator: '<', | ||
right: '100ms', | ||
}, | ||
], | ||
}; | ||
|
||
export const TRIGGER_SPAN_RESPONSE_BODY_CONTAINS: TSnippet = { | ||
name: 'Trigger Span: Response body contains "this string"', | ||
selector: 'span[tracetest.span.type="general" name="Tracetest trigger"]', | ||
assertions: [ | ||
{ | ||
left: 'attr:tracetest.response.body', | ||
comparator: 'contains', | ||
right: '"this string"', | ||
}, | ||
], | ||
}; | ||
|
||
export const GRPC_SPANS_STATUS_CODE: TSnippet = { | ||
name: 'All gRPC Spans: Status is Ok', | ||
selector: 'span[tracetest.span.type="rpc" rpc.system="grpc"]', | ||
assertions: [ | ||
{ | ||
left: 'attr:grpc.status_code', | ||
comparator: '=', | ||
right: '0', | ||
}, | ||
], | ||
}; | ||
|
||
export const DB_SPANS_QUALITY_DB_STATEMENT_PRESENT: TSnippet = { | ||
name: 'All Database Spans: db.statement should always be defined (QUALITY)', | ||
selector: 'span[tracetest.span.type="database"]', | ||
assertions: [ | ||
{ | ||
left: 'attr:db.system', | ||
comparator: '!=', | ||
right: '""', | ||
}, | ||
], | ||
}; | ||
|
||
export const TEST_SPEC_SNIPPETS: TSnippet[] = [ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Dont forget to add it to this array |
||
HTTP_SPANS_STATUS_CODE, | ||
GRPC_SPANS_STATUS_CODE, | ||
TRIGGER_SPAN_RESPONSE_TIME, | ||
TRIGGER_SPAN_RESPONSE_BODY_CONTAINS, | ||
DB_SPANS_RESPONSE_TIME, | ||
DB_SPANS_QUALITY_DB_STATEMENT_PRESENT, | ||
]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking if we should include an option to create an empty test spec. I know you can click the left part of the button but maybe users won't get it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it behave differently than clicking the left button? I think we can gather some feedback on the current UX and then we can think of updating it.
We also need @kdhamric feedback on what other snippets he'd like to add
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should have the same behavior as clicking the left button. It could be the last item in the list (with a visual separator).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Creating a list now.
I am afraid many people will not find this list of available test specs. A cheesy, but possibly workable solution, would be to have the dropdown list 'open' by default Proposal: if you go to the Test screen and there are no Test Specs defined, the dropdown list is Open. @olha23 thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here are 3 more 'prompted test specs'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
all done