'use strict'; /* global MocksHelper, MockL10n, SoundManager, MockSettingsListener, MockLock, MockNavigatorSettings, MockasyncStorage, MockCustomDialog, MockLazyLoader, MockService */ requireApp('system/shared/test/unit/mocks/mock_service.js'); require('/shared/test/unit/mocks/mock_lazy_loader.js'); require('/shared/test/unit/load_body_html_helper.js'); require('/shared/test/unit/mocks/mock_navigator_moz_settings.js'); require('/shared/test/unit/mocks/mock_settings_listener.js'); require('/shared/test/unit/mocks/mock_custom_dialog.js'); require('/shared/test/unit/mocks/mock_l10n.js'); require('/shared/js/async_semaphore.js'); requireApp('system/test/unit/mock_asyncStorage.js'); requireApp('system/test/unit/mock_navigator_moz_telephony.js'); requireApp('system/test/unit/mock_screen_manager.js'); requireApp('system/js/service.js'); requireApp('system/js/base_module.js'); requireApp('system/js/base_ui.js'); requireApp('system/js/base_icon.js'); requireApp('system/js/playing_icon.js'); requireApp('system/js/headphone_icon.js'); requireApp('system/js/mute_icon.js'); requireApp('system/js/sound_manager.js'); var mocksForSoundManager = new MocksHelper([ 'asyncStorage', 'CustomDialog', 'SettingsListener', 'LazyLoader', 'Service' ]).init(); suite('system/sound manager', function() { var realL10n; var realMozSettings; var soundManager; mocksForSoundManager.attachTestHelpers(); function sendChromeEvent(detail) { var evt = new CustomEvent('mozChromeEvent', { detail: detail }); window.dispatchEvent(evt); } function checkVolume(data) { for (var name in data) { assert.equal(data[name], soundManager.currentVolume[name]); } } setup(function() { MockService.mockQueryWith('screenEnabled', true); this.sinon.stub(MockService, 'request', function(action) { if (action === 'showCustomDialog') { MockCustomDialog.show(arguments[1], arguments[2], arguments[3], arguments[4]); } else if (action === 'hideCustomDialog') { MockCustomDialog.hide(arguments[1], arguments[2], arguments[3], arguments[4]); } else { return Promise.resolve(document.createElement('div')); } }); MockLazyLoader.mLoadRightAway = true; this.sinon.spy(MockLazyLoader, 'load'); soundManager = new SoundManager(); soundManager.start(); }); teardown(function() { soundManager.stop(); }); test('Default channel', function() { MockService.mockQueryWith('locked', false); soundManager.homescreenVisible = false; MockService.mockQueryWith('isFtuRunning', true); assert.equal(soundManager.getChannel(), 'notification'); MockService.mockQueryWith('isFtuRunning', false); assert.equal(soundManager.getChannel(), 'content'); }); test('Should lazy load icons', function() { assert.isTrue(MockLazyLoader.load.calledWith([ 'js/headphone_icon.js', 'js/mute_icon.js', 'js/playing_icon.js' ])); }); suiteSetup(function() { loadBodyHTML('/index.html'); realL10n = navigator.mozL10n; realMozSettings = navigator.mozSettings; navigator.mozL10n = MockL10n; navigator.mozSettings = MockNavigatorSettings; }); suiteTeardown(function() { navigator.mozL10n = realL10n; navigator.mozSettings = realMozSettings; document.body.innerHTML = ''; }); suite('Headset', function() { setup(function() { this.sinon.stub(soundManager.headphoneIcon, 'update'); }); test('Headset is connected', function() { sendChromeEvent({'type': 'headphones-status-changed', 'state': 'on' }); assert.isTrue(soundManager.headphoneIcon.update.called); }); test('Headset is disconnected', function() { sendChromeEvent({'type': 'headphones-status-changed', 'state': 'off' }); assert.isFalse(soundManager.headphoneIcon.update.called); }); }); suite('stop test', function() { test('stop listening event listener', function() { sendChromeEvent({'type': 'default-volume-channel-changed', 'channel': 'normal'}); assert.equal('normal', soundManager.defaultVolumeControlChannel); soundManager.stop(); sendChromeEvent({'type': 'default-volume-channel-changed', 'channel': 'none'}); assert.equal('normal', soundManager.defaultVolumeControlChannel); }); }); suite('auto start/stop', function() { suite('change channel', function() { test('default volume channel changed', function() { sendChromeEvent({'type': 'default-volume-channel-changed', 'channel': 'normal'}); assert.equal('normal', soundManager.defaultVolumeControlChannel); }); test('audio channel changed', function() { window.dispatchEvent(new CustomEvent('audiochannelchanged', { detail: { channel: 'alarm' } })); assert.equal('alarm', soundManager.currentChannel); }); }); suite('read volume from settings', function() { setup(function() { MockSettingsListener.mTriggerCallback('audio.volume.alarm', 1); MockSettingsListener.mTriggerCallback('audio.volume.bt_sco', 2); MockSettingsListener.mTriggerCallback('audio.volume.content', 3); MockSettingsListener.mTriggerCallback('audio.volume.notification', 4); MockSettingsListener.mTriggerCallback('audio.volume.telephony', 5); }); test('volume for each channel changed', function() { assert.equal(1, soundManager.currentVolume.alarm); assert.equal(2, soundManager.currentVolume.bt_sco); assert.equal(3, soundManager.currentVolume.content); assert.equal(4, soundManager.currentVolume.notification); assert.equal(5, soundManager.currentVolume.telephony); }); }); suite('settings changed', function() { setup(function() { this.sinon.stub(soundManager.muteIcon, 'update'); }); test('key: audio.volume.cemaxvol', function() { MockSettingsListener.mTriggerCallback('audio.volume.cemaxvol', 6); assert.equal(6, soundManager.CEWarningVol); }); test('key: vibration.enabled', function() { MockSettingsListener.mTriggerCallback('vibration.enabled', true); assert.equal(true, soundManager.vibrationEnabled); assert.isTrue(soundManager.muteIcon.update.called); MockSettingsListener.mTriggerCallback('vibration.enabled', false); assert.equal(false, soundManager.vibrationEnabled); }); }); suite('mute icon update', function() { setup(function() { this.sinon.stub(soundManager.muteIcon, 'update'); }); test('notification volume settings change', function() { MockSettingsListener.mTriggerCallback('audio.volume.notification', 0); assert.isTrue(soundManager.muteIcon.update.called); MockSettingsListener.mTriggerCallback('audio.volume.notification', 1); assert.isTrue(soundManager.muteIcon.update.called); }); }); suite('volume change', function() { setup(function() { // reset the all volume to 5 soundManager.currentVolume.alarm = 5; soundManager.currentVolume.bt_sco = 5; soundManager.currentVolume.content = 5; soundManager.currentVolume.notification = 5; soundManager.currentVolume.telephony = 5; soundManager.currentChannel = 'normal'; }); test('volume up event', function() { window.dispatchEvent(new CustomEvent('volumeup')); checkVolume({ 'alarm': 5, 'bt_sco': 5, 'content': 6, 'notification': 5, 'telephony': 5 }); }); test('volume down event', function() { window.dispatchEvent(new CustomEvent('volumedown')); checkVolume({ 'alarm': 5, 'bt_sco': 5, 'content': 4, 'notification': 5, 'telephony': 5 }); }); test('volume up to vibrate', function() { var spy = this.sinon.spy(soundManager, 'notifyByVibrating'); soundManager.currentChannel = 'notification'; soundManager.currentVolume.notification = -1; soundManager.vibrationEnabled = false; window.dispatchEvent(new CustomEvent('volumeup')); checkVolume({ 'alarm': 5, 'bt_sco': 5, 'content': 5, 'notification': 0, 'telephony': 5 }); assert.equal('MUTE', soundManager.muteState); assert.isTrue(soundManager.vibrationEnabled); assert.isTrue(MockNavigatorSettings.mSettings['vibration.enabled']); var vibrationClassList = soundManager.element.classList; assert.isTrue(vibrationClassList.contains('vibration')); assert.isTrue(spy.calledOnce); }); test('volume down to vibrate', function() { this.sinon.stub(soundManager.muteIcon, 'update'); var spy = this.sinon.spy(soundManager, 'notifyByVibrating'); soundManager.currentChannel = 'notification'; soundManager.currentVolume.notification = 1; soundManager.vibrationEnabled = false; window.dispatchEvent(new CustomEvent('volumedown')); checkVolume({ 'alarm': 5, 'bt_sco': 5, 'content': 5, 'notification': 0, 'telephony': 5 }); assert.equal('MUTE', soundManager.muteState); assert.isTrue(soundManager.vibrationEnabled); assert.isTrue(MockNavigatorSettings.mSettings['vibration.enabled']); var vibrationClassList = soundManager.element.classList; assert.isTrue(vibrationClassList.contains('vibration')); assert.isTrue(spy.calledOnce); assert.isTrue(soundManager.muteIcon.update.called); }); test('volume down to silent', function() { this.sinon.stub(soundManager.muteIcon, 'update'); soundManager.currentChannel = 'notification'; soundManager.currentVolume.notification = 0; window.dispatchEvent(new CustomEvent('volumedown')); // we cannot check content channel here, because it is driven by // SettingsListener's event. checkVolume({ 'alarm': 5, 'bt_sco': 5, 'notification': 0, 'telephony': 5 }); assert.equal('MUTE', soundManager.muteState); assert.isFalse(soundManager.vibrationEnabled); assert.isFalse(MockNavigatorSettings.mSettings['vibration.enabled']); // The content channel should be mute too. assert.equal(0, MockNavigatorSettings.mSettings['audio.volume.content']); var vibrationClassList = soundManager.element.classList; assert.isFalse(vibrationClassList.contains('vibration')); assert.isTrue(soundManager.muteIcon.update.called); }); test('handleVolumeKey: screen-off and channel none', function() { MockService.mockQueryWith('screenEnabled', false); soundManager.currentChannel = 'none'; window.dispatchEvent(new CustomEvent('volumeup')); checkVolume({ 'alarm': 5, 'bt_sco': 5, 'content': 5, 'notification': 5, 'telephony': 5 }); }); test('handleVolumeKey: headset connected and channel-normal', function() { soundManager.isHeadsetConnected = true; soundManager.homescreenVisible = true; window.dispatchEvent(new CustomEvent('volumeup')); checkVolume({ 'alarm': 5, 'bt_sco': 5, 'content': 6, 'notification': 5, 'telephony': 5 }); window.dispatchEvent(new CustomEvent('volumedown')); checkVolume({ 'alarm': 5, 'bt_sco': 5, 'content': 5, 'notification': 5, 'telephony': 5 }); }); test('handleVolumeKey: headset connected and channel-none', function() { soundManager.isHeadsetConnected = true; soundManager.currentChannel = 'none'; soundManager.homescreenVisible = true; window.dispatchEvent(new CustomEvent('volumeup')); checkVolume({ 'alarm': 5, 'bt_sco': 5, 'content': 5, 'notification': 6, 'telephony': 5 }); }); test('handleVolumeKey: not at homescreen', function() { soundManager.currentChannel = 'none'; soundManager.homescreenVisible = false; window.dispatchEvent(new CustomEvent('volumeup')); checkVolume({ 'alarm': 5, 'bt_sco': 5, 'content': 6, 'notification': 5, 'telephony': 5 }); }); test('over volume up', function() { soundManager.changeVolume(20); checkVolume({ 'alarm': 5, 'bt_sco': 5, 'content': 15, 'notification': 5, 'telephony': 5 }); }); test('enter slient mode', function() { soundManager.currentVolume.content = 15; soundManager.enterSilentMode('content'); assert.equal(0, MockNavigatorSettings.mSettings['audio.volume.content']); MockLock.mCallbacks.onsuccess(); assert.equal(15, MockasyncStorage.mItems['content.volume']); }); test('leave slient mode', function() { soundManager.currentVolume.content = 15; soundManager.enterSilentMode('content'); soundManager.leaveSilentMode('content'); assert.equal(15, MockNavigatorSettings.mSettings['audio.volume.content']); }); test('mute it', function() { window.dispatchEvent(new CustomEvent('mute')); assert.equal(0, MockNavigatorSettings.mSettings['audio.volume.notification']); }); test('umute it', function() { window.dispatchEvent(new CustomEvent('mute')); window.dispatchEvent(new CustomEvent('unmute')); assert.equal(5, MockNavigatorSettings.mSettings['audio.volume.notification']); }); test('mute notification and unmute notification/content', function() { soundManager.enterSilentMode('content'); assert.equal(0, MockNavigatorSettings.mSettings['audio.volume.content']); window.dispatchEvent(new CustomEvent('mute')); window.dispatchEvent(new CustomEvent('unmute')); assert.isTrue( MockNavigatorSettings.mSettings['audio.volume.content'] > 0); }); }); suite('homescreen showing', function() { test('hide dialog when homescreen is opening', function() { var event = new CustomEvent('homescreenopening'); window.dispatchEvent(event); assert.isFalse(MockCustomDialog.mShown); assert.isTrue(soundManager.homescreenVisible); }); test('hide dialog when homescreen is opened', function() { var event = new CustomEvent('homescreenopened'); window.dispatchEvent(event); assert.isFalse(MockCustomDialog.mShown); assert.isTrue(soundManager.homescreenVisible); }); }); suite('CE accumulator', function() { var fakeTimer; setup(function() { fakeTimer = sinon.useFakeTimers(); SoundManager.TIME_ONE_MINUTE = 10; SoundManager.CE_RESET_TIME = 50; soundManager.currentVolume.content = 15; sendChromeEvent({'type': 'headphones-status-changed', 'state': 'on' }); window.dispatchEvent(new CustomEvent('audiochannelchanged',{ detail: { channel: 'content' } })); }); teardown(function() { fakeTimer.restore(); }); test('CE check', function() { MockLock.mCallbacks.onsuccess(); assert.isTrue(MockCustomDialog.mShown); MockCustomDialog.mShowedCancel.callback(); assert.isTrue(soundManager.CEAccumulatorID > 0); assert.isTrue(soundManager.CEAccumulatorTime > 0); }); test('CE times out and reset to original state', function() { // trigger timer MockLock.mCallbacks.onsuccess(); fakeTimer.tick(55); assert.equal(0, soundManager.CEAccumulatorTime); assert.equal(0, soundManager.CETimestamp); }); }); }); });