Skip to content

Commit

Permalink
Merge pull request #25 from wlsdms0122/develop
Browse files Browse the repository at this point in the history
[RELEASE] Reducer/2.4.0
  • Loading branch information
wlsdms0122 authored Nov 3, 2024
2 parents 22da634 + 4818646 commit 8fa7838
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 30 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
.DS_Store
/.build
/Packages
/*.xcodeproj
xcuserdata/
DerivedData/
.swiftpm/config/registries.json
.swiftpm/configuration/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
Package.resolved
10 changes: 10 additions & 0 deletions .swiftpm/xcode/xcshareddata/xcschemes/Reducer.xcscheme
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,16 @@
ReferencedContainer = "container:">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "ReducerMacroTests"
BuildableName = "ReducerMacroTests"
BlueprintName = "ReducerMacroTests"
ReferencedContainer = "container:">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
Expand Down
14 changes: 0 additions & 14 deletions Package.resolved

This file was deleted.

2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// swift-tools-version: 5.9
// swift-tools-version: 5.10
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription
Expand Down
13 changes: 13 additions & 0 deletions Sources/Reducer/Reduce.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public protocol Reduce: AnyObject {
var initialState: State { get }

func start() async throws
func error(_ error: any Error, action: Action) async

func mutate(action: Action) async throws
func reduce(state: State, mutation: Mutation) -> State
Expand All @@ -29,6 +30,8 @@ public extension Reduce {

func start() async throws { }

func error(_ error: any Error, action: Action) async { }

func shouldCancel(_ current: Action, _ upcoming: Action) -> Bool {
false
}
Expand Down Expand Up @@ -77,6 +80,7 @@ open class ProxyReduce<R: Reduce>: Reduce {
public var initialState: State

private let _start: ((@escaping (Mutation) -> Void) async throws -> Void)?
private let _error: ((@escaping (Mutation) -> Void, any Error, Action) async -> Void)?
private let _mutate: ((State, Action, @escaping (Mutation) -> Void) async throws -> Void)?
private let _reduce: ((State, Mutation) -> State)?
private let _shouldCancel: ((Action, Action) -> Bool)?
Expand All @@ -85,13 +89,15 @@ open class ProxyReduce<R: Reduce>: Reduce {
public init(
initialState: State,
start: ((@escaping (Mutation) -> Void) async throws -> Void)? = nil,
error: ((@escaping (Mutation) -> Void, any Error, Action) async -> Void)? = nil,
mutate: ((State, Action, @escaping (Mutation) -> Void) async throws -> Void)? = nil,
reduce: ((State, Mutation) -> State)? = nil,
shouldCancel: ((Action, Action) -> Bool)? = nil
) {
self.initialState = initialState

self._start = start
self._error = error
self._mutate = mutate
self._reduce = reduce
self._shouldCancel = shouldCancel
Expand All @@ -103,6 +109,9 @@ open class ProxyReduce<R: Reduce>: Reduce {
start: { _ in
try await reduce.start()
},
error: { _, error, action in
await reduce.error(error, action: action)
},
mutate: { _, action, _ in
try await reduce.mutate(action: action)
},
Expand All @@ -126,6 +135,10 @@ open class ProxyReduce<R: Reduce>: Reduce {
try await _start?({ [weak self] mutation in self?.mutator?(mutation) })
}

public func error(_ error: any Error, action: Action) async {
await _error?({ [weak self] mutation in self?.mutator?(mutation) }, error, action)
}

open func mutate(action: Action) async throws {
try await _mutate?(currentState, action, { [weak self] mutation in self?.mutator?(mutation) })
}
Expand Down
6 changes: 5 additions & 1 deletion Sources/Reducer/Reducer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,11 @@ open class Reducer<R: Reduce>: ObservableObject, Mutable {
action,
with: Task { @MainActor in
// Mutate state from action.
try? await reduce.mutate(action: action)
do {
try await reduce.mutate(action: action)
} catch {
await reduce.error(error, action: action)
}
}
))
}
Expand Down
54 changes: 54 additions & 0 deletions Tests/ReducerTests/Model/ErrorReduce.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//
// ErrorReduce.swift
// Reducer
//
// Created by JSilver on 11/3/24.
//

import Foundation
import Reducer

@Reduce
@MainActor
class ErrorReduce {
enum Action {
case occurError(any Error)
}

enum Mutation {
case setCount(Int)
}

struct State {
var count: Int
}

let initialState: State

init() {
self.initialState = State(
count: 0
)
}

func error(_ error: any Error, action: Action) async {
mutate(.setCount(currentState.count + 1))
}

func mutate(action: Action) async throws {
switch action {
case let .occurError(error):
throw error
}
}

func reduce(state: State, mutation: Mutation) -> State {
var state = state

switch mutation {
case let .setCount(count):
state.count = count
return state
}
}
}
16 changes: 16 additions & 0 deletions Tests/ReducerTests/Model/TestError.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// TestError.swift
// Reducer
//
// Created by JSilver on 11/3/24.
//

import Foundation

struct TestError: Error {
let description: String

init(_ description: String) {
self.description = description
}
}
31 changes: 19 additions & 12 deletions Tests/ReducerTests/ReducerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import XCTest
@testable import Reducer
import Combine

@MainActor
final class ReducerTests: XCTestCase {
// MARK: - Property

Expand All @@ -22,7 +23,6 @@ final class ReducerTests: XCTestCase {
}

// MARK: - Test
@MainActor
func test_that_count_increases_when_receiving_increase_action() async throws {
// Given
let reducer = Reducer(
Expand All @@ -46,7 +46,6 @@ final class ReducerTests: XCTestCase {
XCTAssertEqual(result, [0, 1, 2])
}

@MainActor
func test_that_count_does_not_mutate_when_receiving_same_action_twice() async throws {
// Given
let reducer = Reducer(
Expand All @@ -70,7 +69,6 @@ final class ReducerTests: XCTestCase {
XCTAssertEqual(result, [0, 1])
}

@MainActor
func test_that_all_action_cancelled_when_reducer_deinit() async throws {
// Given
var reducer: Reducer<CountIncreaseReduce>? = Reducer(
Expand All @@ -96,7 +94,6 @@ final class ReducerTests: XCTestCase {
XCTAssertEqual(result, [0])
}

@MainActor
func test_that_count_increases_when_mutate_in_start() async throws {
// Given
let reducer = Reducer(TimerReduce(
Expand All @@ -113,7 +110,6 @@ final class ReducerTests: XCTestCase {
XCTAssertGreaterThan(result.last ?? 0, 0)
}

@MainActor
func test_that_count_increases_when_await_mutate_in_start() async throws {
// Given
let reducer = Reducer(AwaitStartReduce(
Expand All @@ -130,7 +126,6 @@ final class ReducerTests: XCTestCase {
XCTAssertEqual(result, [0, 1])
}

@MainActor
func test_that_reducer_should_be_able_to_assign_proxy_reduce() async throws {
// Given
var reducer = Reducer(CountIncreaseReduce(
Expand Down Expand Up @@ -170,7 +165,6 @@ final class ReducerTests: XCTestCase {
XCTAssertEqual(result, [0, 10])
}

@MainActor
func test_that_initial_count_is_100_when_proxy_set_initial_count() async throws {
// Given
let reducer = Reducer<CountIncreaseReduce>(proxy: .init(
Expand All @@ -189,7 +183,6 @@ final class ReducerTests: XCTestCase {
XCTAssertEqual(result, [100])
}

@MainActor
func test_that_count_increases_when_proxy_receiving_increase_action() async throws {
// Given
let reducer = Reducer<CountIncreaseReduce>(proxy: .init(
Expand Down Expand Up @@ -226,7 +219,6 @@ final class ReducerTests: XCTestCase {
XCTAssertEqual(result, [0, 1])
}

@MainActor
func test_that_count_increases_10_when_proxy_receiving_increase_action() async throws {
// Given
let reducer = Reducer<CountIncreaseReduce>(proxy: .init(
Expand Down Expand Up @@ -264,7 +256,6 @@ final class ReducerTests: XCTestCase {
XCTAssertEqual(result, [0, 10, 20])
}

@MainActor
func test_that_count_does_not_mutate_when_proxy_same_action_twice() async throws {
// Given
let reducer = Reducer<CountIncreaseReduce>(proxy: .init(
Expand Down Expand Up @@ -304,7 +295,6 @@ final class ReducerTests: XCTestCase {
XCTAssertEqual(result, [0, 1])
}

@MainActor
func test_that_count_increases_when_proxy_mutate_in_start() async throws {
// Given
var cancellable: AnyCancellable? = nil
Expand Down Expand Up @@ -336,7 +326,6 @@ final class ReducerTests: XCTestCase {
XCTAssertGreaterThan(result.last ?? 0, 0)
}

@MainActor
func test_that_reducer_can_assign_proxy_inherited_reduce() async throws {
// Given
let reducer = Reducer<CountIncreaseReduce>(
Expand All @@ -357,4 +346,22 @@ final class ReducerTests: XCTestCase {
// Then
XCTAssertEqual(result, [0, 10])
}

func test_that_count_increases_when_error_is_thrown_in_mutation() async throws {
// Given
let sut = Reducer(ErrorReduce())

// When
Task {
sut.action(.occurError(TestError("increase count")))
}

let result = try await wait(
sut.$state.map(\.count),
timeout: 1
)

// Then
XCTAssertEqual(result, [0, 1])
}
}

0 comments on commit 8fa7838

Please sign in to comment.