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,197 @@
'use strict';
/* global BookmarkEditor, msgHandler, realMozSetMessageHandler, utils,
BookmarkRemover */
/* global requireApp, require, suite, suiteTeardown, suiteSetup, test, assert,
MocksHelper, MockL10n, sinon */
require('/shared/test/unit/mocks/mock_l10n.js');
requireApp('bookmark/test/unit/mock_mozsetmessagehandler.js');
requireApp('bookmark/test/unit/mock_bookmark_editor.js');
requireApp('bookmark/js/bookmark_remover.js');
requireApp('bookmark/js/components/status.js');
requireApp('bookmark/js/activity_handler.js');
var mocksHelperForSaveBookmark = new MocksHelper([
'BookmarkEditor'
]);
mocksHelperForSaveBookmark.init();
suite('activity_handler.js >', function() {
mocksHelperForSaveBookmark.attachTestHelpers();
var realMozL10n;
suiteSetup(function() {
realMozL10n = navigator.mozL10n;
navigator.mozL10n = MockL10n;
});
suiteTeardown(function() {
navigator.mozSetMessageHandler = realMozSetMessageHandler;
navigator.mozL10n = realMozL10n;
msgHandler.activity = null;
});
function createSource(name, type) {
return {
name: name,
data: {
type: type
}
};
}
suite('Initialization >', function() {
test('Bookmark app is listening right now ', function() {
// The handler was defined
assert.isFunction(msgHandler.activity);
// The handler defines a parameter -> the activity
assert.equal(msgHandler.activity.length, 1);
});
});
suite('Adding and updating bookmarks >', function() {
suiteSetup(function() {
utils.status.init();
// We change the duration of the status in order to avoid timeout
utils.status.setDuration(400);
});
suiteTeardown(function() {
utils.status.destroy();
});
test.skip('The new bookmark has been added correctly ', function(done) {
msgHandler.activity({
source: createSource('save-bookmark', 'url'),
postResult: function(result) {
assert.equal(result, 'saved');
done();
}
});
// The user clicks on <save> button
BookmarkEditor.save(true);
});
test('The bookmark already exists and it is updated ', function(done) {
msgHandler.activity({
source: createSource('save-bookmark', 'url'),
postResult: function(result) {
assert.equal(result, 'updated');
done();
}
});
// The user clicks on <save> button
BookmarkEditor.save();
});
test('Bookmarking failed - request cancelled by user ', function(done) {
msgHandler.activity({
source: createSource('save-bookmark', 'url'),
postError: function(result) {
assert.equal(result, 'cancelled');
done();
}
});
// The user cancels the request
BookmarkEditor.cancel();
});
test('The status is displayed when a bookmark has been added correctly ',
function(done) {
msgHandler.activity({
source: createSource('save-bookmark', 'url'),
postResult: function() { }
});
window.addEventListener('status-showed', function showed() {
window.removeEventListener('status-showed', showed);
assert.isTrue(document.querySelector('[role="status"] p').textContent.
length > 0);
});
window.addEventListener('status-hidden', function hidden() {
window.removeEventListener('status-hidden', hidden);
done();
});
BookmarkEditor.save(true);
});
});
suite('Removing bookmarks >', function() {
var stub = null,
removed = true;
suiteSetup(function() {
stub = sinon.stub(BookmarkRemover, 'init', function(options) {
removed ? options.onremoved() : options.oncancelled();
});
});
suiteTeardown(function() {
stub.restore();
});
test('The bookmark has been removed correctly ', function(done) {
msgHandler.activity({
source: createSource('remove-bookmark', 'url'),
postResult: function(result) {
assert.equal(result, 'removed');
done();
}
});
});
test('Removing failed ', function(done) {
removed = false;
msgHandler.activity({
source: createSource('remove-bookmark', 'url'),
postError: done
});
});
});
suite('Common errors >', function() {
test('Name not supported ', function(done) {
// "save-watermelon" activities are not supported
msgHandler.activity({
source: createSource('save-watermelon', 'url'),
postError: function(result) {
assert.equal(result, 'name not supported');
done();
}
});
});
test('Type not supported for save-bookmark', function(done) {
// We don't support the type "cherry"
msgHandler.activity({
source: createSource('save-bookmark', 'cherry'),
postError: function(result) {
assert.equal(result, 'type not supported');
done();
}
});
});
test('Type not supported for remove-bookmark', function(done) {
// We don't support the type "lemon"
msgHandler.activity({
source: createSource('remove-bookmark', 'lemon'),
postError: function(result) {
assert.equal(result, 'type not supported');
done();
}
});
});
});
});

