Skip to content
This repository has been archived by the owner on Dec 12, 2021. It is now read-only.

Add state-change-function support for syntax-sugar mapping #7

Merged
merged 1 commit into from
Nov 27, 2016
Merged
Show file tree
Hide file tree
Changes from all 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
6 changes: 5 additions & 1 deletion RxAutomaton.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
1FA0AC461DE8AC2B007F01E0 /* StateFuncMappingSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FA0AC451DE8AC2B007F01E0 /* StateFuncMappingSpec.swift */; };
1FCAB4CD1DC7845200EA6EBF /* RxCocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FCAB4CC1DC7845200EA6EBF /* RxCocoa.framework */; };
1FCAB4CF1DC7845700EA6EBF /* Pulsator.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FCAB4CE1DC7845700EA6EBF /* Pulsator.framework */; };
1FCAB4D01DC784E400EA6EBF /* RxSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4822CC391D61961300783A77 /* RxSwift.framework */; };
Expand Down Expand Up @@ -73,6 +74,7 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
1FA0AC451DE8AC2B007F01E0 /* StateFuncMappingSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StateFuncMappingSpec.swift; sourceTree = "<group>"; };
1FCAB4CC1DC7845200EA6EBF /* RxCocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = RxCocoa.framework; sourceTree = BUILT_PRODUCTS_DIR; };
1FCAB4CE1DC7845700EA6EBF /* Pulsator.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Pulsator.framework; sourceTree = BUILT_PRODUCTS_DIR; };
1FCAB4E21DC7947400EA6EBF /* RxTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = RxTest.framework; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -200,8 +202,9 @@
children = (
4822CC3E1D61969C00783A77 /* Fixtures */,
4822CC301D6194FD00783A77 /* MappingSpec.swift */,
4822CC2F1D6194FD00783A77 /* AnyMappingSpec.swift */,
4822CC311D6194FD00783A77 /* NextMappingSpec.swift */,
4822CC2F1D6194FD00783A77 /* AnyMappingSpec.swift */,
1FA0AC451DE8AC2B007F01E0 /* StateFuncMappingSpec.swift */,
4822CC321D6194FD00783A77 /* StrategyLatestSpec.swift */,
4822CC331D6194FD00783A77 /* TerminatingSpec.swift */,
488738ED1D61689100BF70F4 /* Info.plist */,
Expand Down Expand Up @@ -439,6 +442,7 @@
buildActionMask = 2147483647;
files = (
4822CC351D6194FD00783A77 /* MappingSpec.swift in Sources */,
1FA0AC461DE8AC2B007F01E0 /* StateFuncMappingSpec.swift in Sources */,
4822CC401D61969C00783A77 /* Fixtures.swift in Sources */,
487BDE631D619D3200C86902 /* AnyMappingSpec.swift in Sources */,
487BDE6C1D61B03700C86902 /* NextMappingSpec.swift in Sources */,
Expand Down
17 changes: 17 additions & 0 deletions Sources/Mapping+Helper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,23 @@ public func | <State, Input: Equatable>(input: Input, transition: Transition<Sta
return { $0 == input } | transition
}

public func | <State, Input>(inputFunc: @escaping (Input) -> Bool, transition: @escaping (State) -> State) -> Automaton<State, Input>.Mapping
{
return { fromState, input in
if inputFunc(input) {
return transition(fromState)
}
else {
return nil
}
}
}

public func | <State, Input: Equatable>(input: Input, transition: @escaping (State) -> State) -> Automaton<State, Input>.Mapping
{
return { $0 == input } | transition
}

// MARK: `|` (Automaton.NextMapping constructor)

public func | <State, Input>(mapping: @escaping Automaton<State, Input>.Mapping, nextInputProducer: Observable<Input>) -> Automaton<State, Input>.NextMapping
Expand Down
16 changes: 16 additions & 0 deletions Tests/Fixtures/Fixtures.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import RxSwift
import RxAutomaton

// MARK: AuthState/Input

enum AuthState: String, CustomStringConvertible
{
case loggedOut
Expand All @@ -33,6 +35,20 @@ enum AuthInput: String, CustomStringConvertible
var description: String { return self.rawValue }
}

// MARK: CountState/Input

typealias CountState = Int

enum CountInput: String, CustomStringConvertible
{
case increment
case decrement

var description: String { return self.rawValue }
}

// MARK: MyState/Input

enum MyState
{
case state0, state1, state2
Expand Down
52 changes: 52 additions & 0 deletions Tests/StateFuncMappingSpec.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//
// StateFuncMappingSpec.swift
// RxAutomaton
//
// Created by Yasuhiro Inami on 2016-11-26.
// Copyright © 2016 Yasuhiro Inami. All rights reserved.
//

import RxSwift
import RxTest
import RxAutomaton
import Quick
import Nimble

/// Tests for state-change function mapping.
class StateFuncMappingSpec: QuickSpec
{
override func spec()
{
describe("State-change function mapping") {

typealias Automaton = RxAutomaton.Automaton<CountState, CountInput>
typealias NextMapping = Automaton.NextMapping

let (signal, observer) = Observable<CountInput>.pipe()
var automaton: Automaton?

beforeEach {
let mappings: [Automaton.NextMapping] = [
.increment | { $0 + 1 } | .empty(),
.decrement | { $0 - 1 } | .empty(),
]

// strategy = `.merge`
automaton = Automaton(state: 0, input: signal, mapping: reduce(mappings), strategy: .merge)
}

it("`.increment` and `.decrement` succeed") {
expect(automaton?.state.value) == 0
observer.send(next: .increment)
expect(automaton?.state.value) == 1
observer.send(next: .increment)
expect(automaton?.state.value) == 2
observer.send(next: .decrement)
expect(automaton?.state.value) == 1
observer.send(next: .decrement)
expect(automaton?.state.value) == 0
}

}
}
}
3 changes: 0 additions & 3 deletions Tests/TerminatingSpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,6 @@ class TerminatingSpec: QuickSpec
// `sendInput1And2AfterDelay` will automatically send `.input2` at this point.
testScheduler.advanceByInterval(2)

print(automaton?.state.value)
print(lastRepliesEvent)

// Last state & input should change.
expect(automaton?.state.value) == .state0
expect(lastReply?.input) == .input2
Expand Down