Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
507 lines
17 KiB
JavaScript
Executable file
507 lines
17 KiB
JavaScript
Executable file
/* global Bluetooth, MockSettingsListener, Service, MockL10n,
|
|
MockNavigatorSettings, MockNavigatormozSetMessageHandler,
|
|
MockMozBluetooth, MockBTAdapter, MocksHelper, MockLazyLoader */
|
|
'use strict';
|
|
|
|
require('/shared/test/unit/mocks/mock_navigator_moz_set_message_handler.js');
|
|
require('/shared/test/unit/mocks/mock_navigator_moz_bluetooth_v2.js');
|
|
require('/shared/test/unit/mocks/mock_settings_listener.js');
|
|
require('/shared/test/unit/mocks/mock_navigator_moz_settings.js');
|
|
require('/shared/test/unit/mocks/mock_lazy_loader.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/bluetooth_icon.js');
|
|
requireApp('system/js/bluetooth_transfer_icon.js');
|
|
requireApp('system/js/bluetooth_headphone_icon.js');
|
|
require('/shared/test/unit/mocks/mock_l10n.js');
|
|
|
|
function switchReadOnlyProperty(originObject, propName, targetObj) {
|
|
Object.defineProperty(originObject, propName, {
|
|
configurable: true,
|
|
get: function() { return targetObj; }
|
|
});
|
|
}
|
|
|
|
var mocksForBluetooth = new MocksHelper([
|
|
'SettingsListener',
|
|
'LazyLoader'
|
|
]).init();
|
|
|
|
suite('system/bluetooth_v2', function() {
|
|
var realSetMessageHandler;
|
|
var realSettings;
|
|
var realSettingsListener;
|
|
var realMozBluetooth;
|
|
var realL10n;
|
|
mocksForBluetooth.attachTestHelpers();
|
|
|
|
suiteSetup(function(done) {
|
|
MockLazyLoader.mLoadRightAway = true;
|
|
sinon.spy(MockLazyLoader, 'load');
|
|
|
|
realSetMessageHandler = navigator.mozSetMessageHandler;
|
|
navigator.mozSetMessageHandler = MockNavigatormozSetMessageHandler;
|
|
MockNavigatormozSetMessageHandler.mSetup();
|
|
|
|
realSettings = navigator.mozSettings;
|
|
navigator.mozSettings = MockNavigatorSettings;
|
|
|
|
realSettingsListener = window.SettingsListener;
|
|
window.SettingsListener = MockSettingsListener;
|
|
|
|
realMozBluetooth = navigator.mozBluetooth;
|
|
switchReadOnlyProperty(navigator, 'mozBluetooth', MockMozBluetooth);
|
|
|
|
realL10n = window.navigator.mozL10n;
|
|
window.navigator.mozL10n = MockL10n;
|
|
|
|
requireApp('system/js/bluetooth_v2.js', done);
|
|
});
|
|
|
|
suiteTeardown(function() {
|
|
MockNavigatormozSetMessageHandler.mTeardown();
|
|
navigator.mozSetMessageHandler = realSetMessageHandler;
|
|
window.SettingsListener = realSettingsListener;
|
|
switchReadOnlyProperty(navigator, 'mozBluetooth', realMozBluetooth);
|
|
navigator.mozL10n = realL10n;
|
|
});
|
|
|
|
setup(function() {
|
|
// instanciate bluetooth module
|
|
window.Bluetooth = new window.Bluetooth2();
|
|
});
|
|
|
|
teardown(function() {
|
|
window.Bluetooth.stop();
|
|
});
|
|
|
|
suite('setProfileConnected', function() {
|
|
var profiles = ['hfp', 'opp', 'a2dp', 'sco'];
|
|
setup(function() {
|
|
this.sinon.spy(window, 'dispatchEvent');
|
|
Bluetooth.icon = { update: function() {} };
|
|
this.sinon.stub(Bluetooth.icon, 'update');
|
|
});
|
|
|
|
test('nothing is called when wasConnected', function() {
|
|
profiles.forEach(function(profile){
|
|
Bluetooth['_' + profile + 'Connected'] = true;
|
|
Bluetooth._setProfileConnected(profile, true);
|
|
assert.isFalse(window.dispatchEvent.called);
|
|
assert.isFalse(Bluetooth.icon.update.called);
|
|
});
|
|
});
|
|
|
|
test('event is dispatched, Bluetooth icon is updated when disconnected',
|
|
function() {
|
|
profiles.forEach(function(profile){
|
|
Bluetooth['_' + profile + 'Connected'] = true;
|
|
Bluetooth._setProfileConnected(profile, false);
|
|
assert.ok(window.dispatchEvent.called);
|
|
assert.isTrue(Bluetooth.icon.update.called);
|
|
});
|
|
});
|
|
|
|
test('event is dispatched, Bluetooth icon is updated when first connect',
|
|
function() {
|
|
profiles.forEach(function(profile){
|
|
Bluetooth['_' + profile + 'Connected'] = false;
|
|
Bluetooth._setProfileConnected(profile, true);
|
|
assert.ok(window.dispatchEvent.called);
|
|
assert.isTrue(Bluetooth.icon.update.called);
|
|
});
|
|
});
|
|
|
|
test('event is dispatched with right detail object', function(done) {
|
|
Bluetooth._oppConnected = false;
|
|
var handler = function(evt) {
|
|
assert.equal(evt.detail.name, 'opp');
|
|
assert.isTrue(evt.detail.connected);
|
|
done();
|
|
};
|
|
var bindHandler = handler.bind(this);
|
|
window.addEventListener('bluetoothprofileconnectionchange',
|
|
bindHandler);
|
|
Bluetooth._setProfileConnected('opp', true);
|
|
window.removeEventListener('bluetoothprofileconnectionchange',
|
|
bindHandler);
|
|
});
|
|
|
|
test('transferIcon is not updated with non-OPP profile',
|
|
function() {
|
|
Bluetooth.transferIcon = { update: function() {} };
|
|
this.sinon.stub(Bluetooth.transferIcon, 'update');
|
|
Bluetooth._setProfileConnected('hfp', false);
|
|
assert.isFalse(Bluetooth.transferIcon.update.called);
|
|
Bluetooth._setProfileConnected('a2dp', false);
|
|
assert.isFalse(Bluetooth.transferIcon.update.called);
|
|
Bluetooth._setProfileConnected('sco', false);
|
|
});
|
|
|
|
test('transferIcon is updated with OPP profile', function() {
|
|
Bluetooth.transferIcon = { update: function() {} };
|
|
this.sinon.stub(Bluetooth.transferIcon, 'update');
|
|
Bluetooth._setProfileConnected('opp', false);
|
|
assert.isTrue(Bluetooth.transferIcon.update.called);
|
|
Bluetooth._setProfileConnected('opp', true);
|
|
assert.isTrue(Bluetooth.transferIcon.update.calledTwice);
|
|
});
|
|
});
|
|
|
|
suite('isProfileConnected', function() {
|
|
var profiles = ['hfp', 'opp', 'a2dp', 'sco'];
|
|
|
|
test('return true when profile is connected', function() {
|
|
profiles.forEach(function(profile) {
|
|
Bluetooth['_' + profile + 'Connected'] = false;
|
|
});
|
|
profiles.forEach(function(profile) {
|
|
assert.isFalse(Bluetooth._isProfileConnected(profile));
|
|
});
|
|
});
|
|
|
|
test('return true when profile is connected', function() {
|
|
profiles.forEach(function(profile) {
|
|
Bluetooth['_' + profile + 'Connected'] = true;
|
|
});
|
|
profiles.forEach(function(profile) {
|
|
assert.ok(Bluetooth._isProfileConnected(profile));
|
|
});
|
|
});
|
|
});
|
|
|
|
suite('Initialize', function() {
|
|
setup(function() {
|
|
this.sinon.spy(navigator.mozBluetooth, 'addEventListener');
|
|
this.sinon.stub(Bluetooth, '_setProfileConnected');
|
|
this.sinon.stub(Bluetooth, '_initDefaultAdapter');
|
|
this.sinon.spy(window, 'addEventListener');
|
|
this.sinon.spy(window, 'dispatchEvent');
|
|
this.sinon.spy(Service, 'register');
|
|
this.sinon.spy(Service, 'registerState');
|
|
window.BluetoothTransfer = { start: function() {} };
|
|
Bluetooth.start();
|
|
});
|
|
|
|
test('initDefaultAdapter is called', function() {
|
|
assert.ok(Bluetooth._initDefaultAdapter.called);
|
|
});
|
|
|
|
test('listener called', function() {
|
|
assert.ok(navigator.mozBluetooth.addEventListener.
|
|
calledWith('attributechanged'));
|
|
assert.ok(window.addEventListener
|
|
.calledWith('request-enable-bluetooth'));
|
|
assert.ok(window.addEventListener
|
|
.calledWith('request-disable-bluetooth'));
|
|
});
|
|
|
|
test('MessageHandler bluetooth-opp-transfer-start is called',
|
|
function() {
|
|
MockNavigatormozSetMessageHandler.mTrigger(
|
|
'bluetooth-opp-transfer-start', {
|
|
source: {
|
|
data: {}
|
|
}
|
|
});
|
|
|
|
assert.ok(Bluetooth._setProfileConnected.called);
|
|
assert.ok(window.dispatchEvent.called);
|
|
});
|
|
|
|
test('MessageHandler bluetooth-opp-transfer-complete is called',
|
|
function() {
|
|
MockNavigatormozSetMessageHandler.mTrigger(
|
|
'bluetooth-opp-transfer-complete', {
|
|
source: {
|
|
data: {}
|
|
}
|
|
});
|
|
|
|
assert.ok(Bluetooth._setProfileConnected.called);
|
|
assert.ok(window.dispatchEvent.called);
|
|
});
|
|
|
|
test('register request', function() {
|
|
assert.ok(Service.register.calledWith('adapter'));
|
|
assert.ok(Service.register.calledWith('pair'));
|
|
assert.ok(Service.register.calledWith('getPairedDevices'));
|
|
});
|
|
|
|
test('register state', function() {
|
|
assert.ok(Service.registerState.calledWith('isEnabled'));
|
|
assert.ok(Service.registerState.calledWith('getAdapter'));
|
|
assert.ok(Service.registerState.calledWith('isOPPProfileConnected'));
|
|
assert.ok(Service.registerState.calledWith('isA2DPProfileConnected'));
|
|
assert.ok(Service.registerState.calledWith('isSCOProfileConnected'));
|
|
});
|
|
|
|
test('Should lazy load icons', function() {
|
|
assert.isTrue(MockLazyLoader.load.calledWith(
|
|
['js/bluetooth_transfer.js',
|
|
'js/bluetooth_icon.js',
|
|
'js/bluetooth_transfer_icon.js',
|
|
'js/bluetooth_headphone_icon.js']
|
|
));
|
|
});
|
|
});
|
|
|
|
suite('initDefaultAdapter', function() {
|
|
setup(function() {
|
|
this.sinon.stub(Bluetooth, '_dispatchEnableState');
|
|
Bluetooth._bluetooth = MockMozBluetooth;
|
|
});
|
|
|
|
test('defaultAdapter is available', function() {
|
|
Bluetooth._bluetooth.defaultAdapter = MockBTAdapter;
|
|
Bluetooth._initDefaultAdapter();
|
|
|
|
assert.equal(Bluetooth._adapter, navigator.mozBluetooth.defaultAdapter);
|
|
assert.ok(Bluetooth._dispatchEnableState.called);
|
|
});
|
|
|
|
test('defaultAdapter is not available', function() {
|
|
Bluetooth._bluetooth.defaultAdapter = null;
|
|
Bluetooth._initDefaultAdapter();
|
|
|
|
assert.equal(Bluetooth._adapter, null);
|
|
});
|
|
});
|
|
|
|
suite('Adapter Available Handler', function() {
|
|
setup(function() {
|
|
Bluetooth._adapter = MockBTAdapter;
|
|
this.sinon.stub(Bluetooth._adapter, 'addEventListener');
|
|
Bluetooth._adapterAvailableHandler();
|
|
});
|
|
|
|
test('return true when profile is connected', function() {
|
|
assert.ok(MockBTAdapter.addEventListener.
|
|
calledWith('attributechanged'));
|
|
assert.ok(MockBTAdapter.addEventListener
|
|
.calledWith('hfpstatuschanged'));
|
|
assert.ok(MockBTAdapter.addEventListener
|
|
.calledWith('a2dpstatuschanged'));
|
|
assert.ok(MockBTAdapter.addEventListener
|
|
.calledWith('scostatuschanged'));
|
|
});
|
|
});
|
|
|
|
suite('Adapter Unavailable Handler', function() {
|
|
setup(function() {
|
|
Bluetooth._adapter = MockBTAdapter;
|
|
this.sinon.stub(Bluetooth._adapter, 'removeEventListener');
|
|
Bluetooth._adapterUnavailableHandler();
|
|
});
|
|
|
|
test('removeEventListener is called', function() {
|
|
assert.ok(Bluetooth._adapter.removeEventListener
|
|
.calledWith('hfpstatuschanged'));
|
|
assert.ok(Bluetooth._adapter.removeEventListener
|
|
.calledWith('a2dpstatuschanged'));
|
|
assert.ok(Bluetooth._adapter.removeEventListener
|
|
.calledWith('scostatuschanged'));
|
|
assert.ok(Bluetooth._adapter.removeEventListener
|
|
.calledWith('attributechanged'));
|
|
});
|
|
});
|
|
|
|
suite('handle Bluetooth states', function() {
|
|
setup(function() {
|
|
this.sinon.spy(Bluetooth, '_requestEnableHandler');
|
|
this.sinon.spy(Bluetooth, '_requestDisableHandler');
|
|
this.sinon.spy(Bluetooth, '_dispatchEnableState');
|
|
this.sinon.stub(Bluetooth, '_initDefaultAdapter');
|
|
|
|
this.sinon.stub(MockBTAdapter, 'enable', function() {
|
|
return { then: function(resolve) { resolve(); } };
|
|
});
|
|
this.sinon.stub(MockBTAdapter, 'disable', function() {
|
|
return { then: function(resolve) { resolve(); } };
|
|
});
|
|
});
|
|
|
|
test('request-enable-bluetooth is called', function() {
|
|
Bluetooth._adapter = MockBTAdapter;
|
|
Bluetooth.start();
|
|
window.dispatchEvent(new CustomEvent('request-enable-bluetooth'));
|
|
|
|
assert.ok(Bluetooth._requestEnableHandler.called);
|
|
assert.ok(MockBTAdapter.enable.called);
|
|
});
|
|
|
|
test('request-enable-bluetooth is called when adapter is not available',
|
|
function() {
|
|
Bluetooth._adapter = null;
|
|
Bluetooth.start();
|
|
window.dispatchEvent(new CustomEvent('request-enable-bluetooth'));
|
|
|
|
assert.ok(Bluetooth._dispatchEnableState.called);
|
|
});
|
|
|
|
test('request-disable-bluetooth is called', function() {
|
|
Bluetooth._adapter = MockBTAdapter;
|
|
Bluetooth.start();
|
|
window.dispatchEvent(new CustomEvent('request-disable-bluetooth'));
|
|
|
|
assert.ok(Bluetooth._requestDisableHandler.called);
|
|
assert.ok(MockBTAdapter.disable.called);
|
|
});
|
|
|
|
test('request-disable-bluetooth is called when adapter is not available',
|
|
function() {
|
|
Bluetooth._adapter = null;
|
|
Bluetooth.start();
|
|
|
|
window.dispatchEvent(new CustomEvent('request-disable-bluetooth'));
|
|
assert.ok(Bluetooth._dispatchEnableState.called);
|
|
});
|
|
});
|
|
|
|
suite('bluetoothAdapterHandler', function() {
|
|
setup(function() {
|
|
this.sinon.spy(MockNavigatorSettings, 'createLock');
|
|
this.sinon.stub(window, 'dispatchEvent');
|
|
Bluetooth._adapter = MockBTAdapter;
|
|
Bluetooth.icon = { update: function() {} };
|
|
this.sinon.stub(Bluetooth.icon, 'update');
|
|
});
|
|
|
|
teardown(function() {
|
|
Bluetooth._adapter = null;
|
|
Bluetooth.icon = null;
|
|
});
|
|
|
|
test('bluetooth state is enabled', function() {
|
|
Bluetooth._adapter.state = 'enabled';
|
|
Bluetooth._btAdapterHandler({attrs: ['state']});
|
|
|
|
assert.isTrue(Bluetooth._isEnabled);
|
|
assert.ok(window.dispatchEvent.called);
|
|
assert.ok(Bluetooth.icon.update.called);
|
|
});
|
|
|
|
test('bluetooth state is disabled', function() {
|
|
Bluetooth._adapter.state = 'disabled';
|
|
Bluetooth._btAdapterHandler({attrs: ['state']});
|
|
|
|
assert.isFalse(Bluetooth._isEnabled);
|
|
assert.ok(window.dispatchEvent.called);
|
|
assert.ok(Bluetooth.icon.update.called);
|
|
});
|
|
});
|
|
|
|
suite('btManagerHandler', function() {
|
|
setup(function() {
|
|
this.sinon.stub(Bluetooth, '_adapterUnavailableHandler');
|
|
Bluetooth._bluetooth = window.navigator.mozBluetooth;
|
|
});
|
|
|
|
teardown(function() {
|
|
Bluetooth._adapter = null;
|
|
MockBTAdapter.state = '';
|
|
});
|
|
|
|
test('default adapter and state are updated when defaultAdapter' +
|
|
'is changed', function() {
|
|
var evt = {
|
|
attrs: ['defaultAdapter']
|
|
};
|
|
MockMozBluetooth.defaultAdapter = MockBTAdapter;
|
|
MockBTAdapter.state = 'enabled';
|
|
Bluetooth._btManagerHandler(evt);
|
|
|
|
assert.equal(Bluetooth._adapter, MockBTAdapter);
|
|
assert.ok(Bluetooth._isEnabled, true);
|
|
});
|
|
|
|
test('functions are not called when defaultAdapter is null',
|
|
function() {
|
|
var evt = {
|
|
attrs: ['defaultAdapter']
|
|
};
|
|
MockMozBluetooth.defaultAdapter = null;
|
|
Bluetooth._btManagerHandler(evt);
|
|
|
|
assert.equal(Bluetooth._adapter, null);
|
|
assert.ok(Bluetooth._adapterUnavailableHandler.called);
|
|
});
|
|
|
|
test('functions are not called when no matched attribute',
|
|
function() {
|
|
var evt = {
|
|
attrs: []
|
|
};
|
|
MockMozBluetooth.defaultAdapter = null;
|
|
Bluetooth._btManagerHandler(evt);
|
|
|
|
assert.equal(Bluetooth._adapter, null);
|
|
assert.ok(!Bluetooth._adapterUnavailableHandler.called);
|
|
});
|
|
});
|
|
|
|
suite('oppTransferStartHandler', function() {
|
|
test('event is dispatched with right detail object', function(done) {
|
|
this.sinon.stub(Bluetooth, '_setProfileConnected');
|
|
var transferInfo = this.sinon.stub();
|
|
var handler = function(evt) {
|
|
assert.equal(evt.detail.transferInfo, transferInfo);
|
|
done();
|
|
};
|
|
var bindHandler = handler.bind(this);
|
|
window.addEventListener('bluetooth-opp-transfer-start',
|
|
bindHandler);
|
|
Bluetooth._oppTransferStartHandler(transferInfo);
|
|
assert.ok(Bluetooth._setProfileConnected.called);
|
|
window.removeEventListener('bluetooth-opp-transfer-start',
|
|
bindHandler);
|
|
});
|
|
});
|
|
|
|
suite('oppTransferCompleteHandler', function() {
|
|
test('event is dispatched with right detail object', function(done) {
|
|
this.sinon.stub(Bluetooth, '_setProfileConnected');
|
|
var transferInfo = this.sinon.stub();
|
|
var handler = function(evt) {
|
|
assert.equal(evt.detail.transferInfo, transferInfo);
|
|
done();
|
|
};
|
|
var bindHandler = handler.bind(this);
|
|
window.addEventListener('bluetooth-opp-transfer-complete',
|
|
bindHandler);
|
|
Bluetooth._oppTransferCompleteHandler(transferInfo);
|
|
assert.ok(Bluetooth._setProfileConnected.called);
|
|
window.removeEventListener('bluetooth-opp-transfer-complete',
|
|
bindHandler);
|
|
});
|
|
});
|
|
|
|
suite('service requests', function() {
|
|
test('request the adapter', function() {
|
|
Bluetooth._adapter = MockBTAdapter;
|
|
Service.request('Bluetooth:adapter').then(function(value) {
|
|
assert.equal(value, Bluetooth._adapter);
|
|
});
|
|
});
|
|
|
|
test('request pair', function() {
|
|
Bluetooth._adapter = MockBTAdapter;
|
|
var mac = '01:23:45:67:89:AB';
|
|
this.sinon.spy(MockBTAdapter, 'pair');
|
|
Service.request('Bluetooth:pair', mac).then(function() {
|
|
assert.ok(MockBTAdapter.pair.calledWith(mac));
|
|
});
|
|
});
|
|
|
|
test('request getPairedDevices', function() {
|
|
Bluetooth._adapter = MockBTAdapter;
|
|
this.sinon.spy(MockBTAdapter, 'getPairedDevices');
|
|
Service.request('Bluetooth:getPairedDevices')
|
|
.then(function() {
|
|
assert.ok(MockBTAdapter.getPairedDevices.called);
|
|
});
|
|
});
|
|
});
|
|
});
|