VulpesOS/gaia/apps/system/test/unit/dialer_agent_test.js
OverSu b38dea0597 Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
2026-09-30 23:13:03 +02:00

531 lines
16 KiB
JavaScript
Executable file

'use strict';
/* global DialerAgent, MockAppWindow, MocksHelper, MockNavigatorMozTelephony,
MockSettingsListener, MockSettingsURL, MockAudio, MockApplications,
MockService */
require('/js/dialer_agent.js');
require('/test/unit/mock_app_window.js');
require('/test/unit/mock_applications.js');
require('/test/unit/mock_attention_window.js');
require('/test/unit/mock_callscreen_window.js');
requireApp('system/test/unit/mock_lazy_loader.js');
require('/shared/test/unit/mocks/mock_settings_listener.js');
require('/shared/test/unit/mocks/mock_settings_url.js');
require('/shared/test/unit/mocks/mock_audio.js');
require('/shared/test/unit/mocks/mock_navigator_moz_telephony.js');
require('/shared/test/unit/mocks/mock_service.js');
var mocksForDialerAgent = new MocksHelper([
'CallscreenWindow',
'Audio',
'SettingsListener',
'SettingsURL',
'LazyLoader',
'Service'
]).init();
suite('system/DialerAgent', function() {
mocksForDialerAgent.attachTestHelpers();
var realTelephony, realVibrate, realApplications;
var subject;
var setVisibleSpy;
function callschanged() {
MockNavigatorMozTelephony.mTriggerEvent(new CustomEvent('callschanged'));
}
suiteSetup(function() {
realApplications = window.applications;
window.applications = MockApplications;
realTelephony = navigator.mozTelephony;
navigator.mozTelephony = MockNavigatorMozTelephony;
realVibrate = navigator.vibrate;
});
suiteTeardown(function() {
MockNavigatorMozTelephony.mSuiteTeardown();
navigator.mozTelephony = realTelephony;
navigator.vibrate = realVibrate;
window.applications = realApplications;
});
setup(function() {
if (!('setVisible' in HTMLIFrameElement.prototype)) {
HTMLIFrameElement.prototype.setVisible = function stub() {};
}
setVisibleSpy = this.sinon.spy(HTMLIFrameElement.prototype, 'setVisible');
this.sinon.useFakeTimers();
subject = new DialerAgent();
subject.start();
});
teardown(function() {
subject.stop();
MockService.mTeardown();
MockNavigatorMozTelephony.mTeardown();
});
function MockCall(state) {
this.state = state;
this.addEventListener = function() {};
this.removeEventListener = function() {};
this.hangUp = function() {};
}
test('Should load tone player if just upgraded', function() {
window.toneUpgrader = {
perform: this.sinon.spy()
};
subject.stop();
MockService.mockQueryWith('justUpgraded', true);
subject.start();
assert.isTrue(window.toneUpgrader.perform.calledWith('ringtone'));
delete window.toneUpgrader;
subject.stop();
});
suite('Audio element setup', function() {
var mockAudio;
setup(function() {
mockAudio = MockAudio.instances[0];
});
test('it should set the channel', function() {
assert.equal(mockAudio.mozAudioChannelType, 'ringer');
});
test('it should preload metadata', function() {
assert.equal(mockAudio.preload, 'metadata');
});
test('it should loop', function() {
assert.isTrue(mockAudio.loop);
});
test('it should load the ringtone from the settings', function() {
assert.isUndefined(mockAudio.src);
var blob = new Blob([], {type: 'audio/ogg'});
var src = '----uniq----';
this.sinon.stub(MockSettingsURL.prototype, 'set').withArgs(blob).returns(
src
);
MockSettingsListener.mTriggerCallback('dialer.ringtone', blob);
assert.equal(mockAudio.src, src);
});
});
suite('When an incoming call comes in', function() {
var vibrateSpy;
var mockCall;
var mockAudio;
setup(function() {
vibrateSpy = this.sinon.spy();
navigator.vibrate = vibrateSpy;
mockAudio = MockAudio.instances[0];
mockAudio.src = '---';
this.sinon.spy(mockAudio, 'play');
this.sinon.spy(mockAudio, 'pause');
mockCall = new MockCall('incoming');
this.sinon.spy(mockCall, 'addEventListener');
this.sinon.spy(mockCall, 'removeEventListener');
MockNavigatorMozTelephony.calls = [mockCall];
});
suite('if the vibration is enabled', function() {
setup(function() {
MockSettingsListener.mTriggerCallback('vibration.enabled', true);
callschanged();
});
test('it should start vibrating', function() {
assert.isTrue(vibrateSpy.calledWith([200]));
});
test('it should vibrate every 600ms', function() {
this.sinon.clock.tick(600);
assert.isTrue(vibrateSpy.calledTwice);
this.sinon.clock.tick(600);
assert.isTrue(vibrateSpy.calledThrice);
});
test('it should stop when the call state changes', function() {
mockCall.addEventListener.yield();
vibrateSpy.reset();
this.sinon.clock.tick(600);
assert.isTrue(vibrateSpy.notCalled);
});
test('it should stop when the user presses volume down', function() {
window.dispatchEvent(new CustomEvent('volumedown'));
vibrateSpy.reset();
this.sinon.clock.tick(600);
assert.isTrue(vibrateSpy.notCalled);
});
test('it should stop when the user presses the power button', function() {
window.dispatchEvent(new CustomEvent('sleep'));
vibrateSpy.reset();
this.sinon.clock.tick(600);
sinon.assert.notCalled(vibrateSpy);
});
});
suite('if the vibration is disabled', function() {
setup(function() {
MockSettingsListener.mTriggerCallback('vibration.enabled', false);
callschanged();
});
test('it should not vibrate', function() {
assert.isTrue(vibrateSpy.notCalled);
});
});
suite('if the ringtone has a volume', function() {
setup(function() {
MockSettingsListener.mTriggerCallback('audio.volume.notification', 7);
callschanged();
});
test('it should play the ringtone', function() {
assert.isTrue(mockAudio.play.calledOnce);
});
test('it should pause when the call state changes', function() {
mockCall.addEventListener.yield();
assert.isTrue(mockAudio.pause.calledOnce);
});
test('it should pause when the user presses the sleep button',
function() {
window.dispatchEvent(new CustomEvent('sleep'));
assert.isTrue(mockAudio.pause.calledOnce);
});
suite('but we have no audio source loaded', function() {
setup(function() {
mockAudio.readyState = 0;
});
test('pressing the sleep button should not do anything', function() {
window.dispatchEvent(new CustomEvent('sleep'));
assert.isTrue(mockAudio.pause.notCalled);
});
});
});
suite('if the ringtone is muted', function() {
setup(function() {
MockSettingsListener.mTriggerCallback('audio.volume.notification', 0);
callschanged();
});
test('it should play the silent ringtone', function() {
sinon.assert.calledOnce(mockAudio.play);
});
});
test('it should listen to the state changes of the call', function() {
callschanged();
assert.isTrue(mockCall.addEventListener.calledWith('statechange'));
});
test('it should not listen twice if we get multiple callschanged',
function() {
callschanged();
callschanged();
assert.isTrue(mockCall.addEventListener.calledOnce);
});
test('it should remove the statechange listener after the first trigger',
function() {
callschanged();
mockCall.addEventListener.yield();
assert.isTrue(mockCall.removeEventListener.calledWith('statechange'));
});
});
suite('When a second incoming call comes in', function() {
var vibrateSpy;
var secondCall;
var mockAudio;
setup(function() {
var mockCall = new MockCall('incoming');
this.sinon.spy(mockCall, 'addEventListener');
MockNavigatorMozTelephony.calls = [mockCall];
callschanged();
mockCall.addEventListener.yield();
mockCall.state = 'connected';
secondCall = new MockCall('incoming');
this.sinon.spy(secondCall, 'addEventListener');
MockNavigatorMozTelephony.calls = [mockCall, secondCall];
vibrateSpy = this.sinon.spy();
navigator.vibrate = vibrateSpy;
mockAudio = MockAudio.instances[0];
this.sinon.spy(mockAudio, 'play');
callschanged();
});
suite('if the vibration is enabled', function() {
setup(function() {
MockSettingsListener.mTriggerCallback('vibration.enabled', true);
callschanged();
});
test('it should start vibrating', function() {
sinon.assert.calledWith(vibrateSpy, [200]);
});
test('it should vibrate every 600ms', function() {
this.sinon.clock.tick(600);
sinon.assert.calledTwice(vibrateSpy);
this.sinon.clock.tick(600);
sinon.assert.calledThrice(vibrateSpy);
});
test('it should stop when the call state changes', function() {
secondCall.addEventListener.yield();
vibrateSpy.reset();
this.sinon.clock.tick(600);
sinon.assert.notCalled(vibrateSpy);
});
test('it should stop when the user presses volume down', function() {
window.dispatchEvent(new CustomEvent('volumedown'));
vibrateSpy.reset();
this.sinon.clock.tick(600);
sinon.assert.notCalled(vibrateSpy);
});
test('it should stop when the user presses the power button', function() {
window.dispatchEvent(new CustomEvent('sleep'));
vibrateSpy.reset();
this.sinon.clock.tick(600);
sinon.assert.notCalled(vibrateSpy);
});
});
suite('even if the ringtone has a volume', function() {
setup(function() {
MockSettingsListener.mTriggerCallback('audio.volume.notification', 7);
});
test('it should play the silent ringtone', function() {
sinon.assert.called(mockAudio.play);
});
});
});
suite('When a outgoing call goes out', function() {
var vibrateSpy;
var mockCall;
var mockAudio;
setup(function() {
vibrateSpy = this.sinon.spy();
navigator.vibrate = vibrateSpy;
mockAudio = MockAudio.instances[0];
this.sinon.spy(mockAudio, 'play');
mockCall = new MockCall('dialing');
this.sinon.spy(mockCall, 'addEventListener');
MockNavigatorMozTelephony.calls = [mockCall];
});
suite('even if the vibration is enabled', function() {
setup(function() {
MockSettingsListener.mTriggerCallback('vibration.enabled', true);
callschanged();
});
test('it should not vibrate', function() {
assert.isTrue(vibrateSpy.notCalled);
});
});
suite('even if the ringtone has a volume', function() {
setup(function() {
MockSettingsListener.mTriggerCallback('audio.volume.notification', 7);
callschanged();
});
test('it should not play', function() {
assert.isTrue(mockAudio.play.notCalled);
});
});
test('it should not listen to the state changes of the call', function() {
callschanged();
assert.isTrue(mockCall.addEventListener.notCalled);
});
});
test('should throw if started twice', function(done) {
try {
subject.start();
} catch (e) {
assert.ok(e);
done();
}
});
test('should not do anything if mozTelephony is unavailable', function() {
subject.stop();
MockAudio.mTeardown();
MockSettingsListener.mCallbacks = {};
navigator.mozTelephony = undefined;
subject = new DialerAgent();
subject.start();
assert.equal(MockAudio.instances.length, 0);
assert.deepEqual(MockSettingsListener.mCallbacks, {});
navigator.mozTelephony = MockNavigatorMozTelephony;
});
suite('handling memory pressure events',
function() {
setup(function() {
this.sinon.stub(subject._callscreenWindow, 'free');
});
test('callscreen should be freed once memory is under pressure',
function() {
window.dispatchEvent(new CustomEvent('mozmemorypressure'));
sinon.assert.calledOnce(subject._callscreenWindow.free);
});
test('callscreen should not be freed if a call is present', function() {
MockNavigatorMozTelephony.calls = [{}];
window.dispatchEvent(new CustomEvent('mozmemorypressure'));
sinon.assert.notCalled(subject._callscreenWindow.free);
});
test('callscreen should not be freed if a conference call is present',
function() {
MockNavigatorMozTelephony.conferenceGroup.calls = [{}];
window.dispatchEvent(new CustomEvent('mozmemorypressure'));
sinon.assert.notCalled(subject._callscreenWindow.free);
});
test('callscreen should not be freed if it is visible',
function() {
this.sinon.stub(MockAppWindow.prototype, 'isVisible').returns(true);
window.dispatchEvent(new CustomEvent('mozmemorypressure'));
sinon.assert.notCalled(subject._callscreenWindow.free);
});
});
suite('wake events', function() {
setup(function() {
this.sinon.spy(MockService, 'request');
});
test('during a call should turn on the screen', function() {
MockNavigatorMozTelephony.calls = [new MockCall()];
window.dispatchEvent(new CustomEvent('wake'));
sinon.assert.calledOnce(MockService.request);
sinon.assert.calledWith(MockService.request, 'turnScreenOn');
});
test('when not on a call should be ignored', function() {
window.dispatchEvent(new CustomEvent('wake'));
sinon.assert.notCalled(MockService.request);
});
});
suite('sleep events', function() {
test('when alerting stop playing the ringtone', function() {
var mockAudio = MockAudio.instances[0];
this.sinon.spy(mockAudio, 'pause');
MockNavigatorMozTelephony.calls = [new MockCall('incoming')];
MockNavigatorMozTelephony.mTriggerCallsChanged();
window.dispatchEvent(new CustomEvent('sleep'));
sinon.assert.calledOnce(mockAudio.pause);
});
test('when not alerting hang up all connected calls', function() {
var mockCalls = [ new MockCall() , new MockCall() ];
mockCalls.forEach((mockCall) => this.sinon.spy(mockCall, 'hangUp'));
MockNavigatorMozTelephony.calls = mockCalls;
window.dispatchEvent(new CustomEvent('sleep'));
mockCalls.forEach((mockCall) => sinon.assert.calledOnce(mockCall.hangUp));
});
test('when not alerting hang up the conference call', function() {
var mockCalls = [ new MockCall() , new MockCall() ];
MockNavigatorMozTelephony.conferenceGroup.calls = mockCalls;
this.sinon.spy(MockNavigatorMozTelephony.conferenceGroup, 'hangUp');
MockNavigatorMozTelephony.calls = mockCalls;
window.dispatchEvent(new CustomEvent('sleep'));
sinon.assert.calledOnce(MockNavigatorMozTelephony.conferenceGroup.hangUp);
});
});
test('Make fake notification if application is ready', function() {
subject.stop();
subject = new DialerAgent();
MockApplications.ready = false;
var stubMakeFakeNotification =
this.sinon.stub(subject, 'makeFakeNotification');
subject.start();
assert.isFalse(stubMakeFakeNotification.called);
window.dispatchEvent(new CustomEvent('applicationready'));
assert.isTrue(stubMakeFakeNotification.called);
});
suite('onCall', function() {
test('returns true when on a call', function() {
MockNavigatorMozTelephony.calls = [ new MockCall() ];
assert.isTrue(subject.onCall());
});
test('returns true when on a conference call', function() {
MockNavigatorMozTelephony.conferenceGroup.calls = [
new MockCall() , new MockCall()
];
assert.isTrue(subject.onCall());
});
test('returns false when not on a call', function() {
assert.isFalse(subject.onCall());
});
test('registers as a service when the dialer service is alive', function() {
subject.stop();
this.sinon.spy(MockService, 'registerState');
this.sinon.spy(MockService, 'unregisterState');
subject = new DialerAgent();
subject.start();
sinon.assert.calledOnce(MockService.registerState);
sinon.assert.calledWith(MockService.registerState, 'onCall', subject);
subject.stop();
sinon.assert.calledOnce(MockService.unregisterState);
sinon.assert.calledWith(MockService.unregisterState, 'onCall', subject);
});
});
});