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,4 @@
{
"extends": "../.jshintrc",
"node": true
}

View file

@ -0,0 +1,120 @@
/* global Buffer, process */
'use strict';
/**
* Everything.me server for fixtures. Serves stubbed Everything.me responses.
*/
var http = require('http');
var fs = require('fs');
var fsPath = require('path');
var EventEmitter = require('events').EventEmitter;
function writeJSON(res, object) {
object = object || {};
var json = JSON.stringify(object);
res.writeHead(200, {
'Content-Length': Buffer.byteLength(json),
'Content-Type': 'application/json'
});
res.end(json);
}
/**
* @param {String} root directory where content is.@
* @param {Object} routes for the server.
* @constructor
*/
function EmeServer(root, routes) {
EventEmitter.call(this);
// ensure we always have the slash suffix
if (root[root.length - 1] !== '/') {
root += '/';
}
this.root = root;
this.routes = routes;
this._settings = {};
this.fail = false;
}
EmeServer.prototype = {
__proto__: EventEmitter.prototype,
requestHandler: function() {
var routes = this.routes;
return function(req, res) {
// Fail requests
if (req.url.indexOf('/settings') !== 0 && this.fail) {
process.nextTick(function() {
req.socket.destroy();
});
return;
}
var handler = routes[req.url] || routes['*'];
// routes are always invoked with the context of the server.
return handler.call(this, req, res);
}.bind(this);
},
};
var emeServer = new EmeServer(process.argv[2], {
'/Categories/list': function(req, res) {
var json = JSON.parse(fs.readFileSync(this.root + 'categories_list.json'));
writeJSON(res, json);
},
'/Apps/nativeInfo': function(req, res) {
var json = JSON.parse(fs.readFileSync(this.root + 'apps_nativeinfo.json'));
writeJSON(res, json);
},
'/Apps/search': function(req, res) {
var json = JSON.parse(fs.readFileSync(this.root + 'apps_search.json'));
writeJSON(res, json);
},
'/Search/bgimage': function(req, res) {
var json = JSON.parse(fs.readFileSync(this.root + 'search_bgimage.json'));
writeJSON(res, json);
},
'/Search/suggestions': function(req, res) {
var file = fs.readFileSync(this.root + 'search_suggestions.json');
var json = JSON.parse(file);
writeJSON(res, json);
},
'/settings/failAll': function(req, res) {
this.fail = true;
writeJSON(res);
},
'/settings/unfailAll': function(req, res) {
this.fail = false;
writeJSON(res);
},
/**
* Catch all handler which serves up static assets.
*/
'*': function(req, res) {
var url = req.url;
var filePath = fsPath.join(this.root, url);
console.log('Uncaught request: ', url, filePath);
res.writeHead(404);
res.end();
return;
}
});
var server = http.createServer(emeServer.requestHandler());
server.listen(0, function() {
process.send({ type: 'started', port: server.address().port });
});

View file

@ -0,0 +1,6 @@
{
"errorCode": 1,
"processingTime": 0,
"response": {
}
}

View file

@ -0,0 +1,113 @@
{
"errorCode": 1,
"processingTime": 1,
"response": {
"spellingCorrection": [],
"ads": null,
"disambiguation": [],
"adultContent": false,
"apps": [
{
"appUrl": "http://mozilla1.org",
"favUrl": "@",
"icon": "",
"adult": false,
"type": "app",
"id": 1,
"name": "Mozilla"
},
{
"appUrl": "http://mozilla2.org/firefox",
"favUrl": "@",
"icon": "",
"adult": false,
"type": "app",
"id": 2,
"name": "Firefox"
},
{
"appUrl": "http://mozilla3.org/Thunderbird",
"favUrl": "@",
"icon": "",
"adult": false,
"type": "app",
"id": 3,
"name": "Thunderbird"
},
{
"appUrl": "http://mozilla4.org/Persona",
"favUrl": "@",
"icon": "",
"adult": false,
"type": "app",
"id": 4,
"name": "Persona"
},
{
"appUrl": "http://mozilla5.org/FxOS",
"favUrl": "@",
"icon": "",
"adult": false,
"type": "app",
"id": 5,
"name": "FxOS"
},
{
"appUrl": "http://mozilla6.org/Servo",
"favUrl": "@",
"icon": "",
"adult": false,
"type": "app",
"id": 6,
"name": "Servo"
},
{
"appUrl": "http://mozilla7.org/rust",
"favUrl": "@",
"icon": "",
"adult": false,
"type": "app",
"id": 7,
"name": "Rust"
},
{
"appUrl": "http://mozilla8.org/Javascript",
"favUrl": "@",
"icon": "",
"adult": false,
"type": "app",
"id": 8,
"name": "Javascript"
},
{
"appUrl": "http://mozilla9.org/HTML",
"favUrl": "@",
"icon": "",
"adult": false,
"type": "app",
"id": 9,
"name": "HTML"
},
{
"appUrl": "http://mozilla10.org/CSS",
"favUrl": "@",
"icon": "",
"adult": false,
"type": "app",
"id": 10,
"name": "CSS"
}
],
"paging": {
"max": 20,
"limit": 10,
"first": 0
},
"experiences": [
"music"
],
"query": "music"
},
"errorString": "OK",
"requestId": null
}

View file

@ -0,0 +1,60 @@
{
"errorCode": 1,
"processingTime": 0,
"response": {
"locale": "en_US",
"categories": [
{
"appIds": [
1,
2,
3
],
"locale": "en_US",
"canonicalName": "around me",
"query": "Around Me",
"categoryId": 1
},
{
"appIds": [
1,
2,
3
],
"locale": "en_US",
"canonicalName": "astrology",
"query": "Astrology",
"categoryId": 2
},
{
"appIds": [
1,
2,
3
],
"locale": "en_US",
"canonicalName": "autos",
"query": "Autos",
"categoryId": 3
},
{
"appIds": [
1,
2,
3
],
"locale": "en_US",
"canonicalName": "entertainment",
"query": "Entertainment",
"categoryId": 376
}
],
"icons": {
"1": "/blank.png",
"2": "/blank.png",
"3": "/blank.png"
}
},
"errorString": "OK",
"requestId": "0"
}

