BarredEwe / Prefire

🔥 A library based on SwiftUI Preview, for easy generation: Playbook view, Snapshot and Accessibility tests
Apache License 2.0
251 stars 16 forks source link

Generated PreviewModels swift file has no access to preview files from Swift local packages #31

Closed woutergoossens closed 4 months ago

woutergoossens commented 6 months ago

Context 🕵️‍♀️

We have rather big project with some local SPM local packages. In those packages we have SwiftUI screens and components. I added Prefire to the project and package and updated a SwiftUI preview in the local package to use PrefireProvider. But then the project generated the PreviewModels file but it has no access to

Screenshot 2023-12-06 at 16 37 28

AppointmentDetailsScreen_Previews is part of Presentation package and that package isn't imported or cannot be accessed.. How can I do that? Can I update the PreviewModels template file?

woutergoossens commented 6 months ago

It seems PR 21 is a possible solution? Any ETA on this? https://github.com/BarredEwe/Prefire/pull/21

BarredEwe commented 6 months ago

I'm currently working on a new major release https://github.com/BarredEwe/Prefire/pull/29 with a lot of improvements. In particular, the ability to install custom imports has been added:

test_configuration:
  - target: PrefireExample
  - simulator_device: "iPhone15,2"
  - required_os: 17

playbook_configuration:
  - imports:
      - UIKit
      - Foundation

⚠️ The branch is currently under active development, but the main work has already been done and the general interface has already been fixed.

woutergoossens commented 6 months ago

Sounds great! Can I already test this via SPM with your specific branch?

Our packages also have tests, is that supported? So we run the test in the main project and snapshot tests from the packages are verified?

So in test_configuration target would be just our main target?

When do you think it could be released? I am working for a big Belgian banking company and we have more then > 100 screens and components in SwiftUi that we like to have snapshots from (and tested) :)

so would be a good usecase to test v2, right?

BarredEwe commented 6 months ago

I think it's really possible to use a branch now. According to the plans, there is not much left to finish. About 1-2 weeks before the full release. In general, it sounds great for a test and a quick revision :)

woutergoossens commented 6 months ago

Sounds good. Happy to test :)

I added that branch via SPM but when I run the tests I get this

Screenshot 2023-12-06 at 20 47 37
BarredEwe commented 6 months ago

I can't reproduce it ): Could you clear spm cache?

woutergoossens commented 6 months ago

Tried cleaning everything.. Same issue.. Will try in the example project later today...

woutergoossens commented 6 months ago

I have the same issue when I run the example app.. Let me try again clearing everything :D

Nope.. doesn't work. Should I do something extra?

Screenshot 2023-12-07 at 11 00 12
BarredEwe commented 6 months ago

I've added a couple of changes, can you check on the new version of the branch?

woutergoossens commented 6 months ago

Thanks. That works :) I added it to my project and a package with SwiftUI screens. But now I have an issue with the new macro previews.

For example it wants to generate the PreviewTests.generated file like this -->

Screenshot 2023-12-08 at 09 23 54

We create that screen with a private PreviewViewModel (the VM is our ObservableObject with state and events,...) But the generated file has no access to it.. Also we add an environmentObject to it, which is part of another package. How can I add that import for the tests? How can I fix that without making all those classes public? :)

In the old way of creating previews, it's also created like this and that works without making the VM public.

static var previews: some View {
        SplashScreen(viewModel: PreviewViewModel())
    }
woutergoossens commented 6 months ago

So.. tested now in the Project itself.

So in our project we have SwiftUI files in different packages (for example Presentation, DesignSwiftUI,...)

In the custom config I added extra import Presentation

playbook_configuration:
  - imports:
      - UIKit
      - Foundation
      - Presentation

PreviewModels --> So that is working. The file is found.

Screenshot 2023-12-08 at 13 26 47

PreviewTests --> Macro Previews:

Screenshot 2023-12-08 at 13 31 00 Screenshot 2023-12-08 at 15 34 54
BarredEwe commented 6 months ago

I have added a new configuration:

prefire_configuration:
  - imports:
    - UIKit
    - Foundation
  - testable_imports:
    - SwiftUI

And I fixed a few bugs.

woutergoossens commented 6 months ago

Thanks!

Playbook (PreviewModels.generated) is working now with @testable import Presentation But doesn't show the Macro previews?

PreviewTests is still failing because of Invalid redeclaration of 'test_SelectCoHolderTestPreview_Preview()' Already tried to remove the SwiftUI file but it keeps the test..

Screenshot 2023-12-11 at 14 16 30

What can I do to fix that? Already cleaned DerrivedData/SPM cache/...

BarredEwe commented 6 months ago

I hope I fixed it)

woutergoossens commented 6 months ago

Worked once, then it was cleaned and the method was only there once. Then I did a change. Changed the preview macro to old PreviewProvider and the old macro stays in the PreviewTests file..

Do you need some logs or more info?

woutergoossens commented 6 months ago

Let me try to reproduce it with the example app :)

woutergoossens commented 6 months ago

Hello, while trying to reproduce this I got this weird issue. PreviewTests is combining tests of the Example project and my project.. :D It's mixing some saved cache?

Screenshot 2023-12-13 at 12 25 39
BarredEwe commented 6 months ago

Everything that is generated by macros is in one folder. Now the filtering is very simple (search for the inclusion of the project name in the file name). I'll try to figure out how to improve it.

BarredEwe commented 6 months ago

I have added a new macro file filtering. Macros from another project should no longer be included

