Skip to content

Commit

Permalink
Refactor FXIOS-10576 Simplify the MockStoreForMiddleware and middlewa…
Browse files Browse the repository at this point in the history
…re test action type unwrapping (#23168)

Simplify the MockStoreForMiddleware a bit. Simplify our middleware test guards to use XCTUnwrap and throws.
  • Loading branch information
ih-codes authored Nov 15, 2024
1 parent d1d07f5 commit c356362
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,20 @@ import Redux
class MockStoreForMiddleware<State: StateType>: DefaultDispatchStore {
var state: State

/// Records the number of times dispatch is called, and the actions with which it is called. Check this property to
/// ensure that your middleware correctly dispatches the right action(s) in response to a given action.
var dispatchCalled: (numberOfTimes: Int, withActions: [Redux.Action]) = (0, [])
/// Records all actions dispatched to the mock store. Check this property to ensure that your middleware correctly
/// dispatches the right action(s), and the right count of actions, in response to a given action.
var dispatchedActions: [Redux.Action] = []

/// Used to confirm that a dispatch action completed, this is useful when the middleware is making an asynchronous call
/// and we can use the completion to wait for an expectation to be fulfilled.
var dispatchCalledCompletion: (() -> Void)?
/// Called every time an action is dispatched to the mock store. Used to confirm that a dispatched action completed. This
/// is useful when the middleware is making an asynchronous call and we want to wait for an expectation to be fulfilled.
var dispatchCalled: (() -> Void)?

init(state: State) {
self.state = state
}

func subscribe<S>(_ subscriber: S) where S: Redux.StoreSubscriber, State == S.SubscriberStateType {
// TODO if you need it
// TODO: if you need it
}

func subscribe<SubState, S>(
Expand All @@ -38,22 +38,19 @@ class MockStoreForMiddleware<State: StateType>: DefaultDispatchStore {
) -> Redux.Subscription<SubState>
)?
) where SubState == S.SubscriberStateType, S: Redux.StoreSubscriber {
// TODO if you need it
// TODO: if you need it
}

func unsubscribe<S>(_ subscriber: S) where S: Redux.StoreSubscriber, State == S.SubscriberStateType {
// TODO if you need it
// TODO: if you need it
}

func unsubscribe(_ subscriber: any Redux.StoreSubscriber) {
// TODO if you need it
// TODO: if you need it
}

func dispatch(_ action: Redux.Action) {
var dispatchActions = dispatchCalled.withActions
dispatchActions.append(action)

dispatchCalled = (dispatchCalled.numberOfTimes + 1, dispatchActions)
dispatchCalledCompletion?()
dispatchedActions.append(action)
dispatchCalled?()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,11 @@ final class SearchEngineSelectionMiddlewareTests: XCTestCase, StoreTestUtility {

subject.searchEngineSelectionProvider(AppState(), action)

guard let actionCalled = mockStore.dispatchCalled.withActions.first as? SearchEngineSelectionAction,
case SearchEngineSelectionActionType.didLoadSearchEngines = actionCalled.actionType else {
XCTFail("Unexpected action type dispatched")
return
}
XCTAssertEqual(mockStore.dispatchCalled.numberOfTimes, 1)
let actionCalled = try XCTUnwrap(mockStore.dispatchedActions.first as? SearchEngineSelectionAction)
let actionType = try XCTUnwrap(actionCalled.actionType as? SearchEngineSelectionActionType)

XCTAssertEqual(mockStore.dispatchedActions.count, 1)
XCTAssertEqual(actionType, SearchEngineSelectionActionType.didLoadSearchEngines)
XCTAssertEqual(actionCalled.searchEngines, mockSearchEngineModels)
}

Expand All @@ -57,12 +56,11 @@ final class SearchEngineSelectionMiddlewareTests: XCTestCase, StoreTestUtility {

subject.searchEngineSelectionProvider(AppState(), action)

guard let actionCalled = mockStore.dispatchCalled.withActions.first as? ToolbarAction,
case ToolbarActionType.didStartEditingUrl = actionCalled.actionType else {
XCTFail("Unexpected action type dispatched")
return
}
XCTAssertEqual(mockStore.dispatchCalled.numberOfTimes, 1)
let actionCalled = try XCTUnwrap(mockStore.dispatchedActions.first as? ToolbarAction)
let actionType = try XCTUnwrap(actionCalled.actionType as? ToolbarActionType)

XCTAssertEqual(mockStore.dispatchedActions.count, 1)
XCTAssertEqual(actionType, ToolbarActionType.didStartEditingUrl)
}

// MARK: - Helpers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,51 +23,47 @@ final class PocketMiddlewareTests: XCTestCase, StoreTestUtility {
super.tearDown()
}

func test_initializeAction_getPocketData() {
func test_initializeAction_getPocketData() throws {
let subject = createSubject(pocketManager: pocketManager)
let action = HomepageAction(windowUUID: .XCTestDefaultUUID, actionType: HomepageActionType.initialize)
let expectation = XCTestExpectation(description: "Homepage action initialize dispatched")

mockStore.dispatchCalledCompletion = {
mockStore.dispatchCalled = {
expectation.fulfill()
}

subject.pocketSectionProvider(AppState(), action)

wait(for: [expectation])

guard let actionCalled = mockStore.dispatchCalled.withActions.first as? PocketAction,
case PocketMiddlewareActionType.retrievedUpdatedStories = actionCalled.actionType else {
XCTFail("Unexpected action type dispatched, \(String(describing: mockStore.dispatchCalled.withActions.first))")
return
}
let actionCalled = try XCTUnwrap(mockStore.dispatchedActions.first as? PocketAction)
let actionType = try XCTUnwrap(actionCalled.actionType as? PocketMiddlewareActionType)

XCTAssertEqual(mockStore.dispatchCalled.numberOfTimes, 1)
XCTAssertEqual(actionType, PocketMiddlewareActionType.retrievedUpdatedStories)
XCTAssertEqual(mockStore.dispatchedActions.count, 1)
XCTAssertEqual(actionCalled.pocketStories?.count, 3)
XCTAssertEqual(pocketManager.getPocketItemsCalled, 1)
}

func test_enterForegroundAction_getPocketData() {
func test_enterForegroundAction_getPocketData() throws {
let subject = createSubject(pocketManager: pocketManager)
let action = PocketAction(windowUUID: .XCTestDefaultUUID, actionType: PocketActionType.enteredForeground)

let expectation = XCTestExpectation(description: "Pocket action entered foreground dispatched")
mockStore.dispatchCalledCompletion = {
mockStore.dispatchCalled = {
expectation.fulfill()
}

subject.pocketSectionProvider(AppState(), action)

wait(for: [expectation])

guard let actionCalled = mockStore.dispatchCalled.withActions.first as? PocketAction,
case PocketMiddlewareActionType.retrievedUpdatedStories = actionCalled.actionType else {
XCTFail("Unexpected action type dispatched, \(String(describing: mockStore.dispatchCalled.withActions.first))")
return
}
let actionCalled = try XCTUnwrap(mockStore.dispatchedActions.first as? PocketAction)
let actionType = try XCTUnwrap(actionCalled.actionType as? PocketMiddlewareActionType)

XCTAssertEqual(mockStore.dispatchCalled.numberOfTimes, 1)
XCTAssertTrue(mockStore.dispatchCalled.withActions.first is PocketAction)
XCTAssertEqual(actionType, PocketMiddlewareActionType.retrievedUpdatedStories)
XCTAssertEqual(mockStore.dispatchedActions.count, 1)
XCTAssertTrue(mockStore.dispatchedActions.first is PocketAction)
XCTAssertEqual(actionCalled.pocketStories?.count, 3)
XCTAssertEqual(pocketManager.getPocketItemsCalled, 1)
}
Expand Down

0 comments on commit c356362

Please sign in to comment.