mcpField
V
visual-regression-testing

visual-regression-testing

github.com/editframeテスト・品質1970 回インストール2 週間前に更新
リポジトリ

visual-regression-testing について

ネイティブ Canvas 描画とシリアライズされた foreignObject 描画のピクセル一致性を調べるテストスキルです。開発者が CSS の回帰テストを作成し、プレビューの差異を調査できます。

主な機能

  1. 01Canvas 間の直接比較
  2. 02ベースライン PNG スナップショット検査
  3. 03ピクセル差分しきい値の設定
  4. 04最小限の CSS 再現テスト
  5. 05ネイティブ API の利用可否確認

活用シーン

  1. 01CSS 機能の描画一致性の確認
  2. 02プレビューサムネイルの差異調査
  3. 03シリアライザー変更の検証

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/editframe/skills --skill visual-regression-testing

インストール後、Claude Code で/visual-regression-testingを入力して読み込まれたか確認します。

詳細

ビジュアルリグレッションテスト

2 つのレンダリングパスで、同一のピクセルが生成される必要があります。ネイティブキャンバスパス(drawElementImage を介した renderToImageNative)は、ライブ DOM を Blink で直接レンダリングするため、基準となる結果です。foreignObject パス(captureTimelineToDataUri)は、DOM を SVG の <foreignObject> 内に XHTML としてシリアライズします。両者に差がある場合は、シリアライザーのバグです。

ユーティリティ

elements/packages/elements/test/visualRegressionUtils.ts でテスト API を提供しています。主な関数:

// Compare two canvases directly — returns diffPercentage, no baseline file needed
compareTwoCanvases(canvas1, canvas2, testName, comparisonName, options)
expectCanvasesToMatch(canvas1, canvas2, testName, comparisonName, options)

// Compare a canvas against a stored baseline PNG
assertCanvasSnapshot(canvas, testName, snapshotName, options)
expectCanvasToMatchSnapshot(source, testName, snapshotName, options)

options.acceptableDiffPercentage(デフォルトは 1.0)で、合否の判定基準を設定します。厳密な一致を確認する場合は、0 から 0.5 を指定してください。

標準的な比較パターン

import { captureTimelineToDataUri } from "./rendering/serializeTimelineDirect.js";
import { loadImageFromDataUri } from "./rendering/loadImage.js";
import { renderToImageNative } from "./rendering/renderToImageNative.js";
import { isNativeCanvasApiAvailable } from "./previewSettings.js";
import { expectCanvasesToMatch } from "../../test/visualRegressionUtils.js";

async function captureForComparison(tg: EFTimegroup, W: number, H: number) {
  // foreignObject path
  const dataUri = await captureTimelineToDataUri(tg, W, H, { canvasScale: 1, timeMs: 0 });
  const img = await loadImageFromDataUri(dataUri);
  const fc = document.createElement("canvas");
  fc.width = W; fc.height = H;
  fc.getContext("2d")!.drawImage(img, 0, 0);

  // native path (ground truth — Blink renders the live DOM)
  const nc = await renderToImageNative(tg, W, H, { skipDprScaling: true });

  return { foreignCanvas: fc, nativeCanvas: nc };
}

ネイティブパスのテストには、必ず isNativeCanvasApiAvailable() によるガードを設けてください。WICG の drawElementImage API は Chromium でのみ利用できます。

最小再現テストの作成

最小再現テストでは、単一の CSS プロパティを切り分けます。テストは修正前に失敗し、修正後に成功する必要があります。

it("text-shadow from inline style", async () => {
  if (!isNativeCanvasApiAvailable()) return;
  const tg = document.createElement("ef-timegroup") as EFTimegroup;
  tg.style.cssText = "width:400px;height:200px;background:#000;position:relative;";
  const el = document.createElement("div");
  el.style.cssText = "position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);"
    + "font-size:60px;font-weight:900;color:white;text-shadow:0 0 40px red;";
  el.textContent = "GLOW";
  tg.appendChild(el);
  document.body.appendChild(tg);
  await tg.updateComplete;

  const { foreignCanvas, nativeCanvas } = await captureForComparison(tg, 400, 200);
  await expectCanvasesToMatch(foreignCanvas, nativeCanvas, "canvasDomParity", "text-shadow-inline", {
    acceptableDiffPercentage: 0.5,
  });
  tg.remove();
});

スナップショットファイル

差分 PNG は elements/test-assets/test/__snapshots__/<testName>/ に書き込まれます。ファイルを開いて、どのピクセルに差があるかを目視で確認してください。

シリアライザーのプロパティ

foreignObject シリアライザーは、elements/packages/elements/src/preview/rendering/serializeTimelineDirect.ts の SERIALIZED_STYLE_PROPERTIES に定義された計算済みスタイルを取得します。ここにプロパティがないと、アニメーションを animation:none で固定したときに失われます。CSS 機能の一致に差が生じた場合は、まずこのリストを確認してください。

このスキルを使う場面

  • CSS 機能の差を確認する新しい一致テストを作成するとき
  • プレビューのサムネイルが DOM の表示と異なるという報告を調査するとき
  • serializeTimelineDirect.ts の変更後に、新たなリグレッションがないことを確認するとき

コメント