Skip to content

Commit

Permalink
added unit tests and improved the code
Browse files Browse the repository at this point in the history
  • Loading branch information
Velin92 committed Feb 28, 2025
1 parent 2298124 commit 7a5e6c0
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ enum StartChatScreenErrorType: Error {
case unknown
}

enum StartChatScreenViewModelAction {
enum StartChatScreenViewModelAction: Equatable {
case close
case createRoom
case openRoom(withIdentifier: String)
Expand Down Expand Up @@ -56,7 +56,7 @@ enum StartChatScreenViewAction {
case openRoomDirectorySearch
}

enum JoinByAddressState {
enum JoinByAddressState: Equatable {
case example
case invalidAddress
case addressNotFound
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,40 +103,62 @@ class StartChatScreenViewModel: StartChatScreenViewModelType, StartChatScreenVie

context.$viewState
.map(\.bindings.roomAddress)
.debounceTextQueriesAndRemoveDuplicates()
.sink { [weak self] roomAddress in
.removeDuplicates()
.receive(on: DispatchQueue.main)
.sink { [weak self] _ in
guard let self else {
return
}

state.joinByAddressState = .example
internalRoomAddressState = .example

guard !roomAddress.isEmpty,
isRoomAliasFormatValid(alias: roomAddress) else {
internalRoomAddressState = .invalidAddress
}
.store(in: &cancellables)

context.$viewState
.map(\.bindings.roomAddress)
.debounce(for: .milliseconds(250), scheduler: DispatchQueue.main)
.removeDuplicates()
.sink { [weak self] roomAddress in
guard let self else {
return
}

resolveAliasTask = Task { [weak self] in
guard let self else {
return
}
defer { resolveAliasTask = nil }

guard case let .success(resolved) = await userSession.clientProxy.resolveRoomAlias(roomAddress) else {
internalRoomAddressState = .addressNotFound
return
}

let result = JoinByAddressState.addressFound(address: roomAddress, roomID: resolved.roomId)
internalRoomAddressState = result
state.joinByAddressState = result
}
resolveRoomAddress(roomAddress)
}
.store(in: &cancellables)
}

private func resolveRoomAddress(_ roomAddress: String) {
guard !roomAddress.isEmpty,
isRoomAliasFormatValid(alias: roomAddress) else {
internalRoomAddressState = .invalidAddress
resolveAliasTask = nil
return
}

resolveAliasTask = Task { [weak self] in
guard let self else {
return
}
defer { resolveAliasTask = nil }

guard case let .success(resolved) = await userSession.clientProxy.resolveRoomAlias(roomAddress) else {
if Task.isCancelled {
return
}
internalRoomAddressState = .addressNotFound
return
}

guard !Task.isCancelled else {
return
}

let result = JoinByAddressState.addressFound(address: roomAddress, roomID: resolved.roomId)
internalRoomAddressState = result
state.joinByAddressState = result
}
}

// periphery:ignore - auto cancels when reassigned
@CancellableTask
private var fetchUsersTask: Task<Void, Never>?
Expand Down Expand Up @@ -193,6 +215,9 @@ class StartChatScreenViewModel: StartChatScreenViewModelType, StartChatScreenVie
hideLoadingIndicator()
joinRoomByAddress()
}
} else if internalRoomAddressState == .example {
resolveRoomAddress(state.bindings.roomAddress)
joinRoomByAddress()
} else {
state.joinByAddressState = internalRoomAddressState
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ struct JoinRoomByAddressView: View {
case .addressNotFound:
L10n.screenStartChatJoinRoomByAddressRoomNotFound
case .addressFound:
L10n.screenStartChatJoinRoomByAddressRoomNotFound
L10n.screenStartChatJoinRoomByAddressRoomFound
case .invalidAddress:
L10n.screenStartChatJoinRoomByAddressInvalidAddress
}
Expand Down
37 changes: 37 additions & 0 deletions UnitTests/Sources/StartChatViewModelTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,43 @@ class StartChatScreenViewModelTests: XCTestCase {
XCTAssertTrue(userDiscoveryService.searchProfilesWithCalled)
}

func testJoinRoomByAddress() async throws {
clientProxy.resolveRoomAliasReturnValue = .success(.init(roomId: "id", servers: []))
viewModel.context.roomAddress = "#room:example.com"

let deferredViewState = deferFulfillment(viewModel.context.$viewState) { viewState in
viewState.joinByAddressState == .addressFound(address: "#room:example.com", roomID: "id")
}
try await deferredViewState.fulfill()

let deferredAction = deferFulfillment(viewModel.actions) { action in
action == .openRoom(withIdentifier: "id")
}
context.send(viewAction: .joinRoomByAddress)
try await deferredAction.fulfill()
}

func testJoinRoomByAddressFailsBecauseInvalid() async throws {
viewModel.context.roomAddress = ":"

let deferred = deferFulfillment(viewModel.context.$viewState) { viewState in
viewState.joinByAddressState == .invalidAddress
}
context.send(viewAction: .joinRoomByAddress)
try await deferred.fulfill()
}

func testJoinRoomByAddressFailsBecauseNotFound() async throws {
clientProxy.resolveRoomAliasReturnValue = .failure(.failedResolvingRoomAlias)
viewModel.context.roomAddress = "#room:example.com"

let deferred = deferFulfillment(viewModel.context.$viewState) { viewState in
viewState.joinByAddressState == .addressNotFound
}
context.send(viewAction: .joinRoomByAddress)
try await deferred.fulfill()
}

// MARK: - Private

private func assertSearchResults(toBe count: Int) {
Expand Down

0 comments on commit 7a5e6c0

Please sign in to comment.