View file

@ -0,0 +1,222 @@
'use strict';
/* global loadBodyHTML, BookmarkEditor, BookmarksDatabase, Icon */
/* global requireApp, require, suite, suiteTeardown, suiteSetup, test, assert,
sinon, MocksHelper */
require('/shared/test/unit/load_body_html_helper.js');
require('/shared/test/unit/mocks/mock_l10n.js');
require('/shared/test/unit/mocks/mock_web_manifest_helper.js');
require('/shared/test/unit/mocks/mock_icons_helper.js');
require('/shared/js/homescreens/icon.js');
requireApp('bookmark/js/bookmark_editor.js');
require('/shared/js/bookmarks_database.js');
require('/shared/js/url_helper.js');
var mocksForBookmarkEditor = new MocksHelper([
'IconsHelper', 'WebManifestHelper'
]).init();
suite('bookmark_editor.js >', function() {
var getStub, iconRenderStub, realL10n;
mocksForBookmarkEditor.attachTestHelpers();
var name = 'Mozilla';
var url = 'http://www.mozilla.org/es-ES/firefox/new/';
var bookmark = {
name: name,
url: url
};
var databaseInError = false;
suiteSetup(function() {
realL10n = navigator.mozL10n;
navigator.mozL10n = window.MockL10n;
loadBodyHTML('/save.html');
getStub = sinon.stub(BookmarksDatabase, 'get', function(purl) {
return {
then: function(resolve, refect) {
databaseInError ? refect() : resolve (purl === url ? bookmark : null);
}
};
});
iconRenderStub = sinon.stub(Icon.prototype, 'render', function() {});
});
suiteTeardown(function() {
navigator.mozL10n = realL10n;
document.body.innerHTML = '';
databaseInError = false;
getStub.restore();
iconRenderStub.restore();
});
function noop() {
// Do nothing
}
function dispatchInputEvent() {
BookmarkEditor.form.dispatchEvent(new CustomEvent('input'));
}
suite('Add UI initialized correctly >', function() {
var expectedName = 'Telefonica';
suiteSetup(function() {
BookmarkEditor.init({
data: {
name: expectedName
},
oncancelled: noop
});
});
test('The title has to be defined from options.data.name >', function() {
assert.equal(document.getElementById('bookmark-title').value,
expectedName);
});
test('Checking styles', function() {
assert.equal(document.body.dataset.mode, 'add');
});
});
suite('Edit UI initialized correctly >', function() {
suiteSetup(function() {
BookmarkEditor.init({
data: bookmark,
oncancelled: noop
});
});
test('The title has to be defined from datastore >', function() {
assert.equal(document.getElementById('bookmark-title').value, name);
});
test('Checking styles', function() {
assert.equal(document.body.dataset.mode, 'put');
});
test('Checking "done" button after writing', function() {
document.getElementById('bookmark-form').
dispatchEvent(new CustomEvent('input'));
assert.isFalse(BookmarkEditor.saveButton.disabled);
});
});
suite('UI initialized correctly as "add" when database fails >', function() {
var expectedName = 'Telefonica';
var expectedURL = 'www.telefonica.es';
suiteSetup(function() {
databaseInError = false;
BookmarkEditor.init({
data: {
name: expectedName,
url: expectedURL
},
oncancelled: noop
});
});
test('The title has to be defined from options.data.name >', function() {
assert.equal(document.getElementById('bookmark-title').value,
expectedName);
});
test('Checking styles', function() {
assert.equal(document.body.dataset.mode, 'add');
});
test('Checking "add" button initially', function() {
assert.isFalse(BookmarkEditor.saveButton.disabled);
});
});
suite('Invalid website name >', function() {
suiteSetup(function() {
BookmarkEditor.init({
data: {
name: '',
url: url
},
oncancelled: noop
});
});
test('Bookmarks with blank title should not be saved >', function() {
assert.isTrue(BookmarkEditor.saveButton.disabled,
'Blank title, add button should be disabled');
var saveSpy = sinon.spy(BookmarkEditor, 'save');
BookmarkEditor._submit(new CustomEvent('submit'));
assert.equal(saveSpy.callCount, 0);
BookmarkEditor.save.restore();
});
test('Check save button typing website name ', function() {
BookmarkEditor.bookmarkTitle.value = 'Telefonica';
dispatchInputEvent();
assert.isFalse(BookmarkEditor.saveButton.disabled);
BookmarkEditor.bookmarkTitle.value = '';
dispatchInputEvent();
assert.isTrue(BookmarkEditor.saveButton.disabled);
BookmarkEditor.bookmarkTitle.value = 'Mozilla';
dispatchInputEvent();
assert.isFalse(BookmarkEditor.saveButton.disabled);
});
});
suite('Install App >', function() {
suiteSetup(function() {
BookmarkEditor.init({
data: {
name: 'My App',
url: 'http://example.com'
},
oncancelled: noop
});
});
test('_fetchManifest()', function(done) {
var stubRenderAppIcon = sinon.stub(BookmarkEditor, '_renderAppIcon',
function(manifest, size) {}
);
BookmarkEditor._fetchManifest().then(
function () {
assert.isFalse(
BookmarkEditor.appInstallationSection.classList.contains(
'hidden'));
assert.equal(BookmarkEditor.appNameText.textContent, 'App');
done();
stubRenderAppIcon.restore();
},
function (err) {
done(err);
console.error(err);
});
});
test('_renderAppIcon()', function() {
this.sinon.stub(window.IconsHelper, 'getBestIconFromWebManifest',
function() {
return new URL('http://example.com/icon.png');
});
BookmarkEditor._renderAppIcon({}, 60);
assert.equal(BookmarkEditor.appIcon.getAttribute('src'),
'http://example.com/icon.png');
});
});
});

