* Map a `RunStepDto` (from `GET /runs/{runId}?includeSteps=true`) to a * `CliTestStep` so both the run-scoped and cumulative paths share the same * renderer (`renderStepsText`). * * Fields that don't exist on `RunStepDto`: * - `testId` — taken from the `RunResponse` * -
(step: RunStepDto, run: RunResponse)
| 3504 | * matches `RunResponse.failedStepIndex` |
| 3505 | */ |
| 3506 | function mapRunStepToCliTestStep(step: RunStepDto, run: RunResponse): CliTestStep { |
| 3507 | const numericIndex = parseInt(step.stepIndex, 10); |
| 3508 | return { |
| 3509 | testId: run.testId, |
| 3510 | stepIndex: numericIndex, |
| 3511 | action: step.action, |
| 3512 | description: step.description ?? '', |
| 3513 | status: step.status, |
| 3514 | screenshotUrl: step.screenshotUrl, |
| 3515 | htmlSnapshotUrl: step.htmlSnapshotUrl, |
| 3516 | runIdIfAvailable: run.runId, |
| 3517 | codeVersion: run.codeVersion ?? null, |
| 3518 | capturedAt: step.createdAt, |
| 3519 | updatedAt: step.createdAt, |
| 3520 | // `null` = unclassified (the run has no known failed step); otherwise a |
| 3521 | // concrete boolean — `true` for the failing step, `false` for the known |
| 3522 | // non-contributors. (Per the CliTestStep contract: null ≠ false.) |
| 3523 | outcomeContributesToFailure: |
| 3524 | run.failedStepIndex === null ? null : numericIndex === run.failedStepIndex, |
| 3525 | }; |
| 3526 | } |
| 3527 | |
| 3528 | export async function runSteps( |
| 3529 | opts: StepsOptions, |