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,392 @@
'use strict';
/* globals InputWindow, AppWindow */
require('/shared/test/unit/mocks/mock_service.js');
require('/shared/test/unit/mocks/mock_manifest_helper.js');
requireApp('system/test/unit/mock_app_transition_controller.js');
require('/js/browser_frame.js');
require('/js/app_window.js');
require('/js/browser_mixin.js');
require('/js/input_window.js');
var mocksForInputWindow = new window.MocksHelper([
'ManifestHelper', 'Service', 'AppTransitionController'
]).init();
suite('system/InputWindow', function() {
mocksForInputWindow.attachTestHelpers();
var app;
var keyboardContainer;
setup(function() {
keyboardContainer = document.createElement('div');
keyboardContainer.id = 'keyboards';
document.body.appendChild(keyboardContainer);
this.sinon.stub(document, 'getElementById', function(id) {
if (id === 'keyboards') {
return keyboardContainer;
} else {
return document.createElement('div');
}
});
app = new InputWindow({
manifest: {},
manifestURL: 'app://keyboard.gaiamobile.org/manifestURL.webapp',
origin: 'app://keyboard.gaiamobile.org',
path: '/index.html#ime1',
id: 'ime1'
});
});
teardown(function() {
document.body.removeChild(keyboardContainer);
});
test('Constructor', function() {
assert.isTrue(app.isInputMethod);
assert.equal(app.url, 'app://keyboard.gaiamobile.org/index.html#ime1');
assert.equal(app.browser.element.dataset.frameName, 'ime1');
});
suite('Event handlings', function() {
suite('mozbrowserresize', function() {
var stubPublish ;
var stubSetHeight;
setup(function(){
// this attaches mozbrowserresize listener
app._setAsActiveInput(true);
stubPublish = this.sinon.stub(app, 'publish');
stubSetHeight = this.sinon.stub(app, '_setHeight');
});
teardown(function(){
app._setAsActiveInput(false);
});
var triggerEvent = function (){
var evt = new CustomEvent('mozbrowserresize', {
detail: {
height: 200
}
});
sinon.spy(evt, 'stopPropagation');
app.browser.element.dispatchEvent(evt);
return evt;
};
test('transitionstate-invariant part', function() {
var evt = triggerEvent();
assert.isTrue(stubSetHeight.calledWith(200));
assert.isTrue(stubPublish.calledWith('ready'));
assert.isTrue(evt.stopPropagation.called);
});
test('transitionstate is opened', function() {
app.transitionController._transitionState = 'opened';
triggerEvent();
assert.isTrue(
stubPublish.calledWith('heightchanged'),
'heightchanged should be published when transitionState is opened'
);
});
// these states should not trigger heightchanged
var otherStates = ['opening', 'closing', 'closed'];
otherStates.forEach(state => {
test('transitionstate is ' + state, function() {
app.transitionController._transitionState = state;
triggerEvent();
assert.isFalse(
stubPublish.calledWith('heightchanged'),
`heightchanged should not be published
when transitionState is ${state}`
);
});
});
});
suite('_ready', function() {
var stubSetHeight;
var stubOpen;
setup(function(){
app.element.addEventListener('_ready', app);
app.height = 300;
app._pendingReady = true;
stubSetHeight = this.sinon.stub(app, '_setHeight');
stubOpen = this.sinon.stub(AppWindow.prototype, 'open');
});
test('handler', function() {
app.publish('ready');
assert.isTrue(stubSetHeight.calledWith(300));
assert.isTrue(stubOpen.calledOn(app),
'should call superclass open');
assert.isFalse(app._pendingReady, 'should reset _pendingReady');
});
test('immediateOpen = true', function() {
app.immediateOpen = true;
app.publish('ready');
assert.isTrue(stubOpen.calledWith('immediate'),
'open should be called with immediate');
});
test('immediateOpen = false', function() {
app.immediateOpen = false;
app.publish('ready');
assert.isFalse(stubOpen.calledWith('immediate'),
'open should not be called with immediate');
});
test('should not be able to triggered twice', function() {
app.publish('ready');
app.publish('ready');
assert.isFalse(stubSetHeight.calledTwice);
assert.isFalse(stubOpen.calledTwice);
});
});
});
suite('setHeight()', function() {
var oldDevicePixelRatio;
suiteSetup(function() {
oldDevicePixelRatio = window.devicePixelRatio;
Object.defineProperty(window, 'devicePixelRatio', {
get: function() {
return 2.5;
},
configurable: true
});
});
suiteTeardown(function() {
Object.defineProperty(window, 'devicePixelRatio', {
get: function() {
return oldDevicePixelRatio;
},
configurable: true
});
});
test('without rounding', function () {
app._setHeight(20);
assert.equal(app.height, 20);
});
test('with rounding', function () {
app._setHeight(25);
// with the round calculation the resulting height should be closed to
// 24.8, whose dpx should be one px less than ceil(25*dpx).
assert.isTrue(
Math.abs(app.height - 24.8) < Number.EPSILON
);
});
});
suite('setAsActiveInput', function() {
var stubSetVisible;
var stubSetInputMethodActive;
setup(function(){
stubSetVisible = this.sinon.stub(app, 'setVisible');
// perhaps the iframe (or any browser element) doesn't have
// setInputMethodActive, so we need to add it
if (app.browser.element.setInputMethodActive) {
stubSetInputMethodActive =
this.sinon.stub(app.browser.element, 'setInputMethodActive');
} else {
stubSetInputMethodActive =
app.browser.element.setInputMethodActive = this.sinon.stub();
}
app.height = 123;
});
test('active = true', function() {
var stubClassListAdd = this.sinon.stub(app.element.classList, 'add');
var stubAddEventListener =
this.sinon.stub(app.browser.element, 'addEventListener');
app._setAsActiveInput(true);
assert.isTrue(stubSetVisible.calledWith(true));
assert.isTrue(stubSetInputMethodActive.calledWith(true));
assert.isTrue(stubClassListAdd.calledWith('top-most'));
assert.isTrue(
stubAddEventListener.calledWith('mozbrowserresize', app, true)
);
assert.equal(app.height, 123);
});
test('active = false', function() {
var stubClassListRemove =
this.sinon.stub(app.element.classList, 'remove');
var stubRemoveEventListener =
this.sinon.stub(app.browser.element, 'removeEventListener');
app._setAsActiveInput(false);
assert.isTrue(stubSetVisible.calledWith(false));
assert.isTrue(stubSetInputMethodActive.calledWith(false));
assert.isTrue(stubClassListRemove.calledWith('top-most'));
assert.isTrue(
stubRemoveEventListener.calledWith('mozbrowserresize', app, true)
);
assert.strictEqual(app.height, 0);
});
});
test('close', function() {
var stubRemoveEventListener =
this.sinon.stub(app.element, 'removeEventListener');
var stubClose = this.sinon.stub(AppWindow.prototype, 'close');
app.close('immediate');
assert.isTrue(stubRemoveEventListener.calledWith('_ready'), app);
assert.isTrue(stubClose.calledOn(app), 'should call superclass open');
assert.isTrue(stubClose.calledWith('immediate'));
stubClose.reset();
app.close();
assert.isFalse(stubClose.calledWith('immediate'));
});
suite('open', function() {
setup(function() {
app.hash = '#ime1';
app.pathInitial = '/index.html';
});
test('should set _pendingReady', function() {
app._pendingReady = false;
app.open({
hash: '#ime1',
immediateOpen: false
});
assert.isTrue(app._pendingReady);
});
test('hash changed', function() {
app.immediateOpen = true;
var configs = {
id: 'ime2',
hash: '#ime2',
immediateOpen: false
};
var stubReadyHandler = this.sinon.stub(app, '_handle__ready');
var stubSetAsActiveInput = this.sinon.stub(app, '_setAsActiveInput');
app.open(configs);
assert.equal(app.browser.element.src,
'app://keyboard.gaiamobile.org/index.html#ime2');
assert.equal(app.browser.element.dataset.frameName, 'ime2');
assert.isFalse(app.immediateOpen);
assert.isTrue(stubSetAsActiveInput.calledWith(true));
app.publish('ready');
assert.isTrue(stubReadyHandler.called);
});
suite('hash not changed', function() {
var stubReadyHandler;
var configs = {
hash: '#ime1',
immediateOpen: false
};
setup(function() {
stubReadyHandler = this.sinon.stub(app, '_handle__ready');
this.sinon.stub(app, '_setAsActiveInput');
app.immediateOpen = false;
});
test('transitionState is closing', function() {
app.transitionController._transitionState = 'closing';
app.open(configs);
assert.isTrue(
app.immediateOpen,
'immediateOpen should be true if hash not changed and state = closing'
);
assert.isTrue(
stubReadyHandler.called,
`ready should be automatically triggered if hash not changed
and state = closing`
);
});
// these states should not immediateOpen + trigger ready event
var otherStates = ['opening', 'opened', 'closed'];
otherStates.forEach(state => {
test('transitionState is ' + state, function() {
app.transitionController._transitionState = state;
app.open(configs);
assert.isFalse(
app.immediateOpen,
`immediateOpen should be false if hash not changed
and state = ${state}`
);
assert.isFalse(
stubReadyHandler.called,
`ready should not be automatically triggered if hash not changed
and state = ${state}`
);
});
});
});
});
test('should not set/lock orientation', function() {
var stubLockOrientation =
this.sinon.stub(AppWindow.prototype, 'lockOrientation');
var stubSetOrientation =
this.sinon.stub(AppWindow.prototype, 'setOrientation');
app.lockOrientation();
app.setOrientation();
assert.isFalse(stubLockOrientation.called);
assert.isFalse(stubSetOrientation.called);
});
});