diff --git a/.eslintignore b/.eslintignore index 47d963a48..91cef1057 100644 --- a/.eslintignore +++ b/.eslintignore @@ -6,6 +6,7 @@ src/Kuzzle.js src/KuzzleError.js src/controllers/Auth.js src/controllers/Document.js +src/controllers/Realtime.js src/controllers/Index.js src/controllers/Collection.js src/controllers/Base.js diff --git a/.travis.yml b/.travis.yml index a03c9f9e6..38f09c9b9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -78,7 +78,7 @@ jobs: - npm install - npm run build script: - - npm run doc-testing + - travis_retry npm run doc-testing - stage: Tests name: Dead link check diff --git a/doc/7/controllers/auth/create-api-key/index.md b/doc/7/controllers/auth/create-api-key/index.md index d7a2ca918..f0f301b9f 100644 --- a/doc/7/controllers/auth/create-api-key/index.md +++ b/doc/7/controllers/auth/create-api-key/index.md @@ -56,7 +56,7 @@ The API key content has the following properties: | Name | Type | Description | | --------- | ----------------- | ---------------- | | `userId` |
string
| User kuid | -| `expiresAt` |
number
| Expiration date in UNIX micro-timestamp format (`-1` if the token never expires) | +| `expiresAt` |
number
| Expiration date in Epoch-millis format (`-1` if the token never expires) | | `ttl` |
number
| Original TTL | | `description` |
string
| API key description | | `token` |
string
| Authentication token associated with this API key | diff --git a/doc/7/controllers/realtime/count/index.md b/doc/7/controllers/realtime/count/index.md index d8beddf88..dd5c460ed 100644 --- a/doc/7/controllers/realtime/count/index.md +++ b/doc/7/controllers/realtime/count/index.md @@ -32,7 +32,7 @@ Additional query options ## Resolves -Resolves to a number represensting active connections using the same provided subscription room. +Resolves to a number representing active connections using the same provided subscription room. ## Usage diff --git a/doc/7/controllers/security/create-api-key/index.md b/doc/7/controllers/security/create-api-key/index.md index 35202ecb1..ae4722cb0 100644 --- a/doc/7/controllers/security/create-api-key/index.md +++ b/doc/7/controllers/security/create-api-key/index.md @@ -57,7 +57,7 @@ The API key content has the following properties: | Name | Type | Description | | --------- | ----------------- | ---------------- | | `userId` |
string
| User kuid | -| `expiresAt` |
number
| Aexpiration date in UNIX micro-timestamp format (`-1` if the token never expires) | +| `expiresAt` |
number
| Aexpiration date in Epoch-millis format (`-1` if the token never expires) | | `ttl` |
number
| Original TTL | | `description` |
string
| API key description | | `token` |
string
| Authentication token associated with this API key | diff --git a/doc/7/controllers/security/m-delete-profiles/snippets/m-delete-profiles.test.yml b/doc/7/controllers/security/m-delete-profiles/snippets/m-delete-profiles.test.yml index 6fbf0d363..0c7f7e2de 100644 --- a/doc/7/controllers/security/m-delete-profiles/snippets/m-delete-profiles.test.yml +++ b/doc/7/controllers/security/m-delete-profiles/snippets/m-delete-profiles.test.yml @@ -8,4 +8,4 @@ hooks: }' kuzzle:7512/profiles/profile${i}/_create done template: default -expected: '^\[ ''profile\d'', ''profile\d'', ''profile\d'', ''profile\d', ''profile\d'' \]$' +expected: '^\[ ''profile\d'', ''profile\d'', ''profile\d'', ''profile\d'', ''profile\d'' \]$' diff --git a/doc/7/controllers/security/m-delete-roles/snippets/m-delete-roles.test.yml b/doc/7/controllers/security/m-delete-roles/snippets/m-delete-roles.test.yml index 5578d3834..1fb4967fa 100644 --- a/doc/7/controllers/security/m-delete-roles/snippets/m-delete-roles.test.yml +++ b/doc/7/controllers/security/m-delete-roles/snippets/m-delete-roles.test.yml @@ -14,4 +14,4 @@ hooks: }' kuzzle:7512/roles/role${i}/_create done template: default -expected: '^\[ ''role1'', ''role2'', ''role3'', ''role4'', ''role5'' \]$' +expected: '^\[ ''role\d'', ''role\d'', ''role\d'', ''role\d'', ''role\d'' \]$' diff --git a/doc/7/controllers/security/m-delete-users/snippets/m-delete-users.test.yml b/doc/7/controllers/security/m-delete-users/snippets/m-delete-users.test.yml index be9ebea3d..ef0acb81b 100644 --- a/doc/7/controllers/security/m-delete-users/snippets/m-delete-users.test.yml +++ b/doc/7/controllers/security/m-delete-users/snippets/m-delete-users.test.yml @@ -16,4 +16,4 @@ hooks: }' kuzzle:7512/users/user${i}/_create done template: default -expected: '^\[ ''user1'', ''user2'', ''user3'' \]$' +expected: '^\[ ''user\d'', ''user\d'', ''user\d'' \]$' diff --git a/doc/7/essentials/realtime-notifications/index.md b/doc/7/essentials/realtime-notifications/index.md index cdc976ce7..86583db0d 100644 --- a/doc/7/essentials/realtime-notifications/index.md +++ b/doc/7/essentials/realtime-notifications/index.md @@ -23,7 +23,7 @@ These notifications represent [documents changes & messages](/core/2/api/essenti | `protocol` |
string
| Network protocol used to modify the document | | `result` |
object
| Notification content | | `room` |
string
| Subscription channel identifier. Can be used to link a notification to its corresponding subscription | -| `scope` |
string
| `in`: document enters (or stays) in the scope
string | `in`: document enters (or stays) in the scope
`out`: document leaves the scope | | `timestamp` |
number
| Timestamp of the event, in Epoch-millis format | | `type` |
string
| `document`: Notification type | | `volatile` |
object
| Request [volatile data](/core/2/api/essentials/volatile-data) | @@ -50,7 +50,7 @@ These notifications represent [user events](/core/2/api/essentials/notifications | `room` |
string
| Subscription channel identifier. Can be used to link a notification to its corresponding subscription | | `timestamp` |
number
| Timestamp of the event, in Epoch-millis format | | `type` |
string
| `user`: Notification type | -| `user` |
string
| `in`: a new user has subscribed to the same filters
string | `in`: a new user has subscribed to the same filters
`out`: a user cancelled a shared subscription | | `volatile` |
object
| Request [volatile data](/core/2/api/essentials/volatile-data) | The `result` object is the notification content, and it has the following structure: diff --git a/index.ts b/index.ts index 8552aebd8..9e46e1d98 100644 --- a/index.ts +++ b/index.ts @@ -34,8 +34,9 @@ const exported = { RoleSearchResult, SpecificationsSearchResult, UserSearchResult -} +}; export default exported; + module.exports = exported; diff --git a/src/Kuzzle.ts b/src/Kuzzle.ts index 953d1160b..fb45f8fb0 100644 --- a/src/Kuzzle.ts +++ b/src/Kuzzle.ts @@ -361,15 +361,10 @@ export class Kuzzle extends KuzzleEventEmitter { if (this.autoQueue) { this.startQueuing(); } - - this.realtime.disconnected(); - this.emit('networkError', error); }); this.protocol.addListener('disconnect', () => { - this.realtime.disconnected(); - this.emit('disconnected'); }); @@ -382,8 +377,6 @@ export class Kuzzle extends KuzzleEventEmitter { this.playQueue(); } - this.realtime.reconnected(); - if (this.auth.authenticationToken) { return this.auth.checkToken() .then(res => { diff --git a/src/controllers/Document.ts b/src/controllers/Document.ts index 88066b4a7..60a3c77fc 100644 --- a/src/controllers/Document.ts +++ b/src/controllers/Document.ts @@ -27,7 +27,7 @@ export class DocumentController extends BaseController { count ( index: string, collection: string, - body: JSONObject = null, + body?: JSONObject, options: { queuable?: boolean } = {} ): Promise { const request = { diff --git a/src/controllers/Realtime.js b/src/controllers/Realtime.js deleted file mode 100644 index e68478ba2..000000000 --- a/src/controllers/Realtime.js +++ /dev/null @@ -1,128 +0,0 @@ -const { BaseController } = require('./Base'); -const Room = require('../core/Room'); - - -class RealtimeController extends BaseController { - /** - * @param {Kuzzle} kuzzle - */ - constructor (kuzzle) { - super(kuzzle, 'realtime'); - - this.subscriptions = new Map(); - this.subscriptionsOff = new Map(); - - this.kuzzle.on('tokenExpired', () => this.tokenExpired()); - } - - count (roomId, options = {}) { - return this.query({ - action: 'count', - body: {roomId} - }, options) - .then(response => response.result.count); - } - - publish (index, collection, message, options = {}) { - const request = { - index, - collection, - body: message, - action: 'publish', - _id: options._id - }; - - return this.query(request, options) - .then(response => response.result.published); - } - - subscribe (index, collection, filters, callback, options = {}) { - const room = new Room(this, index, collection, filters, callback, options); - - return room.subscribe() - .then(() => { - if (!this.subscriptions.has(room.id)) { - this.subscriptions.set(room.id, []); - } - this.subscriptions.get(room.id).push(room); - return room.id; - }); - } - - unsubscribe (roomId, options = {}) { - const request = { - action: 'unsubscribe', - body: { roomId } - }; - - return this.query(request, options) - .then(response => { - const rooms = this.subscriptions.get(roomId); - - if (rooms) { - for (const room of rooms) { - room.removeListeners(); - } - - this.subscriptions.delete(roomId); - } - - return response.result; - }); - } - - // called on network error or disconnection - disconnected () { - for (const roomId of this.subscriptions.keys()) { - for (const room of this.subscriptions.get(roomId)) { - room.removeListeners(); - - if (room.autoResubscribe) { - if (!this.subscriptionsOff.has(roomId)) { - this.subscriptionsOff.set(roomId, []); - } - this.subscriptionsOff.get(roomId).push(room); - } - } - - this.subscriptions.delete(roomId); - } - } - - /** - * Called on kuzzle reconnection. - * Resubscribe to eligible disabled rooms. - */ - reconnected () { - for (const roomId of this.subscriptionsOff.keys()) { - for (const room of this.subscriptionsOff.get(roomId)) { - if (!this.subscriptions.has(roomId)) { - this.subscriptions.set(roomId, []); - } - this.subscriptions.get(roomId).push(room); - - room.subscribe() - .catch(() => this.kuzzle.emit('discarded', {request: room.request})); - } - - this.subscriptionsOff.delete(roomId); - } - } - - /** - * Removes all subscriptions. - */ - tokenExpired() { - for (const roomId of this.subscriptions.keys()) { - for (const room of this.subscriptions.get(roomId)) { - room.removeListeners(); - } - } - - this.subscriptions = new Map(); - this.subscriptionsOff = new Map(); - } - -} - -module.exports = { RealtimeController }; diff --git a/src/controllers/Realtime.ts b/src/controllers/Realtime.ts new file mode 100644 index 000000000..007addf64 --- /dev/null +++ b/src/controllers/Realtime.ts @@ -0,0 +1,259 @@ +import { BaseController } from './Base'; +import Room from '../core/Room'; +import { JSONObject } from '../utils/interfaces'; + +/** + * Enum for `scope` option of realtime.subscribe method + */ +export enum ScopeOption { + /** + * Receive all document notifications + */ + all = 'all', + /** + * Receive notifications when document enter or stay in the scope + */ + in = 'in', + /** + * Receive notification when document exit the scope + */ + out = 'out', + /** + * Do not receive document notifications + */ + none = 'none' +} + +/** + * Enum for `user` option of realtime.subscribe method + */ +export enum UserOption { + /** + * Receive all user notifications + */ + all = 'all', + /** + * Receive notification when users join the room + */ + in = 'in', + /** + * Receive notifications when users leave the room + */ + out = 'out', + /** + * Do not receive user notifications + */ + none = 'none' +} + +export class RealtimeController extends BaseController { + private _subscriptions: Map>; + private _subscriptionsOff: Map>; + + constructor (kuzzle) { + super(kuzzle, 'realtime'); + + this._subscriptions = new Map(); + this._subscriptionsOff = new Map(); + + this.kuzzle.on('tokenExpired', () => this.removeSubscriptions()); + this.kuzzle.on('disconnected', () => this.saveSubscriptions()); + this.kuzzle.on('networkError', () => this.saveSubscriptions()); + this.kuzzle.on('reconnected', () => this.resubscribe()); + } + + /** + * Returns the number of other connections sharing the same subscription. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/realtime/count/ + * + * @param roomId Subscription room ID + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + * + * @returns A number represensting active connections using the same provided subscription room. + */ + count (roomId: string, options: { queuable?: boolean } = {}): Promise { + return this.query({ + action: 'count', + body: { roomId } + }, options) + .then(response => response.result.count); + } + + /** + * Sends a real-time message to Kuzzle. + * + * The message will be dispatched to all clients with subscriptions + * matching the index, the collection and the message content. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/realtime/count/ + * + * @param index Index name + * @param collection Collection name + * @param message Message to send (will be put in `_source` property of the notification) + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + * - `_id` Additional unique ID (will be put in the `_id` property of the notification) + */ + publish ( + index: string, + collection: string, + message: JSONObject, + options: { queuable?: boolean, _id?: string } = {} + ): Promise { + const request = { + index, + collection, + body: message, + action: 'publish', + _id: options._id + }; + + return this.query(request, options) + .then(response => response.result.published); + } + + /** + * Subscribes by providing a set of filters: messages, document changes + * and, optionally, user events matching the provided filters will generate + * real-time notifications. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/realtime/subscribe/ + * @see https://docs.kuzzle.io/sdk/js/7/essentials/realtime-notifications/ + * + * @param index Index name + * @param collection Collection name + * @param filters Optional subscription filters (@see https://docs.kuzzle.io/core/2/guides/cookbooks/realtime-api) + * @param callback Callback function to handle notifications + * @param options Additional options + * - `scope` Subscribe to document entering or leaving the scope. (default: 'all') + * - `users` Subscribe to users entering or leaving the room. (default: 'none') + * - `subscribeToSelf` Subscribe to notifications fired by our own queries. (default: true) + * - `volatile` Subscription information sent alongside notifications + * + * @returns A string containing the room ID + */ + subscribe ( + index: string, + collection: string, + filters: JSONObject, + callback: (Notification) => void | Promise, + options: { + /** + * Subscribe to document entering or leaving the scope. (default: 'all') + */ + scope?: ScopeOption; + /** + * Subscribe to users entering or leaving the room. (default: 'none') + */ + users?: UserOption; + /** + * Subscribe to notifications fired by our own queries. (default: true) + */ + subscribeToSelf?: boolean; + /** + * Subscription information sent alongside notifications + */ + volatile?: JSONObject; + } = {} + ): Promise { + const room = new Room(this, index, collection, filters, callback, options); + + return room.subscribe() + .then(() => { + if (!this._subscriptions.has(room.id)) { + this._subscriptions.set(room.id, []); + } + this._subscriptions.get(room.id).push(room); + return room.id; + }); + } + + /** + * Removes a subscription + * + * @param roomId Subscription room ID + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + */ + unsubscribe ( + roomId: string, + options: { queuable?: boolean } = {} + ): Promise { + const request = { + action: 'unsubscribe', + body: { roomId } + }; + + return this.query(request, options) + .then(response => { + const rooms = this._subscriptions.get(roomId); + + if (rooms) { + for (const room of rooms) { + room.removeListeners(); + } + + this._subscriptions.delete(roomId); + } + + return response.result; + }); + } + + /** + * Called when kuzzle is disconnected + */ + private saveSubscriptions () { + for (const roomId of this._subscriptions.keys()) { + for (const room of this._subscriptions.get(roomId)) { + room.removeListeners(); + + if (room.autoResubscribe) { + if (!this._subscriptionsOff.has(roomId)) { + this._subscriptionsOff.set(roomId, []); + } + this._subscriptionsOff.get(roomId).push(room); + } + } + + this._subscriptions.delete(roomId); + } + } + + /** + * Called on kuzzle reconnection + */ + private resubscribe () { + for (const roomId of this._subscriptionsOff.keys()) { + for (const room of this._subscriptionsOff.get(roomId)) { + if (!this._subscriptions.has(roomId)) { + this._subscriptions.set(roomId, []); + } + this._subscriptions.get(roomId).push(room); + + room.subscribe() + .catch(() => this.kuzzle.emit('discarded', { request: room.request })); + } + + this._subscriptionsOff.delete(roomId); + } + } + + /** + * Called when a token expire + */ + private removeSubscriptions() { + for (const roomId of this._subscriptions.keys()) { + for (const room of this._subscriptions.get(roomId)) { + room.removeListeners(); + } + } + + this._subscriptions = new Map(); + this._subscriptionsOff = new Map(); + } +} + +module.exports = { RealtimeController }; diff --git a/src/core/Room.js b/src/core/Room.js index ddf0c4af4..25fd7a6ed 100644 --- a/src/core/Room.js +++ b/src/core/Room.js @@ -1,3 +1,5 @@ +'use strict'; + class Room { /** diff --git a/src/utils/interfaces.ts b/src/utils/interfaces.ts index a7c175da2..c1546ee9d 100644 --- a/src/utils/interfaces.ts +++ b/src/utils/interfaces.ts @@ -239,6 +239,139 @@ export interface CollectionMappings { dynamic?: 'true' | 'false' | 'strict' | boolean, } +/** + * Enum for notification types + */ +export enum ENotificationType { + document = 'document', + user = 'user', + TokenExpired = 'TokenExpired' +} + +/** + * Real-time notifications sent by Kuzzle. + * + */ +export interface Notification { + /** + * Notification type + */ + type: ENotificationType; +} + +export interface BaseNotification extends Notification { + /** + * Controller that triggered the notification + */ + controller: string; + /** + * Action that triggered the notification + */ + action: string; + /** + * Index name + */ + index: string; + /** + * Collection name + */ + collection: string; + /** + * Network protocol used to trigger the notification + */ + protocol: string; + /** + * Subscription channel identifier. + * Can be used to link a notification to its corresponding subscription + */ + room: string; + /** + * Timestamp of the event, in Epoch-millis format + */ + timestamp: number; + /** + * Request volatile data + * @see https://docs.kuzzle.io/core/2/guides/essentials/volatile-data/ + */ + volatile: JSONObject; +} + +/** + * State of the document regarding the scope + */ +export enum EDocumentScope { + /** + * Document enters or stays in the scope + */ + in = 'in', + /** + * Document exit the scope + */ + out = 'out' +} + +/** + * Notification triggered by a document change. + * (create, update, delete) + */ +export interface DocumentNotification extends BaseNotification { + /** + * Updated document that triggered the notification + */ + result: Document; + /** + * State of the document regarding the scope (`in` or `out`) + */ + scope: EDocumentScope; + + type: ENotificationType.document; +} + +/** + * Tells wether an user leave or join the subscription room + */ +export enum EUserScope { + /** + * User enters the subscription room + */ + in = 'in', + /** + * User leaves the subscription room + */ + out = 'out' +} + +/** + * Notification triggered by an user joining or leaving a subscription room + */ +export interface UserNotification extends BaseNotification { + /** + * Tell wether an user leave or join the subscription room (`in` or `out`) + */ + user: EUserScope; + + /** + * Contains the actual number of users in the subscription room + */ + result: { + /** + * Updated users count sharing the same subscription room + */ + count: number; + } + + type: ENotificationType.user; +} + +export interface ServerNotification extends BaseNotification { + /** + * Server message explaining why this notifications has been triggered + */ + message: string; + + type: ENotificationType.TokenExpired; +} + /** * HTTP routes definition format * @example diff --git a/test/controllers/realtime.test.js b/test/controllers/realtime.test.js index c264a24cb..698ecd767 100644 --- a/test/controllers/realtime.test.js +++ b/test/controllers/realtime.test.js @@ -26,17 +26,52 @@ describe('Realtime Controller', () => { }); describe('on: tokenExpired', () => { - it('should call tokenExpired() method', () => { - kuzzle.realtime.tokenExpired = sinon.stub(); + it('should call removeSubscriptions() method', () => { + kuzzle.realtime.removeSubscriptions = sinon.stub(); kuzzle.emit('tokenExpired'); process.nextTick(() => { - should(kuzzle.realtime.tokenExpired).be.called(); + should(kuzzle.realtime.removeSubscriptions).be.called(); }); }); }); + describe('on: disconnected', () => { + it('should call saveSubscriptions() method', () => { + kuzzle.realtime.saveSubscriptions = sinon.stub(); + + kuzzle.emit('disconnected'); + + process.nextTick(() => { + should(kuzzle.realtime.saveSubscriptions).be.called(); + }); + }); + }); + + describe('on: networkError', () => { + it('should call saveSubscriptions() method', () => { + kuzzle.realtime.saveSubscriptions = sinon.stub(); + + kuzzle.emit('networkError'); + + process.nextTick(() => { + should(kuzzle.realtime.saveSubscriptions).be.called(); + }); + }); + }); + + describe('on: reconnected', () => { + it('should call resubscribe() method', () => { + kuzzle.realtime.resubscribe = sinon.stub(); + + kuzzle.emit('reconnected'); + + process.nextTick(() => { + should(kuzzle.realtime.resubscribe).be.called(); + }); + }); + }); describe('#count', () => { it('should call realtime/count query with the roomId and return a Promise which resolves a number', () => { @@ -139,17 +174,17 @@ describe('Realtime Controller', () => { body = {foo: 'bar'}, cb = sinon.stub(); - kuzzle.realtime.subscriptions = new Map(); + kuzzle.realtime._subscriptions = new Map(); return kuzzle.realtime.subscribe('index', 'collection', body, cb, options) .then(() => { - const subscriptions = kuzzle.realtime.subscriptions.get(roomId); + const subscriptions = kuzzle.realtime._subscriptions.get(roomId); should(subscriptions).be.an.Array(); should(subscriptions.length).be.exactly(1); should(subscriptions[0]).be.exactly(room); return kuzzle.realtime.subscribe('index', 'collection', body, cb, options); }).then(() => { - const subscriptions = kuzzle.realtime.subscriptions.get(roomId); + const subscriptions = kuzzle.realtime._subscriptions.get(roomId); should(subscriptions).be.an.Array(); should(subscriptions.length).be.exactly(2); @@ -175,8 +210,8 @@ describe('Realtime Controller', () => { room1.removeListeners.reset(); room2.removeListeners.reset(); - kuzzle.realtime.subscriptions.set(roomId, [room1, room2]); - kuzzle.realtime.subscriptions.set('foo', [room3]); + kuzzle.realtime._subscriptions.set(roomId, [room1, room2]); + kuzzle.realtime._subscriptions.set('foo', [room3]); kuzzle.query.resolves({result: roomId}); }); @@ -193,12 +228,12 @@ describe('Realtime Controller', () => { it('should delete rooms from local storage', () => { return kuzzle.realtime.unsubscribe(roomId) .then(() => { - should(kuzzle.realtime.subscriptions.get(roomId)).be.undefined(); + should(kuzzle.realtime._subscriptions.get(roomId)).be.undefined(); // Check we do not remove other registered rooms: - should(kuzzle.realtime.subscriptions.get('foo')).be.an.Array(); - should(kuzzle.realtime.subscriptions.get('foo').length).be.equal(1); - should(kuzzle.realtime.subscriptions.get('foo')[0]).be.equal(room3); + should(kuzzle.realtime._subscriptions.get('foo')).be.an.Array(); + should(kuzzle.realtime._subscriptions.get('foo').length).be.equal(1); + should(kuzzle.realtime._subscriptions.get('foo')[0]).be.equal(room3); }); }); @@ -218,7 +253,7 @@ describe('Realtime Controller', () => { }); }); - describe('#disconnected', () => { + describe('#saveSubscriptions', () => { it('should disable current subscriptions', () => { const roomA = { autoResubscribe: true, @@ -233,15 +268,15 @@ describe('Realtime Controller', () => { removeListeners: sinon.stub() }; - kuzzle.realtime.subscriptions = new Map([ + kuzzle.realtime._subscriptions = new Map([ ['foo', [roomA, roomB]], ['bar', [roomC]] ]); - kuzzle.realtime.disconnected(); + kuzzle.realtime.saveSubscriptions(); - should(kuzzle.realtime.subscriptions).be.empty(); - should(kuzzle.realtime.subscriptionsOff).eql(new Map([ + should(kuzzle.realtime._subscriptions).be.empty(); + should(kuzzle.realtime._subscriptionsOff).eql(new Map([ ['foo', [roomA]] ])); for (const room of [roomA, roomB, roomC]) { @@ -250,21 +285,21 @@ describe('Realtime Controller', () => { }); }); - describe('#reconnected', () => { + describe('#resubscribe', () => { it('should resubmit pending subcriptions', () => { const roomA = { subscribe: sinon.stub().resolves() }; const roomB = { subscribe: sinon.stub().resolves() }; const roomC = { subscribe: sinon.stub().resolves() }; - kuzzle.realtime.subscriptionsOff = new Map([ + kuzzle.realtime._subscriptionsOff = new Map([ ['foo', [roomA, roomB]], ['bar', [roomC]] ]); - kuzzle.realtime.reconnected(); + kuzzle.realtime.resubscribe(); - should(kuzzle.realtime.subscriptionsOff).be.empty(); - should(kuzzle.realtime.subscriptions).eql(new Map([ + should(kuzzle.realtime._subscriptionsOff).be.empty(); + should(kuzzle.realtime._subscriptions).eql(new Map([ ['foo', [roomA, roomB]], ['bar', [roomC]] ])); @@ -276,19 +311,19 @@ describe('Realtime Controller', () => { }); }); - describe('#tokenExpired', () => { - it('should clear all subscriptions and emit a "tokenExpired" event', () => { + describe('#removeSubscriptions', () => { + it('should clear all subscriptions', () => { const stub = sinon.stub(); kuzzle.jwt = 'foobar'; for (let i = 0; i < 10; i++) { - kuzzle.realtime.subscriptions.set(uuidv4(), [{removeListeners: stub}]); + kuzzle.realtime._subscriptions.set(uuidv4(), [{removeListeners: stub}]); } - kuzzle.realtime.tokenExpired(); + kuzzle.realtime.removeSubscriptions(); - should(kuzzle.realtime.subscriptions).be.empty(); + should(kuzzle.realtime._subscriptions).be.empty(); should(stub.callCount).be.eql(10); }); }); diff --git a/test/kuzzle/connect.test.js b/test/kuzzle/connect.test.js index 63c784b55..a151ffbd5 100644 --- a/test/kuzzle/connect.test.js +++ b/test/kuzzle/connect.test.js @@ -53,7 +53,7 @@ describe('Kuzzle connect', () => { kuzzle = new Kuzzle(protocols.nowhere), eventStub = sinon.stub(); - kuzzle.realtime.disconnected = sinon.stub(); + kuzzle.realtime.saveSubscriptions = sinon.stub(); kuzzle.addListener('networkError', eventStub); @@ -62,7 +62,7 @@ describe('Kuzzle connect', () => { throw new Error('should not happen'); }) .catch(() => { - should(kuzzle.realtime.disconnected).be.calledOnce(); + should(kuzzle.realtime.saveSubscriptions).be.calledOnce(); should(eventStub).be.calledOnce(); }); }); @@ -85,13 +85,13 @@ describe('Kuzzle connect', () => { kuzzle = new Kuzzle(protocols.somewhereagain), eventStub = sinon.stub(); - kuzzle.realtime.reconnected = sinon.stub(); + kuzzle.realtime.resubscribe = sinon.stub(); kuzzle.addListener('reconnected', eventStub); return kuzzle.connect() .then(() => { - should(kuzzle.realtime.reconnected).be.calledOnce(); + should(kuzzle.realtime.resubscribe).be.calledOnce(); should(eventStub).be.calledOnce(); }); }); @@ -137,14 +137,14 @@ describe('Kuzzle connect', () => { kuzzle = new Kuzzle(protocols.somewhere), eventStub = sinon.stub(); - kuzzle.realtime.disconnected = sinon.stub(); + kuzzle.realtime.saveSubscriptions = sinon.stub(); kuzzle.addListener('disconnected', eventStub); return kuzzle.connect() .then(() => kuzzle.protocol.disconnect()) .then(() => { - should(kuzzle.realtime.disconnected).be.calledOnce(); + should(kuzzle.realtime.saveSubscriptions).be.calledOnce(); should(eventStub).be.calledOnce(); }); }); diff --git a/test/kuzzle/listenersManagement.test.js b/test/kuzzle/listenersManagement.test.js index 0bd0599dc..a6d599315 100644 --- a/test/kuzzle/listenersManagement.test.js +++ b/test/kuzzle/listenersManagement.test.js @@ -2,7 +2,7 @@ const should = require('should'); const sinon = require('sinon'); const { Kuzzle } = require('../../src/Kuzzle'); -const { KuzzleEventEmitter } =require('../../src/core/KuzzleEventEmitter'); +const { KuzzleEventEmitter } = require('../../src/core/KuzzleEventEmitter'); const ProtocolMock = require('../mocks/protocol.mock'); describe('Kuzzle listeners management', () => {