~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/pds.js

An atproto PDS in JavaScript, for Cloudflare Workers and Node

0
0
main
84 lines · 2.5 KB Raw History
import { afterEach, describe, expect, it, vi } from 'vitest';
import { createShellExecutor } from '../src/executor.js';

afterEach(() => {
  vi.unstubAllEnvs();
});

/**
 * @param {import('../src/workflow.js').WorkflowStep[]} steps
 * @param {{timeoutMs?: number, env?: Record<string, string>}} [options]
 */
async function run(steps, options = {}) {
  /** @type {string[]} */
  const log = [];
  const executor = createShellExecutor(
    options.timeoutMs ? { timeoutMs: options.timeoutMs } : {},
  );
  const results = await executor({
    dir: process.cwd(),
    steps,
    env: options.env ?? {},
    onLog: (chunk) => log.push(chunk),
  });
  return { results, log: log.join('') };
}

describe('createShellExecutor', () => {
  it('runs every step and reports each exit code', async () => {
    const { results } = await run([
      { name: 'first', run: 'true' },
      { name: 'second', run: 'true' },
    ]);
    expect(results.map((r) => [r.name, r.exitCode])).toEqual([
      ['first', 0],
      ['second', 0],
    ]);
    expect(results.every((r) => r.durationMs >= 0)).toBe(true);
  });

  it('stops at the first failing step', async () => {
    const { results } = await run([
      { name: 'fails', run: 'exit 3' },
      { name: 'never runs', run: 'true' },
    ]);
    expect(results).toHaveLength(1);
    expect(results[0].exitCode).toBe(3);
  });

  it('captures stdout and stderr', async () => {
    const { log } = await run([
      { name: 'talk', run: 'echo out; echo err 1>&2' },
    ]);
    expect(log).toContain('out');
    expect(log).toContain('err');
    expect(log).toContain('=== talk ===');
  });

  it('passes the run environment to the step', async () => {
    const { log } = await run([{ name: 'env', run: 'echo "$MARKER"' }], {
      env: { MARKER: 'from-workflow' },
    });
    expect(log).toContain('from-workflow');
  });

  it('withholds the runner credentials from the step', async () => {
    vi.stubEnv('PDSJS_CI_IDENTIFIER', 'runner.example.com');
    vi.stubEnv('PDSJS_CI_PASSWORD', 'runner-app-password');
    const { log } = await run([
      {
        name: 'env',
        run: 'echo "id=${PDSJS_CI_IDENTIFIER:-absent} pw=${PDSJS_CI_PASSWORD:-absent}"',
      },
    ]);
    expect(log).toContain('id=absent pw=absent');
  });

  it('reports a timed out step as a failure', async () => {
    const { results, log } = await run([{ name: 'hang', run: 'sleep 5' }], {
      timeoutMs: 100,
    });
    expect(results[0].exitCode).not.toBe(0);
    expect(log).toContain('timed out');
  });
});