Ctrl K
ComunidadGuías…

tests/e2e/diff-rendering-assistant.spec.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { expect, test } from "@playwright/test";
import { enableScopedE2EAuth, scopedPath } from "./helpers/auth";
import {
  buildUiEventStreamBody,
  buildUiMessageStreamBody,
  fulfillJson,
  mockBaseApp,
  modelId,
  repo,
} from "./helpers/diff-rendering-fixtures";

test("assistant diff blocks render through the shared diff viewer", async ({
  page,
}) => {
  await enableScopedE2EAuth(page);
  await mockBaseApp(page);

  await page.route(/\/api\/conversations(?:\?.*)?$/, async (route) => {
    if (route.request().method() === "GET") {
      await fulfillJson(route, {
        id: new URL(route.request().url()).searchParams.get("id"),
        repo_id: repo.id,
        workspace_session_id: null,
        messages: [],
        local_msgs: [],
        model: modelId,
        mode: "AUTO",
      });
      return;
    }
    await fulfillJson(route, { ok: true });
  });
  await page.route("**/api/chat", async (route) => {
    await route.fulfill({
      status: 200,
      headers: {
        "content-type": "text/event-stream",
        "x-vercel-ai-ui-message-stream": "v1",
      },
      body: buildUiMessageStreamBody(
        [
          "I changed the greeting.",
          "",
          "```diff",
          "diff --git a/src/greeting.ts b/src/greeting.ts",
          "index 1111111..2222222 100644",
          "--- a/src/greeting.ts",
          "+++ b/src/greeting.ts",
          "@@ -1 +1 @@",
          "-export const greeting = 'hello'",
          "+export const greeting = 'hello there'",
          "```",
        ].join("\n")
      ),
    });
  });

  await page.goto(scopedPath("projects/workspace"));
  await page.waitForLoadState("networkidle");
  await page.getByTestId(`home-open-workspace-${repo.id}`).click();
  await page
    .getByRole("textbox", {
      name: "Ask the agent what to build, fix, or explain. Type / for commands or drop files here.",
    })
    .fill("show me the patch");
  await page.keyboard.press("Enter");

  await expect(page.getByText("Workspace Chat · demo-app")).toBeVisible();
  await expect(page.getByText("src/greeting.ts")).toBeVisible();
  await expect(
    page.getByText("export const greeting = 'hello there'")
  ).toBeVisible();
  await expect(
    page.getByText("diff --git a/src/greeting.ts b/src/greeting.ts")
  ).toHaveCount(0);
});

test("malformed diff fences fall back to the normal code renderer", async ({
  page,
}) => {
  await enableScopedE2EAuth(page);
  await mockBaseApp(page);

  await page.route(/\/api\/conversations(?:\?.*)?$/, async (route) => {
    if (route.request().method() === "GET") {
      await fulfillJson(route, {
        id: new URL(route.request().url()).searchParams.get("id"),
        repo_id: repo.id,
        workspace_session_id: null,
        messages: [],
        local_msgs: [],
        model: modelId,
        mode: "AUTO",
      });
      return;
    }
    await fulfillJson(route, { ok: true });
  });
  await page.route("**/api/chat", async (route) => {
    await route.fulfill({
      status: 200,
      headers: {
        "content-type": "text/event-stream",
        "x-vercel-ai-ui-message-stream": "v1",
      },
      body: buildUiMessageStreamBody(
        [
          "This patch is malformed on purpose.",
          "",
          "```diff",
          "this is not a patch",
          "just plain text inside a diff fence",
          "```",
        ].join("\n")
      ),
    });
  });

  await page.goto(scopedPath("projects/workspace"));
  await page.waitForLoadState("networkidle");
  await page.getByTestId(`home-open-workspace-${repo.id}`).click();
  await page
    .getByRole("textbox", {
      name: "Ask the agent what to build, fix, or explain. Type / for commands or drop files here.",
    })
    .fill("show me the malformed patch");
  await page.keyboard.press("Enter");

  await expect(page.getByText("this is not a patch")).toBeVisible();
  await expect(
    page.getByText("just plain text inside a diff fence")
  ).toBeVisible();
  await expect(page.getByText("src/greeting.ts")).toHaveCount(0);
});

