55// Please see LICENSE files in the repository root for full details.
66//
77
8+ import Clocks
89import PushKit
910import XCTest
1011
@@ -13,39 +14,118 @@ import XCTest
1314@MainActor
1415class ElementCallServiceTests : XCTestCase {
1516 var callProvider : CXProviderMock !
17+ var currentDate : Date !
18+ var testClock : TestClock < Duration > !
1619 let pushRegistry = PKPushRegistry ( queue: nil )
1720
1821 var service : ElementCallService !
1922
2023 func testIncomingCall( ) async {
2124 setupService ( )
25+
2226 XCTAssertFalse ( callProvider. reportNewIncomingCallWithUpdateCompletionCalled)
2327
2428 let expectation = XCTestExpectation ( description: " Call accepted " )
2529
26- service. pushRegistry ( pushRegistry, didReceiveIncomingPushWith: PKPushPayloadMock ( ) , for: . voIP) {
30+ let pkPushPayloadMock = PKPushPayloadMock ( ) . addSeconds ( currentDate, lifetime: 30 )
31+
32+ service. pushRegistry ( pushRegistry, didReceiveIncomingPushWith: pkPushPayloadMock, for: . voIP) {
2733 expectation. fulfill ( )
2834 }
2935
3036 await fulfillment ( of: [ expectation] , timeout: 1 )
3137 XCTAssertTrue ( callProvider. reportNewIncomingCallWithUpdateCompletionCalled)
3238 }
3339
40+ func testCallIsTimingOut( ) async {
41+ setupService ( )
42+
43+ XCTAssertFalse ( callProvider. reportNewIncomingCallWithUpdateCompletionCalled)
44+
45+ let expectation = XCTestExpectation ( description: " Call accepted " )
46+
47+ let pushPayload = PKPushPayloadMock ( ) . addSeconds ( currentDate, lifetime: 20 )
48+
49+ service. pushRegistry ( pushRegistry,
50+ didReceiveIncomingPushWith: pushPayload,
51+ for: . voIP) {
52+ expectation. fulfill ( )
53+ }
54+ await fulfillment ( of: [ expectation] , timeout: 1 )
55+
56+ // advance past the timeout
57+ await testClock. advance ( by: . seconds( 30 ) )
58+
59+ // Call should have ended with unanswered
60+ XCTAssertTrue ( callProvider. reportCallWithEndedAtReasonCalled)
61+ XCTAssertEqual ( callProvider. reportCallWithEndedAtReasonReceivedArguments? . reason, . unanswered)
62+ }
63+
64+ func testExpiredRingLifetimeIsIgnored( ) async {
65+ setupService ( )
66+
67+ XCTAssertFalse ( callProvider. reportNewIncomingCallWithUpdateCompletionCalled)
68+
69+ let pushPayload = PKPushPayloadMock ( ) . addSeconds ( currentDate, lifetime: 20 )
70+
71+ currentDate = currentDate. addingTimeInterval ( 60 )
72+
73+ service. pushRegistry ( pushRegistry,
74+ didReceiveIncomingPushWith: pushPayload,
75+ for: . voIP) { }
76+ sleep ( 20 )
77+
78+ XCTAssertTrue ( !callProvider. reportNewIncomingCallWithUpdateCompletionCalled)
79+ }
80+
81+ func testLifetimeIsCapped( ) async {
82+ setupService ( )
83+
84+ XCTAssertFalse ( callProvider. reportNewIncomingCallWithUpdateCompletionCalled)
85+
86+ let pushPayload = PKPushPayloadMock ( ) . addSeconds ( currentDate, lifetime: 300 )
87+
88+ service. pushRegistry ( pushRegistry,
89+ didReceiveIncomingPushWith: pushPayload,
90+ for: . voIP) { }
91+
92+ // advance pass the max timeout but below the 300
93+ await testClock. advance ( by: . seconds( 100 ) )
94+
95+ // Call should have ended with unanswered
96+ XCTAssertTrue ( callProvider. reportCallWithEndedAtReasonCalled)
97+ XCTAssertEqual ( callProvider. reportCallWithEndedAtReasonReceivedArguments? . reason, . unanswered)
98+ }
99+
34100 // MARK: - Helpers
35101
36102 private func setupService( ) {
37103 callProvider = CXProviderMock ( . init( ) )
38- service = ElementCallService ( callProvider: callProvider)
104+ currentDate = Date ( )
105+ testClock = TestClock ( )
106+ let dateProvider : ( ) -> Date = {
107+ self . currentDate
108+ }
109+ service = ElementCallService ( callProvider: callProvider, timeClock: Time ( clock: testClock, nowDate: dateProvider) )
39110 }
40111}
41112
42113private class PKPushPayloadMock : PKPushPayload {
114+ var dict : [ AnyHashable : Any ] = [ : ]
115+
116+ override init ( ) {
117+ dict [ ElementCallServiceNotificationKey . roomID. rawValue] = " !room:example.com "
118+ dict [ ElementCallServiceNotificationKey . roomDisplayName. rawValue] = " welcome "
119+ dict [ ElementCallServiceNotificationKey . rtcNotifyEventID. rawValue] = " $000 "
120+ dict [ ElementCallServiceNotificationKey . expirationTimestampMillis. rawValue] = 10
121+ }
122+
43123 override var dictionaryPayload : [ AnyHashable : Any ] {
44- [
45- ElementCallServiceNotificationKey . roomID . rawValue : " 1 " ,
46- ElementCallServiceNotificationKey . roomDisplayName . rawValue : " Test " ,
47- ElementCallServiceNotificationKey . rtcNotifyEventID . rawValue : " a " ,
48- ElementCallServiceNotificationKey . expirationTimestampMillis. rawValue: UInt64 ( ( Date ( ) . timeIntervalSince1970 + 5 ) * 1000 )
49- ]
124+ dict
125+ }
126+
127+ func addSeconds ( _ from : Date , lifetime : Int ) -> Self {
128+ dict [ ElementCallServiceNotificationKey . expirationTimestampMillis. rawValue] = UInt64 ( from . timeIntervalSince1970 * 1000 ) + UInt64 ( lifetime )
129+ return self
50130 }
51131}
0 commit comments