Ctrl K
ComunidadGuías…

tests/e2e/skills-library.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 { linkedVercelCapability } from "./helpers/activation-fixtures";
import { GLOBAL_SKILL_SCOPE, type SkillScope } from "@/lib/skills";
import type { Route } from "@playwright/test";

const connectedUser = {
  id: "user-1",
  email: "alex@example.com",
  username: "alex",
  name: "Alex",
  avatar_url: "https://example.com/avatar.png",
  github_connected: true,
  github_app_connected: true,
  github_app_available: true,
  github_connection_mode: "app" as const,
  vercel: linkedVercelCapability,
};

type SkillRecord = {
  id: string;
  name: string;
  description: string | null;
  scope: SkillScope;
  content: string;
  is_public: boolean;
  tags: string[];
  usage_count: number;
  created_at: string;
};

type SaveSkillPayload = Omit<
  SkillRecord,
  "id" | "scope" | "tags" | "usage_count" | "created_at"
> & {
  scope?: SkillScope;
};

async function fulfillJson(route: Route, data: unknown, status = 200) {
  await route.fulfill({
    status,
    contentType: "application/json",
    body: JSON.stringify(data),
  });
}

test("registry install saves the skill and takes the user to the installed list", async ({
  page,
}) => {
  const skills: SkillRecord[] = [
    {
      id: "project-skill-1",
      name: "Project Review",
      description: "Project-specific review guidance",
      scope: "project",
      content: "# Project Review",
      is_public: false,
      tags: [],
      usage_count: 0,
      created_at: new Date().toISOString(),
    },
  ];

  await enableScopedE2EAuth(page);

  await page.route("**/api/auth/user", (route) =>
    fulfillJson(route, { user: connectedUser })
  );
  await page.route("**/api/skills/registry/acme/toolbox/review-bot", (route) =>
    fulfillJson(route, {
      name: "Review Bot",
      description: "Review incoming pull requests",
      installs: 42,
      source: "acme/toolbox",
      content: "# Review Bot\nReview incoming pull requests.",
      installCommand: "npx skills add acme/toolbox --skill review-bot",
      audited: true,
    })
  );
  await page.route("**/api/skills/registry*", async (route) => {
    if (
      route
        .request()
        .url()
        .includes("/api/skills/registry/acme/toolbox/review-bot")
    ) {
      await route.fallback();
      return;
    }
    await fulfillJson(route, {
      skills: [
        {
          id: "acme/toolbox/review-bot",
          skillId: "review-bot",
          name: "Review Bot",
          source: "acme/toolbox",
          installs: 42,
          description: "Review incoming pull requests",
        },
      ],
    });
  });
  await page.route("**/api/skills**", async (route) => {
    const req = route.request();
    const url = new URL(req.url());

    if (
      url.pathname.startsWith("/api/skills/registry") ||
      url.pathname.startsWith("/api/skills/vercel-docs")
    ) {
      await route.fallback();
      return;
    }

    if (req.method() === "GET") {
      const q = url.searchParams.get("q")?.toLowerCase();
      const filtered = q
        ? skills.filter((skill) => skill.name.toLowerCase().includes(q))
        : skills;
      await fulfillJson(route, filtered);
      return;
    }

    if (req.method() === "POST") {
      const payload = req.postDataJSON() as SaveSkillPayload;
      const saved: SkillRecord = {
        id: `skill-${skills.length + 1}`,
        name: payload.name,
        description: payload.description ?? null,
        scope: payload.scope ?? GLOBAL_SKILL_SCOPE,
        content: payload.content,
        is_public: payload.is_public,
        tags: [],
        usage_count: 0,
        created_at: new Date().toISOString(),
      };
      skills.push(saved);
      await fulfillJson(route, saved);
      return;
    }

    await route.abort();
  });

  await page.goto(scopedPath("primitives?tab=skills"));
  const install = page
    .getByRole("button", { name: "Install", exact: true })
    .first();
  await expect(install).toBeEnabled();
  await install.click();

  await expect(
    page.getByText("Skill installed", { exact: true })
  ).toBeVisible();
  await expect(page.getByRole("tab", { name: "Installed (2)" })).toBeVisible();
  await expect(
    page.getByRole("tab", { name: "Installed (2)" })
  ).toHaveAttribute("aria-selected", "true");
  await expect(
    page.getByText("Review Bot", { exact: true }).first()
  ).toBeVisible();
  await expect(page.getByText("Scope: Global", { exact: true })).toBeVisible();
  await expect(
    page.getByText("Scope: Project-specific", { exact: true })
  ).toBeVisible();
});