View file

@ -0,0 +1,153 @@
'use strict';
/* global BookmarkRemover, loadBodyHTML, BookmarksDatabase */
/* global requireApp, require, suite, suiteTeardown, suiteSetup, test, assert,
sinon, teardown, setup, MockL10n */
require('/shared/js/bookmarks_database.js');
require('/shared/test/unit/load_body_html_helper.js');
require('/shared/test/unit/mocks/mock_l10n.js');
requireApp('bookmark/js/bookmark_remover.js');
suite('bookmark_remover.js >', function() {
var getStub;
var realMozL10n;
var name = 'Mozilla';
var url = 'http://www.mozilla.org/es-ES/firefox/new/';
var bookmark = {
name: name,
url: url
};
var databaseInError = false;
suiteSetup(function() {
getStub = sinon.stub(BookmarksDatabase, 'get', function(purl) {
return {
then: function(resolve, reject) {
databaseInError ? reject('rejected') :
resolve (purl === url ? bookmark : null);
}
};
});
realMozL10n = navigator.mozL10n;
navigator.mozL10n = MockL10n;
});
suiteTeardown(function() {
getStub.restore();
navigator.mozL10n = realMozL10n;
});
setup(function() {
loadBodyHTML('/remove.html');
});
teardown(function() {
document.body.innerHTML = '';
databaseInError = false;
});
test('UI initialized correctly >', function() {
BookmarkRemover.init({
id: bookmark.url
});
assert.isTrue(document.getElementById('title').dataset.l10nArgs
.contains(name));
assert.isTrue(document.getElementById('message').dataset.l10nArgs
.contains(name));
});
test('Handles quotes in bookmark name >', function() {
bookmark.name = name = 'Mozilla"\'';
BookmarkRemover.init({
id: bookmark.url
});
var titleArgs =
JSON.parse(document.getElementById('title').dataset.l10nArgs);
var messageArgs =
JSON.parse(document.getElementById('message').dataset.l10nArgs);
assert.equal(titleArgs.name, name);
assert.equal(messageArgs.name, name);
});
test('Bookmark does not exist >', function(done) {
BookmarkRemover.init({
id: bookmark.url + 'blabla',
oncancelled: function(e) {
assert.equal(e, 'bookmark does not exist');
done();
}
});
});
test('Getting bookmark failed >', function(done) {
databaseInError = true;
BookmarkRemover.init({
id: bookmark.url,
oncancelled: function(e) {
assert.equal(e, 'rejected');
done();
}
});
});
test('User cancels >', function(done) {
BookmarkRemover.init({
id: bookmark.url,
oncancelled: function(e) {
assert.equal(e, 'cancelled');
done();
}
});
document.getElementById('cancel-action').click();
});
test('User confirms and bookmark is removed >', function(done) {
var stub = sinon.stub(BookmarksDatabase, 'remove', function(id) {
assert.equal(id, bookmark.url);
return {
then: function(resolve) {
resolve();
}
};
});
BookmarkRemover.init({
id: bookmark.url,
onremoved: function() {
stub.restore();
done();
}
});
document.getElementById('remove-action').click();
});
test('User confirms but it fails >', function(done) {
var stub = sinon.stub(BookmarksDatabase, 'remove', function(id) {
assert.equal(id, bookmark.url);
return {
then: function(resolve, reject) {
reject('failed');
}
};
});
BookmarkRemover.init({
id: bookmark.url,
oncancelled: function(e) {
assert.equal(e, 'failed');
stub.restore();
done();
}
});
document.getElementById('remove-action').click();
});
});

