Render LiveLocations in the map (#5394)
This commit is contained in:
@@ -257,6 +257,72 @@ final class LocationSharingScreenViewModelTests {
|
||||
try await deferredFailure.fulfill()
|
||||
}
|
||||
|
||||
// MARK: - Live Location Share Update Tests
|
||||
|
||||
@Test
|
||||
func viewLiveInitialSenderShownCorrectly() {
|
||||
let aliceShare = makeLiveLocationShare(userID: "@alice:matrix.org", latitude: 51.5, longitude: -0.1)
|
||||
let sender = TimelineItemSender(id: "@alice:matrix.org", displayName: "Alice")
|
||||
let liveLocationsSubject = CurrentValueSubject<[LiveLocationShare], Never>([aliceShare])
|
||||
|
||||
setupViewModelForViewLive(sender: sender, initialShare: aliceShare, liveLocationsSubject: liveLocationsSubject)
|
||||
|
||||
// Initial state is synchronously set from the interaction mode before the async subscription runs.
|
||||
let annotations = context.viewState.annotations
|
||||
#expect(annotations.count == 1)
|
||||
let annotation = annotations.first
|
||||
#expect(annotation?.id == "@alice:matrix.org")
|
||||
#expect(annotation?.coordinate.latitude == 51.5)
|
||||
#expect(annotation?.coordinate.longitude == -0.1)
|
||||
#expect(annotation?.kind == .liveUser(.init(userID: "@alice:matrix.org", displayName: "Alice")))
|
||||
}
|
||||
|
||||
@Test
|
||||
func viewLiveReceivesAdditionalLocationUpdates() async throws {
|
||||
let aliceShare = makeLiveLocationShare(userID: "@alice:matrix.org", latitude: 51.5, longitude: -0.1)
|
||||
let sender = TimelineItemSender(id: "@alice:matrix.org", displayName: "Alice")
|
||||
let liveLocationsSubject = CurrentValueSubject<[LiveLocationShare], Never>([aliceShare])
|
||||
|
||||
setupViewModelForViewLive(sender: sender, initialShare: aliceShare, liveLocationsSubject: liveLocationsSubject)
|
||||
|
||||
let bobShare = makeLiveLocationShare(userID: "@bob:matrix.org", latitude: 48.8, longitude: 2.3)
|
||||
let charlieShare = makeLiveLocationShare(userID: "@charlie:matrix.org", latitude: 40.7, longitude: -74.0)
|
||||
|
||||
let deferred = deferFulfillment(context.observe(\.viewState.annotations)) { $0.count == 3 }
|
||||
liveLocationsSubject.send([aliceShare, bobShare, charlieShare])
|
||||
try await deferred.fulfill()
|
||||
|
||||
let annotations = context.viewState.annotations
|
||||
#expect(annotations.count == 3)
|
||||
let annotationIDs = Set(annotations.map(\.id))
|
||||
#expect(annotationIDs == ["@alice:matrix.org", "@bob:matrix.org", "@charlie:matrix.org"])
|
||||
#expect(annotations.first { $0.id == "@alice:matrix.org" }?.coordinate.latitude == 51.5)
|
||||
#expect(annotations.first { $0.id == "@bob:matrix.org" }?.coordinate.latitude == 48.8)
|
||||
#expect(annotations.first { $0.id == "@charlie:matrix.org" }?.coordinate.latitude == 40.7)
|
||||
}
|
||||
|
||||
@Test
|
||||
func viewLiveProfilesResolvedFromRoomMembers() async throws {
|
||||
let aliceShare = makeLiveLocationShare(userID: "@alice:matrix.org", latitude: 51.5, longitude: -0.1)
|
||||
let sender = TimelineItemSender(id: "@alice:matrix.org", displayName: "Alice")
|
||||
let liveLocationsSubject = CurrentValueSubject<[LiveLocationShare], Never>([aliceShare])
|
||||
|
||||
setupViewModelForViewLive(sender: sender, initialShare: aliceShare, liveLocationsSubject: liveLocationsSubject)
|
||||
|
||||
let bobShare = makeLiveLocationShare(userID: "@bob:matrix.org", latitude: 48.8, longitude: 2.3)
|
||||
let charlieShare = makeLiveLocationShare(userID: "@charlie:matrix.org", latitude: 40.7, longitude: -74.0)
|
||||
|
||||
let deferred = deferFulfillment(context.observe(\.viewState.annotations)) { $0.count == 3 }
|
||||
liveLocationsSubject.send([aliceShare, bobShare, charlieShare])
|
||||
try await deferred.fulfill()
|
||||
|
||||
// Annotation marker kinds should carry profiles resolved from room members.
|
||||
let annotations = context.viewState.annotations
|
||||
#expect(annotations.first { $0.id == "@alice:matrix.org" }?.kind == .liveUser(.init(userID: "@alice:matrix.org", displayName: "Alice")))
|
||||
#expect(annotations.first { $0.id == "@bob:matrix.org" }?.kind == .liveUser(.init(userID: "@bob:matrix.org", displayName: "Bob")))
|
||||
#expect(annotations.first { $0.id == "@charlie:matrix.org" }?.kind == .liveUser(.init(userID: "@charlie:matrix.org", displayName: "Charlie")))
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func setupViewModel(liveLocationManagerConfiguration: LiveLocationManagerMock.Configuration = .init()) {
|
||||
@@ -286,4 +352,32 @@ final class LocationSharingScreenViewModelTests {
|
||||
mediaProvider: MediaProviderMock(configuration: .init()))
|
||||
viewModel.state.bindings.isLocationAuthorized = true
|
||||
}
|
||||
|
||||
private func setupViewModelForViewLive(sender: TimelineItemSender,
|
||||
initialShare: LiveLocationShare,
|
||||
liveLocationsSubject: CurrentValueSubject<[LiveLocationShare], Never>,
|
||||
members: [RoomMemberProxyMock] = .allMembers) {
|
||||
let liveLocationServiceMock = RoomLiveLocationServiceMock()
|
||||
liveLocationServiceMock.liveLocationsPublisher = liveLocationsSubject.eraseToAnyPublisher()
|
||||
|
||||
let roomProxyMock = JoinedRoomProxyMock(.init(members: members))
|
||||
roomProxyMock.makeLiveLocationServiceReturnValue = liveLocationServiceMock
|
||||
|
||||
viewModel = LocationSharingScreenViewModel(interactionMode: .viewLive(sender: sender, initialLiveLocationShare: initialShare),
|
||||
mapURLBuilder: ServiceLocator.shared.settings.mapTilerConfiguration,
|
||||
liveLocationSharingEnabled: true,
|
||||
roomProxy: roomProxyMock,
|
||||
timelineController: MockTimelineController(timelineProxy: TimelineProxyMock(.init())),
|
||||
liveLocationManager: LiveLocationManagerMock(.init()),
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
mediaProvider: MediaProviderMock(configuration: .init()))
|
||||
}
|
||||
|
||||
private func makeLiveLocationShare(userID: String, latitude: Double = 0.0, longitude: Double = 0.0) -> LiveLocationShare {
|
||||
LiveLocationShare(userID: userID,
|
||||
geoURI: .init(latitude: latitude, longitude: longitude),
|
||||
timestamp: .distantPast,
|
||||
timeoutDate: .distantFuture)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user