Snapshot testing framework for Elm.
module Snapshots exposing (run)
import Json.Encode
import Pages.Script exposing (Script)
import Snapshot
run : Script
run =
Snapshot.run "Snapshots"
[ Snapshot.test "greeting" <|
\() -> "Hello, " ++ "World" ++ "!"
, Snapshot.json "user" <|
\() ->
Json.Encode.object
[ ( "name", Json.Encode.string "Alice" )
, ( "age", Json.Encode.int 30 )
]
]Run with elm-pages run src/Snapshots.elm --approve=prompt and press Enter to approve each snapshot. Commit the .approved files to git.
Run a list of snapshot tests as an elm-pages Script.
-- In your Snapshots.elm script:
run : Script
run =
Snapshot.run "Snapshots"
[ Snapshot.test "greeting" <| \() -> greet "World"
, Snapshot.json "config" <| \() -> encodeConfig config
]The first argument is the script name (typically matching the module name).
This organizes snapshots into snapshots/<ScriptName>/ directories,
allowing multiple snapshot scripts in the same project.
Supports CLI options:
--approve=all - Approve all new/changed snapshots--approve=prompt - Interactive per-snapshot approval--approve-only "test name" - Approve a specific test--ci - Compact output for CI environments--list - List all test names without running--prune - Remove obsolete snapshot files--reporter <tool> - Open diff tool for failures (code, opendiff, meld, ksdiff, kdiff3, diff, or any command)Create a snapshot test that compares string output.
Snapshot.test "greeting" <|
\() ->
greet "World"This is the most common form - use when your function already returns a String.
Create a snapshot test for JSON values with pretty printing.
Snapshot.json "user data" <|
\() ->
User.encode userUses 2-space indentation. Keys are sorted alphabetically for deterministic output.
Create a snapshot test with a custom printer.
Snapshot.custom myXmlPrinter "config file" <|
\() ->
buildConfig optionsUse this when you need a custom a -> String conversion.
Create a snapshot test that validates before snapshotting.
Snapshot.checkedTest "parsed config" <|
\() ->
Config.parse rawInput
|> Result.map Config.toStringIf the Result is Err, the test fails with that error message and no
snapshot is written. If Ok, the value is snapshotted normally.
This is useful when test setup might fail (parsing, validation, etc.) and you want to catch those failures before snapshotting.
Create a JSON snapshot test that validates before snapshotting.
Snapshot.checkedJson "decoded user" <|
\() ->
Json.Decode.decodeString userDecoder jsonString
|> Result.mapError Json.Decode.errorToStringCreate a snapshot test with a custom printer that validates before snapshotting.
Snapshot.checkedCustom xmlPrinter "parsed xml" <|
\() ->
Xml.parse rawXml
|> Result.mapError Xml.errorToStringCreate a BackendTask-powered snapshot test for string output.
Snapshot.taskTest "elm.json deps" <|
File.rawFile "elm.json"
|> BackendTask.allowFatalUse this for tests that need IO (file reading, HTTP, etc).
Create a BackendTask-powered snapshot test for JSON values.
Snapshot.taskJson "api response" <|
Http.get url decoder
|> BackendTask.allowFatalUses 2-space indentation. Keys are sorted alphabetically for deterministic output.
Create a BackendTask-powered snapshot test with a custom printer.
Snapshot.taskCustom myPrinter "fetched data" <|
fetchData
|> BackendTask.allowFatalAdd scrubbers to a test with non-deterministic output.
Snapshot.test "log entry" (\() -> formatLog entry)
|> Snapshot.withScrubbers [ Scrubber.timestamp ]
Snapshot.json "api response" (\() -> encodeResponse resp)
|> Snapshot.withScrubbers [ Scrubber.guid, Scrubber.timestamp ]Scrubbers run after printing, replacing patterns like timestamps and GUIDs with stable placeholders.
Group related tests together.
Snapshot.describe "Date formatting"
[ Snapshot.test "ISO format" <|
\() -> Date.toIsoString date
, Snapshot.test "human readable" <|
\() -> Date.toHumanString date
]Test names are prefixed with the group name, separated by " / ". Snapshot files are stored in subdirectories matching the group structure.
Run only this test (and any other tests marked with only).
Snapshot.only <|
Snapshot.test "focus on this" <|
\() -> workInProgressWhen any test is marked with only, all tests without only will be skipped.
Use this during development to focus on specific tests.
Important: Using only causes the test suite to fail, preventing you from
accidentally committing focused tests to CI.
Note: skip takes precedence over only - a skipped test won't run even
if it's inside an only block.
Skip this test.
Snapshot.skip <|
Snapshot.test "broken test" <|
\() -> brokenCodeThe test will be reported as skipped but won't be executed. Use this to temporarily disable tests without deleting them.
Important: Using skip causes the test suite to fail, preventing you from
accidentally committing skipped tests to CI.
Note: skip takes precedence over only - a skipped test won't run even
if it's inside an only block.
A placeholder for a test you intend to write later.
Snapshot.todo "handle edge case where input is empty"The test will be reported as a todo item. This is useful for jotting down test ideas without implementing them immediately.
Important: Using todo causes the test suite to fail, preventing you from
accidentally committing incomplete tests to CI.
An opaque type representing a snapshot test or group of tests.
Create tests using
test,json,custom, or theirtask*variants. Group related tests usingdescribe.