test("saved local messages render patches through the shared diff viewer", async ({
  page,
}) => {
  await enableScopedE2EAuth(page);
  await mockBaseApp(page);

  const patch = [
    "diff --git a/src/local.ts b/src/local.ts",
    "index 1111111..2222222 100644",
    "--- a/src/local.ts",
    "+++ b/src/local.ts",
    "@@ -1 +1 @@",
    "-export const source = 'old'",
    "+export const source = 'local'",
    "",
  ].join("\n");

  await page.route(/\/api\/conversations(?:\?.*)?$/, async (route) => {
    if (route.request().method() === "GET") {
      await fulfillJson(route, {
        id: new URL(route.request().url()).searchParams.get("id"),
        repo_id: repo.id,
        workspace_session_id: null,
        messages: [],
        local_msgs: [{ id: "local-1", text: patch }],
        model: modelId,
        mode: "AUTO",
      });
      return;
    }
    await fulfillJson(route, { ok: true });
  });

  await page.goto(scopedPath("projects/workspace"));
  await page.waitForLoadState("networkidle");
  await page.getByTestId(`home-open-workspace-${repo.id}`).click();

  await expect(page.getByText("src/local.ts")).toBeVisible();
  await expect(page.getByText("export const source = 'local'")).toBeVisible();
});

test("assistant tool parts render nested diff output through the shared viewer", async ({
  page,
}) => {
  await enableScopedE2EAuth(page);
  await mockBaseApp(page);

  const patch = [
    "diff --git a/src/tool.ts b/src/tool.ts",
    "index 1111111..2222222 100644",
    "--- a/src/tool.ts",
    "+++ b/src/tool.ts",
    "@@ -1 +1 @@",
    "-export const toolState = 'waiting'",
    "+export const toolState = 'done'",
    "",
  ].join("\n");

  await page.route(/\/api\/conversations(?:\?.*)?$/, async (route) => {
    if (route.request().method() === "GET") {
      await fulfillJson(route, {
        id: new URL(route.request().url()).searchParams.get("id"),
        repo_id: repo.id,
        workspace_session_id: null,
        messages: [],
        local_msgs: [],
        model: modelId,
        mode: "AUTO",
      });
      return;
    }
    await fulfillJson(route, { ok: true });
  });
  await page.route("**/api/chat", async (route) => {
    await route.fulfill({
      status: 200,
      headers: {
        "content-type": "text/event-stream",
        "x-vercel-ai-ui-message-stream": "v1",
      },
      body: buildUiEventStreamBody([
        {
          type: "tool-input-available",
          toolCallId: "tool-call-1",
          toolName: "git_diff",
          input: { repo: repo.full_name },
        },
        {
          type: "tool-output-available",
          toolCallId: "tool-call-1",
          output: { stdout: patch },
        },
        {
          type: "tool-input-available",
          toolCallId: "tool-diagnostics",
          toolName: "inspect_result",
          input: {},
        },
        {
          type: "tool-output-available",
          toolCallId: "tool-diagnostics",
          output: {
            path: "lib/supabase/run-gallery.tsx",
            detail: "Vercel Sandbox failed: positive credit balance required",
          },
        },
        {
          type: "tool-input-available",
          toolCallId: "tool-error",
          toolName: "inspect_failure",
          input: {},
        },
        {
          type: "tool-output-error",
          toolCallId: "tool-error",
          errorText: "Vercel Sandbox failed: positive credit balance required",
        },
      ]),
    });
  });

  await page.goto(scopedPath("projects/workspace"));
  await page.waitForLoadState("networkidle");
  await page.getByTestId(`home-open-workspace-${repo.id}`).click();
  await page
    .getByRole("textbox", {
      name: "Ask the agent what to build, fix, or explain. Type / for commands or drop files here.",
    })
    .fill("show me the tool output");
  await page.keyboard.press("Enter");
  await page.getByText("git_diff").click();

  await expect(page.getByText("Diff source: stdout")).toBeVisible();
  await expect(page.getByText("src/tool.ts")).toBeVisible();
  await expect(page.getByText("export const toolState = 'done'")).toBeVisible();
  await page.getByText("inspect_result", { exact: true }).click();
  await expect(page.getByText(/lib\/supabase\/run-gallery.tsx/)).toBeVisible();
  await page.getByText("inspect_failure", { exact: true }).click();
  await expect(page.getByText(/positive credit balance required/)).toHaveCount(
    0
  );
  await expect(page.getByText(/Vercel Sandbox failed/)).toHaveCount(0);
  await expect(page.getByText(/MOG-TOOL-TOOLERROR/)).toBeVisible();
});