Repository: microsoft/playwright
File: packages/playwright/src/runner/dispatcher.ts (TypeScript)

Code before:
      body: params.body !== undefined ? Buffer.from(params.body, 'base64') : undefined
    };
    data.result.attachments.push(attachment);
    if (params.stepId) {
      const step = data.steps.get(params.stepId);
      if (step)
        step.attachments.push(attachment);
      else
        this._reporter.onStdErr?.('Internal error: step id not found: ' + params.stepId);
    }
  }

  private _onTestErrors(params: TestErrorsPayload) {
    if (this._failureTracker.hasReachedMaxFailures()) {
      // Do not show more than one error to avoid confusion.
      return;
    }

    const data = this._dataByTestId.get(params.testId)!;
    if (!data)
      return;
    const { test, result } = data;
    result.errors.push(...params.errors);
    result.error = result.errors[0];
    for (const error of result.errors)
      this._reporter.onTestError?.(test, result, error);
  }

  private _failTestWithErrors(test: TestCase, errors: TestError[]) {
    const runData = this._dataByTestId.get(test.id);
    // There might be a single test that has started but has not finished yet.
    let result: TestResult;
    if (runData) {
      result = runData.result;
    } else {
      result = test._appendTestResult();
      this._reporter.onTestBegin?.(test, result);
    }
    result.errors.push(...errors);
    result.error = result.errors[0];
    for (const error of result.errors)
      this._reporter.onTestError?.(test, result, error);
    result.status = errors.length ? 'failed' : 'skipped';
    this._reportTestEnd(test, result);
    this._failedTests.add(test);
  }

  private _massSkipTestsFromRemaining(testIds: Set<string>, errors: TestError[]) {
    for (const test of this._remainingByTestId.values()) {
      if (!testIds.has(test.id))
        continue;

Review comment (suggestion):
- We should not notify about the same error from `result.errors` multiple times.
- It is better for consistency to maintain that `result.errors[result.errors.length - 1] === newError` inside `onTestError()`.

```suggestion
    for (const error of params.errors) {
      result.errors.push(error);
      result.error = result.errors[0];
      this._reporter.onTestError?.(test, result, error);
    }
```

Code after:
      body: params.body !== undefined ? Buffer.from(params.body, 'base64') : undefined
    };
    data.result.attachments.push(attachment);
    if (params.stepId) {
      const step = data.steps.get(params.stepId);
      if (step)
        step.attachments.push(attachment);
      else
        this._reporter.onStdErr?.('Internal error: step id not found: ' + params.stepId);
    }
  }

  private _onTestErrors(params: TestErrorsPayload) {
    if (this._failureTracker.hasReachedMaxFailures()) {
      // Do not show more than one error to avoid confusion.
      return;
    }

    const data = this._dataByTestId.get(params.testId)!;
    if (!data)
      return;
    const { test, result } = data;
    for (const error of params.errors) {
      result.errors.push(error);
      result.error = result.errors[0];
      this._reporter.onTestError?.(test, result, error);
    }
  }

  private _failTestWithErrors(test: TestCase, errors: TestError[]) {
    const runData = this._dataByTestId.get(test.id);
    // There might be a single test that has started but has not finished yet.
    let result: TestResult;
    if (runData) {
      result = runData.result;
    } else {
      result = test._appendTestResult();
      this._reporter.onTestBegin?.(test, result);
    }
    for (const error of errors) {
      result.errors.push(error);
      result.error = result.errors[0];
      this._reporter.onTestError?.(test, result, error);
    }
    result.status = errors.length ? 'failed' : 'skipped';
    this._reportTestEnd(test, result);
    this._failedTests.add(test);
  }

  private _massSkipTestsFromRemaining(testIds: Set<string>, errors: TestError[]) {
    for (const test of this._remainingByTestId.values()) {