dillonkearns/elm-snapshot/1.1.1

Snapshot.Scrubber

Scrubbers clean non-deterministic content from snapshot output.

"Fundamentally, a scrubber is a function that takes a string and returns a string." — ApprovalTests documentation

Scrubbers are applied AFTER the printer converts your value to a string. They replace variable content (timestamps, GUIDs, etc.) with stable placeholders.

Since Scrubber is just a type alias for String -> String, any function with that signature works as a scrubber:

myScrubber : Scrubber
myScrubber =
    String.replace "secret" "[REDACTED]"

Definition

type alias Scrubber =
String -> String

A scrubber transforms a string, typically replacing non-deterministic content with stable placeholders.

Built-in Scrubbers

timestamp : Scrubber

Replace ISO 8601 timestamps with [TIMESTAMP].

Matches patterns like:

  • 2024-01-15T10:30:00Z
  • 2024-01-15T10:30:00.123Z
  • 2024-01-15T10:30:00+05:00
  • 2024-01-15 10:30:00
guid : Scrubber

Replace GUIDs/UUIDs with stable placeholders like [GUID-1], [GUID-2].

Preserves referential equality: the same GUID appearing multiple times in the output will get the same placeholder number.

Matches standard UUID format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

date : String -> Scrubber

Replace dates matching a format pattern with [DATE-1], [DATE-2], etc.

Provide a format string using these tokens:

  • YYYY - 4-digit year
  • MM - 2-digit month (01-12)
  • DD - 2-digit day (01-31)
  • hh - 2-digit hour (00-23)
  • mm - 2-digit minute (00-59)
  • ss - 2-digit second (00-59)

Examples:

-- Match "2024-01-15"
Scrubber.date "YYYY-MM-DD"


-- Match "01/15/2024"
Scrubber.date "MM/DD/YYYY"


-- Match "15-Jan-2024"
Scrubber.date "DD-Mon-YYYY"


-- Match "2024-01-15 10:30:00"
Scrubber.date "YYYY-MM-DD hh:mm:ss"

Like guid, the same date appearing multiple times gets the same number.

Custom Scrubbers

regex : String -> String -> String -> String

Replace all matches of a regex pattern with a fixed string.

-- Replace version numbers
Scrubber.regex "v\\d+\\.\\d+\\.\\d+" "[VERSION]"


-- Replace port numbers
Scrubber.regex ":\\d{4,5}" ":[PORT]"

Note: Uses Elm's Regex module. Invalid patterns are silently ignored.

numbered : String -> String -> String -> String

Replace regex matches with numbered placeholders like [LABEL-1], [LABEL-2].

Preserves referential equality: the same value appearing multiple times gets the same placeholder number.

-- User IDs: "user-123" and "user-456" → "[USER-1]" and "[USER-2]"
Scrubber.numbered "user-\\d+" "USER"


-- Request IDs that appear multiple times get consistent numbers
Scrubber.numbered "req-[a-z0-9]+" "REQUEST"

The label is wrapped in brackets with a number: [LABEL-1], [LABEL-2], etc.

lines : (String -> Bool) -> String -> String

Remove or keep lines based on a predicate.

-- Remove all lines containing "DEBUG"
Scrubber.lines (not << String.contains "DEBUG:")


-- Keep only lines starting with "ERROR"
Scrubber.lines (String.startsWith "ERROR")

The predicate returns True for lines to keep, False for lines to remove.

Composition

all : List Scrubber -> String -> String

Compose multiple scrubbers into one. Applied first to last.

Scrubber.all
    [ Scrubber.timestamp
    , Scrubber.guid
    , Scrubber.regex "v\\d+\\.\\d+\\.\\d+" "[VERSION]"
    ]