Skip to content

Commit

Permalink
chore: support empty load request and no child feature (#23)
Browse files Browse the repository at this point in the history
Co-authored-by: danthorpe <[email protected]>
  • Loading branch information
danthorpe and danthorpe authored Oct 10, 2024
1 parent a79b310 commit 3b6be21
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 1 deletion.
21 changes: 21 additions & 0 deletions Sources/CommonTestHelpers/ParentFeature.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,24 @@ struct ChildlessFeature {
}
}
}

@Reducer
struct ChildlessRandomFeature {
@ObservableState
struct State: Equatable {
@ObservationStateIgnored
@LoadableState<EmptyLoadRequest, Int> package var counterValue
}
enum Action: Equatable {
case counterValue(LoadingAction<EmptyLoadRequest, Int, NoLoadingAction>)
}
@Dependency(\.testClient.getRandomValue) var getRandomValue
var body: some ReducerOf<Self> {
Reduce { _, _ in
return .none
}
.loadable(\.$counterValue, action: \.counterValue) { _ in
try await getRandomValue()
}
}
}
23 changes: 22 additions & 1 deletion Sources/ComposableLoadable/Loadable/LoadingReducer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ extension Reducer where State: Sendable {
)
}

/// Integrate some LoadableState which does not require a child domain
/// Integrate some LoadableState which does not require a child domain with a generic Request type
public func loadable<
ChildState: Sendable,
Request: Sendable
Expand All @@ -75,6 +75,27 @@ extension Reducer where State: Sendable {
line: line
)
}

/// Integrate some LoadableState which does not require a child domain nor a Request type
public func loadable<
ChildState: Sendable
>(
_ toLoadableState: WritableKeyPath<State, LoadableState<EmptyLoadRequest, ChildState>>,
action toLoadingAction: CaseKeyPath<Action, LoadingAction<EmptyLoadRequest, ChildState, NoLoadingAction>>,
load: @escaping @Sendable (State) async throws -> ChildState,
fileID: StaticString = #fileID,
line: UInt = #line
) -> some ReducerOf<Self> {
LoadingReducer(
parent: self,
child: EmptyReducer(),
toLoadableState: toLoadableState,
toLoadingAction: toLoadingAction,
client: LoadingClient(load: load),
fileID: fileID,
line: line
)
}
}

// MARK: - Internal API
Expand Down
19 changes: 19 additions & 0 deletions Tests/ComposableLoadableTests/LoadableReducerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,25 @@ final class ReducerBasicTests: XCTestCase {
) {
$0.$counterValue.finish(request, result: Result(result))
}
}

@MainActor func test__no_request_no_child_domain() async throws {
let randomInt = Int.random(in: 0 ... Int.max)
let store = TestStore(initialState: ChildlessRandomFeature.State()) {
ChildlessRandomFeature()
} withDependencies: {
$0.testClient.getRandomValue = {
randomInt
}
}
await store.send(.counterValue(.load)) {
$0.$counterValue.becomeActive()
}
let result = await TaskResult { randomInt }
await store.receive(
.counterValue(.finished(EmptyLoadRequest(), didRefresh: false, result))
) {
$0.$counterValue.finish(Result(result))
}
}
}

0 comments on commit 3b6be21

Please sign in to comment.