Repository: microsoft/playwright
File: packages/html-reporter/src/testCaseView.tsx (TypeScript)

Code before:
import './testCaseView.css';
import { TestResultView } from './testResultView';
import { linkifyText } from '@web/renderUtils';
import { msToString } from './utils';
import { clsx } from '@web/uiUtils';
import { CopyToClipboardContainer } from './copyToClipboard';
import { HeaderView } from './headerView';
import type { MetadataWithCommitInfo } from '@playwright/isomorphic/types';
import { ProjectAndTagLabelsView } from './labels';

export const TestCaseView: React.FC<{
  projectNames: string[],
  test: TestCase,
  testRunMetadata: MetadataWithCommitInfo | undefined,
  next: TestCaseSummary | undefined,
  prev: TestCaseSummary | undefined,
  run: number,
  options?: HTMLReportOptions,
}> = ({ projectNames, test, testRunMetadata, run, next, prev, options }) => {
  const [selectedResultIndex, setSelectedResultIndex] = React.useState(run);
  const searchParams = React.useContext(SearchParamsContext);

  const filterParam = searchParams.has('q') ? '&q=' + searchParams.get('q') : '';
  const visibleTestAnnotations = test.annotations.filter(a => !a.type.startsWith('_')) ?? [];

  searchParams.delete('testId');
  const previousLink = testResultHref({ test: prev }, searchParams) + filterParam;
  const nextLink = testResultHref({ test: next }, searchParams) + filterParam;

  return <>
    <HeaderView
      title={test.title}
      leftSuperHeader={<div className='test-case-path'>{test.path.join(' › ')}</div>}
      rightSuperHeader={<>
        <div className={clsx(!prev && 'hidden')}><Link href={previousLink}>« previous</Link></div>
        <div style={{ width: 10 }}></div>
        <div className={clsx(!next && 'hidden')}><Link href={nextLink}>next »</Link></div>
      </>}
    />
    <div className='hbox' style={{ lineHeight: '24px' }}>
      <div className='test-case-location'>
        <CopyToClipboardContainer value={`${test.location.file}:${test.location.line}`}>
          {test.location.file}:{test.location.line}
        </CopyToClipboardContainer>
      </div>
      <div style={{ flex: 'auto' }}></div>
      <TraceLink test={test} trailingSeparator={true} />
      <div className='test-case-duration'>{msToString(test.duration)}</div>
    </div>
    <ProjectAndTagLabelsView style={{ marginLeft: '6px' }} projectNames={projectNames} activeProjectName={test.projectName} otherLabels={test.tags} />
    {test.results.length === 0 && visibleTestAnnotations.length !== 0 && <AutoChip header='Annotations' dataTestId='test-case-annotations'>

Review comment (suggestion):
I think it's better to let `testResultHref` handle this? It should set the `testId` based on the passed `test`.

Code after:
import './testCaseView.css';
import { TestResultView } from './testResultView';
import { linkifyText } from '@web/renderUtils';
import { msToString } from './utils';
import { clsx } from '@web/uiUtils';
import { CopyToClipboardContainer } from './copyToClipboard';
import { HeaderView } from './headerView';
import type { MetadataWithCommitInfo } from '@playwright/isomorphic/types';
import { ProjectAndTagLabelsView } from './labels';

export const TestCaseView: React.FC<{
  projectNames: string[],
  test: TestCase,
  testRunMetadata: MetadataWithCommitInfo | undefined,
  next: TestCaseSummary | undefined,
  prev: TestCaseSummary | undefined,
  run: number,
  options?: HTMLReportOptions,
}> = ({ projectNames, test, testRunMetadata, run, next, prev, options }) => {
  const [selectedResultIndex, setSelectedResultIndex] = React.useState(run);
  const searchParams = React.useContext(SearchParamsContext);

  const visibleTestAnnotations = test.annotations.filter(a => !a.type.startsWith('_')) ?? [];

  return <>
    <HeaderView
      title={test.title}
      leftSuperHeader={<div className='test-case-path'>{test.path.join(' › ')}</div>}
      rightSuperHeader={<>
        <div className={clsx(!prev && 'hidden')}><Link href={testResultHref({ test: prev }, searchParams)}>« previous</Link></div>
        <div style={{ width: 10 }}></div>
        <div className={clsx(!next && 'hidden')}><Link href={testResultHref({ test: next }, searchParams)}>next »</Link></div>
      </>}
    />
    <div className='hbox' style={{ lineHeight: '24px' }}>
      <div className='test-case-location'>
        <CopyToClipboardContainer value={`${test.location.file}:${test.location.line}`}>
          {test.location.file}:{test.location.line}
        </CopyToClipboardContainer>
      </div>
      <div style={{ flex: 'auto' }}></div>
      <TraceLink test={test} trailingSeparator={true} />
      <div className='test-case-duration'>{msToString(test.duration)}</div>
    </div>
    <ProjectAndTagLabelsView style={{ marginLeft: '6px' }} projectNames={projectNames} activeProjectName={test.projectName} otherLabels={test.tags} />
    {test.results.length === 0 && visibleTestAnnotations.length !== 0 && <AutoChip header='Annotations' dataTestId='test-case-annotations'>
      {visibleTestAnnotations.map((annotation, index) => <TestCaseAnnotationView key={index} annotation={annotation} />)}
    </AutoChip>}
    <TabbedPane tabs={
      test.results.map((result, index) => ({
        id: String(index),