DalaDev.ScreenBaseline (dala_dev v0.4.0)

Copy Markdown View Source

Screenshot baselines for cheap visual regression between deploys.

Save a named baseline once, then after code changes re-capture and compare. A match tells you the screen is byte-identical to before; a difference saves the new capture next to the baseline for eyeballing.

Baselines are per-device (a Pixel and an iPhone never agree) and live in .dala/screenshots/<device-id>/ so they can be committed or gitignored per project taste.

Comparison is exact-bytes. Screenshots of a static screen on the same device/OS are deterministic in practice; when they aren't (clock in the status bar, animations), treat this as a smoke signal, not a pixel-perfect assertion tool.

Summary

Functions

Path of the baseline file for name. Public for testing.

Captures device_ref fresh and compares against baseline name.

Pure comparison of two captures. Public test seam for the diff logic.

Directory holding baselines for device_id. Public for testing.

Path where a differing capture gets written for comparison.

Captures device_ref and stores it as baseline name. Returns {:ok, path}.

Types

compare_result()

@type compare_result() ::
  {:ok, :match}
  | {:ok,
     {:changed,
      %{
        baseline: String.t(),
        current: String.t(),
        size_a: pos_integer(),
        size_b: pos_integer()
      }}}
  | {:error, term()}

Functions

baseline_path(device_id, name)

@spec baseline_path(String.t(), String.t()) :: String.t()

Path of the baseline file for name. Public for testing.

compare(device_ref, name, opts \\ [])

Captures device_ref fresh and compares against baseline name.

Returns:

  • {:ok, :match} — bytes identical
  • {:ok, {:changed, details}} — differs; fresh capture saved at diff_path/2, details include both paths and sizes
  • {:error, :no_baseline} — nothing saved under that name yet
  • {:error, reason} — capture failure

Test seam: opts[:capture] overrides the capture call (defaults to ScreenCapture.capture/2; receives (device_ref, []), returns {:ok, bytes} / {:error, reason}).

compare_bytes(old_bytes, fresh)

@spec compare_bytes(binary(), binary()) ::
  :match | {:changed, pos_integer(), pos_integer()}

Pure comparison of two captures. Public test seam for the diff logic.

device_dir(device_id)

@spec device_dir(String.t()) :: String.t()

Directory holding baselines for device_id. Public for testing.

diff_path(device_id, name)

@spec diff_path(String.t(), String.t()) :: String.t()

Path where a differing capture gets written for comparison.

save(device_ref, name, opts \\ [])

@spec save(DalaDev.ScreenCapture.device_ref(), String.t(), keyword()) ::
  {:ok, String.t()} | {:error, term()}

Captures device_ref and stores it as baseline name. Returns {:ok, path}.

Test seam: opts[:capture] overrides the capture call (defaults to ScreenCapture.capture/2; receives (device_ref, capture_opts)).