> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getdecipher.com/llms.txt
> Use this file to discover all available pages before exploring further.

# TypeScript Wrapper

> Run decipher-qa test run-cdp programmatically from a Node script, test suite, or custom CI runner

Spawn the `decipher-qa` CLI as a child process and parse its final result block. Below is a copy-pasteable reference implementation.

<Note>
  This is **boilerplate** — a thin wrapper around the CLI to get you started. Fork it, rename the functions, add retry logic, wire it into your test framework, emit your own telemetry — whatever fits your pipeline. The CLI is the contract; the wrapper is just convenience.
</Note>

## The Runner

The CLI prints a final `=== RESULT ===` block with the run summary as JSON. The runner spawns the process, streams its output, and parses that block on exit.

**`decipher-qa-runner.ts`**

```typescript theme={null}
import { spawn } from "child_process";

export type TestRunStatus = "passed" | "failed" | "failed_internal";

export interface RunTestResult {
  status: TestRunStatus;
  duration: number; // milliseconds
  runId: number;
  runUrl: string;
}

export interface RunOptions {
  testId: number;
  cdpUrl?: string;
  headful?: boolean;
  origin?: string;
  stream?: boolean; // default true — pipe CLI output to your terminal
}

export function runDecipherQaTest(opts: RunOptions): Promise<RunTestResult> {
  const args = ["test", "run-cdp", "--testId", String(opts.testId)];
  if (opts.cdpUrl) args.push("--cdp", opts.cdpUrl);
  if (opts.headful) args.push("--headful");
  if (opts.origin) args.push("--origin", opts.origin);

  const child = spawn("decipher-qa", args, {
    stdio: ["ignore", "pipe", "pipe"],
  });

  const streaming = opts.stream !== false;
  let stdout = "";

  child.stdout!.on("data", (chunk: Buffer) => {
    if (streaming) process.stdout.write(chunk);
    stdout += chunk.toString("utf8");
  });
  child.stderr!.on("data", (chunk: Buffer) => {
    if (streaming) process.stderr.write(chunk);
  });

  return new Promise((resolve, reject) => {
    child.on("error", reject);
    child.on("close", () => {
      const clean = stdout.replace(/\x1b\[[0-9;]*m/g, "");
      const marker = clean.lastIndexOf("=== RESULT ===");
      if (marker === -1) {
        return reject(new Error("decipher-qa exited without a result block"));
      }
      try {
        const json = clean.slice(marker + "=== RESULT ===".length).trim();
        resolve(JSON.parse(json) as RunTestResult);
      } catch (err) {
        reject(new Error(`Failed to parse decipher-qa result: ${(err as Error).message}`));
      }
    });
  });
}
```

## Example Script

Here's a self-contained script that runs test `1522` against a local headful Chromium and logs the result. Swap in your own `testId` and options:

```typescript theme={null}
import { runDecipherQaTest } from "./decipher-qa-runner";

async function main() {
  const result = await runDecipherQaTest({
    testId: 1522,
    headful: true,
    origin: "https://staging.myapp.com",
    stream: true,
  });

  console.log("\n=== RESULT ===");
  console.log(JSON.stringify(result, null, 2));

  if (result.status !== "passed") {
    console.error(`Test failed: ${result.error ?? "unknown error"}`);
    process.exit(1);
  }
}

main().catch((err) => {
  console.error(err);
  process.exit(1);
});
```

## Usage

Run it with `tsx` (or compile and run with `node`):

```bash theme={null}
npx tsx run-test.ts
```

You'll get a streaming view of the run followed by a JSON summary:

```json theme={null}
{
  "status": "passed",
  "duration": 127000,
  "runId": 48291,
  "runUrl": "https://app.getdecipher.com/tests/1522/runs/48291"
}
```

The process exits `0` on pass and `1` on fail, so it slots into any CI pipeline that already expects conventional exit codes.

***

*Need help? [Contact our support team](mailto:team@getdecipher.com).*
