job-manager.test.js 2.29 KB
/**
 * Unit Tests — job-manager.js
 */
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import fs from 'fs';

describe('JobManager', () => {
  let JobManager, jm;
  const STORE_PATH = '/tmp/test-jobs.json';

  beforeAll(() => {
    if (fs.existsSync(STORE_PATH)) fs.unlinkSync(STORE_PATH);
    ({ JobManager } = require('../../services/job-manager'));
    jm = new JobManager({ storePath: STORE_PATH });
  });

  afterAll(() => {
    try { fs.unlinkSync(STORE_PATH); } catch {}
  });

  it('should create a job with unique ID', () => {
    const job = jm.createJob({ domain: 'test', description: 'Test job' });
    expect(job.jobId).toBeDefined();
    expect(job.status).toBe('queued');
  });

  it('should get a job by ID', () => {
    const created = jm.createJob({ domain: 'test2' });
    const fetched = jm.getJob(created.jobId);
    expect(fetched).toBeDefined();
    expect(fetched.jobId).toBe(created.jobId);
  });

  it('should return null for non-existent job', () => {
    expect(jm.getJob('nonexistent-id')).toBeNull();
  });

  it('should update job status', () => {
    const job = jm.createJob({ domain: 'update-test' });
    jm.updateJob(job.jobId, { status: 'running', progress: '50%' });
    const updated = jm.getJob(job.jobId);
    expect(updated.status).toBe('running');
    expect(updated.progress).toBe('50%');
  });

  it('should list jobs', () => {
    const jobs = jm.listJobs({ limit: 100 });
    expect(Array.isArray(jobs)).toBe(true);
    expect(jobs.length).toBeGreaterThanOrEqual(2);
  });

  it('should filter jobs by apiKey', () => {
    const job = jm.createJob({ domain: 'keyed', apiKey: 'test-key-123' });
    const filtered = jm.listJobs({ apiKey: 'test-key-123' });
    expect(filtered.some(j => j.jobId === job.jobId)).toBe(true);
  });

  it('should provide public job view', () => {
    const job = jm.createJob({ domain: 'public-test', apiKey: 'secret-key' });
    const pub = jm.getPublicJob(job.jobId);
    expect(pub).toBeDefined();
    expect(pub.jobId).toBe(job.jobId);
    // Public view should not expose internal apiKey
  });

  it('should persist jobs to file', () => {
    expect(fs.existsSync(STORE_PATH)).toBe(true);
    const data = JSON.parse(fs.readFileSync(STORE_PATH, 'utf-8'));
    expect(Array.isArray(data) || typeof data === 'object').toBe(true);
  });
});