<commit_before>import * as mock from 'ringcentral-integration/integration-test/mock';
import { CallCtrlPage } from 'ringcentral-widgets/containers/CallCtrlPage';
import MergeInfo from 'ringcentral-widgets/components/ActiveCallPanel/MergeInfo';
import CallAvatar from 'ringcentral-widgets/components/CallAvatar';
import DurationCounter from 'ringcentral-widgets/components/DurationCounter';
import calleeTypes from 'ringcentral-integration/enums/calleeTypes';
import sessionStatus from 'ringcentral-integration/modules/Webphone/sessionStatus';
import ActiveCallPad from 'ringcentral-widgets/components/ActiveCallPad/';
import ActiveCallButton from 'ringcentral-widgets/components/ActiveCallButton';
import CombinIcon from 'ringcentral-widgets/assets/images/Combine.svg';
import Answer from 'ringcentral-widgets/assets/images/Answer.svg';
import CircleButton from 'ringcentral-widgets/components/CircleButton';
import FromField from 'ringcentral-widgets/components/FromField';
import BackHeader from 'ringcentral-widgets/components/BackHeader';
import BackButton from 'ringcentral-widgets/components/BackButton';
import RecipientsInput from 'ringcentral-widgets/components/RecipientsInput';
import ContactDropdownList from 'ringcentral-widgets/components/ContactDropdownList';
import ContactItem from 'ringcentral-widgets/components/ContactItem';
import LinkLine from 'ringcentral-widgets/components/LinkLine';
import DropdownSelect from 'ringcentral-widgets/components/DropdownSelect';
import deviceBody from './data/device';
import activeCallsBody from './data/activeCalls';
import extensionListBody from './data/extension';
import conferenceCallBody from './data/conferenceCall';
import conferenceCallBringInBody from './data/conferenceCallBringIn';
import incomingResponse from './data/incomingResponse';
import { getWrapper, timeout } from '../shared';
import {
  mockGeneratePresenceApi,
  mockGeneratePresenceUpdateApi,
  mockGenerateActiveCallsApi,
  mockPubnub,
  generateActiveCallsData
} from './helper.js';

let wrapper = null;
let phone = null;

beforeEach(async () => {
  jasmine.DEFAULT_TIMEOUT_INTERVAL = 64000;
  wrapper = await getWrapper();
  phone = wrapper.props().phone;
  phone.webphone._createWebphone();
  phone.webphone._removeWebphone = () => { };
  phone.webphone._connect = () => { };

  Object.defineProperties(wrapper.props().phone.audioSettings, {
    userMedia: { value: true },
  });
});

async function call({
  phoneNumber,
  fromNumber
}) {
  mock.numberParser();
  mock.device(deviceBody, false);
  await phone.dialerUI.call({ phoneNumber, fromNumber });
  await timeout(500);
  wrapper.update();
  const currentSessionId = phone.webphone.activeSession.id;
  const currentSession = await phone.webphone._sessions.get(currentSessionId);
  currentSession.accept(incomingResponse);
}

async function mockSub(ttl = 100) {
  const activeCalls = generateActiveCallsData(phone.webphone.sessions);
  mockGeneratePresenceApi({
    activeCalls
  });
  mockGeneratePresenceUpdateApi({
    activeCalls
  });
  mockGenerateActiveCallsApi({
    sessions: phone.webphone.sessions
  });
  await phone.subscription.subscribe(['/account/~/extension/~/presence'], 10);
  await timeout(ttl);
  await mockPubnub({
    activeCalls
  });
}

async function mockAddCall(contactA, contactB) {
  await call({
    phoneNumber: contactA.phoneNumbers[0].phoneNumber
  });
  const sessionA = phone.webphone.sessions[0];
  await phone.webphone.hold(sessionA.id);
  const callCtrlPage = wrapper.find(CallCtrlPage);
  await callCtrlPage.props().onAdd(sessionA.id);
  await call({
    phoneNumber: contactB.phoneNumbers[0].phoneNumber,
    fromNumber: contactB.phoneNumbers[0].phoneNumber,
  });
  await mockSub();
  wrapper.update();
  await timeout(1000);
}

