@@ -13,6 +13,8 @@ final class MapboxNavigatorTests: TestCase {
13
13
var routeRefreshResult : RouteRefreshResult !
14
14
let timeout : TimeInterval = 0.5
15
15
16
+ var routeProgressExpectation : XCTestExpectation ?
17
+
16
18
override func setUp( ) async throws {
17
19
try ? await super. setUp ( )
18
20
@@ -44,6 +46,14 @@ final class MapboxNavigatorTests: TestCase {
44
46
movementMonitor: . init( )
45
47
)
46
48
navigator = await MapboxNavigator ( configuration: coonfiguration)
49
+
50
+ routeProgressExpectation = nil
51
+ navigator. routeProgress
52
+ . dropFirst ( )
53
+ . sink ( receiveValue: { [ weak self] _ in
54
+ self ? . routeProgressExpectation? . fulfill ( )
55
+ } )
56
+ . store ( in: & subscriptions)
47
57
}
48
58
49
59
@MainActor
@@ -258,4 +268,119 @@ final class MapboxNavigatorTests: TestCase {
258
268
await navigator. updateMapMatching ( status: status)
259
269
await fulfillment ( of: [ expectation] , timeout: timeout)
260
270
}
271
+
272
+ @MainActor
273
+ func testSetRoutesSimilarNewRouteKeepsSession( ) async {
274
+ await startActiveGuidanceAndWaitForRouteProgress ( with: oneLegNavigationRoutes ( ) )
275
+ await setRoutesAndWaitForRouteProgress ( with: oneLegNavigationRoutes ( ) , reason: . newRoute)
276
+
277
+ billingServiceMock. assertEvents ( [ . beginBillingSession( . activeGuidance) ] )
278
+ }
279
+
280
+ @MainActor
281
+ func testSetRoutesSimilarRerouteKeepsSession( ) async {
282
+ await startActiveGuidanceAndWaitForRouteProgress ( with: oneLegNavigationRoutes ( ) )
283
+ await setRoutesAndWaitForRouteProgress ( with: oneLegNavigationRoutes ( ) , reason: . reroute)
284
+
285
+ billingServiceMock. assertEvents ( [ . beginBillingSession( . activeGuidance) ] )
286
+ }
287
+
288
+ @MainActor
289
+ func testSetRoutesDifferentNewRouteBeginsNewSession( ) async {
290
+ await startActiveGuidanceAndWaitForRouteProgress ( with: twoLegNavigationRoutes ( ) )
291
+ await setRoutesAndWaitForRouteProgress ( with: oneLegNavigationRoutes ( ) , reason: . newRoute)
292
+
293
+ billingServiceMock. assertEvents ( [
294
+ . beginBillingSession( . activeGuidance) ,
295
+ . stopBillingSession( . activeGuidance) ,
296
+ . beginBillingSession( . activeGuidance) ,
297
+ ] )
298
+ }
299
+
300
+ @MainActor
301
+ func testSetRoutesDifferentRerouteBeginsNewSession( ) async {
302
+ await startActiveGuidanceAndWaitForRouteProgress ( with: twoLegNavigationRoutes ( ) )
303
+ await setRoutesAndWaitForRouteProgress ( with: oneLegNavigationRoutes ( ) , reason: . reroute)
304
+
305
+ billingServiceMock. assertEvents ( [
306
+ . beginBillingSession( . activeGuidance) ,
307
+ . stopBillingSession( . activeGuidance) ,
308
+ . beginBillingSession( . activeGuidance) ,
309
+ ] )
310
+ }
311
+
312
+ @MainActor
313
+ func testSetRoutesMapMatchingRerouteToDirectionsWithSameDestinationKeepsSession( ) async {
314
+ // This scenario happens with RerouteStrategyForMatchRoute.navigateToFinalDestination
315
+ // when there were more than one waypoint remaining before reroute
316
+ await startActiveGuidanceAndWaitForRouteProgress ( with: twoLegNavigationRoutes ( mapboxApi: . mapMatching) )
317
+ await setRoutesAndWaitForRouteProgress ( with: oneLegNavigationRoutes ( mapboxApi: . directions) , reason: . reroute)
318
+
319
+ billingServiceMock. assertEvents ( [ . beginBillingSession( . activeGuidance) ] )
320
+ }
321
+
322
+ // MARK: - Helpers
323
+
324
+ private func startActiveGuidanceAndWaitForRouteProgress(
325
+ with navigationRoutes: NavigationRoutes
326
+ ) async {
327
+ await navigator. startActiveGuidance ( with: navigationRoutes, startLegIndex: 0 )
328
+ routeProgressExpectation = XCTestExpectation ( description: " route progress after startActiveGuidance " )
329
+ await fulfillment ( of: [ routeProgressExpectation!] , timeout: timeout)
330
+ }
331
+
332
+ private func setRoutesAndWaitForRouteProgress(
333
+ with navigationRoutes: NavigationRoutes ,
334
+ reason: MapboxNavigator . SetRouteReason
335
+ ) async {
336
+ await navigator. setRoutes ( navigationRoutes: navigationRoutes, startLegIndex: 0 , reason: reason)
337
+ routeProgressExpectation = XCTestExpectation ( description: " route progress after setRoutes " )
338
+ await fulfillment ( of: [ routeProgressExpectation!] , timeout: timeout)
339
+ }
340
+
341
+ // Three points along California St in San Fransisco
342
+ private let coordinateA = CLLocationCoordinate2D ( latitude: 37.785832 , longitude: - 122.458148 )
343
+ private let coordinateB = CLLocationCoordinate2D ( latitude: 37.787594 , longitude: - 122.444172 )
344
+ private let coordinateC = CLLocationCoordinate2D ( latitude: 37.78927 , longitude: - 122.430577 )
345
+
346
+ private func oneLegNavigationRoutes(
347
+ mapboxApi: MapboxAPI = . directions
348
+ ) async -> NavigationRoutes {
349
+ await mockNavigationRoutes (
350
+ with: [ mockLeg ( from: coordinateA, to: coordinateC) ] ,
351
+ mapboxApi: mapboxApi
352
+ )
353
+ }
354
+
355
+ private func twoLegNavigationRoutes(
356
+ mapboxApi: MapboxAPI = . directions
357
+ ) async -> NavigationRoutes {
358
+ await mockNavigationRoutes (
359
+ with: [
360
+ mockLeg ( from: coordinateA, to: coordinateB) ,
361
+ mockLeg ( from: coordinateB, to: coordinateC) ,
362
+ ] ,
363
+ mapboxApi: mapboxApi
364
+ )
365
+ }
366
+
367
+ private func mockNavigationRoutes(
368
+ with legs: [ RouteLeg ] ,
369
+ mapboxApi: MapboxAPI = . directions
370
+ ) async -> NavigationRoutes {
371
+ await NavigationRoutes . mock ( mainRoute: . mock(
372
+ route: . mock( legs: legs) ,
373
+ nativeRoute: RouteInterfaceMock ( mapboxApi: mapboxApi)
374
+ ) )
375
+ }
376
+
377
+ private func mockLeg(
378
+ from source: CLLocationCoordinate2D ,
379
+ to destination: CLLocationCoordinate2D
380
+ ) -> RouteLeg {
381
+ var leg = RouteLeg . mock ( )
382
+ leg. source = Waypoint ( coordinate: source)
383
+ leg. destination = Waypoint ( coordinate: destination)
384
+ return leg
385
+ }
261
386
}
0 commit comments