Skip to content

Commit d055f35

Browse files
authored
Merge pull request #4 from wondrous-io/pr/session-tokens
Add support for `sessionToken` in "connect" and "subscribe" operations
2 parents 1f69775 + 773054c commit d055f35

File tree

3 files changed

+110
-22
lines changed

3 files changed

+110
-22
lines changed

ParseLiveQuery/src/main/java/com/parse/ParseLiveQueryClientImpl.java

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.parse;
22

3-
43
import android.util.Log;
54
import android.util.SparseArray;
65

@@ -179,7 +178,6 @@ private void parseMessage(String message) throws LiveQueryException {
179178
} catch (JSONException e) {
180179
throw new LiveQueryException.InvalidResponseException(message);
181180
}
182-
183181
}
184182

185183
private void handleSubscribedEvent(JSONObject jsonObject) throws JSONException {
@@ -223,8 +221,14 @@ private Subscription<T> subscriptionForRequestId(int requestId) {
223221
return subscriptions.get(requestId);
224222
}
225223

226-
private void sendSubscription(Subscription<T> subscription) {
227-
sendOperationAsync(new SubscribeClientOperation<>(subscription.getRequestId(), subscription.getQueryState()));
224+
private void sendSubscription(final Subscription<T> subscription) {
225+
ParseUser.getCurrentSessionTokenAsync().onSuccessTask(new Continuation<String, Task<Void>>() {
226+
@Override
227+
public Task<Void> then(Task<String> task) throws Exception {
228+
String sessionToken = task.getResult();
229+
return sendOperationAsync(new SubscribeClientOperation<>(subscription.getRequestId(), subscription.getQueryState(), sessionToken));
230+
}
231+
});
228232
}
229233

230234
private void sendUnsubscription(Subscription subscription) {
@@ -236,7 +240,13 @@ private WebSocketClient.WebSocketClientCallback getWebSocketClientCallback() {
236240
@Override
237241
public void onOpen() {
238242
Log.v(LOG_TAG, "Socket opened");
239-
sendOperationAsync(new ConnectClientOperation(applicationId, "")).continueWith(new Continuation<Void, Void>() {
243+
ParseUser.getCurrentSessionTokenAsync().onSuccessTask(new Continuation<String, Task<Void>>() {
244+
@Override
245+
public Task<Void> then(Task<String> task) throws Exception {
246+
String sessionToken = task.getResult();
247+
return sendOperationAsync(new ConnectClientOperation(applicationId, sessionToken));
248+
}
249+
}).continueWith(new Continuation<Void, Void>() {
240250
public Void then(Task<Void> task) {
241251
Exception error = task.getError();
242252
if (error != null) {
@@ -277,5 +287,4 @@ public void stateChanged() {
277287
}
278288
};
279289
}
280-
281290
}

ParseLiveQuery/src/main/java/com/parse/SubscribeClientOperation.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,20 @@
77

88
private final int requestId;
99
private final ParseQuery.State<T> state;
10+
private final String sessionToken;
1011

11-
/* package */ SubscribeClientOperation(int requestId, final ParseQuery.State<T> state) {
12+
/* package */ SubscribeClientOperation(int requestId, ParseQuery.State<T> state, String sessionToken) {
1213
this.requestId = requestId;
1314
this.state = state;
15+
this.sessionToken = sessionToken;
1416
}
1517

1618
@Override
1719
/* package */ JSONObject getJSONObjectRepresentation() throws JSONException {
1820
JSONObject jsonObject = new JSONObject();
1921
jsonObject.put("op", "subscribe");
2022
jsonObject.put("requestId", requestId);
23+
jsonObject.put("sessionToken", sessionToken);
2124

2225
JSONObject queryJsonObject = state.toJSON(PointerEncoder.get());
2326

ParseLiveQuery/src/test/java/com/parse/TestParseLiveQueryClient.java

Lines changed: 91 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,28 @@
77
import org.junit.Test;
88
import org.junit.runner.RunWith;
99
import org.mockito.ArgumentCaptor;
10+
import org.mockito.invocation.InvocationOnMock;
11+
import org.mockito.stubbing.Answer;
1012
import org.robolectric.RobolectricGradleTestRunner;
1113
import org.robolectric.annotation.Config;
1214

1315
import java.net.URI;
1416
import java.util.concurrent.Executor;
1517

18+
import bolts.Task;
19+
1620
import static junit.framework.Assert.assertEquals;
1721
import static junit.framework.Assert.assertTrue;
22+
import static org.mockito.AdditionalMatchers.and;
23+
import static org.mockito.AdditionalMatchers.not;
1824
import static org.mockito.Matchers.any;
25+
import static org.mockito.Matchers.anyBoolean;
26+
import static org.mockito.Matchers.contains;
1927
import static org.mockito.Matchers.eq;
2028
import static org.mockito.Mockito.mock;
2129
import static org.mockito.Mockito.times;
2230
import static org.mockito.Mockito.verify;
31+
import static org.mockito.Mockito.when;
2332

2433
@RunWith(RobolectricGradleTestRunner.class)
2534
@Config(constants = BuildConfig.class, sdk = 21)
@@ -29,9 +38,29 @@ public class TestParseLiveQueryClient {
2938
private WebSocketClient.WebSocketClientCallback webSocketClientCallback;
3039
private ParseLiveQueryClient<ParseObject> parseLiveQueryClient;
3140

41+
private ParseUser mockUser;
42+
3243
@Before
3344
public void setUp() throws Exception {
3445
ParsePlugins.initialize("1234", "1234");
46+
47+
// Register a mock currentUserController to make getCurrentUser work
48+
mockUser = mock(ParseUser.class);
49+
ParseCurrentUserController currentUserController = mock(ParseCurrentUserController.class);
50+
when(currentUserController.getAsync(anyBoolean())).thenAnswer(new Answer<Task<ParseUser>>() {
51+
@Override
52+
public Task<ParseUser> answer(InvocationOnMock invocation) throws Throwable {
53+
return Task.forResult(mockUser);
54+
}
55+
});
56+
when(currentUserController.getCurrentSessionTokenAsync()).thenAnswer(new Answer<Task<String>>() {
57+
@Override
58+
public Task<String> answer(InvocationOnMock invocation) throws Throwable {
59+
return Task.forResult(mockUser.getSessionToken());
60+
}
61+
});
62+
ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController);
63+
3564
parseLiveQueryClient = ParseLiveQueryClient.Factory.getClient(new URI(""), new WebSocketClientFactory() {
3665
@Override
3766
public WebSocketClient createInstance(WebSocketClient.WebSocketClientCallback webSocketClientCallback, URI hostUrl) {
@@ -67,12 +96,14 @@ public void testSubscribeWhenSubscribedToCallback() throws Exception {
6796
@Test
6897
public void testUnsubscribeWhenSubscribedToCallback() throws Exception {
6998
ParseQuery<ParseObject> parseQuery = new ParseQuery<>("test");
70-
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery, mock(SubscriptionHandling.HandleSubscribeCallback.class));
99+
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery,
100+
mock(SubscriptionHandling.HandleSubscribeCallback.class));
71101

72102
parseLiveQueryClient.unsubscribe(parseQuery);
73103
verify(webSocketClient, times(1)).send(any(String.class));
74104

75-
SubscriptionHandling.HandleUnsubscribeCallback<ParseObject> unsubscribeMockCallback = mock(SubscriptionHandling.HandleUnsubscribeCallback.class);
105+
SubscriptionHandling.HandleUnsubscribeCallback<ParseObject> unsubscribeMockCallback = mock(
106+
SubscriptionHandling.HandleUnsubscribeCallback.class);
76107
subscriptionHandling.handleUnsubscribe(unsubscribeMockCallback);
77108
webSocketClientCallback.onMessage(createUnsubscribedMessage(subscriptionHandling.getRequestId()).toString());
78109

@@ -82,7 +113,8 @@ public void testUnsubscribeWhenSubscribedToCallback() throws Exception {
82113
@Test
83114
public void testErrorWhenSubscribedToCallback() throws Exception {
84115
ParseQuery<ParseObject> parseQuery = new ParseQuery<>("test");
85-
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery, mock(SubscriptionHandling.HandleSubscribeCallback.class));
116+
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery,
117+
mock(SubscriptionHandling.HandleSubscribeCallback.class));
86118

87119
SubscriptionHandling.HandleErrorCallback<ParseObject> errorMockCallback = mock(SubscriptionHandling.HandleErrorCallback.class);
88120
subscriptionHandling.handleError(errorMockCallback);
@@ -103,7 +135,8 @@ public void testErrorWhenSubscribedToCallback() throws Exception {
103135
@Test
104136
public void testCreateEventWhenSubscribedToCallback() throws Exception {
105137
ParseQuery<ParseObject> parseQuery = new ParseQuery<>("test");
106-
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery, mock(SubscriptionHandling.HandleSubscribeCallback.class));
138+
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery,
139+
mock(SubscriptionHandling.HandleSubscribeCallback.class));
107140

108141
SubscriptionHandling.HandleEventCallback<ParseObject> eventMockCallback = mock(SubscriptionHandling.HandleEventCallback.class);
109142
subscriptionHandling.handleEvent(SubscriptionHandling.Event.CREATE, eventMockCallback);
@@ -119,7 +152,8 @@ public void testCreateEventWhenSubscribedToCallback() throws Exception {
119152
@Test
120153
public void testEnterEventWhenSubscribedToCallback() throws Exception {
121154
ParseQuery<ParseObject> parseQuery = new ParseQuery<>("test");
122-
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery, mock(SubscriptionHandling.HandleSubscribeCallback.class));
155+
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery,
156+
mock(SubscriptionHandling.HandleSubscribeCallback.class));
123157

124158
SubscriptionHandling.HandleEventCallback<ParseObject> eventMockCallback = mock(SubscriptionHandling.HandleEventCallback.class);
125159
subscriptionHandling.handleEvent(SubscriptionHandling.Event.ENTER, eventMockCallback);
@@ -135,7 +169,8 @@ public void testEnterEventWhenSubscribedToCallback() throws Exception {
135169
@Test
136170
public void testUpdateEventWhenSubscribedToCallback() throws Exception {
137171
ParseQuery<ParseObject> parseQuery = new ParseQuery<>("test");
138-
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery, mock(SubscriptionHandling.HandleSubscribeCallback.class));
172+
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery,
173+
mock(SubscriptionHandling.HandleSubscribeCallback.class));
139174

140175
SubscriptionHandling.HandleEventCallback<ParseObject> eventMockCallback = mock(SubscriptionHandling.HandleEventCallback.class);
141176
subscriptionHandling.handleEvent(SubscriptionHandling.Event.UPDATE, eventMockCallback);
@@ -151,7 +186,8 @@ public void testUpdateEventWhenSubscribedToCallback() throws Exception {
151186
@Test
152187
public void testLeaveEventWhenSubscribedToCallback() throws Exception {
153188
ParseQuery<ParseObject> parseQuery = new ParseQuery<>("test");
154-
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery, mock(SubscriptionHandling.HandleSubscribeCallback.class));
189+
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery,
190+
mock(SubscriptionHandling.HandleSubscribeCallback.class));
155191

156192
SubscriptionHandling.HandleEventCallback<ParseObject> eventMockCallback = mock(SubscriptionHandling.HandleEventCallback.class);
157193
subscriptionHandling.handleEvent(SubscriptionHandling.Event.LEAVE, eventMockCallback);
@@ -164,11 +200,11 @@ public void testLeaveEventWhenSubscribedToCallback() throws Exception {
164200
validateSameObject(eventMockCallback, parseQuery, parseObject);
165201
}
166202

167-
168203
@Test
169204
public void testDeleteEventWhenSubscribedToCallback() throws Exception {
170205
ParseQuery<ParseObject> parseQuery = new ParseQuery<>("test");
171-
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery, mock(SubscriptionHandling.HandleSubscribeCallback.class));
206+
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery,
207+
mock(SubscriptionHandling.HandleSubscribeCallback.class));
172208

173209
SubscriptionHandling.HandleEventCallback<ParseObject> eventMockCallback = mock(SubscriptionHandling.HandleEventCallback.class);
174210
subscriptionHandling.handleEvent(SubscriptionHandling.Event.DELETE, eventMockCallback);
@@ -184,7 +220,8 @@ public void testDeleteEventWhenSubscribedToCallback() throws Exception {
184220
@Test
185221
public void testCreateEventWhenSubscribedToAnyCallback() throws Exception {
186222
ParseQuery<ParseObject> parseQuery = new ParseQuery<>("test");
187-
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery, mock(SubscriptionHandling.HandleSubscribeCallback.class));
223+
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery,
224+
mock(SubscriptionHandling.HandleSubscribeCallback.class));
188225

189226
SubscriptionHandling.HandleEventsCallback<ParseObject> eventsMockCallback = mock(SubscriptionHandling.HandleEventsCallback.class);
190227
subscriptionHandling.handleEvents(eventsMockCallback);
@@ -205,12 +242,14 @@ public void testCreateEventWhenSubscribedToAnyCallback() throws Exception {
205242
@Test
206243
public void testSubscriptionStoppedAfterUnsubscribe() throws Exception {
207244
ParseQuery<ParseObject> parseQuery = new ParseQuery<>("test");
208-
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery, mock(SubscriptionHandling.HandleSubscribeCallback.class));
245+
SubscriptionHandling<ParseObject> subscriptionHandling = createSubscription(parseQuery,
246+
mock(SubscriptionHandling.HandleSubscribeCallback.class));
209247

210248
SubscriptionHandling.HandleEventCallback<ParseObject> eventMockCallback = mock(SubscriptionHandling.HandleEventCallback.class);
211249
subscriptionHandling.handleEvent(SubscriptionHandling.Event.CREATE, eventMockCallback);
212250

213-
SubscriptionHandling.HandleUnsubscribeCallback<ParseObject> unsubscribeMockCallback = mock(SubscriptionHandling.HandleUnsubscribeCallback.class);
251+
SubscriptionHandling.HandleUnsubscribeCallback<ParseObject> unsubscribeMockCallback = mock(
252+
SubscriptionHandling.HandleUnsubscribeCallback.class);
214253
subscriptionHandling.handleUnsubscribe(unsubscribeMockCallback);
215254

216255
parseLiveQueryClient.unsubscribe(parseQuery);
@@ -239,14 +278,52 @@ public void testSubscriptionReplayedAfterReconnect() throws Exception {
239278
verify(webSocketClient, times(2)).send(any(String.class));
240279
}
241280

281+
@Test
282+
public void testSessionTokenSentOnConnect() {
283+
when(mockUser.getSessionToken()).thenReturn("the token");
284+
parseLiveQueryClient.reconnect();
285+
webSocketClientCallback.onOpen();
286+
verify(webSocketClient, times(1)).send(contains("\"sessionToken\":\"the token\""));
287+
}
242288

243-
private SubscriptionHandling<ParseObject> createSubscription(ParseQuery<ParseObject> parseQuery, SubscriptionHandling.HandleSubscribeCallback<ParseObject> subscribeMockCallback) throws Exception {
289+
@Test
290+
public void testEmptySessionTokenOnConnect() {
291+
parseLiveQueryClient.reconnect();
292+
webSocketClientCallback.onOpen();
293+
verify(webSocketClient, times(1)).send(not(contains("\"sessionToken\":")));
294+
}
295+
296+
@Test
297+
public void testSessionTokenSentOnSubscribe() {
298+
when(mockUser.getSessionToken()).thenReturn("the token");
299+
when(webSocketClient.getState()).thenReturn(WebSocketClient.State.CONNECTED);
300+
parseLiveQueryClient.subscribe(ParseQuery.getQuery("Test"));
301+
verify(webSocketClient, times(1)).send(and(
302+
contains("\"op\":\"subscribe\""),
303+
contains("\"sessionToken\":\"the token\"")));
304+
}
305+
306+
@Test
307+
public void testEmptySessionTokenOnSubscribe() {
308+
when(mockUser.getSessionToken()).thenReturn("the token");
309+
when(webSocketClient.getState()).thenReturn(WebSocketClient.State.CONNECTED);
310+
parseLiveQueryClient.subscribe(ParseQuery.getQuery("Test"));
311+
verify(webSocketClient, times(1)).send(contains("\"op\":\"connect\""));
312+
verify(webSocketClient, times(1)).send(and(
313+
contains("\"op\":\"subscribe\""),
314+
contains("\"sessionToken\":\"the token\"")));
315+
}
316+
317+
private SubscriptionHandling<ParseObject> createSubscription(ParseQuery<ParseObject> parseQuery,
318+
SubscriptionHandling.HandleSubscribeCallback<ParseObject> subscribeMockCallback) throws Exception {
244319
SubscriptionHandling<ParseObject> subscriptionHandling = parseLiveQueryClient.subscribe(parseQuery).handleSubscribe(subscribeMockCallback);
245320
webSocketClientCallback.onMessage(createSubscribedMessage(subscriptionHandling.getRequestId()).toString());
246321
return subscriptionHandling;
247322
}
248323

249-
private void validateSameObject(SubscriptionHandling.HandleEventCallback<ParseObject> eventMockCallback, ParseQuery<ParseObject> parseQuery, ParseObject originalParseObject) {
324+
private void validateSameObject(SubscriptionHandling.HandleEventCallback<ParseObject> eventMockCallback,
325+
ParseQuery<ParseObject> parseQuery,
326+
ParseObject originalParseObject) {
250327
ArgumentCaptor<ParseObject> objectCaptor = ArgumentCaptor.forClass(ParseObject.class);
251328
verify(eventMockCallback, times(1)).onEvent(eq(parseQuery), objectCaptor.capture());
252329

@@ -335,5 +412,4 @@ private static JSONObject createObjectDeleteMessage(int requestId, ParseObject p
335412
jsonObject.put("object", PointerEncoder.get().encodeRelatedObject(parseObject));
336413
return jsonObject;
337414
}
338-
339415
}

0 commit comments

Comments
 (0)