Skip to content

Commit 7000301

Browse files
committed
feature: add subscription.find
1 parent 17e2a77 commit 7000301

File tree

4 files changed

+129
-4
lines changed

4 files changed

+129
-4
lines changed

src/LiveQueryClient.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const OP_TYPES = {
2121
SUBSCRIBE: 'subscribe',
2222
UNSUBSCRIBE: 'unsubscribe',
2323
ERROR: 'error',
24+
QUERY: 'query',
2425
};
2526

2627
// The event we get back from LiveQuery server
@@ -34,6 +35,7 @@ const OP_EVENTS = {
3435
ENTER: 'enter',
3536
LEAVE: 'leave',
3637
DELETE: 'delete',
38+
RESULT: 'result',
3739
};
3840

3941
// The event the LiveQuery client should emit
@@ -53,6 +55,7 @@ const SUBSCRIPTION_EMMITER_TYPES = {
5355
ENTER: 'enter',
5456
LEAVE: 'leave',
5557
DELETE: 'delete',
58+
RESULT: 'result',
5659
};
5760

5861
// Exponentially-growing random delay
@@ -212,7 +215,7 @@ class LiveQueryClient {
212215
subscribeRequest.sessionToken = sessionToken;
213216
}
214217

215-
const subscription = new LiveQuerySubscription(this.requestId, query, sessionToken);
218+
const subscription = new LiveQuerySubscription(this.requestId, query, sessionToken, this);
216219
this.subscriptions.set(this.requestId, subscription);
217220
this.requestId += 1;
218221
this.connectPromise
@@ -425,6 +428,13 @@ class LiveQueryClient {
425428
}
426429
break;
427430
}
431+
case OP_EVENTS.RESULT: {
432+
if (subscription) {
433+
const objects = data.results.map(json => ParseObject.fromJSON(json, false));
434+
subscription.emit(SUBSCRIPTION_EMMITER_TYPES.RESULT, objects);
435+
}
436+
break;
437+
}
428438
default: {
429439
// create, update, enter, leave, delete cases
430440
if (!subscription) {

src/LiveQuerySubscription.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,18 +92,21 @@ class LiveQuerySubscription {
9292
subscribePromise: any;
9393
unsubscribePromise: any;
9494
subscribed: boolean;
95+
client: any;
9596
emitter: EventEmitter;
9697
on: EventEmitter['on'];
9798
emit: EventEmitter['emit'];
9899
/*
99100
* @param {string | number} id - subscription id
100101
* @param {string} query - query to subscribe to
101102
* @param {string} sessionToken - optional session token
103+
* @param {object} client - LiveQueryClient instance
102104
*/
103-
constructor(id: string | number, query: ParseQuery, sessionToken?: string) {
105+
constructor(id: string | number, query: ParseQuery, sessionToken?: string, client?: any) {
104106
this.id = id;
105107
this.query = query;
106108
this.sessionToken = sessionToken;
109+
this.client = client;
107110
this.subscribePromise = resolvingPromise();
108111
this.unsubscribePromise = resolvingPromise();
109112
this.subscribed = false;
@@ -130,6 +133,21 @@ class LiveQuerySubscription {
130133
return liveQueryClient.unsubscribe(this);
131134
});
132135
}
136+
137+
/**
138+
* Execute a query on this subscription.
139+
* The results will be delivered via the 'result' event.
140+
*/
141+
find() {
142+
if (this.client) {
143+
this.client.connectPromise.then(() => {
144+
this.client.socket.send(JSON.stringify({
145+
op: 'query',
146+
requestId: this.id,
147+
}));
148+
});
149+
}
150+
}
133151
}
134152

135153
export default LiveQuerySubscription;

src/__tests__/LiveQueryClient-test.js

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
jest.dontMock('../LiveQuerySubscription');
12
jest.dontMock('../LiveQueryClient');
23
jest.dontMock('../arrayContainsObject');
34
jest.dontMock('../canBeSerialized');
@@ -23,7 +24,6 @@ jest.dontMock('../UniqueInstanceStateController');
2324
jest.dontMock('../unsavedChildren');
2425
jest.dontMock('../ParseACL');
2526
jest.dontMock('../ParseQuery');
26-
jest.dontMock('../LiveQuerySubscription');
2727
jest.dontMock('../LocalDatastore');
2828
jest.dontMock('../WebSocketController');
2929

@@ -38,6 +38,7 @@ jest.setMock('../LocalDatastore', mockLocalDatastore);
3838
const CoreManager = require('../CoreManager').default;
3939
const EventEmitter = require('../EventEmitter').default;
4040
const LiveQueryClient = require('../LiveQueryClient').default;
41+
const LiveQuerySubscription = require('../LiveQuerySubscription').default;
4142
const ParseObject = require('../ParseObject').default;
4243
const ParseQuery = require('../ParseQuery').default;
4344
const WebSocketController = require('../WebSocketController').default;
@@ -1091,4 +1092,94 @@ describe('LiveQueryClient', () => {
10911092
const subscription = liveQueryClient.subscribe();
10921093
expect(subscription).toBe(undefined);
10931094
});
1095+
1096+
it('can handle WebSocket result response message', () => {
1097+
const liveQueryClient = new LiveQueryClient({
1098+
applicationId: 'applicationId',
1099+
serverURL: 'ws://test',
1100+
javascriptKey: 'javascriptKey',
1101+
masterKey: 'masterKey',
1102+
sessionToken: 'sessionToken',
1103+
});
1104+
// Add mock subscription
1105+
const subscription = new events.EventEmitter();
1106+
liveQueryClient.subscriptions.set(1, subscription);
1107+
const object1 = new ParseObject('Test');
1108+
object1.set('key', 'value1');
1109+
const object2 = new ParseObject('Test');
1110+
object2.set('key', 'value2');
1111+
const data = {
1112+
op: 'result',
1113+
clientId: 1,
1114+
requestId: 1,
1115+
results: [object1._toFullJSON(), object2._toFullJSON()],
1116+
};
1117+
const event = {
1118+
data: JSON.stringify(data),
1119+
};
1120+
// Register checked in advance
1121+
let isChecked = false;
1122+
subscription.on('result', function (objects) {
1123+
isChecked = true;
1124+
expect(objects.length).toBe(2);
1125+
expect(objects[0].get('key')).toEqual('value1');
1126+
expect(objects[1].get('key')).toEqual('value2');
1127+
});
1128+
1129+
liveQueryClient._handleWebSocketMessage(event);
1130+
1131+
expect(isChecked).toBe(true);
1132+
});
1133+
1134+
it('LiveQuerySubscription class has find method', () => {
1135+
expect(typeof LiveQuerySubscription.prototype.find).toBe('function');
1136+
});
1137+
1138+
it('subscription has find method', () => {
1139+
const liveQueryClient = new LiveQueryClient({
1140+
applicationId: 'applicationId',
1141+
serverURL: 'ws://test',
1142+
javascriptKey: 'javascriptKey',
1143+
masterKey: 'masterKey',
1144+
sessionToken: 'sessionToken',
1145+
});
1146+
const query = new ParseQuery('Test');
1147+
query.equalTo('key', 'value');
1148+
1149+
const subscription = liveQueryClient.subscribe(query);
1150+
1151+
expect(subscription).toBeInstanceOf(LiveQuerySubscription);
1152+
expect(typeof subscription.find).toBe('function');
1153+
});
1154+
1155+
it('can send query message via subscription', async () => {
1156+
const liveQueryClient = new LiveQueryClient({
1157+
applicationId: 'applicationId',
1158+
serverURL: 'ws://test',
1159+
javascriptKey: 'javascriptKey',
1160+
masterKey: 'masterKey',
1161+
sessionToken: 'sessionToken',
1162+
});
1163+
liveQueryClient.socket = {
1164+
send: jest.fn(),
1165+
};
1166+
const query = new ParseQuery('Test');
1167+
query.equalTo('key', 'value');
1168+
1169+
const subscription = liveQueryClient.subscribe(query);
1170+
liveQueryClient.connectPromise.resolve();
1171+
await liveQueryClient.connectPromise;
1172+
1173+
subscription.find();
1174+
1175+
// Need to wait for the sendMessage promise to resolve
1176+
await Promise.resolve();
1177+
1178+
const messageStr = liveQueryClient.socket.send.mock.calls[1][0];
1179+
const message = JSON.parse(messageStr);
1180+
expect(message).toEqual({
1181+
op: 'query',
1182+
requestId: 1,
1183+
});
1184+
});
10941185
});

types/LiveQuerySubscription.d.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,15 +89,21 @@ declare class LiveQuerySubscription {
8989
subscribePromise: any;
9090
unsubscribePromise: any;
9191
subscribed: boolean;
92+
client: any;
9293
emitter: EventEmitter;
9394
on: EventEmitter['on'];
9495
emit: EventEmitter['emit'];
95-
constructor(id: string | number, query: ParseQuery, sessionToken?: string);
96+
constructor(id: string | number, query: ParseQuery, sessionToken?: string, client?: any);
9697
/**
9798
* Close the subscription
9899
*
99100
* @returns {Promise}
100101
*/
101102
unsubscribe(): Promise<void>;
103+
/**
104+
* Execute a query on this subscription.
105+
* The results will be delivered via the 'result' event.
106+
*/
107+
find(): void;
102108
}
103109
export default LiveQuerySubscription;

0 commit comments

Comments
 (0)