Skip to content

Commit 555e25b

Browse files
committed
Add LiveQuery
1 parent cf36062 commit 555e25b

33 files changed

+3580
-48
lines changed

package.json

+6-1
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,24 @@
2929
"deepcopy": "^0.6.1",
3030
"express": "^4.13.4",
3131
"gcloud": "^0.28.0",
32+
"lru-cache": "^4.0.0",
3233
"mailgun-js": "^0.7.7",
3334
"mime": "^1.3.4",
3435
"mongodb": "~2.1.0",
3536
"multer": "^1.1.0",
3637
"node-gcm": "^0.14.0",
3738
"parse": "^1.7.0",
39+
"redis": "^2.5.0-1",
3840
"request": "^2.65.0",
39-
"winston": "^2.1.1"
41+
"tv4": "^1.2.7",
42+
"winston": "^2.1.1",
43+
"ws": "^1.0.1"
4044
},
4145
"devDependencies": {
4246
"babel-cli": "^6.5.1",
4347
"babel-core": "^6.5.1",
4448
"babel-istanbul": "^0.6.0",
49+
"babel-plugin-syntax-flow": "^6.5.0",
4550
"babel-plugin-transform-flow-strip-types": "^6.5.0",
4651
"babel-preset-es2015": "^6.5.0",
4752
"babel-preset-stage-0": "^6.5.0",

spec/Client.spec.js

+290
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
1+
var Client = require('../src/LiveQuery/Client').Client;
2+
var ParseWebSocket = require('../src/LiveQuery/ParseWebSocketServer').ParseWebSocket;
3+
4+
describe('Client', function() {
5+
6+
it('can be initialized', function() {
7+
var parseWebSocket = new ParseWebSocket({});
8+
var client = new Client(1, parseWebSocket);
9+
10+
expect(client.id).toBe(1);
11+
expect(client.parseWebSocket).toBe(parseWebSocket);
12+
expect(client.subscriptionInfos.size).toBe(0);
13+
});
14+
15+
it('can push response', function() {
16+
var parseWebSocket = {
17+
send: jasmine.createSpy('send')
18+
};
19+
Client.pushResponse(parseWebSocket, 'message');
20+
21+
expect(parseWebSocket.send).toHaveBeenCalledWith('message');
22+
});
23+
24+
it('can push error', function() {
25+
var parseWebSocket = {
26+
send: jasmine.createSpy('send')
27+
};
28+
Client.pushError(parseWebSocket, 1, 'error', true);
29+
30+
var lastCall = parseWebSocket.send.calls.first();
31+
var messageJSON = JSON.parse(lastCall.args[0]);
32+
expect(messageJSON.op).toBe('error');
33+
expect(messageJSON.error).toBe('error');
34+
expect(messageJSON.code).toBe(1);
35+
expect(messageJSON.reconnect).toBe(true);
36+
});
37+
38+
it('can add subscription information', function() {
39+
var subscription = {};
40+
var fields = ['test'];
41+
var subscriptionInfo = {
42+
subscription: subscription,
43+
fields: fields
44+
}
45+
var client = new Client(1, {});
46+
client.addSubscriptionInfo(1, subscriptionInfo);
47+
48+
expect(client.subscriptionInfos.size).toBe(1);
49+
expect(client.subscriptionInfos.get(1)).toBe(subscriptionInfo);
50+
});
51+
52+
it('can get subscription information', function() {
53+
var subscription = {};
54+
var fields = ['test'];
55+
var subscriptionInfo = {
56+
subscription: subscription,
57+
fields: fields
58+
}
59+
var client = new Client(1, {});
60+
client.addSubscriptionInfo(1, subscriptionInfo);
61+
var subscriptionInfoAgain = client.getSubscriptionInfo(1);
62+
63+
expect(subscriptionInfoAgain).toBe(subscriptionInfo);
64+
});
65+
66+
it('can delete subscription information', function() {
67+
var subscription = {};
68+
var fields = ['test'];
69+
var subscriptionInfo = {
70+
subscription: subscription,
71+
fields: fields
72+
}
73+
var client = new Client(1, {});
74+
client.addSubscriptionInfo(1, subscriptionInfo);
75+
client.deleteSubscriptionInfo(1);
76+
77+
expect(client.subscriptionInfos.size).toBe(0);
78+
});
79+
80+
81+
it('can generate ParseObject JSON with null selected field', function() {
82+
var parseObjectJSON = {
83+
key : 'value',
84+
className: 'test',
85+
objectId: 'test',
86+
updatedAt: '2015-12-07T21:27:13.746Z',
87+
createdAt: '2015-12-07T21:27:13.746Z',
88+
ACL: 'test',
89+
};
90+
var client = new Client(1, {});
91+
92+
expect(client._toJSONWithFields(parseObjectJSON, null)).toBe(parseObjectJSON);
93+
});
94+
95+
it('can generate ParseObject JSON with undefined selected field', function() {
96+
var parseObjectJSON = {
97+
key : 'value',
98+
className: 'test',
99+
objectId: 'test',
100+
updatedAt: '2015-12-07T21:27:13.746Z',
101+
createdAt: '2015-12-07T21:27:13.746Z',
102+
ACL: 'test',
103+
};
104+
var client = new Client(1, {});
105+
106+
expect(client._toJSONWithFields(parseObjectJSON, undefined)).toBe(parseObjectJSON);
107+
});
108+
109+
it('can generate ParseObject JSON with selected fields', function() {
110+
var parseObjectJSON = {
111+
key : 'value',
112+
className: 'test',
113+
objectId: 'test',
114+
updatedAt: '2015-12-07T21:27:13.746Z',
115+
createdAt: '2015-12-07T21:27:13.746Z',
116+
ACL: 'test',
117+
test: 'test'
118+
};
119+
var client = new Client(1, {});
120+
121+
expect(client._toJSONWithFields(parseObjectJSON, ['test'])).toEqual({
122+
className: 'test',
123+
objectId: 'test',
124+
updatedAt: '2015-12-07T21:27:13.746Z',
125+
createdAt: '2015-12-07T21:27:13.746Z',
126+
ACL: 'test',
127+
test: 'test'
128+
});
129+
});
130+
131+
it('can generate ParseObject JSON with nonexistent selected fields', function() {
132+
var parseObjectJSON = {
133+
key : 'value',
134+
className: 'test',
135+
objectId: 'test',
136+
updatedAt: '2015-12-07T21:27:13.746Z',
137+
createdAt: '2015-12-07T21:27:13.746Z',
138+
ACL: 'test',
139+
test: 'test'
140+
};
141+
var client = new Client(1, {});
142+
var limitedParseObject = client._toJSONWithFields(parseObjectJSON, ['name']);
143+
144+
expect(limitedParseObject).toEqual({
145+
className: 'test',
146+
objectId: 'test',
147+
updatedAt: '2015-12-07T21:27:13.746Z',
148+
createdAt: '2015-12-07T21:27:13.746Z',
149+
ACL: 'test',
150+
});
151+
expect('name' in limitedParseObject).toBe(false);
152+
});
153+
154+
it('can push connect response', function() {
155+
var parseWebSocket = {
156+
send: jasmine.createSpy('send')
157+
};
158+
var client = new Client(1, parseWebSocket);
159+
client.pushConnect();
160+
161+
var lastCall = parseWebSocket.send.calls.first();
162+
var messageJSON = JSON.parse(lastCall.args[0]);
163+
expect(messageJSON.op).toBe('connected');
164+
expect(messageJSON.clientId).toBe(1);
165+
});
166+
167+
it('can push subscribe response', function() {
168+
var parseWebSocket = {
169+
send: jasmine.createSpy('send')
170+
};
171+
var client = new Client(1, parseWebSocket);
172+
client.pushSubscribe(2);
173+
174+
var lastCall = parseWebSocket.send.calls.first();
175+
var messageJSON = JSON.parse(lastCall.args[0]);
176+
expect(messageJSON.op).toBe('subscribed');
177+
expect(messageJSON.clientId).toBe(1);
178+
expect(messageJSON.requestId).toBe(2);
179+
});
180+
181+
it('can push unsubscribe response', function() {
182+
var parseWebSocket = {
183+
send: jasmine.createSpy('send')
184+
};
185+
var client = new Client(1, parseWebSocket);
186+
client.pushUnsubscribe(2);
187+
188+
var lastCall = parseWebSocket.send.calls.first();
189+
var messageJSON = JSON.parse(lastCall.args[0]);
190+
expect(messageJSON.op).toBe('unsubscribed');
191+
expect(messageJSON.clientId).toBe(1);
192+
expect(messageJSON.requestId).toBe(2);
193+
});
194+
195+
it('can push create response', function() {
196+
var parseObjectJSON = {
197+
key : 'value',
198+
className: 'test',
199+
objectId: 'test',
200+
updatedAt: '2015-12-07T21:27:13.746Z',
201+
createdAt: '2015-12-07T21:27:13.746Z',
202+
ACL: 'test',
203+
test: 'test'
204+
};
205+
var parseWebSocket = {
206+
send: jasmine.createSpy('send')
207+
};
208+
var client = new Client(1, parseWebSocket);
209+
client.pushCreate(2, parseObjectJSON);
210+
211+
var lastCall = parseWebSocket.send.calls.first();
212+
var messageJSON = JSON.parse(lastCall.args[0]);
213+
expect(messageJSON.op).toBe('create');
214+
expect(messageJSON.clientId).toBe(1);
215+
expect(messageJSON.requestId).toBe(2);
216+
expect(messageJSON.object).toEqual(parseObjectJSON);
217+
});
218+
219+
it('can push enter response', function() {
220+
var parseObjectJSON = {
221+
key : 'value',
222+
className: 'test',
223+
objectId: 'test',
224+
updatedAt: '2015-12-07T21:27:13.746Z',
225+
createdAt: '2015-12-07T21:27:13.746Z',
226+
ACL: 'test',
227+
test: 'test'
228+
};
229+
var parseWebSocket = {
230+
send: jasmine.createSpy('send')
231+
};
232+
var client = new Client(1, parseWebSocket);
233+
client.pushEnter(2, parseObjectJSON);
234+
235+
var lastCall = parseWebSocket.send.calls.first();
236+
var messageJSON = JSON.parse(lastCall.args[0]);
237+
expect(messageJSON.op).toBe('enter');
238+
expect(messageJSON.clientId).toBe(1);
239+
expect(messageJSON.requestId).toBe(2);
240+
expect(messageJSON.object).toEqual(parseObjectJSON);
241+
});
242+
243+
it('can push update response', function() {
244+
var parseObjectJSON = {
245+
key : 'value',
246+
className: 'test',
247+
objectId: 'test',
248+
updatedAt: '2015-12-07T21:27:13.746Z',
249+
createdAt: '2015-12-07T21:27:13.746Z',
250+
ACL: 'test',
251+
test: 'test'
252+
};
253+
var parseWebSocket = {
254+
send: jasmine.createSpy('send')
255+
};
256+
var client = new Client(1, parseWebSocket);
257+
client.pushUpdate(2, parseObjectJSON);
258+
259+
var lastCall = parseWebSocket.send.calls.first();
260+
var messageJSON = JSON.parse(lastCall.args[0]);
261+
expect(messageJSON.op).toBe('update');
262+
expect(messageJSON.clientId).toBe(1);
263+
expect(messageJSON.requestId).toBe(2);
264+
expect(messageJSON.object).toEqual(parseObjectJSON);
265+
});
266+
267+
it('can push leave response', function() {
268+
var parseObjectJSON = {
269+
key : 'value',
270+
className: 'test',
271+
objectId: 'test',
272+
updatedAt: '2015-12-07T21:27:13.746Z',
273+
createdAt: '2015-12-07T21:27:13.746Z',
274+
ACL: 'test',
275+
test: 'test'
276+
};
277+
var parseWebSocket = {
278+
send: jasmine.createSpy('send')
279+
};
280+
var client = new Client(1, parseWebSocket);
281+
client.pushLeave(2, parseObjectJSON);
282+
283+
var lastCall = parseWebSocket.send.calls.first();
284+
var messageJSON = JSON.parse(lastCall.args[0]);
285+
expect(messageJSON.op).toBe('leave');
286+
expect(messageJSON.clientId).toBe(1);
287+
expect(messageJSON.requestId).toBe(2);
288+
expect(messageJSON.object).toEqual(parseObjectJSON);
289+
});
290+
});

spec/EventEmitterPubSub.spec.js

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
var EventEmitterPubSub = require('../src/LiveQuery/EventEmitterPubSub').EventEmitterPubSub;
2+
3+
describe('EventEmitterPubSub', function() {
4+
5+
it('can publish and subscribe', function() {
6+
var publisher = EventEmitterPubSub.createPublisher();
7+
var subscriber = EventEmitterPubSub.createSubscriber();
8+
subscriber.subscribe('testChannel');
9+
// Register mock checked for subscriber
10+
var isChecked = false;
11+
subscriber.on('message', function(channel, message) {
12+
isChecked = true;
13+
expect(channel).toBe('testChannel');
14+
expect(message).toBe('testMessage');
15+
});
16+
17+
publisher.publish('testChannel', 'testMessage');
18+
// Make sure the callback is checked
19+
expect(isChecked).toBe(true);
20+
});
21+
22+
it('can unsubscribe', function() {
23+
var publisher = EventEmitterPubSub.createPublisher();
24+
var subscriber = EventEmitterPubSub.createSubscriber();
25+
subscriber.subscribe('testChannel');
26+
subscriber.unsubscribe('testChannel');
27+
// Register mock checked for subscriber
28+
var isCalled = false;
29+
subscriber.on('message', function(channel, message) {
30+
isCalled = true;
31+
});
32+
33+
publisher.publish('testChannel', 'testMessage');
34+
// Make sure the callback is not called
35+
expect(isCalled).toBe(false);
36+
});
37+
38+
it('can unsubscribe not subscribing channel', function() {
39+
var subscriber = EventEmitterPubSub.createSubscriber();
40+
41+
// Make sure subscriber does not throw exception
42+
subscriber.unsubscribe('testChannel');
43+
});
44+
});

0 commit comments

Comments
 (0)