* Initial plan * Migrate 3 test files from XCTest to Swift Testing - MediaUploadPreviewScreenViewModelTests: @MainActor @Suite struct with init(), BundleFinder class for Bundle(for:), mutating test/setup functions, [self] capture replacing [weak self] in closures - NotificationManagerTests: @MainActor @Suite final class with init()/deinit, expectation/fulfillment(of:) replaced with confirmation(...), test_ prefix stripped - NotificationSettingsScreenViewModelTests: @MainActor @Suite struct with init() throws, non-optional stored properties, test prefix stripped Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Migrate 3 XCTest files to Swift Testing - NotificationSettingsEditScreenViewModelTests: @MainActor @Suite struct with init() throws, mutating test methods - TimelineViewModelTests: @MainActor @Suite final class with init() async throws + deinit - AttributedStringBuilderTests: @Suite struct with init() async throws All XCT assertions replaced with #expect/#require/Issue.record Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Migrate 4 test files from XCTest to Swift Testing - TimelineMediaPreviewViewModelTests: @Suite struct, mutating @Test funcs, testLoadingItem renamed to loadingItem (called internally by other tests) - ServerConfirmationScreenViewModelTests: @Suite final class with init()/deinit - CompletionSuggestionServiceTests: @Suite struct with init() - RoomFlowCoordinatorTests: @Suite final class with deinit Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Migrate 4 test files from XCTest to Swift Testing - VoiceMessageRecorderTests: @Suite struct with init() async throws, added BundleFinder class for Bundle lookup, migrated all assertions - SpaceScreenViewModelTests: @Suite struct, private mutating setupViewModel, all test funcs mutating, XCTestExpectation → confirmation - RoomNotificationSettingsScreenViewModelTests: @Suite struct with init() throws, cancellable tests marked mutating - JoinRoomScreenViewModelTests: @Suite final class with init()/deinit, XCTestExpectation → confirmation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Migrate 6 test files from XCTestCase to Swift Testing Co-authored-by: pixlwave <6060466+pixlwave@users.noreply.github.com> * Fix trailing blank line in RoomPollsHistoryScreenViewModelTests Co-authored-by: pixlwave <6060466+pixlwave@users.noreply.github.com> * Migrate 3 test files from XCTest to Swift Testing - MediaUploadingPreprocessorTests: @Suite final class with init()/deinit, removed executionTimeAllowance, XCTAssertEqual(accuracy:) → abs(Double) - SecurityAndPrivacyScreenViewModelTests: @MainActor @Suite final class, 5 expectation+fulfillment → await confirmation(...) - CreateRoomViewModelTests: @MainActor @Suite final class, 4 expectation+fulfillment → await confirmation(...) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Migrate RoomScreenViewModelTests and RoomDetailsScreenViewModelTests to Swift Testing - Replace XCTest with Testing framework - RoomScreenViewModelTests: final class with init() async throws + deinit - RoomDetailsScreenViewModelTests: struct with init() and mutating funcs - Convert XCT assertions to #expect / Issue.record - Convert XCTestExpectation patterns to confirmation { confirm in } - Strip 'test' prefix from all test function names Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Migrate ComposerToolbarViewModelTests from XCTest to Swift Testing - Replace import XCTest with import Testing - Convert XCTestCase class to @MainActor @Suite final class - Replace setUp()/tearDown() with init()/deinit - Strip 'test' prefix from all 41 test method names and add @Test - Replace XCTAssert* with #expect()/#require() - Replace try XCTUnwrap() with try #require() - Convert expectation+wait patterns to deferFulfillment with PassthroughSubject - Convert isInverted expectation to boolean flag checked after await - Use deferFulfillment on $viewState for state-transition tests Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address comments with Copilot. * Fix the failing tests. * Fixed flaky tests (#5137) resolved flaky tests * Tweaks and fixes. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: pixlwave <6060466+pixlwave@users.noreply.github.com> Co-authored-by: Doug <douglase@element.io> Co-authored-by: Mauro <34335419+Velin92@users.noreply.github.com>
417 lines
26 KiB
Swift
417 lines
26 KiB
Swift
//
|
|
// Copyright 2025 Element Creations Ltd.
|
|
// Copyright 2023-2025 New Vector Ltd.
|
|
//
|
|
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
|
// Please see LICENSE files in the repository root for full details.
|
|
//
|
|
|
|
import Combine
|
|
@testable import ElementX
|
|
import Testing
|
|
|
|
@Suite
|
|
@MainActor
|
|
struct CompletionSuggestionServiceTests {
|
|
@Test
|
|
func userSuggestions() async throws {
|
|
let alice: RoomMemberProxyMock = .mockAlice
|
|
let members: [RoomMemberProxyMock] = [alice, .mockBob, .mockCharlie, .mockMe]
|
|
let roomProxyMock = JoinedRoomProxyMock(.init(id: "roomID", name: "test", members: members))
|
|
let roomSummaryProvider = RoomSummaryProviderMock(.init(state: .loaded(.mockRooms)))
|
|
let service = CompletionSuggestionService(roomProxy: roomProxyMock,
|
|
roomListPublisher: roomSummaryProvider.roomListPublisher.eraseToAnyPublisher())
|
|
|
|
var deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
|
suggestions == []
|
|
}
|
|
|
|
try await deferred.fulfill()
|
|
|
|
deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
|
suggestions == [.init(suggestionType: .user(.init(id: alice.userID, displayName: alice.displayName, avatarURL: alice.avatarURL)), range: .init(), rawSuggestionText: "ali")]
|
|
}
|
|
service.setSuggestionTrigger(.init(type: .user, text: "ali", range: .init()))
|
|
try await deferred.fulfill()
|
|
|
|
deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
|
suggestions == []
|
|
}
|
|
service.setSuggestionTrigger(.init(type: .user, text: "me", range: .init()))
|
|
try await deferred.fulfill()
|
|
|
|
deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
|
suggestions == []
|
|
}
|
|
service.setSuggestionTrigger(.init(type: .user, text: "room", range: .init()))
|
|
try await deferred.fulfill()
|
|
|
|
deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
|
suggestions == []
|
|
}
|
|
service.setSuggestionTrigger(.init(type: .user, text: "everyon", range: .init()))
|
|
try await deferred.fulfill()
|
|
}
|
|
|
|
@Test
|
|
func userSuggestionsIncludingAllUsers() async throws {
|
|
let alice: RoomMemberProxyMock = .mockAlice
|
|
let members: [RoomMemberProxyMock] = [alice, .mockBob, .mockCharlie, .mockMe]
|
|
let roomProxyMock = JoinedRoomProxyMock(.init(id: "roomID",
|
|
name: "test",
|
|
members: members,
|
|
powerLevelsConfiguration: .init(canUserTriggerRoomNotification: true)))
|
|
|
|
let roomSummaryProvider = RoomSummaryProviderMock(.init(state: .loaded(.mockRooms)))
|
|
let service = CompletionSuggestionService(roomProxy: roomProxyMock,
|
|
roomListPublisher: roomSummaryProvider.roomListPublisher.eraseToAnyPublisher())
|
|
|
|
var deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
|
suggestions == []
|
|
}
|
|
|
|
try await deferred.fulfill()
|
|
|
|
deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
|
suggestions == [.init(suggestionType: .allUsers(.room(id: "roomID", name: "test", avatarURL: nil)), range: .init(), rawSuggestionText: "ro")]
|
|
}
|
|
service.setSuggestionTrigger(.init(type: .user, text: "ro", range: .init()))
|
|
try await deferred.fulfill()
|
|
|
|
deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
|
suggestions == [.init(suggestionType: .allUsers(.room(id: "roomID", name: "test", avatarURL: nil)), range: .init(), rawSuggestionText: "every")]
|
|
}
|
|
service.setSuggestionTrigger(.init(type: .user, text: "every", range: .init()))
|
|
try await deferred.fulfill()
|
|
}
|
|
|
|
@Test
|
|
func userSuggestionsWithEmptyText() async throws {
|
|
let alice: RoomMemberProxyMock = .mockAlice
|
|
let bob: RoomMemberProxyMock = .mockBob
|
|
let members: [RoomMemberProxyMock] = [alice, bob, .mockMe]
|
|
let roomProxyMock = JoinedRoomProxyMock(.init(id: "roomID",
|
|
name: "test",
|
|
members: members,
|
|
powerLevelsConfiguration: .init(canUserTriggerRoomNotification: true)))
|
|
let roomSummaryProvider = RoomSummaryProviderMock(.init(state: .loaded(.mockRooms)))
|
|
let service = CompletionSuggestionService(roomProxy: roomProxyMock,
|
|
roomListPublisher: roomSummaryProvider.roomListPublisher.eraseToAnyPublisher())
|
|
|
|
var deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
|
suggestions == []
|
|
}
|
|
|
|
try await deferred.fulfill()
|
|
|
|
deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
|
suggestions == [.init(suggestionType: .allUsers(.room(id: "roomID", name: "test", avatarURL: nil)), range: .init(), rawSuggestionText: ""),
|
|
.init(suggestionType: .user(.init(id: alice.userID, displayName: alice.displayName, avatarURL: alice.avatarURL)), range: .init(), rawSuggestionText: ""),
|
|
.init(suggestionType: .user(.init(id: bob.userID, displayName: bob.displayName, avatarURL: bob.avatarURL)), range: .init(), rawSuggestionText: "")]
|
|
}
|
|
service.setSuggestionTrigger(.init(type: .user, text: "", range: .init()))
|
|
try await deferred.fulfill()
|
|
|
|
// Let's test the same with the processTextMessage method
|
|
deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
|
suggestions == [.init(suggestionType: .allUsers(.room(id: "roomID", name: "test", avatarURL: nil)), range: .init(location: 0, length: 1), rawSuggestionText: ""),
|
|
.init(suggestionType: .user(.init(id: alice.userID, displayName: alice.displayName, avatarURL: alice.avatarURL)), range: .init(location: 0, length: 1), rawSuggestionText: ""),
|
|
.init(suggestionType: .user(.init(id: bob.userID, displayName: bob.displayName, avatarURL: bob.avatarURL)), range: .init(location: 0, length: 1), rawSuggestionText: "")]
|
|
}
|
|
service.processTextMessage("@", selectedRange: .init(location: 0, length: 1))
|
|
try await deferred.fulfill()
|
|
}
|
|
|
|
@Test
|
|
func userSuggestionInDifferentMessagePositions() async throws {
|
|
let alice: RoomMemberProxyMock = .mockAlice
|
|
let members: [RoomMemberProxyMock] = [alice, .mockBob, .mockCharlie, .mockMe]
|
|
let roomProxyMock = JoinedRoomProxyMock(.init(name: "test", members: members))
|
|
let roomSummaryProvider = RoomSummaryProviderMock(.init(state: .loaded(.mockRooms)))
|
|
let service = CompletionSuggestionService(roomProxy: roomProxyMock,
|
|
roomListPublisher: roomSummaryProvider.roomListPublisher.eraseToAnyPublisher())
|
|
|
|
var deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
|
suggestions == [.init(suggestionType: .user(.init(id: alice.userID, displayName: alice.displayName, avatarURL: alice.avatarURL)), range: .init(location: 0, length: 3), rawSuggestionText: "al")]
|
|
}
|
|
service.processTextMessage("@al hello", selectedRange: .init(location: 0, length: 1))
|
|
try await deferred.fulfill()
|
|
|
|
deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
|
suggestions == [.init(suggestionType: .user(.init(id: alice.userID, displayName: alice.displayName, avatarURL: alice.avatarURL)), range: .init(location: 5, length: 3), rawSuggestionText: "al")]
|
|
}
|
|
service.processTextMessage("test @al", selectedRange: .init(location: 5, length: 1))
|
|
try await deferred.fulfill()
|
|
|
|
deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
|
suggestions == [.init(suggestionType: .user(.init(id: alice.userID, displayName: alice.displayName, avatarURL: alice.avatarURL)), range: .init(location: 5, length: 3), rawSuggestionText: "al")]
|
|
}
|
|
service.processTextMessage("test @al test", selectedRange: .init(location: 5, length: 1))
|
|
try await deferred.fulfill()
|
|
}
|
|
|
|
@Test
|
|
func userSuggestionWithMultipleMentionSymbol() async throws {
|
|
let alice: RoomMemberProxyMock = .mockAlice
|
|
let bob: RoomMemberProxyMock = .mockBob
|
|
let members: [RoomMemberProxyMock] = [alice, bob, .mockCharlie, .mockMe]
|
|
let roomProxyMock = JoinedRoomProxyMock(.init(name: "test", members: members))
|
|
let roomSummaryProvider = RoomSummaryProviderMock(.init(state: .loaded(.mockRooms)))
|
|
let service = CompletionSuggestionService(roomProxy: roomProxyMock,
|
|
roomListPublisher: roomSummaryProvider.roomListPublisher.eraseToAnyPublisher())
|
|
|
|
var deffered = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
|
suggestions == [.init(suggestionType: .user(.init(id: alice.userID, displayName: alice.displayName, avatarURL: alice.avatarURL)), range: .init(location: 0, length: 3), rawSuggestionText: "al")]
|
|
}
|
|
service.processTextMessage("@al test @bo", selectedRange: .init(location: 0, length: 1))
|
|
try await deffered.fulfill()
|
|
|
|
deffered = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
|
suggestions == [.init(suggestionType: .user(.init(id: bob.userID, displayName: bob.displayName, avatarURL: bob.avatarURL)), range: .init(location: 9, length: 3), rawSuggestionText: "bo")]
|
|
}
|
|
service.processTextMessage("@al test @bo", selectedRange: .init(location: 9, length: 1))
|
|
try await deffered.fulfill()
|
|
|
|
deffered = deferFulfillment(service.suggestionsPublisher) { suggestion in
|
|
suggestion == []
|
|
}
|
|
service.processTextMessage("@al test @bo", selectedRange: .init(location: 4, length: 1))
|
|
try await deffered.fulfill()
|
|
}
|
|
|
|
@Test
|
|
func roomSuggestions() async throws {
|
|
let alice: RoomMemberProxyMock = .mockAlice
|
|
// We keep the users in the tests since they should not appear in the suggestions when using the room trigger
|
|
let members: [RoomMemberProxyMock] = [alice, .mockBob, .mockCharlie, .mockMe]
|
|
let roomProxyMock = JoinedRoomProxyMock(.init(id: "roomID", name: "test", members: members))
|
|
let roomSummaryProvider = RoomSummaryProviderMock(.init(state: .loaded(.mockRooms)))
|
|
let service = CompletionSuggestionService(roomProxy: roomProxyMock,
|
|
roomListPublisher: roomSummaryProvider.roomListPublisher.eraseToAnyPublisher())
|
|
|
|
var deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
|
suggestions == []
|
|
}
|
|
|
|
try await deferred.fulfill()
|
|
|
|
// The empty # should trigger suggestions from any room with an alias
|
|
deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
|
suggestions == [.init(suggestionType: .room(.init(id: "2",
|
|
canonicalAlias: "#foundation-and-empire:matrix.org",
|
|
name: "Foundation and Empire",
|
|
avatar: .room(id: "2",
|
|
name: "Foundation and Empire",
|
|
avatarURL: .mockMXCAvatar))),
|
|
range: .init(),
|
|
rawSuggestionText: ""),
|
|
.init(suggestionType: .room(.init(id: "6",
|
|
canonicalAlias: "#prelude-foundation:matrix.org",
|
|
name: "Prelude to Foundation",
|
|
avatar: .room(id: "6",
|
|
name: "Prelude to Foundation",
|
|
avatarURL: nil))),
|
|
range: .init(),
|
|
rawSuggestionText: "")]
|
|
}
|
|
service.setSuggestionTrigger(.init(type: .room, text: "", range: .init()))
|
|
try await deferred.fulfill()
|
|
|
|
// Same but with the processTextMessage method
|
|
deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
|
suggestions == [.init(suggestionType: .room(.init(id: "2",
|
|
canonicalAlias: "#foundation-and-empire:matrix.org",
|
|
name: "Foundation and Empire",
|
|
avatar: .room(id: "2",
|
|
name: "Foundation and Empire",
|
|
avatarURL: .mockMXCAvatar))),
|
|
range: .init(location: 0, length: 1),
|
|
rawSuggestionText: ""),
|
|
.init(suggestionType: .room(.init(id: "6",
|
|
canonicalAlias: "#prelude-foundation:matrix.org",
|
|
name: "Prelude to Foundation",
|
|
avatar: .room(id: "6",
|
|
name: "Prelude to Foundation",
|
|
avatarURL: nil))),
|
|
range: .init(location: 0, length: 1),
|
|
rawSuggestionText: "")]
|
|
}
|
|
service.processTextMessage("#", selectedRange: .init(location: 0, length: 1))
|
|
try await deferred.fulfill()
|
|
|
|
deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
|
suggestions == [.init(suggestionType: .room(.init(id: "6",
|
|
canonicalAlias: "#prelude-foundation:matrix.org",
|
|
name: "Prelude to Foundation",
|
|
avatar: .room(id: "6",
|
|
name: "Prelude to Foundation",
|
|
avatarURL: nil))),
|
|
range: .init(),
|
|
rawSuggestionText: "prelude")]
|
|
}
|
|
service.setSuggestionTrigger(.init(type: .room, text: "prelude", range: .init()))
|
|
try await deferred.fulfill()
|
|
}
|
|
|
|
@Test
|
|
func roomSuggestionInDifferentMessagePositions() async throws {
|
|
let alice: RoomMemberProxyMock = .mockAlice
|
|
// We keep the users in the tests since they should not appear in the suggestions when using the room trigger
|
|
let members: [RoomMemberProxyMock] = [alice, .mockBob, .mockCharlie, .mockMe]
|
|
let roomProxyMock = JoinedRoomProxyMock(.init(id: "roomID", name: "test", members: members))
|
|
let roomSummaryProvider = RoomSummaryProviderMock(.init(state: .loaded(.mockRooms)))
|
|
let service = CompletionSuggestionService(roomProxy: roomProxyMock,
|
|
roomListPublisher: roomSummaryProvider.roomListPublisher.eraseToAnyPublisher())
|
|
|
|
var deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
|
suggestions == [.init(suggestionType: .room(.init(id: "6",
|
|
canonicalAlias: "#prelude-foundation:matrix.org",
|
|
name: "Prelude to Foundation",
|
|
avatar: .room(id: "6",
|
|
name: "Prelude to Foundation",
|
|
avatarURL: nil))),
|
|
range: .init(location: 0, length: 3),
|
|
rawSuggestionText: "pr")]
|
|
}
|
|
service.processTextMessage("#pr hello", selectedRange: .init(location: 0, length: 1))
|
|
try await deferred.fulfill()
|
|
|
|
deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
|
suggestions == [.init(suggestionType: .room(.init(id: "6",
|
|
canonicalAlias: "#prelude-foundation:matrix.org",
|
|
name: "Prelude to Foundation",
|
|
avatar: .room(id: "6",
|
|
name: "Prelude to Foundation",
|
|
avatarURL: nil))),
|
|
range: .init(location: 5, length: 3),
|
|
rawSuggestionText: "pr")]
|
|
}
|
|
service.processTextMessage("test #pr", selectedRange: .init(location: 5, length: 1))
|
|
try await deferred.fulfill()
|
|
|
|
deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
|
suggestions == [.init(suggestionType: .room(.init(id: "6",
|
|
canonicalAlias: "#prelude-foundation:matrix.org",
|
|
name: "Prelude to Foundation",
|
|
avatar: .room(id: "6",
|
|
name: "Prelude to Foundation",
|
|
avatarURL: nil))),
|
|
range: .init(location: 5, length: 3),
|
|
rawSuggestionText: "pr")]
|
|
}
|
|
service.processTextMessage("test #pr test", selectedRange: .init(location: 5, length: 1))
|
|
try await deferred.fulfill()
|
|
}
|
|
|
|
@Test
|
|
func roomSuggestionWithMultipleMentionSymbol() async throws {
|
|
let alice: RoomMemberProxyMock = .mockAlice
|
|
// We keep the users in the tests since they should not appear in the suggestions when using the room trigger
|
|
let members: [RoomMemberProxyMock] = [alice, .mockBob, .mockCharlie, .mockMe]
|
|
let roomProxyMock = JoinedRoomProxyMock(.init(id: "roomID", name: "test", members: members))
|
|
let roomSummaryProvider = RoomSummaryProviderMock(.init(state: .loaded(.mockRooms)))
|
|
let service = CompletionSuggestionService(roomProxy: roomProxyMock,
|
|
roomListPublisher: roomSummaryProvider.roomListPublisher.eraseToAnyPublisher())
|
|
|
|
var deffered = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
|
suggestions == [.init(suggestionType: .room(.init(id: "6",
|
|
canonicalAlias: "#prelude-foundation:matrix.org",
|
|
name: "Prelude to Foundation",
|
|
avatar: .room(id: "6",
|
|
name: "Prelude to Foundation",
|
|
avatarURL: nil))),
|
|
range: .init(location: 0, length: 3),
|
|
rawSuggestionText: "pr")]
|
|
}
|
|
service.processTextMessage("#pr test #fo", selectedRange: .init(location: 0, length: 1))
|
|
try await deffered.fulfill()
|
|
|
|
deffered = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
|
suggestions == [.init(suggestionType: .room(.init(id: "2",
|
|
canonicalAlias: "#foundation-and-empire:matrix.org",
|
|
name: "Foundation and Empire",
|
|
avatar: .room(id: "2",
|
|
name: "Foundation and Empire",
|
|
avatarURL: .mockMXCAvatar))),
|
|
range: .init(location: 9, length: 3),
|
|
rawSuggestionText: "fo"),
|
|
.init(suggestionType: .room(.init(id: "6",
|
|
canonicalAlias: "#prelude-foundation:matrix.org",
|
|
name: "Prelude to Foundation",
|
|
avatar: .room(id: "6",
|
|
name: "Prelude to Foundation",
|
|
avatarURL: nil))),
|
|
range: .init(location: 9, length: 3),
|
|
rawSuggestionText: "fo")]
|
|
}
|
|
service.processTextMessage("#pr test #fo", selectedRange: .init(location: 9, length: 1))
|
|
try await deffered.fulfill()
|
|
|
|
deffered = deferFulfillment(service.suggestionsPublisher) { suggestion in
|
|
suggestion == []
|
|
}
|
|
service.processTextMessage("#pr test #fo", selectedRange: .init(location: 4, length: 1))
|
|
try await deffered.fulfill()
|
|
}
|
|
|
|
@Test
|
|
func suggestionsWithMultipleDifferentTriggers() async throws {
|
|
let alice: RoomMemberProxyMock = .mockAlice
|
|
// We keep the users in the tests since they should not appear in the suggestions when using the room trigger
|
|
let members: [RoomMemberProxyMock] = [alice, .mockBob, .mockCharlie, .mockMe]
|
|
let roomProxyMock = JoinedRoomProxyMock(.init(id: "roomID", name: "test", members: members))
|
|
let roomSummaryProvider = RoomSummaryProviderMock(.init(state: .loaded(.mockRooms)))
|
|
let service = CompletionSuggestionService(roomProxy: roomProxyMock,
|
|
roomListPublisher: roomSummaryProvider.roomListPublisher.eraseToAnyPublisher())
|
|
|
|
var deffered = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
|
suggestions == [.init(suggestionType: .room(.init(id: "6",
|
|
canonicalAlias: "#prelude-foundation:matrix.org",
|
|
name: "Prelude to Foundation",
|
|
avatar: .room(id: "6",
|
|
name: "Prelude to Foundation",
|
|
avatarURL: nil))),
|
|
range: .init(location: 0, length: 3),
|
|
rawSuggestionText: "pr")]
|
|
}
|
|
service.processTextMessage("#pr test @al", selectedRange: .init(location: 0, length: 1))
|
|
try await deffered.fulfill()
|
|
|
|
deffered = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
|
suggestions == [.init(suggestionType: .user(.init(id: alice.userID, displayName: alice.displayName, avatarURL: alice.avatarURL)), range: .init(location: 9, length: 3), rawSuggestionText: "al")]
|
|
}
|
|
service.processTextMessage("#pr test @al", selectedRange: .init(location: 9, length: 1))
|
|
try await deffered.fulfill()
|
|
}
|
|
|
|
@Test
|
|
func suggestionsContainingNonAlphanumericCharacters() async throws {
|
|
let alice: RoomMemberProxyMock = .mockAlice
|
|
// We keep the users in the tests since they should not appear in the suggestions when using the room trigger
|
|
let members: [RoomMemberProxyMock] = [alice, .mockBob, .mockCharlie, .mockMe]
|
|
let roomProxyMock = JoinedRoomProxyMock(.init(id: "roomID", name: "test", members: members))
|
|
let roomSummaryProvider = RoomSummaryProviderMock(.init(state: .loaded(.mockRooms)))
|
|
let service = CompletionSuggestionService(roomProxy: roomProxyMock,
|
|
roomListPublisher: roomSummaryProvider.roomListPublisher.eraseToAnyPublisher())
|
|
|
|
var deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
|
suggestions == []
|
|
}
|
|
|
|
try await deferred.fulfill()
|
|
|
|
deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
|
suggestions == [.init(suggestionType: .room(.init(id: "6",
|
|
canonicalAlias: "#prelude-foundation:matrix.org",
|
|
name: "Prelude to Foundation",
|
|
avatar: .room(id: "6",
|
|
name: "Prelude to Foundation",
|
|
avatarURL: nil))),
|
|
range: .init(),
|
|
rawSuggestionText: "#prelude-")]
|
|
}
|
|
service.setSuggestionTrigger(.init(type: .room, text: "#prelude-", range: .init()))
|
|
try await deferred.fulfill()
|
|
}
|
|
}
|