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.
This commit is contained in:
OverSu 2026-09-30 23:13:03 +02:00
commit b38dea0597
25901 changed files with 9982925 additions and 369 deletions

View file

@ -0,0 +1,507 @@
/* 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);
});
});
});
});