From 3e36e21e42b9fcbc3a3727b3023a1aace1c441e3 Mon Sep 17 00:00:00 2001 From: aaue Date: Sat, 16 Mar 2024 23:32:15 +0900 Subject: [PATCH 1/7] Add initial test case --- App/App.xcodeproj/project.pbxproj | 2 + .../xcshareddata/xcschemes/App.xcscheme | 9 +- App/App/App.xctestplan | 29 +++++ MyLibrary/Package.swift | 7 ++ MyLibrary/Sources/DataClient/Client.swift | 104 ++++++++++++++++++ .../Sources/ScheduleFeature/Schedule.swift | 2 +- .../Sources/SponsorFeature/Sponsors.swift | 2 +- .../Sources/trySwiftFeature/Organizers.swift | 2 +- .../Tests/MyLibraryTests/MyLibraryTests.swift | 13 --- .../ScheduleFeatureTests/ScheduleTests.swift | 23 ++++ 10 files changed, 175 insertions(+), 18 deletions(-) create mode 100644 App/App/App.xctestplan delete mode 100644 MyLibrary/Tests/MyLibraryTests/MyLibraryTests.swift create mode 100644 MyLibrary/Tests/ScheduleFeatureTests/ScheduleTests.swift diff --git a/App/App.xcodeproj/project.pbxproj b/App/App.xcodeproj/project.pbxproj index 5445e6e..37af345 100644 --- a/App/App.xcodeproj/project.pbxproj +++ b/App/App.xcodeproj/project.pbxproj @@ -44,6 +44,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 2435021A2BA49F29000083BB /* App.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = App.xctestplan; sourceTree = ""; }; D563615B2B931FF800E4F789 /* App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = App.app; sourceTree = BUILT_PRODUCTS_DIR; }; D563615E2B931FF800E4F789 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = ""; }; D56361642B931FF900E4F789 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; @@ -106,6 +107,7 @@ D56361662B931FF900E4F789 /* App.entitlements */, D563616A2B931FF900E4F789 /* Info.plist */, D583D7C12B9AD2ED00B94F73 /* PrivacyInfo.xcprivacy */, + 2435021A2BA49F29000083BB /* App.xctestplan */, D56361672B931FF900E4F789 /* Preview Content */, ); path = App; diff --git a/App/App.xcodeproj/xcshareddata/xcschemes/App.xcscheme b/App/App.xcodeproj/xcshareddata/xcschemes/App.xcscheme index 66fd886..d1c6e65 100644 --- a/App/App.xcodeproj/xcshareddata/xcschemes/App.xcscheme +++ b/App/App.xcodeproj/xcshareddata/xcschemes/App.xcscheme @@ -27,8 +27,13 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - shouldUseLaunchSchemeArgsEnv = "YES" - shouldAutocreateTestPlan = "YES"> + shouldUseLaunchSchemeArgsEnv = "YES"> + + + + Data { let filePath = Bundle.module.path(forResource: fileName, ofType: "json")! let fileURL = URL(fileURLWithPath: filePath) @@ -50,6 +52,108 @@ extension DataClient: DependencyKey { } } +extension DependencyValues { + public var dataClient: DataClient { + get { self[DataClient.self] } + set { self[DataClient.self] = newValue } + } +} + +extension Conference { + static let mock1 = Self( + id: 1, + title: "conference1", + date: Date(timeIntervalSince1970: 1_000), + schedules: [ + .init( + time: Date(timeIntervalSince1970: 10_000), + sessions: [ + .mock1, + .mock2, + ] + ) + ] + ) + + static let mock2 = Self( + id: 2, + title: "conference2", + date: Date(timeIntervalSince1970: 2_000), + schedules: [ + .init( + time: Date(timeIntervalSince1970: 20_000), + sessions: [ + .mock1, + .mock2 + ] + ) + ] + ) + + static let mock3 = Self( + id: 3, + title: "conference3", + date: Date(timeIntervalSince1970: 3_000), + schedules: [ + .init( + time: Date(timeIntervalSince1970: 30_000), + sessions: [ + .mock1, + .mock2 + ] + ) + ] + ) +} + +extension Session { + static let mock1 = Self( + title: "session1", + speakers: [ + .mock1 + ], + place: "place1", + description: "description1", + requirements: "requirements1" + ) + + static let mock2 = Self( + title: "session2", + speakers: [ + .mock2 + ], + place: "place2", + description: "description2", + requirements: "requirements2" + ) +} + +extension Speaker { + static let mock1 = Self( + name: "speaker1", + imageName: "image1", + bio: "bio1", + links: [ + .init( + name: "sns1", + url: URL(string: "https://example.com/speaker1")! + ) + ] + ) + + static let mock2 = Self( + name: "speaker2", + imageName: "image2", + bio: "bio2", + links: [ + .init( + name: "sns2", + url: URL(string: "https://example.com/speaker2")! + ) + ] + ) +} + let jsonDecoder = { $0.dateDecodingStrategy = .iso8601 $0.keyDecodingStrategy = .convertFromSnakeCase diff --git a/MyLibrary/Sources/ScheduleFeature/Schedule.swift b/MyLibrary/Sources/ScheduleFeature/Schedule.swift index 8786f2e..0ff7b97 100644 --- a/MyLibrary/Sources/ScheduleFeature/Schedule.swift +++ b/MyLibrary/Sources/ScheduleFeature/Schedule.swift @@ -56,7 +56,7 @@ public struct Schedule { case guidance(Safari) } - @Dependency(DataClient.self) var dataClient + @Dependency(\.dataClient) var dataClient @Dependency(\.openURL) var openURL public init() {} diff --git a/MyLibrary/Sources/SponsorFeature/Sponsors.swift b/MyLibrary/Sources/SponsorFeature/Sponsors.swift index c26932f..215a172 100644 --- a/MyLibrary/Sources/SponsorFeature/Sponsors.swift +++ b/MyLibrary/Sources/SponsorFeature/Sponsors.swift @@ -31,7 +31,7 @@ public struct SponsorsList { public init() {} - @Dependency(DataClient.self) var dataClient + @Dependency(\.dataClient) var dataClient @Dependency(\.openURL) var openURL public var body: some ReducerOf { diff --git a/MyLibrary/Sources/trySwiftFeature/Organizers.swift b/MyLibrary/Sources/trySwiftFeature/Organizers.swift index 7af0af7..2c2d680 100644 --- a/MyLibrary/Sources/trySwiftFeature/Organizers.swift +++ b/MyLibrary/Sources/trySwiftFeature/Organizers.swift @@ -31,7 +31,7 @@ public struct Organizers { case profile(Profile) } - @Dependency(DataClient.self) var dataClient + @Dependency(\.dataClient) var dataClient public var body: some ReducerOf { Reduce { state, action in diff --git a/MyLibrary/Tests/MyLibraryTests/MyLibraryTests.swift b/MyLibrary/Tests/MyLibraryTests/MyLibraryTests.swift deleted file mode 100644 index 1d87eb2..0000000 --- a/MyLibrary/Tests/MyLibraryTests/MyLibraryTests.swift +++ /dev/null @@ -1,13 +0,0 @@ -import XCTest - -@testable import MyLibrary - -final class MyLibraryTests: XCTestCase { - func testExample() throws { - // XCTest Documentation - // https://developer.apple.com/documentation/xctest - - // Defining Test Cases and Test Methods - // https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods - } -} diff --git a/MyLibrary/Tests/ScheduleFeatureTests/ScheduleTests.swift b/MyLibrary/Tests/ScheduleFeatureTests/ScheduleTests.swift new file mode 100644 index 0000000..937d51e --- /dev/null +++ b/MyLibrary/Tests/ScheduleFeatureTests/ScheduleTests.swift @@ -0,0 +1,23 @@ +import ComposableArchitecture +import XCTest + +@testable import DataClient +@testable import ScheduleFeature + +final class ScheduleTests: XCTestCase { + @MainActor + func testFetchData() async { + let store = TestStore(initialState: Schedule.State()) { + Schedule() + } withDependencies: { + $0.dataClient.fetchDay1 = { @Sendable in .mock1 } + $0.dataClient.fetchDay2 = { @Sendable in .mock2 } + $0.dataClient.fetchWorkshop = { @Sendable in .mock3 } + } + await store.send(.view(.onAppear)) { + $0.day1 = .mock1 + $0.day2 = .mock2 + $0.workshop = .mock3 + } + } +} From 7ac27fd3dd46373527e1a5d475254c9a6aa79ecb Mon Sep 17 00:00:00 2001 From: aaue Date: Sat, 16 Mar 2024 23:34:05 +0900 Subject: [PATCH 2/7] Add a negative test case --- .../Sources/ScheduleFeature/Schedule.swift | 21 ++++++++++++++----- .../ScheduleFeatureTests/ScheduleTests.swift | 17 ++++++++++++++- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/MyLibrary/Sources/ScheduleFeature/Schedule.swift b/MyLibrary/Sources/ScheduleFeature/Schedule.swift index 0ff7b97..307dd26 100644 --- a/MyLibrary/Sources/ScheduleFeature/Schedule.swift +++ b/MyLibrary/Sources/ScheduleFeature/Schedule.swift @@ -29,7 +29,7 @@ public struct Schedule { @Presents var destination: Destination.State? public init() { - try! Tips.configure([.displayFrequency(.immediate)]) + try? Tips.configure([.displayFrequency(.immediate)]) } } @@ -38,6 +38,7 @@ public struct Schedule { case path(StackAction) case destination(PresentationAction) case view(View) + case fetchResponse(Result<(Conference, Conference, Conference), Error>) public enum View { case onAppear @@ -66,10 +67,12 @@ public struct Schedule { Reduce { state, action in switch action { case .view(.onAppear): - state.day1 = try! dataClient.fetchDay1() - state.day2 = try! dataClient.fetchDay2() - state.workshop = try! dataClient.fetchWorkshop() - return .none + return .send(.fetchResponse(Result { + let day1 = try dataClient.fetchDay1() + let day2 = try dataClient.fetchDay2() + let workshop = try dataClient.fetchWorkshop() + return (day1, day2, workshop) + })) case let .view(.disclosureTapped(session)): guard let description = session.description, let speakers = session.speakers else { return .none @@ -93,6 +96,14 @@ public struct Schedule { #elseif os(visionOS) return .run { _ in await openURL(url) } #endif + case let .fetchResponse(.success((day1, day2, workshop))): + state.day1 = day1 + state.day2 = day2 + state.workshop = workshop + return .none + case let .fetchResponse(.failure(error)): + print(error) + return .none case .binding, .path, .destination: return .none } diff --git a/MyLibrary/Tests/ScheduleFeatureTests/ScheduleTests.swift b/MyLibrary/Tests/ScheduleFeatureTests/ScheduleTests.swift index 937d51e..4b6198b 100644 --- a/MyLibrary/Tests/ScheduleFeatureTests/ScheduleTests.swift +++ b/MyLibrary/Tests/ScheduleFeatureTests/ScheduleTests.swift @@ -14,10 +14,25 @@ final class ScheduleTests: XCTestCase { $0.dataClient.fetchDay2 = { @Sendable in .mock2 } $0.dataClient.fetchWorkshop = { @Sendable in .mock3 } } - await store.send(.view(.onAppear)) { + await store.send(.view(.onAppear)) + await store.receive(\.fetchResponse.success) { $0.day1 = .mock1 $0.day2 = .mock2 $0.workshop = .mock3 } } + + @MainActor + func testFetchDataFailure() async { + struct FetchError: Equatable, Error {} + let store = TestStore(initialState: Schedule.State()) { + Schedule() + } withDependencies: { + $0.dataClient.fetchDay1 = { @Sendable in throw FetchError() } + $0.dataClient.fetchDay2 = { @Sendable in .mock2 } + $0.dataClient.fetchWorkshop = { @Sendable in .mock3 } + } + await store.send(.view(.onAppear)) + await store.receive(\.fetchResponse.failure) + } } From 6f8eb3f55d3f5755a228e042e1cb14346ef9e735 Mon Sep 17 00:00:00 2001 From: aaue Date: Sun, 17 Mar 2024 10:02:20 +0900 Subject: [PATCH 3/7] Back to Dependency Client style --- MyLibrary/Sources/DataClient/Client.swift | 7 ------- MyLibrary/Sources/ScheduleFeature/Schedule.swift | 2 +- MyLibrary/Sources/SponsorFeature/Sponsors.swift | 2 +- MyLibrary/Sources/trySwiftFeature/Organizers.swift | 2 +- .../Tests/ScheduleFeatureTests/ScheduleTests.swift | 12 ++++++------ 5 files changed, 9 insertions(+), 16 deletions(-) diff --git a/MyLibrary/Sources/DataClient/Client.swift b/MyLibrary/Sources/DataClient/Client.swift index 4745705..2fbc7a4 100644 --- a/MyLibrary/Sources/DataClient/Client.swift +++ b/MyLibrary/Sources/DataClient/Client.swift @@ -52,13 +52,6 @@ extension DataClient: DependencyKey { } } -extension DependencyValues { - public var dataClient: DataClient { - get { self[DataClient.self] } - set { self[DataClient.self] = newValue } - } -} - extension Conference { static let mock1 = Self( id: 1, diff --git a/MyLibrary/Sources/ScheduleFeature/Schedule.swift b/MyLibrary/Sources/ScheduleFeature/Schedule.swift index 307dd26..e0c9325 100644 --- a/MyLibrary/Sources/ScheduleFeature/Schedule.swift +++ b/MyLibrary/Sources/ScheduleFeature/Schedule.swift @@ -57,7 +57,7 @@ public struct Schedule { case guidance(Safari) } - @Dependency(\.dataClient) var dataClient + @Dependency(DataClient.self) var dataClient @Dependency(\.openURL) var openURL public init() {} diff --git a/MyLibrary/Sources/SponsorFeature/Sponsors.swift b/MyLibrary/Sources/SponsorFeature/Sponsors.swift index 215a172..c26932f 100644 --- a/MyLibrary/Sources/SponsorFeature/Sponsors.swift +++ b/MyLibrary/Sources/SponsorFeature/Sponsors.swift @@ -31,7 +31,7 @@ public struct SponsorsList { public init() {} - @Dependency(\.dataClient) var dataClient + @Dependency(DataClient.self) var dataClient @Dependency(\.openURL) var openURL public var body: some ReducerOf { diff --git a/MyLibrary/Sources/trySwiftFeature/Organizers.swift b/MyLibrary/Sources/trySwiftFeature/Organizers.swift index 2c2d680..7af0af7 100644 --- a/MyLibrary/Sources/trySwiftFeature/Organizers.swift +++ b/MyLibrary/Sources/trySwiftFeature/Organizers.swift @@ -31,7 +31,7 @@ public struct Organizers { case profile(Profile) } - @Dependency(\.dataClient) var dataClient + @Dependency(DataClient.self) var dataClient public var body: some ReducerOf { Reduce { state, action in diff --git a/MyLibrary/Tests/ScheduleFeatureTests/ScheduleTests.swift b/MyLibrary/Tests/ScheduleFeatureTests/ScheduleTests.swift index 4b6198b..5b28105 100644 --- a/MyLibrary/Tests/ScheduleFeatureTests/ScheduleTests.swift +++ b/MyLibrary/Tests/ScheduleFeatureTests/ScheduleTests.swift @@ -10,9 +10,9 @@ final class ScheduleTests: XCTestCase { let store = TestStore(initialState: Schedule.State()) { Schedule() } withDependencies: { - $0.dataClient.fetchDay1 = { @Sendable in .mock1 } - $0.dataClient.fetchDay2 = { @Sendable in .mock2 } - $0.dataClient.fetchWorkshop = { @Sendable in .mock3 } + $0[DataClient.self].fetchDay1 = { @Sendable in .mock1 } + $0[DataClient.self].fetchDay2 = { @Sendable in .mock2 } + $0[DataClient.self].fetchWorkshop = { @Sendable in .mock3 } } await store.send(.view(.onAppear)) await store.receive(\.fetchResponse.success) { @@ -28,9 +28,9 @@ final class ScheduleTests: XCTestCase { let store = TestStore(initialState: Schedule.State()) { Schedule() } withDependencies: { - $0.dataClient.fetchDay1 = { @Sendable in throw FetchError() } - $0.dataClient.fetchDay2 = { @Sendable in .mock2 } - $0.dataClient.fetchWorkshop = { @Sendable in .mock3 } + $0[DataClient.self].fetchDay1 = { @Sendable in throw FetchError() } + $0[DataClient.self].fetchDay2 = { @Sendable in .mock2 } + $0[DataClient.self].fetchWorkshop = { @Sendable in .mock3 } } await store.send(.view(.onAppear)) await store.receive(\.fetchResponse.failure) From e13d8b1ccc131a9271fb0327904da1afd3852262 Mon Sep 17 00:00:00 2001 From: aaue Date: Sun, 17 Mar 2024 10:06:03 +0900 Subject: [PATCH 4/7] Move mock to test --- MyLibrary/Sources/DataClient/Client.swift | 95 ------------------ .../Tests/ScheduleFeatureTests/Mocks.swift | 97 +++++++++++++++++++ .../ScheduleFeatureTests/ScheduleTests.swift | 2 +- 3 files changed, 98 insertions(+), 96 deletions(-) create mode 100644 MyLibrary/Tests/ScheduleFeatureTests/Mocks.swift diff --git a/MyLibrary/Sources/DataClient/Client.swift b/MyLibrary/Sources/DataClient/Client.swift index 2fbc7a4..9d8b1e4 100644 --- a/MyLibrary/Sources/DataClient/Client.swift +++ b/MyLibrary/Sources/DataClient/Client.swift @@ -52,101 +52,6 @@ extension DataClient: DependencyKey { } } -extension Conference { - static let mock1 = Self( - id: 1, - title: "conference1", - date: Date(timeIntervalSince1970: 1_000), - schedules: [ - .init( - time: Date(timeIntervalSince1970: 10_000), - sessions: [ - .mock1, - .mock2, - ] - ) - ] - ) - - static let mock2 = Self( - id: 2, - title: "conference2", - date: Date(timeIntervalSince1970: 2_000), - schedules: [ - .init( - time: Date(timeIntervalSince1970: 20_000), - sessions: [ - .mock1, - .mock2 - ] - ) - ] - ) - - static let mock3 = Self( - id: 3, - title: "conference3", - date: Date(timeIntervalSince1970: 3_000), - schedules: [ - .init( - time: Date(timeIntervalSince1970: 30_000), - sessions: [ - .mock1, - .mock2 - ] - ) - ] - ) -} - -extension Session { - static let mock1 = Self( - title: "session1", - speakers: [ - .mock1 - ], - place: "place1", - description: "description1", - requirements: "requirements1" - ) - - static let mock2 = Self( - title: "session2", - speakers: [ - .mock2 - ], - place: "place2", - description: "description2", - requirements: "requirements2" - ) -} - -extension Speaker { - static let mock1 = Self( - name: "speaker1", - imageName: "image1", - bio: "bio1", - links: [ - .init( - name: "sns1", - url: URL(string: "https://example.com/speaker1")! - ) - ] - ) - - static let mock2 = Self( - name: "speaker2", - imageName: "image2", - bio: "bio2", - links: [ - .init( - name: "sns2", - url: URL(string: "https://example.com/speaker2")! - ) - ] - ) -} - let jsonDecoder = { $0.dateDecodingStrategy = .iso8601 $0.keyDecodingStrategy = .convertFromSnakeCase diff --git a/MyLibrary/Tests/ScheduleFeatureTests/Mocks.swift b/MyLibrary/Tests/ScheduleFeatureTests/Mocks.swift new file mode 100644 index 0000000..c54bee9 --- /dev/null +++ b/MyLibrary/Tests/ScheduleFeatureTests/Mocks.swift @@ -0,0 +1,97 @@ +import Foundation +import SharedModels + +extension Conference { + static let mock1 = Self( + id: 1, + title: "conference1", + date: Date(timeIntervalSince1970: 1_000), + schedules: [ + .init( + time: Date(timeIntervalSince1970: 10_000), + sessions: [ + .mock1, + .mock2, + ] + ) + ] + ) + + static let mock2 = Self( + id: 2, + title: "conference2", + date: Date(timeIntervalSince1970: 2_000), + schedules: [ + .init( + time: Date(timeIntervalSince1970: 20_000), + sessions: [ + .mock1, + .mock2 + ] + ) + ] + ) + + static let mock3 = Self( + id: 3, + title: "conference3", + date: Date(timeIntervalSince1970: 3_000), + schedules: [ + .init( + time: Date(timeIntervalSince1970: 30_000), + sessions: [ + .mock1, + .mock2 + ] + ) + ] + ) +} + +extension Session { + static let mock1 = Self( + title: "session1", + speakers: [ + .mock1 + ], + place: "place1", + description: "description1", + requirements: "requirements1" + ) + + static let mock2 = Self( + title: "session2", + speakers: [ + .mock2 + ], + place: "place2", + description: "description2", + requirements: "requirements2" + ) +} + +extension Speaker { + static let mock1 = Self( + name: "speaker1", + imageName: "image1", + bio: "bio1", + links: [ + .init( + name: "sns1", + url: URL(string: "https://example.com/speaker1")! + ) + ] + ) + + static let mock2 = Self( + name: "speaker2", + imageName: "image2", + bio: "bio2", + links: [ + .init( + name: "sns2", + url: URL(string: "https://example.com/speaker2")! + ) + ] + ) +} diff --git a/MyLibrary/Tests/ScheduleFeatureTests/ScheduleTests.swift b/MyLibrary/Tests/ScheduleFeatureTests/ScheduleTests.swift index 5b28105..f0f0954 100644 --- a/MyLibrary/Tests/ScheduleFeatureTests/ScheduleTests.swift +++ b/MyLibrary/Tests/ScheduleFeatureTests/ScheduleTests.swift @@ -1,7 +1,7 @@ import ComposableArchitecture +import DataClient import XCTest -@testable import DataClient @testable import ScheduleFeature final class ScheduleTests: XCTestCase { From bce291a78be35a3e0deac5f3b062f9ac7d13c09a Mon Sep 17 00:00:00 2001 From: kwzr Date: Sun, 17 Mar 2024 20:40:38 +0900 Subject: [PATCH 5/7] Update MyLibrary/Sources/ScheduleFeature/Schedule.swift Co-authored-by: Daiki Matsudate --- MyLibrary/Sources/ScheduleFeature/Schedule.swift | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/MyLibrary/Sources/ScheduleFeature/Schedule.swift b/MyLibrary/Sources/ScheduleFeature/Schedule.swift index e0c9325..89a44d0 100644 --- a/MyLibrary/Sources/ScheduleFeature/Schedule.swift +++ b/MyLibrary/Sources/ScheduleFeature/Schedule.swift @@ -101,8 +101,11 @@ public struct Schedule { state.day2 = day2 state.workshop = workshop return .none + case let .fetchResponse(.failure(error as DecodingError)): + assertionFailure(error.localizedDescription) + return .none case let .fetchResponse(.failure(error)): - print(error) + print(error) // TODO: replace to Logger API return .none case .binding, .path, .destination: return .none From 78a993e39feea7ac738610fcd58e26bac249d67c Mon Sep 17 00:00:00 2001 From: aaue Date: Sun, 17 Mar 2024 20:43:25 +0900 Subject: [PATCH 6/7] Remove testValue = Self() --- MyLibrary/Sources/DataClient/Client.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/MyLibrary/Sources/DataClient/Client.swift b/MyLibrary/Sources/DataClient/Client.swift index 9d8b1e4..0bb4377 100644 --- a/MyLibrary/Sources/DataClient/Client.swift +++ b/MyLibrary/Sources/DataClient/Client.swift @@ -42,8 +42,6 @@ extension DataClient: DependencyKey { } ) - static public let testValue = Self() - static func loadDataFromBundle(fileName: String) -> Data { let filePath = Bundle.module.path(forResource: fileName, ofType: "json")! let fileURL = URL(fileURLWithPath: filePath) From 27d94bec22ad279025a997a08abaf41c1d5810c7 Mon Sep 17 00:00:00 2001 From: aaue Date: Sun, 17 Mar 2024 20:48:49 +0900 Subject: [PATCH 7/7] Create struct for response --- .../Sources/ScheduleFeature/Schedule.swift | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/MyLibrary/Sources/ScheduleFeature/Schedule.swift b/MyLibrary/Sources/ScheduleFeature/Schedule.swift index 89a44d0..8e92b88 100644 --- a/MyLibrary/Sources/ScheduleFeature/Schedule.swift +++ b/MyLibrary/Sources/ScheduleFeature/Schedule.swift @@ -16,6 +16,12 @@ public struct Schedule { var id: Self { self } } + public struct SchedulesResponse: Equatable { + var day1: Conference + var day2: Conference + var workshop: Conference + } + @ObservableState public struct State: Equatable { @@ -38,7 +44,7 @@ public struct Schedule { case path(StackAction) case destination(PresentationAction) case view(View) - case fetchResponse(Result<(Conference, Conference, Conference), Error>) + case fetchResponse(Result) public enum View { case onAppear @@ -71,7 +77,7 @@ public struct Schedule { let day1 = try dataClient.fetchDay1() let day2 = try dataClient.fetchDay2() let workshop = try dataClient.fetchWorkshop() - return (day1, day2, workshop) + return .init(day1: day1, day2: day2, workshop: workshop) })) case let .view(.disclosureTapped(session)): guard let description = session.description, let speakers = session.speakers else { @@ -96,10 +102,10 @@ public struct Schedule { #elseif os(visionOS) return .run { _ in await openURL(url) } #endif - case let .fetchResponse(.success((day1, day2, workshop))): - state.day1 = day1 - state.day2 = day2 - state.workshop = workshop + case let .fetchResponse(.success(response)): + state.day1 = response.day1 + state.day2 = response.day2 + state.workshop = response.workshop return .none case let .fetchResponse(.failure(error as DecodingError)): assertionFailure(error.localizedDescription)