View file

@ -0,0 +1,14 @@
{
"processingTime": 1,
"errorString": "OK",
"checksum": "1",
"errorCode": 1,
"requestId": "1",
"response": {
"source": "",
"image": {
"MIMEType": "image/gif",
"data": "R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs="
}
}
}

View file

@ -0,0 +1,12 @@
{
"errorCode":1,
"processingTime":14.3,
"response": [
"[ab]out.com",
"ab",
"[ab]ercrombie & fitch",
"[ab]ner louima"
],
"errorString":"OK",
"requestId":"8WxZsKjO_VU"
}

View file

@ -0,0 +1,89 @@
'use strict';
/* global module, __dirname */
var fork = require('child_process').fork;
/**
* Issue a POST request via marionette.
*/
function post(client, url, json) {
json = json || {};
// must run in chrome so we can do cross domain xhr
client = client.scope({ context: 'chrome' });
return client.executeAsyncScript(function(url, json) {
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function() {
marionetteScriptFinished(xhr.response);
};
xhr.send(json);
}, [url, JSON.stringify(json)]);
}
function EmeServer(root, marionette, port, proc) {
this.root = root;
this.marionette = marionette;
this.url = 'http://localhost:' + port;
this.process = proc;
}
EmeServer.prototype = {
close: function(callback) {
this.process.kill();
this.process.once('exit', callback.bind(this, null));
},
/**
* Indicate to the server that all requests should be given a response with
* headers but then the socket should be closed shortly after that time.
*/
failAll: function() {
return post(this.marionette, this.url + '/settings/failAll');
},
/**
* Allow requests to to proceed without failure after calling `.failAll`.
*/
unfailAll: function() {
return post(this.marionette, this.url + '/settings/unfailAll');
},
};
/**
* Create an everything.me server for use in marionette tests.
*
* @param {Marionette.Client} client for marionette.
* @param {Function} callback [Error]
*/
module.exports = function create(client, callback) {
var stubRoot = __dirname + '/fixtures';
var proc = fork(__dirname + '/child.js', [stubRoot]);
proc.once('error', callback);
proc.on('message', function(msg) {
if (msg.type !== 'started') {
return;
}
proc.removeListener('error', callback);
callback(null, new EmeServer(stubRoot, client, msg.port, proc));
});
};
module.exports.EmeServer;
/**
* Updates the everything.me API setting.
* @param {Object} client The marionette client.
* @param {Object} server An everything.me server instance.
*/
module.exports.setServerURL = function(client, server) {
var chrome = client.scope({ context: 'chrome' });
chrome.executeAsyncScript(function(url) {
var request = navigator.mozSettings.createLock().set({
'appsearch.url': url
});
request.onsuccess = function() {
marionetteScriptFinished();
};
}, [server.url + '/{resource}']);
};

View file

@ -0,0 +1,8 @@
{
"blacklist": {
"apps/calendar/test/marionette/alarm_test.js": "Bug 994976 - Perma-red TBPL test, alarm > without alarm mocks create two events with simultaneous reminders",
"apps/calendar/test/marionette/caldav_test.js": "Bug 972631 - CalDAV setup causing tbpl timeouts",
"apps/calendar/test/marionette/server_test.js": "",
"apps/system/test/marionette/net_error_test.js": "Bug 1148165 - Disable intermittent test"
}
}

View file

@ -0,0 +1,58 @@
/* global module, __dirname */
'use strict';
var fs = require('fs');
/**
* MockManager is in charge of finding and injecting the mock files. They can be
* located either at the app level in apps/$APP/test/marionette/mocks/ or at the
* global level in shared/test/integration
* @param {Marionette.Client} client Marionette client to use.
* @param {String} app App folder to look into
* @constructor
*/
function MockManager(client, appName) {
this.client = client;
this.potentialDirs = [
__dirname + '/../../../apps/' + appName + '/test/marionette/mocks/',
__dirname + '/' // points to shared/test/integration/
];
}
MockManager.prototype = {
inject: function(mocks) {
mocks = Array.isArray(mocks) ? mocks : [mocks];
mocks.forEach(function(mockName) {
this._injectSingle(mockName);
}, this);
},
_injectSingle: function(mockName) {
var fileName = 'mock_' + mockName + '.js';
var filePath = this._findFilePath(fileName);
this.client.contentScript.inject(filePath);
},
_findFilePath: function(fileName) {
var index = this.potentialDirs.findIndex(function(dir) {
return this._isFileAccessible(dir + fileName);
}, this);
if(index === -1) {
throw new Error(fileName + ' was not found');
}
return this.potentialDirs[index] + fileName;
},
_isFileAccessible: function(filePath) {
try {
fs.accessSync(filePath);
return true;
} catch(e) {
return false;
}
}
};
module.exports = MockManager;

View file

@ -0,0 +1,21 @@
[include:../../../tests/integration/devtools/manifest.ini]
[include:../../../apps/keyboard/test/marionette/manifest.ini]
[include:../../../apps/music/test/marionette/manifest.ini]
[include:../../../apps/browser/test/marionette/manifest.ini]
[include:../../../apps/homescreen/test/marionette/manifest.ini]
[include:../../../apps/search/test/marionette/manifest.ini]
[include:../../../apps/ftu/test/marionette/manifest.ini]
[include:../../../apps/settings/test/marionette/tests/manifest.ini]
[include:../../../apps/verticalhome/test/marionette/manifest.ini]
[include:../../../apps/homescreen/test/marionette/manifest.ini]
[include:../../../apps/system/test/marionette/manifest.ini]
[include:../../../apps/ringtones/test/marionette/manifest.ini]
[include:../../../apps/sms/test/marionette/manifest.ini]
[include:../../../apps/gallery/test/marionette/manifest.ini]
[include:../../../apps/email/test/marionette/manifest.ini]
[include:../../../apps/findmydevice/test/marionette/manifest.ini]
[include:../../../apps/clock/test/marionette/manifest.ini]
[include:../../../apps/calendar/test/marionette/manifest.ini]
[include:../../../apps/communications/dialer/test/marionette/manifest.ini]
[include:../../../apps/communications/contacts/test/marionette/manifest.ini]
[include:../../../apps/video/test/marionette/manifest.ini]

