SkillAgentSearch skills...

Prefire

πŸ”₯ A library based on Xcode Preview, for easy generation: Playbook view, Snapshot and Accessibility tests. SwiftUI and UIKit supported!

Install / Use

/learn @BarredEwe/Prefire

README

Prefire

<p align="center"> <a href="https://github.com/BarredEwe/Prefire/releases/latest"><img alt="Release" src="https://img.shields.io/github/release/BarredEwe/Prefire.svg"/></a> <a href="https://developer.apple.com/"><img alt="Platform" src="https://img.shields.io/badge/platform-iOS-green.svg"/></a> <a href="https://developer.apple.com/swift"><img alt="Swift6" src="https://img.shields.io/badge/language-Swift_6-green.svg"/></a> <a href="https://swift.org/package-manager"><img alt="Swift Package Manager" src="https://img.shields.io/badge/SwiftPM-compatible-yellowgreen.svg"/></a> <img alt="Swift Package Manager" src="https://img.shields.io/badge/Xcode%20Plugins-Supported-brightgreen.svg"/> </p>

πŸ”₯ 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 UIView and UIViewController
  • βš™οΈ 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 #Preview and PreviewProvider blocks
  • 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 Stencil templates
  • Respects .prefire.yml configuration

πŸ“˜ 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:

    .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:

    <img src="https://i.postimg.cc/jSh23G8W/temp-Image9a-EDKU.avif" width="350" align="right">
    .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

    <br clear="all">
  • If a preview contains more than one View, you can mark State for these views.

    <img src="https://i.postimg.cc/Z5JKNwTJ/temp-Imageh19pin.avif" width="350" align="right">
    .previewState(.loading)
    
    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

# Generate snapshot tests
prefire tests

# Generate playbook models
prefire playbook

Run 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: true

Distribution

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, logic
  • PrefireGenerator β€” handles stencil templating + snapshot generation
  • PrefireCacheManager β€” unifies caching for Types and Previews
  • PrefireTestsPlugin / PrefirePlaybookPlugin β€” SPM/Xcode integrations
  • prefire β€” 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:

  1. Fork the repository
  2. Create a feature branch
  3. Submit a Pull Request

πŸ“„ License

Prefire is released under the Apache License 2.0. See LICENSE for details.

Related Skills

View on GitHub
GitHub Stars470
CategoryDevelopment
Updated17m ago
Forks36

Languages

Swift

Security Score

100/100

Audited on Apr 1, 2026

No findings