View file

@ -0,0 +1,311 @@
'use strict';
/* global BookmarksDatabase, MockDatastore, MockNavigatorDatastore */
/* global require, suite, suiteTeardown, suiteSetup, test, assert, teardown,
setup */
require('/shared/test/unit/mocks/mock_navigator_datastore.js');
require('/shared/js/bookmarks_database.js');
suite('bookmarks_database.js >', function() {
var realDatastore = null,
url = 'http://mozilla.org',
name = 'mozilla',
data = {
url: url,
name: name
};
suiteSetup(function() {
realDatastore = navigator.getDataStores;
});
suiteTeardown(function() {
navigator.getDataStores = realDatastore;
});
setup(function() {
navigator.getDataStores = MockNavigatorDatastore.getDataStores;
});
teardown(function() {
MockDatastore._inError = false;
MockDatastore._records = Object.create(null);
});
function assertEvent(type, event) {
assert.equal(event.type, type);
assert.equal(event.target.id, url);
assert.equal(event.target.url, url);
assert.equal(event.target.name, name);
}
test('testing not getDataStores defined >', function(done) {
navigator.getDataStores = undefined;
BookmarksDatabase.getRevisionId().then(function(id) {
// Do noting
}, function(e) {
assert.equal(e.name, 'NO_DATASTORE');
done();
});
});
test('testing no access to datastore >', function(done) {
navigator.getDataStores = function() {
return {
then: function(resolve, reject) {
resolve({
length: 0
});
}
};
};
BookmarksDatabase.getRevisionId().then(function(id) {
// Do noting
}, function(e) {
assert.equal(e.name, 'NO_ACCESS_TO_DATASTORE');
done();
});
});
test('calling to add method - added >', function(done) {
BookmarksDatabase.add(data).then(function(value) {
assert.isTrue(value);
done();
});
});
test('calling to add method - updated >', function(done) {
var expectedName = name + 'corporation';
BookmarksDatabase.add(data).then(function(value) {
assert.isTrue(value);
BookmarksDatabase.add({
url: url,
name: expectedName
}).then(function(value) {
assert.isUndefined(value);
done();
});
});
});
test('calling to add method - failed >', function(done) {
MockDatastore._inError = true;
BookmarksDatabase.add(data).then(function() {
// Do nothing here
}, function() {
done();
});
});
test('calling to put method - OK >', function(done) {
var id = url;
var expectedName = 'Telefonica';
var expectedURL = 'http://www.telefonica.es';
MockDatastore._records[id] = {
id: id,
url: url,
name: name
};
BookmarksDatabase.put({
id: id,
url: expectedURL,
name: expectedName
}).then(function onSuccess() {
BookmarksDatabase.get(id).then(function(bookmark) {
assert.equal(bookmark.name, expectedName);
assert.equal(bookmark.url, expectedURL);
assert.equal(bookmark.id, id);
done();
});
});
});
test('calling to put method - failed >', function(done) {
MockDatastore._inError = true;
BookmarksDatabase.put(data).then(function() {
// Do nothing here
}, function() {
done();
});
});
test('calling to remove method - OK >', function(done) {
var id = url;
MockDatastore._records[id] = {
id: id,
url: url,
name: name
};
BookmarksDatabase.remove(id).then(function(bookmark) {
assert.equal(Object.keys(MockDatastore._records).length, 0);
done();
});
});
test('calling to remove method - failed >', function(done) {
MockDatastore._inError = true;
BookmarksDatabase.remove(url).then(function() {
// Do nothing here
}, function() {
done();
});
});
test('calling to get method - OK >', function(done) {
BookmarksDatabase.add(data).then(function() {
BookmarksDatabase.get(url).then(function(bookmark) {
assert.equal(bookmark.name, name);
assert.equal(bookmark.url, url);
assert.equal(bookmark.id, url);
done();
});
});
});
test('calling to get method - failed >', function(done) {
MockDatastore._inError = true;
BookmarksDatabase.get('www.telefonica.es').then(function() {
// Do nothing here
}, function() {
done();
});
});
test('calling to getRevisionId method - OK >', function(done) {
BookmarksDatabase.getRevisionId().then(function(id) {
assert.equal(id, MockDatastore.revisionId);
done();
});
});
test('calling to getAll method - OK >', function(done) {
MockDatastore.sync = function() {
var cursor = {
next: function() {
cursor.next = function() {
return new window.Promise(function(resolve, reject) {
resolve({
operation: 'done'
});
});
};
return new window.Promise(function(resolve, reject) {
resolve({
operation: 'add',
data: {
id: url,
url: url,
name: name
}
});
});
}
};
return cursor;
};
BookmarksDatabase.getAll().then(function(bookmarks) {
assert.equal(Object.keys(bookmarks).length, 1);
assert.equal(bookmarks[url].name, name);
assert.equal(bookmarks[url].id, url);
assert.equal(bookmarks[url].url, url);
done();
});
});
test('calling to getAll method - failed >', function(done) {
MockDatastore.sync = function() {
var cursor = {
next: function() {
return new window.Promise(function(resolve, reject) {
reject();
});
}
};
return cursor;
};
BookmarksDatabase.getAll().then(function(bookmarks) {
// Do nothing
}, function() {
done();
});
});
test('testing addEventListener for "added" event >', function(done) {
BookmarksDatabase.addEventListener('added', function onAdded(event) {
BookmarksDatabase.removeEventListener('added', onAdded);
assertEvent('added', event);
done();
});
BookmarksDatabase.add(data);
});
test('testing addEventListener for context >', function(done) {
var myObject = {
handleEvent: function(event) {
BookmarksDatabase.removeEventListener('added', myObject);
assert.equal(this, myObject);
assertEvent('added', event);
done();
}
};
BookmarksDatabase.addEventListener('added', myObject);
BookmarksDatabase.add(data);
});
test('testing addEventListener for "updated" event >', function(done) {
// Testing handleEvent instead of a callback directly
var handler = {
handleEvent: function(event) {
BookmarksDatabase.removeEventListener('updated', handler);
assertEvent('updated', event);
done();
}
};
BookmarksDatabase.addEventListener('updated', handler);
BookmarksDatabase.add(data).then(function onAdded() {
BookmarksDatabase.add(data);
});
});
test('testing removeEventListener >', function(done) {
var onAdded = function() {
done(new Error('The "added" listener should NOT be called!!!'));
};
BookmarksDatabase.addEventListener('added', onAdded);
var ret = BookmarksDatabase.removeEventListener('added', onAdded);
assert.isTrue(ret);
BookmarksDatabase.add(data).then(function() {
done();
});
});
test('testing removeEventListener unknown type >', function() {
assert.isFalse(BookmarksDatabase.removeEventListener('dog', function() {
// Do nothing...
}));
});
test('testing removeEventListener unknown callback >', function() {
assert.isFalse(BookmarksDatabase.removeEventListener('added', function() {
// Do nothing...
}));
});
});

