Skip to content

Commit 63e309b

Browse files
committed
Add more test cases for livequery
1 parent ae536ca commit 63e309b

File tree

4 files changed

+240
-3
lines changed

4 files changed

+240
-3
lines changed

ParseSwift.xcodeproj/project.pbxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,9 @@
388388
918CED5A2684C74000CFDC83 /* ParseLiveQuery+combine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 918CED582684C74000CFDC83 /* ParseLiveQuery+combine.swift */; };
389389
918CED5B2684C74000CFDC83 /* ParseLiveQuery+combine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 918CED582684C74000CFDC83 /* ParseLiveQuery+combine.swift */; };
390390
918CED5C2684C74000CFDC83 /* ParseLiveQuery+combine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 918CED582684C74000CFDC83 /* ParseLiveQuery+combine.swift */; };
391+
918CED5E268618C600CFDC83 /* ParseLiveQueryCombineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 918CED5D268618C600CFDC83 /* ParseLiveQueryCombineTests.swift */; };
392+
918CED5F268618C600CFDC83 /* ParseLiveQueryCombineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 918CED5D268618C600CFDC83 /* ParseLiveQueryCombineTests.swift */; };
393+
918CED60268618C600CFDC83 /* ParseLiveQueryCombineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 918CED5D268618C600CFDC83 /* ParseLiveQueryCombineTests.swift */; };
391394
9194657824F16E330070296B /* ParseACLTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9194657724F16E330070296B /* ParseACLTests.swift */; };
392395
91B40651267A66ED00B129CD /* ParseErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91B40650267A66ED00B129CD /* ParseErrorTests.swift */; };
393396
91B40652267A66ED00B129CD /* ParseErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91B40650267A66ED00B129CD /* ParseErrorTests.swift */; };
@@ -712,6 +715,7 @@
712715
916786E1259B7DDA00BB5B4E /* ParseCloud.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseCloud.swift; sourceTree = "<group>"; };
713716
916786EF259BC59600BB5B4E /* ParseCloudTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseCloudTests.swift; sourceTree = "<group>"; };
714717
918CED582684C74000CFDC83 /* ParseLiveQuery+combine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ParseLiveQuery+combine.swift"; sourceTree = "<group>"; };
718+
918CED5D268618C600CFDC83 /* ParseLiveQueryCombineTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseLiveQueryCombineTests.swift; sourceTree = "<group>"; };
715719
9194657724F16E330070296B /* ParseACLTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseACLTests.swift; sourceTree = "<group>"; };
716720
91B40650267A66ED00B129CD /* ParseErrorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseErrorTests.swift; sourceTree = "<group>"; };
717721
91CB9536265966DF0043E5D6 /* ParseAnanlyticsCombineTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseAnanlyticsCombineTests.swift; sourceTree = "<group>"; };
@@ -894,6 +898,7 @@
894898
70386A5B25D9A4010048EC1B /* ParseLDAPCombineTests.swift */,
895899
70386A4525D99C8B0048EC1B /* ParseLDAPTests.swift */,
896900
7003963A25A288100052CB31 /* ParseLiveQueryTests.swift */,
901+
918CED5D268618C600CFDC83 /* ParseLiveQueryCombineTests.swift */,
897902
70C7DC2024D20F190050419B /* ParseObjectBatchTests.swift */,
898903
7044C1DE25C5C70D0011F6E7 /* ParseObjectCombine.swift */,
899904
70732C592606CCAD000CAB81 /* ParseObjectCustomObjectIdTests.swift */,
@@ -1742,6 +1747,7 @@
17421747
isa = PBXSourcesBuildPhase;
17431748
buildActionMask = 2147483647;
17441749
files = (
1750+
918CED5E268618C600CFDC83 /* ParseLiveQueryCombineTests.swift in Sources */,
17451751
911DB13624C4FC100027F3C7 /* ParseObjectTests.swift in Sources */,
17461752
70E09E1C262F0634002DD451 /* ParsePointerCombineTests.swift in Sources */,
17471753
89899D592603CF3E002E2043 /* ParseTwitterTests.swift in Sources */,
@@ -1906,6 +1912,7 @@
19061912
isa = PBXSourcesBuildPhase;
19071913
buildActionMask = 2147483647;
19081914
files = (
1915+
918CED60268618C600CFDC83 /* ParseLiveQueryCombineTests.swift in Sources */,
19091916
709B98512556ECAA00507778 /* ParseEncoderExtraTests.swift in Sources */,
19101917
70E09E1E262F0634002DD451 /* ParsePointerCombineTests.swift in Sources */,
19111918
89899D642603CF3F002E2043 /* ParseTwitterTests.swift in Sources */,
@@ -1968,6 +1975,7 @@
19681975
isa = PBXSourcesBuildPhase;
19691976
buildActionMask = 2147483647;
19701977
files = (
1978+
918CED5F268618C600CFDC83 /* ParseLiveQueryCombineTests.swift in Sources */,
19711979
70F2E2B6254F283000B2EA5C /* ParseACLTests.swift in Sources */,
19721980
70E09E1D262F0634002DD451 /* ParsePointerCombineTests.swift in Sources */,
19731981
89899D632603CF3E002E2043 /* ParseTwitterTests.swift in Sources */,

Sources/ParseSwift/LiveQuery/ParseLiveQuery.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,15 @@ extension ParseLiveQuery {
243243
//Remove in subscriptions just in case the server
244244
//responded before this was called
245245
self.subscriptions.removeValue(forKey: requestIdToRemove)
246+
closeWebsocketIfNoSubscriptions()
247+
}
248+
249+
func closeWebsocketIfNoSubscriptions() {
250+
self.notificationQueue.async {
251+
if self.subscriptions.isEmpty && self.pendingSubscriptions.isEmpty {
252+
self.close()
253+
}
254+
}
246255
}
247256

248257
/// Set a specific ParseLiveQuery client to be the default for all `ParseLiveQuery` connections.
@@ -288,6 +297,7 @@ extension ParseLiveQuery {
288297
public func removePendingSubscription<T: ParseObject>(_ query: Query<T>) throws {
289298
let queryData = try ParseCoding.jsonEncoder().encode(query)
290299
pendingSubscriptions.removeAll(where: { (_, value) -> Bool in
300+
self.closeWebsocketIfNoSubscriptions()
291301
if queryData == value.queryData {
292302
return true
293303
} else {
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
//
2+
// ParseLiveQueryCombineTests.swift
3+
// ParseSwift
4+
//
5+
// Created by Corey Baker on 6/25/21.
6+
// Copyright © 2021 Parse Community. All rights reserved.
7+
//
8+
9+
#if !os(Linux) && !os(Android)
10+
import Foundation
11+
import XCTest
12+
@testable import ParseSwift
13+
#if canImport(Combine)
14+
import Combine
15+
#endif
16+
17+
@available(macOS 10.15, iOS 13.0, macCatalyst 13.0, watchOS 6.0, tvOS 13.0, *)
18+
class ParseLiveQueryCombineTests: XCTestCase {
19+
20+
override func setUpWithError() throws {
21+
try super.setUpWithError()
22+
guard let url = URL(string: "http://localhost:1337/1") else {
23+
XCTFail("Should create valid URL")
24+
return
25+
}
26+
ParseSwift.initialize(applicationId: "applicationId",
27+
clientKey: "clientKey",
28+
masterKey: "masterKey",
29+
serverURL: url,
30+
testing: true)
31+
ParseLiveQuery.setDefault(try ParseLiveQuery(isDefault: true))
32+
}
33+
34+
override func tearDownWithError() throws {
35+
try super.tearDownWithError()
36+
MockURLProtocol.removeAll()
37+
#if !os(Linux) && !os(Android)
38+
try KeychainStore.shared.deleteAll()
39+
#endif
40+
try ParseStorage.shared.deleteAll()
41+
URLSession.liveQuery.closeAll()
42+
}
43+
44+
func testOpen() throws {
45+
guard let client = ParseLiveQuery.getDefault() else {
46+
XCTFail("Should be able to get client")
47+
return
48+
}
49+
client.close()
50+
51+
var subscriptions = Set<AnyCancellable>()
52+
let expectation1 = XCTestExpectation(description: "Send Ping")
53+
let publisher = client.openPublisher(isUserWantsToConnect: true)
54+
.sink(receiveCompletion: { result in
55+
56+
switch result {
57+
58+
case .finished:
59+
XCTFail("Should have produced failure")
60+
case .failure(let error):
61+
XCTAssertNotNil(error) //Should always fail since WS isn't intercepted.
62+
}
63+
expectation1.fulfill()
64+
65+
}, receiveValue: { _ in
66+
XCTFail("Should have produced error")
67+
})
68+
publisher.store(in: &subscriptions)
69+
wait(for: [expectation1], timeout: 20.0)
70+
}
71+
72+
func testPingSocketNotEstablished() throws {
73+
guard let client = ParseLiveQuery.getDefault() else {
74+
XCTFail("Should be able to get client")
75+
return
76+
}
77+
client.close()
78+
var subscriptions = Set<AnyCancellable>()
79+
let expectation1 = XCTestExpectation(description: "Send Ping")
80+
let publisher = client.sendPingPublisher()
81+
.sink(receiveCompletion: { result in
82+
83+
switch result {
84+
85+
case .finished:
86+
XCTFail("Should have produced failure")
87+
case .failure(let error):
88+
XCTAssertEqual(client.isSocketEstablished, false)
89+
XCTAssertNil(client.task)
90+
guard let parseError = error as? ParseError else {
91+
XCTFail("Should have casted to ParseError.")
92+
expectation1.fulfill()
93+
return
94+
}
95+
XCTAssertEqual(parseError.code, ParseError.Code.unknownError)
96+
XCTAssertTrue(parseError.message.contains("pinged"))
97+
}
98+
expectation1.fulfill()
99+
100+
}, receiveValue: { _ in
101+
XCTFail("Should have produced error")
102+
})
103+
publisher.store(in: &subscriptions)
104+
wait(for: [expectation1], timeout: 20.0)
105+
}
106+
107+
func testPing() throws {
108+
guard let client = ParseLiveQuery.getDefault() else {
109+
XCTFail("Should be able to get client")
110+
return
111+
}
112+
client.isSocketEstablished = true // Socket needs to be true
113+
client.isConnecting = true
114+
client.isConnected = true
115+
client.clientId = "yolo"
116+
117+
var subscriptions = Set<AnyCancellable>()
118+
let expectation1 = XCTestExpectation(description: "Send Ping")
119+
let publisher = client.sendPingPublisher()
120+
.sink(receiveCompletion: { result in
121+
122+
switch result {
123+
124+
case .finished:
125+
XCTFail("Should have produced failure")
126+
case .failure(let error):
127+
XCTAssertEqual(client.isSocketEstablished, true)
128+
XCTAssertNotNil(error) // Should have error because testcases don't intercept websocket
129+
}
130+
expectation1.fulfill()
131+
132+
}, receiveValue: { _ in
133+
XCTFail("Should have produced error")
134+
})
135+
publisher.store(in: &subscriptions)
136+
wait(for: [expectation1], timeout: 20.0)
137+
}
138+
}
139+
#endif

Tests/ParseSwiftTests/ParseLiveQueryTests.swift

Lines changed: 83 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ class ParseLiveQueryTests: XCTestCase {
314314
XCTFail("Should be able to get client")
315315
return
316316
}
317-
client.isSocketEstablished = true // Socket neets to be true
317+
client.isSocketEstablished = true // Socket needs to be true
318318
client.isConnecting = true
319319
client.isConnected = true
320320
client.attempts = 5
@@ -325,14 +325,27 @@ class ParseLiveQueryTests: XCTestCase {
325325
XCTAssertEqual(client.isConnecting, false)
326326
XCTAssertEqual(client.clientId, "yolo")
327327
XCTAssertEqual(client.attempts, 5)
328+
329+
// Test too many attempts and close
330+
client.isSocketEstablished = true // Socket needs to be true
331+
client.isConnecting = true
332+
client.isConnected = true
333+
client.attempts = ParseLiveQueryConstants.maxConnectionAttempts + 1
334+
client.clientId = "yolo"
335+
client.isDisconnectedByUser = false
336+
337+
XCTAssertEqual(client.isSocketEstablished, false)
338+
XCTAssertEqual(client.isConnecting, false)
339+
XCTAssertEqual(client.clientId, "yolo")
340+
XCTAssertEqual(client.attempts, ParseLiveQueryConstants.maxConnectionAttempts + 1)
328341
}
329342

330343
func testDisconnectedState() throws {
331344
guard let client = ParseLiveQuery.getDefault() else {
332345
XCTFail("Should be able to get client")
333346
return
334347
}
335-
client.isSocketEstablished = true // Socket neets to be true
348+
client.isSocketEstablished = true // Socket needs to be true
336349
client.isConnecting = true
337350
client.isConnected = true
338351
client.clientId = "yolo"
@@ -353,7 +366,7 @@ class ParseLiveQueryTests: XCTestCase {
353366
XCTFail("Should be able to get client")
354367
return
355368
}
356-
client.isSocketEstablished = true // Socket neets to be true
369+
client.isSocketEstablished = true // Socket needs to be true
357370
client.isConnecting = true
358371
client.isConnected = true
359372
client.clientId = "yolo"
@@ -392,6 +405,70 @@ class ParseLiveQueryTests: XCTestCase {
392405
XCTAssertEqual(client.isDisconnectedByUser, true)
393406
}
394407

408+
func testOpenSocket() throws {
409+
guard let client = ParseLiveQuery.getDefault() else {
410+
XCTFail("Should be able to get client")
411+
return
412+
}
413+
client.close()
414+
client.open(isUserWantsToConnect: true) { error in
415+
XCTAssertNotNil(error) //Should always fail since WS isn't intercepted.
416+
}
417+
}
418+
419+
func testCloseAll() throws {
420+
guard let client = ParseLiveQuery.getDefault() else {
421+
XCTFail("Should be able to get client")
422+
return
423+
}
424+
client.closeAll()
425+
client.synchronizationQueue.asyncAfter(deadline: .now() + 2) {
426+
XCTAssertFalse(client.isSocketEstablished)
427+
XCTAssertNil(client.task)
428+
}
429+
}
430+
431+
func testPingSocketNotEstablished() throws {
432+
guard let client = ParseLiveQuery.getDefault() else {
433+
XCTFail("Should be able to get client")
434+
return
435+
}
436+
client.close()
437+
let expectation1 = XCTestExpectation(description: "Send Ping")
438+
client.sendPing { error in
439+
XCTAssertEqual(client.isSocketEstablished, false)
440+
XCTAssertNil(client.task)
441+
guard let parseError = error as? ParseError else {
442+
XCTFail("Should have casted to ParseError.")
443+
expectation1.fulfill()
444+
return
445+
}
446+
XCTAssertEqual(parseError.code, ParseError.Code.unknownError)
447+
XCTAssertTrue(parseError.message.contains("pinged"))
448+
expectation1.fulfill()
449+
}
450+
wait(for: [expectation1], timeout: 20.0)
451+
}
452+
453+
func testPing() throws {
454+
guard let client = ParseLiveQuery.getDefault() else {
455+
XCTFail("Should be able to get client")
456+
return
457+
}
458+
client.isSocketEstablished = true // Socket needs to be true
459+
client.isConnecting = true
460+
client.isConnected = true
461+
client.clientId = "yolo"
462+
463+
let expectation1 = XCTestExpectation(description: "Send Ping")
464+
client.sendPing { error in
465+
XCTAssertEqual(client.isSocketEstablished, true)
466+
XCTAssertNotNil(error) // Should have error because testcases don't intercept websocket
467+
expectation1.fulfill()
468+
}
469+
wait(for: [expectation1], timeout: 20.0)
470+
}
471+
395472
func testReconnectInterval() throws {
396473
guard let client = ParseLiveQuery.getDefault() else {
397474
XCTFail("Should be able to get client")
@@ -546,6 +623,9 @@ class ParseLiveQueryTests: XCTestCase {
546623
//Unsubscribe
547624
subscription.handleUnsubscribe { query in
548625
XCTAssertEqual(query, subscribedQuery)
626+
XCTAssertTrue(client.pendingSubscriptions.isEmpty)
627+
XCTAssertTrue(client.subscriptions.isEmpty)
628+
XCTAssertFalse(client.isSocketEstablished)
549629
expectation2.fulfill()
550630
}
551631
XCTAssertNotNil(try? query.unsubscribe())

0 commit comments

Comments
 (0)