View file

@ -0,0 +1,66 @@
'use strict';
var MockManager = require('./manager_mock.js');
var COMMS_APPS = ['dialer', 'contacts'];
/**
* @param {Marionette.Client} client Marionette client to use.
* @constructor
*/
function MarionetteLoader(client) {
this.client = client;
}
module.exports = MarionetteLoader;
/**
* Make a new helper.
* @param {Marionette.Client} client Marionette client to use.
* @param {Object} options Optional map of attributes for Apps.
* @return {Apps} instance.
*/
MarionetteLoader.setup = function(client, options) {
return new MarionetteLoader(client);
};
MarionetteLoader.prototype = {
/**
* @type {Marionette.Client}
*/
client: null,
/**
* Includes the main entry point for an application.
* @param {String} app
* @param {String} region
* @param {String} [baseFolder=apps] base folder of app.
*/
getAppClass: function(app, region, baseFolder) {
region = region || app;
app = COMMS_APPS.indexOf(app) === -1 ? app : 'communications/' + app;
baseFolder = baseFolder || 'apps';
var AppClass = require(
__dirname + '/../../../' +
baseFolder + '/' + app + '/test/marionette/lib/' + region);
return new AppClass(this.client);
},
/**
* Returns an instance of MockManager that will look into the given app and the
* shared folder.
* @param {String} app
*/
getMockManager: function(app) {
return new MockManager(this.client, app);
},
/**
* Gets the marionette-client Actions class and instantiates it.
* @param {String} helper.
*/
getActions: function() {
var Actions = require('marionette-client').Actions;
return new Actions(this.client);
}
};

View file

@ -0,0 +1,12 @@
'use strict';
var win = document.defaultView;
var battery = {
level: 0,
charging: false,
addEventListener: function() {}
};
win.wrappedJSObject.navigator.__defineGetter__('battery', function() {
return battery;
});

View file

@ -0,0 +1,18 @@
/* global Components, Services */
'use strict';
Components.utils.import('resource://gre/modules/Services.jsm');
Services.obs.addObserver(function(document) {
if (!document || !document.location) {
return;
}
var window = document.defaultView;
Object.defineProperty(window.wrappedJSObject.navigator, 'mozIccManager', {
configurable: false,
writable: true,
value: Components.utils.cloneInto({iccIds: []}, window)
});
}, 'document-element-inserted', false);

View file

@ -0,0 +1,41 @@
/*global Components, Services*/
/**
* @fileoverview This script mocks the mozSetMessageHandler API
* (developer.mozilla.org/docs/Web/API/Navigator.mozSetMessageHandler)
* for app integration tests. You should use and improve this if you
* want to write a marionette test for app functionality which gets
* triggered by a system message (activities, alarms, etc.).
*/
'use strict';
Components.utils.import('resource://gre/modules/Services.jsm');
Services.obs.addObserver(function(document) {
if (!document || !document.location) {
return;
}
var window = document.defaultView.wrappedJSObject;
var messageHandlers = {};
window.navigator.__defineGetter__('mozSetMessageHandler', function() {
return function(type, callback) {
messageHandlers[type] = callback;
};
});
window.__defineGetter__('fireMessageHandler', function() {
return function(data, type) {
// For historical purposes, this only supported alarm callbacks. To avoid
// force updating code that still assumes that, still assume that as a
// default.
type = type || 'alarm';
var messageHandler = messageHandlers[type];
if (messageHandler && typeof(messageHandler) === 'function') {
messageHandler(data);
return true;
}
return false;
};
});
}, 'document-element-inserted', false);

View file

@ -0,0 +1,76 @@
/*global Components, Services*/
/**
* @fileoverview This script mocks the mozAlarms API
* (developer.mozilla.org/docs/WebAPI/Alarm) for app integration tests.
* You should use and improve this if you want to write a marionette test
* which verifies that your app sets alarms correctly.
*/
'use strict';
Components.utils.import('resource://gre/modules/Services.jsm');
Services.obs.addObserver(function(document) {
if (!document || !document.location) {
return;
}
var window = document.defaultView.wrappedJSObject;
var fakeAlarms = [];
function makeSafeObject(obj) {
var exposedProps = {};
Object.keys(obj).forEach(function(key) {
exposedProps[key] = 'wr';
});
obj.__exposedProps__ = exposedProps;
return obj;
}
function makeFakeRequest(result) {
var request = makeSafeObject({
onsuccess: null,
onerror: null
});
window.setTimeout(function() {
if (request.onsuccess) {
request.onsuccess(result);
}
});
return request;
}
window.navigator.__defineGetter__('mozAlarms', function() {
return {
__exposedProps__: {
remove: 'r',
add: 'r',
getAll: 'r'
},
remove: function() {
// just ignore
},
add: function(date, respectTimezone, data) {
fakeAlarms.push(makeSafeObject(data));
return makeFakeRequest({});
},
getAll: function() {
return makeFakeRequest(makeSafeObject({
target: makeSafeObject({
result: []
})
}));
}
};
});
window.navigator.__defineGetter__('__mozFakeAlarms', function() {
return fakeAlarms;
});
}, 'document-element-inserted', false);

View file

