Repository navigation
Redesign snapshot API around a config DSL (breaking) - #6
Merged
Merged
Conversation
Replaces the positional AckeeSnapshotTests constructor with a config DSL and an internal resolver expanding config + per-preview overrides into snapshot variants. Adds SnapshotResolver, ExtraMetadataParser, PreviewIdentifier, variant naming, the DSL scopes, UiTheme -> UiMode rename, and the :framework unit-test suite. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> WIP WIP
Rework PaparazziEngine.init to take (kind, device, uiMode, scope) and drive one Paparazzi per group via Kotest beforeEach/afterEach, replacing the PaparazziExtension listener bridge. Extract device/night-mode/rendering mappings into PaparazziMappings + PaparazziRenderConfig, switch PaparazziSnapshotTests to the config DSL, and add unit tests for the mappings. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
AckeeSnapshotTests now takes an engineFactory (() -> SnapshotEngine) and builds a fresh engine for each (kind, device, uiMode) group, so each instance's init is called exactly once. Backends no longer need cross-group state management. Updates docs, wiring test doubles, and the PaparazziSnapshotTests subclass accordingly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Framework / paparazzi:
- PaparazziEngine now derives the golden identity from the per-test variant
name (case-preserved) via the JUnit Description, instead of a group label
plus a lowercased Paparazzi snapshot name.
- Golden/variant names are source-mirroring, "_"-delimited segments with no
"_" inside a segment: device as "Pixel6-portrait", uiMode as "LIGHT", font
scale as "FontScale-NORMAL"; the redundant "component" kind label is dropped.
("-" rather than "." because the Kotest test name -> Paparazzi golden-file
pipeline rewrites "." to "_".)
- Wire the previously-dead before(context) hook into the render path.
Sample (Phase 4 + comprehensive override coverage):
- New UI: ArticleCard, Avatar, StatusBadge, ThemedChip, PromoBanner, PriceTag
and Welcome/Settings/Pricing/Profile/Login screens; previews grouped by
concern in SamplePreviews.kt.
- Per-concern snapshot classes: DefaultConfig, ExcludeCoupling, ProfileOverride,
InlineOverride, OverrideWidening, OverridePrecedence and AllLevelsOverride,
exercising every override axis at both profile and preview level, narrowing
and widening, plus the all-levels combination.
- Record 60 goldens; replace the old positional SampleSnapshotTests and remove
the stale goldens.
Framework unit tests updated for the new naming.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Regenerate API dumps for the redesigned framework/paparazzi surface - Make PaparazziEngine.DEFAULT_THEME private (was leaking into public API) - Bump versions to 3.0.0 (annotations major: PreviewSnapshotStrategy renamed to PreviewSnapshotKind; framework/paparazzi major; BOM), keeping the -paparazzialpha02 suffix on paparazzi/bom - Rewrite README for the config DSL + migration scenarios - Update CHANGELOG (Unreleased), RELEASING (inter-artifact edge note), and CLAUDE.md (framework->annotations dep, framework unit tests, DSL/SnapshotKind/UiMode) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a repo-wide `*.png filter=lfs` rule in .gitattributes and convert all 61 tracked PNGs (the 60 sample goldens + imgs/cover.png) to LFS pointers via `git add --renormalize` (no history rewrite). Keeps binary churn out of the packfiles as goldens accumulate across projects. Remote is GitHub, which serves LFS. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The library is stable and well-tested, but the config DSL and the SnapshotEngine extension point may still change as they are exercised against more complex projects. Mark them experimental so the API can evolve without an immediate breaking release, while signalling to consumers that the code is production-ready. - Add ExperimentalSnapshotsApi (@RequiresOptIn, WARNING, BINARY) in :annotations, the universal base module so the opt-in FQN resolves everywhere. - Apply it to SnapshotConfigScope, VariantsScope, ProfileOverrideScope and SnapshotEngine. - Auto opt-in all modules via optIn.add(...) in KotlinConventionPlugin, keeping internal/sample code free of @OptIn and green under allWarningsAsErrors; consumers opt in explicitly. - Add implementation(projects.annotations) to :paparazzi so the FQN resolves there (implementation deps are not transitive). - Regenerate annotations.api (only the marker class is added; BCV does not record annotation usages, so widening the experimental surface is not an ABI change). - Document the opt-in in README and the convention in CLAUDE.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Snapshot goldens are now stored in Git LFS, so any CI job that runs verifyPaparazziDebug must fetch the LFS objects or it compares against pointer stubs and fails. Set `lfs: true` on the checkout in the pull-request, main-branch and deploy preflight jobs (the publish job doesn't touch goldens, so it's left as-is). Document the LFS requirement for contributors in CLAUDE.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
petrs143
approved these changes
Jul 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Major redesign of the snapshot testing API. The old positional constructor (one test
class per kind/device/UI-mode/font-scale combination) is replaced by a single config DSL
on the test class, so one class now spans many kinds, devices, UI modes and font scales. New
axes and per-preview exceptions no longer require new constructor parameters or copied library
internals.
What changed
annotations
PreviewSnapshotStrategy→PreviewSnapshotKind(Component/Screenunchanged).PreviewFontScale,PreviewUiMode,PreviewDevice.SnapshotEngine@ExperimentalSnapshotsApi(opt-inWARNING).framework
AckeeSnapshotTeststakes a single DSL block (previews/before/decorate/variants) instead of the positional parameter list.UiTheme→UiMode;SnapshotStrategysealed interface →SnapshotKindenum plus a separate device axis.
SnapshotEngineSPI reworked(
init(kind, device, uiMode, scope)+snapshot(goldenName, content)), with a fresh enginecreated per
(kind, device, uiMode)group.<id>_<device>_<uiMode>_FontScale-<scale>).Device.Pixel6/Device.Nexus10.portrait/.landscapeshortcuts, namedprofiles,and a standing
exclude { }predicate. Overrides resolveinline ?: profile ?: class.SnapshotConfigException.:frameworknow depends on:annotations.paparazzi
PaparazziSnapshotTeststakes the DSL block; positional constructor removed.PaparazziEnginereimplemented against the new SPI (onePaparazziper group).tooling / infra
.gitattributestracks*.png); CI checkouts setlfs: true.AckeeSnapshotTestswiring; sample rebuilt into per-concern*SnapshotTestsclasses.README,CHANGELOG,RELEASING, and CLAUDE.md.Golden names now encode every axis, so all consumers must re-record their goldens after
upgrading:
See the README Usage and Migrating from the positional constructor sections.