async function mockContacts() {
  mock.extensionList(extensionListBody);
  await phone.accountExtension.fetchData();
}
async function mockStartConference() {
  // HACK: `updateConference` should be mock at mockForLogin func.
  // mock.updateConferenceCall(conferenceUpdate.id, conferenceUpdate);
  mock.conferenceCallBringIn(conferenceCallBody.id);
  mock.terminateConferenceCall(conferenceCallBody.id);
  mock.conferenceCall();
  let contactA;
  let contactB;
  await mockContacts();
  contactA = phone.contacts.allContacts.find(item => item.type === 'company');
  contactB = phone.contacts.allContacts.find(item => item.type === 'company');
  await mockAddCall(contactA, contactB);
  expect(phone.routerInteraction.currentPath).toEqual('/calls/active');
  wrapper.update();
  const callCtrlPage = wrapper.find(CallCtrlPage);
  const sessionId = phone.webphone.activeSession.id;
  callCtrlPage.props().onMerge(sessionId);
  const fromSessionId = phone.conferenceCall.state.mergingPair.fromSessionId;
  const fromSession = phone.webphone._sessions.get(fromSessionId);
  const toSessionId = phone.conferenceCall.state.mergingPair.toSessionId;
  const toSession = phone.webphone._sessions.get(toSessionId);
  toSession.terminate();
  fromSession.terminate();
  await timeout(1000);
  toSession.reject();
  fromSession.reject();
  await timeout(1000);
  const conferenceSessionId = Object.values(phone.conferenceCall.conferences)[0].sessionId;
  const conferenceSession = phone.webphone._sessions.get(conferenceSessionId);
  conferenceSession.accept();
  await timeout(2000);
  wrapper.update();
}
describe('RCI-1071: simplified call control page #3', () => {
  let contactA = null;
  let contactB = null;

  test('#1 Check the Simplified Call control page'
    , async () => {
      // Prepare: Contacts has a internal contact with avatar and a external contact without avatar
      await mockContacts();
      contactA = phone.contacts.allContacts.find(item => item.type === 'company' && item.hasProfileImage);
      contactB = phone.contacts.allContacts.find(item => item.type === 'personal' && !item.hasProfileImage);

      await mockAddCall(contactA, contactB);
      expect(phone.routerInteraction.currentPath).toEqual('/calls/active');
      await timeout(3000);
      const mergeInfo = wrapper.find(MergeInfo);
      expect(mergeInfo).toHaveLength(1);

      const callAvatarA = mergeInfo.find(CallAvatar).at(0);
      const callAvatarB = mergeInfo.find(CallAvatar).at(1);
      // TODO: mock contactsA's data
      // expect(callAvatar.props().avatarUrl).toEqual('avatarUrl');
      expect(mergeInfo.find('.callee_name').text()).toEqual(contactA.name);
      expect(mergeInfo.find('.callee_status').text()).toEqual('On Hold');
      expect(callAvatarB.props().avatarUrl).toBeNull();
      expect(mergeInfo.find('.callee_name_active').text()).toEqual('Unknown');
      expect(mergeInfo.find(DurationCounter)).toHaveLength(1);
    });
  test('#2 Contact A hangs up the call', async () => {
    await mockContacts();
    contactA = phone.contacts.allContacts.find(item => item.type === 'company' && item.hasProfileImage);
    contactB = phone.contacts.allContacts.find(item => item.type === 'personal' && !item.hasProfileImage);
    await mockAddCall(contactA, contactB);
    const sessionId = phone.webphone.sessions[1].id;
    const sessionA = phone.webphone._sessions.get(sessionId);
    sessionA.terminate();
    wrapper.update();
    await timeout(3000);

    const mergeInfo = wrapper.find(MergeInfo);
    expect(mergeInfo).toHaveLength(1);

    const callAvatarA = mergeInfo.find(CallAvatar).at(0);
    const callAvatarB = mergeInfo.find(CallAvatar).at(1);
    const domCalleeStatus = mergeInfo.find('.callee_status');
    // TODO: mock contactsA's data
    // expect(callAvatarA.props().avatarUrl).toEqual('');
    expect(mergeInfo.find('.callee_name').text()).toEqual(contactA.name);
    expect(domCalleeStatus.text()).toEqual('Disconnected');
    expect(domCalleeStatus.props().className).toContain('callee_status_disconnected');
    expect(callAvatarB.props().avatarUrl).toBeNull();
    expect(mergeInfo.find('.callee_name_active').text()).toEqual('Unknown');
    expect(mergeInfo.find(DurationCounter)).toHaveLength(1);
  });
  test('#3 && #4 user makes a conference call then make an outbound call, then hangup', async () => {
    await mockStartConference();
    const conferenceSessionId = Object.values(phone.conferenceCall.conferences)[0].sessionId;
    const conferenceSession = phone.webphone._sessions.get(conferenceSessionId);
    const conferenceId = Object.values(phone.conferenceCall.conferences)[0].conference.id;
    expect(phone.routerInteraction.currentPath).toEqual('/calls/active');
    const callCtrlPage = wrapper.find(CallCtrlPage);
    callCtrlPage.props().onAdd(conferenceSessionId);
    await timeout(500);
    wrapper.update();
    expect(phone.routerInteraction.currentPath).toEqual(`/conferenceCall/dialer/${conferenceSession.fromNumber}/${conferenceSession.id}`);
    call({
      phoneNumber: contactA.phoneNumbers[0].phoneNumber,
    });
    await timeout(1000);
    await mockSub(1000);
    await timeout(1000);
    expect(phone.routerInteraction.currentPath).toEqual('/calls/active');<commit_msg>test(ActiveCallPanel.spec.js): fix router validation (#1152)<commit_after>import * as mock from 'ringcentral-integration/integration-test/mock';
import { CallCtrlPage } from 'ringcentral-widgets/containers/CallCtrlPage';
import MergeInfo from 'ringcentral-widgets/components/ActiveCallPanel/MergeInfo';
import CallAvatar from 'ringcentral-widgets/components/CallAvatar';
import DurationCounter from 'ringcentral-widgets/components/DurationCounter';
import calleeTypes from 'ringcentral-integration/enums/calleeTypes';
import sessionStatus from 'ringcentral-integration/modules/Webphone/sessionStatus';
import ActiveCallPad from 'ringcentral-widgets/components/ActiveCallPad/';
import ActiveCallButton from 'ringcentral-widgets/components/ActiveCallButton';
import CombinIcon from 'ringcentral-widgets/assets/images/Combine.svg';
import Answer from 'ringcentral-widgets/assets/images/Answer.svg';
import CircleButton from 'ringcentral-widgets/components/CircleButton';
import FromField from 'ringcentral-widgets/components/FromField';
import BackHeader from 'ringcentral-widgets/components/BackHeader';
import BackButton from 'ringcentral-widgets/components/BackButton';
import RecipientsInput from 'ringcentral-widgets/components/RecipientsInput';
import ContactDropdownList from 'ringcentral-widgets/components/ContactDropdownList';
import ContactItem from 'ringcentral-widgets/components/ContactItem';
import LinkLine from 'ringcentral-widgets/components/LinkLine';
import DropdownSelect from 'ringcentral-widgets/components/DropdownSelect';
import deviceBody from './data/device';
import activeCallsBody from './data/activeCalls';
import extensionListBody from './data/extension';
import conferenceCallBody from './data/conferenceCall';
import conferenceCallBringInBody from './data/conferenceCallBringIn';
import incomingResponse from './data/incomingResponse';
import { getWrapper, timeout } from '../shared';
import {
  mockGeneratePresenceApi,
  mockGeneratePresenceUpdateApi,
  mockGenerateActiveCallsApi,
  mockPubnub,
  generateActiveCallsData
} from './helper.js';

let wrapper = null;
let phone = null;

beforeEach(async () => {
  jasmine.DEFAULT_TIMEOUT_INTERVAL = 64000;
  wrapper = await getWrapper();
  phone = wrapper.props().phone;
  phone.webphone._createWebphone();
  phone.webphone._removeWebphone = () => { };
  phone.webphone._connect = () => { };

  Object.defineProperties(wrapper.props().phone.audioSettings, {
    userMedia: { value: true },
  });
});

async function call({
  phoneNumber,
  fromNumber
}) {
  mock.numberParser();
  mock.device(deviceBody, false);
  await phone.dialerUI.call({ phoneNumber, fromNumber });
  await timeout(500);
  wrapper.update();
  const currentSessionId = phone.webphone.activeSession.id;
  const currentSession = await phone.webphone._sessions.get(currentSessionId);
  currentSession.accept(incomingResponse);
}

async function mockSub(ttl = 100) {
  const activeCalls = generateActiveCallsData(phone.webphone.sessions);
  mockGeneratePresenceApi({
    activeCalls
  });
  mockGeneratePresenceUpdateApi({
    activeCalls
  });
  mockGenerateActiveCallsApi({
    sessions: phone.webphone.sessions
  });
  await phone.subscription.subscribe(['/account/~/extension/~/presence'], 10);
  await timeout(ttl);
  await mockPubnub({
    activeCalls
  });
}

async function mockAddCall(contactA, contactB) {
  await call({
    phoneNumber: contactA.phoneNumbers[0].phoneNumber
  });
  const sessionA = phone.webphone.sessions[0];
  await phone.webphone.hold(sessionA.id);
  const callCtrlPage = wrapper.find(CallCtrlPage);
  await callCtrlPage.props().onAdd(sessionA.id);
  await call({
    phoneNumber: contactB.phoneNumbers[0].phoneNumber,
    fromNumber: contactB.phoneNumbers[0].phoneNumber,
  });
  await mockSub();
  wrapper.update();
  await timeout(1000);
}

async function mockContacts() {
  mock.extensionList(extensionListBody);
  await phone.accountExtension.fetchData();
}
async function mockStartConference() {
  // HACK: `updateConference` should be mock at mockForLogin func.
  // mock.updateConferenceCall(conferenceUpdate.id, conferenceUpdate);
  mock.conferenceCallBringIn(conferenceCallBody.id);
  mock.terminateConferenceCall(conferenceCallBody.id);
  mock.conferenceCall();
  let contactA;
  let contactB;
  await mockContacts();
  contactA = phone.contacts.allContacts.find(item => item.type === 'company');
  contactB = phone.contacts.allContacts.find(item => item.type === 'company');
  await mockAddCall(contactA, contactB);
  expect(phone.routerInteraction.currentPath).toEqual('/calls/active');
  wrapper.update();
  const callCtrlPage = wrapper.find(CallCtrlPage);
  const sessionId = phone.webphone.activeSession.id;
  callCtrlPage.props().onMerge(sessionId);
  const fromSessionId = phone.conferenceCall.state.mergingPair.fromSessionId;
  const fromSession = phone.webphone._sessions.get(fromSessionId);
  const toSessionId = phone.conferenceCall.state.mergingPair.toSessionId;
  const toSession = phone.webphone._sessions.get(toSessionId);
  toSession.terminate();
  fromSession.terminate();
  await timeout(1000);
  toSession.reject();
  fromSession.reject();
  await timeout(1000);
  const conferenceSessionId = Object.values(phone.conferenceCall.conferences)[0].sessionId;
  const conferenceSession = phone.webphone._sessions.get(conferenceSessionId);
  conferenceSession.accept();
  await timeout(2000);
  wrapper.update();
}
describe('RCI-1071: simplified call control page #3', () => {
  let contactA = null;
  let contactB = null;

  test('#1 Check the Simplified Call control page'
    , async () => {
      // Prepare: Contacts has a internal contact with avatar and a external contact without avatar
      await mockContacts();
      contactA = phone.contacts.allContacts.find(item => item.type === 'company' && item.hasProfileImage);
      contactB = phone.contacts.allContacts.find(item => item.type === 'personal' && !item.hasProfileImage);

      await mockAddCall(contactA, contactB);
      expect(phone.routerInteraction.currentPath).toEqual('/calls/active');
      await timeout(3000);
      const mergeInfo = wrapper.find(MergeInfo);
      expect(mergeInfo).toHaveLength(1);

      const callAvatarA = mergeInfo.find(CallAvatar).at(0);
      const callAvatarB = mergeInfo.find(CallAvatar).at(1);
      // TODO: mock contactsA's data
      // expect(callAvatar.props().avatarUrl).toEqual('avatarUrl');
      expect(mergeInfo.find('.callee_name').text()).toEqual(contactA.name);
      expect(mergeInfo.find('.callee_status').text()).toEqual('On Hold');
      expect(callAvatarB.props().avatarUrl).toBeNull();
      expect(mergeInfo.find('.callee_name_active').text()).toEqual('Unknown');
      expect(mergeInfo.find(DurationCounter)).toHaveLength(1);
    });
  test('#2 Contact A hangs up the call', async () => {
    await mockContacts();
    contactA = phone.contacts.allContacts.find(item => item.type === 'company' && item.hasProfileImage);
    contactB = phone.contacts.allContacts.find(item => item.type === 'personal' && !item.hasProfileImage);
    await mockAddCall(contactA, contactB);
    const sessionId = phone.webphone.sessions[1].id;
    const sessionA = phone.webphone._sessions.get(sessionId);
    sessionA.terminate();
    wrapper.update();
    await timeout(3000);

    const mergeInfo = wrapper.find(MergeInfo);
    expect(mergeInfo).toHaveLength(1);

    const callAvatarA = mergeInfo.find(CallAvatar).at(0);
    const callAvatarB = mergeInfo.find(CallAvatar).at(1);
    const domCalleeStatus = mergeInfo.find('.callee_status');
    // TODO: mock contactsA's data
    // expect(callAvatarA.props().avatarUrl).toEqual('');
    expect(mergeInfo.find('.callee_name').text()).toEqual(contactA.name);
    expect(domCalleeStatus.text()).toEqual('Disconnected');
    expect(domCalleeStatus.props().className).toContain('callee_status_disconnected');
    expect(callAvatarB.props().avatarUrl).toBeNull();
    expect(mergeInfo.find('.callee_name_active').text()).toEqual('Unknown');
    expect(mergeInfo.find(DurationCounter)).toHaveLength(1);
  });
  test('#3 && #4 user makes a conference call then make an outbound call, then hangup', async () => {
    await mockStartConference();
    const conferenceSessionId = Object.values(phone.conferenceCall.conferences)[0].sessionId;
    const conferenceSession = phone.webphone._sessions.get(conferenceSessionId);
    const conferenceId = Object.values(phone.conferenceCall.conferences)[0].conference.id;
    expect(phone.routerInteraction.currentPath.indexOf('/calls/active')).toEqual(0);
    const callCtrlPage = wrapper.find(CallCtrlPage);
    callCtrlPage.props().onAdd(conferenceSessionId);
    await timeout(500);
    wrapper.update();
    expect(phone.routerInteraction.currentPath).toEqual(`/conferenceCall/dialer/${conferenceSession.fromNumber}/${conferenceSession.id}`);
    call({
      phoneNumber: contactA.phoneNumbers[0].phoneNumber,
    });
    await timeout(1000);
    await mockSub(1000);
    await timeout(1000);
    expect(phone.routerInteraction.currentPath).toEqual('/calls/active');
{'fraction_non_alphanumeric': 0.12955174322080798, 'fraction_numerical': 0.008909795240730493, 'mean_word_length': 5.35407876230661, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4159833', 'n_tokens_mistral': 5426, 'n_tokens_neox': 5296, 'n_words': 935}