@ -0,0 +1,64 @@
/**
* @fileoverview This script mocks the vibration API
* (https://developer.mozilla.org/en-US/docs/Web/Guide/API/Vibration) for
* app integration tests. You should use and improve this if you want to
* write a marionette test which verifies that your app uses vibration
* correctly.
*/
'use strict';
(function() {
var fake_vibrations = 0;
var document_visibility_state = true;
var vibrationPattern = null;
var screenEnabled = window.wrappedJSObject.ScreenManager.screenEnabled;
window.navigator.wrappedJSObject.__defineGetter__('vibrate', function() {
return function(pattern) {
fake_vibrations++;
vibrationPattern = pattern;
return true;
};
});
window.wrappedJSObject.__defineGetter__('__fakeVibrationsNo', function() {
return fake_vibrations;
});
window.document.wrappedJSObject.__defineGetter__('hidden', function() {
return !document_visibility_state;
});
window.wrappedJSObject.__defineGetter__(
'__setDocumentVisibility', function() {
return function(visible) {
document_visibility_state = visible;
return true;
};
});
window.wrappedJSObject.__defineGetter__('__fakeVibrationPattern',
function() {
return vibrationPattern;
});
window.wrappedJSObject.ScreenManager.__defineGetter__(
'turnScreenOff', function() {
return function(_dim) {
screenEnabled = false;
};
});
window.wrappedJSObject.ScreenManager.__defineGetter__(
'turnScreenOn', function() {
return function(_dim) {
screenEnabled = true;
};
});
window.wrappedJSObject.ScreenManager.__defineGetter__(
'screenEnabled', function() {
return screenEnabled;
});
})();

View file

