Swiftpack.co - reddavis/RedUx as Swift Package

Swiftpack.co is a collection of thousands of indexed Swift packages. Search packages.
See all packages published by reddavis.
reddavis/RedUx v1.1.0
A super simple Swift implementation of the redux pattern making use of Swift 5.5's new async await API's.
⭐️ 5
🕓 1 week ago
iOS macOS
.package(url: "https://github.com/reddavis/RedUx.git", from: "v1.1.0")

RedUx

A super simple Swift implementation of the redux pattern making use of Swift 5.5's new async await API's.

Requirements

  • iOS 15.0+
  • macOS 12.0+

Installation

Swift Package Manager

In Xcode:

  1. Click Project.
  2. Click Package Dependencies.
  3. Click +.
  4. Enter package URL: https://github.com/reddavis/Redux.
  5. Add RedUx to your app target.
  6. If you want the test utilities, add RedUxTestUtilities to your test target.

![Example screenshot of Xcode](https://raw.github.com/reddavis/RedUx/main/./Documentation Resources/Installation.png)

Usage

Store definition

import RedUx
import SwiftUI


enum RootScreen
{
    typealias Store = RedUx.Store<State, Event, Environment>
    
    static func make() -> some View
    {
        ContentView(
            store: Store(
                state: .init(),
                reducer: self.reducer,
                environment: .init()
            )
        )
    }
    
    static func mock(
        state: State
    ) -> some View
    {
        ContentView(
            store: Store(
                state: state,
                reducer: .empty(),
                environment: .init()
            )
        )
    }
}



// MARK: Reducer

extension RootScreen
{
    static let reducer: Reducer<State, Event, Environment> = Reducer { state, event, environment in
        switch event
        {
        case .increment:
            state.count += 1
            return .none
        case .decrement:
            state.count -= 1
            return .none
        case .incrementWithDelay:
            return .init { continuation in
                // Really taxing shiz
                await Task.sleep(2 * 1_000_000_000)
                continuation.yield(.increment)
                continuation.finish()
            }
        }
    }
}



// MARK: State

extension RootScreen
{
    struct State: Equatable
    {
        var count = 0
    }
}



// MARK: Event

extension RootScreen
{
    enum Event
    {
        case increment
        case decrement
        case incrementWithDelay
    }
}



// MARK: Environment

extension RootScreen
{
    struct Environment { }
}

View

import SwiftUI


extension RootScreen
{
    struct ContentView: View
    {
        @StateObject var store: Store
        
        // MARK: Body
        
        var body: some View {
            VStack(alignment: .center) {
                Text(verbatim: .init(self.store.count))
                    .font(.largeTitle)
                
                HStack {
                    Button("Decrement") {
                        self.store.send(.decrement)
                    }
                    .buttonStyle(.bordered)
                    
                    Button("Increment") {
                        self.store.send(.increment)
                    }
                    .buttonStyle(.bordered)
                    
                    Button("Delayed increment") {
                        self.store.send(.incrementWithDelay)
                    }
                    .buttonStyle(.bordered)
                }
            }
        }
    }
}



// MARK: Preview

struct RootScreen_ContentView_Previews: PreviewProvider
{
    static var previews: some View {
        RootScreen.mock(
            state: .init(
                count: 0
            )
        )
    }
}

Tests

import XCTest
import RedUxTestUtilities
@testable import Example


class RootScreenTests: XCTestCase
{
    @MainActor
    func testStateChange() async
    {
        let store = RootScreen.Store(
            state: .init(),
            reducer: RootScreen.reducer,
            environment: .init()
        )
        
        await XCTAssertStateChange(
            store: store,
            events: [
                .increment,
                .decrement,
                .incrementWithDelay
            ],
            matches: [
                .init(),
                .init(count: 1),
                .init(count: 0),
                .init(count: 1)
            ]
        )
    }
}


License

Whatevs.

GitHub

link
Stars: 5
Last commit: 1 week ago
jonrohan Something's broken? Yell at me @ptrpavlik. Praise and feedback (and money) is also welcome.

Release Notes

v1.1.0
1 week ago

Overview

This release adds a testing utility framework to provide helpers when testing against RedUx stores.

Added

  • RedUxTestUtilities framework.

Changed

  • Removed the @MainActor declaration from the Store and moved it to the store's send(_:) function.

Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API | Analytics