Home Reference Source

src/conferences/ConferenceLog.spec.ts

import {WapiClient} from '@quobis/wapi-client';
import {expect} from 'chai';
import {map} from 'rxjs/operators';
import {TestScheduler} from 'rxjs/testing';
import sinon from 'sinon';
import {StubbedInstance, stubConstructor} from 'ts-sinon';

import {ConferenceLog} from '../Sippo';
import {WacRequest} from '../wac-proxy/wac-stack/WacRequest';
import {ConferenceLogService} from '../wac-proxy/wac-stack/conference-log/ConferenceLogService';
import * as ConferenceLogBuilder from '../wac-proxy/wac-stack/conference-log/builder';

describe('conferences/ConferenceLog', () => {
	let testScheduler: TestScheduler;
	let wacRequest: WacRequest;
	let conferenceLogService: StubbedInstance<ConferenceLogService>;

	beforeEach(() => {
		testScheduler = new TestScheduler((actual, expected) => {
			expect(actual).to.deep.equal(expected);
		});
		wacRequest = new WacRequest(stubConstructor(WapiClient));
		conferenceLogService = stubConstructor(ConferenceLogService, wacRequest);
	});

	afterEach(() => {
		sinon.restore();
	});

	it('should update the list when a new entry is created', () => {
		testScheduler.run(({expectObservable, hot}) => {
			const ENTRY_DTO_1 = ConferenceLogBuilder.inviteTo('alice', 100);
			const ENTRY_DTO_2 = ConferenceLogBuilder.inviteTo('bob', 200);

			sinon.stub(conferenceLogService, 'contactEvent$').value(hot('50ms a 100ms b', {
				a: {method: 'POST', body: ENTRY_DTO_1},
				b: {method: 'POST', body: ENTRY_DTO_2},
			}));
			const conferenceLog = new ConferenceLog(conferenceLogService);

			const toInvites$ = conferenceLog.entries$.pipe(map(entries => entries.map(entry => entry.invites[0].to)));
			expectObservable(toInvites$).toBe('a 49ms b 100ms c', {
				a: [],
				b: ['alice'],
				c: ['bob', 'alice'],
			});
		});
	});

	it('should be able to recover old entries', () => {
		const CONFERENCE_HISTORY = [
			ConferenceLogBuilder.inviteTo('alice', 5000),
			ConferenceLogBuilder.inviteTo('bob', 4900),
			ConferenceLogBuilder.inviteTo('carol', 4800),
			ConferenceLogBuilder.inviteTo('dan', 4700),
			ConferenceLogBuilder.inviteTo('alice', 4600),
		];

		testScheduler.run(({expectObservable, cold}) => {
			conferenceLogService.fetch.callsFake((limit, createdAt) => cold('a', {a: CONFERENCE_HISTORY.filter(e => e.createdAt < createdAt).slice(0, limit)}));

			const conferenceLog = new ConferenceLog(conferenceLogService);
			cold('20ms b 49ms c 99ms d', {
				b: 2,
				c: 1,
				d: 3,
			}).subscribe(async limit => conferenceLog.fetch(limit));

			const toInvites$ = conferenceLog.entries$.pipe(map(entries => entries.map(entry => entry.invites[0].to)));
			expectObservable(toInvites$).toBe('a 19ms b 49ms c 99ms d', {
				a: [],
				b: ['alice', 'bob'],
				c: ['alice', 'bob', 'carol'],
				d: ['alice', 'bob', 'carol', 'dan', 'alice'],
			});
		});
	});

	it('should recover inviteTo conference entries', () => {
		testScheduler.run(({expectObservable, cold}) => {
			conferenceLogService.fetch.returns(cold('a', {a: [ConferenceLogBuilder.inviteTo('alice', 5000)]}));
			const conferenceLog = new ConferenceLog(conferenceLogService);
			cold('a').subscribe(async () => conferenceLog.fetch());

			const candidates = conferenceLog.entries$.pipe(map(entries => entries.map(entry => entry.invites[0].getCandidates())));
			expectObservable(candidates).toBe('(ab)', {
				a: [],
				b: [[{
					address: 'alice',
					direction: 'incoming',
					state: 'accepted',
					type: 'invite',
					group: false,
				}]],
			});
		});
	});

	it('should recover inviteToGroup conference entries', () => {
		testScheduler.run(({expectObservable, cold}) => {
			conferenceLogService.fetch.returns(cold('a', {a: [ConferenceLogBuilder.inviteToGroup('alice', 5000)]}));
			const conferenceLog = new ConferenceLog(conferenceLogService);
			cold('a').subscribe(async () => conferenceLog.fetch());

			const candidates = conferenceLog.entries$.pipe(map(entries => entries.map(entry => entry.invites[0].getCandidates())));
			expectObservable(candidates).toBe('(ab)', {
				a: [],
				b: [[{
					address: 'alice',
					direction: 'incoming',
					state: 'accepted',
					type: 'invite',
					group: true,
				}, {
					address: 'wac-user:user-in-group',
					direction: 'incoming',
					state: 'rejected',
					type: 'invite',
					group: true,
				}]],
			});
		});
	});

	it('should recover transferToDecline conference entries', () => {
		testScheduler.run(({expectObservable, cold}) => {
			conferenceLogService.fetch.returns(cold('a', {a: [ConferenceLogBuilder.transferToDeclined('alice', 5000)]}));
			const conferenceLog = new ConferenceLog(conferenceLogService);
			cold('a').subscribe(async () => conferenceLog.fetch());

			const invites$ = conferenceLog.entries$.pipe(map(entries => entries.map(entry => entry.invites)));
			expectObservable(invites$).toBe('(ab)', {
				a: [],
				b: [[]],
			});
			const transfers$ = conferenceLog.entries$.pipe(map(entries => entries.map(entry => entry.transfers[0].getParticipants())));
			expectObservable(transfers$).toBe('(ab)', {
				a: [],
				b: [[{
					address: 'wac-user:transfer-from',
					direction: 'outgoing',
					state: 'rejected',
				}, {
					address: 'alice',
					direction: 'incoming',
					state: 'rejected',
				}]],
			});
		});
	});
});