diff --git a/docs/internal/private-api-usage.md b/docs/internal/private-api-usage.md index ec522c0f1..55d52db7e 100644 --- a/docs/internal/private-api-usage.md +++ b/docs/internal/private-api-usage.md @@ -21,17 +21,25 @@ None ### `test/realtime/delta.test.js` +Marked in code. + - `channel._lastPayload.messageId = null` - to make decoding fail +Note that this test passes an overridden VCDiff decoder, but some SDKs don't use a VCDiff decoder + ### `test/realtime/encoding.test.js` +Marked in code. + - `var BufferUtils = Ably.Realtime.Platform.BufferUtils;` - `var Defaults = Ably.Rest.Platform.Defaults;` - just used for accessing library’s baked-in protocol version, to pass to `request()` ### `test/realtime/presence.test.js` +Marked in code. + - `var createPM = Ably.protocolMessageFromDeserialized;` - `var PresenceMessage = Ably.Realtime.PresenceMessage;` - replacing `channel.sendPresence` with a version that checks the presence message’s client ID @@ -47,6 +55,8 @@ None ### `test/realtime/event_emitter.test.js` +Marked in code. + - `eventEmitter.emit('custom');` — RTE6 says that `emit` is internal ### `test/realtime/api.test.js` @@ -55,15 +65,18 @@ None ### `test/realtime/crypto.test.js` +Marked in code. + - `var BufferUtils = Ably.Realtime.Platform.BufferUtils;` - `var msgpack = typeof window == 'object' ? Ably.msgpack : require('@ably/msgpack-js');` - `Message.encode(testMessage, channelOpts)` - `Message.decode(encryptedMessage, channelOpts);` -- `Message.fromValues(` - `expect(channel.channelOptions.cipher.algorithm).to.equal('aes');` — `channel.channelOptions` is not public API ### `test/realtime/failure.test.js` +Marked in code. + - `webSocketConnectTimeout: 50` client option - replacing `channel.processMessage` to drop `ATTACHED` - replacing `realtime.connection.connectionManager.activeProtocol.transport.onProtocolMessage` to drop `ACK` @@ -75,6 +88,8 @@ None ### `test/realtime/channel.test.js` +Marked in code. + - `var createPM = Ably.protocolMessageFromDeserialized;` - `expect(channel.channelOptions).to.deep.equal(channelOptions, 'Check requested channel options');` (`channelOptions` isn’t public API) - listens for `channel._allChannelChanges.on(['update'],` @@ -88,13 +103,18 @@ None ### `test/realtime/auth.test.js` +Marked in code. + - `var http = new Ably.Realtime._Http();` — just uses this as an HTTP client to fetch a JWT +- reads `realtime.auth.method` to check it’s `token` - spies on `rest.time` to count how many times called - checks `rest.serverTimeOffset` - spies on `transport.send` to look for an outgoing `AUTH` and check its properties ### `test/realtime/transports.test.js` +Skipped marking in code. + Transports are a JS-specific concept so might not be worth worrying too much about the contents of this file - `const Defaults = Ably.Rest.Platform.Defaults;` @@ -111,12 +131,18 @@ Transports are a JS-specific concept so might not be worth worrying too much abo ### `test/realtime/utils.test.js` +Marked in code. + Ah, I just realised that some of the properties on `shared_helper` actually refer to properties of the library, e.g. `helper.Utils` is actually `Ably.Realtime.Utils`. So perhaps I missed some usages of internal APIs in earlier files. But can figure that out later. +(I’ve addressed this in the context of marking the code; utils stuff is properly marked.) + - this entire file is a test of the internal `utils.getRetryTime(…)` method ### `test/realtime/resume.test.js` +Marked in code. + - `connectionManager.once('transport.active',` and inside the callback it makes an assertion on `transport.params.mode` - sets a channel’s state: `suspendedChannel.state = 'suspended';` - sabotages a resume by setting `connection.connectionManager`’s `conectionKey` and `connectionId` to garbage @@ -132,6 +158,8 @@ Ah, I just realised that some of the properties on `shared_helper` actually refe ### `test/realtime/message.test.js` +Marked in code. + - `let config = Ably.Realtime.Platform.Config;` - `var createPM = Ably.protocolMessageFromDeserialized;` - modifies `transport.send` to check the `clientId` on the outgoing `MESSAGE` @@ -141,6 +169,8 @@ Ah, I just realised that some of the properties on `shared_helper` actually refe ### `test/realtime/connection.test.js` +Marked in code. + - creates a `recover` client option which uses knowledge of ably-js’s serialization of recovery key - spies on `transport.send` to listen for `MESSAGE`, check its properties, and then continue the test - calls `connectionManager.disconnectAllTransports();` @@ -149,6 +179,8 @@ Ah, I just realised that some of the properties on `shared_helper` actually refe ### `test/realtime/init.test.js` +Marked in code. + - accesses `var transport = realtime.connection.connectionManager.activeProtocol.transport.uri` or `.recvRequest.recvUri` to check the `v=3` query parameter - `expect(realtime.options).to.deep.equal(realtime.connection.connectionManager.options);` - checks `realtime.connection.connectionManager.httpHosts[0];` to check it’s using correct default host, also checks length of that array @@ -165,6 +197,8 @@ None ### `test/realtime/connectivity.test.js` +Marked in code. + - directly calls `new Ably.Realtime._Http().checkConnectivity()` and checks it succeeds (i.e. directly tests this method) ### `test/realtime/reauth.test.js` @@ -173,19 +207,27 @@ None ### `test/realtime/sync.test.js` +Marked in code. + - calling `channel.processMessage` to inject an `ATTACHED` with a presence flag, and then a `SYNC`, later on a `PRESENCE` - spies on `channel.processMessage` to, after processing a received `SYNC`, inject a `PRESENCE` ### `test/browser/simple.test.js` +Skipped marking in code since it’s browser-specific. + - checks whether a transport is available using `transport in Ably.Realtime.ConnectionManager.supportedTransports(Ably.Realtime._transports)` ### `test/browser/http.test.js` +Skipped marking in code since it’s browser-specific. + - changes `Ably.Rest.Platform.Config.xhrSupported` to false to make it use Fetch ### `test/browser/connection.test.js` +Skipped marking in code since it’s browser-specific. + (I guess that this is a test that we might not include in the unified test suite.) - uses knowledge of library’s usage of `window.sessionStorage` for transport preference and recovery key @@ -197,6 +239,8 @@ None ### `test/browser/modular.test.js` +Skipped marking in code since it’s browser-specific. + Another file that probably wouldn’t be part of a unified test suite. - `const BufferUtils = BaseRest.Platform.BufferUtils;` @@ -227,10 +271,14 @@ N/A ### `test/common/modules/client_module.js` -- uses `Ably.Realtime.Utils` for its `mixin` function +Marked in code. + +- uses `Ably.Realtime.Utils` for its `mixin` and `copy` function ### `test/common/modules/testapp_manager.js` +Marked in code. + - uses `ably.Realtime.Platform.BufferUtils` ### `test/common/modules/testapp_module.js` @@ -239,6 +287,8 @@ None ### `test/common/modules/shared_helper.js` +Marked in code. + - `var utils = clientModule.Ably.Realtime.Utils;` - `var platform = clientModule.Ably.Realtime.Platform;` - uses `platform.Config.nextTick()` @@ -314,15 +364,21 @@ N/A ### `test/rest/bufferutils.test.js` +Skipped marking in code. + This file is a unit test of `Ably.Realtime.Platform.BufferUtils`; something we wouldn’t include in a unified test suite. ### `test/rest/presence.test.js` +Marked in code. + - `var BufferUtils = Ably.Realtime.Platform.BufferUtils;` - I’m going to stop mentioning the use of BufferUtils as a test util now; the pattern is clear and not hard to fix. ### `test/rest/fallbacks.test.js` +Marked in code. + - checks `rest._currentFallback.{host, validUntil}` to check that the working fallback has been stored correctly - modifies `rest._currentFallback.validUntil` to check library correctly forgets stored fallback @@ -344,12 +400,16 @@ None ### `test/rest/auth.test.js` +Marked in code. + - ditto will stop mentioning usage of `Utils` for stuff that will be pretty easy to replace None ### `test/rest/http.test.js` +Marked in code. + - accesses `Ably.Rest.Platform.Defaults` to check its `version` is being used to populate `Ably-Agent` - spies on `rest.http.do` to make assertions about request headers - replaces `rest.http.do` to simulate a 204 response @@ -360,10 +420,14 @@ None ### `test/rest/push.test.js` +Marked in code. + None ### `test/rest/message.test.js` +Marked in code. + - spies on `channel._publish` to verify that client does / doesn’t add a `clientId` - ditto to check that idempotent REST publishing generates message IDs - ditto to check `params` @@ -371,14 +435,20 @@ None ### `test/rest/init.test.js` +Marked in code. + - accesses various properties of `rest.options` to check the effect of passing various things to the constructor ### `test/rest/history.test.js` +Marked in code. + None ### `test/rest/defaults.test.js` +TODO decide what to do re marking this one. + This appears to be a unit test of the `Defaults` class’s `normaliseOptions()`, `getHosts()`, and `getPort()` methods. But I imagine it’s actually providing the test suite’s coverage of a bunch of spec points which aren’t written in terms of this API. ### `test/rest/status.test.js` @@ -387,6 +457,8 @@ None ### `test/rest/request.test.js` +Marked in code. + - overrides `rest.http.do()` to check `X-Ably-Version` request header ### `test/package/browser/template/server/resources/runTest.js` diff --git a/test/common/globals/named_dependencies.js b/test/common/globals/named_dependencies.js index 0558b575e..f406284b6 100644 --- a/test/common/globals/named_dependencies.js +++ b/test/common/globals/named_dependencies.js @@ -13,5 +13,9 @@ define(function () { shared_helper: { browser: 'test/common/modules/shared_helper', node: 'test/common/modules/shared_helper' }, async: { browser: 'node_modules/async/lib/async' }, chai: { browser: 'node_modules/chai/chai', node: 'node_modules/chai/chai' }, + private_api_recorder: { + browser: 'test/common/modules/private_api_recorder', + node: 'test/common/modules/private_api_recorder', + }, }); }); diff --git a/test/common/modules/client_module.js b/test/common/modules/client_module.js index 5ea3c37ba..e43fc0bec 100644 --- a/test/common/modules/client_module.js +++ b/test/common/modules/client_module.js @@ -5,8 +5,10 @@ define(['ably', 'globals', 'test/common/modules/testapp_module'], function (Ably, ablyGlobals, testAppHelper) { var utils = Ably.Realtime.Utils; - function ablyClientOptions(options) { + function ablyClientOptions(helper, options) { + helper.recordPrivateApi('call.Utils.copy'); var clientOptions = utils.copy(ablyGlobals); + helper.recordPrivateApi('call.Utils.mixin'); utils.mixin(clientOptions, options); var authMethods = ['authUrl', 'authCallback', 'token', 'tokenDetails', 'key']; @@ -22,12 +24,12 @@ define(['ably', 'globals', 'test/common/modules/testapp_module'], function (Ably return clientOptions; } - function ablyRest(options) { - return new Ably.Rest(ablyClientOptions(options)); + function ablyRest(helper, options) { + return new Ably.Rest(ablyClientOptions(helper, options)); } - function ablyRealtime(options) { - return new Ably.Realtime(ablyClientOptions(options)); + function ablyRealtime(helper, options) { + return new Ably.Realtime(ablyClientOptions(helper, options)); } return (module.exports = { diff --git a/test/common/modules/private_api_recorder.js b/test/common/modules/private_api_recorder.js new file mode 100644 index 000000000..f3030a7c7 --- /dev/null +++ b/test/common/modules/private_api_recorder.js @@ -0,0 +1,158 @@ +'use strict'; + +define([], function () { + const privateAPIIdentifiers = [ + 'call.BufferUtils.areBuffersEqual', + 'call.BufferUtils.base64Decode', + 'call.BufferUtils.base64Encode', + 'call.BufferUtils.utf8Encode', + 'call.BufferUtils.hexEncode', + 'call.BufferUtils.isBuffer', + 'call.BufferUtils.toArrayBuffer', + 'call.ConnectionManager.supportedTransports', + 'call.Defaults.getHost', + 'call.EventEmitter.emit', + 'call.Message.decode', + 'call.Message.encode', + 'call.Platform.nextTick', + 'call.PresenceMessage.fromValues', + 'call.ProtocolMessage.setFlag', + 'call.Utils.copy', + 'call.Utils.getRetryTime', + 'call.Utils.inspectError', + 'call.Utils.keysArray', + 'call.Utils.mixin', + 'call.Utils.toQueryString', + 'call.auth.getAuthHeaders', + 'call.channel.checkPendingState', + 'call.channel.processMessage', + 'call.channel.requestState', + 'call.channel.sendPresence', + 'call.channel.sync', + 'call.connectionManager.disconnectAllTransports', + 'call.connectionManager.notifyState', + 'call.connectionManager.onChannelMessage', + 'call.connectionManager.requestState', + 'call.connectionManager.send', + 'call.filteredSubscriptions.has', + 'call.http._getHosts', + 'call.http.checkConnectivity', + 'call.http.doUri', + 'call.msgpack.decode', + 'call.msgpack.encode', + 'call.presence._myMembers.put', + 'call.presence.waitSync', + 'call.protocolMessageFromDeserialized', + 'call.realtime.baseUri', + 'call.realtime.connection.connectionManager.activeProtocol.getTransport', + 'call.rest.baseUri', + 'call.rest.http.do', + 'call.restChannel._publish', + 'call.transport.onProtocolMessage', + 'call.transport.send', + 'delete.auth.authOptions.requestHeaders', + 'deserialize.recoveryKey', + 'listen.channel._allChannelChanges.attached', + 'listen.channel._allChannelChanges.update', + 'listen.connectionManager.connectiondetails', + 'listen.connectionManager.transport.active', + 'listen.connectionManager.transport.pending', + 'listen.transport.disposed', + 'new.Crypto.CipherParams', // This is not _really_ a private API since the CipherParams class is part of the IDL (although not part of the JS typings) + 'pass.clientOption.connectivityCheckUrl', // actually ably-js public API but no other SDK has it and it doesn’t enable ably-js-specific functionality + 'pass.clientOption.disableConnectivityCheck', // actually ably-js public API but no other SDK has it and it doesn’t enable ably-js-specific functionality + 'pass.clientOption.webSocketConnectTimeout', + 'read.Defaults.protocolVersion', + 'read.Defaults.version', + 'read.EventEmitter.events', + 'read.Realtime._transports', + 'read.auth.authOptions.authUrl', + 'read.auth.key', + 'read.auth.method', + 'read.auth.tokenParams.version', + 'read.channel.channelOptions', + 'read.channel.channelOptions.cipher', + 'read.connectionManager.activeProtocol', + 'read.connectionManager.baseTransport', + 'read.connectionManager.connectionId', + 'read.connectionManager.connectionId', + 'read.connectionManager.connectionStateTtl', + 'read.connectionManager.httpHosts', + 'read.connectionManager.msgSerial', + 'read.connectionManager.options', + 'read.connectionManager.options.timeouts.httpMaxRetryDuration', + 'read.connectionManager.options.timeouts.httpRequestTimeout', + 'read.connectionManager.pendingTransport', + 'read.connectionManager.queuedMessages.messages', + 'read.connectionManager.states.disconnected.retryDelay', + 'read.connectionManager.states.suspended.retryDelay', + 'read.connectionManager.webSocketTransportAvailable', + 'read.realtime.connection.connectionManager.activeProtocol.transport', + 'read.realtime.options', + 'read.realtime.options.key', + 'read.realtime.options.maxMessageSize', + 'read.realtime.options.token', + 'read.rest._currentFallback', + 'read.rest._currentFallback.host', + 'read.rest._currentFallback.validUntil', + 'read.rest.options.key', + 'read.rest.options.realtimeHost', + 'read.rest.serverTimeOffset', + 'read.transport.params.mode', + 'read.transport.recvRequest.recvUri', + 'read.transport.uri', + 'replace.channel.attachImpl', + 'replace.channel.processMessage', + 'replace.channel.sendMessage', + 'replace.channel.sendPresence', + 'replace.connectionManager.onChannelMessage', + 'replace.connectionManager.send', + 'replace.connectionManager.tryATransport', + 'replace.http.doUri', + 'replace.rest.http.do', + 'replace.rest.time', + 'replace.restChannel._publish', + 'replace.transport.onProtocolMessage', + 'replace.transport.send', + 'serialize.recoveryKey', + 'write.auth.authOptions.requestHeaders', + 'write.auth.key', + 'write.auth.tokenDetails.token', + 'write.channel._lastPayload', + 'write.channel.state', + 'write.connectionManager.connectionDetails.maxMessageSize', + 'write.connectionManager.connectionId', + 'write.connectionManager.connectionKey', + 'write.connectionManager.lastActivity', + 'write.connectionManager.msgSerial', + 'write.realtime.options.timeouts.realtimeRequestTimeout', + 'write.rest._currentFallback.validUntil', + ]; + + class PrivateApiRecorder { + privateAPIUsages = []; + + /** + * Creates a recording context for the current Mocha test case. + * + * @param description A description of the context for which the calls will be recorded. + */ + createContext(description) { + if (!description) { + throw new Error('No description passed to createContext'); + } + + return { + record: (privateAPIIdentifier) => { + if (privateAPIIdentifiers.indexOf(privateAPIIdentifier) == -1) { + throw new Error(`(${description}) Recorded unknown private API: ${privateAPIIdentifier}`); + } + console.log(`(${description}) Recorded private API: ${privateAPIIdentifier}`); + this.privateAPIUsages.push({ contextDescription: description, privateAPIIdentifier }); + }, + }; + } + } + + return (module.exports = new PrivateApiRecorder()); +}); diff --git a/test/common/modules/shared_helper.js b/test/common/modules/shared_helper.js index 34b7643e5..9c65a7533 100644 --- a/test/common/modules/shared_helper.js +++ b/test/common/modules/shared_helper.js @@ -10,7 +10,8 @@ define([ 'globals', 'async', 'chai', -], function (testAppModule, clientModule, testAppManager, globals, async, chai) { + 'private_api_recorder', +], function (testAppModule, clientModule, testAppManager, globals, async, chai, privateApiRecorder) { var utils = clientModule.Ably.Realtime.Utils; var platform = clientModule.Ably.Realtime.Platform; var BufferUtils = platform.BufferUtils; @@ -21,13 +22,9 @@ define([ class SharedHelper { setupApp = testAppModule.setup; - tearDownApp = testAppModule.tearDown; - createStats = testAppModule.createStatsFixtureData; getTestApp = testAppModule.getTestApp; Ably = clientModule.Ably; - AblyRest = clientModule.AblyRest; - ablyClientOptions = clientModule.ablyClientOptions; Utils = utils; loadTestData = testAppManager.loadJsonData; @@ -42,6 +39,7 @@ define([ throw new Error('SharedHelper created without context'); } this.context = context; + this.privateApiContext = privateApiRecorder.createContext(this.context); } static forTest(thisInBeforeEach) { @@ -59,7 +57,14 @@ define([ return new this(`${thisInDescribe.title} (defining ${label})`); } + recordPrivateApi(identifier) { + this.privateApiContext.record(identifier); + } + get availableTransports() { + this.recordPrivateApi('call.Utils.keysArray'); + this.recordPrivateApi('call.ConnectionManager.supportedTransports'); + this.recordPrivateApi('read.Realtime._transports'); return utils.keysArray( clientModule.Ably.Realtime.ConnectionManager.supportedTransports(clientModule.Ably.Realtime._transports), ); @@ -137,18 +142,24 @@ define([ } simulateDroppedConnection(realtime) { + const self = this; // Go into the 'disconnected' state before actually disconnecting the transports // to avoid the instantaneous reconnect attempt that would be triggered in // notifyState by the active transport getting disconnected from a connected state realtime.connection.once('disconnected', function () { + self.recordPrivateApi('call.connectionManager.disconnectAllTransports'); realtime.connection.connectionManager.disconnectAllTransports(); }); + this.recordPrivateApi('call.connectionManager.requestState'); realtime.connection.connectionManager.requestState({ state: 'disconnected' }); } becomeSuspended(realtime, cb) { + this.recordPrivateApi('call.connectionManager.disconnectAllTransports'); realtime.connection.connectionManager.disconnectAllTransports(); + const self = this; realtime.connection.once('disconnected', function () { + self.recordPrivateApi('call.connectionManager.notifyState'); realtime.connection.connectionManager.notifyState({ state: 'suspended' }); }); if (cb) @@ -158,19 +169,24 @@ define([ } callbackOnClose(realtime, callback) { + this.recordPrivateApi('read.connectionManager.activeProtocol'); if (!realtime.connection.connectionManager.activeProtocol) { + this.recordPrivateApi('call.Platform.nextTick'); platform.Config.nextTick(function () { realtime.close(); callback(); }); return; } + this.recordPrivateApi('read.realtime.connection.connectionManager.activeProtocol.transport'); + this.recordPrivateApi('listen.transport.disposed'); realtime.connection.connectionManager.activeProtocol.transport.on('disposed', function () { callback(); }); /* wait a tick before closing in order to avoid the final close * happening synchronously in a publish/attach callback, which * complicates channelattach_publish_invalid etc. */ + this.recordPrivateApi('call.Platform.nextTick'); platform.Config.nextTick(function () { realtime.close(); }); @@ -260,7 +276,9 @@ define([ return; } + this.recordPrivateApi('call.BufferUtils.isBuffer'); if (BufferUtils.isBuffer(one.data) && BufferUtils.isBuffer(two.data)) { + this.recordPrivateApi('call.BufferUtils.areBuffersEqual'); expect(BufferUtils.areBuffersEqual(one.data, two.data), 'Buffer data contents mismatch.').to.equal(true); return; } @@ -274,10 +292,18 @@ define([ expect(json1 === json2, 'JSON data contents mismatch.').to.be.ok; } + ablyClientOptions(options) { + return clientModule.ablyClientOptions(this, options); + } + + AblyRest(options) { + return clientModule.AblyRest(this, options); + } + static activeClients = []; AblyRealtime(options) { - const client = clientModule.AblyRealtime(options); + const client = clientModule.AblyRealtime(this, options); SharedHelper.activeClients.push(client); return client; } @@ -305,6 +331,14 @@ define([ } } } + + createStats(app, statsData, callback) { + testAppModule.createStatsFixtureData(this, app, statsData, callback); + } + + tearDownApp(app, callback) { + testAppModule.tearDown(this, app, callback); + } } SharedHelper.testOnAllTransports.skip = function (thisInDescribe, name, testFn) { diff --git a/test/common/modules/testapp_manager.js b/test/common/modules/testapp_manager.js index d69fcb904..4c897bca2 100644 --- a/test/common/modules/testapp_manager.js +++ b/test/common/modules/testapp_manager.js @@ -31,9 +31,11 @@ define(['globals', 'ably'], function (ablyGlobals, ably) { } } - function toBase64(str) { + function toBase64(helper, str) { var bufferUtils = ably.Realtime.Platform.BufferUtils; + helper.recordPrivateApi('call.BufferUtils.utf8Encode'); var buffer = bufferUtils.utf8Encode(str); + helper.recordPrivateApi('call.BufferUtils.base64Encode'); return bufferUtils.base64Encode(buffer); } @@ -164,11 +166,11 @@ define(['globals', 'ably'], function (ablyGlobals, ably) { }); } - function createStatsFixtureData(app, statsData, callback) { + function createStatsFixtureData(helper, app, statsData, callback) { var postData = JSON.stringify(statsData); var authKey = app.keys[0].keyStr; - var authHeader = toBase64(authKey); + var authHeader = toBase64(helper, authKey); var postOptions = { host: restHost, @@ -195,9 +197,9 @@ define(['globals', 'ably'], function (ablyGlobals, ably) { }); } - function deleteApp(app, callback) { + function deleteApp(helper, app, callback) { var authKey = app.keys[0].keyStr, - authHeader = toBase64(authKey); + authHeader = toBase64(helper, authKey); var delOptions = { host: restHost, diff --git a/test/realtime/auth.test.js b/test/realtime/auth.test.js index 9bdb50c10..b3595cc92 100644 --- a/test/realtime/auth.test.js +++ b/test/realtime/auth.test.js @@ -13,8 +13,9 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async /* * Helper function to fetch JWT tokens from the echo server */ - function getJWT(params, callback) { + function getJWT(params, helper, callback) { var authUrl = echoServer + '/createJWT'; + helper.recordPrivateApi('call.http.doUri'); Helper.whenPromiseSettles(http.doUri('get', authUrl, null, null, params), function (err, result) { if (result.error) { callback(result.error, null); @@ -182,6 +183,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async realtime.connection.on('connected', function () { try { + helper.recordPrivateApi('read.auth.method'); expect(realtime.auth.method).to.equal('token'); helper.closeAndFinish(done, realtime); } catch (err) { @@ -222,6 +224,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async realtime.connection.on('connected', function () { try { + helper.recordPrivateApi('read.auth.method'); expect(realtime.auth.method).to.equal('token'); helper.closeAndFinish(done, realtime); } catch (err) { @@ -258,6 +261,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async realtime.connection.on('connected', function () { try { + helper.recordPrivateApi('read.auth.method'); expect(realtime.auth.method).to.equal('token'); helper.closeAndFinish(done, realtime); } catch (err) { @@ -296,6 +300,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async keyName: tokenRequest.keyName, mac: tokenRequest.mac, }; + helper.recordPrivateApi('call.Utils.toQueryString'); var authPath = echoServer + '/qs_to_body' + helper.Utils.toQueryString(lowerPrecedenceTokenRequestParts); realtime = helper.AblyRealtime({ authUrl: authPath, authParams: higherPrecedenceTokenRequestParts }); @@ -666,6 +671,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async done(err); return; } + helper.recordPrivateApi('call.Utils.mixin'); clientRealtime = helper.AblyRealtime( helper.Utils.mixin(realtimeOpts, { tokenDetails: tokenDetails, queryTime: true }), ); @@ -701,12 +707,14 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async originalTime = rest.time; /* stub time */ + helper.recordPrivateApi('replace.rest.time'); rest.time = async function () { timeRequestCount += 1; return originalTime.call(rest); }; try { + helper.recordPrivateApi('read.rest.serverTimeOffset'); expect( isNaN(parseInt(rest.serverTimeOffset)) && !rest.serverTimeOffset, 'Server time offset is empty and falsey until a time request has been made', @@ -723,6 +731,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async if (err) { return callback(err); } + helper.recordPrivateApi('read.rest.serverTimeOffset'); expect( !isNaN(parseInt(rest.serverTimeOffset)), 'Server time offset is configured when time is requested', @@ -768,6 +777,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }); }; + helper.recordPrivateApi('call.Utils.mixin'); realtime = helper.AblyRealtime( helper.Utils.mixin(realtimeOpts, { authCallback: authCallback, clientId: clientId }), ); @@ -812,6 +822,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }); }; + helper.recordPrivateApi('call.Utils.mixin'); realtime = helper.AblyRealtime( helper.Utils.mixin(realtimeOpts, { authCallback: authCallback, clientId: clientId }), ); @@ -851,6 +862,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async helper.closeAndFinish(done, realtime, err); return; } + helper.recordPrivateApi('call.Utils.mixin'); realtime = helper.AblyRealtime( helper.Utils.mixin(realtimeOpts, { token: tokenDetails.token, clientId: clientId }), ); @@ -896,6 +908,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async return; } setTimeout(function () { + helper.recordPrivateApi('call.Utils.mixin'); realtime = helper.AblyRealtime( helper.Utils.mixin(realtimeOpts, { token: tokenDetails.token, clientId: clientId }), ); @@ -946,6 +959,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }); }; + helper.recordPrivateApi('call.Utils.mixin'); realtime = helper.AblyRealtime(helper.Utils.mixin(realtimeOpts, { authCallback: authCallback })); realtime.connection.once('connected', function () { var channel = realtime.channels.get('right'); @@ -992,6 +1006,9 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }); try { + helper.recordPrivateApi('read.auth.tokenParams.version'); + helper.recordPrivateApi('read.auth.authOptions.authUrl'); + expect(realtime.auth.tokenParams.version).to.equal(1, 'Check initial defaultTokenParams stored'); expect(realtime.auth.tokenDetails.token).to.equal('1', 'Check initial token stored'); expect(realtime.auth.authOptions.authUrl).to.equal('1', 'Check initial authUrl stored'); @@ -1030,8 +1047,10 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async realtime = helper.AblyRealtime({ authCallback: authCallback, transports: [helper.bestTransport] }); realtime.connection.once('connected', function () { + helper.recordPrivateApi('read.realtime.connection.connectionManager.activeProtocol.transport'); var transport = realtime.connection.connectionManager.activeProtocol.transport, originalSend = transport.send; + helper.recordPrivateApi('replace.transport.send'); /* Spy on transport.send to detect the outgoing AUTH */ transport.send = function (message) { if (message.action === 17) { @@ -1042,10 +1061,12 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async helper.closeAndFinish(done, realtime, err); } } else { + helper.recordPrivateApi('call.transport.send'); originalSend.call(this, message); } }; /* Inject a fake AUTH from realtime */ + helper.recordPrivateApi('call.transport.onProtocolMessage'); transport.onProtocolMessage({ action: 17 }); }); }); @@ -1059,9 +1080,10 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async var currentKey = helper.getTestApp().keys[0]; var keys = { keyName: currentKey.keyName, keySecret: currentKey.keySecret }; var clientId = 'testJWTClientId'; + helper.recordPrivateApi('call.Utils.mixin'); var params = helper.Utils.mixin(keys, { clientId: clientId }); var authCallback = function (tokenParams, callback) { - getJWT(params, callback); + getJWT(params, helper, callback); }; var realtime = helper.AblyRealtime({ authCallback: authCallback }); @@ -1093,9 +1115,10 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async var currentKey = helper.getTestApp().keys[0]; var keys = { keyName: currentKey.keyName, keySecret: currentKey.keySecret, returnType: 'jwt' }; var clientId = 'testJWTClientId'; + helper.recordPrivateApi('call.Utils.mixin'); var params = helper.Utils.mixin(keys, { clientId: clientId }); var authCallback = function (tokenParams, callback) { - getJWT(params, callback); + getJWT(params, helper, callback); }; var realtime = helper.AblyRealtime({ authCallback: authCallback }); @@ -1127,7 +1150,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async var currentKey = helper.getTestApp().keys[3]; // get subscribe-only keys { "*":["subscribe"] } var params = { keyName: currentKey.keyName, keySecret: currentKey.keySecret }; var authCallback = function (tokenParams, callback) { - getJWT(params, callback); + getJWT(params, helper, callback); }; var realtime = helper.AblyRealtime({ authCallback: authCallback }); @@ -1155,7 +1178,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async var currentKey = helper.getTestApp().keys[0]; var params = { keyName: currentKey.keyName, keySecret: currentKey.keySecret }; var authCallback = function (tokenParams, callback) { - getJWT(params, callback); + getJWT(params, helper, callback); }; var publishEvent = 'publishEvent', @@ -1185,7 +1208,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async var currentKey = helper.getTestApp().keys[0]; var params = { keyName: currentKey.keyName, keySecret: currentKey.keySecret, expiresIn: 5 }; var authCallback = function (tokenParams, callback) { - getJWT(params, callback); + getJWT(params, helper, callback); }; var realtime = helper.AblyRealtime({ authCallback: authCallback }); @@ -1213,7 +1236,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async // We create a token that lasts 35 so there's room to receive the update event message. var params = { keyName: currentKey.keyName, keySecret: currentKey.keySecret, expiresIn: 35 }; var authCallback = function (tokenParams, callback) { - getJWT(params, callback); + getJWT(params, helper, callback); }; var realtime = helper.AblyRealtime({ authCallback: authCallback }); @@ -1239,7 +1262,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async const helper = this.helper; var currentKey = helper.getTestApp().keys[0]; var params = { keyName: currentKey.keyName, keySecret: currentKey.keySecret }; - getJWT(params, function (err, token) { + getJWT(params, helper, function (err, token) { if (err) { done(err); return; @@ -1302,6 +1325,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async return; } /* Fake an expired token */ + // TODO is _writing_ token.expires a private API? token.expires = Date.now() - 5000; var authCallbackCallCount = 0; var authCallback = function (_, callback) { diff --git a/test/realtime/channel.test.js b/test/realtime/channel.test.js index b6cffeb3d..077f86b74 100644 --- a/test/realtime/channel.test.js +++ b/test/realtime/channel.test.js @@ -172,6 +172,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async var realtime = helper.AblyRealtime(realtimeOpts); realtime.connection.on('connected', function () { try { + helper.recordPrivateApi('read.channel.channelOptions'); /* set options on init */ var channel0 = realtime.channels.get('channelinit0', { fakeOption: true }); expect(channel0.channelOptions.fakeOption).to.equal(true); @@ -518,6 +519,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async return; } try { + helper.recordPrivateApi('read.channel.channelOptions'); expect(channel.channelOptions).to.deep.equal(channelOptions, 'Check requested channel options'); expect(channel.params).to.deep.equal(params, 'Check result params'); expect(channel.modes).to.deep.equal(['subscribe'], 'Check result modes'); @@ -572,6 +574,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async helper.closeAndFinish(done, realtime, err); return; } + helper.recordPrivateApi('read.channel.channelOptions'); expect(channel.channelOptions).to.deep.equal(channelOptions, 'Check requested channel options'); expect(channel.params).to.deep.equal(params, 'Check result params'); expect(channel.modes).to.deep.equal(['subscribe'], 'Check result modes'); @@ -696,6 +699,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }, function (cb) { var channelUpdated = false; + helper.recordPrivateApi('listen.channel._allChannelChanges.update'); channel._allChannelChanges.on(['update'], function () { channelUpdated = true; }); @@ -709,6 +713,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async function () { /* Wait a tick so we don' depend on whether the update event runs the * channelUpdated listener or the setOptions listener first */ + helper.recordPrivateApi('call.Platform.nextTick'); Ably.Realtime.Platform.Config.nextTick(function () { expect( channelUpdated, @@ -721,6 +726,8 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }, function (cb) { var channelUpdated = false; + helper.recordPrivateApi('listen.channel._allChannelChanges.update'); + helper.recordPrivateApi('listen.channel._allChannelChanges.attached'); channel._allChannelChanges.on(['attached', 'update'], function () { channelUpdated = true; }); @@ -730,6 +737,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async modes: ['subscribe'], }), function () { + helper.recordPrivateApi('call.Platform.nextTick'); Ably.Realtime.Platform.Config.nextTick(function () { expect(channelUpdated, 'Check channel went to the server to update the channel mode').to.be.ok; cb(); @@ -773,6 +781,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async return; } try { + helper.recordPrivateApi('read.channel.channelOptions'); expect(channel.channelOptions).to.deep.equal(channelOptions, 'Check requested channel options'); expect(channel.params).to.deep.equal(params, 'Check result params'); expect(channel.modes).to.deep.equal(paramsModes, 'Check result modes'); @@ -824,6 +833,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async return; } try { + helper.recordPrivateApi('read.channel.channelOptions'); expect(channel.channelOptions).to.deep.equal(channelOptions, 'Check requested channel options'); expect(channel.modes).to.deep.equal(modes, 'Check result modes'); } catch (err) { @@ -875,6 +885,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async return; } try { + helper.recordPrivateApi('read.channel.channelOptions'); expect(channel.channelOptions).to.deep.equal(channelOptions, 'Check requested channel options'); expect(channel.params).to.deep.equal({ delta: 'vcdiff' }, 'Check result params'); expect(channel.modes).to.deep.equal(modes, 'Check result modes'); @@ -1149,14 +1160,19 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }, function (cb) { /* Sabotage the reattach attempt, then simulate a server-sent detach */ + helper.recordPrivateApi('replace.channel.sendMessage'); channel.sendMessage = function () {}; + helper.recordPrivateApi('write.realtime.options.timeouts.realtimeRequestTimeout'); realtime.options.timeouts.realtimeRequestTimeout = 100; channel.once(function (stateChange) { expect(stateChange.current).to.equal('attaching', 'Channel reattach attempt happens immediately'); expect(stateChange.reason.code).to.equal(50000, 'check error is propogated in the reason'); cb(); }); + helper.recordPrivateApi('call.realtime.connection.connectionManager.activeProtocol.getTransport'); var transport = realtime.connection.connectionManager.activeProtocol.getTransport(); + helper.recordPrivateApi('call.protocolMessageFromDeserialized'); + helper.recordPrivateApi('call.transport.onProtocolMessage'); transport.onProtocolMessage( createPM({ action: 13, @@ -1190,8 +1206,10 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async channel = realtime.channels.get(channelName); realtime.connection.once('connected', function () { + helper.recordPrivateApi('call.realtime.connection.connectionManager.activeProtocol.getTransport'); var transport = realtime.connection.connectionManager.activeProtocol.getTransport(); /* Mock sendMessage to respond to attaches with a DETACHED */ + helper.recordPrivateApi('replace.channel.sendMessage'); channel.sendMessage = function (msg) { try { expect(msg.action).to.equal(10, 'check attach action'); @@ -1199,7 +1217,10 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async helper.closeAndFinish(done, realtime, err); return; } + helper.recordPrivateApi('call.Platform.nextTick'); Ably.Realtime.Platform.Config.nextTick(function () { + helper.recordPrivateApi('call.protocolMessageFromDeserialized'); + helper.recordPrivateApi('call.transport.onProtocolMessage'); transport.onProtocolMessage( createPM({ action: 13, @@ -1245,7 +1266,10 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async helper.closeAndFinish(done, realtime, err); } }); + helper.recordPrivateApi('call.realtime.connection.connectionManager.activeProtocol.getTransport'); var transport = realtime.connection.connectionManager.activeProtocol.getTransport(); + helper.recordPrivateApi('call.protocolMessageFromDeserialized'); + helper.recordPrivateApi('call.transport.onProtocolMessage'); transport.onProtocolMessage( createPM({ action: 9, @@ -1288,7 +1312,10 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async expect(channel.state).to.equal('attached', 'check channel still attached'); cb(); }); + helper.recordPrivateApi('call.realtime.connection.connectionManager.activeProtocol.getTransport'); var transport = realtime.connection.connectionManager.activeProtocol.getTransport(); + helper.recordPrivateApi('call.protocolMessageFromDeserialized'); + helper.recordPrivateApi('call.transport.onProtocolMessage'); transport.onProtocolMessage( createPM({ action: 11, @@ -1338,6 +1365,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async channel = realtime.channels.get(channelName); /* Stub out the channel's ability to communicate */ + helper.recordPrivateApi('replace.channel.sendMessage'); channel.sendMessage = function () {}; async.series( @@ -1357,6 +1385,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }, function (cb) { /* nexttick so that it doesn't pick up the suspended event */ + helper.recordPrivateApi('call.Platform.nextTick'); Ably.Realtime.Platform.Config.nextTick(function () { channel.once(function (stateChange) { expect(stateChange.current).to.equal('attaching', 'Check channel tries again after a bit'); @@ -1400,13 +1429,16 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async /* Have the connection go into the suspended state, and check that the * channel goes into the suspended state and doesn't try to reattach * until the connection reconnects */ + helper.recordPrivateApi('replace.channel.sendMessage'); channel.sendMessage = function (msg) { expect(false, 'Channel tried to send a message ' + JSON.stringify(msg)).to.be.ok; }; + helper.recordPrivateApi('write.realtime.options.timeouts.realtimeRequestTimeout'); realtime.options.timeouts.realtimeRequestTimeout = 2000; helper.becomeSuspended(realtime, function () { /* nextTick as connection event is emitted before channel state is changed */ + helper.recordPrivateApi('call.Platform.nextTick'); Ably.Realtime.Platform.Config.nextTick(function () { expect(channel.state).to.equal('suspended', 'check channel state is suspended'); cb(); @@ -1417,6 +1449,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async realtime.connection.once(function (stateChange) { expect(stateChange.current).to.equal('connecting', 'Check we try to connect again'); /* We no longer want to fail the test for an attach, but still want to sabotage it */ + helper.recordPrivateApi('replace.channel.sendMessage'); channel.sendMessage = function () {}; cb(); }); @@ -1465,6 +1498,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async /* Sabotage the detach attempt, detach, then simulate a server-sent attached while * the detach is ongoing. Expect to see the library reassert the detach */ let detachCount = 0; + helper.recordPrivateApi('replace.channel.sendMessage'); channel.sendMessage = function (msg) { expect(msg.action).to.equal(12, 'Check we only see a detach. No attaches!'); expect(channel.state).to.equal('detaching', 'Check still in detaching state after both detaches'); @@ -1477,7 +1511,10 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async /* */ channel.detach(); setTimeout(function () { + helper.recordPrivateApi('call.realtime.connection.connectionManager.activeProtocol.getTransport'); var transport = realtime.connection.connectionManager.activeProtocol.getTransport(); + helper.recordPrivateApi('call.protocolMessageFromDeserialized'); + helper.recordPrivateApi('call.transport.onProtocolMessage'); transport.onProtocolMessage(createPM({ action: 11, channel: channelName })); }, 0); }, diff --git a/test/realtime/connection.test.js b/test/realtime/connection.test.js index cbd33b99e..4cc3a68b1 100644 --- a/test/realtime/connection.test.js +++ b/test/realtime/connection.test.js @@ -69,8 +69,10 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async realtime = helper.AblyRealtime(); realtime.connection.on('connected', function () { try { + helper.recordPrivateApi('deserialize.recoveryKey'); const recoveryContext = JSON.parse(realtime.connection.recoveryKey); expect(recoveryContext.connectionKey).to.equal(realtime.connection.key); + helper.recordPrivateApi('read.connectionManager.msgSerial'); expect(recoveryContext.msgSerial).to.equal(realtime.connection.connectionManager.msgSerial); } catch (err) { helper.closeAndFinish(done, realtime, err); @@ -88,8 +90,10 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async function (cb) { channel.subscribe(function () { setTimeout(function () { + helper.recordPrivateApi('deserialize.recoveryKey'); const recoveryContext = JSON.parse(realtime.connection.recoveryKey); expect(recoveryContext.connectionKey).to.equal(realtime.connection.key); + helper.recordPrivateApi('read.connectionManager.msgSerial'); expect(recoveryContext.msgSerial).to.equal(realtime.connection.connectionManager.msgSerial); cb(); }, 0); @@ -126,6 +130,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async it('unrecoverableConnection', function (done) { const helper = this.helper; var realtime; + helper.recordPrivateApi('serialize.recoveryKey'); const fakeRecoveryKey = JSON.stringify({ connectionKey: '_____!ablyjs_test_fake-key____', msgSerial: 3, @@ -143,6 +148,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async 80018, 'verify unrecoverable-connection error set in connection.errorReason', ); + helper.recordPrivateApi('read.connectionManager.msgSerial'); expect(realtime.connection.connectionManager.msgSerial).to.equal( 0, 'verify msgSerial is 0 (new connection), not 3', @@ -174,6 +180,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async connectionManager = realtime.connection.connectionManager; realtime.connection.once('connected', function () { + helper.recordPrivateApi('read.realtime.connection.connectionManager.activeProtocol.transport'); var transport = connectionManager.activeProtocol.transport; Helper.whenPromiseSettles(channel.attach(), function (err) { if (err) { @@ -183,6 +190,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async let transportSendCallback; + helper.recordPrivateApi('replace.transport.send'); /* Sabotage sending the message */ transport.send = function (msg) { if (msg.action == 15) { @@ -232,9 +240,11 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }, function (cb) { /* After the disconnect, on reconnect, spy on transport.send again */ + helper.recordPrivateApi('listen.connectionManager.transport.pending'); connectionManager.once('transport.pending', function (transport) { var oldSend = transport.send; + helper.recordPrivateApi('replace.transport.send'); transport.send = function (msg, msgCb) { if (msg.action === 15) { if (msg.messages[0].name === 'first') { @@ -258,12 +268,14 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async cb(); } } + helper.recordPrivateApi('call.transport.send'); oldSend.call(transport, msg, msgCb); }; channel.publish('second', null); }); /* Disconnect the transport (will automatically reconnect and resume) () */ + helper.recordPrivateApi('call.connectionManager.disconnectAllTransports'); connectionManager.disconnectAllTransports(); }, ], @@ -287,15 +299,18 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async realtime = helper.AblyRealtime(), connectionManager = realtime.connection.connectionManager; realtime.connection.once('connected', function () { + helper.recordPrivateApi('listen.connectionManager.connectiondetails'); connectionManager.once('connectiondetails', function (details) { try { expect(details.connectionStateTtl).to.equal(12345, 'Check connectionStateTtl in event'); + helper.recordPrivateApi('read.connectionManager.connectionStateTtl'); expect(connectionManager.connectionStateTtl).to.equal( 12345, 'Check connectionStateTtl set in connectionManager', ); expect(details.clientId).to.equal('foo', 'Check clientId in event'); expect(realtime.auth.clientId).to.equal('foo', 'Check clientId set in auth'); + helper.recordPrivateApi('read.realtime.options.maxMessageSize'); expect(realtime.options.maxMessageSize).to.equal(98765, 'Check maxMessageSize set'); } catch (err) { helper.closeAndFinish(done, realtime, err); @@ -303,6 +318,9 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async } helper.closeAndFinish(done, realtime); }); + helper.recordPrivateApi('call.realtime.connection.connectionManager.activeProtocol.getTransport'); + helper.recordPrivateApi('replace.transport.onProtocolMessage'); + helper.recordPrivateApi('call.protocolMessageFromDeserialized'); connectionManager.activeProtocol.getTransport().onProtocolMessage( createPM({ action: 4, diff --git a/test/realtime/connectivity.test.js b/test/realtime/connectivity.test.js index 6ad70a75d..351d38f8e 100644 --- a/test/realtime/connectivity.test.js +++ b/test/realtime/connectivity.test.js @@ -21,9 +21,14 @@ define(['ably', 'shared_helper', 'chai'], function (Ably, Helper, chai) { */ it('http_connectivity_check', function (done) { const helper = this.helper; + helper.recordPrivateApi('call.http.checkConnectivity'); Helper.whenPromiseSettles(new Ably.Realtime._Http().checkConnectivity(), function (err, res) { try { - expect(res && !err, 'Connectivity check completed ' + (err && helper.Utils.inspectError(err))).to.be.ok; + expect( + res && !err, + 'Connectivity check completed ' + + (err && (helper.recordPrivateApi('call.Utils.inspectError'), helper.Utils.inspectError(err))), + ).to.be.ok; } catch (err) { done(err); return; @@ -32,7 +37,9 @@ define(['ably', 'shared_helper', 'chai'], function (Ably, Helper, chai) { }); }); - function options(connectivityCheckUrl, disableConnectivityCheck) { + function options(helper, connectivityCheckUrl, disableConnectivityCheck) { + helper.recordPrivateApi('pass.clientOption.connectivityCheckUrl'); + helper.recordPrivateApi('pass.clientOption.disableConnectivityCheck'); return { connectivityCheckUrl, disableConnectivityCheck, @@ -48,11 +55,16 @@ define(['ably', 'shared_helper', 'chai'], function (Ably, Helper, chai) { it('succeeds with scheme', function (done) { const helper = this.helper; + helper.recordPrivateApi('call.http.checkConnectivity'); Helper.whenPromiseSettles( - helper.AblyRealtime(options(urlScheme + successUrl)).http.checkConnectivity(), + helper.AblyRealtime(options(helper, urlScheme + successUrl)).http.checkConnectivity(), function (err, res) { try { - expect(res && !err, 'Connectivity check completed ' + (err && helper.Utils.inspectError(err))).to.be.ok; + expect( + res && !err, + 'Connectivity check completed ' + + (err && (helper.recordPrivateApi('call.Utils.inspectError'), helper.Utils.inspectError(err))), + ).to.be.ok; } catch (err) { done(err); return; @@ -64,8 +76,9 @@ define(['ably', 'shared_helper', 'chai'], function (Ably, Helper, chai) { it('fails with scheme', function (done) { const helper = this.helper; + helper.recordPrivateApi('call.http.checkConnectivity'); Helper.whenPromiseSettles( - helper.AblyRealtime(options(urlScheme + failUrl)).http.checkConnectivity(), + helper.AblyRealtime(options(helper, urlScheme + failUrl)).http.checkConnectivity(), function (err, res) { try { expect(!res, 'Connectivity check expected to return false').to.be.ok; @@ -79,11 +92,16 @@ define(['ably', 'shared_helper', 'chai'], function (Ably, Helper, chai) { it('succeeds with querystring', function (done) { const helper = this.helper; + helper.recordPrivateApi('call.http.checkConnectivity'); Helper.whenPromiseSettles( - helper.AblyRealtime(options(successUrl)).http.checkConnectivity(), + helper.AblyRealtime(options(helper, successUrl)).http.checkConnectivity(), function (err, res) { try { - expect(res && !err, 'Connectivity check completed ' + (err && helper.Utils.inspectError(err))).to.be.ok; + expect( + res && !err, + 'Connectivity check completed ' + + (err && (helper.recordPrivateApi('call.Utils.inspectError'), helper.Utils.inspectError(err))), + ).to.be.ok; done(); } catch (err) { done(err); @@ -94,23 +112,31 @@ define(['ably', 'shared_helper', 'chai'], function (Ably, Helper, chai) { it('fails with querystring', function (done) { const helper = this.helper; - Helper.whenPromiseSettles(helper.AblyRealtime(options(failUrl)).http.checkConnectivity(), function (err, res) { - try { - expect(!res, 'Connectivity check expected to return false').to.be.ok; - done(); - } catch (err) { - done(err); - } - }); + helper.recordPrivateApi('call.http.checkConnectivity'); + Helper.whenPromiseSettles( + helper.AblyRealtime(options(helper, failUrl)).http.checkConnectivity(), + function (err, res) { + try { + expect(!res, 'Connectivity check expected to return false').to.be.ok; + done(); + } catch (err) { + done(err); + } + }, + ); }); it('succeeds with plain url', function (done) { const helper = this.helper; Helper.whenPromiseSettles( - helper.AblyRealtime(options('sandbox-rest.ably.io/time')).http.checkConnectivity(), + helper.AblyRealtime(options(helper, 'sandbox-rest.ably.io/time')).http.checkConnectivity(), function (err, res) { try { - expect(res && !err, 'Connectivity check completed ' + (err && helper.Utils.inspectError(err))).to.be.ok; + expect( + res && !err, + 'Connectivity check completed ' + + (err && (helper.recordPrivateApi('call.Utils.inspectError'), helper.Utils.inspectError(err))), + ).to.be.ok; done(); } catch (err) { done(err); @@ -121,8 +147,9 @@ define(['ably', 'shared_helper', 'chai'], function (Ably, Helper, chai) { it('fails with plain url', function (done) { const helper = this.helper; + helper.recordPrivateApi('call.http.checkConnectivity'); Helper.whenPromiseSettles( - helper.AblyRealtime(options('echo.ably.io')).http.checkConnectivity(), + helper.AblyRealtime(options(helper, 'echo.ably.io')).http.checkConnectivity(), function (err, res) { try { expect(!res, 'Connectivity check expected to return false').to.be.ok; @@ -137,11 +164,16 @@ define(['ably', 'shared_helper', 'chai'], function (Ably, Helper, chai) { it('disable_connectivity_check', function (done) { const helper = this.helper; + helper.recordPrivateApi('call.http.checkConnectivity'); Helper.whenPromiseSettles( - helper.AblyRealtime(options('notarealhost', true)).http.checkConnectivity(), + helper.AblyRealtime(options(helper, 'notarealhost', true)).http.checkConnectivity(), function (err, res) { try { - expect(res && !err, 'Connectivity check completed ' + (err && helper.Utils.inspectError(err))).to.be.ok; + expect( + res && !err, + 'Connectivity check completed ' + + (err && (helper.recordPrivateApi('call.Utils.inspectError'), helper.Utils.inspectError(err))), + ).to.be.ok; done(); } catch (err) { done(err); diff --git a/test/realtime/crypto.test.js b/test/realtime/crypto.test.js index 7573cb859..532bc27be 100644 --- a/test/realtime/crypto.test.js +++ b/test/realtime/crypto.test.js @@ -37,6 +37,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async return; } var realtime = helper.AblyRealtime(); + helper.recordPrivateApi('call.BufferUtils.base64Decode'); var key = BufferUtils.base64Decode(testData.key); var iv = BufferUtils.base64Decode(testData.iv); var channel = realtime.channels.get(channelName, { cipher: { key: key, iv: iv } }); @@ -63,9 +64,11 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async if (testPlaintextVariants) { var testMessage = await createTestMessage(); + helper.recordPrivateApi('call.BufferUtils.isBuffer'); if (BufferUtils.isBuffer(testMessage.data) && !(testMessage.data instanceof ArrayBuffer)) { // Now, check that we can also handle an ArrayBuffer plaintext. var testMessageWithArrayBufferData = await createTestMessage(); + helper.recordPrivateApi('call.BufferUtils.toArrayBuffer'); testMessageWithArrayBufferData.data = BufferUtils.toArrayBuffer(testMessageWithArrayBufferData.data); runTest(testMessageWithArrayBufferData); } @@ -143,13 +146,16 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }); it('getDefaultParams_ArrayBuffer_key', function (done) { + const helper = this.helper; Helper.whenPromiseSettles(Crypto.generateRandomKey(), function (err, key) { if (err) { done(err); } + helper.recordPrivateApi('call.BufferUtils.toArrayBuffer'); var arrayBufferKey = Ably.Realtime.Platform.BufferUtils.toArrayBuffer(key); var params = Crypto.getDefaultParams({ key: arrayBufferKey }); try { + helper.recordPrivateApi('call.BufferUtils.areBuffersEqual'); expect(BufferUtils.areBuffersEqual(params.key, key)).to.equal(true); done(); } catch (err) { @@ -159,14 +165,17 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }); it('getDefaultParams_base64_key', function (done) { + const helper = this.helper; Helper.whenPromiseSettles(Crypto.generateRandomKey(), function (err, key) { if (err) { done(err); return; } + helper.recordPrivateApi('call.BufferUtils.base64Encode'); var b64key = Ably.Realtime.Platform.BufferUtils.base64Encode(key); var params = Crypto.getDefaultParams({ key: b64key }); try { + helper.recordPrivateApi('call.BufferUtils.areBuffersEqual'); expect(BufferUtils.areBuffersEqual(params.key, key)).to.equal(true); done(); } catch (err) { @@ -220,6 +229,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async true, function (channelOpts, testMessage, encryptedMessage) { /* encrypt plaintext message; encode() also to handle data that is not already string or buffer */ + helper.recordPrivateApi('call.Message.encode'); Helper.whenPromiseSettles(Message.encode(testMessage, channelOpts), function () { /* compare */ testMessageEquality(done, helper, testMessage, encryptedMessage); @@ -239,6 +249,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async true, function (channelOpts, testMessage, encryptedMessage) { /* encrypt plaintext message; encode() also to handle data that is not already string or buffer */ + helper.recordPrivateApi('call.Message.encode'); Helper.whenPromiseSettles(Message.encode(testMessage, channelOpts), function () { /* compare */ testMessageEquality(done, helper, testMessage, encryptedMessage); @@ -258,6 +269,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async false, async function (channelOpts, testMessage, encryptedMessage) { /* decrypt encrypted message; decode() also to handle data that is not string or buffer */ + helper.recordPrivateApi('call.Message.decode'); await Message.decode(encryptedMessage, channelOpts); /* compare */ testMessageEquality(done, helper, testMessage, encryptedMessage); @@ -276,6 +288,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async false, async function (channelOpts, testMessage, encryptedMessage) { /* decrypt encrypted message; decode() also to handle data that is not string or buffer */ + helper.recordPrivateApi('call.Message.decode'); await Message.decode(encryptedMessage, channelOpts); /* compare */ testMessageEquality(done, helper, testMessage, encryptedMessage); @@ -296,6 +309,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async done(err); return; } + helper.recordPrivateApi('call.BufferUtils.base64Decode'); var key = BufferUtils.base64Decode(testData.key); var iv = BufferUtils.base64Decode(testData.iv); @@ -321,9 +335,13 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async 2, false, function (channelOpts, testMessage, encryptedMessage, msgpackEncodedMessage) { + helper.recordPrivateApi('call.Message.encode'); Helper.whenPromiseSettles(Message.encode(testMessage, channelOpts), function () { + helper.recordPrivateApi('call.msgpack.encode'); var msgpackFromEncoded = msgpack.encode(testMessage); var msgpackFromEncrypted = msgpack.encode(encryptedMessage); + helper.recordPrivateApi('call.BufferUtils.base64Decode'); + helper.recordPrivateApi('call.msgpack.decode'); var messageFromMsgpack = Message.fromValues( msgpack.decode(BufferUtils.base64Decode(msgpackEncodedMessage)), ); @@ -331,6 +349,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async try { /* Mainly testing that we're correctly encoding the direct output from * the platform's ICipher implementation into the msgpack binary type */ + helper.recordPrivateApi('call.BufferUtils.areBuffersEqual'); expect(BufferUtils.areBuffersEqual(msgpackFromEncoded, msgpackFromEncrypted)).to.equal( true, 'verify msgpack encodings of newly-encrypted and preencrypted messages identical using areBuffersEqual', @@ -358,8 +377,11 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async false, function (channelOpts, testMessage, encryptedMessage, msgpackEncodedMessage) { Helper.whenPromiseSettles(Message.encode(testMessage, channelOpts), function () { + helper.recordPrivateApi('call.msgpack.encode'); var msgpackFromEncoded = msgpack.encode(testMessage); var msgpackFromEncrypted = msgpack.encode(encryptedMessage); + helper.recordPrivateApi('call.BufferUtils.base64Decode'); + helper.recordPrivateApi('call.msgpack.decode'); var messageFromMsgpack = Message.fromValues( msgpack.decode(BufferUtils.base64Decode(msgpackEncodedMessage)), ); @@ -367,6 +389,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async try { /* Mainly testing that we're correctly encoding the direct output from * the platform's ICipher implementation into the msgpack binary type */ + helper.recordPrivateApi('call.BufferUtils.areBuffersEqual'); expect(BufferUtils.areBuffersEqual(msgpackFromEncoded, msgpackFromEncrypted)).to.equal( true, 'verify msgpack encodings of newly-encrypted and preencrypted messages identical using areBuffersEqual', @@ -408,6 +431,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async return; } try { + helper.recordPrivateApi('read.channel.channelOptions.cipher'); expect(channel.channelOptions.cipher.algorithm).to.equal('aes'); expect(channel.channelOptions.cipher.keyLength).to.equal(keyLength); } catch (err) { @@ -456,6 +480,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async Helper.whenPromiseSettles(Crypto.generateRandomKey(128), function (err, key) { channel.setOptions({ cipher: { key: key } }); try { + helper.recordPrivateApi('read.channel.channelOptions.cipher'); expect(channel.channelOptions.cipher.algorithm).to.equal('aes'); expect(channel.channelOptions.cipher.keyLength).to.equal(128); } catch (err) { @@ -557,6 +582,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async return; } try { + helper.recordPrivateApi('read.channel.channelOptions.cipher'); expect(txChannel.channelOptions.cipher.algorithm).to.equal('aes'); expect(rxChannel.channelOptions.cipher.algorithm).to.equal('aes'); } catch (err) { diff --git a/test/realtime/delta.test.js b/test/realtime/delta.test.js index b1d000ca4..321ed6f02 100644 --- a/test/realtime/delta.test.js +++ b/test/realtime/delta.test.js @@ -155,6 +155,7 @@ define(['shared_helper', 'vcdiff-decoder', 'async', 'chai'], function (Helper, v if (index === 1) { /* Simulate issue */ + helper.recordPrivateApi('write.channel._lastPayload'); channel._lastPayload.messageId = null; channel.once('attaching', function (stateChange) { try { diff --git a/test/realtime/encoding.test.js b/test/realtime/encoding.test.js index 84f66e362..1b761bbf9 100644 --- a/test/realtime/encoding.test.js +++ b/test/realtime/encoding.test.js @@ -65,6 +65,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async channel.subscribe(name, function (msg) { try { if (encodingSpec.expectedHexValue) { + helper.recordPrivateApi('call.BufferUtils.hexEncode'); expect(BufferUtils.hexEncode(msg.data)).to.equal( encodingSpec.expectedHexValue, 'Check data matches', @@ -83,6 +84,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async binarychannel.subscribe(name, function (msg) { try { if (encodingSpec.expectedHexValue) { + helper.recordPrivateApi('call.BufferUtils.hexEncode'); expect(BufferUtils.hexEncode(msg.data)).to.equal( encodingSpec.expectedHexValue, 'Check data matches', @@ -98,6 +100,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }); }, function (parallelCb) { + helper.recordPrivateApi('read.Defaults.protocolVersion'); Helper.whenPromiseSettles( realtime.request( 'post', @@ -163,6 +166,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async var data, name = index.toString(); if (encodingSpec.expectedHexValue) { + helper.recordPrivateApi('call.BufferUtils.base64Decode'); data = BufferUtils.base64Decode(encodingSpec.data); } else { data = encodingSpec.expectedValue; @@ -181,6 +185,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async eachOfCb(err); return; } + helper.recordPrivateApi('read.Defaults.protocolVersion'); Helper.whenPromiseSettles( realtime.request('get', channelPath, Defaults.protocolVersion, null, null, null), function (err, resultPage) { diff --git a/test/realtime/event_emitter.test.js b/test/realtime/event_emitter.test.js index 568e1136f..7984dd2cb 100644 --- a/test/realtime/event_emitter.test.js +++ b/test/realtime/event_emitter.test.js @@ -84,6 +84,7 @@ define(['shared_helper', 'chai'], function (Helper, chai) { callbackCalled = true; }); + helper.recordPrivateApi('call.EventEmitter.emit'); eventEmitter.emit('custom'); try { expect(callbackCalled, 'Last callback should have been called').to.be.ok; @@ -108,6 +109,7 @@ define(['shared_helper', 'chai'], function (Helper, chai) { onCallbackCalled += 1; }); + helper.recordPrivateApi('call.EventEmitter.emit'); eventEmitter.emit('custom'); eventEmitter.emit('custom'); eventEmitter.emit('custom'); @@ -137,6 +139,7 @@ define(['shared_helper', 'chai'], function (Helper, chai) { eventEmitter.once('custom', callback); eventEmitter.once('custom', callback); + helper.recordPrivateApi('call.EventEmitter.emit'); eventEmitter.emit('custom'); eventEmitter.emit('custom'); @@ -165,11 +168,13 @@ define(['shared_helper', 'chai'], function (Helper, chai) { eventEmitter.on('custom', callback); eventEmitter.on('custom', callback); + helper.recordPrivateApi('call.EventEmitter.emit'); eventEmitter.emit('custom'); expect(callbackCalled).to.equal(3, 'The same callback should have been called for every registration'); callbackCalled = 0; eventEmitter.off(callback); + helper.recordPrivateApi('call.EventEmitter.emit'); eventEmitter.emit('custom'); expect(callbackCalled).to.equal(0, 'All callbacks should have been removed'); } catch (err) { @@ -195,11 +200,13 @@ define(['shared_helper', 'chai'], function (Helper, chai) { eventEmitter.on('custom', callback); eventEmitter.on('custom', callback); + helper.recordPrivateApi('call.EventEmitter.emit'); eventEmitter.emit('custom'); expect(callbackCalled).to.equal(3, 'The same callback should have been called for every registration'); callbackCalled = 0; eventEmitter.off(); + helper.recordPrivateApi('call.EventEmitter.emit'); eventEmitter.emit('custom'); expect(callbackCalled).to.equal(0, 'All callbacks should have been removed'); } catch (err) { @@ -225,11 +232,13 @@ define(['shared_helper', 'chai'], function (Helper, chai) { eventEmitter.on('custom', callback); eventEmitter.on('custom', callback); + helper.recordPrivateApi('call.EventEmitter.emit'); eventEmitter.emit('custom'); expect(callbackCalled).to.equal(3, 'The same callback should have been called for every registration'); callbackCalled = 0; eventEmitter.off('custom', callback); + helper.recordPrivateApi('call.EventEmitter.emit'); eventEmitter.emit('custom'); expect(callbackCalled).to.equal(0, 'All callbacks should have been removed'); } catch (err) { @@ -255,11 +264,13 @@ define(['shared_helper', 'chai'], function (Helper, chai) { eventEmitter.on('custom', callback); eventEmitter.on('custom', callback); + helper.recordPrivateApi('call.EventEmitter.emit'); eventEmitter.emit('custom'); expect(callbackCalled).to.equal(3, 'The same callback should have been called for every registration'); callbackCalled = 0; eventEmitter.off('custom'); + helper.recordPrivateApi('call.EventEmitter.emit'); eventEmitter.emit('custom'); expect(callbackCalled).to.equal(0, 'All callbacks should have been removed'); } catch (err) { @@ -287,16 +298,20 @@ define(['shared_helper', 'chai'], function (Helper, chai) { try { eventEmitter.once('custom', callback); eventEmitter.on('custom', callback); + helper.recordPrivateApi('read.EventEmitter.events'); expect('custom' in eventEmitter.events, 'custom event array exists').to.be.ok; eventEmitter.off('custom', callback); + helper.recordPrivateApi('read.EventEmitter.events'); expect(!('custom' in eventEmitter.events), 'custom event listener array is removed from object').to.be.ok; eventEmitter.once('custom', callback); eventEmitter.on('custom', callback); + helper.recordPrivateApi('read.EventEmitter.events'); expect('custom' in eventEmitter.events, 'custom event array exists').to.be.ok; eventEmitter.off(callback); + helper.recordPrivateApi('read.EventEmitter.events'); expect(!('custom' in eventEmitter.events), 'event listener array is removed from object').to.be.ok; } catch (err) { helper.closeAndFinish(done, realtime, err); @@ -317,6 +332,7 @@ define(['shared_helper', 'chai'], function (Helper, chai) { }; try { + helper.recordPrivateApi('call.EventEmitter.emit'); callbackCalled = 0; eventEmitter.on(['a', 'b', 'c'], callback); eventEmitter.emit('a'); @@ -360,6 +376,7 @@ define(['shared_helper', 'chai'], function (Helper, chai) { try { callbackCalled = 0; eventEmitter.once(['a', 'b', 'c'], callback); + helper.recordPrivateApi('call.EventEmitter.emit'); eventEmitter.emit('a', 'expected'); eventEmitter.emit('b', 'wrong'); eventEmitter.emit('c', 'wrong'); @@ -387,6 +404,7 @@ define(['shared_helper', 'chai'], function (Helper, chai) { secondCbCalled = true; }); }); + helper.recordPrivateApi('call.EventEmitter.emit'); eventEmitter.emit('a'); try { @@ -431,6 +449,7 @@ define(['shared_helper', 'chai'], function (Helper, chai) { eventEmitter.off(); }); + helper.recordPrivateApi('call.EventEmitter.emit'); eventEmitter.emit('a'); try { @@ -483,6 +502,7 @@ define(['shared_helper', 'chai'], function (Helper, chai) { eventEmitter = realtime.connection; const p = eventEmitter.once(); + helper.recordPrivateApi('call.EventEmitter.emit'); eventEmitter.emit('b'); p.then(function () { helper.closeAndFinish(done, realtime); @@ -497,6 +517,7 @@ define(['shared_helper', 'chai'], function (Helper, chai) { eventEmitter = realtime.connection; const p = eventEmitter.once(['a', 'b', 'c']); + helper.recordPrivateApi('call.EventEmitter.emit'); eventEmitter.emit('b'); p.then(function () { helper.closeAndFinish(done, realtime); diff --git a/test/realtime/failure.test.js b/test/realtime/failure.test.js index 28e4f0495..58d39d535 100644 --- a/test/realtime/failure.test.js +++ b/test/realtime/failure.test.js @@ -116,6 +116,8 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async var lifecycleTest = function (transports) { return function (cb) { var connectionEvents = []; + + helper.recordPrivateApi('pass.clientOption.webSocketConnectTimeout'); var realtime = helper.AblyRealtime({ transports: transports, realtimeHost: 'invalid', @@ -346,10 +348,12 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async channel = realtime.channels.get('failed_attach'), originalProcessMessage = channel.processMessage.bind(channel); + helper.recordPrivateApi('replace.channel.processMessage'); channel.processMessage = async function (message) { if (message.action === 11) { return; } + helper.recordPrivateApi('call.channel.processMessage'); await originalProcessMessage(message); }; @@ -389,17 +393,20 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async var performance = isBrowser ? window.performance : require('perf_hooks').performance; + helper.recordPrivateApi('replace.channel.processMessage'); channel.processMessage = async function (message) { // Ignore ATTACHED messages if (message.action === 11) { return; } + helper.recordPrivateApi('call.channel.processMessage'); await originalProcessMessage(message); }; var retryTimeouts = []; realtime.connection.on('connected', function () { + helper.recordPrivateApi('write.realtime.options.timeouts.realtimeRequestTimeout'); realtime.options.timeouts.realtimeRequestTimeout = 1; Helper.whenPromiseSettles(channel.attach(), function (err) { if (err) { @@ -461,12 +468,15 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async Helper.whenPromiseSettles(channel.attach(), cb); }, function (cb) { + helper.recordPrivateApi('read.realtime.connection.connectionManager.activeProtocol.transport'); var transport = realtime.connection.connectionManager.activeProtocol.transport, originalOnProtocolMessage = transport.onProtocolMessage; + helper.recordPrivateApi('replace.transport.onProtocolMessage'); transport.onProtocolMessage = function (message) { /* make sure we don't get an ack! */ if (message.action !== 1) { + helper.recordPrivateApi('call.transport.onProtocolMessage'); originalOnProtocolMessage.apply(this, arguments); } }; @@ -483,6 +493,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async cb(err); } }); + helper.recordPrivateApi('call.Platform.nextTick'); Ably.Realtime.Platform.Config.nextTick(function () { failureFn(realtime, helper); }); @@ -509,7 +520,9 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async it( 'nack_on_connection_failed', nack_on_connection_failure( - function (realtime) { + function (realtime, helper) { + helper.recordPrivateApi('read.realtime.connection.connectionManager.activeProtocol.transport'); + helper.recordPrivateApi('call.transport.onProtocolMessage'); realtime.connection.connectionManager.activeProtocol.transport.onProtocolMessage({ action: 9, error: { statusCode: 401, code: 40100, message: 'connection failed because reasons' }, @@ -536,12 +549,15 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async realtime = helper.AblyRealtime({ realtimeRequestTimeout: 2000 }), originalOnProtocolMessage; + helper.recordPrivateApi('listen.connectionManager.transport.pending'); realtime.connection.connectionManager.on('transport.pending', function (transport) { originalOnProtocolMessage = transport.onProtocolMessage; + helper.recordPrivateApi('replace.transport.onProtocolMessage'); transport.onProtocolMessage = function (message) { if (message.action === 4) { message.connectionDetails.maxIdleInterval = 100; } + helper.recordPrivateApi('call.transport.onProtocolMessage'); originalOnProtocolMessage.call(this, message); }; }); @@ -569,10 +585,11 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async * we try again we use a fallback host */ Helper.testOnAllTransports(this, 'try_fallback_hosts_on_placement_constraint', function (realtimeOpts) { return function (done) { + const helper = this.helper; /* Use the echoserver as a fallback host because it doesn't support * websockets, so it'll fail to connect, which we can detect */ - var helper = this.helper, - realtime = helper.AblyRealtime(helper.Utils.mixin({ fallbackHosts: ['echo.ably.io'] }, realtimeOpts)), + helper.recordPrivateApi('call.Utils.mixin'); + var realtime = helper.AblyRealtime(helper.Utils.mixin({ fallbackHosts: ['echo.ably.io'] }, realtimeOpts)), connection = realtime.connection, connectionManager = connection.connectionManager; @@ -591,6 +608,9 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async helper.closeAndFinish(done, realtime); }); }); + helper.recordPrivateApi('call.protocolMessageFromDeserialized'); + helper.recordPrivateApi('call.connectionManager.activeProtocol.getTransport'); + helper.recordPrivateApi('call.transport.onProtocolMessage'); connectionManager.activeProtocol.getTransport().onProtocolMessage( createPM({ action: 6, @@ -628,10 +648,13 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async var connectionManager = sender_realtime.connection.connectionManager; var onChannelMsgOrig = connectionManager.onChannelMessage; + helper.recordPrivateApi('replace.connectionManager.onChannelMessage'); connectionManager.onChannelMessage = function (msg, transport) { if (msg.action === 15) { + helper.recordPrivateApi('call.channel.requestState'); sender_channel.requestState('attaching'); } + helper.recordPrivateApi('call.connectionManager.onChannelMessage'); onChannelMsgOrig.call(connectionManager, msg, transport); }; diff --git a/test/realtime/init.test.js b/test/realtime/init.test.js index b655a88ab..b310d36f0 100644 --- a/test/realtime/init.test.js +++ b/test/realtime/init.test.js @@ -30,8 +30,17 @@ define(['ably', 'shared_helper', 'chai'], function (Ably, Helper, chai) { realtime = helper.AblyRealtime({ transports: ['web_socket', 'xhr_polling'] }); realtime.connection.on('connected', function () { /* check api version */ + helper.recordPrivateApi('read.realtime.connection.connectionManager.activeProtocol.transport'); var transport = realtime.connection.connectionManager.activeProtocol.transport; - var connectUri = helper.isWebsocket(transport) ? transport.uri : transport.recvRequest.recvUri; + var connectUri = helper.isWebsocket(transport) + ? (() => { + helper.recordPrivateApi('read.transport.uri'); + return transport.uri; + })() + : (() => { + helper.recordPrivateApi('read.transport.recvRequest.recvUri'); + return transport.recvRequest.recvUri; + })(); try { expect(connectUri.indexOf('v=3') > -1, 'Check uri includes v=3').to.be.ok; } catch (err) { @@ -57,7 +66,10 @@ define(['ably', 'shared_helper', 'chai'], function (Ably, Helper, chai) { realtime = new helper.Ably.Realtime(keyStr); try { + helper.recordPrivateApi('read.realtime.options.key'); expect(realtime.options.key).to.equal(keyStr); + helper.recordPrivateApi('read.realtime.options'); + helper.recordPrivateApi('read.connectionManager.options'); expect(realtime.options).to.deep.equal(realtime.connection.connectionManager.options); } catch (err) { helper.closeAndFinish(done, realtime, err); @@ -87,7 +99,10 @@ define(['ably', 'shared_helper', 'chai'], function (Ably, Helper, chai) { realtime = new helper.Ably.Realtime(tokenStr); try { + helper.recordPrivateApi('read.realtime.options.token'); expect(realtime.options.token).to.equal(tokenStr); + helper.recordPrivateApi('read.realtime.options'); + helper.recordPrivateApi('read.connectionManager.options'); expect(realtime.options).to.deep.equal(realtime.connection.connectionManager.options); helper.closeAndFinish(done, realtime); } catch (err) { @@ -106,7 +121,9 @@ define(['ably', 'shared_helper', 'chai'], function (Ably, Helper, chai) { try { var keyStr = helper.getTestApp().keys[0].keyStr; realtime = helper.AblyRealtime({ key: keyStr, useTokenAuth: true }); + helper.recordPrivateApi('read.realtime.options.key'); expect(realtime.options.key).to.equal(keyStr); + helper.recordPrivateApi('read.auth.method'); expect(realtime.auth.method).to.equal('token'); expect(realtime.auth.clientId).to.equal(undefined); /* Check that useTokenAuth by default results in an anonymous (and not wildcard) token */ @@ -230,6 +247,7 @@ define(['ably', 'shared_helper', 'chai'], function (Ably, Helper, chai) { * host set, so not using helpers.realtime this time, which will use a * test env */ var realtime = new Ably.Realtime({ key: 'not_a.real:key', autoConnect: false }); + helper.recordPrivateApi('read.connectionManager.httpHosts'); var defaultHost = realtime.connection.connectionManager.httpHosts[0]; expect(defaultHost).to.equal('rest.ably.io', 'Verify correct default rest host chosen'); realtime.close(); @@ -252,18 +270,22 @@ define(['ably', 'shared_helper', 'chai'], function (Ably, Helper, chai) { }); /* Note: uses internal knowledge of connectionManager */ try { + helper.recordPrivateApi('read.connectionManager.states.disconnected.retryDelay'); expect(realtime.connection.connectionManager.states.disconnected.retryDelay).to.equal( 123, 'Verify disconnected retry frequency is settable', ); + helper.recordPrivateApi('read.connectionManager.states.suspended.retryDelay'); expect(realtime.connection.connectionManager.states.suspended.retryDelay).to.equal( 456, 'Verify suspended retry frequency is settable', ); + helper.recordPrivateApi('read.connectionManager.options.timeouts.httpRequestTimeout'); expect(realtime.connection.connectionManager.options.timeouts.httpRequestTimeout).to.equal( 789, 'Verify http request timeout is settable', ); + helper.recordPrivateApi('read.connectionManager.options.timeouts.httpMaxRetryDuration'); expect(realtime.connection.connectionManager.options.timeouts.httpMaxRetryDuration).to.equal( 321, 'Verify http max retry duration is settable', @@ -290,6 +312,7 @@ define(['ably', 'shared_helper', 'chai'], function (Ably, Helper, chai) { fallbackHosts: ['b', 'c', 'd', 'e'], }); /* Note: uses internal knowledge of connectionManager */ + helper.recordPrivateApi('read.connectionManager.httpHosts'); expect(realtime.connection.connectionManager.httpHosts.length).to.equal( 3, 'Verify hosts list is the expected length', @@ -297,6 +320,7 @@ define(['ably', 'shared_helper', 'chai'], function (Ably, Helper, chai) { expect(realtime.connection.connectionManager.httpHosts[0]).to.equal('a', 'Verify given restHost is first'); /* Replace chooseTransportForHost with a spy, then try calling * chooseHttpTransport to see what host is picked */ + helper.recordPrivateApi('replace.connectionManager.tryATransport'); realtime.connection.connectionManager.tryATransport = function (transportParams, transport, cb) { switch (transportParams.host) { case 'a': @@ -332,7 +356,9 @@ define(['ably', 'shared_helper', 'chai'], function (Ably, Helper, chai) { var realtime; try { realtime = helper.AblyRealtime({ transports: helper.availableTransports }); + helper.recordPrivateApi('read.connectionManager.baseTransport'); expect(realtime.connection.connectionManager.baseTransport).to.equal('comet'); + helper.recordPrivateApi('read.connectionManager.webSocketTransportAvailable'); expect(realtime.connection.connectionManager.webSocketTransportAvailable).to.be.ok; helper.closeAndFinish(done, realtime); } catch (err) { @@ -348,9 +374,12 @@ define(['ably', 'shared_helper', 'chai'], function (Ably, Helper, chai) { try { var keyStr = helper.getTestApp().keys[0].keyStr; var realtime = helper.AblyRealtime({ key: keyStr, useTokenAuth: true }); + helper.recordPrivateApi('listen.connectionManager.transport.pending'); realtime.connection.connectionManager.once('transport.pending', function (state) { + helper.recordPrivateApi('read.connectionManager.pendingTransport'); var transport = realtime.connection.connectionManager.pendingTransport, originalOnProtocolMessage = transport.onProtocolMessage; + helper.recordPrivateApi('replace.transport.onProtocolMessage'); realtime.connection.connectionManager.pendingTransport.onProtocolMessage = function (message) { try { if (message.action === 4) { @@ -358,6 +387,7 @@ define(['ably', 'shared_helper', 'chai'], function (Ably, Helper, chai) { message.connectionDetails.connectionKey = 'importantConnectionKey'; message.connectionDetails.clientId = 'customClientId'; } + helper.recordPrivateApi('call.transport.onProtocolMessage'); originalOnProtocolMessage.call(transport, message); } catch (err) { helper.closeAndFinish(done, realtime, err); @@ -394,6 +424,7 @@ define(['ably', 'shared_helper', 'chai'], function (Ably, Helper, chai) { }); realtime.connection.once('connected', function () { try { + helper.recordPrivateApi('call.http._getHosts'); var hosts = new Ably.Rest._Http()._getHosts(realtime); /* restHost rather than realtimeHost as that's what connectionManager * knows about; converted to realtimeHost by the websocketTransport */ @@ -416,6 +447,7 @@ define(['ably', 'shared_helper', 'chai'], function (Ably, Helper, chai) { fallbackHosts: [goodHost, 'b', 'c'], }); realtime.connection.once('connected', function () { + helper.recordPrivateApi('call.http._getHosts'); var hosts = new Ably.Realtime._Http()._getHosts(realtime); /* restHost rather than realtimeHost as that's what connectionManager * knows about; converted to realtimeHost by the websocketTransport */ diff --git a/test/realtime/message.test.js b/test/realtime/message.test.js index 7cee97f47..ab2cd80df 100644 --- a/test/realtime/message.test.js +++ b/test/realtime/message.test.js @@ -143,6 +143,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async txRealtime, rxRealtime; try { + helper.recordPrivateApi('call.Utils.mixin'); txRealtime = helper.AblyRealtime(helper.Utils.mixin(realtimeOpts, { autoConnect: false })); rxRealtime = helper.AblyRealtime(); var txChannel = txRealtime.channels.get('publishQueued_' + String(Math.random()).substr(2)); @@ -634,9 +635,11 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async realtime = helper.AblyRealtime({ clientId: clientId }); realtime.connection.once('connected', function () { + helper.recordPrivateApi('read.realtime.connection.connectionManager.activeProtocol.transport'); var transport = realtime.connection.connectionManager.activeProtocol.transport, originalSend = transport.send; + helper.recordPrivateApi('replace.transport.send'); transport.send = function (message) { try { if (message.action === 15) { @@ -644,6 +647,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async expect(!message.messages[0].clientId, 'client ID is not added by the client library as it is implicit').to .be.ok; } + helper.recordPrivateApi('call.transport.send'); originalSend.apply(transport, arguments); } catch (err) { helper.closeAndFinish(done, realtime, err); @@ -674,15 +678,18 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async realtime = helper.AblyRealtime({ clientId: clientId, transports: [helper.bestTransport] }); realtime.connection.once('connected', function () { + helper.recordPrivateApi('read.realtime.connection.connectionManager.activeProtocol.transport'); var transport = realtime.connection.connectionManager.activeProtocol.transport, originalSend = transport.send; + helper.recordPrivateApi('replace.transport.send'); transport.send = function (message) { try { if (message.action === 15) { expect(message.messages[0].name === 'event0', 'Outgoing message interecepted').to.be.ok; expect(message.messages[0].clientId === clientId, 'client ID is present when published to Ably').to.be.ok; } + helper.recordPrivateApi('call.transport.send'); originalSend.apply(transport, arguments); } catch (err) { helper.closeAndFinish(done, realtime, err); @@ -764,9 +771,11 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }, 500); // ensure that the message is not published }); + helper.recordPrivateApi('listen.connectionManager.transport.pending'); realtime.connection.connectionManager.on('transport.pending', function (transport) { var originalSend = transport.send; + helper.recordPrivateApi('replace.transport.send'); transport.send = function (message) { try { if (message.action === 15) { @@ -774,6 +783,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async expect(message.messages[0].clientId === invalidClientId, 'client ID is present when published to Ably') .to.be.ok; } + helper.recordPrivateApi('call.transport.send'); originalSend.apply(transport, arguments); } catch (err) { helper.closeAndFinish(done, realtime, err); @@ -820,6 +830,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async ++received; if (received === 2) { /* wait a tick to make sure no more messages come in */ + helper.recordPrivateApi('call.Platform.nextTick'); config.nextTick(function () { innercb(); }); @@ -901,6 +912,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async return cb(e); } // Wait for any errant messages to arrive before continuing + helper.recordPrivateApi('call.Platform.nextTick'); config.nextTick(cb); }, ); @@ -954,12 +966,14 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async return expect.fail('Listener should not fire'); }; channel.subscribe({ refType: 'com.ably.test', refTimeserial: '0123456789' }, listener); + helper.recordPrivateApi('call.filteredSubscriptions.has'); expect(channel.filteredSubscriptions.has(listener), 'Listener should initially be present').to.be.true; channel.unsubscribe(listener); expect( channel.filteredSubscriptions.has(listener), 'Listener should no longer be present after unsubscribing', ).to.be.false; + helper.recordPrivateApi('call.Platform.nextTick'); config.nextTick(cb); } catch (e) { cb(e); @@ -1038,6 +1052,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async channel = realtime.channels.get('maxMessageSize'); realtime.connection.once('connected', function () { + helper.recordPrivateApi('listen.connectionManager.connectiondetails'); connectionManager.once('connectiondetails', function (details) { Helper.whenPromiseSettles( channel.publish('foo', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'), @@ -1054,7 +1069,11 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async ); }); var connectionDetails = connectionManager.connectionDetails; + helper.recordPrivateApi('write.connectionManager.connectionDetails.maxMessageSize'); connectionDetails.maxMessageSize = 64; + helper.recordPrivateApi('call.realtime.connection.connectionManager.activeProtocol.getTransport'); + helper.recordPrivateApi('call.protocolMessageFromDeserialized'); + helper.recordPrivateApi('call.transport.onProtocolMessage'); connectionManager.activeProtocol.getTransport().onProtocolMessage( createPM({ action: 4, @@ -1099,6 +1118,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async channelOne.publish({ name: 'm', id: 'bundle_m', data: { expectedBundle: 9 } }); channelOne.publish('z_last', { expectedBundle: 10 }); + helper.recordPrivateApi('call.transport.onProtocolMessage'); var queue = realtime.connection.connectionManager.queuedMessages; var messages; try { diff --git a/test/realtime/presence.test.js b/test/realtime/presence.test.js index 21a568539..770092f78 100644 --- a/test/realtime/presence.test.js +++ b/test/realtime/presence.test.js @@ -416,6 +416,8 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async } cb(); }); + + helper.recordPrivateApi('call.PresenceMessage.fromValues'); presence.enter( PresenceMessage.fromValues({ extras: { headers: { key: 'value' } }, @@ -436,6 +438,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async } cb(); }); + helper.recordPrivateApi('call.PresenceMessage.fromValues'); presence.leave( PresenceMessage.fromValues({ extras: { headers: { otherKey: 'otherValue' } }, @@ -1191,6 +1194,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async var channel = client.channels.get('presenceClientIdIsImplicit'), presence = channel.presence; + helper.recordPrivateApi('replace.channel.sendPresence'); var originalSendPresence = channel.sendPresence; channel.sendPresence = function (presence, callback) { try { @@ -1199,6 +1203,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async helper.closeAndFinish(done, client, err); return; } + helper.recordPrivateApi('call.channel.sendPresence'); originalSendPresence.apply(channel, arguments); }; @@ -1237,13 +1242,16 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async transports: [helper.bestTransport], }; + helper.recordPrivateApi('call.Utils.mixin'); var realtimeBin = helper.AblyRealtime(helper.Utils.mixin(options, { useBinaryProtocol: true })); var realtimeJson = helper.AblyRealtime(helper.Utils.mixin(options, { useBinaryProtocol: false })); var runTest = function (realtime, callback) { + helper.recordPrivateApi('listen.connectionManager.transport.active'); realtime.connection.connectionManager.once('transport.active', function (transport) { var originalSend = transport.send; + helper.recordPrivateApi('replace.transport.send'); transport.send = function (message) { if (message.action === 14) { /* Message is formatted for Ably by the toJSON method, so need to @@ -1257,9 +1265,11 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async callback(err); return; } + helper.recordPrivateApi('replace.transport.send'); transport.send = originalSend; callback(); } + helper.recordPrivateApi('call.transport.send'); originalSend.apply(transport, arguments); }; @@ -1558,6 +1568,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }, function (cb) { if (!channel.presence.syncComplete) { + helper.recordPrivateApi('call.presence.waitSync'); channel.presence.members.waitSync(cb); } else { cb(); @@ -1572,7 +1583,9 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }, function (cb) { /* inject an additional member into the myMember set, then force a suspended state */ + helper.recordPrivateApi('read.connectionManager.connectionId'); var connId = realtime.connection.connectionManager.connectionId; + helper.recordPrivateApi('call.presence._myMembers.put'); channel.presence._myMembers.put({ action: 'enter', clientId: 'two', @@ -1600,8 +1613,10 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async * that realtime will feel it necessary to do a sync - if it doesn't, * we request one */ if (channel.presence.syncComplete) { + helper.recordPrivateApi('call.channel.sync'); channel.sync(); } + helper.recordPrivateApi('call.presence.waitSync'); channel.presence.members.waitSync(cb); }, function (cb) { @@ -1680,6 +1695,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }, function (cb) { if (!channel.presence.syncComplete) { + helper.recordPrivateApi('call.presence.waitSync'); channel.presence.members.waitSync(cb); } else { cb(); @@ -1698,7 +1714,9 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }, function (cb) { /* inject an additional member into the myMember set, then force a suspended state */ + helper.recordPrivateApi('read.connectionManager.connectionId'); var connId = realtime.connection.connectionManager.connectionId; + helper.recordPrivateApi('call.presence._myMembers.put'); channel.presence._myMembers.put({ action: 'enter', clientId: 'me', @@ -1761,6 +1779,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }, function (cb) { /* stub out attachimpl */ + helper.recordPrivateApi('replace.channel.attachImpl'); channel.attachImpl = function () {}; channel.attach(); @@ -1768,13 +1787,17 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async channel.presence.enterClient('client_' + i.toString(), i.toString()); } + helper.recordPrivateApi('replace.channel.attachImpl'); channel.attachImpl = originalAttachImpl; + + helper.recordPrivateApi('call.channel.checkPendingState'); channel.checkPendingState(); /* Now just wait for an enter. One enter implies all, they'll all be * sent in one protocol message */ channel.presence.subscribe('enter', function () { channel.presence.unsubscribe('enter'); + helper.recordPrivateApi('call.Platform.nextTick'); Ably.Realtime.Platform.Config.nextTick(cb); }); }, @@ -1845,6 +1868,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }, function (cb) { /* Inject an additional member locally */ + helper.recordPrivateApi('call.channel.processMessage'); channel .processMessage({ action: 14, @@ -1888,6 +1912,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async } cb(); }); + helper.recordPrivateApi('call.channel.sync'); channel.sync(); }, function (cb) { @@ -1978,6 +2003,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async cb(); }); /* Inject an ATTACHED with RESUMED and HAS_PRESENCE both false */ + helper.recordPrivateApi('call.protocolMessageFromDeserialized'); channel.processMessage( createPM({ action: 11, diff --git a/test/realtime/resume.test.js b/test/realtime/resume.test.js index 3593a2d49..c8a6d0950 100644 --- a/test/realtime/resume.test.js +++ b/test/realtime/resume.test.js @@ -75,8 +75,10 @@ define(['shared_helper', 'async', 'chai'], function (Helper, async, chai) { /* re-open the connection, verify resume mode */ rxRealtime.connection.connect(); var connectionManager = rxRealtime.connection.connectionManager; + helper.recordPrivateApi('listen.connectionManager.transport.active'); connectionManager.once('transport.active', function (transport) { try { + helper.recordPrivateApi('read.transport.params.mode'); expect(transport.params.mode).to.equal('resume', 'Verify reconnect is resume mode'); } catch (err) { callback(err); @@ -208,8 +210,10 @@ define(['shared_helper', 'async', 'chai'], function (Helper, async, chai) { rxCount = 0; rxRealtime.connection.connect(); var connectionManager = rxRealtime.connection.connectionManager; + helper.recordPrivateApi('listen.connectionManager.transport.active'); connectionManager.on('transport.active', function (transport) { try { + helper.recordPrivateApi('read.transport.params.mode'); expect(transport.params.mode).to.equal('resume', 'Verify reconnect is resume mode'); } catch (err) { callback(err); @@ -284,17 +288,23 @@ define(['shared_helper', 'async', 'chai'], function (Helper, async, chai) { }); }, function (cb) { + helper.recordPrivateApi('write.channel.state'); suspendedChannel.state = 'suspended'; Helper.whenPromiseSettles(attachedChannel.attach(), cb); }, function (cb) { /* Sabotage the resume */ - (connection.connectionManager.connectionKey = '_____!ablyjs_test_fake-key____'), + helper.recordPrivateApi('write.connectionManager.connectionKey'); + helper.recordPrivateApi('write.connectionManager.connectionId'); + helper.recordPrivateApi('write.connectionManager.msgSerial')( + (connection.connectionManager.connectionKey = '_____!ablyjs_test_fake-key____'), + ), (connection.connectionManager.connectionId = 'ablyjs_tes'); connection.connectionManager.msgSerial = 15; connection.once('disconnected', function () { cb(); }); + helper.recordPrivateApi('call.connectionManager.disconnectAllTransports'); connection.connectionManager.disconnectAllTransports(); }, function (cb) { @@ -306,7 +316,9 @@ define(['shared_helper', 'async', 'chai'], function (Helper, async, chai) { ); expect(attachedChannel.state).to.equal('attaching', 'Attached channel went into attaching'); expect(suspendedChannel.state).to.equal('attaching', 'Suspended channel went into attaching'); + helper.recordPrivateApi('read.connectionManager.msgSerial'); expect(connection.connectionManager.msgSerial).to.equal(0, 'Check msgSerial is reset to 0'); + helper.recordPrivateApi('read.connectionManager.connectionId'); expect( connection.connectionManager.connectionId !== 'ablyjs_tes', 'Check connectionId is set by the new CONNECTED', @@ -356,6 +368,7 @@ define(['shared_helper', 'async', 'chai'], function (Helper, async, chai) { }, function (cb) { /* Sabotage the resume - use a valid but now-expired token */ + helper.recordPrivateApi('write.auth.tokenDetails.token'); realtime.auth.tokenDetails.token = badtoken.token; connection.once(function (stateChange) { try { @@ -366,6 +379,7 @@ define(['shared_helper', 'async', 'chai'], function (Helper, async, chai) { } cb(); }); + helper.recordPrivateApi('call.connectionManager.disconnectAllTransports'); connection.connectionManager.disconnectAllTransports(); }, function (cb) { @@ -403,7 +417,9 @@ define(['shared_helper', 'async', 'chai'], function (Helper, async, chai) { }); }, function (cb) { + helper.recordPrivateApi('read.auth.key'); var keyName = realtime.auth.key.split(':')[0]; + helper.recordPrivateApi('write.auth.key'); realtime.auth.key = keyName + ':wrong'; connection.once(function (stateChange) { try { @@ -414,6 +430,8 @@ define(['shared_helper', 'async', 'chai'], function (Helper, async, chai) { } cb(); }); + helper.recordPrivateApi('call.connectionManager.disconnectAllTransports'); + connection.connectionManager.disconnectAllTransports(); }, function (cb) { @@ -523,6 +541,7 @@ define(['shared_helper', 'async', 'chai'], function (Helper, async, chai) { helper.becomeSuspended(realtime, cb); }, function (cb) { + helper.recordPrivateApi('replace.connectionManager.tryATransport'); realtime.connection.connectionManager.tryATransport = function (transportParams) { try { expect(transportParams.mode).to.equal('clean', 'Check library didn’t try to resume'); @@ -552,10 +571,14 @@ define(['shared_helper', 'async', 'chai'], function (Helper, async, chai) { connectionManager = connection.connectionManager; connection.once('connected', function () { + helper.recordPrivateApi('write.connectionManager.lastActivity'); connectionManager.lastActivity = Date.now() - 10000000; /* noop-out onProtocolMessage so that a DISCONNECTED message doesn't * reset the last activity timer */ + helper.recordPrivateApi('call.realtime.connection.connectionManager.activeProtocol.getTransport'); + helper.recordPrivateApi('replace.transport.onProtocolMessage'); connectionManager.activeProtocol.getTransport().onProtocolMessage = function () {}; + helper.recordPrivateApi('replace.connectionManager.tryATransport'); connectionManager.tryATransport = function (transportParams) { try { expect(transportParams.mode).to.equal('clean', 'Check library didn’t try to resume'); @@ -565,6 +588,7 @@ define(['shared_helper', 'async', 'chai'], function (Helper, async, chai) { } helper.closeAndFinish(done, realtime); }; + helper.recordPrivateApi('call.connectionManager.disconnectAllTransports'); connectionManager.disconnectAllTransports(); }); }); @@ -595,9 +619,12 @@ define(['shared_helper', 'async', 'chai'], function (Helper, async, chai) { var resumed_receiver_realtime = helper.AblyRealtime(); var connectionManager = resumed_receiver_realtime.connection.connectionManager; + helper.recordPrivateApi('replace.connectionManager.send'); var sendOrig = connectionManager.send; connectionManager.send = function (msg, queueEvent, callback) { + helper.recordPrivateApi('call.ProtocolMessage.setFlag'); msg.setFlag('ATTACH_RESUME'); + helper.recordPrivateApi('call.connectionManager.send'); sendOrig.call(connectionManager, msg, queueEvent, callback); }; diff --git a/test/realtime/sync.test.js b/test/realtime/sync.test.js index 416d28a07..b699de48c 100644 --- a/test/realtime/sync.test.js +++ b/test/realtime/sync.test.js @@ -45,6 +45,8 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async channelName = 'syncexistingset', channel = realtime.channels.get(channelName); + helper.recordPrivateApi('call.protocolMessageFromDeserialized'); + helper.recordPrivateApi('call.channel.processMessage'); await channel.processMessage( createPM({ action: 11, @@ -61,6 +63,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async async.series( [ function (cb) { + helper.recordPrivateApi('call.channel.processMessage'); channel .processMessage({ action: 16, @@ -104,6 +107,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }, function (cb) { /* Trigger another sync. Two has gone without so much as a `leave` message! */ + helper.recordPrivateApi('call.channel.processMessage'); channel .processMessage({ action: 16, @@ -166,6 +170,8 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async channelName = 'sync_member_arrives_in_middle', channel = realtime.channels.get(channelName); + helper.recordPrivateApi('call.protocolMessageFromDeserialized'); + helper.recordPrivateApi('call.channel.processMessage'); await channel.processMessage( createPM({ action: 11, @@ -175,6 +181,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async ); /* First sync */ + helper.recordPrivateApi('call.channel.processMessage'); await channel.processMessage({ action: 16, channel: channelName, @@ -190,6 +197,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }); /* A second sync, this time in multiple parts, with a presence message in the middle */ + helper.recordPrivateApi('call.channel.processMessage'); await channel.processMessage({ action: 16, channel: channelName, @@ -205,6 +213,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async ], }); + helper.recordPrivateApi('call.channel.processMessage'); await channel.processMessage({ action: 14, channel: channelName, @@ -219,6 +228,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async ], }); + helper.recordPrivateApi('call.channel.processMessage'); await channel.processMessage({ action: 16, channel: channelName, @@ -269,6 +279,8 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async channelName = 'sync_member_arrives_normally_after_came_in_sync', channel = realtime.channels.get(channelName); + helper.recordPrivateApi('call.protocolMessageFromDeserialized'); + helper.recordPrivateApi('call.channel.processMessage'); await channel.processMessage( createPM({ action: 11, @@ -277,6 +289,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }), ); + helper.recordPrivateApi('call.channel.processMessage'); await channel.processMessage({ action: 16, channel: channelName, @@ -292,6 +305,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async ], }); + helper.recordPrivateApi('call.channel.processMessage'); await channel.processMessage({ action: 14, channel: channelName, @@ -306,6 +320,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async ], }); + helper.recordPrivateApi('call.channel.processMessage'); await channel.processMessage({ action: 16, channel: channelName, @@ -353,6 +368,8 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async channelName = 'sync_member_arrives_normally_before_comes_in_sync', channel = realtime.channels.get(channelName); + helper.recordPrivateApi('call.protocolMessageFromDeserialized'); + helper.recordPrivateApi('call.channel.processMessage'); await channel.processMessage( createPM({ action: 11, @@ -361,6 +378,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }), ); + helper.recordPrivateApi('call.channel.processMessage'); await channel.processMessage({ action: 16, channel: channelName, @@ -376,6 +394,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async ], }); + helper.recordPrivateApi('call.channel.processMessage'); await channel.processMessage({ action: 14, channel: channelName, @@ -390,6 +409,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async ], }); + helper.recordPrivateApi('call.channel.processMessage'); await channel.processMessage({ action: 16, channel: channelName, @@ -438,6 +458,8 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async channelName = 'sync_ordering', channel = realtime.channels.get(channelName); + helper.recordPrivateApi('call.protocolMessageFromDeserialized'); + helper.recordPrivateApi('call.channel.processMessage'); await channel.processMessage( createPM({ action: 11, @@ -446,6 +468,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async ); /* One enters */ + helper.recordPrivateApi('call.channel.processMessage'); await channel.processMessage({ action: 14, channel: channelName, @@ -461,6 +484,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }); /* An earlier leave from one (should be ignored) */ + helper.recordPrivateApi('call.channel.processMessage'); await channel.processMessage({ action: 14, channel: channelName, @@ -476,6 +500,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }); /* One adds some data in a newer msgSerial */ + helper.recordPrivateApi('call.channel.processMessage'); await channel.processMessage({ action: 14, channel: channelName, @@ -492,6 +517,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }); /* Two enters */ + helper.recordPrivateApi('call.channel.processMessage'); await channel.processMessage({ action: 14, channel: channelName, @@ -507,6 +533,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }); /* Two updates twice in the same message */ + helper.recordPrivateApi('call.channel.processMessage'); await channel.processMessage({ action: 14, channel: channelName, @@ -528,6 +555,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }); /* Three enters */ + helper.recordPrivateApi('call.channel.processMessage'); await channel.processMessage({ action: 14, channel: channelName, @@ -544,6 +572,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async /* Synthesized leave for three (with earlier msgSerial, incompatible id, * and later timestamp) */ + helper.recordPrivateApi('call.channel.processMessage'); await channel.processMessage({ action: 14, channel: channelName, @@ -629,11 +658,15 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }, function (cb) { var originalProcessMessage = syncerChannel.processMessage; + helper.recordPrivateApi('replace.channel.processMessage'); syncerChannel.processMessage = async function (message) { + helper.recordPrivateApi('call.channel.processMessage'); await originalProcessMessage.apply(this, arguments); /* Inject an additional presence message after the first sync */ if (message.action === 16) { + helper.recordPrivateApi('replace.channel.processMessage'); syncerChannel.processMessage = originalProcessMessage; + helper.recordPrivateApi('call.channel.processMessage'); await syncerChannel.processMessage({ action: 14, id: 'messageid:0', diff --git a/test/realtime/utils.test.js b/test/realtime/utils.test.js index a32c266f0..b80ac10b0 100644 --- a/test/realtime/utils.test.js +++ b/test/realtime/utils.test.js @@ -10,6 +10,7 @@ define(['shared_helper', 'chai'], function (Helper, chai) { var retryAttempts = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; var initialTimeout = 15; + helper.recordPrivateApi('call.Utils.getRetryTime'); var retryTimeouts = retryAttempts.map((attempt) => helper.Utils.getRetryTime(initialTimeout, attempt)); expect(retryTimeouts.filter((timeout) => timeout >= 30).length).to.equal(0); diff --git a/test/rest/auth.test.js b/test/rest/auth.test.js index cbe7fe654..0bf4695b5 100644 --- a/test/rest/auth.test.js +++ b/test/rest/auth.test.js @@ -133,9 +133,12 @@ define(['chai', 'shared_helper', 'async', 'globals'], function (chai, Helper, as it('Token generation with explicit auth', async function () { const helper = this.helper; + helper.recordPrivateApi('call.auth.getAuthHeaders'); const authHeaders = await rest.auth.getAuthHeaders(); + helper.recordPrivateApi('write.auth.authOptions.requestHeaders'); rest.auth.authOptions.requestHeaders = authHeaders; var tokenDetails = await rest.auth.requestToken(); + helper.recordPrivateApi('delete.auth.authOptions.requestHeaders'); delete rest.auth.authOptions.requestHeaders; expect(tokenDetails.token, 'Verify token value').to.be.ok; expect(tokenDetails.issued && tokenDetails.issued >= currentTime, 'Verify token issued').to.be.ok; @@ -145,6 +148,7 @@ define(['chai', 'shared_helper', 'async', 'globals'], function (chai, Helper, as it('Token generation with explicit auth, different key', async function () { const helper = this.helper; + helper.recordPrivateApi('call.auth.getAuthHeaders'); const authHeaders = await rest.auth.getAuthHeaders(); var testKeyOpts = { key: helper.getTestApp().keys[1].keyStr }; var testCapability = JSON.parse(helper.getTestApp().keys[1].capability); @@ -280,7 +284,9 @@ define(['chai', 'shared_helper', 'async', 'globals'], function (chai, Helper, as const helper = this.helper; var currentKey = helper.getTestApp().keys[0]; var keys = { keyName: currentKey.keyName, keySecret: currentKey.keySecret }; + helper.recordPrivateApi('call.Utils.mixin'); var authParams = helper.Utils.mixin(keys, params); + helper.recordPrivateApi('call.Utils.toQueryString'); var authUrl = echoServer + '/createJWT' + helper.Utils.toQueryString(authParams); var restJWTRequester = helper.AblyRest({ authUrl: authUrl }); @@ -308,6 +314,7 @@ define(['chai', 'shared_helper', 'async', 'globals'], function (chai, Helper, as it('JWT request with invalid key', async function () { const helper = this.helper; var keys = { keyName: 'invalid.invalid', keySecret: 'invalidinvalid' }; + helper.recordPrivateApi('call.Utils.toQueryString'); var authUrl = echoServer + '/createJWT' + helper.Utils.toQueryString(keys); var restJWTRequester = helper.AblyRest({ authUrl: authUrl }); @@ -330,6 +337,7 @@ define(['chai', 'shared_helper', 'async', 'globals'], function (chai, Helper, as const helper = this.helper; var currentKey = helper.getTestApp().keys[0]; var keys = { keyName: currentKey.keyName, keySecret: currentKey.keySecret }; + helper.recordPrivateApi('call.Utils.toQueryString'); var authUrl = echoServer + '/createJWT' + helper.Utils.toQueryString(keys); var restJWTRequester = helper.AblyRest({ authUrl: authUrl }); @@ -349,6 +357,7 @@ define(['chai', 'shared_helper', 'async', 'globals'], function (chai, Helper, as it('Rest JWT with authCallback and invalid keys', async function () { const helper = this.helper; var keys = { keyName: 'invalid.invalid', keySecret: 'invalidinvalid' }; + helper.recordPrivateApi('call.Utils.toQueryString'); var authUrl = echoServer + '/createJWT' + helper.Utils.toQueryString(keys); var restJWTRequester = helper.AblyRest({ authUrl: authUrl }); diff --git a/test/rest/fallbacks.test.js b/test/rest/fallbacks.test.js index bac64944f..60e40f1e2 100644 --- a/test/rest/fallbacks.test.js +++ b/test/rest/fallbacks.test.js @@ -30,26 +30,34 @@ define(['shared_helper', 'async', 'chai'], function (Helper, async, chai) { var validUntil; var serverTime = await rest.time(); expect(serverTime, 'Check serverTime returned').to.be.ok; + helper.recordPrivateApi('read.rest._currentFallback'); var currentFallback = rest._currentFallback; expect(currentFallback, 'Check current fallback stored').to.be.ok; + helper.recordPrivateApi('read.rest._currentFallback.host'); expect(currentFallback && currentFallback.host).to.equal(goodHost, 'Check good host set'); + helper.recordPrivateApi('read.rest._currentFallback.validUntil'); validUntil = currentFallback.validUntil; /* now try again, check that this time it uses the remembered good endpoint straight away */ var serverTime = await rest.time(); expect(serverTime, 'Check serverTime returned').to.be.ok; var currentFallback = rest._currentFallback; + helper.recordPrivateApi('read.rest._currentFallback.validUntil'); expect(currentFallback.validUntil).to.equal( validUntil, 'Check validUntil is the same (implying currentFallback has not been re-set)', ); /* set the validUntil to the past and check that the stored fallback is forgotten */ var now = Date.now(); + helper.recordPrivateApi('write.rest._currentFallback.validUntil'); rest._currentFallback.validUntil = now - 1000; var serverTime = await rest.time(); expect(serverTime, 'Check serverTime returned').to.be.ok; + helper.recordPrivateApi('read.rest._currentFallback'); var currentFallback = rest._currentFallback; expect(currentFallback, 'Check current fallback re-stored').to.be.ok; + helper.recordPrivateApi('read.rest._currentFallback.host'); expect(currentFallback && currentFallback.host).to.equal(goodHost, 'Check good host set again'); + helper.recordPrivateApi('read.rest._currentFallback.validUntil'); expect(currentFallback.validUntil > now, 'Check validUntil has been re-set').to.be.ok; }); diff --git a/test/rest/history.test.js b/test/rest/history.test.js index 0841fd8b5..3df592450 100644 --- a/test/rest/history.test.js +++ b/test/rest/history.test.js @@ -46,6 +46,7 @@ define(['shared_helper', 'async', 'chai'], function (Helper, async, chai) { messages.forEach(function (msg) { ids[msg.id] = msg; }); + helper.recordPrivateApi('call.Utils.keysArray'); expect(helper.Utils.keysArray(ids).length).to.equal( testMessages.length, 'Verify correct number of distinct message ids found', @@ -69,6 +70,7 @@ define(['shared_helper', 'async', 'chai'], function (Helper, async, chai) { messages.forEach(function (msg) { ids[msg.id] = msg; }); + helper.recordPrivateApi('call.Utils.keysArray'); expect(helper.Utils.keysArray(ids).length).to.equal( testMessages.length, 'Verify correct number of distinct message ids found', @@ -107,6 +109,7 @@ define(['shared_helper', 'async', 'chai'], function (Helper, async, chai) { } } /* verify message ids are unique */ + helper.recordPrivateApi('call.Utils.keysArray'); expect(helper.Utils.keysArray(ids).length).to.equal( testMessages.length, 'Verify correct number of distinct message ids found', @@ -147,6 +150,7 @@ define(['shared_helper', 'async', 'chai'], function (Helper, async, chai) { } /* verify message ids are unique */ + helper.recordPrivateApi('call.Utils.keysArray'); expect(helper.Utils.keysArray(ids).length).to.equal( testMessages.length, 'Verify correct number of distinct message ids found', @@ -220,6 +224,7 @@ define(['shared_helper', 'async', 'chai'], function (Helper, async, chai) { } /* verify message ids are unique */ + helper.recordPrivateApi('call.Utils.keysArray'); expect(helper.Utils.keysArray(ids).length).to.equal( testMessages.length, 'Verify correct number of distinct message ids found', diff --git a/test/rest/http.test.js b/test/rest/http.test.js index eb1da43be..4dfcb357a 100644 --- a/test/rest/http.test.js +++ b/test/rest/http.test.js @@ -23,6 +23,7 @@ define(['ably', 'shared_helper', 'chai'], function (Ably, Helper, chai) { * RSC7a */ it('Should send X-Ably-Version and Ably-Agent headers in get/post requests', async function () { + const helper = this.helper; var originalDo = rest.http.do; // Intercept Http.do with test @@ -33,6 +34,7 @@ define(['ably', 'shared_helper', 'chai'], function (Ably, Helper, chai) { // This test should not directly validate version against Defaults.version, as // ultimately the version header has been derived from that value. expect(headers['X-Ably-Version']).to.equal('3', 'Verify current version number'); + helper.recordPrivateApi('read.Defaults.version'); expect(headers['Ably-Agent'].indexOf('ably-js/' + Defaults.version) > -1, 'Verify agent').to.be.ok; expect(headers['Ably-Agent'].indexOf('custom-agent/0.1.2') > -1, 'Verify custom agent').to.be.ok; @@ -48,9 +50,11 @@ define(['ably', 'shared_helper', 'chai'], function (Ably, Helper, chai) { expect(headers['Ably-Agent'].indexOf('nodejs') > -1, 'Verify agent').to.be.ok; } + helper.recordPrivateApi('call.rest.http.do'); return originalDo.call(rest.http, method, path, headers, body, params); } + helper.recordPrivateApi('replace.rest.http.do'); rest.http.do = testRequestHandler; // Call all methods that use rest http calls @@ -63,12 +67,14 @@ define(['ably', 'shared_helper', 'chai'], function (Ably, Helper, chai) { }); it('Should handle no content responses', async function () { + const helper = this.helper; //Intercept Http.do with test async function testRequestHandler() { return { error: null, body: null, headers: { 'X-Ably-Foo': 'headerValue' }, unpacked: false, statusCode: 204 }; } + helper.recordPrivateApi('replace.rest.http.do'); rest.http.do = testRequestHandler; const response = await rest.request('GET', '/foo', {}, null, {}); diff --git a/test/rest/init.test.js b/test/rest/init.test.js index db0af97b4..99ec05c18 100644 --- a/test/rest/init.test.js +++ b/test/rest/init.test.js @@ -22,6 +22,7 @@ define(['ably', 'shared_helper', 'chai'], function (Ably, Helper, chai) { var keyStr = helper.getTestApp().keys[0].keyStr; var rest = new helper.Ably.Rest(keyStr); + helper.recordPrivateApi('read.rest.options.key'); expect(rest.options.key).to.equal(keyStr); }); @@ -35,18 +36,21 @@ define(['ably', 'shared_helper', 'chai'], function (Ably, Helper, chai) { var tokenStr = tokenDetails.token, rest = new helper.Ably.Rest(tokenStr); + helper.recordPrivateApi('read.rest.options.token'); expect(rest.options.token).to.equal(tokenStr); }); it('Init with tls: false', function () { const helper = this.helper; var rest = helper.AblyRest({ tls: false, port: 123, tlsPort: 456 }); + helper.recordPrivateApi('call.rest.baseUri'); expect(rest.baseUri('example.com')).to.equal('http://example.com:123'); }); it('Init with tls: true', function () { const helper = this.helper; var rest = helper.AblyRest({ tls: true, port: 123, tlsPort: 456 }); + helper.recordPrivateApi('call.rest.baseUri'); expect(rest.baseUri('example.com')).to.equal('https://example.com:456'); }); @@ -54,6 +58,7 @@ define(['ably', 'shared_helper', 'chai'], function (Ably, Helper, chai) { it('Init without any tls key should enable tls', function () { const helper = this.helper; var rest = helper.AblyRest({ port: 123, tlsPort: 456 }); + helper.recordPrivateApi('call.rest.baseUri'); expect(rest.baseUri('example.com')).to.equal('https://example.com:456'); }); diff --git a/test/rest/message.test.js b/test/rest/message.test.js index e77d89724..5eccdb801 100644 --- a/test/rest/message.test.js +++ b/test/rest/message.test.js @@ -26,10 +26,12 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async channel = rest.channels.get('rest_implicit_client_id_0'); var originalPublish = channel._publish; + helper.recordPrivateApi('replace.restChannel._publish'); channel._publish = async function (requestBody) { var message = JSON.parse(requestBody)[0]; expect(message.name === 'event0', 'Outgoing message interecepted').to.be.ok; expect(!message.clientId, 'client ID is not added by the client library as it is implicit').to.be.ok; + helper.recordPrivateApi('call.restChannel._publish'); return originalPublish.apply(channel, arguments); }; @@ -49,6 +51,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async channel = rest.channels.get('rest_explicit_client_id_0'); var originalPublish = channel._publish; + helper.recordPrivateApi('replace.restChannel._publish'); channel._publish = async function (requestBody) { var message = JSON.parse(requestBody)[0]; expect(message.name === 'event0', 'Outgoing message interecepted').to.be.ok; @@ -56,6 +59,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async message.clientId == clientId, 'client ID is added by the client library as it is explicit in the publish', ).to.be.ok; + helper.recordPrivateApi('call.restChannel._publish'); return originalPublish.apply(channel, arguments); }; @@ -80,6 +84,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async channel = rest.channels.get('rest_explicit_client_id_1'); var originalPublish = channel._publish; + helper.recordPrivateApi('replace.restChannel._publish'); channel._publish = async function (requestBody) { var message = JSON.parse(requestBody)[0]; expect(message.name === 'event0', 'Outgoing message interecepted').to.be.ok; @@ -87,6 +92,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async message.clientId == invalidClientId, 'invalid client ID is added by the client library as it is explicit in the publish', ).to.be.ok; + helper.recordPrivateApi('call.restChannel._publish'); return originalPublish.apply(channel, arguments); }; @@ -150,6 +156,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async originalPublish = channel._publish, originalDoUri = Ably.Realtime._Http.doUri; + helper.recordPrivateApi('replace.restChannel._publish'); channel._publish = async function (requestBody) { var messageOne = JSON.parse(requestBody)[0]; var messageTwo = JSON.parse(requestBody)[1]; @@ -161,11 +168,15 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async expect(idTwo, 'id set on message 2').to.be.ok; expect(idOne && idOne.split(':')[1]).to.equal('0', 'check zero-based index'); expect(idTwo && idTwo.split(':')[1]).to.equal('1', 'check zero-based index'); + helper.recordPrivateApi('call.restChannel._publish'); return originalPublish.apply(channel, arguments); }; + helper.recordPrivateApi('replace.http.doUri'); Ably.Rest._Http.doUri = async function (method, uri, headers, body, params) { + helper.recordPrivateApi('call.http.doUri'); const resultPromise = originalDoUri(method, uri, headers, body, params); + helper.recordPrivateApi('replace.http.doUri'); Ably.Rest._Http.doUri = originalDoUri; const result = await resultPromise; if (result.error) { @@ -193,8 +204,10 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async var originalPublish = channel._publish; /* Stub out _publish to check params */ + helper.recordPrivateApi('replace.restChannel._publish'); channel._publish = async function (requestBody, headers, params) { expect(params && params.testParam).to.equal('testParamValue'); + helper.recordPrivateApi('call.restChannel._publish'); return originalPublish.apply(channel, arguments); }; diff --git a/test/rest/presence.test.js b/test/rest/presence.test.js index 1d5ab4046..b82ce6651 100644 --- a/test/rest/presence.test.js +++ b/test/rest/presence.test.js @@ -7,13 +7,15 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async var Crypto = Ably.Realtime.Platform.Crypto; var BufferUtils = Ably.Realtime.Platform.BufferUtils; - function cipherParamsFromConfig(cipherConfig) { + function cipherParamsFromConfig(cipherConfig, helper) { + helper.recordPrivateApi('new.Crypto.CipherParams'); var cipherParams = new Crypto.CipherParams(); for (var prop in cipherConfig) { cipherParams[prop] = cipherConfig[prop]; } cipherParams.keyLength = cipherConfig.keylength; delete cipherParams.keylength; // grr case differences + helper.recordPrivateApi('call.BufferUtils.base64Decode'); cipherParams.key = BufferUtils.base64Decode(cipherParams.key); cipherParams.iv = BufferUtils.base64Decode(cipherParams.iv); return cipherParams; @@ -33,7 +35,8 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async function presence_simple(operation) { return async function () { - var cipherParams = cipherParamsFromConfig(cipherConfig); + const helper = this.helper; + var cipherParams = cipherParamsFromConfig(cipherConfig, helper); var channel = rest.channels.get('persisted:presence_fixtures', { cipher: cipherParams }); var resultPage = await channel.presence[operation](); var presenceMessages = resultPage.items; diff --git a/test/rest/push.test.js b/test/rest/push.test.js index 9e969cd96..de603633b 100644 --- a/test/rest/push.test.js +++ b/test/rest/push.test.js @@ -83,6 +83,9 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async data: { foo: 'bar' }, }; + helper.recordPrivateApi('read.realtime.options'); + helper.recordPrivateApi('call.Defaults.getHost'); + helper.recordPrivateApi('call.realtime.baseUri'); var baseUri = realtime.baseUri(Ably.Rest.Platform.Defaults.getHost(realtime.options)); var pushRecipient = { transportType: 'ablyChannel', diff --git a/test/rest/request.test.js b/test/rest/request.test.js index 9e49ce64e..6f5fe7cc1 100644 --- a/test/rest/request.test.js +++ b/test/rest/request.test.js @@ -21,7 +21,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }); }); - Helper.restTestOnJsonMsgpack('request_version', function (rest) { + Helper.restTestOnJsonMsgpack('request_version', function (rest, _, helper) { const version = 150; // arbitrarily chosen async function testRequestHandler(_, __, headers) { @@ -35,12 +35,14 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async return new Promise(() => {}); } + helper.recordPrivateApi('replace.rest.http.do'); rest.http.do = testRequestHandler; rest.request('get', '/time' /* arbitrarily chosen */, version, null, null, null); }); - Helper.restTestOnJsonMsgpack('request_time', async function (rest) { + Helper.restTestOnJsonMsgpack('request_time', async function (rest, _, helper) { + helper.recordPrivateApi('read.Defaults.protocolVersion'); const res = await rest.request('get', '/time', Defaults.protocolVersion, null, null, null); expect(res.statusCode).to.equal(200, 'Check statusCode'); expect(res.success).to.equal(true, 'Check success'); @@ -48,10 +50,11 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async expect(res.items.length).to.equal(1, 'Check array was of length 1'); }); - Helper.restTestOnJsonMsgpack('request_404', async function (rest) { + Helper.restTestOnJsonMsgpack('request_404', async function (rest, _, helper) { /* NB: can't just use /invalid or something as the CORS preflight will * fail. Need something superficially a valid path but where the actual * request fails */ + helper.recordPrivateApi('read.Defaults.protocolVersion'); const res = await rest.request( 'get', '/keys/ablyjs.test/requestToken', @@ -71,6 +74,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async const helper = this.helper; rest = helper.AblyRest({ restHost: helper.unroutableAddress }); try { + helper.recordPrivateApi('read.Defaults.protocolVersion'); var res = await rest.request('get', '/time', Defaults.protocolVersion, null, null, null); } catch (err) { expect(err, 'Check get an err').to.be.ok; @@ -81,20 +85,23 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async }); /* Use the request feature to publish, then retrieve (one at a time), some messages */ - Helper.restTestOnJsonMsgpack('request_post_get_messages', async function (rest, channelName) { + Helper.restTestOnJsonMsgpack('request_post_get_messages', async function (rest, channelName, helper) { var channelPath = '/channels/' + channelName + '/messages', msgone = { name: 'faye', data: 'whittaker' }, msgtwo = { name: 'martin', data: 'reed' }; + helper.recordPrivateApi('read.Defaults.protocolVersion'); var res = await rest.request('post', channelPath, Defaults.protocolVersion, null, msgone, null); expect(res.statusCode).to.equal(201, 'Check statusCode is 201'); expect(res.success).to.equal(true, 'Check post was a success'); expect(res.items && res.items.length).to.equal(1, 'Check number of results is as expected'); + helper.recordPrivateApi('read.Defaults.protocolVersion'); res = await rest.request('post', channelPath, Defaults.protocolVersion, null, msgtwo, null); expect(res.statusCode).to.equal(201, 'Check statusCode is 201'); expect(res.items && res.items.length).to.equal(1, 'Check number of results is as expected'); + helper.recordPrivateApi('read.Defaults.protocolVersion'); res = await rest.request( 'get', channelPath, @@ -171,6 +178,7 @@ define(['ably', 'shared_helper', 'async', 'chai'], function (Ably, Helper, async it('check' + method, async function () { const helper = this.helper; var restEcho = helper.AblyRest({ useBinaryProtocol: false, restHost: echoServerHost, tls: true }); + helper.recordPrivateApi('read.Defaults.protocolVersion'); var res = await restEcho.request(method, '/methods', Defaults.protocolVersion, {}, {}, {}); expect(res.items[0] && res.items[0].method).to.equal(method); });