From 9fa01962d1273d7b7c2665bea68ff15ce10f6eea Mon Sep 17 00:00:00 2001 From: Arash Koushkebaghi Date: Thu, 24 Oct 2019 16:23:07 -0700 Subject: [PATCH] feat(RoomsAdapter): implement adapter --- src/RoomsAdapter.js | 89 ++++++++++++++++++++++++++++++++++++++++ src/RoomsAdapter.test.js | 64 +++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 src/RoomsAdapter.js create mode 100644 src/RoomsAdapter.test.js diff --git a/src/RoomsAdapter.js b/src/RoomsAdapter.js new file mode 100644 index 0000000..e607e07 --- /dev/null +++ b/src/RoomsAdapter.js @@ -0,0 +1,89 @@ +/* eslint-disable valid-jsdoc */ +import {throwError} from 'rxjs'; + +import WebexAdapter from './WebexAdapter'; + +/** + * A Room object with details about the room. + * + * @typedef {Object} Room + * @property {string} ID The room identifier. + * @property {string} title The room title. + * @property {RoomType} type The type of the room. @see RoomType enum + */ + +/** + * @typedef {Object} ActivityDate + * @param {string} date Date that will render on a time ruler. Must be a valid date-time string. + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse#Date_Time_String_Format + */ + +/** + * Enum for room type values. + * + * @readonly + * @enum {string} + */ +export const RoomType = { + GROUP: 'group', + DIRECT: 'direct', +}; + +/** + * This is a base class that defines the interface that maps room data. + * Developers that want to extend `RoomsAdapter` must implement all of its methods, + * adhering to the exact parameters and structure of the returned objects. + * + * `RoomsAdapter` handles data of a room such as details about that room but also + * activities that happened/will happen within that room. Activities are expected + * to be lazy loaded, and therefore, chunked. + */ +export default class RoomsAdapter extends WebexAdapter { + /** + * Returns an observable that emits room data of the given ID. + * + * @param {string} ID ID of the room to get. + * @returns {Observable.} + * @memberof RoomsAdapter + */ + getRoom(ID) { + return throwError(new Error('getRoom(ID) must be defined in RoomsAdapter')); + } + + /** + * Returns an observable that emits an array of current and future activities of the given roomID. + * + * @param {string} ID ID of the room for which to get activities. + * @returns {Observable.>} + * @memberof RoomsAdapter + */ + getRoomActivities(ID) { + return throwError(new Error('getRoomActivities(ID) must be defined in RoomsAdapter')); + } + + /** + * Returns an observable that emits an array of the next chunk of previous + * activity data of the given roomID. If `hasMoreActivities` returns false, + * the observable will complete. + * **Previous activity data must be sorted newest-to-oldest.** + * + * @param {string} ID ID of the room for which to get activities. + * @returns {Observable.>} + * @memberof RoomsAdapter + */ + getPreviousRoomActivities(ID) { + return throwError(new Error('getPreviousRoomActivities(ID) must be defined in RoomsAdapter')); + } + + /** + * Returns `true` if there are more activities to load from the room of the given ID. + * Otherwise, it returns `false`. + * + * @param {string} ID ID of the room for which to verify activities. + * @returns {boolean} + * @memberof RoomsAdapter + */ + hasMoreActivities(ID) { + throw new Error('hasMoreActivities(ID) must be defined in RoomsAdapter'); + } +} diff --git a/src/RoomsAdapter.test.js b/src/RoomsAdapter.test.js new file mode 100644 index 0000000..3d83dbf --- /dev/null +++ b/src/RoomsAdapter.test.js @@ -0,0 +1,64 @@ +import {isObservable} from 'rxjs'; + +import RoomsAdapter from './RoomsAdapter'; + +describe('Rooms Adapter Interface', () => { + let roomsAdapter; + + beforeEach(() => { + roomsAdapter = new RoomsAdapter(); + }); + + test('getRoom() returns an observable', () => { + expect(isObservable(roomsAdapter.getRoom())).toBeTruthy(); + }); + + test('getRoom() errors because it needs to be defined', (done) => { + roomsAdapter.getRoom('ID').subscribe( + () => {}, + (error) => { + expect(error.message).toBe('getRoom(ID) must be defined in RoomsAdapter'); + done(); + } + ); + }); + + test('getRoomActivities() returns an observable', () => { + expect(isObservable(roomsAdapter.getRoomActivities())).toBeTruthy(); + }); + + test('getRoomActivities() errors because it needs to be defined', (done) => { + roomsAdapter.getRoomActivities('id').subscribe( + () => {}, + (error) => { + expect(error.message).toBe('getRoomActivities(ID) must be defined in RoomsAdapter'); + done(); + } + ); + }); + + test('getPreviousRoomActivities() returns an observable', () => { + expect(isObservable(roomsAdapter.getRoomActivities())).toBeTruthy(); + }); + + test('getPreviousRoomActivities() errors because it needs to be defined', (done) => { + roomsAdapter.getPreviousRoomActivities('id').subscribe( + () => {}, + (error) => { + expect(error.message).toBe('getPreviousRoomActivities(ID) must be defined in RoomsAdapter'); + done(); + } + ); + }); + + test('hasMoreActivities() errors because it needs to be defined', () => { + try { + expect(roomsAdapter.hasMoreActivities('ID')).toThrowError(); + // eslint-disable-next-line no-empty + } catch (error) {} + }); + + afterEach(() => { + roomsAdapter = null; + }); +});