π₯ A library based on Xcode Preview, for easy generation: Playbook view, Snapshot and Accessibility tests. SwiftUI and UIKit supported!
510
stars
334
commits
Swift
primary language
Sep 10, 2026
updated

Prefire transforms your #Preview blocks into:
#Preview, @PreviewableUIView/UIViewController and NSView/NSViewControllerπ¦ 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#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:
Package.swift)brew install prefire)mint install BarredEwe/Prefire)See detailed setup in the Installation guide
Install the bundled CLI via Mint:
mint install BarredEwe/Prefire
The installed prefire wrapper ships the PrefireBinary artifactbundle as an embedded SwiftPM resource, so it is self-contained β no external binary path is required. To override the path of the embedded binary (e.g. for local development against an in-progress build), set PREFIRE_BINARY_PATH to the absolute path of the prefire executable.
#Preview and PreviewProvider blocks.prefireEnabled(), .prefireIgnored()Types and PreviewBodiesStencil templates.prefire.yml configurationUserStory, StatePreviewModels.generated.swiftTo 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
isComponent: trueisComponent: falseimport 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, OTPView and PincodeView
If a preview contains more than one View, you can mark State for these views.
.previewState(.loading)
static var previews: some View {
TestView("Default")
TestView("Loading")
.previewState(.loading)
}
Prefire supports native SwiftUI parameterized previews:
#Preview("TextView", traits: .sizeThatFitsLayout, arguments: ["- A", "- B", "- C"]) { suffix in
Text("1 \(suffix)")
}
Prefire expands each argument into its own snapshot and Playbook preview.
| 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) |
| Parameterized preview | #Preview(..., arguments: values) |
# Generate snapshot tests
prefire tests
# Generate playbook models
prefire playbook
Run prefire tests --help or prefire playbook --help for more options.
.prefire.ymlSee detailed configuration in the Configuration guide
test_configuration:
target: MyApp
playbook_configuration:
preview_default_enabled: true
When 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 for Types and PreviewsPrefireTestsPlugin / PrefirePlaybookPlugin β SPM/Xcode integrationsprefire β CLI entry point, calls shared generator codeNavigationView in Preview not supported for Playbook
Running Prefire via CI
defaults write com.apple.dt.Xcode IDESkipPackagePluginFingerprintValidatation -bool YESXcode is unable to generate tests in a custom path.
defaults write com.apple.dt.Xcode IDEPackageSupportDisablePluginExecutionSandbox -bool YESWe welcome contributions! Please follow these steps:
Prefire is released under the Apache License 2.0. See LICENSE for details.
Swift
98.1%
Makefile
1.9%
π₯ A library based on Xcode Preview, for easy generation: Playbook view, Snapshot and Accessibility tests. SwiftUI and UIKit supported!
510
stars
334
commits
Swift
primary language
Sep 10, 2026
updated

Prefire transforms your #Preview blocks into:
#Preview, @PreviewableUIView/UIViewController and NSView/NSViewControllerπ¦ 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#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:
Package.swift)brew install prefire)mint install BarredEwe/Prefire)See detailed setup in the Installation guide
Install the bundled CLI via Mint:
mint install BarredEwe/Prefire
The installed prefire wrapper ships the PrefireBinary artifactbundle as an embedded SwiftPM resource, so it is self-contained β no external binary path is required. To override the path of the embedded binary (e.g. for local development against an in-progress build), set PREFIRE_BINARY_PATH to the absolute path of the prefire executable.
#Preview and PreviewProvider blocks.prefireEnabled(), .prefireIgnored()Types and PreviewBodiesStencil templates.prefire.yml configurationUserStory, StatePreviewModels.generated.swiftTo 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
isComponent: trueisComponent: falseimport 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, OTPView and PincodeView
If a preview contains more than one View, you can mark State for these views.
.previewState(.loading)
static var previews: some View {
TestView("Default")
TestView("Loading")
.previewState(.loading)
}
Prefire supports native SwiftUI parameterized previews:
#Preview("TextView", traits: .sizeThatFitsLayout, arguments: ["- A", "- B", "- C"]) { suffix in
Text("1 \(suffix)")
}
Prefire expands each argument into its own snapshot and Playbook preview.
| 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) |
| Parameterized preview | #Preview(..., arguments: values) |
# Generate snapshot tests
prefire tests
# Generate playbook models
prefire playbook
Run prefire tests --help or prefire playbook --help for more options.
.prefire.ymlSee detailed configuration in the Configuration guide
test_configuration:
target: MyApp
playbook_configuration:
preview_default_enabled: true
When 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 for Types and PreviewsPrefireTestsPlugin / PrefirePlaybookPlugin β SPM/Xcode integrationsprefire β CLI entry point, calls shared generator codeNavigationView in Preview not supported for Playbook
Running Prefire via CI
defaults write com.apple.dt.Xcode IDESkipPackagePluginFingerprintValidatation -bool YESXcode is unable to generate tests in a custom path.
defaults write com.apple.dt.Xcode IDEPackageSupportDisablePluginExecutionSandbox -bool YESWe welcome contributions! Please follow these steps:
Prefire is released under the Apache License 2.0. See LICENSE for details.
Swift
98.1%
Makefile
1.9%