@ -0,0 +1,377 @@
/* global TVSource, TVChannel, TVProgram */
'use strict';
/**
* This mock service contains mock channels and programs that make testing
* easier.
*/
(function(exports) {
var channelInfo = [
{
name: 'HBO',
number: '1'
}, {
name: 'TVBS',
number: '2'
}, {
name: 'Discovery',
number: '3'
}, {
name: 'Fox',
number: '5'
}, {
name: 'ABC',
number: '8'
}, {
name: 'CNN',
number: '9'
}, {
name: 'AXS TV',
number: '10'
}, {
name: 'MTV',
number: '10-1'
}, {
name: 'TNT',
number: '10-2'
}, {
name: 'Disney',
number: '13'
}, {
name: 'Oxygen',
number: '14'
}, {
name: 'Lifetime',
number: '15'
}, {
name: 'AXN',
number: '19'
}, {
name: 'ESON',
number: '20'
}, {
name: 'Mozilla',
number: '25'
}
];
(function overrideTVSourceFunction() {
// Override native TVChannel constructor in order to create mock channels.
window.TVChannel = function() {};
// Delete native property in order to override it
delete TVSource.prototype.currentChannel;
var channels = [];
for(var i = 0; i < channelInfo.length; i++) {
var channel = new TVChannel();
channel.name = channelInfo[i].name;
channel.number = channelInfo[i].number;
channels.push(channel);
}
TVSource.prototype.getChannels = function() {
var lastChannel;
var lastChannelNumber = localStorage.getItem('_Mock-Channel-Number');
channels.some(function(channel) {
if (channel.number === lastChannelNumber) {
lastChannel = channel;
return true;
}
return false;
}.bind(this));
this.currentChannel = lastChannel;
return {
then: function(success) {
setTimeout(function() {
success(channels);
}, 500);
}
};
};
TVSource.prototype.setCurrentChannel = function(channelNumber) {
var resolve;
if (this._lastTimeoutId) {
clearTimeout(this._lastTimeoutId);
}
this._lastTimeoutId = setTimeout(function() {
this.currentChannel = channels[channelNumber];
localStorage.setItem('_Mock-Channel-Number', channelNumber);
if (resolve) {
resolve();
}
}.bind(this), 500);
return {
then: function(success) {
resolve = success;
}
};
};
})();
var programMeta = [{
title: 'The Dark Knight',
description: 'When the menace known as the Joker wreaks havoc and chaos' +
'on the people of Gotham, the caped crusader must come to terms with' +
' one of the greatest psychological tests of his ability to fight' +
' injustice.'
}, {
title: 'Pulp Fiction',
description: 'The lives of two mob hit men, a boxer, a gangster\'s wife' +
', and a pair of diner bandits intertwine in four tales of violence' +
' and redemption.'
}, {
title: 'The Lord of the Rings: The Return of the King',
description: 'Gandalf and Aragorn lead the World of Men against' +
' Sauron\'s army to draw his gaze from Frodo and Sam as they approach' +
' Mount Doom with the One Ring.'
}, {
title: 'Star Wars: Episode V - The Empire Strikes Back',
description: 'After the rebels have been brutally overpowered by the ' +
'Empire on their newly established base, Luke Skywalker takes ' +
'advanced Jedi training with Master Yoda, while his friends are ' +
'pursued by Darth Vader as part of his plan to capture Luke.'
}, {
title: 'Forrest Gump',
description: 'Forrest Gump, while not intelligent, has accidentally ' +
'been present at many historic moments, but his true love, Jenny ' +
'Curran, eludes him.'
}, {
title: 'Inception',
description: 'A thief who steals corporate secrets through use of ' +
'dream-sharing technology is given the inverse task of planting an ' +
'idea into the mind of a CEO.'
}, {
title: 'The Matrix',
description: 'A computer hacker learns from mysterious rebels about ' +
'the true nature of his reality and his role in the war against ' +
'its controllers.'
}, {
title: 'Interstellar',
description: 'A team of explorers travel through a wormhole in an ' +
'attempt to ensure humanity\'s survival.'
}, {
title: 'Whiplash',
description: 'A promising young drummer enrolls at a cut-throat music' +
' conservatory where his dreams of greatness are mentored by an ' +
'instructor who will stop at nothing to realize a student\'s potential.'
}, {
title: 'The Intouchables',
description: 'After he becomes a quadriplegic from a paragliding ' +
'accident, an aristocrat hires a young man from the projects to be ' +
'his caregiver.'
}, {
title: 'Gladiator',
description: 'When a Roman general is betrayed and his family murdered' +
' by an emperor\'s corrupt son, he comes to Rome as a gladiator to' +
' seek revenge.'
}, {
title: 'Alien',
description: 'The commercial vessel Nostromo receives a distress call' +
' from an unexplored planet. After searching for survivors, the crew' +
' heads home only to realize that a deadly bioform has joined them.'
}, {
title: 'The Lion King',
description: 'Tricked into thinking that he caused the death of his ' +
'father, a lion cub flees and abandons his destiny as the future king.'
}, {
title: 'American Beauty',
description: 'A sexually frustrated suburban father has a mid-life ' +
'crisis after becoming infatuated with his daughter\'s best friend.'
}, {
title: 'Toy Story 3',
description: 'The toys are mistakenly delivered to a day-care center' +
' instead of the attic right before Andy leaves for college, and ' +
'it\'s up to Woody to convince the other toys that they weren\'t' +
' abandoned and to return home.'
}, {
title: 'Indiana Jones and the Last Crusade',
description: 'When Dr. Henry Jones Sr. suddenly goes missing while ' +
'pursuing the Holy Grail, eminent archaeologist Indiana Jones must ' +
'follow in his father\'s footsteps and stop the Nazis.'
}, {
title: 'The Wolf of Wall Street',
description: 'Based on the true story of Jordan Belfort, from his rise ' +
'to a wealthy stock-broker living the high life to his fall involving' +
' crime, corruption and the federal government.'
}, {
title: 'Gone Girl',
description: 'With his wife\'s disappearance having become the focus ' +
'of an intense media circus, a man sees the spotlight turned on him' +
' when it\'s suspected that he may not be innocent.'
}, {
title: 'A Beautiful Mind',
description: 'After a brilliant but asocial mathematician accepts ' +
'secret work in cryptography, his life takes a turn for the ' +
'nightmarish.'
}, {
title: 'The Grand Budapest Hotel',
description: 'The adventures of Gustave H, a legendary concierge at a' +
' famous hotel from the fictional Republic of Zubrowka between the ' +
'first and second World Wars, and Zero Moustafa, the lobby boy who ' +
'becomes his most trusted friend.'
}, {
title: 'Monsters, Inc.',
description: 'Monsters generate their city\'s power by scaring ' +
'children, but they are terribly afraid themselves of being ' +
'contaminated by children, so when one enters Monstropolis, top ' +
'scarer Sulley finds his world disrupted.'
}, {
title: 'The Hobbit: The Battle of the Five Armies',
description: 'Bilbo and Company are forced to engage in a war against ' +
'an array of combatants and keep the Lonely Mountain from falling ' +
'into the hands of a rising darkness.'
}, {
title: 'Maleficent',
description: 'A vengeful fairy is driven to curse an infant princess, ' +
'only to discover that the child may be the one person who can ' +
'restore peace to their troubled land.'
}, {
title: 'X-Men: Days of Future Past',
description: 'The X-Men send Wolverine to the past in a desperate ' +
'effort to change history and prevent an event that results in ' +
'doom for both humans and mutants.'
}, {
title: 'Captain America: The Winter Soldier',
description: 'As Steve Rogers struggles to embrace his role in the ' +
'modern world, he teams up with another super soldier, the black widow,' +
' to battle a new threat from old history: an assassin known as the ' +
'Winter Soldier.'
}, {
title: 'The Amazing Spider-Man 2',
description: 'When New York is put under siege by Oscorp, it is up to ' +
'Spider-Man to save the city he swore to protect as well as his ' +
'loved ones'
}, {
title: 'Dawn of the Planet of the Apes',
description: 'An ape empire conflicts with a sustaining human ' +
'rebellion, as well as a rogue renegade due to the catastrophic ' +
'events ten years earlier.'
}, {
title: 'Fast & Furious 6',
description: 'Hobbs has Dominic and Brian reassemble their crew to ' +
'take down a team of mercenaries: Dominic unexpectedly gets ' +
'convoluted also facing his presumed deceased girlfriend, Letty.'
}, {
title: 'Iron Man 3',
description: 'When Tony Stark\'s world is torn apart by a formidable ' +
'terrorist called the Mandarin, he starts an odyssey of rebuilding ' +
'and retribution.'
}, {
title: 'Frozen',
description: 'When the newly crowned Queen Elsa accidentally uses her ' +
'power to turn things into ice to curse her home in infinite winter,' +
' her sister, Anna, teams up with a mountain man, his playful ' +
'reindeer, and a snowman to change the weather condition.'
}, {
title: '2012',
description: 'A frustrated writer struggles to keep his family alive ' +
'when a series of global catastrophes threatens to annihilate mankind.'
}, {
title: 'Magic Mike',
description: 'A male stripper teaches a younger performer how to party,' +
' pick up women, and make easy money.'
}, {
title: 'The Hunger Games',
description: 'Katniss Everdeen voluntarily takes her younger sister\'s' +
' place in the Hunger Games, a televised fight to the death in which' +
' two teenagers from each of the twelve Districts of Panem are chosen' +
' at random to compete.'
}, {
title: 'Dredd',
description: 'In a violent, futuristic city where the police have the' +
' authority to act as judge, jury and executioner, a cop teams with ' +
'a trainee to take down a gang that deals the reality-altering drug,' +
' SLO-MO.'
}, {
title: 'Silver Linings Playbook',
description: 'After a stint in a mental institution, former teacher Pat' +
' Solitano moves back in with his parents and tries to reconcile ' +
'with his ex-wife. Things get more challenging when Pat meets ' +
'Tiffany, a mysterious girl with problems of her own.'
}, {
title: 'The Hobbit: An Unexpected Journey',
description: 'A reluctant hobbit, Bilbo Baggins, sets out to the ' +
'Lonely Mountain with a spirited group of dwarves to reclaim their ' +
'mountain home - and the gold within it - from the dragon Smaug.'
}, {
title: '21 Jump Street',
description: 'A pair of underachieving cops are sent back to a local ' +
'high school to blend in and bring down a synthetic drug ring.'
}, {
title: 'The Amazing Spider-Man',
description: 'After Peter Parker is bitten by a genetically altered ' +
'spider, he gains newfound, spider-like powers and ventures out to ' +
'solve the mystery of his parent\'s mysterious death.'
}, {
title: 'Skyfall',
description: 'Bond\'s loyalty to M is tested when her past comes back ' +
'to haunt her. Whilst MI6 comes under attack, 007 must track down ' +
'and destroy the threat, no matter how personal the cost.'
}, {
title: 'Argo',
description: 'Acting under the cover of a Hollywood producer scouting ' +
'a location for a science fiction film, a CIA agent launches a ' +
'dangerous operation to rescue six Americans in Tehran during the ' +
'U.S. hostage crisis in Iran in 1980.'
}];
(function overrideTVChannelFunction() {
// Override native TVProgram constructor in order to create mock programs.
window.TVProgram = function() {};
TVChannel.prototype._generatePrograms = function() {
var quarterHour = 15 * 60000; // 15 min
var halfHour = 30 * 60000;
var startTime =
new Date((Math.floor(Date.now() / halfHour) - 20) * halfHour)
.getTime();
var duration;
var programs = [];
var program;
var index;
var tmp;
var i;
for(i = 0; i < programMeta.length; i++) {
index = Math.floor(Math.random() * (programMeta.length - i)) + i;
tmp = programMeta[i];
programMeta[i] = programMeta[index];
programMeta[index] = tmp;
duration = (Math.floor(Math.random() * 4) + 2 ) * quarterHour;
program = new TVProgram();
program.title = programMeta[i].title;
program.description = programMeta[i].description;
program.startTime = startTime;
program.duration = duration;
programs.push(program);
startTime += Math.ceil(duration / halfHour) * halfHour;
}
this._programs = programs;
};
TVChannel.prototype.getPrograms = function() {
var promise = {
then: function(callback) {
if (!this._programs) {
this._generatePrograms();
}
setTimeout(function() {
callback(this._programs);
}.bind(this), 800);
return promise;
}.bind(this),
catch: function() {
return promise;
}
};
return promise;
};
})();
})(window);

