Ctrl K
ComunidadGuías…

tests/e2e/flows-pane-keyboard-filters.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,
  primaryModifier,
} from "./helpers/flows-pane-keyboard-fixtures";
import type { FlowNode } from "../../lib/types";

test("workflow viewing filters stay outside the canvas and trigger scope binds account plus repository", async ({
  page,
}) => {
  let publishCount = 0;
  const { getFlow } = await stubFlowsPage(page, {
    flowStatus: "inactive",
    onFlowPublish: () => {
      publishCount += 1;
    },
    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" },
        ],
      },
      {
        id: "inst-2",
        installation_id: 202,
        account_login: "alex",
        account_type: "User",
        repositories: [{ id: "repo-3", full_name: "alex/priority-project" }],
      },
    ],
  });
  const broadFlow = getFlow();
  const scopedFlow = (
    id: string,
    name: string,
    installationId: number,
    repo: string
  ) => ({
    ...structuredClone(broadFlow),
    id,
    name,
    installation_id: installationId,
    draft_graph: {
      ...structuredClone(broadFlow.draft_graph),
      nodes: broadFlow.draft_graph.nodes.map((node) =>
        node.type === "start"
          ? {
              ...structuredClone(node),
              data: {
                ...structuredClone(node.data),
                filter: {
                  scope: "all",
                  installationIds: [installationId],
                  repos: [repo],
                },
              },
            }
          : structuredClone(node)
      ),
    },
  });
  await page.unroute("**/api/flows");
  await page.route("**/api/flows", (route) =>
    fulfillJson(route, [
      broadFlow,
      scopedFlow(
        "flow-blackbox",
        "Blackbox strict checks",
        101,
        "webrenew/blackbox"
      ),
      scopedFlow(
        "flow-mogplex",
        "Mogplex strict checks",
        101,
        "webrenew/mogplex"
      ),
      scopedFlow(
        "flow-personal",
        "Personal checks",
        202,
        "alex/priority-project"
      ),
    ])
  );

  await page.setViewportSize({ width: 1600, height: 900 });
  await page.goto("/alex/workflows");
  await page.waitForLoadState("networkidle");

  const filterBar = page.getByTestId("flow-browser-filters");
  const canvas = page.locator(".react-flow");
  await expect(filterBar).toBeVisible();
  await expect(
    page.getByLabel("Filter workflows by GitHub account")
  ).toHaveAttribute("data-value", "all");
  await expect(page.getByLabel("New workflow installation")).toHaveCount(0);
  const filterBox = await filterBar.boundingBox();
  const canvasBox = await canvas.boundingBox();
  expect(filterBox).not.toBeNull();
  expect(canvasBox).not.toBeNull();
  expect(filterBox!.y + filterBox!.height).toBeLessThanOrEqual(canvasBox!.y);

  await selectAppOption(page.getByTestId("flow-browser-account"), "101");
  await expect(filterBar).toContainText("3 of 4 workflows");
  const repositoryFilter = page.getByTestId("flow-browser-repository");
  await repositoryFilter.click();
  await page
    .getByTestId("flow-browser-repository-option-webrenew/blackbox")
    .click();
  await repositoryFilter.click();
  await expect(filterBar).toContainText("2 of 4 workflows");
  await repositoryFilter.click();
  await page
    .getByTestId("flow-browser-repository-option-webrenew/mogplex")
    .click();
  await repositoryFilter.click();
  await expect(repositoryFilter).toContainText("2 repositories");
  await expect(filterBar).toContainText("3 of 4 workflows");
  await page.getByLabel("Select workflow").click();
  await expect(page.getByRole("option")).toHaveCount(3);
  await page.keyboard.press("Escape");

  const startNode = page
    .locator(".react-flow__node")
    .filter({ hasText: "PR opened" });
  await startNode.click();

  // A GitHub trigger without installationIds runs for every connected
  // account, so the editor must say so instead of naming flows.installation_id.
  const account = page.getByTestId("flow-trigger-account");
  await expect(account).toHaveAttribute("data-value", "all");
  await expect(account).toContainText("All accounts");
  const repositoryScope = page.getByTestId("flow-trigger-repository-scope");
  await expect(repositoryScope).toContainText("All repositories");
  await repositoryScope.click();
  await page
    .getByTestId("flow-trigger-repository-option-webrenew/blackbox")
    .click();
  await repositoryScope.click();
  await expect(startNode).toContainText("All accounts · webrenew/blackbox");

  await account.click();
  await page.getByTestId("flow-trigger-account-option-202").click();
  await account.click();
  await expect(account).toHaveAttribute("data-value", "202");
  await expect(repositoryScope).toContainText("All repositories");
  await repositoryScope.click();
  await page
    .getByTestId("flow-trigger-repository-option-alex/priority-project")
    .click();
  await repositoryScope.click();
  await expect(startNode).toContainText("alex · alex/priority-project");
  await page.keyboard.press(`${primaryModifier}+S`);

  await expect.poll(() => getFlow().installation_id).toBe(101);
  await expect
    .poll(() => {
      const start = (getFlow().draft_graph.nodes as FlowNode[]).find(
        (node) => node.type === "start"
      );
      return start?.data.filter;
    })
    .toMatchObject({
      scope: "all",
      installationIds: [202],
      repos: ["alex/priority-project"],
    });
  const publishButton = page.getByTestId("flow-publish-button");
  await expect(publishButton).toHaveText("Publish & activate");
  await publishButton.click();
  await expect.poll(() => publishCount).toBe(1);
  await expect.poll(() => getFlow().installation_id).toBe(202);
});