Ctrl K
ComunidadGuías…

tests/e2e/flows-pane-keyboard-templates.spec.ts

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

Archivo original ↗Preguntar a KiBot
import { expect, test } from "@playwright/test";
import { selectAppOption } from "./helpers/app-select";
import {
  stubFlowsPage,
  fulfillJson,
} from "./helpers/flows-pane-keyboard-fixtures";

test("new workflow picker creates a selected starter template", async ({
  page,
}) => {
  const createPayloads: Record<string, unknown>[] = [];
  await stubFlowsPage(page, {
    onFlowCreate: (payload) => {
      createPayloads.push(payload);
    },
  });

  await page.goto("/alex/workflows");
  await page.waitForLoadState("networkidle");

  await page.getByRole("button", { name: "New workflow" }).click();
  const picker = page.getByTestId("flow-template-picker");
  await expect(picker).toBeVisible();
  await expect(picker).toContainText("Nothing runs until you publish it.");
  await expect(picker.getByRole("button")).toHaveCount(5);

  await page.getByTestId("flow-template-dependabot-autopilot").click();

  await expect
    .poll(() => createPayloads[0]?.template_id)
    .toBe("dependabot-autopilot");
  expect(createPayloads[0]?.installation_id).toBe(101);
  await expect(picker).toBeHidden();
  await expect(
    page.getByText("Started from Dependabot autopilot.", { exact: true })
  ).toBeVisible();
});

test("personal workflow templates bind a target repository and can be saved from the picker", async ({
  page,
}) => {
  const flowCreatePayloads: Record<string, unknown>[] = [];
  const templateCreatePayloads: Record<string, unknown>[] = [];
  await stubFlowsPage(page, {
    installations: [
      {
        id: "inst-1",
        installation_id: 101,
        account_login: "webrenew",
        account_type: "Organization",
        repositories: [
          { id: "repo-1", full_name: "webrenew/blackbox" },
          { id: "repo-2", full_name: "webrenew/mogplex" },
        ],
      },
    ],
    personalTemplates: [
      {
        id: "template-strict-review",
        name: "Strict PR review",
        description: "Extra checks for critical repositories.",
        trigger_event: "webhook",
        reconnect: ["webhook"],
        requires_repository: true,
      },
    ],
    onFlowCreate: (payload) => flowCreatePayloads.push(payload),
    onTemplateCreate: (payload) => templateCreatePayloads.push(payload),
  });

  await page.goto("/alex/workflows");
  await page.waitForLoadState("networkidle");

  await page.getByRole("button", { name: "New workflow" }).click();
  const personalTemplate = page.getByTestId(
    "flow-personal-template-template-strict-review"
  );
  await expect(personalTemplate).toBeDisabled();
  await expect(personalTemplate).toContainText("Reconnect webhook");

  await selectAppOption(
    page.getByRole("combobox", { name: "New workflow repository" }),
    "webrenew/blackbox"
  );
  await expect(personalTemplate).toBeEnabled();
  await personalTemplate.click();

  await expect
    .poll(() => flowCreatePayloads[0]?.personal_template_id)
    .toBe("template-strict-review");
  expect(flowCreatePayloads[0]?.repo_full_name).toBe("webrenew/blackbox");

  await page.getByRole("button", { name: "New workflow" }).click();
  await page.getByTestId("flow-save-personal-template").click();
  const dialog = page.getByTestId("flow-save-template-dialog");
  await expect(dialog).toBeVisible();
  await dialog.getByLabel("Template name").fill("Critical repo review");
  await page.getByTestId("flow-save-template-submit").click();

  await expect
    .poll(() => templateCreatePayloads[0]?.name)
    .toBe("Critical repo review");
  expect(templateCreatePayloads[0]?.flow_id).toBe("flow-1");

  await page
    .getByRole("button", { name: "Delete Critical repo review template" })
    .click();
  await page.getByRole("button", { name: "Delete template" }).click();
  await expect(
    page.getByRole("button", { name: "Delete Critical repo review template" })
  ).toHaveCount(0);
  const deletionToast = page
    .locator('[data-variant="info"]')
    .filter({ hasText: "Template deleted" });
  await expect(deletionToast).toBeVisible();
  await expect(deletionToast).toContainText(
    '"Critical repo review" was permanently deleted.'
  );
});

test("team workflow templates are separated, reused, and saved in active team scope", async ({
  page,
}) => {
  const teamId = "11111111-2222-4333-8444-555555555555";
  const flowCreateRequests: Array<{
    payload: Record<string, unknown>;
    teamId: string | undefined;
  }> = [];
  const templateCreates: Array<{
    payload: Record<string, unknown>;
    scope: "personal" | "team";
  }> = [];

  await stubFlowsPage(page, {
    teamId,
    personalTemplates: [
      {
        id: "template-personal",
        name: "My review",
        description: "Personal baseline",
        trigger_event: "pr_opened",
        reconnect: [],
        requires_repository: false,
      },
    ],
    teamTemplates: [
      {
        id: "template-team",
        name: "Team release gate",
        description: "Shared release checks",
        trigger_event: "pr_opened",
        reconnect: ["agent"],
        requires_repository: false,
      },
    ],
    onFlowCreate: (payload) => {
      flowCreateRequests.push({ payload, teamId: undefined });
    },
    onTemplateCreate: (payload, scope) => {
      templateCreates.push({ payload, scope });
    },
  });
  await page.route("**/api/flows", async (route) => {
    if (route.request().method() !== "POST") {
      await route.fallback();
      return;
    }
    flowCreateRequests.push({
      payload: route.request().postDataJSON() as Record<string, unknown>,
      teamId: route.request().headers()["x-mogplex-team-id"],
    });
    await fulfillJson(
      route,
      {
        id: "flow-created",
        name: "Team release gate",
      },
      201
    );
  });

  await page.goto("/acme/workflows");
  await page.waitForLoadState("networkidle");

  await page.getByRole("button", { name: "New workflow" }).click();
  const picker = page.getByTestId("flow-template-picker");
  await expect(picker).toContainText("Team templates");
  await expect(picker).toContainText("Your templates");
  const teamTemplate = page.getByTestId("flow-team-template-template-team");
  await expect(teamTemplate).toContainText("Reconnect agent");
  await teamTemplate.click();

  await expect
    .poll(() => flowCreateRequests.at(-1)?.payload.team_template_id)
    .toBe("template-team");
  expect(flowCreateRequests.at(-1)?.teamId).toBe(teamId);

  await page.getByRole("button", { name: "New workflow" }).click();
  await page.getByTestId("flow-save-personal-template").click();
  const dialog = page.getByTestId("flow-save-template-dialog");
  await expect(dialog).toBeVisible();
  await expect(page.getByTestId("flow-template-scope-team")).toBeChecked();
  await dialog.getByLabel("Template name").fill("Shared critical review");
  await page.getByTestId("flow-save-template-submit").click();

  await expect.poll(() => templateCreates.at(-1)?.scope).toBe("team");
  expect(templateCreates.at(-1)?.payload.name).toBe("Shared critical review");
});