From 3073b777396441e36ef69b113fa0f82854bffe3e Mon Sep 17 00:00:00 2001 From: dblythy Date: Sun, 5 Jun 2022 21:31:10 +1000 Subject: [PATCH] fix: allow `Parse.Cloud.beforeSubscribe` rejections to be caught by query.subscribe --- integration/test/ParseLiveQueryTest.js | 27 ++++++++++++++++++++++++ integration/test/cloud/before_connect.js | 3 +++ integration/test/cloud/main.js | 4 ++++ src/LiveQueryClient.js | 16 ++++++++++++-- 4 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 integration/test/cloud/before_connect.js diff --git a/integration/test/ParseLiveQueryTest.js b/integration/test/ParseLiveQueryTest.js index d3089f691..56d78a735 100644 --- a/integration/test/ParseLiveQueryTest.js +++ b/integration/test/ParseLiveQueryTest.js @@ -256,4 +256,31 @@ describe('Parse LiveQuery', () => { object.set({ foo: 'bar' }); await object.save(); }); + + it('live query can handle beforeConnect and beforeSubscribe errors', async () => { + const client = new Parse.LiveQueryClient({ + applicationId: 'integration', + serverURL: 'ws://localhost:1337', + javascriptKey: null, + masterKey: null, + sessionToken: null, + installationId: null, + }); + client.open(); + const query = new Parse.Query('TestError'); + let subscription = client.subscribe(query); + await expectAsync(subscription.subscribePromise).toBeRejectedWith( + new Parse.Error(141, 'not allowed to subscribe') + ); + client.close(); + await reconfigureServer({ + cloud: `${__dirname}/cloud/before_connect.js`, + }); + client.open(); + subscription = client.subscribe(query); + await expectAsync(subscription.subscribePromise).toBeRejectedWith( + new Parse.Error(141, 'not allowed to connect') + ); + client.close(); + }); }); diff --git a/integration/test/cloud/before_connect.js b/integration/test/cloud/before_connect.js new file mode 100644 index 000000000..e334bdc53 --- /dev/null +++ b/integration/test/cloud/before_connect.js @@ -0,0 +1,3 @@ +Parse.Cloud.beforeConnect(() => { + throw 'not allowed to connect'; +}); diff --git a/integration/test/cloud/main.js b/integration/test/cloud/main.js index 920948d83..063986120 100644 --- a/integration/test/cloud/main.js +++ b/integration/test/cloud/main.js @@ -48,3 +48,7 @@ Parse.Cloud.job('CloudJob2', function () { Parse.Cloud.job('CloudJobFailing', function () { throw 'cloud job failed'; }); + +Parse.Cloud.beforeSubscribe('TestError', () => { + throw 'not allowed to subscribe'; +}); diff --git a/src/LiveQueryClient.js b/src/LiveQueryClient.js index 2210dee4d..198c2d3b0 100644 --- a/src/LiveQueryClient.js +++ b/src/LiveQueryClient.js @@ -14,6 +14,7 @@ import EventEmitter from './EventEmitter'; import ParseObject from './ParseObject'; import LiveQuerySubscription from './LiveQuerySubscription'; import { resolvingPromise } from './promiseUtils'; +import ParseError from './ParseError'; // The LiveQuery client inner state const CLIENT_STATE = { @@ -218,6 +219,10 @@ class LiveQueryClient extends EventEmitter { this.subscriptions.set(this.requestId, subscription); this.requestId += 1; this.connectPromise.then(() => { + if (this.connectError) { + subscription.subscribePromise.reject(this.connectError); + return; + } this.socket.send(JSON.stringify(subscribeRequest)); }); @@ -382,10 +387,16 @@ class LiveQueryClient extends EventEmitter { setTimeout(() => subscription.emit(SUBSCRIPTION_EMMITER_TYPES.OPEN, response), 200); } break; - case OP_EVENTS.ERROR: + case OP_EVENTS.ERROR: { + const parseError = new ParseError(data.code, data.error); + if (!this.id) { + this.connectError = parseError; + this.connectPromise.resolve(); + this.state = CLIENT_STATE.DISCONNECTED; + } if (data.requestId) { if (subscription) { - subscription.subscribePromise.resolve(); + subscription.subscribePromise.reject(parseError); setTimeout(() => subscription.emit(SUBSCRIPTION_EMMITER_TYPES.ERROR, data.error), 200); } } else { @@ -398,6 +409,7 @@ class LiveQueryClient extends EventEmitter { this._handleReconnect(); } break; + } case OP_EVENTS.UNSUBSCRIBED: // We have already deleted subscription in unsubscribe(), do nothing here break;