Skip to content

Split snapshot folders by source file under new split_snapshot_directories flag#163

Merged
BarredEwe merged 1 commit into
BarredEwe:mainfrom
AllDmeat:fix/issue-80-per-source-snapshot-folder
Jun 10, 2026
Merged

Split snapshot folders by source file under new split_snapshot_directories flag#163
BarredEwe merged 1 commit into
BarredEwe:mainfrom
AllDmeat:fix/issue-80-per-source-snapshot-folder

Conversation

@AllDmeat

Copy link
Copy Markdown
Contributor

Summary

Fixes #80 — when use_grouped_snapshots: false, snapshots still landed in a single shared __Snapshots__/PreviewTests.generated/ folder even though Prefire generated separate <File>Tests.generated.swift files per source.

Adds an opt-in split_snapshot_directories config flag (default false) that fixes this.

Root cause

Since #135 (use_grouped_snapshots: false) Prefire emits one .swift test file per source (ButtonViewTests.generated.swift, CartViewTests.generated.swift, …). But the Keys.file argument passed into the Stencil template — used as private var file: StaticString and forwarded to every assertSnapshot(file: file, ...) — was hardcoded to <test_target_path>/PreviewTests.generated.swift in GenerateTestsCommand.makeArguments.

swift-snapshot-testing derives __Snapshots__/<basename(file) without .swift>/ from that path. Same file: in every class ⇒ everything ends up in __Snapshots__/PreviewTests.generated/, regardless of how many separate classes Prefire emitted.

Fix

Two surgical edits + one new config flag:

  1. GenerateTestsCommand.makeArguments picks Constants.snapshotFileTemplated ({PREVIEW_FILE_NAME}Tests.generated.swift) instead of Constants.snapshotFileName when both use_grouped_snapshots: false and split_snapshot_directories: true.
  2. PrefireGenerator.generateUngroupedFiles resolves the {PREVIEW_FILE_NAME} placeholder inside any string-valued argument (i.e. file) per iteration, mirroring the existing placeholder resolution it already does on inlineTemplate and output.
  3. New config key split_snapshot_directories plumbed through Config.TestsConfig, ConfigDecoder, and GeneratedTestsOptions.

If the user combines split_snapshot_directories: true with use_grouped_snapshots: true, the flag is ignored with a warn-log explaining why (one shared .swift ⇒ one shared folder).

Behaviour matrix

use_grouped_snapshots split_snapshot_directories Result
true (default) false (default) Unchanged: 1 file PreviewTests.generated.swift, all snapshots in __Snapshots__/PreviewTests.generated/.
true true Warn-log; flag ignored (one shared .swift cannot split folders via file:).
false false (default) Unchanged backward-compat after #135: N .swift files, but file: still shared ⇒ snapshots still in one folder. Keeps existing snapshot files in place after upgrade.
false true Newfile: is per-source ⇒ snapshots land in __Snapshots__/<File>Tests.generated/ per source. Closes #80.

Minimal config to enable the new layout

test_configuration:
  use_grouped_snapshots: false
  split_snapshot_directories: true
  test_file_path: "Tests/{PREVIEW_FILE_NAME}Tests.generated.swift"

Migration note

Default-off is deliberate. Projects already on use_grouped_snapshots: false keep their current __Snapshots__/PreviewTests.generated/ layout untouched after upgrading. Opting in is a content-move that the user controls — either move existing PNGs into the new <File>Tests.generated/ subfolders, or wipe and re-record.

Test plan

  • cd PrefireExecutable && swift test — 41/41 pass, including 3 new tests:
    • GenerateTestsCommandTests.test_makeArguments_split_snapshot_directories_uses_templated_file_name
    • GenerateTestsCommandTests.test_makeArguments_ungrouped_without_split_keeps_legacy_file_name
    • PrefireGeneratorTests.testUngroupedFileGenerationResolvesPlaceholderInArguments
  • swift build -c release clean
  • End-to-end CLI run on Example/Shared with use_grouped_snapshots:false + split_snapshot_directories:true → each generated <File>Tests.generated.swift contains its own private var file: StaticString { ... "<File>Tests.generated.swift" }, no {PREVIEW_FILE_NAME} leftover.
  • End-to-end CLI run on Example/Shared with legacy use_grouped_snapshots:false only (no split) → all 3 classes still reference the shared PreviewTests.generated.swift, confirming backward compatibility.

…tories` flag

When `use_grouped_snapshots: false` was introduced in BarredEwe#135 the generated
.swift test files split per source, but every class still rendered the same
hardcoded `file:` path (`PreviewTests.generated.swift`). swift-snapshot-testing
derives `__Snapshots__/<basename>/` from `file:`, so all PNGs kept landing in
one shared folder — issue BarredEwe#80.

Add an opt-in `split_snapshot_directories` config key (default `false`). When
combined with `use_grouped_snapshots: false` Prefire templates `Keys.file` to
`{PREVIEW_FILE_NAME}Tests.generated.swift` and resolves the placeholder per
source file inside `PrefireGenerator.generateUngroupedFiles`, so each class
points at its own .swift and snapshots land in `__Snapshots__/<File>Tests.generated/`.

Default-off keeps existing snapshot layouts unchanged; combining with
`use_grouped_snapshots: true` warns instead of silently splitting.

Fixes BarredEwe#80

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@BarredEwe

Copy link
Copy Markdown
Owner

Great work, @AllDmeat! I've reviewed the changes thoroughly.

The root cause analysis is spot on - hardcoded file: path in the Stencil template was the issue, and the fix is both minimal and correct.

@BarredEwe BarredEwe merged commit c33faeb into BarredEwe:main Jun 10, 2026
3 checks passed
BarredEwe pushed a commit that referenced this pull request Jun 11, 2026
The release pipeline currently ships a stale CLI:

1. `make update version=X.Y.Z` only renames the binary directory and
   rewrites `info.json` + `Version.swift` — it does not rebuild
   `Binaries/PrefireBinary.artifactbundle/prefire-<ver>-macos/bin/prefire`.

2. `.github/workflows/publish.yml` runs only `make archive` on a tag
   push, which `tar`s up the binary already committed to the repo.

Effect: the binary path inside the artifactbundle gets renamed on each
release, but the actual file is byte-identical with the previous
release. In the 5.6.0 tag commit (178ee10), the binary blob hash is
unchanged from 5.5.0 (`R100` rename), and the bundled CLI reports
`--version` = `5.4.1`. As a result, config keys added after 5.4.1 —
including the freshly-merged `split_snapshot_directories` from #163 —
are silently ignored at runtime even though the Swift sources in the
release contain them.

This patch closes the gap in two places:

- `make update` now runs `make binary` as its last step. Since the
  recipe rewrites `Version.swift` before invoking `binary`, the
  rebuilt CLI picks up the new `Version.value` constant. The
  recursive `$(MAKE)` re-evaluates `CUR_VERSION` from the already-
  renamed folder, so the rebuilt binary lands in the new directory.
- `publish.yml` runs `make binary` before `make archive` as a
  defense-in-depth guard, so a manual / forgotten `make update`
  cannot still ship a stale CLI.

Also dropping a duplicate `sed` on `info.json` line 9 that was a
no-op (it ran the same substitution twice).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Snapshots names doesn't contain view name

2 participants