abstract href generator
This commit is contained in:
parent
2ae3918401
commit
f04234b3df
|
|
@ -14,7 +14,7 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import type { TestAttachment } from './types';
|
||||
import type { TestAttachment, TestCase, TestCaseSummary, TestResult, TestResultSummary } from './types';
|
||||
import * as React from 'react';
|
||||
import * as icons from './icons';
|
||||
import { TreeItem } from './treeItem';
|
||||
|
|
@ -22,6 +22,7 @@ import { CopyToClipboard } from './copyToClipboard';
|
|||
import './links.css';
|
||||
import { linkifyText } from '@web/renderUtils';
|
||||
import { clsx } from '@web/uiUtils';
|
||||
import { URLSearchParams } from 'url';
|
||||
|
||||
export function navigate(href: string) {
|
||||
window.history.pushState({}, '', href);
|
||||
|
|
@ -149,3 +150,14 @@ export function Anchor({ id, children }: React.PropsWithChildren<{ id: AnchorID
|
|||
|
||||
return <div ref={ref}>{children}</div>;
|
||||
}
|
||||
|
||||
export function testResultHref({ test, result, anchor }: { test?: TestCase | TestCaseSummary, result?: TestResult | TestResultSummary, anchor?: string }) {
|
||||
const params = new URLSearchParams();
|
||||
if (test)
|
||||
params.set('testId', test.testId);
|
||||
if (test && result)
|
||||
params.set('run', '' + test.results.indexOf(result as any));
|
||||
if (anchor)
|
||||
params.set('anchor', anchor);
|
||||
return `#?` + params;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import * as React from 'react';
|
|||
import { TabbedPane } from './tabbedPane';
|
||||
import { AutoChip } from './chip';
|
||||
import './common.css';
|
||||
import { Link, ProjectLink, SearchParamsContext } from './links';
|
||||
import { Link, ProjectLink, SearchParamsContext, testResultHref } from './links';
|
||||
import { statusIcon } from './statusIcon';
|
||||
import './testCaseView.css';
|
||||
import { TestResultView } from './testResultView';
|
||||
|
|
@ -53,9 +53,9 @@ export const TestCaseView: React.FC<{
|
|||
{test && <div className='hbox'>
|
||||
<div className='test-case-path'>{test.path.join(' › ')}</div>
|
||||
<div style={{ flex: 'auto' }}></div>
|
||||
<div className={clsx(!prev && 'hidden')}><Link href={`#?testId=${prev?.testId}${filterParam}`}>« previous</Link></div>
|
||||
<div className={clsx(!prev && 'hidden')}><Link href={testResultHref({ test: prev }) + filterParam}>« previous</Link></div>
|
||||
<div style={{ width: 10 }}></div>
|
||||
<div className={clsx(!next && 'hidden')}><Link href={`#?testId=${next?.testId}${filterParam}`}>next »</Link></div>
|
||||
<div className={clsx(!next && 'hidden')}><Link href={testResultHref({ test: next }) + filterParam}>next »</Link></div>
|
||||
</div>}
|
||||
{test && <div className='test-case-title'>{test?.title}</div>}
|
||||
{test && <div className='hbox'>
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import * as React from 'react';
|
|||
import { hashStringToInt, msToString } from './utils';
|
||||
import { Chip } from './chip';
|
||||
import { filterWithToken } from './filter';
|
||||
import { generateTraceUrl, Link, navigate, ProjectLink, SearchParamsContext } from './links';
|
||||
import { generateTraceUrl, Link, navigate, ProjectLink, SearchParamsContext, testResultHref } from './links';
|
||||
import { statusIcon } from './statusIcon';
|
||||
import './testFileView.css';
|
||||
import { video, image, trace } from './icons';
|
||||
|
|
@ -48,7 +48,7 @@ export const TestFileView: React.FC<React.PropsWithChildren<{
|
|||
{statusIcon(test.outcome)}
|
||||
</span>
|
||||
<span>
|
||||
<Link href={`#?testId=${test.testId}${filterParam}`} title={[...test.path, test.title].join(' › ')}>
|
||||
<Link href={testResultHref({ test }) + filterParam} title={[...test.path, test.title].join(' › ')}>
|
||||
<span className='test-file-title'>{[...test.path, test.title].join(' › ')}</span>
|
||||
</Link>
|
||||
{projectNames.length > 1 && !!test.projectName &&
|
||||
|
|
@ -59,7 +59,7 @@ export const TestFileView: React.FC<React.PropsWithChildren<{
|
|||
<span data-testid='test-duration' style={{ minWidth: '50px', textAlign: 'right' }}>{msToString(test.duration)}</span>
|
||||
</div>
|
||||
<div className='test-file-details-row'>
|
||||
<Link href={`#?testId=${test.testId}`} title={[...test.path, test.title].join(' › ')} className='test-file-path-link'>
|
||||
<Link href={testResultHref({ test })} title={[...test.path, test.title].join(' › ')} className='test-file-path-link'>
|
||||
<span className='test-file-path'>{test.location.file}:{test.location.line}</span>
|
||||
</Link>
|
||||
{imageDiffBadge(test)}
|
||||
|
|
@ -75,14 +75,14 @@ function imageDiffBadge(test: TestCaseSummary): JSX.Element | undefined {
|
|||
for (const result of test.results) {
|
||||
for (const attachment of result.attachments) {
|
||||
if (attachment.contentType.startsWith('image/') && !!attachment.name.match(/-(expected|actual|diff)/))
|
||||
return <Link href={`#?` + new URLSearchParams({ testId: test.testId, anchor: `attachment-${attachment.name}`, run: '' + test.results.indexOf(result) })} title='View images' className='test-file-badge'>{image()}</Link>;
|
||||
return <Link href={testResultHref({ test, result, anchor: `attachment-${attachment.name}` })} title='View images' className='test-file-badge'>{image()}</Link>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function videoBadge(test: TestCaseSummary): JSX.Element | undefined {
|
||||
const resultWithVideo = test.results.find(result => result.attachments.some(attachment => attachment.name === 'video'));
|
||||
return resultWithVideo ? <Link href={`#?` + new URLSearchParams({ testId: test.testId, anchor: `attachment-video`, run: '' + test.results.indexOf(resultWithVideo) })} title='View video' className='test-file-badge'>{video()}</Link> : undefined;
|
||||
return resultWithVideo ? <Link href={testResultHref({ test, result: resultWithVideo, anchor: 'attachment-video' })} title='View video' className='test-file-badge'>{video()}</Link> : undefined;
|
||||
}
|
||||
|
||||
function traceBadge(test: TestCaseSummary): JSX.Element | undefined {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import { TreeItem } from './treeItem';
|
|||
import { msToString } from './utils';
|
||||
import { AutoChip } from './chip';
|
||||
import { traceImage } from './images';
|
||||
import { Anchor, AttachmentLink, generateTraceUrl } from './links';
|
||||
import { Anchor, AttachmentLink, generateTraceUrl, testResultHref } from './links';
|
||||
import { statusIcon } from './statusIcon';
|
||||
import type { ImageDiff } from '@web/shared/imageDiffView';
|
||||
import { ImageDiffView } from '@web/shared/imageDiffView';
|
||||
|
|
@ -177,7 +177,7 @@ const StepTreeItem: React.FC<{
|
|||
const attachmentName = step.title.match(/^attach "(.*)"$/)?.[1];
|
||||
return <TreeItem title={<span aria-label={step.title}>
|
||||
<span style={{ float: 'right' }}>{msToString(step.duration)}</span>
|
||||
{attachmentName && <a style={{ float: 'right' }} title='link to attachment' href={`#?testId=${test.testId}&anchor=attachment-${encodeURIComponent(attachmentName)}&run=${test.results.indexOf(result)}`} onClick={evt => { evt.stopPropagation(); }}>{icons.attachment()}</a>}
|
||||
{attachmentName && <a style={{ float: 'right' }} title='link to attachment' href={testResultHref({ test, result, anchor: `attachment-${attachmentName}` })} onClick={evt => { evt.stopPropagation(); }}>{icons.attachment()}</a>}
|
||||
{statusIcon(step.error || step.duration === -1 ? 'failed' : 'passed')}
|
||||
<span>{step.title}</span>
|
||||
{step.count > 1 && <> ✕ <span className='test-result-counter'>{step.count}</span></>}
|
||||
|
|
|
|||
Loading…
Reference in a new issue