View file

@ -0,0 +1,32 @@
'use strict';
/* global module */
var appRoot = require('app-root-path');
// TODO Export this helper in its own npm package
function FromApp(app) {
this.app = app;
return this;
}
FromApp.prototype = {
filePath: function(relativePath) {
var app = this.app;
if (['dialer', 'contacts'].indexOf(app) !== -1) {
app = 'communications/' + app;
}
return appRoot + '/apps/' + app + '/test/marionette/' + relativePath;
},
require: function(resource) {
return require(this.filePath(resource));
}
};
module.exports = function(app) {
return new FromApp(app);
};

View file

@ -0,0 +1,92 @@
'use strict';
function Server(root, port, child) {
this.root = root;
this.port = port;
this.child = child;
}
Server.prototype = {
/**
* Formats given input with localhost and port.
*
* @param {String} path part of url.
* @return {String} url of location.
*/
url: function(path) {
return 'http://localhost:' + this.port + '/' + path;
},
/**
* Sends signal to stop child process and stop server.
*/
stop: function() {
this.child.send({
action: 'stop'
});
this.child.kill();
},
/**
* Cork the response body of the given url while allowing headers.
* @param {String} url to cork
*/
cork: function(url) {
this.child.send({
action: 'cork',
args: url
});
},
/**
* Allow the body to be sent after calling `.cork`.
* @param {String} url to uncork
*/
uncork: function(url) {
this.child.send({
action: 'uncork',
args: url
});
},
/**
* Protects a URL using HTTP authentication.
* @param {String} url to protect
*/
protect: function(url) {
this.child.send({
action: 'protect',
args: url
});
},
/**
* Stops protecting a URL.
* @param {String} url to protect
*/
unprotect: function(url) {
this.child.send({
action: 'unprotect',
args: url
});
}
};
/**
* Spawn the child process where the http server lives.
*
* @param {Function} callback [Error err, Server server].
*/
Server.create = function(root, callback) {
var fork = require('child_process').fork;
var child = fork(__dirname + '/server_child.js', [root]);
// wait for start message ['start', PORT_NUMBER].
child.on('message', function(data) {
if (Array.isArray(data) && data[0] === 'start') {
callback(null, new Server(root, data[1], child));
}
});
};
module.exports = Server;

View file

@ -0,0 +1,117 @@
'use strict';
var http = require('http');
var emptyPort = require('empty-port');
var nodeStatic = require('node-static');
var EventEmitter = require('events').EventEmitter;
var root = process.argv[2];
var server;
function Server() {
EventEmitter.call(this);
}
Server.prototype = {
__proto__: EventEmitter.prototype,
/**
* Http server running in this process.
*/
http: null,
/**
* A map of corked URLs.
*/
corkedUrls: {},
/**
* A map of protected URLs.
*/
authUrls: {},
stop: function() {
if (this.http) {
this.http.close();
}
},
start: function(port) {
// using node-static for now we can do fancy stuff in the future.
var file = new nodeStatic.Server(root);
this.http = http.createServer(function(req, res) {
req.addListener('end', function() {
// Handle corked urls.
var fullUrl = 'http://' + req.headers.host + req.url;
if (server.corkedUrls[fullUrl]) {
server.once('uncorked ' + fullUrl, file.serve.bind(file, req, res));
return;
}
// Handle protected URLs.
// Users can login with 'username' and 'password'
if (server.authUrls[fullUrl] &&
req.headers.authorization !== 'Basic dXNlcm5hbWU6cGFzc3dvcmQ=') {
res.writeHead(401, {
'WWW-Authenticate': 'Basic realm="login required"'
});
res.end();
return;
}
// hand off request to node-static
file.serve(req, res);
}).resume();
}).listen(port);
},
cork: function(url) {
this.corkedUrls[url] = true;
},
uncork: function(url) {
delete this.corkedUrls[url];
this.emit('uncorked ' + url);
},
protect: function(url) {
this.authUrls[url] = true;
},
unprotect: function(url) {
delete this.authUrls[url];
}
};
server = new Server();
// figure out which port we are on
emptyPort({}, function(err, port) {
server.start(port);
process.send(['start', port]);
});
// handle process messages
process.on('message', function(data) {
switch (data.action) {
case 'cork':
server.cork(data.args);
break;
case 'uncork':
server.uncork(data.args);
break;
case 'protect':
server.protect(data.args);
break;
case 'unprotect':
server.unprotect(data.args);
break;
case 'stop':
server.stop();
break;
}
});

View file

@ -0,0 +1,7 @@
marionette.plugin('apps', require('marionette-apps'));
marionette.plugin('contentScript', require('marionette-content-script'));
marionette.plugin('fileManager', require('marionette-file-manager'));
marionette.plugin('forms', require('marionette-plugin-forms'));
marionette.plugin('helper', require('marionette-helper'));
marionette.plugin('loader', require(__dirname + '/marionette_loader'));
marionette.plugin('settings', require('marionette-settings-api'));

