Awesome
Prefire
<img src="https://i.ibb.co/LNYBfMw/ezgif-com-gif-maker-2.gif" alt="Playbook" width="200" align="right">Do you like SwiftUI Preview and use it? Then you must try ๐ฅPrefire!
You can try ๐ฅPrefire starting from example project.
- โ Easy to use: Get started with the example project.
- โ Fully automatic generation based on Sourcery
- โ Generation Playbook (Demo) views
- โ Generation Snapshot tests based on swift-snapshot-testing
- โ Generation Accesability Snapshot tests
- โ Support for Xcode Plugin
Installation
Prefire can be installed for an Xcode Project
or only for one Package
.
Xcode Project Plugin
You can integrate Prefire as an Xcode Build Tool Plug-in if you're working on a project in Xcode.
- Add
Prefire
as a package dependency to your project without linking any of the products.
- Select the target to which you want to add linting and open the
Build Phases
inspector. OpenRun Build Tool Plug-ins
and select the+
button. From the list, selectPrefirePlaybookPlugin
orPrefireTestsPlugin
, and add it to the project.
Swift Package Plugin
You can integrate Prefire as a Swift Package Manager Plug-in if you're working with
a Swift Package with a Package.swift
manifest.
- Add Prefire as a package dependency to your
Package.swift
file.
dependencies: [
.package(url: "https://github.com/BarredEwe/Prefire", from: "1.0.0")
]
- Add Prefire to a target using the
plugins
parameter.
.target(
plugins: [
// For Playbook (Demo) view
.plugin(name: "PrefirePlaybookPlugin", package: "Prefire")
]
),
.testTarget(
plugins: [
// For Snapshot Tests
.plugin(name: "PrefireTestsPlugin", package: "Prefire")
]
)
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:
<br clear="all">LoginView
,OTPView
andPincodeView
-
If a preview contains more than one
<img src="https://i.postimg.cc/Z5JKNwTJ/temp-Imageh19pin.avif" width="350" align="right">View
, you can markState
for these views..previewState(.loading)
<br clear="all">static var previews: some View { TestView("Default") TestView("Loading") .previewState(.loading) }
Config
To further customize Prefire, you can create a .prefire.yml
file in the root directory of your project. Here's an example of its content:
test_configuration:
- target: PrefireExample
- test_file_path: PrefireExampleTests/PreviewTests.generated.swift
- template_file_path: CustomPreviewTests.stencil
- simulator_device: "iPhone15,2"
- required_os: 16
- preview_default_enabled: true
- sources:
- ${PROJECT_DIR}/Sources/
- snapshot_devices:
- iPhone 14
- iPad
- imports:
- UIKit
- SwiftUI
- testable_imports:
- Prefire
playbook_configuration:
- preview_default_enabled: true
- template_file_path: CustomModels.stencil
- imports:
- UIKit
- Foundation
- testable_imports:
- SwiftUI
Configuration keys and their descriptions
target
- Your project Target for Snapshot tests. Default: FirstTargettest_file_path
- Filepath to generated file. Default: DerivedDatatemplate_file_path
- Stencil file for generated file. Optional parameter.
For test plugin Default: Templates/PreviewTests.stencil from the package.
For playbook plugin Default: Templates/PreviewModels.stencil from the packagesimulator_device
- Device for Snapshot testing. Optional parameter.required_os
- iOS version for Snapshot testing. Optional parameter.snapshot_devices
- the list of devices snapshots should be generated for. Thesimulator_device
specified above will still be required and used, but snapshotting will take on the traits of thesnapshot_devices
. ThedisplayScale
will default to2.0
and device specific safe areas will be.zero
. Optional parameter.preview_default_enabled
- Do I need to automatically add all previews based on the new syntax to the tests. Default: trueimports
- Additional imports for the generated Playbook/Tests. Optional parameter.testable_imports
- Additional@testable
imports for the generated Playbook/Tests. Optional parameter.sources
- Paths to swift file or directory sources. Default: File paths of a specific target or project
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;
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