From a3fb997f3aa174f31e582dc988048943b2cafd5e Mon Sep 17 00:00:00 2001 From: Takehiro Kaneko Date: Tue, 26 Mar 2024 16:19:36 +0900 Subject: [PATCH] Add trySwiftTests (#51) --- App/App/App.xctestplan | 7 + MyLibrary/Package.swift | 8 + .../Sources/trySwiftFeature/Organizers.swift | 9 ++ .../Sources/trySwiftFeature/trySwift.swift | 8 +- .../Tests/trySwiftFeatureTests/Mocks.swift | 30 ++++ .../trySwiftFeatureTests/trySwiftTests.swift | 143 ++++++++++++++++++ 6 files changed, 204 insertions(+), 1 deletion(-) create mode 100644 MyLibrary/Tests/trySwiftFeatureTests/Mocks.swift create mode 100644 MyLibrary/Tests/trySwiftFeatureTests/trySwiftTests.swift diff --git a/App/App/App.xctestplan b/App/App/App.xctestplan index 91bc0ce..5a84bfb 100644 --- a/App/App/App.xctestplan +++ b/App/App/App.xctestplan @@ -30,6 +30,13 @@ "identifier" : "SponsorFeatureTests", "name" : "SponsorFeatureTests" } + }, + { + "target" : { + "containerPath" : "container:..\/MyLibrary", + "identifier" : "trySwiftFeatureTests", + "name" : "trySwiftFeatureTests" + } } ], "version" : 1 diff --git a/MyLibrary/Package.swift b/MyLibrary/Package.swift index 62fed8c..b7c19ff 100644 --- a/MyLibrary/Package.swift +++ b/MyLibrary/Package.swift @@ -104,5 +104,13 @@ let package = Package( .product(name: "ComposableArchitecture", package: "swift-composable-architecture"), ] ), + .testTarget( + name: "trySwiftFeatureTests", + dependencies: [ + "trySwiftFeature", + "SharedModels", + .product(name: "ComposableArchitecture", package: "swift-composable-architecture"), + ] + ), ] ) diff --git a/MyLibrary/Sources/trySwiftFeature/Organizers.swift b/MyLibrary/Sources/trySwiftFeature/Organizers.swift index 7af0af7..67819c7 100644 --- a/MyLibrary/Sources/trySwiftFeature/Organizers.swift +++ b/MyLibrary/Sources/trySwiftFeature/Organizers.swift @@ -9,6 +9,14 @@ public struct Organizers { public struct State: Equatable { var organizers = IdentifiedArrayOf() @Presents var destination: Destination.State? + + public init( + organizers: IdentifiedArrayOf = [], + destination: Destination.State? = nil + ) { + self.organizers = organizers + self.destination = destination + } } public enum Action: ViewAction { @@ -21,6 +29,7 @@ public struct Organizers { case _organizerTapped(Organizer) } + @CasePathable public enum Delegate { case organizerTapped(Organizer) } diff --git a/MyLibrary/Sources/trySwiftFeature/trySwift.swift b/MyLibrary/Sources/trySwiftFeature/trySwift.swift index 71ddcea..7175a0f 100644 --- a/MyLibrary/Sources/trySwiftFeature/trySwift.swift +++ b/MyLibrary/Sources/trySwiftFeature/trySwift.swift @@ -9,7 +9,12 @@ public struct TrySwift { @ObservableState public struct State: Equatable { var path = StackState() - public init() {} + + public init( + path: StackState = .init() + ) { + self.path = path + } } public enum Action: BindableAction, ViewAction { @@ -17,6 +22,7 @@ public struct TrySwift { case binding(BindingAction) case view(View) + @CasePathable public enum View { case organizerTapped case codeOfConductTapped diff --git a/MyLibrary/Tests/trySwiftFeatureTests/Mocks.swift b/MyLibrary/Tests/trySwiftFeatureTests/Mocks.swift new file mode 100644 index 0000000..082cb5d --- /dev/null +++ b/MyLibrary/Tests/trySwiftFeatureTests/Mocks.swift @@ -0,0 +1,30 @@ +import Foundation +import SharedModels + +extension Organizer { + static let alice = Self( + id: 1, + name: "alice", + imageName: "Alice", + bio: "", + links: [ + Link( + name: "@alice", + url: URL(string: "https://example.com/alice")! + ) + ] + ) + + static let bob = Self( + id: 2, + name: "bob", + imageName: "Bob", + bio: "", + links: [ + Link( + name: "@bob", + url: URL(string: "https://example.com/bob")! + ) + ] + ) +} diff --git a/MyLibrary/Tests/trySwiftFeatureTests/trySwiftTests.swift b/MyLibrary/Tests/trySwiftFeatureTests/trySwiftTests.swift new file mode 100644 index 0000000..c197321 --- /dev/null +++ b/MyLibrary/Tests/trySwiftFeatureTests/trySwiftTests.swift @@ -0,0 +1,143 @@ +import ComposableArchitecture +import SharedModels +import DependencyExtra +import XCTest + +@testable import trySwiftFeature + +final class trySwiftTests: XCTestCase { + @MainActor + func testOrganizerTapped() async { + let store = TestStore(initialState: TrySwift.State()) { + TrySwift() + } + + await store.send(\.view.organizerTapped) { + $0.path[id: 0] = .organizers(.init()) + } + } + + @MainActor + func testCodeOfConductTapped() async { + let receivedUrl = ActorIsolated(nil) + + let store = TestStore(initialState: TrySwift.State()) { + TrySwift() + } withDependencies: { + $0.safari = { @Sendable in + SafariEffect { url in + await receivedUrl.withValue { + $0 = url + return true + } + } + }() + } + + await store.send(\.view.codeOfConductTapped) + await receivedUrl.withValue { + XCTAssertEqual($0, URL(string: "https://tryswift.jp/code-of-conduct_en")!) + } + } + + @MainActor + func testPrivacyPolicyTapped() async { + let receivedUrl = ActorIsolated(nil) + + let store = TestStore(initialState: TrySwift.State()) { + TrySwift() + } withDependencies: { + $0.safari = { @Sendable in + SafariEffect { url in + await receivedUrl.withValue { + $0 = url + return true + } + } + }() + } + + await store.send(\.view.privacyPolicyTapped) + await receivedUrl.withValue { + XCTAssertEqual($0, URL(string: "https://tryswift.jp/privacy-policy_en")!) + } + } + + @MainActor + func testAcknowledgementsTapped() async { + let store = TestStore(initialState: TrySwift.State()) { + TrySwift() + } + + await store.send(\.view.acknowledgementsTapped) { + $0.path[id: 0] = .acknowledgements(.init()) + } + } + + @MainActor + func testEventBriteTapped() async { + let receivedUrl = ActorIsolated(nil) + + let store = TestStore(initialState: TrySwift.State()) { + TrySwift() + } withDependencies: { + $0.safari = { @Sendable in + SafariEffect { url in + await receivedUrl.withValue { + $0 = url + return true + } + } + }() + } + + await store.send(\.view.eventbriteTapped) + await receivedUrl.withValue { + XCTAssertEqual($0, URL(string: "https://www.eventbrite.com/e/try-swift-tokyo-2024-tickets-712565200697")!) + } + } + + @MainActor + func testWebsiteTapped() async { + let receivedUrl = ActorIsolated(nil) + + let store = TestStore(initialState: TrySwift.State()) { + TrySwift() + } withDependencies: { + $0.safari = { @Sendable in + SafariEffect { url in + await receivedUrl.withValue { + $0 = url + return true + } + } + }() + } + + await store.send(\.view.websiteTapped) + await receivedUrl.withValue { + XCTAssertEqual($0, URL(string: "https://tryswift.jp/_en")!) + } + } + + @MainActor + func testProfileNavigation() async { + let store = TestStore( + initialState: TrySwift.State( + path: StackState([ + .organizers( + Organizers.State( + organizers: .init(arrayLiteral: .alice, .bob) + ) + ) + ]) + ) + ) { + TrySwift() + } + + await store.send(\.path[id: 0].organizers.delegate.organizerTapped, .alice) { + $0.path[id: 1] = .profile(.init(organizer: .alice)) + } + } +}