Repository: microsoft/playwright
File: packages/html-reporter/src/filter.ts (TypeScript)

Code before:
  let status: SearchValues['status'] = 'passed';
  if (test.outcome === 'unexpected')
    status = 'failed';
  if (test.outcome === 'flaky')
    status = 'flaky';
  if (test.outcome === 'skipped')
    status = 'skipped';
  const searchValues: SearchValues = {
    text: (status + ' ' + test.projectName + ' ' + test.tags.join(' ') + ' ' + test.location.file + ' ' + test.path.join(' ') + ' ' + test.title).toLowerCase(),
    project: test.projectName.toLowerCase(),
    status,
    file: test.location.file,
    line: String(test.location.line),
    column: String(test.location.column),
    labels: test.tags.map(tag => tag.toLowerCase()),
    annotations: test.annotations.map(a => a.type.toLowerCase() + '=' + a.description?.toLocaleLowerCase())
  };
  test[searchValuesSymbol] = searchValues;
  return searchValues;
}

// Extract quoted groups of search params, or tokens separated by whitespace
const SEARCH_PARAM_GROUP_REGEX = /("[^"]*"|"[^"]*$|\S+)/g;

export function filterWithQuery(searchParams: URLSearchParams, token: string, append: boolean): string {
  const result = new URLSearchParams();
  if (searchParams.has('speedboard'))
    result.set('speedboard', '');

  const existingQuery = searchParams.get('q') ?? '';
  const tokens = [...existingQuery.matchAll(SEARCH_PARAM_GROUP_REGEX)].map(m => {
    const rawValue = m[0];
    return rawValue.startsWith('"') && rawValue.endsWith('"') && rawValue.length > 1 ? rawValue.slice(1, rawValue.length - 1) : rawValue;
  });
  if (append) {
    result.set('q', joinTokens(!tokens.includes(token) ? [...tokens, token] : tokens.filter(t => t !== token)));
    return '#?' + result;
  }

  // if metaKey or ctrlKey is not pressed, replace existing token with new token
  let prefix: 's:' | 'p:' | '@';
  if (token.startsWith('s:'))
    prefix = 's:';
  if (token.startsWith('p:'))
    prefix = 'p:';
  if (token.startsWith('@'))
    prefix = '@';

  const newTokens = tokens.filter(t => !t.startsWith(prefix));
  newTokens.push(token);


Review comment (suggestion):
I'd recommend `const result = new URLSearchParams(searchParams)` instead to inherit everything you've got.

Code after:
  let status: SearchValues['status'] = 'passed';
  if (test.outcome === 'unexpected')
    status = 'failed';
  if (test.outcome === 'flaky')
    status = 'flaky';
  if (test.outcome === 'skipped')
    status = 'skipped';
  const searchValues: SearchValues = {
    text: (status + ' ' + test.projectName + ' ' + test.tags.join(' ') + ' ' + test.location.file + ' ' + test.path.join(' ') + ' ' + test.title).toLowerCase(),
    project: test.projectName.toLowerCase(),
    status,
    file: test.location.file,
    line: String(test.location.line),
    column: String(test.location.column),
    labels: test.tags.map(tag => tag.toLowerCase()),
    annotations: test.annotations.map(a => a.type.toLowerCase() + '=' + a.description?.toLocaleLowerCase())
  };
  test[searchValuesSymbol] = searchValues;
  return searchValues;
}

// Extract quoted groups of search params, or tokens separated by whitespace
const SEARCH_PARAM_GROUP_REGEX = /("[^"]*"|"[^"]*$|\S+)/g;

export function filterWithQuery(searchParams: URLSearchParams, token: string, append: boolean): string {
  const result = new URLSearchParams(searchParams);
  const existingQuery = searchParams.get('q') ?? '';
  const tokens = [...existingQuery.matchAll(SEARCH_PARAM_GROUP_REGEX)].map(m => {
    const rawValue = m[0];
    return rawValue.startsWith('"') && rawValue.endsWith('"') && rawValue.length > 1 ? rawValue.slice(1, rawValue.length - 1) : rawValue;
  });
  if (append) {
    result.set('q', joinTokens(!tokens.includes(token) ? [...tokens, token] : tokens.filter(t => t !== token)));
    return '#?' + result;
  }

  // if metaKey or ctrlKey is not pressed, replace existing token with new token
  let prefix: 's:' | 'p:' | '@';
  if (token.startsWith('s:'))
    prefix = 's:';
  if (token.startsWith('p:'))
    prefix = 'p:';
  if (token.startsWith('@'))
    prefix = '@';

  const newTokens = tokens.filter(t => !t.startsWith(prefix));
  newTokens.push(token);

  result.set('q', joinTokens(newTokens));
  return '#?' + result;
}