From dfe425cf6e94d505f5e34d9c5903f27af4bcc2d4 Mon Sep 17 00:00:00 2001 From: Lawrence Forooghian Date: Fri, 20 Oct 2023 16:02:11 -0300 Subject: [PATCH] Fix RealtimePresence#leave handling of PresenceMessage argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RealtimePresence’s `enter*`, `update*` and `leave*` methods all advertise themselves as accepting a PresenceMessage instance instead of just a data object. This is the only way that ably-js supports passing message extras to these methods. However, `leave` does not handle a PresenceMessage argument properly; it ends up nesting the PresenceMessage’s top-level fields inside the payload’s `data` property. To fix this, we change the argument handling to match that used by `enter`. Resolves #1465. --- src/common/lib/client/realtimepresence.ts | 6 +- test/realtime/presence.test.js | 71 ++++++++++++++++------- 2 files changed, 53 insertions(+), 24 deletions(-) diff --git a/src/common/lib/client/realtimepresence.ts b/src/common/lib/client/realtimepresence.ts index 8837e07f6f..51d6f51f22 100644 --- a/src/common/lib/client/realtimepresence.ts +++ b/src/common/lib/client/realtimepresence.ts @@ -223,10 +223,8 @@ class RealtimePresence extends Presence { 'RealtimePresence.leaveClient()', 'leaving; channel = ' + this.channel.name + ', client = ' + clientId ); - const presence = PresenceMessage.fromValues({ - action: 'leave', - data: data, - }); + const presence = PresenceMessage.fromData(data); + presence.action = 'leave'; if (clientId) { presence.clientId = clientId; } diff --git a/test/realtime/presence.test.js b/test/realtime/presence.test.js index 6a7e911902..948e1acded 100644 --- a/test/realtime/presence.test.js +++ b/test/realtime/presence.test.js @@ -373,38 +373,69 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, helper, async /* * Attach to channel, enter presence channel with extras and check received - * PresenceMessage has extras. + * PresenceMessage has extras. Then do the same for leaving presence. */ it('presenceMessageExtras', function (done) { var clientRealtime = helper.AblyRealtime({ clientId: testClientId, tokenDetails: authToken }); - var channelName = 'presenceMessageExtras'; + var channelName = 'presenceEnterWithExtras'; var clientChannel = clientRealtime.channels.get(channelName); var presence = clientChannel.presence; - presence.subscribe( - function (presenceMessage) { - try { - expect(presenceMessage.extras).to.deep.equal( - { headers: { key: 'value' } }, - 'extras should have headers "key=value"' + + async.series( + [ + function (cb) { + clientChannel.attach(cb); + }, + // Test entering with extras + function (cb) { + presence.subscribe('enter', function (presenceMessage) { + try { + expect(presenceMessage.extras).to.deep.equal( + { headers: { key: 'value' } }, + 'extras should have headers "key=value"' + ); + } catch (err) { + cb(err); + return; + } + cb(); + }); + presence.enter( + PresenceMessage.fromValues({ + extras: { headers: { key: 'value' } }, + }) ); - } catch (err) { - closeAndFinish(done, clientRealtime, err); - return; - } - closeAndFinish(done, clientRealtime); - }, - function onPresenceSubscribe(err) { + }, + // Test leaving with extras + function (cb) { + presence.subscribe('leave', function (presenceMessage) { + try { + expect(presenceMessage.extras).to.deep.equal( + { headers: { otherKey: 'otherValue' } }, + 'extras should have headers "otherKey=otherValue"' + ); + } catch (err) { + cb(err); + return; + } + cb(); + }); + presence.leave( + PresenceMessage.fromValues({ + extras: { headers: { otherKey: 'otherValue' } }, + }) + ); + }, + ], + function (err) { if (err) { closeAndFinish(done, clientRealtime, err); return; } - clientChannel.presence.enter( - PresenceMessage.fromValues({ - extras: { headers: { key: 'value' } }, - }) - ); + closeAndFinish(done, clientRealtime); } ); + monitorConnection(done, clientRealtime); });