Files
swift-composable-architectu…/Tests/ComposableArchitectureTests/ReducerBuilderTests.swift
Stephen Celis 57e804f1cc Macro bonanza (#2553)
* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* Silence test warnings

* wip

* wip

* wip

* update a bunch of docs

* wip

* wip

* fix

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* Kill integration tests for now

* wip

* wip

* wip

* wip

* updating docs for @Reducer macro

* replaced more Reducer protocols with @Reducer

* Fixed some broken docc references

* wip

* Some @Reducer docs

* more docs

* convert some old styles to new style

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* bump

* update tutorials to use body

* update tutorials to use DML on destination state enum

* Add diagnostic

* wip

* updated a few more tests

* wip

* wip

* Add another gotcha

* wip

* wip

* wip

* fixes

* wip

* wip

* wip

* wip

* wip

* fix

* wip

* remove for now

* wip

* wip

* updated some docs

* migration guides

* more migration guide

* fix ci

* fix

* soft deprecate all apis using AnyCasePath

* wip

* Fix

* fix tests

* swift-format 509 compatibility

* wip

* wip

* Update Sources/ComposableArchitecture/Macros.swift

Co-authored-by: Mateusz Bąk <bakmatthew@icloud.com>

* wip

* wip

* update optional state case study

* remove initializer

* Don't use @State for BasicsView integration demo

* fix tests

* remove reduce diagnostics for now

* diagnose error not warning

* Update Sources/ComposableArchitecture/Macros.swift

Co-authored-by: Jesse Tipton <jesse@jessetipton.com>

* wip

* move integration tests to cron

* Revert "move integration tests to cron"

This reverts commit f9bdf2f04b.

* disable flakey tests on CI

* wip

* wip

* Revert "Revert "move integration tests to cron""

This reverts commit 66aafa7327.

* fix

* wip

* fix

---------

Co-authored-by: Brandon Williams <mbrandonw@hey.com>
Co-authored-by: Mateusz Bąk <bakmatthew@icloud.com>
Co-authored-by: Brandon Williams <135203+mbrandonw@users.noreply.github.com>
Co-authored-by: Jesse Tipton <jesse@jessetipton.com>
2023-11-13 12:57:35 -08:00

219 lines
4.0 KiB
Swift

// NB: This file contains compile-time tests to ensure reducer builder generic inference is working.
import ComposableArchitecture
import XCTest
@Reducer
private struct Test {
struct State {}
enum Action { case tap }
var body: some Reducer<State, Action> {
EmptyReducer()
}
@available(iOS, introduced: 9999)
@Reducer
struct Unavailable {
var body: some Reducer<State, Action> {
EmptyReducer()
}
}
}
func testExistentialReducers() {
_ = CombineReducers {
Test()
Test() as any ReducerOf<Test>
}
}
func testLimitedAvailability() {
_ = CombineReducers {
Test()
if #available(iOS 9999, *) {
Test.Unavailable()
} else if #available(iOS 8888, *) {
EmptyReducer()
}
}
}
@Reducer
private struct Root {
struct State {
var feature: Feature.State
var optionalFeature: Feature.State?
var enumFeature: Features.State?
var features: IdentifiedArrayOf<Feature.State>
}
enum Action {
case feature(Feature.Action)
case optionalFeature(Feature.Action)
case enumFeature(Features.Action)
case features(id: Feature.State.ID, action: Feature.Action)
}
@available(iOS, introduced: 9999)
@Reducer
struct Unavailable {
let body = EmptyReducer<State, Action>()
}
var body: some ReducerOf<Self> {
CombineReducers {
Scope(state: \.feature, action: \.feature) {
Feature()
Feature()
}
Scope(state: \.feature, action: \.feature) {
Feature()
Feature()
}
}
.ifLet(\.optionalFeature, action: \.optionalFeature) {
Feature()
Feature()
}
.ifLet(\.enumFeature, action: \.enumFeature) {
EmptyReducer()
.ifCaseLet(\.featureA, action: \.featureA) {
Feature()
Feature()
}
.ifCaseLet(\.featureB, action: \.featureB) {
Feature()
Feature()
}
Features()
}
.forEach(\.features, action: \.features) {
Feature()
Feature()
}
}
@ReducerBuilder<State, Action>
var testFlowControl: some ReducerOf<Self> {
if true {
Self()
}
if Bool.random() {
Self()
} else {
EmptyReducer()
}
for _ in 1...10 {
Self()
}
if #available(iOS 9999, *) {
Unavailable()
}
}
@Reducer
struct Feature {
struct State: Identifiable {
let id: Int
}
enum Action {
case action
}
var body: some Reducer<State, Action> {
EmptyReducer()
}
}
@Reducer
struct Features {
enum State {
case featureA(Feature.State)
case featureB(Feature.State)
}
enum Action {
case featureA(Feature.Action)
case featureB(Feature.Action)
}
var body: some ReducerOf<Self> {
Scope(state: \.featureA, action: \.featureA) {
Feature()
}
Scope(state: \.featureB, action: \.featureB) {
Feature()
}
}
}
}
@Reducer
private struct IfLetExample {
struct State {
var optional: Int?
}
enum Action {}
var body: some ReducerOf<Self> {
EmptyReducer().ifLet(\.optional, action: \.self) { EmptyReducer() }
}
}
@Reducer
private struct IfCaseLetExample {
enum State {
case value(Int)
}
enum Action {}
var body: some ReducerOf<Self> {
EmptyReducer().ifCaseLet(\.value, action: \.self) { EmptyReducer() }
}
}
@Reducer
private struct ForEachExample {
struct Element: Identifiable { let id: Int }
struct State {
var values: IdentifiedArrayOf<Element>
}
enum Action {
case value(id: Element.ID, action: Never)
}
var body: some ReducerOf<Self> {
EmptyReducer().forEach(\.values, action: \.value) { EmptyReducer() }
}
}
@Reducer
private struct ScopeIfLetExample {
struct State {
var optionalSelf: Self? {
get { self }
set { newValue.map { self = $0 } }
}
}
enum Action {}
var body: some ReducerOf<Self> {
Scope(state: \.self, action: \.self) {
EmptyReducer()
.ifLet(\.optionalSelf, action: \.self) {
EmptyReducer()
}
}
}
}