Source: pipeline/prompts/playwrightCapabilityGuide.js

/**
 * @module pipeline/prompts/playwrightCapabilityGuide
 * @description Tier/scenario-aware Playwright capability guidance to keep
 * prompts focused instead of dumping an undifferentiated capability list.
 */

const CLOUD_UI_CAPABILITIES = [
  "Use browser/context lifecycle only when needed (newContext/newPage/storageState).",
  "Prefer resilient locators: getByRole/getByText/getByTestId, locator(), frameLocator() for iframes.",
  "Cover rich interactions where the UI requires them: dblclick/hover/check/uncheck/drag-drop/file upload/press.",
  "Use targeted waiting: auto-wait first, then waitForSelector/waitForLoadState('domcontentloaded') when justified.",
  "Use network/API primitives only for relevant flows: page.route mocks, request.newContext contract checks.",
  "Add debugging observability for fragile flows: screenshots/tracing/video attachments.",
  "For scale scenarios, structure tests with hooks/fixtures/retries/timeouts and parallel-safe describe blocks.",
  "Use device emulation/geolocation only when mobile or regional behaviour is explicitly under test.",
];

const LOCAL_UI_CAPABILITIES = [
  "Match Playwright APIs to scenario complexity (frames/uploads/drag-drop/mocks/API/device).",
  "Prefer semantic locators (getByRole/getByText/getByTestId) and frameLocator for iframe flows.",
  "Use stable waits (auto-wait + domcontentloaded + targeted waitForSelector).",
];

const API_CAPABILITIES = [
  "API tests must use request.newContext + HTTP methods (get/post/put/patch/delete).",
  "Validate status + response schema/content; use route mocking only when API dependency requires isolation.",
  "Do not include browser-only UI interactions unless explicitly generating hybrid API+UI coverage.",
];

const DEBUG_CAPABILITIES = [
  "Preserve advanced primitives already in the test (route mocks, storageState, tracing, frame locators).",
  "Apply the smallest fix possible without downgrading robust Playwright patterns to basic click/fill only.",
];

/**
 * Regexes that indicate the test uses advanced Playwright patterns where
 * assertion enhancement should be conservative to avoid breaking orchestration.
 */
const ADVANCED_PLAYWRIGHT_PATTERNS = [
  /\bpage\.route\s*\(/,
  /\broute\.(fulfill|continue|abort|fallback)\s*\(/,
  /\brequest\.newContext\s*\(/,
  /\bapi\.(get|post|put|patch|delete|fetch)\s*\(/,
  /\bframeLocator\s*\(/,
  /\bsetInputFiles\s*\(/,
  /\bdragAndDrop\s*\(/,
  /\bdragTo\s*\(/,
  /\bstorageState\s*\(/,
  /\btracing\.(start|stop|startChunk|stopChunk)\s*\(/,
];

/**
 * Build a capability block tuned for prompt purpose and model tier.
 *
 * @param {object} [opts]
 * @param {"ui"|"api"|"debug"} [opts.mode="ui"]
 * @param {"cloud"|"local"} [opts.tier="cloud"]
 * @returns {string}
 */
export function buildCapabilityCoverageBlock({ mode = "ui", tier = "cloud" } = {}) {
  let items = CLOUD_UI_CAPABILITIES;
  if (mode === "api") items = API_CAPABILITIES;
  if (mode === "debug") items = DEBUG_CAPABILITIES;
  if (mode === "ui" && tier === "local") items = LOCAL_UI_CAPABILITIES;
  return `PLAYWRIGHT CAPABILITY RULES (${mode.toUpperCase()}):
${items.map((item, idx) => `${idx + 1}. ${item}`).join("\n")}`;
}

/**
 * Returns true when code includes advanced Playwright primitives that are
 * sensitive to assertion enhancer rewrites.
 *
 * @param {string} playwrightCode
 * @returns {boolean}
 */
export function isAdvancedPlaywrightScenario(playwrightCode) {
  if (!playwrightCode || typeof playwrightCode !== "string") return false;
  return ADVANCED_PLAYWRIGHT_PATTERNS.some((pattern) => pattern.test(playwrightCode));
}