Prefire transforms your #Preview blocks into:
- โ Snapshot tests
- โ Playbook views
- โ Visual flows with states and user stories
- โ Living documentation โ fully automated
- ๐ง Smart Preview Parsing โ including
#Preview,@Previewable - ๐ธ Snapshot Testing โ automatic test generation from previews
- ๐ Playbook View โ auto-generated interactive component catalog
- ๐ Flow-aware โ build user stories from multiple preview steps
- ๐งฉ UIKit Support โ support for
UIViewandUIViewController - โ๏ธ SPM + Xcode Plugins โ works in CLI, Xcode build phases, or CI
- ๐ง Fast Caching โ fingerprint-based AST and body caching avoids redundant work
- โ๏ธ Stencil Templates โ customize output with your own templates
- ๐ฅ Save Time - Generate tests and documentation automatically
- ๐ฅ Stay Consistent - Keep previews and tests always in sync
- ๐ฅ Improve Quality - Catch visual regressions before users do
- ๐ฅ Boost Collaboration - Share living documentation with your team
๐ฆ Example project available at: Prefire Example
// Package.swift
dependencies: [
.package(url: "https://github.com/BarredEwe/Prefire.git", from: "5.4.0")
.package(url: "https://github.com/pointfreeco/swift-snapshot-testing", from: "1.18.0"),
],
.testTarget(
dependencies: [
.product(name: "Prefire", package: "Prefire"),
.product(name: "SnapshotTesting", package: "swift-snapshot-testing"),
],
plugins: [
.plugin(name: "PrefireTestsPlugin", package: "Prefire")
]
)#Preview {
Button("Submit")
}Just run the test target ๐ โ Prefire will auto-generate snapshots based on your previews.
๐ก If your test target is empty, Prefire will still generate files and snapshot code during build.
Supports:
- โ
SPM Plugin (
Package.swift) - โ Xcode Build Tool Plugin
- โ
CLI (
brew install prefire) - โ GitHub Actions / CI
See detailed setup in the Installation guide
- Finds all
#PreviewandPreviewProviderblocks - Supports modifiers:
.prefireEnabled(),.prefireIgnored()
- Based on file modification date + SHA-256 of inputs
- Avoids re-parsing if nothing changed
- Uses
Stenciltemplates - Respects
.prefire.ymlconfiguration
- Groups by
UserStory,State - Outputs
PreviewModels.generated.swift
To generate tests and playbook, simply mark your preview using the PrefireProvider protocol:
struct Text_Previews: PreviewProvider, PrefireProvider {
static var previews: some View { ... }
}If you use the #Preview macro, ๐ฅPrefire will automatically find it!
If you don't need it, mark view - .prefireIgnored():
#Preview {
Text("")
.prefireIgnored()
}If you want to disable the automatic get of all previews, use the setting preview_default_enabled: false. Then to include preview in the test, you need to call the .prefireEnabled():
#Preview {
Text("")
.prefireEnabled()
}To use Playbook, simply use PlaybookView
- If you want to see a list of all the Views, use
isComponent: true - If you want to sort by UserStory, use
isComponent: false
import Prefire
struct ContentView: View {
var body: some View {
PlaybookView(isComponent: true, previewModels: PreviewModels.models)
}
}Just run generated tests ๐ All tests will be generated in the DerivedData folder.
Plugin PrefireTestsPlugin will handle everything for you ๐ ๏ธ
For detailed instruction, check out swift-snapshot-testing or examine an example project.
Prefire provide new commands for previews:
-
You can set the delay, precision and perceptualPrecision parameters for the snapshot:
.snapshot(delay: 0.3, precision: 0.95, perceptualPrecision: 0.98)
static var previews: some View { TestView() .snapshot(delay: 0.3, precision: 0.95, perceptualPrecision: 0.98) }
-
Function for connecting preview together in one Flow:
.previewUserStory(.auth)
static var previews: some View { PrefireView() .previewUserStory(.auth) } static var previews: some View { AuthView() .previewUserStory(.auth) }
For example Authorization flow:
LoginView,OTPViewandPincodeView
-
If a preview contains more than one
View, you can markStatefor these views..previewState(.loading)
static var previews: some View { TestView("Default") TestView("Loading") .previewState(.loading) }
| Feature | Modifier |
|---|---|
| Include in snapshot | .prefireEnabled() |
| Exclude from snapshot | .prefireIgnored() |
| Group in a flow | .previewUserStory(.auth) |
| Mark a UI state | .previewState(.error) |
| Customize snapshot | .snapshot(delay: 0.3, precision: 0.95) |
# Generate snapshot tests
prefire tests
# Generate playbook models
prefire playbookRun prefire tests --help or prefire playbook --help for more options.
See detailed configuration in the Configuration guide
test_configuration:
target: MyApp
playbook_configuration:
preview_default_enabled: trueWhen preparing for distribution, you may want to exclude your PreviewProvider and mock data from release builds. This can be achieved by wrapping them in #if DEBUG compiler directives. Alternatively, you can pass a compiler flag to exclude PreviewModels from release builds.
To exclude PreviewModels using Swift Package Manager, pass the PLAYBOOK_DISABLED swift setting in the package that links PrefirePlaybookPlugin:
swiftSettings: [
.define("PLAYBOOK_DISABLED", .when(configuration: .release)),
]If you are using Xcode, you can pass the compiler flag in the Xcode build settings:
SWIFT_ACTIVE_COMPILATION_CONDITIONS = PLAYBOOK_DISABLED;
PrefireCoreโ AST + preview parsing, caching, logicPrefireGeneratorโ handles stencil templating + snapshot generationPrefireCacheManagerโ unifies caching forTypesandPreviewsPrefireTestsPlugin/PrefirePlaybookPluginโ SPM/Xcode integrationsprefireโ CLI entry point, calls shared generator code
- Swift 5.6 or higher
- Xcode 14.0 or higher
- iOS 14 or higher
NavigationView in Preview not supported for Playbook
- Consider using other views or layouts for your Playbook needs.
Running Prefire via CI
- To run Prefire via Continuous Integration (CI), you need to configure permissions:
defaults write com.apple.dt.Xcode IDESkipPackagePluginFingerprintValidatation -bool YES
Xcode is unable to generate tests in a custom path.
- To resolve this, youโll need to disable the sandbox for file generation by running the following command in your terminal:
defaults write com.apple.dt.Xcode IDEPackageSupportDisablePluginExecutionSandbox -bool YES
We welcome contributions! Please follow these steps:
- Fork the repository
- Create a feature branch
- Submit a Pull Request
Prefire is released under the Apache License 2.0. See LICENSE for details.




