text: /*!
   * Copyright (c) 2015-2019 Cisco Systems, Inc. See LICENSE file.
   */
  
  import {assert} from '@webex/test-helper-chai';
  import sinon from 'sinon';
  import MockWebex from '@webex/test-helper-mock-webex';
  import Device from '@webex/internal-plugin-wdm';
  import Mercury from '@webex/internal-plugin-mercury';
  import Meetings from '@webex/plugin-meetings/src/meetings';
  import PersonalMeetingRoom from '@webex/plugin-meetings/src/personal-meeting-room';
  import Reachability from '@webex/plugin-meetings/src/reachability';
  import MeetingCollection from '@webex/plugin-meetings/src/meetings/collection';
  import MeetingsUtil from '@webex/plugin-meetings/src/meetings/util';
  import Meeting from '@webex/plugin-meetings/src/meeting';
  import MediaUtil from '@webex/plugin-meetings/src/media/util';
  import LoggerProxy from '@webex/plugin-meetings/src/common/logs/logger-proxy';
  import LoggerConfig from '@webex/plugin-meetings/src/common/logs/logger-config';
  import TriggerProxy from '@webex/plugin-meetings/src/common/events/trigger-proxy';
  import uuid from 'uuid';
  import {skipInBrowser} from '@webex/test-helper-mocha';
  
  
  skipInBrowser(describe)('plugin-meetings', () => {
    const logger = {
      log: () => {},
      info: () => {},
      error: () => {},
      warn: () => {},
      trace: () => {},
      debug: () => {}
    };
  
    beforeEach(() => {
      LoggerConfig.set({verboseEvents: true, enable: false});
      LoggerProxy.set(logger);
      TriggerProxy.trigger = sinon.stub().returns(true);
    });
  
    let webex;
    let uuid1;
    let uri1;
    let url1;
    let test1;
    let test2;
  
    describe('meetings index', () => {
      beforeEach(() => {
        uuid1 = uuid.v4();
        url1 = `https://example.com/${uuid.v4()}`;
        uri1 = `test-${uuid.v4()}@example.com`;
        test1 = `test-${uuid.v4()}`;
        test2 = `test2-${uuid.v4()}`;
        webex = new MockWebex({
          children: {
            device: Device,
            mercury: Mercury,
            meetings: Meetings
          }
        });
      });
      it('has a webex instance with a meetings property', () => {
        assert.exists(webex, 'webex was initialized with children');
        assert.exists(webex.meetings, 'meetings child was set up on the webex instance');
      });
      describe('Public API Contracts', () => {
        describe('gets', () => {
          describe('#getReachability', () => {
            it('should have #getReachability', () => {
              assert.exists(webex.meetings.getReachability);
            });
            describe('before #setReachability', () => {
              it('does not get a reachability instance', () => {
                const reachability = webex.meetings.getReachability();
  
                assert.notExists(reachability, 'reachability is undefined because #setReachability has not been called');
              });
            });
            describe('after #setReachability', () => {
              beforeEach(() => {
                webex.meetings.setReachability();
                const reachabilityMocker = webex.meetings.getReachability();
  
                sinon.stub(reachabilityMocker, 'gatherReachability').returns(true);
              });
              it('gets the reachability data instance from webex.meetings', () => {
                const reachability = webex.meetings.getReachability();
  
                assert.exists(reachability, 'reachability is defined because #setReachability has been called');
                assert.instanceOf(reachability, Reachability, 'should be a reachability instance');
              });
            });
          });
          describe('#getPersonalMeetingRoom', () => {
            it('should have #getPersonalMeetingRoom', () => {
              assert.exists(webex.meetings.getPersonalMeetingRoom);
            });
            it('gets the personal meeting room instance from webex.meetings', () => {
              const personalMeetingRoom = webex.meetings.getPersonalMeetingRoom();
  
              assert.exists(personalMeetingRoom, 'personal meeting room instance is set up at object creation');
              assert.instanceOf(personalMeetingRoom, PersonalMeetingRoom, 'should be a personal meeting room instance');
            });
          });
          describe('Static shortcut proxy methods', () => {
            describe('MeetingCollection getByKey proxies', () => {
              beforeEach(() => {
                webex.meetings.meetingCollection.getByKey = sinon.stub().returns(true);
              });
              it('should have #getMeetingByType', () => {
                assert.exists(webex.meetings.getMeetingByType);
              });
              describe('#getMeetingByType', () => {
                it('gets the Meeting instance from MeetingCollection using type and value', () => {
                  webex.meetings.getMeetingByType(test1, test2);
                  assert.calledOnce(webex.meetings.meetingCollection.getByKey);
                  assert.calledWith(webex.meetings.meetingCollection.getByKey, test1, test2);
                });
              });
            });
            describe('MeetingCollection getAll proxies', () => {
              beforeEach(() => {
                webex.meetings.meetingCollection.getAll = sinon.stub().returns(true);
              });
              it('should have #getAllMeetings', () => {
                assert.exists(webex.meetings.getAllMeetings);
              });
              describe('#getAllMeetings', () => {
                it('calls MeetingCollection to get all meetings with supplied options', () => {
                  webex.meetings.getAllMeetings({test: test1});
                  assert.calledOnce(webex.meetings.meetingCollection.getAll);
                  assert.calledWith(webex.meetings.meetingCollection.getAll, {test: test1});
                });
              });
            });
          });
        });
        describe('#syncMeetings', () => {
          it('should have #syncMeetings', () => {
            assert.exists(webex.meetings.syncMeetings);
          });
          describe('succesful requests', () => {
            beforeEach(() => {
              webex.meetings.request.getActiveMeetings = sinon.stub().returns(Promise.resolve({loci: [{url: url1}]}));
            });
            describe('when meeting is returned', () => {
              let parse;
  
              beforeEach(() => {
                parse = sinon.stub().returns(true);
                webex.meetings.meetingCollection.getByKey = sinon.stub().returns({locusInfo: {parse}});
              });
              it('tests the sync meeting calls for existing meeting', async () => {
                await webex.meetings.syncMeetings();
                assert.calledOnce(webex.meetings.request.getActiveMeetings);
                assert.calledOnce(webex.meetings.meetingCollection.getByKey);
                assert.calledOnce(parse);
                assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
              });
            });
            describe('when meeting is not returned', () => {
              let initialSetup;
  
              beforeEach(() => {
                initialSetup = sinon.stub().returns(true);
                webex.meetings.meetingCollection.getByKey = sinon.stub().returns(null);
                webex.meetings.create = sinon.stub().returns(Promise.resolve({locusInfo: {initialSetup}}));
              });
              it('tests the sync meeting calls for not existing meeting', async () => {
                await webex.meetings.syncMeetings();
                assert.calledOnce(webex.meetings.request.getActiveMeetings);
                assert.calledThrice(webex.meetings.meetingCollection.getByKey);
                assert.calledOnce(initialSetup);
                assert.calledOnce(webex.meetings.create);
                assert.calledWith(webex.meetings.request.getActiveMeetings);
                assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
                assert.calledWith(webex.meetings.create, {url: url1}, 'LOCUS_ID');
                assert.calledWith(initialSetup, {url: url1});
              });
            });
          });
        });
        describe('#create', () => {
          it('should have #create', () => {
            assert.exists(webex.meetings.create);
          });
          beforeEach(() => {
            webex.meetings.createMeeting = sinon.stub().returns(Promise.resolve({on: () => true}));
          });
          it('calls createMeeting and returns its promise', async () => {
            const create = webex.meetings.create(test1, test2);
  
            assert.exists(create.then);
            await create;
            assert.calledOnce(webex.meetings.createMeeting);
            assert.calledWith(webex.meetings.createMeeting, test1, test2);
          });
        });
      });
      describe('Private Detailed API and Helpers', () => {
        describe('#handleLocusMercury', () => {
          beforeEach(() => {
            webex.meetings.handleLocusEvent = sinon.stub().returns(true);
          });
          it('doesnt call handle locus mercury for a locus roap event', () => {
            webex.meetings.handleLocusMercury({data: {eventType: 'locus.message.roap'}});
            assert.notCalled(webex.meetings.handleLocusEvent);
          });
          it('doesnt call handle locus mercury for an undefined eventType', () => {
            webex.meetings.handleLocusMercury({data: {}});
            assert.notCalled(webex.meetings.handleLocusEvent);
          });
          it('calls handle locus mercury for all locus events', () => {
            webex.meetings.handleLocusMercury({data: {eventType: test1}});
            assert.calledOnce(webex.meetings.handleLocusEvent);
            assert.calledWith(webex.meetings.handleLocusEvent, {eventType: test1});
          });
        });
        describe('#handleLocusEvent', () => {
          describe('there was a meeting', () => {
            let parse;
  
            beforeEach(() => {
              parse = sinon.stub().returns(true);
              webex.meetings.meetingCollection.getByKey = sinon.stub().returns({locusInfo: {parse}});
            });
            it('should parse the meeting info', () => {
              webex.meetings.handleLocusEvent({locusUrl: url1});
              assert.calledOnce(webex.meetings.meetingCollection.getByKey);
              assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
              assert.calledOnce(parse);
              assert.calledWith(parse, {locusInfo: {parse}}, {locusUrl: url1});
            });
          });
          describe('there was not a meeting', () => {
            let initialSetup;
  
            beforeEach(() => {
              initialSetup = sinon.stub().returns(true);
              webex.meetings.meetingCollection.getByKey = sinon.stub().returns(undefined);
              webex.meetings.create = sinon.stub().returns(Promise.resolve({locusInfo: {initialSetup}}));
            });
            it('should setup the meeting by difference event', async () => {
              await webex.meetings.handleLocusEvent({locus: {id: uuid1, self: {callBackInfo: {callbackAddress: uri1}}}, eventType: 'locus.difference', locusUrl: url1});
              assert.calledThrice(webex.meetings.meetingCollection.getByKey);
              assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
              assert.calledOnce(initialSetup);
              assert.calledWith(initialSetup, {id: uuid1, self: {callBackInfo: {callbackAddress: uri1}}});
            });
            it('should setup the meeting by a not difference event', async () => {
              await webex.meetings.handleLocusEvent({locus: {id: uuid1, self: {callBackInfo: {callbackAddress: uri1}}}, eventType: test1, locusUrl: url1});
              assert.calledThrice(webex.meetings.meetingCollection.getByKey);
              assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
              assert.calledOnce(initialSetup);
              assert.calledWith(initialSetup, {id: uuid1, self: {callBackInfo: {callbackAddress: uri1}}});
            });
          });
        });
        describe('#createMeeting', () => {
          beforeEach(() => {
            MediaUtil.createPeerConnection = sinon.stub().returns(true);
            webex.internal.device.userId = uuid1;
            webex.internal.device.url = url1;
            MeetingCollection.set = sinon.stub().returns(true);
            MeetingsUtil.getMeetingAddedType = sinon.stub().returns('test');
            MeetingsUtil.extractDestination = sinon.stub().returns('test');
          });
          describe('successful MeetingInfo.#fetchMeetingInfo', () => {
            beforeEach(() => {
              webex.meetings.meetingInfo.fetchMeetingInfo = sinon.stub().returns(Promise.resolve(true));
            });
            it('creates the meeting from a successful meeting info fetch promise testing', async () => {
              const meeting = webex.meetings.createMeeting('test', 'test');
  
              assert.exists(meeting.then);
              await meeting;
              assert.calledOnce(webex.meetings.meetingInfo.fetchMeetingInfo);
              assert.calledOnce(MeetingsUtil.extractDestination);
              assert.calledOnce(MeetingsUtil.getMeetingAddedType);
              assert.calledOnce(TriggerProxy.trigger);
              assert.calledWith(webex.meetings.meetingInfo.fetchMeetingInfo, 'test');
              assert.calledWith(MeetingsUtil.extractDestination, 'test', 'test');
              assert.calledWith(MeetingsUtil.getMeetingAddedType, 'test');
            });
  
            it('creates the meeting from a successful meeting info fetch meeting resolve testing', async () => {
              const meeting = await webex.meetings.createMeeting('test', 'test');
  
              assert.instanceOf(meeting, Meeting, 'createMeeting should eventually resolve to a Meeting Object');
              assert.calledOnce(webex.meetings.meetingInfo.fetchMeetingInfo);
              assert.calledOnce(MeetingsUtil.extractDestination);
              assert.calledOnce(MeetingsUtil.getMeetingAddedType);
              assert.calledOnce(TriggerProxy.trigger);
              assert.calledWith(webex.meetings.meetingInfo.fetchMeetingInfo, 'test');
              assert.calledWith(MeetingsUtil.extractDestination, 'test', 'test');
              assert.calledWith(MeetingsUtil.getMeetingAddedType, 'test');
              assert.calledWith(TriggerProxy.trigger, sinon.match.instanceOf(Meetings), {file: 'meetings', function: 'createMeeting'}, 'meeting:added', {meeting: sinon.match.instanceOf(Meeting), type: 'test'});
            });
          });
          describe('rejected MeetingInfo.#fetchMeetingInfo', () => {
            beforeEach(() => {
              console.error = sinon.stub().returns(false);
              webex.meetings.meetingInfo.fetchMeetingInfo = sinon.stub().returns(Promise.reject(new Error('test')));
            });
            it('creates the meeting from a rejected meeting info fetch', async () => {
              const meeting = await webex.meetings.createMeeting('test', 'test');
  
              assert.instanceOf(meeting, Meeting, 'createMeeting should eventually resolve to a Meeting Object');
              assert.calledOnce(webex.meetings.meetingInfo.fetchMeetingInfo);
              assert.calledOnce(MeetingsUtil.extractDestination);
              assert.calledOnce(MeetingsUtil.getMeetingAddedType);
              assert.calledOnce(TriggerProxy.trigger);
              assert.calledWith(webex.meetings.meetingInfo.fetchMeetingInfo, 'test');
              assert.calledWith(MeetingsUtil.extractDestination, 'test', 'test');
              assert.calledWith(MeetingsUtil.getMeetingAddedType, 'test');
              assert.calledWith(TriggerProxy.trigger, sinon.match.instanceOf(Meetings), {file: 'meetings', function: 'createMeeting'}, 'meeting:added', {meeting: sinon.match.instanceOf(Meeting), type: 'test'});
            });
          });
        });
      });
      describe('Public Event Triggers', () => {
        describe('#destroy', () => {
          it('should have #destroy', () => {
            assert.exists(webex.meetings.destroy);
          });
          beforeEach(() => {
            webex.meetings.meetingCollection.delete = sinon.stub().returns(true);
          });
          describe('correctly established meeting', () => {
            it('tests the destroy removal from the collection', () => {
              const response = webex.meetings.destroy(uuid1, test1);
  
              assert.calledOnce(webex.meetings.meetingCollection.delete);
              assert.calledWith(webex.meetings.meetingCollection.delete, uuid1);
              assert.equal(response, test1);
              assert.calledOnce(TriggerProxy.trigger);
              assert.calledWith(TriggerProxy.trigger, sinon.match.instanceOf(Meetings), {file: 'meetings', function: 'destroy'}, 'meeting:removed', {meetingId: uuid1, response: test1});
            });
          });
        });
      });
    });
  });
  