View file

@ -0,0 +1,79 @@
{
"blacklist": {
"apps/calendar/test/marionette/alarm_test.js": "Bug 994976 - Perma-red TBPL test, alarm > without alarm mocks create two events with simultaneous reminders",
"apps/calendar/test/marionette/caldav_test.js": "Bug 972631 - CalDAV setup causing tbpl timeouts",
"apps/calendar/test/marionette/create_event_test.js": "Bug 1175744 - Intermittent create_event_test.js",
"apps/calendar/test/marionette/day_view_test.js": "Bug 1076716 - TEST-UNEXPECTED-FAIL | day view before each hook",
"apps/calendar/test/marionette/month_view_test.js": "Bug 1179906 - Perma-fail month_view_test.js | month view should show event dots",
"apps/calendar/test/marionette/server_test.js": "",
"apps/calendar/test/marionette/toggle_calendar_test.js": "Bug 1190699 - Intermittent toggle_calendar_test.js",
"apps/calendar/test/marionette/week_view_test.js": "Bug 1060447 - Re-enable week_view_test.js",
"apps/camera/test/marionette/capture_test.js": "device only - missing desktop shims",
"apps/camera/test/marionette/hud_test.js": "device only - missing desktop shims",
"apps/camera/test/marionette/settings_test.js": "device only - missing desktop shims",
"apps/camera/test/marionette/zoom_test.js": "device only - missing desktop shims",
"apps/clock/test/marionette/alarm_test.js": "Bug 1035930 - TEST-UNEXPECTED-FAIL | Alarm System statusbar shows an icon when an alarm is active",
"apps/clock/test/marionette/hour_format_test.js": "Bug 1116311 - Intermittent hour_format_test.js",
"apps/clock/test/marionette/timer_test.js": "Bug 1233503 - TEST-UNEXPECTED-FAIL | apps/clock/test/marionette/timer_test.js",
"apps/communications/contacts/test/marionette/ice_test.js": "Bug 1147601 - Intermittent failures",
"apps/communications/contacts/test/marionette/list_test.js": "Bug 1106194 - Intermittent apps/communications/contacts/test/marionette/list_test.js | Contacts > List Visited contacts > number of visited is the same after leaving search view",
"apps/communications/contacts/test/marionette/multiple_select_test.js": "Bug 1235814 - Intermittent TEST-UNEXPECTED-FAIL | apps/communications/contacts/test/marionette/multiple_select_test.js | Contacts > MultipleSelect Import Importing all contacts",
"apps/communications/contacts/test/marionette/search_test.js": "Bug 1235525 - Intermittent TEST-UNEXPECTED-FAIL | apps/communications/contacts/test/marionette/search_test.js",
"apps/communications/contacts/test/marionette/settings_test.js": "Bug 1233517 - Intermittent TEST-UNEXPECTED-FAIL | apps/communications/contacts/test/marionette/settings_test.js | Contacts > Settings Export, delete and ice buttons disabled No contacts -> Disabled",
"apps/email/test/marionette/activity_create_email_account_complete_test.js": "Bug 975588 - Re-enable email marionette js tests",
"apps/email/test/marionette/local_drafts_test.js": "Bug 975588 - Re-enable email marionette js tests",
"apps/email/test/marionette/manual_setup_outgoing_credentials_test.js": "Bug 975588 - Re-enable email marionette js tests",
"apps/email/test/marionette/message_list_test.js": "Bug 975588 - Re-enable email marionette js tests",
"apps/email/test/marionette/next_previous_test.js": "Bug 975588 - Re-enable email marionette js tests",
"apps/email/test/marionette/notification_click_test.js": "Bug 975588 - Re-enable email marionette js tests",
"apps/email/test/marionette/notification_disable_test.js": "Bug 975588 - Re-enable email marionette js tests",
"apps/email/test/marionette/notification_foreground_test.js": "Bug 975588 - Re-enable email marionette js tests",
"apps/email/test/marionette/notification_set_interval_test.js": "Bug 975588 - Re-enable email marionette js tests",
"apps/email/test/marionette/outbox_test.js": "Bug 975588 - Re-enable email marionette js tests",
"apps/email/test/marionette/reply_imap_email_test.js": "Bug 975588 - Re-enable email marionette js tests",
"apps/email/test/marionette/search_test.js": "Bug 975588 - Re-enable email marionette js tests",
"apps/email/test/marionette/send_imap_email_test.js": "Bug 975588 - Re-enable email marionette js tests",
"apps/fm/test/marionette/fm_test.js": "Bug 1233777 - Intermittent TEST-UNEXPECTED-FAIL | apps/fm/test/marionette/fm_test.js | FM Radio test FM Radio favourites Test favouriting",
"apps/ringtones/test/marionette/manage_test.js": "Bug 1037716 - Disable intermittent test after TC change.",
"apps/ringtones/test/marionette/share_test.js": "Bug 1222154 - Failing share_test.js | Share as ringtone Share activity Create new ringtone",
"apps/search/test/marionette/app_installed_test.js": "Bug 1236308 - Intermittent app_installed_test.js | Search - Installed Apps Test app result after install/uninstall",
"apps/search/test/marionette/browser_test.js": "Bug 1236041 - TEST-UNEXPECTED-FAIL | apps/search/test/marionette/browser_test.js | Browser test",
"apps/search/test/marionette/home_button_test.js": "Bug 1188574 - Intermittent apps/search/test/marionette/home_button_test.js | Search - Home Button Press Home button returns to home screen",
"apps/search/test/marionette/places_search_test.js": "Bug 1180068 - Intermittent | Places tests Test url searching",
"apps/settings/test/marionette/tests/airplane_mode_settings_test.js": "",
"apps/settings/test/marionette/tests/app_permission_settings_test.js": "Bug 1004348 - Disable intermittent failing test, manipulate app permissions set geolocation of first app to Grant",
"apps/settings/test/marionette/tests/hotspot_wifi_settings_test.js": "Bug 1006527 - Disable intermittent failing travis test, manipulate hotspot wifi settings resets settings for second load",
"apps/settings/test/marionette/tests/message_settings_test.js": "",
"apps/system/fxa/test/marionette/fxa_screen_flow_test.js": "Bug 1064305 - [Marionette] FxA tests - intermittent timeout failures on system/fxa/test/marionette/fxa_screen_flow_test.js",
"apps/system/test/marionette/audio_channel_competing_test.js": "Bug 1239338 - Intermittent apps/system/test/marionette/audio_channel_competing_test.js | Audio channel competing Public notification audio channel competes with audio channels Public notification channel competes with system channel",
"apps/system/test/marionette/browser_clear_browsing_history_test.js": "Bug 1236038 - TEST-UNEXPECTED-FAIL | apps/system/test/marionette/browser_clear_browsing_history_test.js | Browser test Clear browsing history",
"apps/system/test/marionette/browser_site_loading_background_test.js": "Bug 1233864 - Intermittent browser_site_loading_background_test.js | Browser - Site loading background validate loading background color",
"apps/system/test/marionette/cell_broadcast_system_test.js": "Bug 1230362 - Intermittent cell_broadcast_system_test.js | mozApps - lockscreen enabled CellBroadcastSystem is shown when a message arrives, and clear notification",
"apps/system/test/marionette/keyboard_edge_resize_test.js": "Bug 1147618",
"apps/system/test/marionette/lockscreen_camera_button_test.js": "Bug 1235848 - Intermittent TEST-UNEXPECTED-FAIL | apps/system/test/marionette/lockscreen_camera_button_test.js | LockScreen > after launch the app, turning off and then on the screen should dismiss it",
"apps/system/test/marionette/lockscreen_media_playback_test.js": "Bug 1110913",
"apps/system/test/marionette/lockscreen_passcode_unlock_test.js": "Bug 1226340 - Intermittent lockscreen_passcode_unlock_test.js",
"apps/system/test/marionette/notification_behavior_test.js": "Bug 1148336",
"apps/system/test/marionette/notification_events_test.js": "Bug 1235884 - Intermittent TEST-UNEXPECTED-FAIL | apps/system/test/marionette/notification_events_test.js",
"apps/system/test/marionette/notification_test.js": "Bug 1191036 - Intermittent apps/system/test/marionette/notification_test.js",
"apps/system/test/marionette/software_home_lockscreen_power_menu_test.js": "Bug 1192249 - Intermittent apps/system/test/marionette/software_home_lockscreen_power_menu_test.js",
"apps/system/test/marionette/statusbar_icon_color_test.js": "Bug 1134018",
"apps/system/test/marionette/text_selection_test.js": "Bug 1163853 - Intermittent text_selection_test.js",
"apps/system/test/marionette/update_addon_test.js": "Bug 1225932 - Intermittent update_addon_test.js | Update add-on Basic add-on update test",
"apps/verticalhome/test/marionette/app_hosted_use_cached_icon_test.js": "Bug 1037194 - TEST-UNEXPECTED-FAIL | Vertical Home - Hosted app cached icon fetch fallback to default icon",
"apps/verticalhome/test/marionette/app_packaged_fail_test.js": "Bug 1197816 - Intermittent app_packaged_fail_test.js | Vertical Home - Packaged App Failed Download failed state then retry and launch",
"apps/verticalhome/test/marionette/group_collapse_drag_into_test.js": "Bug 1125696 - Intermittent failing test, TEST-UNEXPECTED-FAIL | Vertical - Group check dragging icon into collapsed group",
"tests/jsmarionette/plugins/marionette-helper/test/index_test.js": "Bug 1165660",
"tests/jsmarionette/plugins/marionette-helper/test/input_select_test.js": "Bug 1189608 - Intermittent TEST-UNEXPECTED-FAIL | MarionetteHelper.fillInputFieldAndtapSelectOption should set date on input",
"tests/jsmarionette/plugins/marionette-js-logger/test/client_test.js": "Bug 1222355 - Intermittent tests/jsmarionette/plugins/marionette-js-logger/test/client_test.js | client get logs from (nested) mozbrowser iframes",
"apps/communications/contacts/test/marionette/form_test.js": "Bug 1205896 - Intermittent form_test.js | Contacts > Form > Edit Contact Simple edition of contact details. ORG field",
"dev_apps/music-oga/test/marionette/music_test.js": "Bug 1236275 - Intermittent apps/music/test/marionette/music_test.js | Music ui tests Test open activity Player shows with one song in database.",
"dev_apps/music-oga/test/marionette/metadata_test.js": "Bug 1238411 - Intermittent dev_apps/music-oga/test/marionette/metadata_test.js | Music player metadata Album art display Check album art is displayed. moztrap:8749",
"dev_apps/music-oga/test/marionette/Player_test.js": "Bug 1238822 - Intermittent apps/music/test/marionette/Player_test.js | Music player tests Rating test Check Rating is saved. moztrap:2683",
"dev_apps/music-oga/test/marionette/search_test.js": "Bug 1238201 - Intermittent dev_apps/music-oga/test/marionette/search_test.js | Music player search \"before each\" hook for \"Check simple search results in tracks.\"",
"distros/raptor/apps/test-startup-limit/test/marionette/counter_test.js": "Bug 1171918 - Intermittent counter_test.js | counter + should increment count",
"tests/jsmarionette/client/marionette-client/test/integration/scope-test.js": "Bug 1181423 - Intermittent tests/jsmarionette/client/marionette-client/test/integration/scope-test.js",
"tests/jsmarionette/plugins/marionette-apps/test/app_test.js": "Bug 1189882 - Intermittent tests/jsmarionette/plugins/marionette-apps/test/app_test.js",
"tv_apps/smart-system/fxa/test/marionette/fxa_screen_flow_test.js": "Bug 1064305 - TEST-UNEXPECTED-FAIL | /builds/slave/test/gaia/apps/system/fxa/test/marionette/fxa_screen_flow_test.js | Firefox Accounts Screen Flow Test (UITest app) should walk screen flow for existing user"
}
}