Ctrl K
ComunidadGuías…

tests/e2e/flows-pane-theme-light.spec.ts

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

Archivo original ↗Preguntar a KiBot
import { expect, test } from "@playwright/test";
import {
  setupWorkflowsPage,
  normalizeCssColors,
} from "./helpers/flows-pane-theme-fixtures";

test("workflows builder and portalled surfaces follow the light app theme", async ({
  page,
}, testInfo) => {
  await setupWorkflowsPage(page, "light");

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

  // Prove the premise: the surrounding app really is in its light theme.
  await expect(page.locator("html")).not.toHaveClass(/dark/);

  // React Flow's own color mode has to track the app theme, not the OS.
  await expect(page.locator(".react-flow.light")).toBeVisible();
  await expect(page.locator(".react-flow.dark")).toHaveCount(0);

  const paneStyles = await page.locator(".flows-pane").evaluate((node) => {
    const styles = getComputedStyle(node);
    return {
      themeBackground: styles.getPropertyValue("--background").trim(),
      backgroundColor: styles.backgroundColor,
      color: styles.color,
      colorScheme: styles.colorScheme,
    };
  });
  const [
    expectedLightBackground,
    actualLightBackground,
    expectedLightForeground,
    actualLightForeground,
    expectedLightCard,
  ] = await normalizeCssColors(page, [
    "#f6f5f0",
    paneStyles.backgroundColor,
    "#10110d",
    paneStyles.color,
    "#fcfbf7",
  ]);
  expect(paneStyles.themeBackground).not.toBe("");
  expect(actualLightBackground).toBe(expectedLightBackground);
  expect(actualLightForeground).toBe(expectedLightForeground);
  expect(paneStyles.colorScheme).toBe("light");

  const canvasThemeColors = await page
    .locator(".flows-canvas")
    .evaluate((node) => {
      const styles = getComputedStyle(node);
      return {
        canvasBackground: styles
          .getPropertyValue("--xy-background-color")
          .trim(),
        themeBackground: styles.getPropertyValue("--background").trim(),
      };
    });
  expect(canvasThemeColors.canvasBackground).toBe(
    canvasThemeColors.themeBackground
  );
  const canvasBg = await page
    .locator(".react-flow__background")
    .evaluate((node) => getComputedStyle(node).backgroundColor);
  expect((await normalizeCssColors(page, [canvasBg]))[0]).toBe(
    expectedLightBackground
  );

  // Node cards must sit on a light surface too — they are the one place that
  // still paints its own background rather than inheriting the canvas.
  const nodeCardBackgrounds = await page
    .locator(".flows-node-card")
    .evaluateAll((nodes) =>
      nodes.map((node) => getComputedStyle(node).backgroundColor)
    );
  expect(nodeCardBackgrounds.length).toBeGreaterThan(0);
  const normalizedLightNodeCards = await normalizeCssColors(
    page,
    nodeCardBackgrounds
  );
  expect(
    normalizedLightNodeCards.every(
      (background) => background === expectedLightCard
    )
  ).toBe(true);
  await page.screenshot({
    path: testInfo.outputPath("flows-pane-light-theme.png"),
    fullPage: true,
  });

  // The context menu portals to document.body, outside `.flows-pane`, and
  // relies on `.flows-theme` to pick up the same palette.
  await page
    .locator(".react-flow__pane")
    .click({ button: "right", position: { x: 200, y: 60 } });
  const contextMenu = page.getByTestId("flow-context-menu");
  await expect(contextMenu).toBeVisible();
  const menuStyles = await contextMenu.evaluate((node) => {
    const styles = getComputedStyle(node);
    return {
      insidePane: Boolean(node.closest(".flows-pane")),
      hasFlowsTheme: node.classList.contains("flows-theme"),
      themeBackground: styles.getPropertyValue("--background").trim(),
      backgroundColor: styles.backgroundColor,
      color: styles.color,
    };
  });
  expect(menuStyles.insidePane).toBe(false);
  expect(menuStyles.hasFlowsTheme).toBe(true);
  expect(menuStyles.themeBackground).not.toBe("");
  expect(menuStyles.backgroundColor).not.toBe("rgba(0, 0, 0, 0)");
  expect((await normalizeCssColors(page, [menuStyles.color]))[0]).toBe(
    expectedLightForeground
  );
  await page.keyboard.press("Escape");
  await expect(contextMenu).not.toBeVisible();

  // The run-details dialog also portals to document.body and must carry the
  // light palette via `.flows-theme`.
  await page.getByTestId("flows-runs-tab").click();
  await page.getByTestId("flow-run-card-run-1").click();
  const runDialog = page.locator('[data-slot="dialog-content"]');
  await expect(runDialog).toBeVisible();
  await expect(runDialog.getByText("Overview")).toBeVisible();
  const dialogStyles = await runDialog.evaluate((node) => {
    const styles = getComputedStyle(node);
    return {
      insidePane: Boolean(node.closest(".flows-pane")),
      hasFlowsTheme: node.classList.contains("flows-theme"),
      backgroundColor: styles.backgroundColor,
      color: styles.color,
    };
  });
  expect(dialogStyles.insidePane).toBe(false);
  expect(dialogStyles.hasFlowsTheme).toBe(true);
  const [dialogBackground, dialogForeground] = await normalizeCssColors(page, [
    dialogStyles.backgroundColor,
    dialogStyles.color,
  ]);
  expect(dialogBackground).toBe(expectedLightBackground);
  expect(dialogForeground).toBe(expectedLightForeground);
});