{"version":3,"file":"dump/task-status.mjs","sources":["../../../src/dump/task-status.ts"],"sourcesContent":["/**\n * Single source of truth for turning raw task/execution dump data into a\n * semantic status.\n *\n * Both the report sidebar (per-step status icon) and the merged-report\n * status aggregation must agree on what \"failed\" means, otherwise a merged\n * report can mark a failing case as passed. Keeping the rules here — as pure\n * functions over plain dump fields — lets the front-end icons and the backend\n * `mergeReportFiles` attribute derivation share the exact same logic.\n */\nimport type { ExecutionTask, TestStatus } from '../types';\n\n/**\n * The subset of a task's fields needed to derive its status, picked from\n * `ExecutionTask` so the field names/types stay defined in one place. It is a\n * structural subset, so both the full `ExecutionTask` and the front-end task\n * variants (which carry extra fields) satisfy it.\n */\nexport type TaskStatusFields = Partial<\n  Pick<ExecutionTask, 'status' | 'subType' | 'error' | 'errorMessage'> & {\n    // `output` is only ever compared to `false`; keep it `unknown` rather than\n    // the picked generic `any` so the field stays type-safe for callers.\n    output: unknown;\n  }\n>;\n\nexport type DerivedTaskStatus =\n  | 'passed'\n  | 'failed'\n  | 'warning'\n  | 'pending'\n  | 'running'\n  | 'cancelled';\n\n/**\n * Derive a single task's semantic status from its raw dump fields. Mirrors the\n * historical `getStatusIcon` logic in the report sidebar so icons and merged\n * status never diverge.\n */\nexport function deriveTaskStatus(task: TaskStatusFields): DerivedTaskStatus {\n  const isFinished = task.status === 'finished';\n\n  // Hard failure: the task threw / was aborted (status === 'failed', e.g. a\n  // failed Assert which throws `Assertion failed`, or a locate failure), or it\n  // finished but still carries an error.\n  if (task.status === 'failed') {\n    return 'failed';\n  }\n  if (isFinished && (task.error || task.errorMessage)) {\n    return 'failed';\n  }\n\n  // A `WaitFor` that finished falsy is a warning, not a hard failure.\n  if (isFinished && task.subType === 'WaitFor' && task.output === false) {\n    return 'warning';\n  }\n\n  // An `Assert` that finished with a falsy result is a failure. This is a\n  // legacy fallback: modern asserts throw and are caught above.\n  if (task.subType === 'Assert' && isFinished && task.output === false) {\n    return 'failed';\n  }\n\n  if (task.status === 'pending') return 'pending';\n  if (task.status === 'running') return 'running';\n  if (task.status === 'cancelled') return 'cancelled';\n\n  // finished, no error\n  return 'passed';\n}\n\n/**\n * Aggregate the tasks of one case (a list of executions) into a single\n * `TestStatus`. A case is `failed` when any of its tasks derives to `failed`;\n * otherwise it is `passed`. Warnings, pending/running/cancelled steps do not by\n * themselves fail a case.\n *\n * This only ever produces `passed` / `failed`; the finer `timedOut` /\n * `skipped` / `interrupted` statuses can only come from a source report that\n * already recorded them (e.g. a Playwright run), which callers should prefer\n * when available.\n */\nexport function deriveCaseStatus(\n  executions: Array<{ tasks?: TaskStatusFields[] }>,\n): TestStatus {\n  for (const execution of executions) {\n    for (const task of execution.tasks ?? []) {\n      if (deriveTaskStatus(task) === 'failed') {\n        return 'failed';\n      }\n    }\n  }\n  return 'passed';\n}\n"],"names":["deriveTaskStatus","task","isFinished","deriveCaseStatus","executions","execution"],"mappings":"AAuCO,SAASA,iBAAiBC,IAAsB;IACrD,MAAMC,aAAaD,AAAgB,eAAhBA,KAAK,MAAM;IAK9B,IAAIA,AAAgB,aAAhBA,KAAK,MAAM,EACb,OAAO;IAET,IAAIC,cAAeD,CAAAA,KAAK,KAAK,IAAIA,KAAK,YAAW,GAC/C,OAAO;IAIT,IAAIC,cAAcD,AAAiB,cAAjBA,KAAK,OAAO,IAAkBA,AAAgB,UAAhBA,KAAK,MAAM,EACzD,OAAO;IAKT,IAAIA,AAAiB,aAAjBA,KAAK,OAAO,IAAiBC,cAAcD,AAAgB,UAAhBA,KAAK,MAAM,EACxD,OAAO;IAGT,IAAIA,AAAgB,cAAhBA,KAAK,MAAM,EAAgB,OAAO;IACtC,IAAIA,AAAgB,cAAhBA,KAAK,MAAM,EAAgB,OAAO;IACtC,IAAIA,AAAgB,gBAAhBA,KAAK,MAAM,EAAkB,OAAO;IAGxC,OAAO;AACT;AAaO,SAASE,iBACdC,UAAiD;IAEjD,KAAK,MAAMC,aAAaD,WACtB,KAAK,MAAMH,QAAQI,UAAU,KAAK,IAAI,EAAE,CACtC,IAAIL,AAA2B,aAA3BA,iBAAiBC,OACnB,OAAO;IAIb,OAAO;AACT"}