Skip to content

Commit

Permalink
Fix tests crashing when accessing SPM dependency resource bundle (tui…
Browse files Browse the repository at this point in the history
…st#6895)

* Adds the base sample project

* Adds tests to demonstrate the problem

* Tweaks the ResourcesProjectMapper
Removes the perhaps unnecessary BuildAcceptanceTest I added?

* Runs lint-fix

* Adds an install command before testing

* Reverts the changes from tuist#6865

* Re-runs lint fix

* Revert "Reverts the changes from tuist#6865"

This reverts commit 08cc4d1.

* Gates the bundle resource fix behind an #if canImport(XCTest) compiler directive.

* Empty commit to re-attempt CI, which failed to install Mise

* Runs mise lint again

* Adds extended comment with link to PR
  • Loading branch information
rhysm94 authored Oct 30, 2024
1 parent c6d3930 commit 30bda6c
Show file tree
Hide file tree
Showing 11 changed files with 154 additions and 1 deletion.
3 changes: 3 additions & 0 deletions Sources/TuistAcceptanceTesting/TuistAcceptanceFixtures.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public enum TuistAcceptanceFixtures {
case frameworkWithMacroAndPluginPackages
case frameworkWithNativeSwiftMacro
case frameworkWithSwiftMacro
case frameworkWithSPMBundle
case invalidManifest
case invalidWorkspaceManifestName
case iosAppLarge
Expand Down Expand Up @@ -133,6 +134,8 @@ public enum TuistAcceptanceFixtures {
return "framework_with_native_swift_macro"
case .frameworkWithSwiftMacro:
return "framework_with_swift_macro"
case .frameworkWithSPMBundle:
return "framework_with_spm_bundle"
case .invalidManifest:
return "invalid_manifest"
case .invalidWorkspaceManifestName:
Expand Down
11 changes: 10 additions & 1 deletion Sources/TuistGenerator/Mappers/ResourcesProjectMapper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -258,9 +258,10 @@ public class ResourcesProjectMapper: ProjectMapping { // swiftlint:disable:this
), the bundle containing the resources is copied into the final product.
static let module: Bundle = {
let bundleName = "\(bundleName)"
let bundleFinderResourceURL = Bundle(for: BundleFinder.self).resourceURL
var candidates = [
Bundle.main.resourceURL,
Bundle(for: BundleFinder.self).resourceURL,
bundleFinderResourceURL,
Bundle.main.bundleURL,
]
// This is a fix to make Previews work with bundled resources.
Expand All @@ -279,6 +280,14 @@ public class ResourcesProjectMapper: ProjectMapping { // swiftlint:disable:this
}
}
}
// This is a fix to make unit tests work with bundled resources.
// Making this change allows unit tests to search one directory up for a bundle.
// More context can be found in this PR: https://github.com/tuist/tuist/pull/6895
#if canImport(XCTest)
candidates.append(bundleFinderResourceURL?.appendingPathComponent(".."))
#endif
for candidate in candidates {
let bundlePath = candidate?.appendingPathComponent(bundleName + ".bundle")
if let bundle = bundlePath.flatMap(Bundle.init(url:)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ final class TestAcceptanceTests: TuistAcceptanceTestCase {
try await run(TestCommand.self)
}

func test_with_framework_with_spm_bundle() async throws {
try await setUpFixture(.frameworkWithSPMBundle)
try await run(InstallCommand.self)
try await run(TestCommand.self)
}

func test_with_app_with_test_plan() async throws {
try await setUpFixture(.appWithTestPlan)
try await run(TestCommand.self)
Expand Down
31 changes: 31 additions & 0 deletions fixtures/framework_with_spm_bundle/Feature/Project.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import ProjectDescription

let project = Project(
name: "Feature",
targets: [
.target(
name: "Feature",
destinations: .iOS,
product: .framework,
bundleId: "io.tuist.app",
deploymentTargets: .iOS("16.0"),
infoPlist: .default,
sources: "Sources/**",
dependencies: [
.project(target: "SharedUI", path: "../SharedUI"),
]
),
.target(
name: "FeatureTests",
destinations: .iOS,
product: .unitTests,
bundleId: "io.tuist.app.tests",
deploymentTargets: .iOS("16.0"),
infoPlist: .default,
sources: "Tests/**",
dependencies: [
.target(name: "Feature"),
]
),
]
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import SharedUI
import UIKit

public final class FeatureView: UIView {
let textField = PaymentTextField()

override public init(frame: CGRect) {
super.init(frame: frame)
addSubview(textField)
NSLayoutConstraint.activate([
textField.topAnchor.constraint(equalTo: topAnchor),
textField.leadingAnchor.constraint(equalTo: leadingAnchor),
textField.trailingAnchor.constraint(equalTo: trailingAnchor),
textField.bottomAnchor.constraint(equalTo: bottomAnchor),
])
}

@available(*, unavailable)
required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Feature
import XCTest

final class FeatureViewTest: XCTestCase {
func testFeatureView() {
let view = FeatureView()
}
}
19 changes: 19 additions & 0 deletions fixtures/framework_with_spm_bundle/SharedUI/Project.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import ProjectDescription

let project = Project(
name: "SharedUI",
targets: [
.target(
name: "SharedUI",
destinations: .iOS,
product: .framework,
bundleId: "io.tuist.app",
deploymentTargets: .iOS("16.0"),
infoPlist: .default,
sources: "Sources/**",
dependencies: [
.external(name: "Stripe"),
]
),
]
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import StripePaymentsUI
import SwiftUI
import UIKit

public final class PaymentTextField: STPPaymentCardTextField, STPPaymentCardTextFieldDelegate {
public init() {
super.init(frame: .zero)
delegate = self
}

@available(*, unavailable)
public required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

public struct PaymentTextFieldRepresentable: UIViewRepresentable {
public init() {}

public func makeUIView(context _: Context) -> PaymentTextField {
.init()
}

public func updateUIView(_: PaymentTextField, context _: Context) {}
}
15 changes: 15 additions & 0 deletions fixtures/framework_with_spm_bundle/Tuist/Package.resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"originHash" : "b9f3c72bc0a4f32d237e8fe5b2a237ffccde38f6008fc2a64058af8cbf83bf5f",
"pins" : [
{
"identity" : "stripe-ios-spm",
"kind" : "remoteSourceControl",
"location" : "https://github.com/stripe/stripe-ios-spm",
"state" : {
"revision" : "87b6850b5e6a9a6767c5ed4c43c8a84e2191d65f",
"version" : "23.27.3"
}
}
],
"version" : 3
}
9 changes: 9 additions & 0 deletions fixtures/framework_with_spm_bundle/Tuist/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// swift-tools-version: 5.10
@preconcurrency import PackageDescription

let package = Package(
name: "PackageName",
dependencies: [
.package(url: "https://github.com/stripe/stripe-ios-spm", exact: "23.27.3"),
]
)
6 changes: 6 additions & 0 deletions fixtures/framework_with_spm_bundle/Workspace.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import ProjectDescription

let workspace = Workspace(
name: "Workspace",
projects: ["SharedUI", "Feature"]
)

0 comments on commit 30bda6c

Please sign in to comment.