View file

@ -0,0 +1,22 @@
'use strict';
/* exported MockBookmarkEditor */
var MockBookmarkEditor = {
init: function mbe_init(options) {
this.onsaved = options.onsaved;
this.oncancelled = options.oncancelled;
},
close: function mbe_close() {
this.oncancelled();
},
save: function mbe_save(value) {
this.onsaved(value);
},
cancel: function mbe_cancel() {
this.oncancelled();
}
};

View file

@ -0,0 +1,9 @@
'use strict';
/* exported realMozSetMessageHandler, msgHandler */
var realMozSetMessageHandler = navigator.mozSetMessageHandler;
var msgHandler = {};
navigator.mozSetMessageHandler = function(type, handler) {
msgHandler[type] = handler;
};

View file

@ -0,0 +1,19 @@
'use strict';
/* exported MockXMLHttpRequest */
var MockXMLHttpRequest = function() {
this.response = 'foo';
};
MockXMLHttpRequest.prototype.send = function() {
this.status = '200';
this.onload();
};
MockXMLHttpRequest.prototype.setRequestHeader = function() {
};
MockXMLHttpRequest.prototype.open = function() {
};

View file

@ -0,0 +1,4 @@
'use strict';
/* global require */
require('/shared/test/unit/mocks/mocks_helper.js');