BarredEwe/Prefire
π₯ A library based on Xcode Preview, for easy generation: Playbook view, Snapshot and Accessibility tests. SwiftUI and UIKit supported!
π₯ What is Prefire?
Prefire transforms your #Preview blocks into:
- β Snapshot tests
- β Playbook views
- β Visual flows with states and user stories
- β Living documentation β fully automated
π Key Features
<img src="https://i.ibb.co/LNYBfMw/ezgif-com-gif-maker-2.gif" alt="Playbook" width="200" align="right">
- π§ 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
Why Prefire?
- π₯ 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
<br clear="all">
β‘οΈ Quick Start
π¦ Example project available at: Prefire Example
1. Add Prefire to Your Project
// 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")
]
)2. Write #Preview
#Preview {
Button("Submit")
}3. Run tests
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.
<img src="https://i.postimg.cc/XNPVPL1G/Untitled-2.gif" width="300">
π¦ Installation
Supports:
- β
SPM Plugin (
Package.swift) - β Xcode Build Tool Plugin
- β
CLI (
brew install prefire) - β GitHub Actions / CI
See detailed setup in the Installation guide
π§ How It Works
π 1. Parses all source files
- Finds all
#PreviewandPreviewProviderblocks - Supports modifiers:
.prefireEnabled(),.prefireIgnored()
π 2. Caches Types and PreviewBodies
- Based on file modification date + SHA-256 of inputs
- Avoids re-parsing if nothing changed
π’ 3. Generates Snapshot Tests
- Uses
Stenciltemplates - Respects
.prefire.ymlconfiguration
π 4. Generates Playbook View
- Groups by
UserStory,State - Outputs
PreviewModels.generated.swift
π Advanced Usage
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()
}Playbook (Demo) View
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)
}
}Snapshot tests
Just run generated tests π All tests will be generated in the DerivedData folder.
<img src="https://i.postimg.cc/XNPVPL1G/Untitled-2.gif" width="300">
Plugin PrefireTestsPlugin will handle everything for you π οΈ
For detailed instruction, check out swift-snapshot-testing or examine an example project.
API
Prefire provide new commands for previews:
- You can set the delay, precision and perceptualPrecision parameters for the snapshot:
``swift .snapshot(delay: 0.3, precision: 0.95, perceptualPrecision: 0.98) ``
``swift static var previews: some View { TestView() .snapshot(delay: 0.3, precision: 0.95, perceptualPrecision: 0.98) } ``
- Function for connecting preview together in one Flow:
<img src="https://i.postimg.cc/jSh23G8W/temp-Image9a-EDKU.avif" width="350" align="right">
``swift .previewUserStory(.auth) ``
```swift static var previews: some View { PrefireView() .previewUserStory(.auth) }
static var previews: some View { AuthView() .previewUserStory(.auth) } ```
For example Authorization flow: LoginView, OTPView and PincodeView
<br clear="all">
- If a preview contains more than one
View, you can markStatefor these views.
<img src="https://i.postimg.cc/Z5JKNwTJ/temp-Imageh19pin.avif" width="350" align="right">
``swift .previewState(.loading) ``
```swift static var previews: some View { TestView("Default")
TestView("Loading") .previewState(.loading) } ```
<br clear="all">
π§° API Summary
| 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) |
π‘ Advanced: CLI Usage
prefire tests
# Generate playbook models
prefire playbookRun prefire tests --help or prefire playbook --help for more options.
π Configuration: `.prefire.yml`
See detailed configuration in the Configuration guide
test_configuration:
target: MyApp
playbook_configuration:
preview_default_enabled: trueDistribution
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;π§ Internal Architecture
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
Requirements
- Swift 5.6 or higher
- Xcode 14.0 or higher
- iOS 14 or higher
Troubleshooting
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
π€ Contributing
We welcome contributions! Please follow these steps:
- Fork the repository
- Create a feature branch
- Submit a Pull Request
π License
Prefire is released under the Apache License 2.0. See LICENSE for details.
Package Metadata
Repository: BarredEwe/Prefire
Homepage: https://prefire.ru
Stars: 482
Forks: 37
Open issues: 28
Default branch: main
Primary language: swift
License: Apache-2.0
Topics: accesibility-tests, component, ios, playbook, plugin, preview, screen, snapshot-testing, swift, swift-plugin, swiftui, swiftui-previews, swiftui-xcode-previews, testing, xcode, xcode-plugin, xcode-previews
README: README.md