Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add initial test cases #38

Merged
merged 7 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions App/App.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
2435021A2BA49F29000083BB /* App.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = App.xctestplan; sourceTree = "<group>"; };
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 = "<group>"; };
D56361642B931FF900E4F789 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
Expand Down Expand Up @@ -106,6 +107,7 @@
D56361662B931FF900E4F789 /* App.entitlements */,
D563616A2B931FF900E4F789 /* Info.plist */,
D583D7C12B9AD2ED00B94F73 /* PrivacyInfo.xcprivacy */,
2435021A2BA49F29000083BB /* App.xctestplan */,
D56361672B931FF900E4F789 /* Preview Content */,
);
path = App;
Expand Down
9 changes: 7 additions & 2 deletions App/App.xcodeproj/xcshareddata/xcschemes/App.xcscheme
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,13 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
shouldUseLaunchSchemeArgsEnv = "YES">
<TestPlans>
<TestPlanReference
reference = "container:App/App.xctestplan"
default = "YES">
</TestPlanReference>
</TestPlans>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
Expand Down
29 changes: 29 additions & 0 deletions App/App/App.xctestplan
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"configurations" : [
{
"id" : "235E58B3-6724-418C-907A-6211C4CC541B",
"name" : "Test Scheme Action",
"options" : {

}
}
],
"defaultOptions" : {
"codeCoverage" : false,
"targetForVariableExpansion" : {
"containerPath" : "container:App.xcodeproj",
"identifier" : "D563615A2B931FF800E4F789",
"name" : "App"
}
},
"testTargets" : [
{
"target" : {
"containerPath" : "container:..\/MyLibrary",
"identifier" : "ScheduleFeatureTests",
"name" : "ScheduleFeatureTests"
}
}
],
"version" : 1
}
7 changes: 7 additions & 0 deletions MyLibrary/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,12 @@ let package = Package(
.plugin(name: "LicenseProviderPlugin", package: "LicenseProvider")
]
),
.testTarget(
name: "ScheduleFeatureTests",
dependencies: [
"ScheduleFeature",
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
]
),
]
)
104 changes: 104 additions & 0 deletions MyLibrary/Sources/DataClient/Client.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ extension DataClient: DependencyKey {
}
)

static public let testValue = Self()

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also macro's roll

static func loadDataFromBundle(fileName: String) -> Data {
let filePath = Bundle.module.path(forResource: fileName, ofType: "json")!
let fileURL = URL(fileURLWithPath: filePath)
Expand All @@ -50,6 +52,108 @@ extension DataClient: DependencyKey {
}
}

extension DependencyValues {
public var dataClient: DataClient {
get { self[DataClient.self] }
set { self[DataClient.self] = newValue }
}
}
kvvzr marked this conversation as resolved.
Show resolved Hide resolved

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
]
)
kvvzr marked this conversation as resolved.
Show resolved Hide resolved
]
)
}

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")!
)
]
)
}

kvvzr marked this conversation as resolved.
Show resolved Hide resolved
let jsonDecoder = {
$0.dateDecodingStrategy = .iso8601
$0.keyDecodingStrategy = .convertFromSnakeCase
Expand Down
23 changes: 17 additions & 6 deletions MyLibrary/Sources/ScheduleFeature/Schedule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public struct Schedule {
@Presents var destination: Destination.State?

public init() {
try! Tips.configure([.displayFrequency(.immediate)])
try? Tips.configure([.displayFrequency(.immediate)])
}
}

Expand All @@ -38,6 +38,7 @@ public struct Schedule {
case path(StackAction<Path.State, Path.Action>)
case destination(PresentationAction<Destination.Action>)
case view(View)
case fetchResponse(Result<(Conference, Conference, Conference), Error>)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be better with creating struct.

Suggested change
case fetchResponse(Result<(Conference, Conference, Conference), Error>)
case fetchResponse(Result<SchedulesResponse, Error>)

The struct may be like below:

public struct SchedulesResponse: Equatable {
  var day1: Conference
  var day2: Conference
  var workshop: Conference
}


public enum View {
case onAppear
Expand All @@ -56,7 +57,7 @@ public struct Schedule {
case guidance(Safari)
}

@Dependency(DataClient.self) var dataClient
@Dependency(\.dataClient) var dataClient
@Dependency(\.openURL) var openURL

public init() {}
Expand All @@ -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
Expand All @@ -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
kvvzr marked this conversation as resolved.
Show resolved Hide resolved
case .binding, .path, .destination:
return .none
}
Expand Down
2 changes: 1 addition & 1 deletion MyLibrary/Sources/SponsorFeature/Sponsors.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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<Self> {
Expand Down
2 changes: 1 addition & 1 deletion MyLibrary/Sources/trySwiftFeature/Organizers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public struct Organizers {
case profile(Profile)
}

@Dependency(DataClient.self) var dataClient
@Dependency(\.dataClient) var dataClient

public var body: some ReducerOf<Organizers> {
Reduce { state, action in
Expand Down
13 changes: 0 additions & 13 deletions MyLibrary/Tests/MyLibraryTests/MyLibraryTests.swift

This file was deleted.

38 changes: 38 additions & 0 deletions MyLibrary/Tests/ScheduleFeatureTests/ScheduleTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
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))
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)
}
}