Z ZPI 文档 v0.3.8
介绍页

源码

tests/desktop/mention-folders.spec.ts

typescript108 行查看原文
import { mkdir, mkdtemp, realpath, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import type { ElectronApplication } from "@playwright/test";
import { chunk, done, fakeServer, send } from "../fake-server.ts";
import { runCleanup } from "../helpers/cleanup.ts";
import { select } from "../helpers/composer.ts";
import { launchDesktop } from "../helpers/desktop.ts";
import { expect, test } from "../helpers/test.ts";
import { seedHistory } from "../history-fixture.ts";

test("folder mentions share ZCode file search, parent paths, icons, keyboard scrolling and draft restoration", async () => {
  const dir = await mkdtemp(join(tmpdir(), "zpi-mention-folders-"));
  const cwd = join(dir, "workspace");
  const folder = join(cwd, "skills", "know-base-update");
  await mkdir(join(folder, "references"), { recursive: true });
  const folderPath = await realpath(folder);
  await writeFile(join(folder, "SKILL.md"), "Skill contents");
  await Promise.all(
    Array.from({ length: 40 }, (_, i) =>
      writeFile(join(cwd, `update-${i.toString().padStart(2, "0")}.py`), ""),
    ),
  );
  const id = seedHistory(dir, cwd, 1).id;
  const server = await fakeServer((_, response) => {
    send(response, chunk({ content: "Folder received" }));
    done(response);
  });
  let app: ElectronApplication | undefined;
  try {
    app = await launchDesktop({ dir, url: server.url });
    let page = await app.firstWindow();
    await select(page, id);
    let editor = page.getByLabel("消息", { exact: true });
    const panel = page.getByRole("listbox", { name: "引用上下文" });
    for (const prefix of ["帮我看看", "参考:", "看看,", "\n"]) {
      await editor.fill(prefix);
      await editor.press("End");
      await editor.press("@");
      await expect(panel).toBeVisible();
      await editor.press("Escape");
      await expect(panel).toHaveCount(0);
      await expect(editor).toHaveText(`${prefix}@`);
    }
    for (const text of ["name@example.com", "联系邮箱@example.com", "用户@例子.公司"]) {
      await editor.fill(text);
      await expect(panel).toHaveCount(0);
    }
    await editor.fill("帮我看看@know-base-update");
    await expect(panel.getByRole("option", { name: "know-base-update skills/", exact: true })).toBeVisible();
    await editor.press("Tab");
    await expect(editor).toHaveText("帮我看看know-base-update ");
    await expect(editor.locator(".inline-mention.file")).toHaveText("know-base-update");
    await editor.fill("@update");
    await expect(panel.locator(".file-option")).toHaveCount(43);
    await expect(panel.locator("h3")).toHaveCount(0);
    const option = panel.getByRole("option", { name: "know-base-update skills/", exact: true });
    await expect(option.locator("img")).toHaveAttribute("src", /material-icons\/folder\.svg$/);
    await expect(option.locator("span")).toHaveText("skills/");
    const dock = await page.locator(".composer").boundingBox();
    for (let i = 0; i < 40; i++) await editor.press("ArrowDown");
    await expect(option).toHaveAttribute("aria-selected", "true");
    await expect(option).toBeInViewport();
    expect(await panel.locator(".command-options").evaluate((el) => el.scrollTop)).toBeGreaterThan(0);
    expect(await page.locator(".composer").boundingBox()).toEqual(dock);
    for (const colorScheme of ["light", "dark"] as const) {
      await page.emulateMedia({ colorScheme });
      await page.screenshot({ path: `test-results/folder-mentions-${colorScheme}.png` });
    }
    await editor.press("Tab");
    const chip = editor.locator(".inline-mention.file");
    await expect(chip).toHaveText("know-base-update");
    await expect(chip).toHaveAttribute("data-markdown", /know-base-update\/\)$/);
    await expect(chip).toHaveCSS("--mention-image", /folder\.svg/);
    await expect
      .poll(async () => {
        const draft = await page.evaluate((id) => window.zpi.getDraft(id), id);
        return draft.ok ? draft.value.text : "";
      })
      .toBe(`[know-base-update](${folderPath}/) `);
    await app.close();
    app = await launchDesktop({ dir, url: server.url });
    page = await app.firstWindow();
    editor = page.getByLabel("消息", { exact: true });
    await expect(editor.locator(".inline-mention.file")).toHaveText("know-base-update");
    await expect(page.locator(".draft-warning")).toHaveCount(0);
    await editor.press("Enter");
    await expect.poll(() => server.requests.length).toBe(1);
    await expect(page.getByTestId("run").last()).toHaveAttribute("data-status", "completed");
    expect(JSON.stringify(server.requests[0])).toContain(`${folderPath}/`);
    await expect(page.locator(".user-message-text .inline-mention.file").last()).toHaveCSS(
      "--mention-image",
      /folder\.svg/,
    );
    await editor.fill("@kbupd");
    await expect(page.getByRole("option", { name: "know-base-update skills/", exact: true })).toBeVisible();
    await editor.press("Escape");
    await expect(page.getByRole("listbox", { name: "引用上下文" })).toHaveCount(0);
    await expect(editor).toHaveText("@kbupd");
  } finally {
    await runCleanup([
      () => rm(dir, { recursive: true, force: true }),
      () => server.close(),
      () => app?.close(),
    ]);
  }
});