woutergoossens commented 6 months ago

Thanks! That's working.

But I still have an issue ==> I need multiple testable imports

Our structure: AppTests target will run the tests from the App target + tests from all the Swift Packages (and we need tests from Presentation, DesignSwiftUI,...)

How can we have that? For example now I have as config:

test_configuration:
  - target: Presentation

And in the generated PreviewTests file it is combining the test from AppTests target + packages. So it needs to have multiple @testable import statements.

For example the generated file now has:

@testable import Presentation
 private var file: StaticString { .init(stringLiteral: "/Users/gowo/Development/**/mobile-ios/Presentation/PreviewTests.swift") }

But in my case it could better be

@testable import Presentation
@testable import DesignSwiftUI

 private var file: StaticString { .init(stringLiteral: "/Users/gowo/Development/**/mobile-ios/AppTests/PreviewTests.swift") }

because now it finds the previews from the Presentation package but it also generated the preview tests for the DesignSwiftUI package but it doesn't find those files :)

Thanks!!

BarredEwe commented 6 months ago

Added parameter setting for test_configuration (same as for playbook_configuration):

test_configuration:
  - required_os: 17
  - imports:
      - UIKit
      - SwiftUI
  - testable_imports:
      - Prefire
woutergoossens commented 6 months ago

Thanks! It's working!! 🥳

But I think I found an issue regarding the Macro's.

I updated the test_configuration target to AppName_STUB_Debug as this is the main App module for the tests. And so it would create the snapshots in the AppName_STUB_Debug folder, instead of the Presentation folder.

Screenshot 2023-12-15 at 15 36 43

So I have 2 testable imports (via the config) + 1 import added via the target

@testable import Argenta_STUB_Debug @testable import Presentation @testable import DesignSwiftUI

But when I do that, the macro previews are not included in the PreviewTests file, only the ones from PreviewProvider. When I update the target to DesignSwiftUI or Presentation, the macro previews from the chosen package are included.

private var file: StaticString { .init(stringLiteral: "/Users/gowo/Development/**/mobile-ios/AppName_STUB_Debug/PreviewTests.swift") }

How can we fix that? :)

Almost there! Thanks for the great work and effort!

EDIT: I think we should combine all the preview bodies, not only from specified target but also from the testable import targets?

woutergoossens commented 6 months ago

And I tried to build it via our CI and got this issue

error: “PrefirePlaybookPlugin” must be enabled before it can be used

On Xcode I get a popup to trust the plugin.. But hmm how should we do that on CI? :)

woutergoossens commented 6 months ago

And I tried to build it via our CI and got this issue

error: “PrefirePlaybookPlugin” must be enabled before it can be used

On Xcode I get a popup to trust the plugin.. But hmm how should we do that on CI? :)

I think I found it. I should use defaults write com.apple.dt.Xcode IDESkipPackagePluginFingerprintValidatation -bool YES

BarredEwe commented 6 months ago

Thanks! It's working!! 🥳

But I think I found an issue regarding the Macro's.

I updated the test_configuration target to AppName_STUB_Debug as this is the main App module for the tests. And so it would create the snapshots in the AppName_STUB_Debug folder, instead of the Presentation folder. Screenshot 2023-12-15 at 15 36 43

So I have 2 testable imports (via the config) + 1 import added via the target

@testable import Argenta_STUB_Debug @testable import Presentation @testable import DesignSwiftUI

But when I do that, the macro previews are not included in the PreviewTests file, only the ones from PreviewProvider. When I update the target to DesignSwiftUI or Presentation, the macro previews from the chosen package are included.

private var file: StaticString { .init(stringLiteral: "/Users/gowo/Development/**/mobile-ios/AppName_STUB_Debug/PreviewTests.swift") }

How can we fix that? :)

Almost there! Thanks for the great work and effort!

EDIT: I think we should combine all the preview bodies, not only from specified target but also from the testable import targets?

I understood the problem. I've redesigned the macro filtering system. Now it will enable all macros along the path of the main target.

woutergoossens commented 6 months ago

Hi,

Thanks for the update. But now it doesn't include any macro previews.. Should I update the config? Only when I change the target name to a package name, I see the macros..

Our app folder structure. Every package has a folder in the root.

/AppName /Presentation /DesignSwiftUI /...

And our main Target is something like AppName_STUB_Debug which hasn't a folder in this stucture. AppName_STUB_Debug folder is only created to put the snapshots..

When I remove target from the config it will use "App" target. But then I get this -->

Screenshot 2023-12-18 at 15 28 28

App is the target name but AppName_STUB_Debug is our product/module name for testing..

Almost there! How can I make this work?

Wouter

woutergoossens commented 6 months ago

Let me try create a sample app :)

woutergoossens commented 6 months ago

So I created an example app with 2 Swift Packages.

Presentation has an AuthView and Design has PrefireView

But here also have an issue ==> When it creates the PreviewTests file the first time, it contains the preview macro (but only 1 per View). But when I add some more macro previews, the PreviewTests file is not updated.. It only adds the first one from a file?

Good thing is that it adds the preview macro's from the packages

PrefireExample.zip

BarredEwe commented 6 months ago

Thanks for the example project! I found the problem and posted a fix.

woutergoossens commented 5 months ago

Thanks. Working great now. It generated 300 snapshots now of our SwiftUI Screens :)

What is the progress on the 2.0?

BarredEwe commented 5 months ago

Version 2.0 is almost ready. It remains to complete the tests and documentation)