Ctrl K
ComunidadGuías…

e2e/file-previews.spec.ts

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

Archivo original ↗Preguntar a KiBot
import { openFileDetails, openProject } from "./workspace-controls";
import { expect, test } from "@playwright/test";
import { readFile } from "node:fs/promises";

test("project files preview safe content and preserve ZIP, SVG and JSON originals", async ({ page }) => {
  const svg = '<svg xmlns="http://www.w3.org/2000/svg" onload="window.previewUnsafe=true"><script>window.previewUnsafe=true</script><image href="https://example.org/svg-preview-tracker"/></svg>';
  const evidence = JSON.stringify({ note: "<script>window.previewUnsafe=true</script>", passed: true });
  const requests: string[] = [];
  await page.route("https://example.org/svg-preview-tracker", (route) => { requests.push(route.request().url()); return route.abort(); });
  await page.goto("/");
  await page.getByLabel("Workspace password").fill("demo-password-please-change");
  await page.getByRole("button", { name: "Sign in", exact: true }).click();
  await openProject(page, "Synthetic H2D desk lamp");
  await page.getByRole("tab", { name: /^Files/u }).click();
  const files = [
    { name: "preview-instructions.md", mimeType: "text/markdown", buffer: Buffer.from("# Assembly preview\n\n**Read first**\n\n<script>window.previewUnsafe = true</script>\n\n![remote](https://example.org/tracker)") },
    { name: "preview-drawing.png", mimeType: "image/png", buffer: Buffer.from("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+j1ioAAAAASUVORK5CYII=", "base64") },
    { name: "preview-part.stl", mimeType: "model/stl", buffer: Buffer.from("solid part\nfacet normal 0 0 1\nouter loop\nvertex 0 0 0\nvertex 1 0 0\nvertex 0 1 0\nendloop\nendfacet\nendsolid part") },
    { name: "preview-source.step", mimeType: "model/step", buffer: Buffer.from("Synthetic download-only source") },
    { name: "preview-source.zip", mimeType: "application/zip", buffer: Buffer.from("504b0506000000000000000000000000000000000000", "hex") },
    { name: "preview-drawing.svg", mimeType: "image/svg+xml", buffer: Buffer.from(svg) },
    { name: "preview-evidence.json", mimeType: "application/json", buffer: Buffer.from(evidence) },
  ];
  await page.getByLabel("Choose files to upload").setInputFiles(files);
  await page.getByRole("button", { name: "Add 7 files", exact: true }).click();
  await expect(page.getByText("7 of 7 files uploaded", { exact: true })).toBeVisible();
  const markdownButton = page.getByRole("button", { name: "Preview preview-instructions.md", exact: true });
  await markdownButton.click();
  let dialog = page.getByRole("dialog", { name: "preview-instructions.md", exact: true });
  await expect(dialog.getByRole("heading", { name: "Assembly preview" })).toBeVisible();
  await expect(dialog.locator("strong")).toHaveText("Read first");
  await expect(dialog.locator("img, script")).toHaveCount(0);
  expect(await page.locator('button[aria-label="Preview preview-instructions.md"]').evaluate((element) => Boolean(element.closest('[aria-hidden="true"]')))).toBe(true);
  await page.keyboard.press("Escape"); await expect(dialog).toHaveCount(0); await expect(markdownButton).toBeFocused();
  await page.setViewportSize({ width: 390, height: 844 });
  await page.getByRole("button", { name: "Preview preview-drawing.png", exact: true }).click();
  dialog = page.getByRole("dialog", { name: "preview-drawing.png", exact: true });
  const image = dialog.getByRole("img"); await expect(image).toBeVisible();
  await expect.poll(() => image.evaluate((element) => (element as HTMLImageElement).naturalWidth)).toBe(1);
  const bounds = await dialog.boundingBox(); expect(bounds!.x + bounds!.width).toBeLessThanOrEqual(390);
  await dialog.getByRole("button", { name: "Close preview" }).click();
  await page.setViewportSize({ width: 1280, height: 900 });
  await page.getByRole("button", { name: "Preview preview-part.stl", exact: true }).click();
  dialog = page.getByRole("dialog", { name: "preview-part.stl", exact: true });
  await expect(dialog.getByRole("img", { name: "STL model preview" })).toBeVisible();
  await dialog.locator("canvas").evaluate(canvas => canvas.dispatchEvent(new Event("webglcontextlost", { cancelable: true })));
  await expect(dialog.getByRole("alert")).toContainText("graphics connection was lost");
  await dialog.getByRole("button", { name: "Retry STL preview", exact: true }).click();
  await expect(dialog.getByRole("img", { name: "STL model preview" })).toBeVisible();
  await dialog.getByRole("button", { name: "Reset view" }).click();
  await dialog.getByRole("button", { name: "Close preview" }).click();
  await expect(page.getByRole("button", { name: "Preview preview-source.step", exact: true })).toHaveCount(0);
  await expect(page.getByRole("button", { name: "Download preview-source.step", exact: true })).toBeVisible();
  await expect(page.getByRole("button", { name: "Preview preview-source.zip", exact: true })).toHaveCount(0);
  await expect(page.getByRole("button", { name: "Download preview-source.zip", exact: true })).toBeVisible();
  for (const [name, source] of [["preview-drawing.svg", svg], ["preview-evidence.json", evidence]] as const) {
    const responsePromise = page.waitForResponse(response => /\/artifacts\/[^/]+\/download$/u.test(new URL(response.url()).pathname));
    await page.getByRole("button", { name: `Preview ${name}`, exact: true }).click();
    const response = await responsePromise;
    dialog = page.getByRole("dialog", { name, exact: true });
    await expect(dialog.locator("pre")).toHaveText(source);
    await expect(dialog.locator("svg, img, script, iframe, object, embed")).toHaveCount(0);
    await dialog.getByRole("button", { name: "Close preview" }).click();
    await expect(dialog).toHaveCount(0);
    const details = await openFileDetails(page, name);
    await expect(details.getByRole("button", { name: "Download file", exact: true })).toBeVisible();
    // Ordinary authenticated navigation must download too, without the UI's
    // fetch/blob path or a download attribute that could hide response-policy bugs.
    await page.evaluate(url => {
      const link = document.createElement("a");
      link.id = "direct-artifact-download";
      link.href = url;
      link.textContent = "Direct artifact download";
      Object.assign(link.style, { position: "fixed", top: "0", left: "400px", zIndex: "2147483647" });
      document.body.append(link);
    }, response.url());
    const [download] = await Promise.all([
      page.waitForEvent("download"),
      page.getByRole("link", { name: "Direct artifact download", exact: true }).click(),
    ]);
    expect(download.suggestedFilename()).toBe(name);
    expect(await readFile((await download.path())!)).toEqual(Buffer.from(source));
    await page.locator("#direct-artifact-download").evaluate(element => element.remove());
  }
  expect(requests).toEqual([]);
  expect(await page.evaluate(() => Reflect.get(window, "previewUnsafe"))).toBeUndefined();
  await page.route("**/artifacts/*/download", (route) => route.fulfill({ status: 200, body: "corrupted" }));
  await markdownButton.click();
  await expect(page.getByRole("dialog").getByRole("alert")).toContainText("integrity check");
});