/* globals ConferenceGroupHandler, FontSizeManager, HandledCall, l10nAssert, MockCall, MockCallScreen, MockCallsHandler, MockContactPhotoHelper, MockContacts, MockFontSizeUtils, MockL10n, MockNavigatorMozIccManager, MockNavigatorSettings, MocksHelper, MockTonePlayer, MockUtils, MockVoicemail */ 'use strict'; require('/shared/test/unit/mocks/mock_navigator_moz_settings.js'); require('/shared/test/unit/mocks/mock_audio.js'); require('/shared/test/unit/mocks/mock_contact_photo_helper.js'); require('/shared/test/unit/mocks/mock_font_size_utils.js'); require('/shared/test/unit/mocks/mock_l10n.js'); require('/shared/test/unit/mocks/mock_navigator_moz_icc_manager.js'); require('/shared/test/unit/mocks/dialer/mock_contacts.js'); require('/shared/test/unit/mocks/dialer/mock_keypad.js'); require('/shared/test/unit/mocks/dialer/mock_utils.js'); require('/shared/test/unit/mocks/dialer/mock_call.js'); require('/shared/test/unit/mocks/dialer/mock_calls_handler.js'); require('/shared/test/unit/mocks/dialer/mock_tone_player.js'); require('/shared/test/unit/mocks/dialer/mock_font_size_manager.js'); require('/shared/test/unit/mocks/mock_voicemail.js'); require('/test/unit/mock_call_screen.js'); require('/test/unit/mock_conference_group_handler.js'); require('/js/handled_call.js'); var mocksHelperForHandledCall = new MocksHelper([ 'Audio', 'AudioContext', 'Contacts', 'CallScreen', 'ConferenceGroupHandler', 'CallsHandler', 'FontSizeUtils', 'KeypadManager', 'Utils', 'ContactPhotoHelper', 'TonePlayer', 'FontSizeManager', 'Voicemail' ]).init(); suite('dialer/handled_call', function() { var realMozL10n; var realNavigatorSettings; var realMozIccManager; const VOICEMAIL_NUMBER = '123'; var subject; var mockCall; var templates; var phoneNumber; var photoFullResolution; var photoThumbnail; mocksHelperForHandledCall.attachTestHelpers(); suiteSetup(function() { realMozL10n = navigator.l10n; navigator.mozL10n = MockL10n; realNavigatorSettings = navigator.mozSettings; navigator.mozSettings = MockNavigatorSettings; realMozIccManager = navigator.mozIccManager; navigator.mozIccManager = MockNavigatorMozIccManager; phoneNumber = Math.floor(Math.random() * 10000); templates = document.createElement('div'); templates.innerHTML = ``; document.body.appendChild(templates); }); suiteTeardown(function() { templates.parentNode.removeChild(templates); navigator.mozSettings = realNavigatorSettings; navigator.mozIccManager = realMozIccManager; navigator.mozL10n = realMozL10n; }); setup(function() { photoFullResolution = new Blob(); photoThumbnail = new Blob(); this.sinon.stub(MockContactPhotoHelper, 'getFullResolution').returns(photoFullResolution); this.sinon.stub(MockContactPhotoHelper, 'getThumbnail').returns(photoThumbnail); this.sinon.stub(MockFontSizeUtils, 'getMaxFontSizeInfo').returns({ fontSize: 1.0 }); this.sinon.useFakeTimers(Date.now()); mockCall = new MockCall(String(phoneNumber), 'dialing'); subject = new HandledCall(mockCall); MockVoicemail.mResolvePromise(false); document.body.appendChild(subject.node); }); teardown(function() { MockNavigatorMozIccManager.mTeardown(); var node = subject.node; if (node && node.parentNode) { node.parentNode.removeChild(node); } }); suite('initialization', function() { setup(function() { this.sinon.spy(MockCallsHandler, 'updatePlaceNewCall'); }); test('full resolution photo', function() { assert.equal(subject.photo, photoFullResolution); }); test('should set caller image by contact photo', function() { assert.isTrue(MockCallScreen.mSetCallerContactImageCalled); }); test('call', function() { assert.equal(subject.call, mockCall); }); test('call event listener', function() { assert.equal(mockCall._eventListeners.statechange.length, 1); }); test('CallsHandler.updatePlaceNewCall added as call state listener', function() { subject.call.mChangeState(); sinon.assert.calledOnce(MockCallsHandler.updatePlaceNewCall); }); suite('node', function() { test('should not have an id', function() { assert.equal(subject.node.id, ''); }); test('should have the handled-call class', function() { assert.isTrue(subject.node.classList.contains('handled-call')); }); test('should not be hidden', function() { assert.isFalse(subject.node.hidden); }); test('should have a numberNode in a numberWrapper', function() { var numberNode = subject.node.querySelector('.numberWrapper .number bdi'); assert.equal(subject.numberNode, numberNode); }); test('should have an outerNode in a numberWrapper', function() { var outerNode = subject.node.querySelector('.numberWrapper .number'); assert.equal(subject.outerNode, outerNode); }); test('should have an additionalContactTel node', function() { var additionalTelNode = subject.node.querySelector('.additionalContactInfo .tel'); assert.equal(subject.additionalTelNode, additionalTelNode); }); test('should have an additionalContactTelType node', function() { var additionalTelTypeNode = subject.node.querySelector('.additionalContactInfo .tel-type'); assert.equal(subject.additionalTelTypeNode, additionalTelTypeNode); }); test('should have a duration node', function() { var durationNode = subject.node.querySelector('.duration'); assert.equal(subject.durationNode, durationNode); }); test('should have a duration child node', function() { var durationChildNode = subject.node.querySelector('.duration span'); assert.equal(subject.durationChildNode, durationChildNode); assert.isTrue(durationChildNode.classList.contains('font-light')); }); }); test('duration outgoing', function() { assert.ok(subject.durationChildNode); l10nAssert(subject.durationChildNode, 'connecting'); }); test('duration incoming', function() { mockCall = new MockCall('888', 'incoming'); subject = new HandledCall(mockCall); MockVoicemail.mResolvePromise(false); assert.ok(subject.durationChildNode); l10nAssert(subject.durationChildNode, 'incoming'); }); test('number', function() { assert.ok(subject.numberNode); assert.equal(MockContacts.mCalledWith, mockCall.id.number); }); test('initial state', function() { assert.equal(subject._initialState, 'dialing'); }); test('support for calls already connected at init', function() { mockCall = new MockCall(String(phoneNumber), 'connected'); subject = new HandledCall(mockCall); MockVoicemail.mResolvePromise(false); assert.isFalse(subject.node.hidden); assert.isTrue(subject.node.classList.contains('ongoing')); }); suite('stk call', function() { var reqStub, settingsSetSpy; var contactLookupSpy, tel, contact; setup(function() { reqStub = { onsuccess: null, result: { 'icc.callmessage': 'stk second alpha identifier' } }; settingsSetSpy = this.sinon.spy(); var newCreateLock = function() { return { get: function() { return reqStub; }, set: settingsSetSpy }; }; this.sinon.stub(navigator.mozSettings, 'createLock', newCreateLock); tel = { value: '666666666', carrier: 'carrier', type: 'type' }; contact = { id: 666, name: ['from contact lookup'], tel: [tel] }; contactLookupSpy = this.sinon.spy(MockContacts, 'findByNumber'); mockCall = new MockCall(String(phoneNumber), 'dialing'); subject = new HandledCall(mockCall); MockVoicemail.mResolvePromise(false); }); test('should display the icc call message', function() { contactLookupSpy.yield(contact, tel, false); reqStub.onsuccess(); assert.equal(subject.numberNode.textContent, 'stk second alpha identifier'); }); test('should clear the icc call message setting', function() { reqStub.onsuccess(); assert.isTrue(settingsSetSpy.calledOnce); assert.isTrue(settingsSetSpy.calledWith({'icc.callmessage': null})); }); test('should not let the contact lookup override the number', function() { reqStub.onsuccess(); contactLookupSpy.yield(contact, tel, false); assert.equal(subject.numberNode.textContent, 'stk second alpha identifier'); }); }); }); suite('on connect', function() { setup(function() { this.sinon.spy(MockCallsHandler, 'updatePlaceNewCall'); this.sinon.spy(MockCallsHandler, 'updateMergeAndOnHoldStatus'); this.sinon.spy(MockCallsHandler, 'updateMuteAndSpeakerStatus'); mockCall._connect(); }); test('show the node', function() { assert.isFalse(subject.node.hidden); }); test('ensure the callscreen in connected mode', function() { assert.equal(MockCallScreen.mLastRenderMode, 'connected'); }); test('start the timer', function() { assert.isTrue(MockCallScreen.mCalledCreateTicker); }); test('sync speaker', function() { assert.isTrue(MockCallScreen.mSyncSpeakerCalled); }); test('photo displaying', function() { assert.isTrue(MockCallScreen.mSetCallerContactImageCalled); }); test('should set contact picture', function() { this.sinon.stub(MockCallScreen, 'setCallerContactImage'); mockCall._connect(); sinon.assert.calledOnce(MockCallScreen.setCallerContactImage); }); suite('in a group', function() { setup(function() { MockCallScreen.mSetCallerContactImageCalled = false; mockCall.group = {}; mockCall._connect(); }); test('contact image updated', function() { assert.isTrue(MockCallScreen.mSetCallerContactImageCalled); }); }); test('primary contact info', function() { assert.isTrue(MockUtils.mCalledGetPhoneNumberPrimaryInfo); }); test('mute initially off', function() { assert.isFalse(MockCallScreen.mMuteOn); }); test('speaker initially off', function() { assert.isFalse(MockCallScreen.mSpeakerOn); }); test('the place new call button status is updated', function() { sinon.assert.calledOnce(MockCallsHandler.updatePlaceNewCall); }); test('the merge and on hold buttons status is updated', function() { sinon.assert.calledOnce(MockCallsHandler.updateMergeAndOnHoldStatus); }); test('the mute and speaker buttons\' status is updated', function() { sinon.assert.calledOnce(MockCallsHandler.updateMuteAndSpeakerStatus); }); }); suite('on disconnect', function() { var node; setup(function() { node = subject.node; }); suite('from a regular call', function() { setup(function() { mockCall._connect(); MockCallScreen.mute(); MockCallScreen.switchToSpeaker(); }); test('should show call ended', function() { mockCall._disconnect(); l10nAssert(subject.node.querySelector('.duration span'), 'callEnded'); }); test('should not show the total call duration', function() { subject.node.querySelector('.duration span').textContent = 'Incoming'; mockCall._disconnect(); assert.equal(subject.node.querySelector('.total-duration').textContent, ''); }); test('should show the total call duration', function() { var totalCallDuration = '12:34'; subject.node.querySelector('.duration span').textContent = totalCallDuration; mockCall._disconnect(); assert.equal(subject.node.querySelector('.total-duration').textContent, totalCallDuration); }); test('should remove listener on the call', function() { this.sinon.spy(mockCall, 'removeEventListener'); mockCall._disconnect(); sinon.assert.calledWith( mockCall.removeEventListener, 'statechange', subject); mockCall.removeEventListener.restore(); }); test('should keep the call', function() { mockCall._disconnect(); assert.ok(subject.call); }); test('should nullify the photo', function() { mockCall._disconnect(); assert.isNull(subject.photo); }); test('should clear the ticker', function() { mockCall._disconnect(); assert.isTrue(MockCallScreen.mCalledStopTicker); }); test('should remove the node from the dom', function() { assert.isFalse(MockCallScreen.mRemoveCallCalled); mockCall._disconnect(); //check that the node is not immediately removed from DOM. assert.isFalse(MockCallScreen.mRemoveCallCalled); this.sinon.clock.tick(MockCallScreen.callEndPromptTime); assert.isTrue(MockCallScreen.mRemoveCallCalled); }); test('should nullify the node', function() { mockCall._disconnect(); assert.isNotNull(subject.node); this.sinon.clock.tick(MockCallScreen.callEndPromptTime); assert.isNull(subject.node); }); test('it does not show the banner', function() { assert.isFalse(MockCallScreen.mShowStatusMessageCalled); }); test('end call tone should be played', function() { var playSpy = this.sinon.spy(MockTonePlayer, 'playSequence'); mockCall._disconnect(); assert.isTrue(playSpy.calledWith([[480, 620, 250]])); }); test('the place new call button status is updated', function() { this.sinon.spy(MockCallsHandler, 'updatePlaceNewCall'); mockCall._disconnect(); sinon.assert.calledOnce(MockCallsHandler.updatePlaceNewCall); }); test('the merge and on hold buttons status is updated', function() { this.sinon.spy(MockCallsHandler, 'updateMergeAndOnHoldStatus'); mockCall._disconnect(); sinon.assert.calledOnce(MockCallsHandler.updateMergeAndOnHoldStatus); }); test('the mute and speaker buttons\' status is updated', function() { this.sinon.spy(MockCallsHandler, 'updateMuteAndSpeakerStatus'); mockCall._disconnect(); sinon.assert.calledOnce(MockCallsHandler.updateMuteAndSpeakerStatus); }); }); suite('from a group', function() { setup(function() { this.sinon.spy(MockCallScreen, 'showStatusMessage'); mockCall._connect(); MockCallScreen.mute(); MockCallScreen.switchToSpeaker(); mockCall.group = null; mockCall.mChangeState('disconnecting'); mockCall.ongroupchange(mockCall); mockCall._disconnect(); }); test('show the banner', function() { sinon.assert.calledWithMatch( MockCallScreen.showStatusMessage, { id: 'caller-left-call', args: { caller: ['test name'] } } ); }); }); suite('the call was not connected', function() { test('end call tone is not played', function() { var playSpy = this.sinon.spy(MockTonePlayer, 'playSequence'); mockCall._disconnect(); assert.isFalse(playSpy.called); }); }); }); suite('on hold', function() { setup(function() { this.sinon.spy(MockCallsHandler, 'updatePlaceNewCall'); this.sinon.spy(MockCallsHandler, 'updateMergeAndOnHoldStatus'); this.sinon.spy(MockCallsHandler, 'updateMuteAndSpeakerStatus'); mockCall._hold(); }); test('show the node', function() { assert.isFalse(subject.node.hidden); }); test('put the callscreen in connected-hold mode', function() { assert.equal(MockCallScreen.mLastRenderMode, 'connected-hold'); }); test('mute is off', function() { assert.isFalse(MockCallScreen.mMuteOn); }); test('speaker is off', function() { assert.isFalse(MockCallScreen.mSpeakerOn); }); test('the place new call button status is updated', function() { sinon.assert.calledOnce(MockCallsHandler.updatePlaceNewCall); }); test('the merge and on hold buttons status is updated', function() { sinon.assert.calledOnce(MockCallsHandler.updateMergeAndOnHoldStatus); }); test('the mute and speaker buttons\' status is updated', function() { sinon.assert.calledOnce(MockCallsHandler.updateMuteAndSpeakerStatus); }); }); suite('call direction', function() { suite('outgoing call', function() { setup(function() { mockCall = new MockCall('888', 'outgoing'); subject = new HandledCall(mockCall); MockVoicemail.mResolvePromise(false); }); test('before and after connexion', function() { assert.isTrue(subject.node.classList.contains('outgoing')); assert.isFalse(subject.node.classList.contains('ongoing')); mockCall._connect(); assert.isTrue(subject.node.classList.contains('ongoing')); assert.isTrue(subject.node.classList.contains('outgoing')); assert.isTrue(subject.node.hasAttribute('data-l10n-id')); l10nAssert(subject.node, 'outgoing_screen_reader'); }); }); suite('incoming call', function() { setup(function() { mockCall = new MockCall('888', 'incoming'); subject = new HandledCall(mockCall); MockVoicemail.mResolvePromise(false); }); test('before and after connexion', function() { assert.isTrue(subject.node.classList.contains('incoming')); assert.isFalse(subject.node.classList.contains('ongoing')); mockCall._connect(); assert.isTrue(subject.node.classList.contains('ongoing')); assert.isTrue(subject.node.classList.contains('incoming')); assert.isTrue(subject.node.hasAttribute('data-l10n-id')); l10nAssert(subject.node, 'incoming_screen_reader'); }); }); }); test('should display contact name', function() { mockCall = new MockCall('888', 'incoming'); subject = new HandledCall(mockCall); MockVoicemail.mResolvePromise(false); assert.equal(subject.numberNode.textContent, 'test name'); }); test('should display withheld-number l10n key', function() { mockCall = new MockCall('', 'incoming'); subject = new HandledCall(mockCall); MockVoicemail.mResolvePromise(false); l10nAssert(subject.numberNode, 'withheld-number'); }); test('should display switch-calls l10n key', function() { mockCall = new MockCall('888', 'connected'); subject = new HandledCall(mockCall); mockCall.secondId = { number: '999' }; MockVoicemail.mResolvePromise(false); subject.updateCallNumber(); l10nAssert(subject.numberNode, 'switch-calls'); }); suite('Emergency Call layout', function() { setup(function() { MockCallScreen.mSetEmergencyWallpaperCalled = false; }); test('should set the emergency class', function() { mockCall = new MockCall('112', 'dialing'); subject = new HandledCall(mockCall); MockVoicemail.mResolvePromise(false); assert.isTrue(subject.node.classList.contains('emergency')); }); test('should display emergency number label', function() { mockCall = new MockCall('112', 'dialing'); mockCall.emergency = true; subject = new HandledCall(mockCall); MockVoicemail.mResolvePromise(false); l10nAssert(subject.additionalTelNode, 'emergencyNumber'); }); }); test('should display voicemail label', function() { mockCall = new MockCall(VOICEMAIL_NUMBER, 'dialing'); subject = new HandledCall(mockCall); MockVoicemail.mResolvePromise(true); l10nAssert(subject.numberNode, 'voiceMail'); }); suite('additional information', function() { test('check additional info updated', function() { this.sinon.stub(MockUtils, 'getPhoneNumberAdditionalInfo') .returns({ id: 'phone_type_custom_and_carrier', args: { type: 'type', carrier: 'carrier' } }); mockCall = new MockCall('888', 'incoming'); subject = new HandledCall(mockCall); MockVoicemail.mResolvePromise(false); assert.equal(subject.additionalTelNode.textContent, '888'); l10nAssert( subject.additionalTelTypeNode, { id: 'phone_type_custom_and_carrier', args: { type: 'type', carrier: 'carrier' } } ); }); test('check switch-calls mode', function() { mockCall = new MockCall('888', 'connected'); subject = new HandledCall(mockCall); mockCall.secondId = { number: '999' }; MockVoicemail.mResolvePromise(false); subject.updateCallNumber(); assert.equal('', subject.additionalTelNode.textContent); assert.equal('', subject.additionalTelTypeNode.textContent); subject.restoreAdditionalContactInfo(); assert.equal('', subject.additionalTelNode.textContent); assert.equal('', subject.additionalTelTypeNode.textContent); }); suite('additional contact info', function() { setup(function() { mockCall = new MockCall('888', 'incoming'); subject = new HandledCall(mockCall); MockVoicemail.mResolvePromise(false); }); suite('when there are additional infos to display', function() { setup(function() { subject.replaceAdditionalContactInfo( { raw: 'test additional tel' }, { id: 'phone_type_mobile_and_carrier', args: { carrier: 'carrier' } } ); }); test('should update the text content', function() { assert.equal(subject.additionalTelNode.textContent, 'test additional tel'); l10nAssert( subject.additionalTelTypeNode, { id: 'phone_type_mobile_and_carrier', args: { carrier: 'carrier' } } ); }); test('should add the proper css class', function() { assert.isTrue(subject.node.classList.contains('additionalInfo')); }); }); suite('when there aren\'t additional infos to display', function() { setup(function() { subject.replaceAdditionalContactInfo('', ''); }); test('should empty the text content', function() { assert.equal(subject.additionalTelNode.textContent, ''); assert.equal(subject.additionalTelTypeNode.textContent, ''); }); test('should remove the css class', function() { assert.isFalse(subject.node.classList.contains('additionalInfo')); }); }); }); }); suite('phone number', function() { test('formatPhoneNumber should call the font size manager if call is not' + ' in a conference', function() { this.sinon.spy(FontSizeManager, 'adaptToSpace'); subject.formatPhoneNumber('end'); sinon.assert.calledWith( FontSizeManager.adaptToSpace, MockCallScreen.mScenario, subject.outerNode, false, 'end'); }); test('formatPhoneNumber should not call the font size manager if call is' + ' in a conference', function() { subject.call.group = {}; this.sinon.spy(FontSizeManager, 'adaptToSpace'); subject.formatPhoneNumber('end'); assert.equal(FontSizeManager.adaptToSpace.callCount, 0); delete subject.call.group; }); test('should ensureFixedBaseline with a contact', function() { mockCall = new MockCall('888', 'dialing'); subject = new HandledCall(mockCall); MockVoicemail.mResolvePromise(false); this.sinon.spy(FontSizeManager, 'ensureFixedBaseline'); subject.formatPhoneNumber('end'); sinon.assert.calledWith( FontSizeManager.ensureFixedBaseline, MockCallScreen.mScenario, subject.numberNode ); }); test('should call resetFixedBaseline without a contact', function() { mockCall = new MockCall('111', 'dialing'); subject = new HandledCall(mockCall); MockVoicemail.mResolvePromise(false); this.sinon.spy(FontSizeManager, 'resetFixedBaseline'); subject.formatPhoneNumber('end'); sinon.assert.calledWith( FontSizeManager.resetFixedBaseline, subject.numberNode); }); test('check render number with regular number', function() { mockCall = new MockCall('888', 'incoming'); subject = new HandledCall(mockCall); MockVoicemail.mResolvePromise(false); subject.renderPhoneNumber({ raw: '12345678' }); l10nAssert(subject.numberNode, { raw: '12345678' }); }); test('check render number with l10n id', function() { mockCall = new MockCall('', 'incoming'); subject = new HandledCall(mockCall); MockVoicemail.mResolvePromise(false); subject.renderPhoneNumber('withheld-number'); l10nAssert(subject.numberNode, 'withheld-number'); }); test('check restore number', function() { mockCall = new MockCall('888', 'incoming'); subject = new HandledCall(mockCall); MockVoicemail.mResolvePromise(false); subject.replacePhoneNumber({ raw: '12345678' }); subject.renderPhoneNumber('123'); subject.restorePhoneNumber(); l10nAssert(subject.numberNode, { raw: '12345678' }); }); test('check restore withheld-number', function() { mockCall = new MockCall('', 'incoming'); subject = new HandledCall(mockCall); MockVoicemail.mResolvePromise(false); subject.replacePhoneNumber('withheld-number'); subject.renderPhoneNumber('123'); subject.restorePhoneNumber(); l10nAssert(subject.numberNode, 'withheld-number'); }); test('check restore voicemail number', function() { mockCall = new MockCall(VOICEMAIL_NUMBER, 'incoming'); subject = new HandledCall(mockCall); MockVoicemail.mResolvePromise(true); subject.renderPhoneNumber('123'); subject.restorePhoneNumber(); l10nAssert(subject.numberNode, 'voiceMail'); }); test('check restore emergency number', function() { mockCall = new MockCall('112', 'incoming'); mockCall.emergency = true; subject = new HandledCall(mockCall); MockVoicemail.mResolvePromise(false); subject.renderPhoneNumber('123'); subject.restorePhoneNumber(); assert.equal(subject.numberNode.textContent, '112'); }); }); suite('caller photo', function() { setup(function() { MockCallScreen.mSetCallerContactImageCalled = false; }); test('should reset photo when receiving a new handled call', function() { mockCall = new MockCall('111', 'incoming'); subject = new HandledCall(mockCall); MockVoicemail.mResolvePromise(false); assert.isTrue(MockCallScreen.mSetCallerContactImageCalled); }); }); suite('explicit visibility', function() { test('calling show should show the node', function() { subject.node.hidden = true; subject.show(); assert.isFalse(subject.node.hidden); }); test('calling show should update singleLine status', function() { subject.show(); assert.isTrue(MockCallScreen.mUpdateSingleLineCalled); }); test('calling hide should hide the node', function() { subject.node.hidden = false; subject.hide(); assert.isTrue(subject.node.hidden); }); test('calling hide should update singleLine status', function() { subject.show(); assert.isTrue(MockCallScreen.mUpdateSingleLineCalled); }); suite('when the node got nullified', function() { setup(function() { subject.node = null; }); test('show() should handle it', function() { subject.show(); assert.isTrue(true); // We'll get a JS error otherwise }); test('hide() should handle it', function() { subject.hide(); assert.isTrue(true); // We'll get a JS error otherwise }); }); }); suite('ongroupchange', function() { var addToGroupDetailsSpy; setup(function() { mockCall = new MockCall(String(phoneNumber), 'connected'); subject = new HandledCall(mockCall); MockVoicemail.mResolvePromise(false); addToGroupDetailsSpy = this.sinon.spy( ConferenceGroupHandler, 'addToGroupDetails'); this.sinon.spy(MockCallScreen, 'insertCall'); }); test('When entering a group, it should ask ' + 'the CallScreen to move into the group details', function() { mockCall.group = this.sinon.stub(); mockCall.ongroupchange(mockCall); assert.isTrue(addToGroupDetailsSpy.calledWith(subject.node)); assert.isFalse(MockCallScreen.mShowStatusMessageCalled); }); suite('when leaving a group but still connected', function() { setup(function() { mockCall.group = null; }); test('it should clone the call node if the participant list overlay is ' + 'shown', function() { this.sinon.stub( ConferenceGroupHandler, 'isGroupDetailsShown').returns(true); var parent = document.createElement('div'); this.sinon.spy(parent, 'insertBefore'); parent.appendChild(subject.node); mockCall.ongroupchange(mockCall); sinon.assert.calledOnce(parent.insertBefore); document.body.appendChild(subject.node); }); test('it should move the call node back to the CallScreen', function() { mockCall.ongroupchange(mockCall); sinon.assert.calledWith(MockCallScreen.insertCall, subject.node); }); test('it should not show any status message on disconnect', function() { mockCall.ongroupchange(mockCall); mockCall._disconnect(); assert.isFalse(MockCallScreen.mShowStatusMessageCalled); }); }); suite('when leaving a group by hanging up', function() { setup(function() { mockCall.group = null; mockCall.state = 'disconnecting'; mockCall.ongroupchange(mockCall); }); test('it shouldn\'t move back to the CallScreen', function() { sinon.assert.notCalled(MockCallScreen.insertCall); assert.isFalse(MockCallScreen.mShowStatusMessageCalled); }); test('it should show a status message.', function() { mockCall._disconnect(); assert.isTrue(MockCallScreen.mShowStatusMessageCalled); }); }); suite('when leaving a group by hanging up the whole group calls', function() { setup(function() { mockCall.group = null; mockCall.state = 'disconnecting'; subject.node.dataset.groupHangup = 'groupHangup'; mockCall.ongroupchange(mockCall); }); test('it shouldn\'t move back', function() { sinon.assert.notCalled(MockCallScreen.insertCall); }); test('it shouldn\'t show any status message', function() { mockCall._disconnect(); assert.isFalse(MockCallScreen.mShowStatusMessageCalled); }); }); }); suite('Controls displayed when in a group', function() { test('hangup button', function() { mockCall = new MockCall(String(phoneNumber), 'connected'); subject = new HandledCall(mockCall); MockVoicemail.mResolvePromise(false); var hangUpSpy = this.sinon.spy(mockCall, 'hangUp'); subject.hangupButton.onclick(); assert.isTrue(hangUpSpy.calledOnce); }); }); suite('DSDS SIM display >', function() { setup(function() { MockNavigatorMozIccManager.addIcc('12345', {'cardState': 'ready'}); }); suite('One SIM >', function() { test('should hide the sim nodes', function() { mockCall = new MockCall('888', 'outgoing'); subject = new HandledCall(mockCall); MockVoicemail.mResolvePromise(false); assert.isTrue(subject.viaSimNode.hidden); assert.isTrue(subject.simNumberNode.hidden); }); }); suite('Multiple SIMs >', function() { setup(function() { MockNavigatorMozIccManager.addIcc('424242', {'cardState': 'ready'}); }); test('should show which sim is in use', function() { mockCall = new MockCall('888', 'outgoing'); subject = new HandledCall(mockCall); MockVoicemail.mResolvePromise(false); assert.isFalse(subject.viaSimNode.hidden); assert.isFalse(subject.simNumberNode.hidden); l10nAssert(subject.viaSimNode, { id: 'via-sim', args: { n: 2 } }); l10nAssert(subject.simNumberNode, { id: 'sim-number', args: { n: 2 } }); }); }); }); suite('STK Call Control changes Number', function() { test('should resolve to changed contact', function() { mockCall = new MockCall('111', 'dialing'); subject = new HandledCall(mockCall); assert.equal(subject.numberNode.textContent, ''); //simulate the STK change to a different number mockCall.id.number = '555'; mockCall._connect(); MockVoicemail.mResolvePromise(false); assert.equal(subject.numberNode.textContent, 'test name'); }); test('should resolve to number if no contact', function() { mockCall = new MockCall('555', 'dialing'); subject = new HandledCall(mockCall); assert.equal(subject.numberNode.textContent, ''); //simulate the STK change to a different number mockCall.id.number = '111'; mockCall._connect(); MockVoicemail.mResolvePromise(false); assert.equal(subject.numberNode.textContent, '111'); }); test('should resolve to voicemail', function() { //simulate the STK change to a different number mockCall = new MockCall('111', 'dialing'); subject = new HandledCall(mockCall); mockCall.id.number = '123'; mockCall._connect(); MockVoicemail.mResolvePromise(true); l10nAssert(subject.numberNode, 'voiceMail'); }); test('should correctly identify emergency', function() { mockCall = new MockCall('555', 'dialing'); subject = new HandledCall(mockCall); MockVoicemail.mResolvePromise(false); mockCall.id.number = '112'; mockCall.emergency = true; mockCall._connect(); l10nAssert(subject.additionalTelNode, 'emergencyNumber'); assert.isTrue(subject.node.classList.contains('emergency')); assert.isTrue(subject.node.textContent.includes('112')); }); }); suite('Resizing the call ended string', function() { var durationChildNode; setup(function() { durationChildNode = subject.node.querySelector('.duration span'); durationChildNode.textContent = 'Call ended'; this.sinon.spy(subject.mutationObserver, 'disconnect'); this.sinon.spy(subject.mutationObserver, 'observe'); this.sinon.spy(subject, 'computeCallEndedFontSizeRules'); }); test('Does not resize the string if no l10n attribute is present', function() { subject.observeMutation(); sinon.assert.notCalled(subject.mutationObserver.disconnect); sinon.assert.notCalled(subject.mutationObserver.observe); sinon.assert.notCalled(subject.computeCallEndedFontSizeRules); }); test('Disconnects and reconnects the observer before adjusting the string', function() { durationChildNode.setAttribute('data-l10n-id', 'callEnded'); subject.observeMutation(); assert.isTrue( subject.mutationObserver.disconnect.calledBefore( subject.computeCallEndedFontSizeRules ) ); assert.isTrue( subject.mutationObserver.observe.calledAfter( subject.computeCallEndedFontSizeRules ) ); }); }); });