import { describe, test, expect } from 'vitest';
import { buildScanObjective } from '../src/objective.js';

describe('buildScanObjective', () => {
  test('locks the agent to the given dev origin', () => {
    const p = buildScanObjective({ scope: null, origin: 'http://localhost:5173' });
    expect(p).toContain('http://localhost:5173');
    // origin-lock must be stated, not just mentioned
    expect(p).toMatch(/only.*http:\/\/localhost:5173|http:\/\/localhost:5173.*only/is);
  });

  test('whole-site scope when no scope is given', () => {
    const p = buildScanObjective({ scope: null, origin: 'http://localhost:5173' });
    expect(p).toMatch(/whole|entire/i);
  });

  test('threads a natural-language scope verbatim and bounds the agent to it', () => {
    const p = buildScanObjective({ scope: 'the checkout flow', origin: 'http://localhost:5173' });
    expect(p).toContain('the checkout flow');
    // must instruct staying within that scope
    expect(p).toMatch(/only.*the checkout flow|stay.*the checkout flow|within.*the checkout flow/is);
  });

  test('is offensive: destructive allowed, exploit-to-confirm', () => {
    const p = buildScanObjective({ scope: null, origin: 'http://localhost:5173' });
    expect(p).toMatch(/destructive/i);
    expect(p).toMatch(/exploit|confirm/i);
  });

  test('states the legitimacy boundary: no other origins, no DoS, no evasion', () => {
    const p = buildScanObjective({ scope: null, origin: 'http://localhost:5173' });
    expect(p).toMatch(/no\s+other\s+origin|never.*other\s+origin|other\s+origins?/i);
    expect(p).toMatch(/denial.of.service|dos|flood/i);
    expect(p).toMatch(/evasion|evade|stealth/i);
  });

  test('teaches the warm-up → attack → record loop with the probe tools', () => {
    const p = buildScanObjective({ scope: null, origin: 'http://localhost:5173' });
    // warm-up traffic generation
    expect(p).toMatch(/mcp__playwright/);
    // the probe/sweep tools
    expect(p).toMatch(/suggest_probes/);
    expect(p).toMatch(/replay_flow/);
    // checks recorded with intent + expected status
    expect(p).toMatch(/intent/i);
    expect(p).toMatch(/expect|expected/i);
  });

  test('ends by demanding an explicit coverage-gap (what was NOT tested) report', () => {
    const p = buildScanObjective({ scope: null, origin: 'http://localhost:5173' });
    expect(p).toMatch(/not\s+test|did\s+not\s+(?:test|cover)|coverage\s+gap|what.*could.*not/is);
    // gaps must be recorded structurally (so both CLI + widget reports see them)
    expect(p).toMatch(/record_coverage_gap/);
  });
});
