mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 03:06:37 +00:00
Add a Low Priority room filter behind a feature flag. (#4394)
* Add Low Priority room filter with incompatibility rules Co-authored-by: pixlwave <6060466+pixlwave@users.noreply.github.com> * Add a feature flag and use the SDK filters. * Fix filter tests and add RoomSummaryProvider tests for the default filters. * Remove unnecessary comment. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: pixlwave <6060466+pixlwave@users.noreply.github.com> Co-authored-by: Doug <douglase@element.io>
This commit is contained in:
@@ -10,16 +10,25 @@ import XCTest
|
||||
@testable import ElementX
|
||||
|
||||
final class RoomListFiltersStateTests: XCTestCase {
|
||||
var appSettings: AppSettings!
|
||||
|
||||
var state: RoomListFiltersState!
|
||||
var allCasesWithoutLowPriority = RoomListFilter.allCases.filter { $0 != .lowPriority }
|
||||
|
||||
override func setUp() {
|
||||
state = RoomListFiltersState()
|
||||
AppSettings.resetAllSettings()
|
||||
appSettings = AppSettings()
|
||||
state = RoomListFiltersState(appSettings: appSettings)
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
AppSettings.resetAllSettings()
|
||||
}
|
||||
|
||||
func testInitialState() {
|
||||
XCTAssertFalse(state.isFiltering)
|
||||
XCTAssertEqual(state.activeFilters, [])
|
||||
XCTAssertEqual(state.availableFilters, RoomListFilter.allCases)
|
||||
XCTAssertEqual(state.availableFilters, allCasesWithoutLowPriority)
|
||||
}
|
||||
|
||||
func testSetAndUnsetFilters() {
|
||||
@@ -30,7 +39,7 @@ final class RoomListFiltersStateTests: XCTestCase {
|
||||
state.deactivateFilter(.unreads)
|
||||
XCTAssertFalse(state.isFiltering)
|
||||
XCTAssertEqual(state.activeFilters, [])
|
||||
XCTAssertEqual(state.availableFilters, RoomListFilter.allCases)
|
||||
XCTAssertEqual(state.availableFilters, allCasesWithoutLowPriority)
|
||||
}
|
||||
|
||||
func testMutuallyExclusiveFilters() {
|
||||
@@ -42,7 +51,7 @@ final class RoomListFiltersStateTests: XCTestCase {
|
||||
state.deactivateFilter(.people)
|
||||
XCTAssertFalse(state.isFiltering)
|
||||
XCTAssertEqual(state.activeFilters, [])
|
||||
XCTAssertEqual(state.availableFilters, RoomListFilter.allCases)
|
||||
XCTAssertEqual(state.availableFilters, allCasesWithoutLowPriority)
|
||||
|
||||
state.activateFilter(.rooms)
|
||||
XCTAssertTrue(state.isFiltering)
|
||||
@@ -71,7 +80,7 @@ final class RoomListFiltersStateTests: XCTestCase {
|
||||
state.clearFilters()
|
||||
XCTAssertFalse(state.isFiltering)
|
||||
XCTAssertEqual(state.activeFilters, [])
|
||||
XCTAssertEqual(state.availableFilters, RoomListFilter.allCases)
|
||||
XCTAssertEqual(state.availableFilters, allCasesWithoutLowPriority)
|
||||
}
|
||||
|
||||
func testOrder() {
|
||||
@@ -81,7 +90,7 @@ final class RoomListFiltersStateTests: XCTestCase {
|
||||
|
||||
state.deactivateFilter(.favourites)
|
||||
XCTAssertEqual(state.activeFilters, [])
|
||||
XCTAssertEqual(state.availableFilters, RoomListFilter.allCases)
|
||||
XCTAssertEqual(state.availableFilters, allCasesWithoutLowPriority)
|
||||
|
||||
state.activateFilter(.rooms)
|
||||
XCTAssertEqual(state.activeFilters, [.rooms])
|
||||
@@ -95,4 +104,25 @@ final class RoomListFiltersStateTests: XCTestCase {
|
||||
XCTAssertEqual(state.activeFilters, [.rooms])
|
||||
XCTAssertEqual(state.availableFilters, [.unreads, .favourites])
|
||||
}
|
||||
|
||||
// MARK: Low Priority feature flag
|
||||
|
||||
// Don't forget to add .lowPriority into the mix above when enabling the feature.
|
||||
func testWithLowPriorityFeature() {
|
||||
enableLowPriorityFeature()
|
||||
XCTAssertFalse(state.isFiltering)
|
||||
XCTAssertEqual(state.activeFilters, [])
|
||||
XCTAssertEqual(state.availableFilters, RoomListFilter.allCases)
|
||||
|
||||
state.activateFilter(.lowPriority)
|
||||
XCTAssertEqual(state.activeFilters, [.lowPriority])
|
||||
XCTAssertEqual(state.availableFilters, [.unreads, .people, .rooms])
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
private func enableLowPriorityFeature() {
|
||||
appSettings.lowPriorityFilterEnabled = true
|
||||
state = RoomListFiltersState(appSettings: appSettings)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
//
|
||||
// Copyright 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 XCTest
|
||||
|
||||
@testable import ElementX
|
||||
|
||||
final class RoomSummaryProviderTests: XCTestCase {
|
||||
var appSettings: AppSettings!
|
||||
var roomList: RoomListSDKMock!
|
||||
var dynamicEntriesController: RoomListDynamicEntriesControllerSDKMock!
|
||||
|
||||
var roomSummaryProvider: RoomSummaryProvider!
|
||||
|
||||
override func setUp() {
|
||||
AppSettings.resetAllSettings()
|
||||
appSettings = AppSettings()
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
AppSettings.resetAllSettings()
|
||||
}
|
||||
|
||||
func testDefaultRustFilters() async {
|
||||
// Given a new room provider.
|
||||
setupProvider()
|
||||
await Task.yield()
|
||||
|
||||
// Then it should have the default Rust filters enabled.
|
||||
XCTAssertEqual(dynamicEntriesController.setFilterKindCallsCount, 1)
|
||||
XCTAssertEqual(dynamicEntriesController.setFilterKindReceivedInvocations.last, .all(filters: [.nonLeft,
|
||||
.nonSpace,
|
||||
.deduplicateVersions]))
|
||||
|
||||
// When setting one our user filters.
|
||||
roomSummaryProvider.setFilter(.all(filters: [.favourites]))
|
||||
await Task.yield()
|
||||
|
||||
// Then that filter should be added to the default Rust filters.
|
||||
XCTAssertEqual(dynamicEntriesController.setFilterKindCallsCount, 2)
|
||||
XCTAssertEqual(dynamicEntriesController.setFilterKindReceivedInvocations.last, .all(filters: [.all(filters: [.favourite, .joined]),
|
||||
.nonLeft,
|
||||
.nonSpace,
|
||||
.deduplicateVersions]))
|
||||
}
|
||||
|
||||
func testLowPriorityRustFilters() async {
|
||||
// Given a new room provider with the low priority filter enabled.
|
||||
setupProvider(isLowPriorityFilterEnabled: true)
|
||||
await Task.yield()
|
||||
|
||||
// Then the default Rust filters should include the non-low priority filter,
|
||||
// so that low priority rooms are hidden from the top of the room list.
|
||||
XCTAssertEqual(dynamicEntriesController.setFilterKindCallsCount, 1)
|
||||
XCTAssertEqual(dynamicEntriesController.setFilterKindReceivedInvocations.last, .all(filters: [.nonLeft,
|
||||
.nonSpace,
|
||||
.deduplicateVersions,
|
||||
.all(filters: [.nonLowPriority, .joined])]))
|
||||
|
||||
// When setting the low priority filter.
|
||||
roomSummaryProvider.setFilter(.all(filters: [.lowPriority]))
|
||||
await Task.yield()
|
||||
|
||||
// Then the non-low priority filter should be replaced with the low priority filter.
|
||||
XCTAssertEqual(dynamicEntriesController.setFilterKindCallsCount, 2)
|
||||
XCTAssertEqual(dynamicEntriesController.setFilterKindReceivedInvocations.last, .all(filters: [.all(filters: [.lowPriority, .joined]),
|
||||
.nonLeft,
|
||||
.nonSpace,
|
||||
.deduplicateVersions]))
|
||||
|
||||
// When setting another one of our filters.
|
||||
roomSummaryProvider.setFilter(.all(filters: [.rooms]))
|
||||
await Task.yield()
|
||||
|
||||
// Then the filter should be combined with the non-low priority filter.
|
||||
XCTAssertEqual(dynamicEntriesController.setFilterKindCallsCount, 3)
|
||||
XCTAssertEqual(dynamicEntriesController.setFilterKindReceivedInvocations.last, .all(filters: [.all(filters: [.category(expect: .group), .joined]),
|
||||
.nonLeft,
|
||||
.nonSpace,
|
||||
.deduplicateVersions,
|
||||
.all(filters: [.nonLowPriority, .joined])]))
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
private func setupProvider(isLowPriorityFilterEnabled: Bool = false) {
|
||||
appSettings.lowPriorityFilterEnabled = isLowPriorityFilterEnabled
|
||||
|
||||
let stateEventStringBuilder = RoomStateEventStringBuilder(userID: "@me:matrix.org")
|
||||
let attributedStringBuilder = AttributedStringBuilder(mentionBuilder: MentionBuilder())
|
||||
let eventStringBuilder = RoomEventStringBuilder(stateEventStringBuilder: stateEventStringBuilder,
|
||||
messageEventStringBuilder: RoomMessageEventStringBuilder(attributedStringBuilder: attributedStringBuilder,
|
||||
destination: .roomList),
|
||||
shouldDisambiguateDisplayNames: true,
|
||||
shouldPrefixSenderName: true)
|
||||
|
||||
roomSummaryProvider = RoomSummaryProvider(roomListService: RoomListServiceSDKMock(),
|
||||
eventStringBuilder: eventStringBuilder,
|
||||
name: "Test",
|
||||
notificationSettings: NotificationSettingsProxyMock(with: .init()),
|
||||
appSettings: appSettings)
|
||||
|
||||
dynamicEntriesController = RoomListDynamicEntriesControllerSDKMock()
|
||||
dynamicEntriesController.setFilterKindReturnValue = true
|
||||
let dynamicAdaptersResult = RoomListEntriesWithDynamicAdaptersResultSDKMock()
|
||||
dynamicAdaptersResult.controllerReturnValue = dynamicEntriesController
|
||||
roomList = RoomListSDKMock()
|
||||
roomList.entriesWithDynamicAdaptersPageSizeListenerReturnValue = dynamicAdaptersResult
|
||||
roomList.loadingStateListenerReturnValue = .some(.init(state: .notLoaded, stateStream: .init(noPointer: .init())))
|
||||
roomSummaryProvider.setRoomList(roomList)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user