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:
parent
93e3a48004
commit
b38dea0597
25901 changed files with 9982925 additions and 369 deletions
17
gaia/shared/test/.jshintrc
Executable file
17
gaia/shared/test/.jshintrc
Executable file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"extends": "../../.jshintrc",
|
||||
"predef": [
|
||||
"suite",
|
||||
"test",
|
||||
"setup",
|
||||
"teardown",
|
||||
"suiteSetup",
|
||||
"suiteTeardown",
|
||||
"marionette",
|
||||
"marionetteScriptFinished",
|
||||
"require",
|
||||
"define",
|
||||
"requireApp",
|
||||
"sinon"
|
||||
]
|
||||
}
|
||||
4
gaia/shared/test/integration/.jshintrc
Executable file
4
gaia/shared/test/integration/.jshintrc
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"extends": "../.jshintrc",
|
||||
"node": true
|
||||
}
|
||||
120
gaia/shared/test/integration/eme_server/child.js
Executable file
120
gaia/shared/test/integration/eme_server/child.js
Executable 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 });
|
||||
});
|
||||
6
gaia/shared/test/integration/eme_server/fixtures/apps_nativeinfo.json
Executable file
6
gaia/shared/test/integration/eme_server/fixtures/apps_nativeinfo.json
Executable file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"errorCode": 1,
|
||||
"processingTime": 0,
|
||||
"response": {
|
||||
}
|
||||
}
|
||||
113
gaia/shared/test/integration/eme_server/fixtures/apps_search.json
Executable file
113
gaia/shared/test/integration/eme_server/fixtures/apps_search.json
Executable 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
|
||||
}
|
||||
60
gaia/shared/test/integration/eme_server/fixtures/categories_list.json
Executable file
60
gaia/shared/test/integration/eme_server/fixtures/categories_list.json
Executable 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"
|
||||
}
|
||||
14
gaia/shared/test/integration/eme_server/fixtures/search_bgimage.json
Executable file
14
gaia/shared/test/integration/eme_server/fixtures/search_bgimage.json
Executable file
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"processingTime": 1,
|
||||
"errorString": "OK",
|
||||
"checksum": "1",
|
||||
"errorCode": 1,
|
||||
"requestId": "1",
|
||||
"response": {
|
||||
"source": "",
|
||||
"image": {
|
||||
"MIMEType": "image/gif",
|
||||
"data": "R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs="
|
||||
}
|
||||
}
|
||||
}
|
||||
12
gaia/shared/test/integration/eme_server/fixtures/search_suggestions.json
Executable file
12
gaia/shared/test/integration/eme_server/fixtures/search_suggestions.json
Executable 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"
|
||||
}
|
||||
89
gaia/shared/test/integration/eme_server/parent.js
Executable file
89
gaia/shared/test/integration/eme_server/parent.js
Executable 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}']);
|
||||
};
|
||||
8
gaia/shared/test/integration/local-manifest.json
Executable file
8
gaia/shared/test/integration/local-manifest.json
Executable 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"
|
||||
}
|
||||
}
|
||||
58
gaia/shared/test/integration/manager_mock.js
Executable file
58
gaia/shared/test/integration/manager_mock.js
Executable 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;
|
||||
21
gaia/shared/test/integration/manifest.ini
Executable file
21
gaia/shared/test/integration/manifest.ini
Executable 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]
|
||||
66
gaia/shared/test/integration/marionette_loader.js
Executable file
66
gaia/shared/test/integration/marionette_loader.js
Executable 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);
|
||||
}
|
||||
};
|
||||
12
gaia/shared/test/integration/mock_navigator_battery.js
Executable file
12
gaia/shared/test/integration/mock_navigator_battery.js
Executable 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;
|
||||
});
|
||||
18
gaia/shared/test/integration/mock_navigator_moz_icc_manager.js
Executable file
18
gaia/shared/test/integration/mock_navigator_moz_icc_manager.js
Executable 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);
|
||||
41
gaia/shared/test/integration/mock_navigator_moz_set_message_handler.js
Executable file
41
gaia/shared/test/integration/mock_navigator_moz_set_message_handler.js
Executable 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);
|
||||
76
gaia/shared/test/integration/mock_navigator_mozalarms.js
Executable file
76
gaia/shared/test/integration/mock_navigator_mozalarms.js
Executable 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);
|
||||
64
gaia/shared/test/integration/mock_navigator_vibrate.js
Executable file
64
gaia/shared/test/integration/mock_navigator_vibrate.js
Executable 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;
|
||||
});
|
||||
})();
|
||||
377
gaia/shared/test/integration/mock_tv_service.js
Executable file
377
gaia/shared/test/integration/mock_tv_service.js
Executable 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);
|
||||
|
||||
32
gaia/shared/test/integration/require_from_app.js
Executable file
32
gaia/shared/test/integration/require_from_app.js
Executable 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);
|
||||
};
|
||||
92
gaia/shared/test/integration/server.js
Executable file
92
gaia/shared/test/integration/server.js
Executable 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;
|
||||
117
gaia/shared/test/integration/server_child.js
Executable file
117
gaia/shared/test/integration/server_child.js
Executable 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;
|
||||
}
|
||||
});
|
||||
7
gaia/shared/test/integration/setup.js
Executable file
7
gaia/shared/test/integration/setup.js
Executable 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'));
|
||||
79
gaia/shared/test/integration/tbpl-manifest.json
Executable file
79
gaia/shared/test/integration/tbpl-manifest.json
Executable 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"
|
||||
}
|
||||
}
|
||||
43
gaia/shared/test/unit/load_body_html_helper.js
Executable file
43
gaia/shared/test/unit/load_body_html_helper.js
Executable file
|
|
@ -0,0 +1,43 @@
|
|||
(function(global) {
|
||||
'use strict';
|
||||
|
||||
var parser = new DOMParser();
|
||||
var bodyHTML = {};
|
||||
|
||||
function getFile(filename, callback) {
|
||||
var req = new XMLHttpRequest();
|
||||
req.open('GET', filename, false);
|
||||
req.onerror = function() {
|
||||
throw new Error('Unable to load ' + filename + ' for body HTML');
|
||||
};
|
||||
req.send();
|
||||
if (req.status !== 200) {
|
||||
req.onerror();
|
||||
}
|
||||
|
||||
// parse and sanitize the document
|
||||
var doc = parser.parseFromString(req.response, 'text/html');
|
||||
if (!doc) {
|
||||
throw new Error('Unable to parse ' + filename + ' for body HTML');
|
||||
}
|
||||
|
||||
// remove scripts for safety
|
||||
var scripts = doc.querySelectorAll('script');
|
||||
Array.prototype.forEach.call(scripts, function(scriptNode) {
|
||||
scriptNode.parentNode.removeChild(scriptNode);
|
||||
});
|
||||
|
||||
// copy html from body tag
|
||||
bodyHTML[filename] = doc.body.innerHTML;
|
||||
}
|
||||
|
||||
function loadBodyHTML(filename) {
|
||||
if (!(filename in bodyHTML)) {
|
||||
getFile(filename);
|
||||
}
|
||||
document.body.innerHTML = bodyHTML[filename];
|
||||
}
|
||||
|
||||
global.loadBodyHTML = loadBodyHTML;
|
||||
|
||||
}(this));
|
||||
10
gaia/shared/test/unit/mocks/contacts/mock_contacts_buttons.js
Executable file
10
gaia/shared/test/unit/mocks/contacts/mock_contacts_buttons.js
Executable file
|
|
@ -0,0 +1,10 @@
|
|||
/* exported MockContactsButtons */
|
||||
|
||||
'use strict';
|
||||
|
||||
var MockContactsButtons = {
|
||||
init: function() {},
|
||||
renderPhones: function() {},
|
||||
renderEmails: function() {},
|
||||
reMark: function() {}
|
||||
};
|
||||
86
gaia/shared/test/unit/mocks/dialer/mock_call.js
Executable file
86
gaia/shared/test/unit/mocks/dialer/mock_call.js
Executable file
|
|
@ -0,0 +1,86 @@
|
|||
'use strict';
|
||||
|
||||
/* exported MockCall */
|
||||
|
||||
function MockCall(aNumber, aState, aServiceId) {
|
||||
this._eventListeners = {
|
||||
'connected': [],
|
||||
'disconnected': [],
|
||||
'statechange': []
|
||||
};
|
||||
|
||||
this.id = { number: aNumber };
|
||||
this.serviceId = (aServiceId === undefined) ? 1 : aServiceId;
|
||||
this.state = aState;
|
||||
this.switchable = true; // The call can be put on hold by default
|
||||
this.mergeable = true; // The call can be merged by default
|
||||
|
||||
this.answer = function() {
|
||||
this._connect();
|
||||
};
|
||||
this.hangUp = function() {
|
||||
this._disconnect();
|
||||
};
|
||||
this.hold = function() {};
|
||||
this.resume = function() {};
|
||||
|
||||
this.mEmergencyNumbers = ['112', '911'];
|
||||
this.emergency = this.mEmergencyNumbers.indexOf(aNumber) >= 0;
|
||||
|
||||
this.mVoicemailNumbers = ['123'];
|
||||
this.voicemail = this.mVoicemailNumbers.indexOf(aNumber) >= 0;
|
||||
|
||||
this.addEventListener = (function(type, handler) {
|
||||
if (this._eventListeners[type]) {
|
||||
this._eventListeners[type].push(handler);
|
||||
}
|
||||
}).bind(this);
|
||||
|
||||
this.removeEventListener = (function(type, handler) {
|
||||
if (this._eventListeners[type]) {
|
||||
var idx = this._eventListeners[type].indexOf(handler);
|
||||
this._eventListeners[type].splice(idx, 1);
|
||||
}
|
||||
}).bind(this);
|
||||
|
||||
this.triggerEvent = function(type) {
|
||||
this._mTriggerEventListeners(type);
|
||||
},
|
||||
|
||||
// Mocking the events
|
||||
this.mChangeState = (function(state) {
|
||||
this.state = state;
|
||||
this._mTriggerEventListeners('statechange');
|
||||
}).bind(this);
|
||||
|
||||
this._connect = this.mChangeState.bind(this, 'connected');
|
||||
|
||||
this._disconnect = (function() {
|
||||
this.mChangeState('disconnected');
|
||||
this._mTriggerEventListeners('disconnected');
|
||||
}).bind(this);
|
||||
|
||||
this._hold = (function() {
|
||||
this.mChangeState('held');
|
||||
}).bind(this);
|
||||
|
||||
this._resume = (function() {
|
||||
this.mChangeState('connected');
|
||||
}).bind(this);
|
||||
|
||||
this._mTriggerEventListeners = function(type) {
|
||||
if (!this._eventListeners[type]) {
|
||||
return;
|
||||
}
|
||||
|
||||
var self = this;
|
||||
this._eventListeners[type].forEach(function(callback) {
|
||||
if (typeof callback === 'function') {
|
||||
callback({call: self});
|
||||
} else if (typeof callback == 'object' &&
|
||||
typeof callback.handleEvent === 'function') {
|
||||
callback.handleEvent({call: self});
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
44
gaia/shared/test/unit/mocks/dialer/mock_calls_handler.js
Executable file
44
gaia/shared/test/unit/mocks/dialer/mock_calls_handler.js
Executable file
|
|
@ -0,0 +1,44 @@
|
|||
'use strict';
|
||||
/* exported MockCallsHandler */
|
||||
|
||||
var MockCallsHandler = {
|
||||
mActiveCall: null,
|
||||
mActiveCallForContactImage: null,
|
||||
mIsFirstCallOnCdmaNetwork: false,
|
||||
|
||||
get activeCall() {
|
||||
return this.mActiveCall;
|
||||
},
|
||||
|
||||
get activeCallForContactImage() {
|
||||
return this.mActiveCallForContactImage;
|
||||
},
|
||||
|
||||
isFirstCallOnCdmaNetwork: function() {
|
||||
return this.mIsFirstCallOnCdmaNetwork;
|
||||
},
|
||||
|
||||
toggleCalls: function() {},
|
||||
toggleMute: function() {},
|
||||
unmute: function() {},
|
||||
toggleSpeaker: function() {},
|
||||
switchToSpeaker: function() {},
|
||||
switchToDefaultOut: function() {},
|
||||
switchToReceiver: function() {},
|
||||
checkCalls: function() {},
|
||||
end: function() {},
|
||||
answer: function() {},
|
||||
updateAllPhoneNumberDisplays: function() {},
|
||||
updatePlaceNewCall: function() {},
|
||||
mergeCalls: function() {},
|
||||
holdOrResumeSingleCall: function() {},
|
||||
updateMergeAndOnHoldStatus: function() {},
|
||||
updateMuteAndSpeakerStatus: function() {},
|
||||
setup: function () {},
|
||||
|
||||
mTeardown: function() {
|
||||
this.mActiveCall = null;
|
||||
this.mActiveCallForContactImage = null;
|
||||
this.mIsFirstCallOnCdmaNetwork = false;
|
||||
}
|
||||
};
|
||||
60
gaia/shared/test/unit/mocks/dialer/mock_contacts.js
Executable file
60
gaia/shared/test/unit/mocks/dialer/mock_contacts.js
Executable file
|
|
@ -0,0 +1,60 @@
|
|||
'use strict';
|
||||
/* exported MockContacts */
|
||||
|
||||
var MockContacts = {
|
||||
|
||||
// We need to test calls without contact information
|
||||
// so we'll return that info depending on the
|
||||
// calling number
|
||||
// '111': No contacts
|
||||
// '222': More than 1 contact for that number
|
||||
// Any other: 1 contact
|
||||
findByNumber: function findByNumber(number, callback) {
|
||||
this.mCalledWith = number;
|
||||
this.mPhoto = 'test';
|
||||
this.mName = 'test name';
|
||||
var tel = {
|
||||
value: this.mCalledWith,
|
||||
carrier: this.mCarrier,
|
||||
type: this.mType
|
||||
};
|
||||
var contact = {
|
||||
id: this.mId,
|
||||
name: [this.mName],
|
||||
tel: [tel],
|
||||
photo: [this.mPhoto]
|
||||
};
|
||||
var contactsWithSameNumber = 0;
|
||||
switch (number) {
|
||||
case '111':
|
||||
this.mPhoto = null;
|
||||
this.mName = null;
|
||||
contact = null;
|
||||
tel = null;
|
||||
break;
|
||||
case '222':
|
||||
contactsWithSameNumber = 2;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
callback(contact, tel, contactsWithSameNumber);
|
||||
},
|
||||
findListByNumber: function cm_getContactData(number, maxitems, callback) {
|
||||
callback(this.mResult);
|
||||
},
|
||||
getRevision: function cm_getRevision(callback) { callback(0); },
|
||||
mId: 'id',
|
||||
mPhoto: null,
|
||||
mName: null,
|
||||
mCalledWith: null,
|
||||
mCarrier: 'carrier',
|
||||
mType: 'type',
|
||||
mResult: null,
|
||||
mTearDown: function tearDown() {
|
||||
this._calledWith = null;
|
||||
this.mCarrier = 'carrier';
|
||||
this.mType = 'type';
|
||||
this.mResult = [];
|
||||
}
|
||||
};
|
||||
18
gaia/shared/test/unit/mocks/dialer/mock_font_size_manager.js
Executable file
18
gaia/shared/test/unit/mocks/dialer/mock_font_size_manager.js
Executable file
|
|
@ -0,0 +1,18 @@
|
|||
/* exported MockFontSizeManager */
|
||||
|
||||
'use strict';
|
||||
|
||||
var MockFontSizeManager = {
|
||||
/**
|
||||
* Possible scenarios as declared by FontSizeManager.
|
||||
*/
|
||||
DIAL_PAD: 0,
|
||||
SINGLE_CALL: 1,
|
||||
CALL_WAITING: 2,
|
||||
STATUS_BAR: 3,
|
||||
SECOND_INCOMING_CALL: 4,
|
||||
|
||||
adaptToSpace: function() {},
|
||||
ensureFixedBaseline: function() {},
|
||||
resetFixedBaseline: function() {}
|
||||
};
|
||||
94
gaia/shared/test/unit/mocks/dialer/mock_handled_call.js
Executable file
94
gaia/shared/test/unit/mocks/dialer/mock_handled_call.js
Executable file
|
|
@ -0,0 +1,94 @@
|
|||
/* globals HandledCall, MockNavigatorMozTelephony */
|
||||
/* exported telephonyAddCall, telephonyAddCdmaCall */
|
||||
|
||||
'use strict';
|
||||
|
||||
function MockHandledCall(call) {
|
||||
this.call = call;
|
||||
this.node = document.createElement('section'); // fake dom
|
||||
}
|
||||
|
||||
MockHandledCall.prototype.handleEvent = function hc_handle(evt) {
|
||||
};
|
||||
|
||||
MockHandledCall.prototype.startTimer = function hc_startTimer() {
|
||||
};
|
||||
|
||||
MockHandledCall.prototype.updateCallNumber = function hc_updateCallNumber() {
|
||||
};
|
||||
|
||||
MockHandledCall.prototype.replaceAdditionalContactInfo =
|
||||
function hc_replaceAdditionalContactInfo(additionalContactInfo) {
|
||||
};
|
||||
|
||||
MockHandledCall.prototype.restoreAdditionalContactInfo =
|
||||
function hc_restoreAdditionalContactInfo(additionalContactInfo) {
|
||||
};
|
||||
|
||||
MockHandledCall.prototype.formatPhoneNumber =
|
||||
function hc_formatPhoneNumber(ellipsisSide, maxFontSize) {
|
||||
};
|
||||
|
||||
MockHandledCall.prototype.renderPhoneNumber =
|
||||
function hc_renderPhoneNumber(phoneNumber, ellipsisSide) {
|
||||
};
|
||||
|
||||
MockHandledCall.prototype.replacePhoneNumber =
|
||||
function hc_replacePhoneNumber(phoneNumber, ellipsisSide) {
|
||||
};
|
||||
|
||||
MockHandledCall.prototype.restorePhoneNumber =
|
||||
function hc_restorePhoneNumber() {
|
||||
};
|
||||
|
||||
MockHandledCall.prototype.updateDirection = function hc_updateDirection() {
|
||||
};
|
||||
|
||||
MockHandledCall.prototype.remove = function hc_remove() {
|
||||
};
|
||||
|
||||
MockHandledCall.prototype.connected = function hc_connected() {
|
||||
};
|
||||
|
||||
MockHandledCall.prototype.busy = function hc_busy() {
|
||||
};
|
||||
|
||||
MockHandledCall.prototype.disconnected = function hc_disconnected() {
|
||||
};
|
||||
|
||||
MockHandledCall.prototype.show = function hc_show() {
|
||||
};
|
||||
|
||||
MockHandledCall.prototype.hide = function hc_hide() {
|
||||
};
|
||||
|
||||
// Should be called in the context of a suite
|
||||
function telephonyAddCall(mockCall, opt) {
|
||||
MockNavigatorMozTelephony.calls.push(mockCall);
|
||||
|
||||
var handledCall = new MockHandledCall(mockCall);
|
||||
|
||||
// not already stubed
|
||||
if (!('restore' in HandledCall)) {
|
||||
/* jshint validthis: true */
|
||||
this.sinon.stub(window, 'HandledCall');
|
||||
}
|
||||
HandledCall.withArgs(mockCall).returns(handledCall);
|
||||
|
||||
if (opt && opt.trigger) {
|
||||
MockNavigatorMozTelephony.mTriggerCallsChanged();
|
||||
}
|
||||
|
||||
return handledCall;
|
||||
}
|
||||
|
||||
/* Should be called in the context of a suite after one call has already been
|
||||
* added via telephonyAddCall(). */
|
||||
function telephonyAddCdmaCall(number, opt) {
|
||||
MockNavigatorMozTelephony.calls[0].secondId = { number: number };
|
||||
MockNavigatorMozTelephony.calls[0].state = 'connected';
|
||||
|
||||
if (opt && opt.trigger) {
|
||||
MockNavigatorMozTelephony.mTriggerCallsChanged();
|
||||
}
|
||||
}
|
||||
29
gaia/shared/test/unit/mocks/dialer/mock_keypad.js
Executable file
29
gaia/shared/test/unit/mocks/dialer/mock_keypad.js
Executable file
|
|
@ -0,0 +1,29 @@
|
|||
'use strict';
|
||||
/* exported MockKeypadManager */
|
||||
|
||||
var MockKeypadManager = {
|
||||
_phoneNumber: '',
|
||||
mOnMakeCall: null,
|
||||
lastCalled: '15555555555',
|
||||
init: function() {},
|
||||
updatePhoneNumber: function khm_updatePhoneNumber(number) {
|
||||
this._phoneNumber = number;
|
||||
},
|
||||
makeCall: function makeCall() {
|
||||
if (this.mOnMakeCall) {
|
||||
if (this._phoneNumber) {
|
||||
this.lastCalled = this._phoneNumber;
|
||||
}
|
||||
this.mOnMakeCall(this._phoneNumber);
|
||||
}
|
||||
},
|
||||
phoneNumber: function phoneNumber() {
|
||||
return this._phoneNumber;
|
||||
},
|
||||
fetchLastCalled: function() {
|
||||
this._phoneNumber = this.lastCalled;
|
||||
},
|
||||
render: function() {},
|
||||
restorePhoneNumber: function() {},
|
||||
restoreAdditionalContactInfo: function() {}
|
||||
};
|
||||
20
gaia/shared/test/unit/mocks/dialer/mock_telephony_helper.js
Executable file
20
gaia/shared/test/unit/mocks/dialer/mock_telephony_helper.js
Executable file
|
|
@ -0,0 +1,20 @@
|
|||
'use strict';
|
||||
|
||||
/* exported MockTelephonyHelper */
|
||||
|
||||
var MockTelephonyHelper = {
|
||||
mInUseSim: null,
|
||||
mCallPromise: null,
|
||||
call: function() {
|
||||
if (!this.mCallPromise) {
|
||||
this.mCallPromise = new Promise(() => {});
|
||||
}
|
||||
|
||||
return this.mCallPromise;
|
||||
},
|
||||
getInUseSim: function() { return this.mInUseSim; },
|
||||
mTeardown: function() {
|
||||
this.mInUseSim = null;
|
||||
this.mCallPromise = null;
|
||||
}
|
||||
};
|
||||
14
gaia/shared/test/unit/mocks/dialer/mock_telephony_messages.js
Executable file
14
gaia/shared/test/unit/mocks/dialer/mock_telephony_messages.js
Executable file
|
|
@ -0,0 +1,14 @@
|
|||
'use strict';
|
||||
|
||||
/* exported MockTelephonyMessages */
|
||||
|
||||
var MockTelephonyMessages = {
|
||||
REGULAR_CALL: 0,
|
||||
NO_NETWORK: 1,
|
||||
EMERGENCY_ONLY: 2,
|
||||
|
||||
displayMessage: function() {},
|
||||
handleDisconnect: function() {},
|
||||
handleError: function() {},
|
||||
notifyBusyLine: function() {}
|
||||
};
|
||||
10
gaia/shared/test/unit/mocks/dialer/mock_tone_player.js
Executable file
10
gaia/shared/test/unit/mocks/dialer/mock_tone_player.js
Executable file
|
|
@ -0,0 +1,10 @@
|
|||
/* exported MockTonePlayer */
|
||||
|
||||
'use strict';
|
||||
|
||||
var MockTonePlayer = {
|
||||
init: function() {},
|
||||
playSequence: function() {},
|
||||
start: function(frequencies, shortPress) {},
|
||||
stop: function() {}
|
||||
};
|
||||
72
gaia/shared/test/unit/mocks/dialer/mock_utils.js
Executable file
72
gaia/shared/test/unit/mocks/dialer/mock_utils.js
Executable file
|
|
@ -0,0 +1,72 @@
|
|||
'use strict';
|
||||
/* exported MockUtils */
|
||||
|
||||
var MockUtils = {
|
||||
mCalledPrettyDate: false,
|
||||
mCalledSetHeaderDate: false,
|
||||
mCalledGetDayDate: false,
|
||||
mCalledGetPhoneNumberPrimaryInfo: false,
|
||||
mCalledGetPhoneNumberAdditionalInfo: false,
|
||||
|
||||
prettyDate: function ut_prettyDate(time) {
|
||||
this.mCalledPrettyDate = true;
|
||||
},
|
||||
|
||||
setHeaderDate: function ut_headerDate(elem, time) {
|
||||
this.mCalledSetHeaderDate = true;
|
||||
elem.textContent = time;
|
||||
},
|
||||
|
||||
getDayDate: function re_getDayDate(timestamp) {
|
||||
this.mCalledGetDayDate = true;
|
||||
var date = new Date(timestamp);
|
||||
var startDate = new Date(date.getFullYear(),
|
||||
date.getMonth(), date.getDate());
|
||||
return startDate.getTime();
|
||||
},
|
||||
|
||||
getPhoneNumberAdditionalInfo:
|
||||
function getPhoneNumberAdditionalInfo(matchingTel) {
|
||||
return {
|
||||
id: matchingTel.type,
|
||||
args: {
|
||||
carrier: matchingTel.carrier
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
addEllipsis: function ut_addEllipsis() {},
|
||||
|
||||
getNextFontSize: function ut_getNextFontSize(view, fakeView, maxFontSize,
|
||||
minFontSize, fontStep) {
|
||||
return maxFontSize;
|
||||
},
|
||||
|
||||
mTearDown: function tearDown() {
|
||||
this.mCalledPrettyDate = false;
|
||||
this.mCalledHeaderDate = false;
|
||||
this.mCalledGetDayDate = false;
|
||||
this.mCalledGetPhoneNumberPrimaryInfo = false;
|
||||
this.mCalledGetPhoneNumberAdditionalInfo = false;
|
||||
},
|
||||
|
||||
getPhoneNumberPrimaryInfo: function ut_getPhoneNumberPrimaryInfo(matchingTel,
|
||||
contact) {
|
||||
this.mCalledGetPhoneNumberPrimaryInfo = true;
|
||||
if (contact) {
|
||||
if (contact.name && String(contact.name) !== '') {
|
||||
return contact.name;
|
||||
} else if (contact.org && String(contact.org) !== '') {
|
||||
return contact.org;
|
||||
}
|
||||
}
|
||||
if (matchingTel) {
|
||||
return matchingTel.value;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
prettyDuration: function(node, duration, l10nPrefix) {},
|
||||
isPhoneType: function(type) {}
|
||||
};
|
||||
|
||||
77
gaia/shared/test/unit/mocks/elements/custom_elements_helper.js
Executable file
77
gaia/shared/test/unit/mocks/elements/custom_elements_helper.js
Executable file
|
|
@ -0,0 +1,77 @@
|
|||
'use strict';
|
||||
|
||||
/**
|
||||
* Helper for applying methods from a mock to an element in the DOM. This is
|
||||
* needed when mocking web components. For instance, we may have to test that
|
||||
* some code properly calls into a web component like so:
|
||||
*
|
||||
* ```html
|
||||
* <!-- mock html -->
|
||||
* <gaia-web-component id="myWC"></gaia-web-component>
|
||||
* ```
|
||||
*
|
||||
* ```js
|
||||
* // code to test
|
||||
* var wc = document.getElementById('myWC');
|
||||
* wc.foo();
|
||||
* ```
|
||||
*
|
||||
* ```js
|
||||
* // test
|
||||
* var wc = document.getElementById('myWC');
|
||||
* this.sinon.stub(wc, 'foo');
|
||||
* // call method that will call foo()
|
||||
* sinon.assert.calledOnce(wc.foo);
|
||||
* ```
|
||||
*
|
||||
* This won't work because we aren't importing the actual gaia-web-component
|
||||
* component. The solution here is to copy the methods from a mock to the
|
||||
* gaia-web-component, like this:
|
||||
*
|
||||
* ```html
|
||||
* <!-- mock html -->
|
||||
* <gaia-web-component id="myWC"></gaia-web-component>
|
||||
* ```
|
||||
*
|
||||
* ```js
|
||||
* // code to test
|
||||
* var wc = document.getElementById('myWC');
|
||||
* wc.foo();
|
||||
* ```
|
||||
*
|
||||
* ```js
|
||||
* // mock
|
||||
* var MockGaiaWebComponent = {
|
||||
* foo: function() {}
|
||||
* };
|
||||
* ```
|
||||
*
|
||||
* ```js
|
||||
* // test
|
||||
*
|
||||
* // use MocksHelper to set GaiaWebComponent = MockGaiaWebComponent
|
||||
*
|
||||
* var customElementsHelperForMyTest =
|
||||
* new CustomElementsHelper(['GaiaWebComponent']);
|
||||
* customElementsHelperForMyTest.resolve();
|
||||
*
|
||||
* // now stub and call it as before
|
||||
* ```
|
||||
*/
|
||||
var CustomElementsHelper = function(mocks) {
|
||||
this.mocks = mocks.sort();
|
||||
};
|
||||
|
||||
CustomElementsHelper.prototype = {
|
||||
resolve: function emh_resolve() {
|
||||
this.mocks.forEach(function(objName) {
|
||||
var eltName = objName.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
|
||||
var matchingElts = document.querySelectorAll(eltName);
|
||||
for (var key in window[objName]) {
|
||||
for (var i = 0; i < matchingElts.length; i++) {
|
||||
matchingElts[i][key] = window[objName][key];
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
8
gaia/shared/test/unit/mocks/elements/gaia_menu/mock_gaia_menu.js
Executable file
8
gaia/shared/test/unit/mocks/elements/gaia_menu/mock_gaia_menu.js
Executable file
|
|
@ -0,0 +1,8 @@
|
|||
/* exported MockGaiaMenu */
|
||||
|
||||
'use strict';
|
||||
|
||||
var MockGaiaMenu = {
|
||||
show: function() {},
|
||||
hide: function() {}
|
||||
};
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
/* exported MockGaiaSimPicker */
|
||||
|
||||
'use strict';
|
||||
|
||||
var MockGaiaSimPicker = {
|
||||
getOrPick: function() { }
|
||||
};
|
||||
12
gaia/shared/test/unit/mocks/gzip/mock_gzip.min.js
vendored
Executable file
12
gaia/shared/test/unit/mocks/gzip/mock_gzip.min.js
vendored
Executable file
|
|
@ -0,0 +1,12 @@
|
|||
'use strict';
|
||||
|
||||
var Zlib = {};
|
||||
|
||||
Zlib.Gzip = function(data) {
|
||||
this.data = data;
|
||||
};
|
||||
|
||||
Zlib.Gzip.prototype.compress = function(payload) {
|
||||
throw 'Gzip.compress error';
|
||||
};
|
||||
|
||||
27
gaia/shared/test/unit/mocks/gzip/mock_gzip_worker.js
Executable file
27
gaia/shared/test/unit/mocks/gzip/mock_gzip_worker.js
Executable file
|
|
@ -0,0 +1,27 @@
|
|||
/* global Zlib */
|
||||
'use strict';
|
||||
|
||||
importScripts('mock_gzip.min.js');
|
||||
|
||||
self.onmessage = function(message) {
|
||||
var cmd = message.data.cmd;
|
||||
|
||||
if (cmd === 'gzip') {
|
||||
// gzip function requires Uint8Array
|
||||
var textEncoder = new TextEncoder('utf8');
|
||||
var payload = message.data.payload;
|
||||
var uint8Data = textEncoder.encode(payload);
|
||||
|
||||
try {
|
||||
var gzip = new Zlib.Gzip(uint8Data);
|
||||
var compressed = gzip.compress();
|
||||
postMessage({returnResult: true, gzipData: compressed});
|
||||
}
|
||||
catch(e) {
|
||||
postMessage({returnResult: false, error: e});
|
||||
}
|
||||
} else {
|
||||
console.warn('GzipWorker, unsupported cmd:', cmd);
|
||||
}
|
||||
};
|
||||
|
||||
7
gaia/shared/test/unit/mocks/mock_accessibility_helper.js
Executable file
7
gaia/shared/test/unit/mocks/mock_accessibility_helper.js
Executable file
|
|
@ -0,0 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
/* exported MockAccessibilityHelper */
|
||||
|
||||
var MockAccessibilityHelper = {
|
||||
setAriaSelected: function(selectedTab, tabs) {}
|
||||
};
|
||||
31
gaia/shared/test/unit/mocks/mock_advanced_telemetry_helper.js
Executable file
31
gaia/shared/test/unit/mocks/mock_advanced_telemetry_helper.js
Executable file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
Copyright 2015, Mozilla Foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/* exported MockAdvancedTelemetryHelper */
|
||||
|
||||
function MockAdvancedTelemetryHelper(type, name) {
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
MockAdvancedTelemetryHelper.HISTOGRAM_COUNT = 4;
|
||||
MockAdvancedTelemetryHelper.HISTOGRAM_EXP = 0;
|
||||
MockAdvancedTelemetryHelper.HISTOGRAM_LINEAR = 1;
|
||||
|
||||
MockAdvancedTelemetryHelper.prototype.add = function(number) {};
|
||||
|
||||
11
gaia/shared/test/unit/mocks/mock_async_storage.js
Executable file
11
gaia/shared/test/unit/mocks/mock_async_storage.js
Executable file
|
|
@ -0,0 +1,11 @@
|
|||
/*exported MockasyncStorage */
|
||||
|
||||
'use strict';
|
||||
|
||||
var MockasyncStorage = {
|
||||
getItem: function(key, callback) {
|
||||
callback();
|
||||
},
|
||||
setItem: function(key, value) {},
|
||||
removeItem: function() {}
|
||||
};
|
||||
87
gaia/shared/test/unit/mocks/mock_audio.js
Executable file
87
gaia/shared/test/unit/mocks/mock_audio.js
Executable file
|
|
@ -0,0 +1,87 @@
|
|||
'use strict';
|
||||
|
||||
function MockAudio(src) {
|
||||
MockAudio.instances.push(this);
|
||||
this.src = src;
|
||||
this.readyState = 1;
|
||||
this.paused = true;
|
||||
}
|
||||
|
||||
MockAudio.instances = [];
|
||||
|
||||
MockAudio.mSetup = function() {
|
||||
MockAudio.instances = [];
|
||||
};
|
||||
|
||||
MockAudio.mTeardown = function() {
|
||||
MockAudio.instances = [];
|
||||
};
|
||||
|
||||
MockAudio.prototype.HAVE_NOTHING = 0;
|
||||
|
||||
MockAudio.prototype.load = function() {
|
||||
};
|
||||
|
||||
MockAudio.prototype.play = function() {
|
||||
// FIXME can we replace playing with paused?
|
||||
this.playing = true;
|
||||
this.paused = false;
|
||||
};
|
||||
|
||||
MockAudio.prototype.pause = function() {
|
||||
this.playing = false;
|
||||
this.paused = true;
|
||||
};
|
||||
|
||||
MockAudio.prototype.removeAttribute = function() {
|
||||
};
|
||||
|
||||
MockAudio.prototype.cloneNode = function() {
|
||||
return this;
|
||||
};
|
||||
|
||||
function MockAudioContext(channel) {
|
||||
MockAudioContext.instances.push(this);
|
||||
this.mozAudioChannelType = channel;
|
||||
this.currentTime = 0;
|
||||
this.sampleRate = 0;
|
||||
this.destination = {};
|
||||
}
|
||||
|
||||
MockAudioContext.instances = [];
|
||||
|
||||
MockAudioContext.mSetup = function() {
|
||||
MockAudioContext.instances = [];
|
||||
};
|
||||
|
||||
MockAudioContext.mTeardown = function() {
|
||||
MockAudioContext.instances = [];
|
||||
};
|
||||
|
||||
MockAudioContext.prototype.createBuffer = function() { return {}; };
|
||||
MockAudioContext.prototype.createBufferSource = function() {
|
||||
return {
|
||||
connect: function() {},
|
||||
start: function() {},
|
||||
stop: function() {}
|
||||
};
|
||||
};
|
||||
MockAudioContext.prototype.createGain = function() {
|
||||
return {
|
||||
connect() {},
|
||||
gain: {
|
||||
setValueAtTime() {},
|
||||
setValueCurveAtTime() {}
|
||||
}
|
||||
};
|
||||
};
|
||||
MockAudioContext.prototype.createOscillator = function() {
|
||||
return {
|
||||
frequency: { value: 0 },
|
||||
connect: function() {},
|
||||
start: function() {},
|
||||
stop: function() {}
|
||||
};
|
||||
};
|
||||
MockAudioContext.prototype.addEventListener = function() {};
|
||||
MockAudioContext.prototype.removeEventListener = function() {};
|
||||
25
gaia/shared/test/unit/mocks/mock_basket_client.js
Executable file
25
gaia/shared/test/unit/mocks/mock_basket_client.js
Executable file
|
|
@ -0,0 +1,25 @@
|
|||
/* global Promise */
|
||||
/* exported MockBasket */
|
||||
|
||||
'use strict';
|
||||
|
||||
var MockBasket = {
|
||||
_err: null,
|
||||
_data: {
|
||||
'status': 'ok'
|
||||
},
|
||||
_dataStore: null,
|
||||
|
||||
send: function(data, callback) {
|
||||
if (callback) {
|
||||
callback(this._err, this._data);
|
||||
}
|
||||
},
|
||||
|
||||
getDataStore: function() {
|
||||
var self = this;
|
||||
return new Promise(function (resolve, reject) {
|
||||
resolve(self._dataStore);
|
||||
});
|
||||
}
|
||||
};
|
||||
33
gaia/shared/test/unit/mocks/mock_bluetooth_helper.js
Executable file
33
gaia/shared/test/unit/mocks/mock_bluetooth_helper.js
Executable file
|
|
@ -0,0 +1,33 @@
|
|||
/* exported MockBluetoothHelper, MockBluetoothHelperInstance */
|
||||
|
||||
'use strict';
|
||||
|
||||
var MockBluetoothHelperInstance = {
|
||||
profiles: {
|
||||
'HFP': 0x111E,
|
||||
'A2DP': 0x110D
|
||||
},
|
||||
answerWaitingCall: function() {},
|
||||
ignoreWaitingCall: function() {},
|
||||
toggleCalls: function() {},
|
||||
getConnectedDevicesByProfile: function() {},
|
||||
connectSco: function() {},
|
||||
disconnectSco: function() {},
|
||||
getPairedDevices: function() {},
|
||||
getAddress: function() {},
|
||||
setPairingConfirmation: function() {},
|
||||
setPinCode: function() {},
|
||||
setPasskey: function() {},
|
||||
isScoConnected: function() {},
|
||||
sendMediaMetaData: function() {},
|
||||
sendMediaPlayStatus: function() {},
|
||||
onhfpstatuschanged: null,
|
||||
onscostatuschanged: null,
|
||||
ona2dpstatuschanged: null,
|
||||
onpairedstatuschanged: null,
|
||||
onrequestmediaplaystatus: null
|
||||
};
|
||||
|
||||
var MockBluetoothHelper = function() {
|
||||
return MockBluetoothHelperInstance;
|
||||
};
|
||||
32
gaia/shared/test/unit/mocks/mock_bookmarks_database.js
Executable file
32
gaia/shared/test/unit/mocks/mock_bookmarks_database.js
Executable file
|
|
@ -0,0 +1,32 @@
|
|||
'use strict';
|
||||
|
||||
(function(exports) {
|
||||
exports.MockBookmarksDatabase = {
|
||||
get: function() {},
|
||||
_callbacks: {},
|
||||
getAll: function() {},
|
||||
getRevisionId: function() {},
|
||||
addEventListener: function(type, cb) {
|
||||
this._callbacks[type] = cb;
|
||||
},
|
||||
removeEventListener: function(type) {
|
||||
this._callbacks[type] = null;
|
||||
},
|
||||
add: function(data) {
|
||||
if (this._callbacks.added) {
|
||||
this._callbacks.added(data);
|
||||
}
|
||||
},
|
||||
put: function(data) {
|
||||
if (this._callbacks.added) {
|
||||
this._callbacks.added(data);
|
||||
}
|
||||
},
|
||||
remove: function(id) {
|
||||
if (this._callbacks.removed) {
|
||||
this._callbacks.removed(id);
|
||||
}
|
||||
},
|
||||
clear: function() {}
|
||||
};
|
||||
}(window));
|
||||
16
gaia/shared/test/unit/mocks/mock_canvas.js
Executable file
16
gaia/shared/test/unit/mocks/mock_canvas.js
Executable file
|
|
@ -0,0 +1,16 @@
|
|||
'use strict';
|
||||
|
||||
(function(exports) {
|
||||
var MockCanvas = function() {
|
||||
this.width = null;
|
||||
this.height = null;
|
||||
return this;
|
||||
};
|
||||
|
||||
MockCanvas.prototype = {
|
||||
getContext: function mc_getContext() {
|
||||
}
|
||||
};
|
||||
|
||||
exports.MockCanvas = MockCanvas;
|
||||
})(window);
|
||||
18
gaia/shared/test/unit/mocks/mock_canvas_rendering_context_2d.js
Executable file
18
gaia/shared/test/unit/mocks/mock_canvas_rendering_context_2d.js
Executable file
|
|
@ -0,0 +1,18 @@
|
|||
'use strict';
|
||||
|
||||
(function(exports) {
|
||||
var MockCanvasRenderingContext2D = function() {
|
||||
this.width = null;
|
||||
this.height = null;
|
||||
return this;
|
||||
};
|
||||
|
||||
MockCanvasRenderingContext2D.prototype = {
|
||||
drawImage: function mcrc2_drawImage() {
|
||||
},
|
||||
getImageData: function mcrc2_getImageData() {
|
||||
},
|
||||
};
|
||||
|
||||
exports.MockCanvasRenderingContext2D = MockCanvasRenderingContext2D;
|
||||
})(window);
|
||||
35
gaia/shared/test/unit/mocks/mock_card_store.js
Executable file
35
gaia/shared/test/unit/mocks/mock_card_store.js
Executable file
|
|
@ -0,0 +1,35 @@
|
|||
(function(exports) {
|
||||
'use strict';
|
||||
|
||||
var MockCardStore = {
|
||||
_dataInStore: {},
|
||||
mPrepareData: function(id, data) {
|
||||
this._dataInStore[id] = data;
|
||||
},
|
||||
|
||||
mClearData: function() {
|
||||
this._dataInStore = {};
|
||||
},
|
||||
|
||||
getData: function(id) {
|
||||
var that = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
if (that._dataInStore[id]) {
|
||||
resolve(that._dataInStore[id]);
|
||||
} else {
|
||||
resolve(undefined);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
saveData: function(id, data) {
|
||||
var that = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
that._dataInStore[id] = data;
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
exports.MockCardStore = MockCardStore;
|
||||
}(window));
|
||||
22
gaia/shared/test/unit/mocks/mock_confirm_dialog.js
Executable file
22
gaia/shared/test/unit/mocks/mock_confirm_dialog.js
Executable file
|
|
@ -0,0 +1,22 @@
|
|||
'use strict';
|
||||
|
||||
/* exported MockConfirmDialog */
|
||||
|
||||
var MockConfirmDialog = {
|
||||
showing: false,
|
||||
title: null,
|
||||
text: null,
|
||||
button: null,
|
||||
show: function(title, text, button) {
|
||||
this.showing = true;
|
||||
this.title = title;
|
||||
this.text = text;
|
||||
this.button = button;
|
||||
},
|
||||
hide: function() {
|
||||
this.showing = false;
|
||||
this.title = null;
|
||||
this.text = null;
|
||||
this.button = null;
|
||||
}
|
||||
};
|
||||
98
gaia/shared/test/unit/mocks/mock_contact_all_fields.js
Executable file
98
gaia/shared/test/unit/mocks/mock_contact_all_fields.js
Executable file
|
|
@ -0,0 +1,98 @@
|
|||
'use strict';
|
||||
/* exported MockContactAllFields */
|
||||
|
||||
function MockContactAllFields(withoutPhoto) {
|
||||
var photo;
|
||||
if (!withoutPhoto) {
|
||||
photo = getPhotoBlob();
|
||||
}
|
||||
return {
|
||||
'id': '1',
|
||||
'updated': new Date(),
|
||||
'additionalName': ['Green'],
|
||||
'adr': [
|
||||
{
|
||||
'type': ['home'],
|
||||
'pref': true,
|
||||
'countryName': 'Germany',
|
||||
'locality': 'Chemnitz',
|
||||
'region': 'Chemnitz',
|
||||
'postalCode': '09034',
|
||||
'streetAddress': 'Gotthardstrasse 22'
|
||||
}
|
||||
],
|
||||
'bday': new Date(Date.UTC(1970, 0, 1)),
|
||||
'email': [
|
||||
{
|
||||
'type': ['personal'],
|
||||
'value': 'test@test.com'
|
||||
},
|
||||
{
|
||||
'type': ['work'],
|
||||
'value': 'test@work.com',
|
||||
'pref': true
|
||||
}
|
||||
],
|
||||
'honorificPrefix': ['Mr.'],
|
||||
'familyName': ['Grillo'],
|
||||
'givenName': ['Pepito'],
|
||||
'nickname': ['PG'],
|
||||
'jobTitle': ['Sr. Software Architect'],
|
||||
'name': ['Pepito Grillo'],
|
||||
'org': ['Test ORG'],
|
||||
'tel': [
|
||||
{
|
||||
'value': '+346578888888',
|
||||
'type': ['mobile'],
|
||||
'carrier': 'TEF',
|
||||
'pref': true
|
||||
},
|
||||
{
|
||||
'value': '+3120777777',
|
||||
'type': ['Home'],
|
||||
'carrier': 'KPN'
|
||||
}
|
||||
],
|
||||
'url' : [
|
||||
{
|
||||
'type' : ['fb_profile_photo'],
|
||||
'value' : 'https://abcd1.jpg'
|
||||
}
|
||||
],
|
||||
'category': ['favorite'],
|
||||
'note': ['Note 1'],
|
||||
'photo': [photo]
|
||||
};
|
||||
}
|
||||
|
||||
function getPhotoBlob() {
|
||||
var b64 = 'R0lGODlhEAAQAMQfAKxoR8VkLxFw1feVPITSWv+eQv7Qo0Cc6OyIN/v7+3PLTSCZ' +
|
||||
'EFy17Wa6XuT1x2bGQ3nNUU6vRXPAa9mLXMTkwJZEHJt7LL5aJ/z8/O2KONx3L/ubP/r6+rtV' +
|
||||
'I////////yH5BAEAAB8ALAAAAAAQABAAAAWD4CeOZDlimOitnvlhXefFiyCs3NkZMe9QDMGi' +
|
||||
'k3t1BgZDIcZgHCCxHAyxKRQmnYOkoYgaNYMNr3JoEB6dDBGmyWxihwNBgVZz2Js3YB+JWNpr' +
|
||||
'HW15YgA2FxkaRB8JgoQxHQEbdiKNg4R5iYuVgpcZmkUjHDEapYqbJRyjkKouoqqhIyEAOw==';
|
||||
|
||||
return b64toBlob(b64, 'image/gif');
|
||||
}
|
||||
|
||||
function b64toBlob(b64Data, contentType, sliceSize) {
|
||||
contentType = contentType || '';
|
||||
sliceSize = sliceSize || 1024;
|
||||
|
||||
function charCodeFromCharacter(c) {
|
||||
return c.charCodeAt(0);
|
||||
}
|
||||
|
||||
var byteCharacters = atob(b64Data);
|
||||
var byteArrays = [];
|
||||
|
||||
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
|
||||
var slice = byteCharacters.slice(offset, offset + sliceSize);
|
||||
var byteNumbers = Array.prototype.map.call(slice, charCodeFromCharacter);
|
||||
var byteArray = new Uint8Array(byteNumbers);
|
||||
|
||||
byteArrays.push(byteArray);
|
||||
}
|
||||
|
||||
return new Blob(byteArrays, {type: contentType});
|
||||
}
|
||||
21
gaia/shared/test/unit/mocks/mock_contact_photo_helper.js
Executable file
21
gaia/shared/test/unit/mocks/mock_contact_photo_helper.js
Executable file
|
|
@ -0,0 +1,21 @@
|
|||
'use strict';
|
||||
|
||||
/* exported MockContactPhotoHelper */
|
||||
|
||||
var MockContactPhotoHelper = {
|
||||
getThumbnail: function(contact) {
|
||||
if (!contact || !contact.photo || !contact.photo.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return contact.photo[0];
|
||||
},
|
||||
|
||||
getFullResolution: function(contact) {
|
||||
if (!contact || !contact.photo || !contact.photo.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return contact.photo[0];
|
||||
}
|
||||
};
|
||||
41
gaia/shared/test/unit/mocks/mock_crop_resize_rotate.js
Executable file
41
gaia/shared/test/unit/mocks/mock_crop_resize_rotate.js
Executable file
|
|
@ -0,0 +1,41 @@
|
|||
'use strict';
|
||||
/*jshint maxlen:false*/
|
||||
/*exported MockCropResizeRotate*/
|
||||
|
||||
var MockCropResizeRotate =
|
||||
function(blob, cropRegion, outputSize, outputType, metadata, callback) {
|
||||
// The 2nd, 3rd, 4th and 5th arguments are optional, so fix things up if we're
|
||||
// called with fewer than 6 args. The last argument is always the callback.
|
||||
switch (arguments.length) {
|
||||
case 2:
|
||||
callback = cropRegion;
|
||||
cropRegion = outputSize = outputType = metadata = null;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
callback = outputSize;
|
||||
outputSize = outputType = metadata = null;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
callback = outputType;
|
||||
outputType = metadata = null;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
callback = metadata;
|
||||
metadata = null;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
// everything fine. do nothing here
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error('wrong number of arguments: ' + arguments.length);
|
||||
}
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback(null, blob);
|
||||
}
|
||||
};
|
||||
38
gaia/shared/test/unit/mocks/mock_custom_dialog.js
Executable file
38
gaia/shared/test/unit/mocks/mock_custom_dialog.js
Executable file
|
|
@ -0,0 +1,38 @@
|
|||
/* exported MockCustomDialog */
|
||||
|
||||
'use strict';
|
||||
|
||||
var MockCustomDialog = {
|
||||
show: function(title, msg, cancel, confirm, element) {
|
||||
this.mShown = true;
|
||||
this.mShowedTitle = title;
|
||||
this.mShowedMsg = msg;
|
||||
this.mShowedCancel = cancel;
|
||||
this.mShowedConfirm = confirm;
|
||||
this.mShowedElement = element;
|
||||
this.mShowedScreen = document.createElement('form');
|
||||
|
||||
return this.mShowedScreen;
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
this.mShown = false;
|
||||
},
|
||||
|
||||
mShown: false,
|
||||
mShowedTitle: null,
|
||||
mShowedMsg: null,
|
||||
mShowedCancel: null,
|
||||
mShowedConfirm: null,
|
||||
mShowedElement: null,
|
||||
mShowedScreen: null,
|
||||
mTeardown: function teardown() {
|
||||
this.mShown = false;
|
||||
this.mShowedTitle = null;
|
||||
this.mShowedMsg = null;
|
||||
this.mShowedCancel = null;
|
||||
this.mShowedConfirm = null;
|
||||
this.mShowedElement = null;
|
||||
this.mShowedScreen = null;
|
||||
}
|
||||
};
|
||||
26
gaia/shared/test/unit/mocks/mock_custom_event.js
Executable file
26
gaia/shared/test/unit/mocks/mock_custom_event.js
Executable file
|
|
@ -0,0 +1,26 @@
|
|||
'use strict';
|
||||
|
||||
(function(exports) {
|
||||
var MockCustomEvent = function(type, eventInitDict) {
|
||||
this.type = type;
|
||||
if (typeof eventInitDict === 'object') {
|
||||
this.bubbles = eventInitDict.bubbles;
|
||||
this.cancelable = eventInitDict.cancelable;
|
||||
this.detail = eventInitDict.detail;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
MockCustomEvent.prototype = {
|
||||
initCustomEvent:
|
||||
function mce_initCustomEvent(type, canBubble, cancelable, detail) {
|
||||
this.type = type;
|
||||
this.bubbles = canBubble;
|
||||
this.cancelable = cancelable;
|
||||
this.detail = detail;
|
||||
}
|
||||
};
|
||||
|
||||
exports.MockCustomEvent = MockCustomEvent;
|
||||
}(window));
|
||||
30
gaia/shared/test/unit/mocks/mock_default_activity_helper.js
Executable file
30
gaia/shared/test/unit/mocks/mock_default_activity_helper.js
Executable file
|
|
@ -0,0 +1,30 @@
|
|||
'use strict';
|
||||
|
||||
window.MockDefaultActivityHelper = {
|
||||
|
||||
getDefaultConfig: function(name, type) {
|
||||
if (name === 'testactivity' && type === 'testtype') {
|
||||
return {
|
||||
name: 'testactivity',
|
||||
type: ['testtype']
|
||||
};
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
|
||||
getDefaultAction: function(name, type) {
|
||||
if (name === 'testactivity' && type === 'testtype') {
|
||||
return {
|
||||
'aa': 'kk'
|
||||
};
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
|
||||
setDefaultAction: function(name, type, choice) {
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
85
gaia/shared/test/unit/mocks/mock_device_storage.js
Executable file
85
gaia/shared/test/unit/mocks/mock_device_storage.js
Executable file
|
|
@ -0,0 +1,85 @@
|
|||
'use strict';
|
||||
|
||||
function MockDeviceStorage() {
|
||||
MockDeviceStorage.instances.push(this);
|
||||
|
||||
this.entries = [
|
||||
{name: 'mock1'},
|
||||
{name: 'mock2'},
|
||||
{name: 'mock3'},
|
||||
{name: 'mock4'}
|
||||
];
|
||||
|
||||
this.cursors = [];
|
||||
}
|
||||
|
||||
MockDeviceStorage.mSetup = function() {
|
||||
this.realGetDeviceStorage = navigator.getDeviceStorage;
|
||||
navigator.getDeviceStorage = function() {
|
||||
return new MockDeviceStorage();
|
||||
};
|
||||
|
||||
MockDeviceStorage.instances = [];
|
||||
};
|
||||
|
||||
MockDeviceStorage.mTeardown = function() {
|
||||
navigator.getDeviceStorage = this.realGetDeviceStorage;
|
||||
MockDeviceStorage.instances = [];
|
||||
};
|
||||
|
||||
MockDeviceStorage.prototype.enumerate = function() {
|
||||
var storage = this;
|
||||
|
||||
var req = {
|
||||
onsuccess: null,
|
||||
onerror: null
|
||||
};
|
||||
|
||||
var cursor = {
|
||||
index: -1,
|
||||
|
||||
done: false,
|
||||
|
||||
continue: function() {
|
||||
this.index += 1;
|
||||
|
||||
if (this.index < storage.entries.length) {
|
||||
this.result = storage.entries[this.index];
|
||||
} else {
|
||||
this.result = null;
|
||||
this.done = true;
|
||||
}
|
||||
|
||||
setTimeout(function() {
|
||||
if (req.onsuccess) {
|
||||
req.onsuccess.call(cursor);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
result: null
|
||||
};
|
||||
|
||||
this.cursors.push(cursor);
|
||||
cursor.continue();
|
||||
return req;
|
||||
};
|
||||
|
||||
MockDeviceStorage.prototype.delete = function(name) {
|
||||
for (var i = 0; i < this.entries.length; i++) {
|
||||
if (this.entries[i] && this.entries[i].name === name) {
|
||||
this.entries.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i > this.entries.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (var j = 0; j < this.cursors.length; j++) {
|
||||
if (this.cursors[j].index >= i) {
|
||||
this.cursors[j].index -= 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
149
gaia/shared/test/unit/mocks/mock_dom_request.js
Executable file
149
gaia/shared/test/unit/mocks/mock_dom_request.js
Executable file
|
|
@ -0,0 +1,149 @@
|
|||
'use strict';
|
||||
|
||||
/* global MockEventTarget */
|
||||
|
||||
(function(exports) {
|
||||
/**
|
||||
* This is an reimplementation of DOMRequest in JavaScript,
|
||||
* usable as a mock for tests.
|
||||
*
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/API/DOMRequest
|
||||
* and http://dxr.mozilla.org/mozilla-central/source/dom/base/DOMRequest.h
|
||||
* for the simulated real APIs.
|
||||
*
|
||||
* There are two additional methods (fireSuccess() and fireError()) for
|
||||
* explicitly invoking success/error in test script.
|
||||
*
|
||||
* @class MockDOMRequest
|
||||
* @requires MockEventTarget
|
||||
*
|
||||
*/
|
||||
var MockDOMRequest = function MockDOMRequest() {
|
||||
this._promise = null;
|
||||
};
|
||||
|
||||
MockDOMRequest.prototype = new MockEventTarget();
|
||||
|
||||
/**
|
||||
* The operation's result.
|
||||
* @memberof MockDOMRequest.prototype
|
||||
* @type {Mixed}
|
||||
*/
|
||||
MockDOMRequest.prototype.result = undefined;
|
||||
|
||||
/**
|
||||
* Error information, if any.
|
||||
* @type {Mixed}
|
||||
*/
|
||||
MockDOMRequest.prototype.error = undefined;
|
||||
|
||||
/**
|
||||
* A callback handler called when the operation represented by the
|
||||
* DOMRequest is completed.
|
||||
* @memberof MockDOMRequest.prototype
|
||||
* @type {Function}
|
||||
*/
|
||||
MockDOMRequest.prototype.onsuccess = null;
|
||||
|
||||
/**
|
||||
* A callback handler that gets called when an error occurs while processing
|
||||
* the operation.
|
||||
* @memberof MockDOMRequest.prototype
|
||||
* @type {Function}
|
||||
*/
|
||||
MockDOMRequest.prototype.onerror = null;
|
||||
|
||||
/**
|
||||
* A string indicating whether or not the operation is finished running.
|
||||
* Its value is either "done" or "pending".
|
||||
* @memberof MockDOMRequest.prototype
|
||||
* @type {String}
|
||||
*/
|
||||
MockDOMRequest.prototype.readyState = 'pending';
|
||||
|
||||
/**
|
||||
* Fire success event with result given.
|
||||
* @memberof MockDOMRequest.prototype
|
||||
* @param {Mixed} result The result.
|
||||
*/
|
||||
MockDOMRequest.prototype.fireSuccess = function(result) {
|
||||
if (this.readyState === 'done') {
|
||||
throw 'The DOMRequest instance has already fired.';
|
||||
}
|
||||
this.readyState = 'done';
|
||||
this.result = result;
|
||||
|
||||
// Fake event that only implements two properties.
|
||||
// I am not interested in writing MockDOMEvent :-/
|
||||
var evt = {
|
||||
type: 'success'
|
||||
};
|
||||
|
||||
this.dispatchEvent(evt);
|
||||
|
||||
// Remove callbacks since we will never file them again.
|
||||
this._captureCallbacks = [];
|
||||
this._bubbleCallbacks = [];
|
||||
|
||||
this._getInternalPromise().resolve(result);
|
||||
};
|
||||
|
||||
/**
|
||||
* Fire error event with error given.
|
||||
* @memberof MockDOMRequest.prototype
|
||||
* @param {Mixed} error The error.
|
||||
*/
|
||||
MockDOMRequest.prototype.fireError = function(error) {
|
||||
if (this.readyState === 'done') {
|
||||
throw 'The DOMRequest instance has already fired.';
|
||||
}
|
||||
this.readyState = 'done';
|
||||
this.error = error;
|
||||
|
||||
// Fake event that only implements two properties.
|
||||
// I am not interested in writing MockDOMEvent :-/
|
||||
var evt = {
|
||||
type: 'error'
|
||||
};
|
||||
|
||||
this.dispatchEvent(evt);
|
||||
|
||||
// Remove callbacks since we will never file them again.
|
||||
this._captureCallbacks = [];
|
||||
this._bubbleCallbacks = [];
|
||||
|
||||
this._getInternalPromise().reject(error);
|
||||
};
|
||||
|
||||
/**
|
||||
* The then-able interface of DOMRequest. See bug 839838 for real impl.
|
||||
* @returns {Mixed} A Promise instance returned by the then() method.
|
||||
*/
|
||||
MockDOMRequest.prototype.then = function(fulfillCallback, rejectCallback) {
|
||||
return this._getInternalPromise().then(fulfillCallback, rejectCallback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the internal promise instance. Internal only.
|
||||
* Create the instance when being required for the first time.
|
||||
* @returns {Mixed} A Promise instance.
|
||||
*/
|
||||
MockDOMRequest.prototype._getInternalPromise = function() {
|
||||
if (this._promise) {
|
||||
return this._promise;
|
||||
}
|
||||
|
||||
var oResolve, oReject;
|
||||
var p = this._promise = new Promise(function(resolve, reject) {
|
||||
oResolve = resolve;
|
||||
oReject = reject;
|
||||
});
|
||||
|
||||
p.resolve = oResolve;
|
||||
p.reject = oReject;
|
||||
|
||||
return p;
|
||||
};
|
||||
|
||||
exports.MockDOMRequest = MockDOMRequest;
|
||||
}(window));
|
||||
56
gaia/shared/test/unit/mocks/mock_download.js
Executable file
56
gaia/shared/test/unit/mocks/mock_download.js
Executable file
|
|
@ -0,0 +1,56 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var DEFAULT_PARAMS = {
|
||||
id: '0',
|
||||
totalBytes: 1800,
|
||||
currentBytes: 100,
|
||||
url: 'http://firefoxos.com/archivo.mp3',
|
||||
path: '//SDCARD/Downloads/archivo.mp3',
|
||||
state: 'downloading',
|
||||
contentType: 'audio/mpeg',
|
||||
startTime: new Date(),
|
||||
error: null
|
||||
};
|
||||
|
||||
function MockDownload(params) {
|
||||
params = params || {};
|
||||
|
||||
this.id = params.id || '0';
|
||||
this.totalBytes = params.totalBytes || DEFAULT_PARAMS.totalBytes;
|
||||
this.currentBytes = params.currentBytes || DEFAULT_PARAMS.currentBytes;
|
||||
this.url = params.url || DEFAULT_PARAMS.url;
|
||||
this.path = params.path || DEFAULT_PARAMS.path;
|
||||
this.state = params.state || DEFAULT_PARAMS.state;
|
||||
this.contentType = params.contentType || DEFAULT_PARAMS.contentType;
|
||||
this.startTime = params.startTime || DEFAULT_PARAMS.startTime;
|
||||
this.error = params.error || DEFAULT_PARAMS.error;
|
||||
|
||||
this.listeners = [];
|
||||
}
|
||||
|
||||
MockDownload.prototype = {
|
||||
addEventListener: function(type, listener) {
|
||||
if(this.listeners.indexOf(listener) == -1) {
|
||||
this.listeners.push(listener);
|
||||
}
|
||||
},
|
||||
|
||||
removeEventListener: function(type, listener) {
|
||||
var index = this.listeners.indexOf(listener);
|
||||
if (index > -1) {
|
||||
this.listeners.splice(index, 1);
|
||||
}
|
||||
},
|
||||
|
||||
pause: function() {
|
||||
return {
|
||||
then: function(success, error) { setTimeout(success, 0); }
|
||||
};
|
||||
},
|
||||
resume: function() {
|
||||
return {
|
||||
then: function(success, error) { setTimeout(success, 0); }
|
||||
};
|
||||
}
|
||||
};
|
||||
26
gaia/shared/test/unit/mocks/mock_download_formatter.js
Executable file
26
gaia/shared/test/unit/mocks/mock_download_formatter.js
Executable file
|
|
@ -0,0 +1,26 @@
|
|||
'use strict';
|
||||
/* exported MockDownloadFormatter */
|
||||
|
||||
var MockDownloadFormatter = {
|
||||
getFormattedSize: function(bytes) {
|
||||
return Promise.resolve('45 MB');
|
||||
},
|
||||
getPercentage: function(download) {
|
||||
return 10;
|
||||
},
|
||||
getFileName: function(download) {
|
||||
return 'file.mp3';
|
||||
},
|
||||
getTotalSize: function(download) {
|
||||
return Promise.resolve('12 MB');
|
||||
},
|
||||
getDownloadedSize: function(download) {
|
||||
return Promise.resolve('2 MB');
|
||||
},
|
||||
getDate: function(download, callback) {
|
||||
callback && callback('Just now');
|
||||
},
|
||||
getUUID: function(download) {
|
||||
return download.id;
|
||||
}
|
||||
};
|
||||
25
gaia/shared/test/unit/mocks/mock_download_helper.js
Executable file
25
gaia/shared/test/unit/mocks/mock_download_helper.js
Executable file
|
|
@ -0,0 +1,25 @@
|
|||
'use strict';
|
||||
/* exported MockDownloadHelper */
|
||||
|
||||
var MockDownloadHelper = {
|
||||
open: function() {
|
||||
return {
|
||||
set onsuccess(s) { setTimeout(function() {
|
||||
s();
|
||||
}, 100); },
|
||||
set onerror(e) {}
|
||||
};
|
||||
},
|
||||
remove: function() {
|
||||
return {
|
||||
set onsuccess(s) { s(); },
|
||||
set onerror(e) {}
|
||||
};
|
||||
},
|
||||
handlerError: function(error, download, cb) {
|
||||
|
||||
},
|
||||
showRemoveFileUI: function(download, cb) {
|
||||
|
||||
}
|
||||
};
|
||||
34
gaia/shared/test/unit/mocks/mock_dump.js
Executable file
34
gaia/shared/test/unit/mocks/mock_dump.js
Executable file
|
|
@ -0,0 +1,34 @@
|
|||
'use strict';
|
||||
|
||||
var MockDump = (function() {
|
||||
var dump_off = function() {};
|
||||
var dump_on = function(msg, optionalObject) {
|
||||
var output = msg;
|
||||
if (optionalObject) {
|
||||
output += JSON.stringify(optionalObject);
|
||||
}
|
||||
console.log('[MockDUMP] ' + output);
|
||||
};
|
||||
|
||||
return {
|
||||
enable: function() {
|
||||
return dump_on;
|
||||
},
|
||||
disable: function() {
|
||||
return dump_off;
|
||||
}
|
||||
};
|
||||
}());
|
||||
|
||||
MockDump.disable();
|
||||
|
||||
var realDUMP = null;
|
||||
|
||||
MockDump.mSuiteSetup = function() {
|
||||
realDUMP = window.DUMP;
|
||||
window.DUMP = MockDump.disable();
|
||||
};
|
||||
|
||||
MockDump.mSuiteTeardown = function() {
|
||||
window.DUMP = realDUMP;
|
||||
};
|
||||
15
gaia/shared/test/unit/mocks/mock_enumerate_all.js
Executable file
15
gaia/shared/test/unit/mocks/mock_enumerate_all.js
Executable file
|
|
@ -0,0 +1,15 @@
|
|||
'use strict';
|
||||
|
||||
var MockEnumerateAll = function(storages, dir, options) {
|
||||
return {
|
||||
result: {
|
||||
name: MockEnumerateAll.certificateName
|
||||
},
|
||||
set onsuccess(callback) {
|
||||
callback();
|
||||
},
|
||||
continue: function() {}
|
||||
};
|
||||
};
|
||||
|
||||
MockEnumerateAll.certificateName = 'filename';
|
||||
120
gaia/shared/test/unit/mocks/mock_event_target.js
Executable file
120
gaia/shared/test/unit/mocks/mock_event_target.js
Executable file
|
|
@ -0,0 +1,120 @@
|
|||
'use strict';
|
||||
|
||||
(function(exports) {
|
||||
/**
|
||||
* This is an reimplementation of EventTarget in JavaScript,
|
||||
* usable as a mock for tests, and creating interfaces that inherits
|
||||
* from MockEventTarget.
|
||||
*
|
||||
* @class MockEventTarget
|
||||
*/
|
||||
var MockEventTarget = function MockEventTarget() {
|
||||
};
|
||||
|
||||
/**
|
||||
* Adding an event listener for the success/error event.
|
||||
* @memberof MockEventTarget.prototype
|
||||
* @param {String} type Event type, success or error.
|
||||
* @param {Function|Object} handler Event handler.
|
||||
* @param {Boolean} capture True if use capture mode.
|
||||
*/
|
||||
MockEventTarget.prototype.addEventListener =
|
||||
function(type, handler, capture) {
|
||||
if (typeof handler !== 'function' && handler &&
|
||||
typeof handler.handleEvent !== 'function') {
|
||||
return;
|
||||
}
|
||||
|
||||
var eventCallbacks;
|
||||
if (capture) {
|
||||
eventCallbacks = this._captureCallbacks = this._captureCallbacks || {};
|
||||
} else {
|
||||
eventCallbacks = this._bubbleCallbacks = this._bubbleCallbacks || {};
|
||||
}
|
||||
|
||||
eventCallbacks[type] = eventCallbacks[type] || [];
|
||||
// the same handler should not be added twice.
|
||||
if (eventCallbacks[type].indexOf(handler) !== -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
eventCallbacks[type].push(handler);
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove an event listener for the success/error event.
|
||||
* @memberof MockEventTarget.prototype
|
||||
* @param {String} type Event type, success or error.
|
||||
* @param {Function|Object} handler Event handler.
|
||||
* @param {Boolean} capture True if use capture mode.
|
||||
*/
|
||||
MockEventTarget.prototype.removeEventListener = function(type, handler,
|
||||
capture) {
|
||||
if (typeof handler !== 'function' && handler &&
|
||||
typeof handler.handleEvent !== 'function') {
|
||||
return;
|
||||
}
|
||||
|
||||
var eventCallbacks;
|
||||
if (capture) {
|
||||
eventCallbacks = this._captureCallbacks = this._captureCallbacks || {};
|
||||
} else {
|
||||
eventCallbacks = this._bubbleCallbacks = this._bubbleCallbacks || {};
|
||||
}
|
||||
|
||||
var callbacks = eventCallbacks[type] || [];
|
||||
var index = callbacks.indexOf(handler);
|
||||
|
||||
if (index === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
callbacks.splice(index, 1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Dispatch event.
|
||||
* @memberof MockEventTarget.prototype
|
||||
* @param {object} event Mocked event to dispatch (`type` is required).
|
||||
*/
|
||||
MockEventTarget.prototype.dispatchEvent = function(evt) {
|
||||
var type = evt.type;
|
||||
|
||||
this._captureCallbacks = this._captureCallbacks || {};
|
||||
this._bubbleCallbacks = this._bubbleCallbacks || {};
|
||||
|
||||
var captureCallbacks = this._captureCallbacks[type] || [];
|
||||
var bubbleCallbacks = this._bubbleCallbacks[type] || [];
|
||||
|
||||
// Don't overwrite evt.target if it is assigned already.
|
||||
// Sometimes we want to simulate event bubbling/capturing in the DOM tree
|
||||
// even though this is not how this mock behaves.
|
||||
if (!evt.target) {
|
||||
evt.target = this;
|
||||
}
|
||||
evt.currentTarget = this;
|
||||
|
||||
captureCallbacks.forEach(function fireCaptureEvents(handler) {
|
||||
if (typeof handler === 'function') {
|
||||
handler.call(this, evt);
|
||||
} else {
|
||||
handler.handleEvent(evt);
|
||||
}
|
||||
}, this);
|
||||
|
||||
if (('on' + evt.type) in this &&
|
||||
typeof this['on' + evt.type] === 'function') {
|
||||
this['on' + evt.type](evt);
|
||||
}
|
||||
|
||||
bubbleCallbacks.forEach(function fireCaptureEvents(handler) {
|
||||
if (typeof handler === 'function') {
|
||||
handler.call(this, evt);
|
||||
} else {
|
||||
handler.handleEvent(evt);
|
||||
}
|
||||
}, this);
|
||||
};
|
||||
|
||||
exports.MockEventTarget = MockEventTarget;
|
||||
}(window));
|
||||
52
gaia/shared/test/unit/mocks/mock_fb_data_reader.js
Executable file
52
gaia/shared/test/unit/mocks/mock_fb_data_reader.js
Executable file
|
|
@ -0,0 +1,52 @@
|
|||
'use strict';
|
||||
/* exported MockFbContacts */
|
||||
|
||||
var MockFbContactsObj = function(result, inError) {
|
||||
this.mResult = result;
|
||||
this.inError = inError;
|
||||
};
|
||||
|
||||
|
||||
MockFbContactsObj.prototype = {
|
||||
_getRequest: function() {
|
||||
if (this.inError === true) {
|
||||
return {
|
||||
error: {
|
||||
name: 'UnknownError'
|
||||
},
|
||||
set onerror(cb) {
|
||||
window.setTimeout(function() {
|
||||
cb({
|
||||
target: this
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
return {
|
||||
result: this.mResult,
|
||||
set onsuccess(cb) {
|
||||
cb();
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
search: function(by, number) {
|
||||
return this._getRequest();
|
||||
},
|
||||
|
||||
get: function(uid) {
|
||||
return this._getRequest();
|
||||
},
|
||||
|
||||
getByPhone: function(number) {
|
||||
return this._getRequest();
|
||||
},
|
||||
|
||||
mTeardown: function() {
|
||||
this.mResult = [];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var MockFbContacts = new MockFbContactsObj();
|
||||
20
gaia/shared/test/unit/mocks/mock_fb_reader_utils.js
Executable file
20
gaia/shared/test/unit/mocks/mock_fb_reader_utils.js
Executable file
|
|
@ -0,0 +1,20 @@
|
|||
'use strict';
|
||||
/* exported MockFbReaderUtilsObj */
|
||||
|
||||
var MockFbReaderUtilsObj = function() {
|
||||
this.getContactByNumber = function(number, cb, errorCb) {
|
||||
if (this.inError) {
|
||||
errorCb({
|
||||
name: 'Data in error'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (number !== this.targetFbNumber) {
|
||||
cb(null);
|
||||
return;
|
||||
}
|
||||
|
||||
cb({ name: [this.fbContactName], isFbContact: true });
|
||||
};
|
||||
};
|
||||
8
gaia/shared/test/unit/mocks/mock_font_size_utils.js
Executable file
8
gaia/shared/test/unit/mocks/mock_font_size_utils.js
Executable file
|
|
@ -0,0 +1,8 @@
|
|||
/* exported MockFontSizeUtils */
|
||||
|
||||
'use strict';
|
||||
|
||||
var MockFontSizeUtils = {
|
||||
getMaxFontSizeInfo: function() {},
|
||||
getOverflowCount: function() {}
|
||||
};
|
||||
68
gaia/shared/test/unit/mocks/mock_geolocation.js
Executable file
68
gaia/shared/test/unit/mocks/mock_geolocation.js
Executable file
|
|
@ -0,0 +1,68 @@
|
|||
/* exported MockGeolocation */
|
||||
|
||||
'use strict';
|
||||
|
||||
var MockGeolocation = {
|
||||
mSetup: function() {
|
||||
this.fakeCoords = {
|
||||
latitude: 37.388590,
|
||||
longitude: -122.061704,
|
||||
accuracy: 5.0
|
||||
};
|
||||
|
||||
this.fakePosition = {
|
||||
timestamp: 1404756850457,
|
||||
coords: this.fakeCoords
|
||||
};
|
||||
|
||||
this.activeWatches = [];
|
||||
|
||||
this.realGetCurrentPosition = navigator.geolocation.getCurrentPosition;
|
||||
navigator.geolocation.getCurrentPosition = (function(onsuccess, onerror) {
|
||||
if (onsuccess) {
|
||||
onsuccess(this.createFakePosition());
|
||||
}
|
||||
}).bind(this);
|
||||
|
||||
this.realWatchPosition = navigator.geolocation.watchPosition;
|
||||
navigator.geolocation.watchPosition = (function(onsuccess, onerror) {
|
||||
var watch = setInterval(function() {
|
||||
if (onsuccess) {
|
||||
onsuccess(this.createFakePosition());
|
||||
}
|
||||
}.bind(this), 4);
|
||||
|
||||
this.activeWatches.push(watch);
|
||||
return watch;
|
||||
}).bind(this);
|
||||
|
||||
this.realClearWatch = navigator.geolocation.clearWatch;
|
||||
navigator.geolocation.clearWatch = (function(watch) {
|
||||
var idx = this.activeWatches.indexOf(watch);
|
||||
|
||||
if (idx >= 0) {
|
||||
this.activeWatches.splice(idx, 1);
|
||||
clearInterval(watch);
|
||||
}
|
||||
}).bind(this);
|
||||
|
||||
this.createFakePosition = function() {
|
||||
this.fakePosition = {
|
||||
timestamp: Date.now(),
|
||||
coords: this.fakeCoords
|
||||
};
|
||||
return this.fakePosition;
|
||||
};
|
||||
},
|
||||
|
||||
mTeardown: function() {
|
||||
for (var i = 0; i < this.activeWatches.length; i++) {
|
||||
clearInterval(this.activeWatches[i]);
|
||||
}
|
||||
|
||||
this.activeWatches = [];
|
||||
navigator.geolocation.getCurrentPosition = this.realGetCurrentPosition;
|
||||
navigator.geolocation.watchPosition = this.realWatchPosition;
|
||||
navigator.geolocation.clearWatch = this.realClearWatch;
|
||||
}
|
||||
};
|
||||
9
gaia/shared/test/unit/mocks/mock_gesture_detector.js
Executable file
9
gaia/shared/test/unit/mocks/mock_gesture_detector.js
Executable file
|
|
@ -0,0 +1,9 @@
|
|||
'use strict';
|
||||
|
||||
var MockGestureDetector = function() {};
|
||||
|
||||
MockGestureDetector.prototype = {
|
||||
startDetecting: function() {},
|
||||
stopDetecting: function() {}
|
||||
};
|
||||
|
||||
80
gaia/shared/test/unit/mocks/mock_icc_helper.js
Executable file
80
gaia/shared/test/unit/mocks/mock_icc_helper.js
Executable file
|
|
@ -0,0 +1,80 @@
|
|||
'use strict';
|
||||
/* exported MockIccHelper */
|
||||
|
||||
var MockIccHelper = {
|
||||
mProps: {'cardState': null, 'iccInfo': {}, 'retryCount': 0},
|
||||
|
||||
mEventListeners: {'cardstatechange': [], 'iccinfochange': []},
|
||||
|
||||
mSetup: function icch_suite_setup() {
|
||||
this.mProps = {
|
||||
'cardState': null,
|
||||
'iccInfo': {},
|
||||
'retryCount': 0
|
||||
};
|
||||
this.mEventListeners = {'cardstatechange': [], 'iccinfochange': []};
|
||||
},
|
||||
|
||||
mTeardown: function icch_teardown() {
|
||||
this.mProps = {};
|
||||
this.mEventListeners = {};
|
||||
},
|
||||
|
||||
mTriggerEventListeners: function icch_triggerEventListeners(type, evt) {
|
||||
if (!this.mEventListeners[type]) {
|
||||
return;
|
||||
}
|
||||
this.mEventListeners[type].forEach(function(callback) {
|
||||
if (typeof callback === 'function') {
|
||||
callback(evt);
|
||||
} else if (typeof callback == 'object' &&
|
||||
typeof callback.handleEvent === 'function') {
|
||||
callback.handleEvent(evt);
|
||||
}
|
||||
});
|
||||
|
||||
if (typeof this['on' + type] === 'function') {
|
||||
this['on' + type](evt);
|
||||
}
|
||||
},
|
||||
|
||||
get cardState() {
|
||||
return this.mProps.cardState;
|
||||
},
|
||||
|
||||
get iccInfo() {
|
||||
return this.mProps.iccInfo;
|
||||
},
|
||||
|
||||
getCardLockRetryCount: function(lockType, onresult) {
|
||||
onresult(this.mProps.retryCount);
|
||||
},
|
||||
|
||||
setProperty: function _setProperty(property, newState) {
|
||||
this.mProps[property] = newState;
|
||||
},
|
||||
|
||||
addEventListener: function icch_addEventListener(type, callback) {
|
||||
if (this.mEventListeners[type]) {
|
||||
this.mEventListeners[type][this.mEventListeners[type].length] = callback;
|
||||
}
|
||||
},
|
||||
|
||||
removeEventListener: function icch_removeEventListener(type, callback) {
|
||||
if (this.mEventListeners[type]) {
|
||||
var idx = this.mEventListeners[type].indexOf(callback);
|
||||
this.mEventListeners[type].splice(idx, 1);
|
||||
}
|
||||
},
|
||||
|
||||
unlockCardLock: function() {
|
||||
var settingsRequest = {
|
||||
result: {},
|
||||
set onsuccess(callback) {
|
||||
callback.call(this);
|
||||
},
|
||||
set onerror(callback) {}
|
||||
};
|
||||
return settingsRequest;
|
||||
}
|
||||
};
|
||||
8
gaia/shared/test/unit/mocks/mock_icc_manager.js
Executable file
8
gaia/shared/test/unit/mocks/mock_icc_manager.js
Executable file
|
|
@ -0,0 +1,8 @@
|
|||
/* exported MockIccManager */
|
||||
'use strict';
|
||||
|
||||
var MockIccManager = {
|
||||
iccIds: [],
|
||||
getIccById: function() {},
|
||||
addEventListener: function() {}
|
||||
};
|
||||
73
gaia/shared/test/unit/mocks/mock_iccmanager.js
Executable file
73
gaia/shared/test/unit/mocks/mock_iccmanager.js
Executable file
|
|
@ -0,0 +1,73 @@
|
|||
'use strict';
|
||||
|
||||
|
||||
|
||||
var MockIccManager = function() {
|
||||
this.iccIds = [];
|
||||
this.adnContacts = [];
|
||||
this.sdnContacts = [];
|
||||
this.isAdnOnError = false;
|
||||
this.isSdnOnError = false;
|
||||
this.async = false;
|
||||
};
|
||||
|
||||
MockIccManager.prototype.getIccById = function(id) {
|
||||
var self = this;
|
||||
return {
|
||||
'iccInfo': {
|
||||
'iccid': id
|
||||
},
|
||||
'readContacts': function(type) {
|
||||
if (type === 'adn') {
|
||||
return new MockReadContactsRequest(self.isAdnOnError, self.adnContacts,
|
||||
self.async);
|
||||
}
|
||||
if (type === 'sdn') {
|
||||
return new MockReadContactsRequest(self.isSdnOnError, self.sdnContacts,
|
||||
self.async);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
function MockReadContactsRequest(willFail, result, async) {
|
||||
this._result = result;
|
||||
this._willFail = willFail;
|
||||
this._async = async;
|
||||
}
|
||||
|
||||
MockReadContactsRequest.prototype = {
|
||||
set onsuccess(successCb) {
|
||||
var self = this;
|
||||
|
||||
if (!this._willFail) {
|
||||
this.result = this._result;
|
||||
if (typeof successCb === 'function') {
|
||||
if (this._async) {
|
||||
setTimeout(function() {
|
||||
successCb({ target: self });
|
||||
});
|
||||
} else {
|
||||
successCb({ target: this });
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
set onerror(errorCb) {
|
||||
var self = this;
|
||||
|
||||
if (this._willFail) {
|
||||
this.error = { name: 'error' };
|
||||
if (typeof errorCb === 'function') {
|
||||
if (this._async) {
|
||||
setTimeout(function() {
|
||||
errorCb(self.error);
|
||||
});
|
||||
} else {
|
||||
errorCb(this.error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
14
gaia/shared/test/unit/mocks/mock_ice_store.js
Executable file
14
gaia/shared/test/unit/mocks/mock_ice_store.js
Executable file
|
|
@ -0,0 +1,14 @@
|
|||
/* globals Promise */
|
||||
/* exported MockICEStore */
|
||||
'use strict';
|
||||
|
||||
var MockICEStore = {
|
||||
setContacts: function mis_setContacts(ids) {
|
||||
MockICEStore.ids = ids;
|
||||
return Promise.resolve(ids);
|
||||
},
|
||||
getContacts: function mis_getContacts() {
|
||||
return Promise.resolve(MockICEStore.ids);
|
||||
},
|
||||
onChange: function() {}
|
||||
};
|
||||
38
gaia/shared/test/unit/mocks/mock_icons_helper.js
Executable file
38
gaia/shared/test/unit/mocks/mock_icons_helper.js
Executable file
|
|
@ -0,0 +1,38 @@
|
|||
'use strict';
|
||||
|
||||
/* exported MockIconsHelper */
|
||||
|
||||
var _defaultIconSize = 0;
|
||||
|
||||
var MockIconsHelper = {
|
||||
set _defaultIconSize(size) {
|
||||
_defaultIconSize = size;
|
||||
},
|
||||
|
||||
getIcon: function(url, placeObject, siteObject) {
|
||||
return new Promise(resolve => {
|
||||
resolve();
|
||||
});
|
||||
},
|
||||
getIconBlob: function(uri, iconTargetSize, placeObj = {}, siteObj = {}) {
|
||||
return Promise.resolve({
|
||||
blob: 'abc',
|
||||
originalUrl: 'http://example.com/icons/16.png',
|
||||
timestamp: Date.now()
|
||||
});
|
||||
},
|
||||
|
||||
setElementIcon: Promise.resolve.bind(Promise),
|
||||
|
||||
getBestIconFromWebManifest: function() {},
|
||||
getBestIconFromMetaTags: function() {},
|
||||
|
||||
fetchIcon: function() {},
|
||||
fetchIconBlob: function() {},
|
||||
|
||||
get defaultIconSize() {
|
||||
return _defaultIconSize;
|
||||
},
|
||||
|
||||
clear: function() {}
|
||||
};
|
||||
34
gaia/shared/test/unit/mocks/mock_image.js
Executable file
34
gaia/shared/test/unit/mocks/mock_image.js
Executable file
|
|
@ -0,0 +1,34 @@
|
|||
'use strict';
|
||||
|
||||
/* exported MockImage */
|
||||
|
||||
var MockImage = function() {
|
||||
this.complete = false;
|
||||
this.onload = null;
|
||||
this.onabort = null;
|
||||
this.onerror = null;
|
||||
|
||||
MockImage.instances.push(this);
|
||||
};
|
||||
|
||||
MockImage.instances = [];
|
||||
|
||||
MockImage.triggerEvent = function(name) {
|
||||
MockImage.instances.forEach(function(aInstance) {
|
||||
aInstance.triggerEvent(name);
|
||||
});
|
||||
};
|
||||
|
||||
MockImage.teardown = function() {
|
||||
MockImage.instances = [];
|
||||
};
|
||||
|
||||
MockImage.prototype.triggerEvent = function(name) {
|
||||
var callback = this[name];
|
||||
|
||||
if (name === 'onload') {
|
||||
this.complete = true;
|
||||
}
|
||||
|
||||
callback && callback();
|
||||
};
|
||||
244
gaia/shared/test/unit/mocks/mock_indexedDB.js
Executable file
244
gaia/shared/test/unit/mocks/mock_indexedDB.js
Executable file
|
|
@ -0,0 +1,244 @@
|
|||
'use strict';
|
||||
/* global sinon */
|
||||
/* exported MockIndexedDB */
|
||||
|
||||
function MockIndexedDB() {
|
||||
var dbs = [];
|
||||
var deletedDbs = [];
|
||||
this.options = {};
|
||||
this.storedDataDbs = {};
|
||||
|
||||
var self = this;
|
||||
|
||||
var nextId = 1;
|
||||
|
||||
Object.defineProperty(this, 'dbs', {
|
||||
get: function() {
|
||||
return dbs;
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(this, 'deletedDbs', {
|
||||
get: function() {
|
||||
return deletedDbs;
|
||||
}
|
||||
});
|
||||
|
||||
var FakeDB = function(name, storedData) {
|
||||
var dummyFunction = function(obj) {
|
||||
return obj;
|
||||
};
|
||||
|
||||
this.receivedData = [];
|
||||
this.receivedDataHash = {};
|
||||
this.deletedData = [];
|
||||
this.storedData = storedData || {};
|
||||
this.options = {};
|
||||
|
||||
var objectStore = {
|
||||
createIndex: dummyFunction
|
||||
};
|
||||
|
||||
this.objectStoreNames = ['fakeObjStore'];
|
||||
this.createObjectStore = dummyFunction.bind(undefined,
|
||||
objectStore);
|
||||
|
||||
this.deleteObjectStore = dummyFunction;
|
||||
this.transaction = sinon.stub();
|
||||
this.objectStore = sinon.stub();
|
||||
this.get = dummyFunction;
|
||||
this.put = dummyFunction;
|
||||
this.delete = dummyFunction;
|
||||
this.openCursor = dummyFunction;
|
||||
this.close = dummyFunction;
|
||||
this.clear = dummyFunction;
|
||||
this.index = dummyFunction;
|
||||
|
||||
this.transaction.returns(this);
|
||||
this.objectStore.returns(this);
|
||||
|
||||
var self = this;
|
||||
|
||||
sinon.stub(this, 'index', function(indexName) {
|
||||
var data = self.storedData;
|
||||
|
||||
if (self._indexedData && self._indexedData.by) {
|
||||
data = self._indexedData.by[indexName] || self.storedData;
|
||||
}
|
||||
return new FakeIndex(indexName, data, self.options);
|
||||
});
|
||||
|
||||
sinon.stub(this, 'close', function() {
|
||||
self.isClosed = true;
|
||||
});
|
||||
|
||||
sinon.stub(this, 'put', function(data) {
|
||||
data.id = data.id || nextId++;
|
||||
self.receivedDataHash[data.id] = data;
|
||||
self.receivedData.push(data);
|
||||
return _getRequest();
|
||||
});
|
||||
|
||||
sinon.stub(this, 'get', function(key) {
|
||||
return _getRequest(self.storedData[key] || self.receivedDataHash[key]);
|
||||
});
|
||||
|
||||
sinon.stub(this, 'openCursor', function() {
|
||||
if (self.options.cursorOpenInError === true) {
|
||||
return _getRequest(null, {
|
||||
isInError: true
|
||||
});
|
||||
}
|
||||
if (Object.keys(self.storedData).length === 0) {
|
||||
return _getRequest(null);
|
||||
}
|
||||
|
||||
var cursor = new FakeCursor(self.storedData);
|
||||
var req = _getRequest(cursor);
|
||||
cursor.request = req;
|
||||
|
||||
return req;
|
||||
});
|
||||
|
||||
sinon.stub(this, 'delete', function(id) {
|
||||
if (Array.isArray(self.options.deleteInError) &&
|
||||
self.options.deleteInError.indexOf(id) !== -1) {
|
||||
return _getRequest(null, {
|
||||
isInError: true
|
||||
});
|
||||
}
|
||||
|
||||
delete self.storedData[id];
|
||||
delete self.receivedDataHash[id];
|
||||
var idx = self.receivedData.findIndex(function(elem) {
|
||||
return elem.id && elem.id === id;
|
||||
});
|
||||
if (idx !== -1) {
|
||||
self.receivedData.splice(idx, 1);
|
||||
}
|
||||
|
||||
self.deletedData.push(id);
|
||||
return _getRequest(true);
|
||||
});
|
||||
|
||||
sinon.stub(this, 'clear', function() {
|
||||
self.storedData = {};
|
||||
self.receivedDataHash = {};
|
||||
self.receivedData = [];
|
||||
|
||||
return _getRequest();
|
||||
});
|
||||
};
|
||||
|
||||
function FakeIndex(indexName, data, options) {
|
||||
this.openCursor = function() {
|
||||
if (options.cursorOpenInError === true) {
|
||||
return _getRequest(null, {
|
||||
isInError: true
|
||||
});
|
||||
}
|
||||
|
||||
if (Object.keys(data).length === 0) {
|
||||
return _getRequest(null);
|
||||
}
|
||||
|
||||
var cursor = new FakeCursor(data);
|
||||
var req = _getRequest(cursor);
|
||||
cursor.request = req;
|
||||
|
||||
return req;
|
||||
};
|
||||
}
|
||||
|
||||
var FakeCursor = function(data) {
|
||||
var _pointer = 0;
|
||||
var keys = Object.keys(data);
|
||||
|
||||
Object.defineProperty(this, 'value', {
|
||||
get: function() {
|
||||
return data[keys[_pointer]];
|
||||
}
|
||||
});
|
||||
|
||||
this.continue = function() {
|
||||
_pointer++;
|
||||
if (_pointer < keys.length) {
|
||||
this.request.done(this);
|
||||
}
|
||||
else {
|
||||
this.request.done(null);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
var openStub = sinon.stub(window.indexedDB, 'open', function(name) {
|
||||
if (Array.isArray(self.options.inErrorDbs) &&
|
||||
self.options.inErrorDbs.indexOf(name) !== -1) {
|
||||
return _getRequest(null, {
|
||||
isInError: true
|
||||
});
|
||||
}
|
||||
|
||||
var db = new FakeDB(name, self.storedDataDbs[name]);
|
||||
dbs.push(db);
|
||||
var outReq = _getRequest(db, {
|
||||
upgradeNeeded: (Array.isArray(self.options.upgradeNeededDbs) &&
|
||||
self.options.upgradeNeededDbs.indexOf(name) !== -1)
|
||||
});
|
||||
|
||||
return outReq;
|
||||
});
|
||||
|
||||
var deleteDatabaseStub = sinon.stub(window.indexedDB, 'deleteDatabase',
|
||||
function(name) {
|
||||
deletedDbs.push(name);
|
||||
return _getRequest(null);
|
||||
});
|
||||
|
||||
function _getRequest(result, opts) {
|
||||
var options = opts || {};
|
||||
|
||||
return {
|
||||
result: result,
|
||||
error: null,
|
||||
set onerror(cb) {
|
||||
if (options.isInError) {
|
||||
this.error = {
|
||||
name: 'DB In Error'
|
||||
};
|
||||
cb({
|
||||
target: this
|
||||
});
|
||||
}
|
||||
},
|
||||
set onsuccess(cb) {
|
||||
this._doneCb = cb;
|
||||
if (!options.isInError) {
|
||||
cb({
|
||||
target: this
|
||||
});
|
||||
}
|
||||
},
|
||||
set onupgradeneeded(cb) {
|
||||
if (options.upgradeNeeded) {
|
||||
cb({
|
||||
target: this
|
||||
});
|
||||
}
|
||||
},
|
||||
done: function(result) {
|
||||
this.result = result;
|
||||
if (typeof this._doneCb === 'function') {
|
||||
this._doneCb({
|
||||
target: this
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
this.mTearDown = () => {
|
||||
openStub.restore();
|
||||
deleteDatabaseStub.restore();
|
||||
};
|
||||
}
|
||||
31
gaia/shared/test/unit/mocks/mock_intl_helper.js
Executable file
31
gaia/shared/test/unit/mocks/mock_intl_helper.js
Executable file
|
|
@ -0,0 +1,31 @@
|
|||
(function(global) {
|
||||
'use strict';
|
||||
/* global mozIntl */
|
||||
|
||||
const helperCache = new Map();
|
||||
|
||||
global.MockIntlHelper = {
|
||||
define: function(name, type, options) {
|
||||
helperCache.set(name, {options, type});
|
||||
},
|
||||
get: function(name) {
|
||||
if (!helperCache.has(name)) {
|
||||
throw new Error('Intl Object with name "' + name + '" is not defined');
|
||||
}
|
||||
var formatter = helperCache.get(name);
|
||||
switch (formatter.type) {
|
||||
case 'number':
|
||||
return Intl.NumberFormat(navigator.languages, formatter.options);
|
||||
case 'datetime':
|
||||
return Intl.DateTimeFormat(navigator.languages, formatter.options);
|
||||
case 'mozdatetime':
|
||||
return mozIntl.DateTimeFormat(navigator.languages, formatter.options);
|
||||
case 'mozduration':
|
||||
return mozIntl.DurationFormat(navigator.languages, formatter.options);
|
||||
}
|
||||
},
|
||||
observe: function() {},
|
||||
unobserve: function() {},
|
||||
};
|
||||
|
||||
}(this));
|
||||
142
gaia/shared/test/unit/mocks/mock_keyboard_helper.js
Executable file
142
gaia/shared/test/unit/mocks/mock_keyboard_helper.js
Executable file
|
|
@ -0,0 +1,142 @@
|
|||
'use strict';
|
||||
|
||||
var MockKeyboardHelper = {
|
||||
fallbackLayouts: {},
|
||||
mKeyboards: [
|
||||
{
|
||||
manifestURL: 'app://keyboard.gaiamobile.org/manifest.webapp',
|
||||
manifest: {
|
||||
name: 'app1',
|
||||
description: 'app1',
|
||||
permissions: {
|
||||
'settings': { 'access': 'readwrite' },
|
||||
'keyboard': {}
|
||||
},
|
||||
role: 'input',
|
||||
launch_path: '/settings.html',
|
||||
inputs: {
|
||||
'en': {
|
||||
'name': 'layout1',
|
||||
'launch_path': '/index.html#layout1',
|
||||
'description': 'layout1',
|
||||
'types': ['url', 'text'],
|
||||
enabled: true,
|
||||
'default': true
|
||||
},
|
||||
'number': {
|
||||
'name': 'layout2',
|
||||
'launch_path': '/index.html#layout2',
|
||||
'description': 'layout2',
|
||||
'types': ['number']
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
manifestURL: 'app://app2.gaiamobile.org/manifest.webapp',
|
||||
manifest: {
|
||||
name: 'app2',
|
||||
description: 'app2',
|
||||
permissions: {
|
||||
'settings': { 'access': 'readwrite' },
|
||||
'input': {}
|
||||
},
|
||||
role: 'input',
|
||||
launch_path: '/settings.html',
|
||||
inputs: {
|
||||
'layout1': {
|
||||
'name': 'layout1',
|
||||
'launch_path': '/index.html#layout1',
|
||||
'description': 'layout1',
|
||||
'types': ['url']
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
manifestURL: 'app://app3.gaiamobile.org/manifest.webapp',
|
||||
manifest: {
|
||||
name: 'app3',
|
||||
description: 'app3',
|
||||
permissions: {
|
||||
'settings': { 'access': 'readwrite' },
|
||||
'keyboard': {}
|
||||
},
|
||||
role: 'input',
|
||||
launch_path: '/settings.html',
|
||||
inputs: {
|
||||
'layout1': {
|
||||
'name': 'layout1',
|
||||
'launch_path': '/index.html#layout1',
|
||||
'description': 'layout1',
|
||||
'types': ['number'],
|
||||
enabled: true,
|
||||
'default': true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
mSetup: function() {
|
||||
this.watchCallback = null;
|
||||
// dirty clone
|
||||
this.keyboards = JSON.parse(JSON.stringify(this.mKeyboards));
|
||||
|
||||
this.layouts = this.keyboards.reduce(function(carry, keyboard) {
|
||||
var inputIds = Object.keys(keyboard.manifest.inputs);
|
||||
var layouts = inputIds.map(function(layoutId) {
|
||||
var inputManifest = keyboard.manifest.inputs[layoutId];
|
||||
return {
|
||||
app: keyboard,
|
||||
manifest: keyboard.manifest,
|
||||
inputManifest: inputManifest,
|
||||
layoutId: layoutId,
|
||||
enabled: inputManifest.enabled,
|
||||
'default': inputManifest['default']
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
return carry.concat(layouts);
|
||||
}, []);
|
||||
},
|
||||
stopWatching: function() {
|
||||
this.watchCallback = null;
|
||||
},
|
||||
getLayouts: function(options, callback) {
|
||||
if (typeof options === 'function') {
|
||||
callback = options;
|
||||
options = {};
|
||||
}
|
||||
callback(this.layouts);
|
||||
},
|
||||
watchLayouts: function(options, callback) {
|
||||
if (typeof options === 'function') {
|
||||
callback = options;
|
||||
options = {};
|
||||
}
|
||||
this.watchCallback = callback;
|
||||
callback(this.layouts, { apps: true, settings: true });
|
||||
},
|
||||
checkDefaults: function() {},
|
||||
setLayoutEnabled: function(manifestURL, layoutId, enabled) {
|
||||
this.layouts.some(function eachLayout(layout) {
|
||||
if (layout.app.manifestURL === manifestURL &&
|
||||
layout.layoutId === layoutId) {
|
||||
layout.enabled = enabled;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
},
|
||||
saveToSettings: function() {
|
||||
if (this.watchCallback) {
|
||||
this.watchCallback(this.layouts, { settings: true });
|
||||
}
|
||||
},
|
||||
isKeyboardType: function() {
|
||||
return true;
|
||||
},
|
||||
changeDefaultLayouts: function() {}
|
||||
};
|
||||
|
||||
MockKeyboardHelper.mSuiteSetup = MockKeyboardHelper.mSetup;
|
||||
139
gaia/shared/test/unit/mocks/mock_l10n.js
Executable file
139
gaia/shared/test/unit/mocks/mock_l10n.js
Executable file
|
|
@ -0,0 +1,139 @@
|
|||
/* globals assert */
|
||||
|
||||
(function(exports) {
|
||||
'use strict';
|
||||
|
||||
exports.MockL10n = {
|
||||
|
||||
readyState: 'complete',
|
||||
|
||||
get: stringify,
|
||||
_stringify: stringify,
|
||||
|
||||
formatValue: function(id, args) {
|
||||
return Promise.resolve(stringify(id, args || ''));
|
||||
},
|
||||
|
||||
translateFragment: function() {},
|
||||
|
||||
// XXX Remove in https://bugzil.la/1020137
|
||||
localize: function(element, id, args) {
|
||||
if (id) {
|
||||
element.setAttribute('data-l10n-id', id);
|
||||
} else {
|
||||
element.removeAttribute('data-l10n-id');
|
||||
element.removeAttribute('data-l10n-args');
|
||||
element.textContent = '';
|
||||
}
|
||||
if (args) {
|
||||
element.setAttribute('data-l10n-args', JSON.stringify(args));
|
||||
} else {
|
||||
element.removeAttribute('data-l10n-args');
|
||||
}
|
||||
element.textContent = id + (args ? JSON.stringify(args) : '');
|
||||
},
|
||||
|
||||
setAttributes: function(element, id, args) {
|
||||
element.setAttribute('data-l10n-id', id);
|
||||
if (args) {
|
||||
element.setAttribute('data-l10n-args', JSON.stringify(args));
|
||||
}
|
||||
},
|
||||
|
||||
getAttributes: function(element) {
|
||||
return {
|
||||
id: element.getAttribute('data-l10n-id'),
|
||||
args: JSON.parse(element.getAttribute('data-l10n-args'))
|
||||
};
|
||||
},
|
||||
|
||||
ready: function(handler) {
|
||||
setTimeout(handler);
|
||||
},
|
||||
|
||||
once: function(handler) {
|
||||
setTimeout(handler);
|
||||
},
|
||||
|
||||
language: {
|
||||
code: 'en-US',
|
||||
direction: 'ltr'
|
||||
},
|
||||
|
||||
qps: {
|
||||
'fr-x-psaccent': {
|
||||
id: 'fr-x-psaccent',
|
||||
name: 'Pseudo English',
|
||||
translate: stringify
|
||||
}
|
||||
},
|
||||
|
||||
DateTimeFormat: function() {
|
||||
// Support navigator.mozL10n.DateTimeFormat() without new the object.
|
||||
if (!this.localeFormat) {
|
||||
var localeFormat = function mockLocaleFormat(time, strFormat) {
|
||||
return '' + time;
|
||||
};
|
||||
return {
|
||||
localeFormat: localeFormat
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Defining methods on the prototype allows to spy on them in tests
|
||||
exports.MockL10n.DateTimeFormat.prototype = {
|
||||
localeFormat: stringify,
|
||||
fromNow: stringify,
|
||||
relativeParts: stringify
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper used to check that an element has been properly localized. This
|
||||
* supports all the patterns described on MDN for localization best
|
||||
* practices:
|
||||
* - If 'expectedL10n' is a string it will check that the node's
|
||||
* 'data-l10n-id' attribute is set and matches that id.
|
||||
* - If 'expectedL10n' is an object then if it as an id and an args field it
|
||||
* will check if the node's 'data-l10n-id' and 'data-l10n-args' fields
|
||||
* match them.
|
||||
* - If 'expectedL10n' is an object with a 'raw' field it will check that the
|
||||
* node doesn't have a 'data-l10n-id' attribute and its 'textContent' field
|
||||
* matches the'raw' field.
|
||||
* - If 'expectedL10n' is an object with am 'html' field it will check that
|
||||
* the node doesn't have a 'data-l10n-id' attribute and its 'innerHTML'
|
||||
* field matches the'html' field.
|
||||
*/
|
||||
exports.l10nAssert = function(node, expectedL10n) {
|
||||
if (typeof expectedL10n === 'string') {
|
||||
assert.isTrue(node.hasAttribute('data-l10n-id'));
|
||||
assert.equal(node.getAttribute('data-l10n-id'), expectedL10n);
|
||||
} else if (expectedL10n.raw) {
|
||||
assert.isFalse(node.hasAttribute('data-l10n-id'));
|
||||
assert.equal(node.textContent, expectedL10n.raw);
|
||||
} else if (expectedL10n.html) {
|
||||
assert.isFalse(node.hasAttribute('data-l10n-id'));
|
||||
assert.equal(node.innerHTML, expectedL10n.html);
|
||||
} else if (expectedL10n.id) {
|
||||
assert.isTrue(node.hasAttribute('data-l10n-id'));
|
||||
assert.equal(node.getAttribute('data-l10n-id'), expectedL10n.id);
|
||||
if (expectedL10n.args) {
|
||||
assert.isTrue(node.hasAttribute('data-l10n-args'));
|
||||
assert.deepEqual(
|
||||
JSON.parse(node.getAttribute('data-l10n-args')),
|
||||
expectedL10n.args
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function stringify() {
|
||||
return Array.prototype.reduce.call(arguments, function(prev, cur) {
|
||||
if (typeof cur === 'object') {
|
||||
cur = JSON.stringify(cur);
|
||||
}
|
||||
return prev + cur;
|
||||
}, '');
|
||||
}
|
||||
|
||||
}(this));
|
||||
91
gaia/shared/test/unit/mocks/mock_l20n.js
Executable file
91
gaia/shared/test/unit/mocks/mock_l20n.js
Executable file
|
|
@ -0,0 +1,91 @@
|
|||
/* globals assert */
|
||||
|
||||
(function(exports) {
|
||||
'use strict';
|
||||
|
||||
exports.MockL10n = {
|
||||
|
||||
_stringify: stringify,
|
||||
|
||||
formatValue: function(id, args) {
|
||||
return Promise.resolve(
|
||||
args ? stringify(id, args) : stringify(id));
|
||||
},
|
||||
|
||||
formatValues: function(...keys) {
|
||||
return Promise.resolve(
|
||||
keys.map(key => stringify(key)));
|
||||
},
|
||||
|
||||
translateFragment: function() {
|
||||
return Promise.resolve();
|
||||
},
|
||||
|
||||
setAttributes: function(element, id, args) {
|
||||
element.setAttribute('data-l10n-id', id);
|
||||
if (args) {
|
||||
element.setAttribute('data-l10n-args', JSON.stringify(args));
|
||||
}
|
||||
},
|
||||
|
||||
getAttributes: function(element) {
|
||||
return {
|
||||
id: element.getAttribute('data-l10n-id'),
|
||||
args: JSON.parse(element.getAttribute('data-l10n-args'))
|
||||
};
|
||||
},
|
||||
|
||||
ready: Promise.resolve(),
|
||||
|
||||
requestLanguages: function() {
|
||||
return Promise.resolve();
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper used to check that an element has been properly localized. This
|
||||
* supports all the patterns described on MDN for localization best
|
||||
* practices:
|
||||
* - If 'expectedL10n' is a string it will check that the node's
|
||||
* 'data-l10n-id' attribute is set and matches that id.
|
||||
* - If 'expectedL10n' is an object then if it as an id and an args field it
|
||||
* will check if the node's 'data-l10n-id' and 'data-l10n-args' fields
|
||||
* match them.
|
||||
* - If 'expectedL10n' is an object with a 'raw' field it will check that the
|
||||
* node doesn't have a 'data-l10n-id' attribute and its 'textContent' field
|
||||
* matches the'raw' field.
|
||||
* - If 'expectedL10n' is an object with am 'html' field it will check that
|
||||
* the node doesn't have a 'data-l10n-id' attribute and its 'innerHTML'
|
||||
* field matches the'html' field.
|
||||
*/
|
||||
exports.l10nAssert = function(node, expectedL10n) {
|
||||
if (typeof expectedL10n === 'string') {
|
||||
assert.isTrue(node.hasAttribute('data-l10n-id'));
|
||||
assert.equal(node.getAttribute('data-l10n-id'), expectedL10n);
|
||||
} else if (expectedL10n.raw) {
|
||||
assert.isFalse(node.hasAttribute('data-l10n-id'));
|
||||
assert.equal(node.textContent, expectedL10n.raw);
|
||||
} else if (expectedL10n.html) {
|
||||
assert.isFalse(node.hasAttribute('data-l10n-id'));
|
||||
assert.equal(node.innerHTML, expectedL10n.html);
|
||||
} else if (expectedL10n.id) {
|
||||
assert.isTrue(node.hasAttribute('data-l10n-id'));
|
||||
assert.equal(node.getAttribute('data-l10n-id'), expectedL10n.id);
|
||||
if (expectedL10n.args) {
|
||||
assert.isTrue(node.hasAttribute('data-l10n-args'));
|
||||
assert.deepEqual(
|
||||
JSON.parse(node.getAttribute('data-l10n-args')),
|
||||
expectedL10n.args
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function stringify(...args) {
|
||||
return args.reduce(
|
||||
(prev, cur) =>
|
||||
prev + (typeof cur === 'object' ? JSON.stringify(cur) : cur), '');
|
||||
}
|
||||
|
||||
}(this));
|
||||
22
gaia/shared/test/unit/mocks/mock_language_list.js
Executable file
22
gaia/shared/test/unit/mocks/mock_language_list.js
Executable file
|
|
@ -0,0 +1,22 @@
|
|||
(function(exports) {
|
||||
'use strict';
|
||||
|
||||
var langs = {
|
||||
'en-US': 'English (US)'
|
||||
};
|
||||
|
||||
exports.MockLanguageList = {
|
||||
_languages: {
|
||||
then: function(callback) {
|
||||
callback(langs);
|
||||
}
|
||||
},
|
||||
get: function(callback) {
|
||||
callback(langs, 'en-US');
|
||||
},
|
||||
wrapBidi: function(lang, name) {
|
||||
return name;
|
||||
}
|
||||
};
|
||||
|
||||
}(this));
|
||||
16
gaia/shared/test/unit/mocks/mock_lazy_loader.js
Executable file
16
gaia/shared/test/unit/mocks/mock_lazy_loader.js
Executable file
|
|
@ -0,0 +1,16 @@
|
|||
'use strict';
|
||||
/* exported MockLazyLoader */
|
||||
|
||||
var MockLazyLoader = {
|
||||
load: function(fileArray, callback) {
|
||||
if (callback) {
|
||||
callback();
|
||||
} else {
|
||||
return Promise.resolve();
|
||||
}
|
||||
},
|
||||
|
||||
getJSON: function(file) {
|
||||
return Promise.resolve({});
|
||||
}
|
||||
};
|
||||
14
gaia/shared/test/unit/mocks/mock_manifest_helper.js
Executable file
14
gaia/shared/test/unit/mocks/mock_manifest_helper.js
Executable file
|
|
@ -0,0 +1,14 @@
|
|||
'use strict';
|
||||
/* exported MockManifestHelper */
|
||||
|
||||
function MockManifestHelper(manifest) {
|
||||
for (var prop in manifest) {
|
||||
this[prop] = manifest[prop];
|
||||
}
|
||||
}
|
||||
|
||||
Object.defineProperty(MockManifestHelper.prototype, 'displayName', {
|
||||
get: function displayName() {
|
||||
return this.short_name || this.name;
|
||||
}
|
||||
});
|
||||
29
gaia/shared/test/unit/mocks/mock_mediadb.js
Executable file
29
gaia/shared/test/unit/mocks/mock_mediadb.js
Executable file
|
|
@ -0,0 +1,29 @@
|
|||
'use strict';
|
||||
/* exported MockMediaDB */
|
||||
|
||||
var MockMediaDB = (function() {
|
||||
|
||||
function MockMediaDB(blob) {
|
||||
this.blob = blob;
|
||||
|
||||
this.OPENING = 'opening'; // this is initializing itself
|
||||
this.UPGRADING = 'upgrading'; // this is upgrading database
|
||||
this.READY = 'ready'; // this is available and ready for use
|
||||
this.NOCARD = 'nocard'; // Unavailable because there is no sd card
|
||||
this.UNMOUNTED = 'unmounted'; // Unavailable because card unmounted
|
||||
this.CLOSED = 'closed'; // Unavailable because closed() was called
|
||||
}
|
||||
|
||||
MockMediaDB.prototype = {
|
||||
getFile: function getFile(filename, callback) {
|
||||
callback(this.blob);
|
||||
},
|
||||
|
||||
updateMetadata: sinon.spy()
|
||||
};
|
||||
|
||||
sinon.spy(MockMediaDB.prototype, 'getFile');
|
||||
|
||||
return MockMediaDB;
|
||||
|
||||
}());
|
||||
20
gaia/shared/test/unit/mocks/mock_mobile_operator.js
Executable file
20
gaia/shared/test/unit/mocks/mock_mobile_operator.js
Executable file
|
|
@ -0,0 +1,20 @@
|
|||
'use strict';
|
||||
/* exported MockMobileOperator */
|
||||
|
||||
var MockMobileOperator = {
|
||||
userFacingInfo: function mmo_userFacingInfo(mobileConnection) {
|
||||
return {
|
||||
'operator': this.mOperator,
|
||||
'carrier': this.mCarrier,
|
||||
'region': this.mRegion
|
||||
};
|
||||
},
|
||||
|
||||
mOperator: '',
|
||||
mCarrier: '',
|
||||
mRegion: '',
|
||||
|
||||
mTeardown: function() {
|
||||
this.mOperator = this.mCarrier = this.mRegion = '';
|
||||
}
|
||||
};
|
||||
157
gaia/shared/test/unit/mocks/mock_mozContacts.js
Executable file
157
gaia/shared/test/unit/mocks/mock_mozContacts.js
Executable file
|
|
@ -0,0 +1,157 @@
|
|||
'use strict';
|
||||
|
||||
var MockMozContacts;
|
||||
|
||||
function MockMozContactsObj(contacts) {
|
||||
this.contacts = contacts;
|
||||
}
|
||||
|
||||
var listeners = {};
|
||||
MockMozContactsObj.prototype = {
|
||||
limit: 20,
|
||||
|
||||
addEventListener: function(evt, handler) {
|
||||
listeners[evt] = handler;
|
||||
},
|
||||
|
||||
removeEventListener: function(evt, handler) {
|
||||
delete listeners[evt];
|
||||
},
|
||||
|
||||
dispatchEvent: function(evt) {
|
||||
listeners[evt.type] && listeners[evt.type](evt);
|
||||
},
|
||||
|
||||
_getRequest: function(options) {
|
||||
var that = this;
|
||||
function Req(options) {
|
||||
var self = this;
|
||||
Object.defineProperty(self, 'onsuccess', { set: function(cb) {
|
||||
if (options.type === 'find') {
|
||||
if (options.data.filterBy &&
|
||||
options.data.filterBy.indexOf('id') !== -1) {
|
||||
for (var i = 0; i < that.contacts.length; i++) {
|
||||
if (options.data.filterValue === that.contacts[i].id) {
|
||||
self.result = [that.contacts[i]];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.result = that.contacts;
|
||||
}
|
||||
} else {
|
||||
self.result = options.data;
|
||||
}
|
||||
cb.call(self, { target: self });
|
||||
}});
|
||||
}
|
||||
return new Req(options);
|
||||
},
|
||||
find: function find(filter) {
|
||||
return this._getRequest({
|
||||
type: 'find',
|
||||
data: filter
|
||||
});
|
||||
},
|
||||
total: 0,
|
||||
set number(n) {
|
||||
this.total = n;
|
||||
},
|
||||
getCount: function() {
|
||||
return this._getRequest({
|
||||
type: 'count',
|
||||
data: MockMozContacts.total
|
||||
});
|
||||
},
|
||||
getAll: function getAll() {
|
||||
return {
|
||||
set onsuccess(callback) {
|
||||
var count = 0;
|
||||
this.continue = function() {
|
||||
count++;
|
||||
var evt = {
|
||||
target: {}
|
||||
};
|
||||
if (count <= MockMozContacts.limit) {
|
||||
evt.target.result = {
|
||||
id: count,
|
||||
givenName: ['givenName ' + count],
|
||||
lastName: ['lastName ' + count]
|
||||
};
|
||||
}
|
||||
callback.call(this, evt);
|
||||
};
|
||||
|
||||
var evt = {
|
||||
target: {
|
||||
result: {
|
||||
id: count,
|
||||
givenName: ['givenName ' + count],
|
||||
lastName: ['lastName ' + count]
|
||||
}
|
||||
}
|
||||
};
|
||||
callback.call(this, evt);
|
||||
},
|
||||
set onerror(callback) {
|
||||
|
||||
}
|
||||
};
|
||||
},
|
||||
save: function save(ct) {
|
||||
ct.id = this.contacts.length;
|
||||
this.contacts.push(ct);
|
||||
return {
|
||||
set onsuccess(callback) {
|
||||
var self = this;
|
||||
setTimeout(function() {
|
||||
callback.call(self);
|
||||
}, 10);
|
||||
},
|
||||
set onerror(callback) {
|
||||
|
||||
}
|
||||
};
|
||||
},
|
||||
getRevision: function() {
|
||||
var req = {
|
||||
result: 'fakeRevision',
|
||||
set onsuccess(callback) {
|
||||
setTimeout(() => {
|
||||
callback.call(this, { target: req });
|
||||
});
|
||||
},
|
||||
set onerror(callback) {
|
||||
}
|
||||
};
|
||||
return req;
|
||||
},
|
||||
|
||||
setContacts: function(contacts) {
|
||||
this.contacts = contacts;
|
||||
},
|
||||
|
||||
remove: function remove(ct) {
|
||||
var contactsIndex = this.contacts.indexOf(ct);
|
||||
if (contactsIndex > -1) {
|
||||
this.contacts.splice(contactsIndex, 1);
|
||||
}
|
||||
|
||||
return {
|
||||
set onsuccess(callback) {
|
||||
var self = this;
|
||||
setTimeout(function() {
|
||||
callback.call(self);
|
||||
}, 0);
|
||||
},
|
||||
set onerror(callback) {
|
||||
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
clear: function clear() {
|
||||
this.contacts.splice(0, this.contacts.length);
|
||||
}
|
||||
};
|
||||
|
||||
MockMozContacts = new MockMozContactsObj([]);
|
||||
49
gaia/shared/test/unit/mocks/mock_moz_activity.js
Executable file
49
gaia/shared/test/unit/mocks/mock_moz_activity.js
Executable file
|
|
@ -0,0 +1,49 @@
|
|||
'use strict';
|
||||
|
||||
/* exported MockMozActivity */
|
||||
|
||||
var MockMozActivity = function(info) {
|
||||
MockMozActivity.calls.push(info);
|
||||
MockMozActivity.instances.push(this);
|
||||
|
||||
if (!info) {
|
||||
return;
|
||||
}
|
||||
|
||||
var name = info.name;
|
||||
var data = info.data;
|
||||
return {
|
||||
set onsuccess(cb) {
|
||||
MockMozActivity.timeouts.push(setTimeout(cb, 50));
|
||||
},
|
||||
set onerror(cb) {
|
||||
MockMozActivity.errorCallback = cb;
|
||||
},
|
||||
name: name,
|
||||
data: data,
|
||||
get result() {
|
||||
return MockMozActivity.successResult;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// create an array to hold any calls to this function to test them
|
||||
MockMozActivity.mSetup = function() {
|
||||
MockMozActivity.calls = [];
|
||||
MockMozActivity.instances = [];
|
||||
MockMozActivity.successResult = null;
|
||||
MockMozActivity.timeouts = [];
|
||||
};
|
||||
|
||||
MockMozActivity.mTriggerOnError = function() {
|
||||
MockMozActivity.errorCallback();
|
||||
};
|
||||
|
||||
// destroy the array so it resets every time
|
||||
MockMozActivity.mTeardown = function() {
|
||||
delete MockMozActivity.calls;
|
||||
delete MockMozActivity.instances;
|
||||
|
||||
MockMozActivity.timeouts.forEach(clearTimeout);
|
||||
MockMozActivity.timeouts = [];
|
||||
};
|
||||
96
gaia/shared/test/unit/mocks/mock_moz_alarms.js
Executable file
96
gaia/shared/test/unit/mocks/mock_moz_alarms.js
Executable file
|
|
@ -0,0 +1,96 @@
|
|||
// modified from the clock app's mock_moz_alarm.js for bug 1034570
|
||||
|
||||
(function(exports) {
|
||||
'use strict';
|
||||
|
||||
var mozAlarmsId = 0;
|
||||
|
||||
function MockOSAlarm(date, respectTimezone, data, callback) {
|
||||
this.date = date || new Date();
|
||||
this.data = data || {};
|
||||
this.callback = callback;
|
||||
this.id = mozAlarmsId++;
|
||||
this.respectTimezone = respectTimezone;
|
||||
this.timeout = setTimeout(function() {
|
||||
if ((typeof this.callback) === 'function') {
|
||||
this.callback({
|
||||
id: this.id,
|
||||
respectTimezone: this.respectTimezone,
|
||||
date: this.date,
|
||||
data: this.data
|
||||
});
|
||||
}
|
||||
}.bind(this), this.date.getTime() - Date.now());
|
||||
}
|
||||
|
||||
function MockMozAlarmRequest(config) {
|
||||
this.init(config || {});
|
||||
}
|
||||
|
||||
MockMozAlarmRequest.prototype = {
|
||||
|
||||
init: function mar_init(config) {
|
||||
setTimeout(function() {
|
||||
this.fire(config.error, config.result);
|
||||
}.bind(this), 0);
|
||||
},
|
||||
|
||||
fire: function mar_call(error, result) {
|
||||
if (!error) {
|
||||
this.result = result;
|
||||
this.onsuccess && this.onsuccess(this);
|
||||
} else {
|
||||
this.error = error;
|
||||
this.onerror && this.onerror(this);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
var messageHandlers = [];
|
||||
navigator.mozSetMessageHandler = function(type, callback) {
|
||||
if (type === 'alarm') {
|
||||
messageHandlers.push(callback);
|
||||
}
|
||||
};
|
||||
|
||||
exports.MockMozAlarms = {
|
||||
alarms: [],
|
||||
|
||||
getAll: function() {
|
||||
return new MockMozAlarmRequest({
|
||||
result: this.alarms
|
||||
});
|
||||
},
|
||||
|
||||
add: function(date, timezone, data) {
|
||||
if (!(timezone === 'ignoreTimezone' ||
|
||||
timezone === 'honorTimezone')) {
|
||||
throw new Error('invalid timezone argument');
|
||||
}
|
||||
var alarm = new MockOSAlarm(date, timezone, data, function(x) {
|
||||
messageHandlers.forEach(function(callback) {
|
||||
callback(x);
|
||||
});
|
||||
this.remove(x.id);
|
||||
}.bind(this));
|
||||
|
||||
this.alarms.push(alarm);
|
||||
return new MockMozAlarmRequest({
|
||||
result: alarm.id
|
||||
});
|
||||
},
|
||||
|
||||
remove: function(id) {
|
||||
for (var i = 0; i < this.alarms.length; i++) {
|
||||
var alarm = this.alarms[i];
|
||||
if (alarm && (alarm.id === id)) {
|
||||
clearTimeout(alarm.timeout);
|
||||
this.alarms.splice(i, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}(this));
|
||||
13
gaia/shared/test/unit/mocks/mock_moz_contact.js
Executable file
13
gaia/shared/test/unit/mocks/mock_moz_contact.js
Executable file
|
|
@ -0,0 +1,13 @@
|
|||
/* exported MockmozContact */
|
||||
|
||||
'use strict';
|
||||
|
||||
var MockmozContact = function(obj) {
|
||||
if (!obj) {
|
||||
return;
|
||||
}
|
||||
var self = this;
|
||||
Object.keys(obj).forEach(function(k) {
|
||||
self[k] = obj[k];
|
||||
});
|
||||
};
|
||||
61
gaia/shared/test/unit/mocks/mock_moz_intl.js
Executable file
61
gaia/shared/test/unit/mocks/mock_moz_intl.js
Executable file
|
|
@ -0,0 +1,61 @@
|
|||
(function(global) {
|
||||
'use strict';
|
||||
|
||||
global.MockMozIntl = {
|
||||
formatList: function(list) {
|
||||
return Promise.resolve(list.join(', '));
|
||||
},
|
||||
DateTimeFormat: function(locales, options) {
|
||||
var formatter = Intl.DateTimeFormat(locales, options);
|
||||
return {
|
||||
// we need this because mozIntl options extend Intl options
|
||||
resolvedOptions() { return options; },
|
||||
format: formatter.format.bind(formatter)
|
||||
};
|
||||
},
|
||||
calendarInfo: function(token) {
|
||||
return Promise.resolve(0);
|
||||
},
|
||||
DurationFormat: function(locales, options) {
|
||||
return Promise.resolve({
|
||||
format: function(input) {
|
||||
return JSON.stringify({ value: input, options: options });
|
||||
}
|
||||
});
|
||||
},
|
||||
RelativeTimeFormat: function(locales, options) {
|
||||
return {
|
||||
format: function(value) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
};
|
||||
},
|
||||
UnitFormat: function(locales, options) {
|
||||
return {
|
||||
format: function(value) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
};
|
||||
},
|
||||
_gaia: {
|
||||
relativePart: function(ms) {
|
||||
return {
|
||||
unit: 'minutes',
|
||||
value: Math.abs(parseInt(ms / 1000 / 60))
|
||||
};
|
||||
},
|
||||
RelativeDate: function(locales, options) {
|
||||
return {
|
||||
format: function(value) {
|
||||
return Promise.resolve('pretty date');
|
||||
},
|
||||
formatElement: function(element, time, maxDiff) {}
|
||||
};
|
||||
},
|
||||
getFormattedUnit(type, style, v) {
|
||||
return Promise.resolve();
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
}(this));
|
||||
13
gaia/shared/test/unit/mocks/mock_moz_ndefrecord.js
Executable file
13
gaia/shared/test/unit/mocks/mock_moz_ndefrecord.js
Executable file
|
|
@ -0,0 +1,13 @@
|
|||
'use strict';
|
||||
|
||||
var MockMozNDEFRecord = function(dict) {
|
||||
this.tnf = dict ? dict.tnf : 'empty';
|
||||
this.type = dict && dict.type;
|
||||
this.id = dict && dict.id;
|
||||
this.payload = dict && dict.payload;
|
||||
};
|
||||
|
||||
MockMozNDEFRecord.tnf = 'empty';
|
||||
MockMozNDEFRecord.type = null;
|
||||
MockMozNDEFRecord.id = null;
|
||||
MockMozNDEFRecord.payload = null;
|
||||
20
gaia/shared/test/unit/mocks/mock_moz_nfc.js
Executable file
20
gaia/shared/test/unit/mocks/mock_moz_nfc.js
Executable file
|
|
@ -0,0 +1,20 @@
|
|||
/* exported MockMozNfc */
|
||||
/* global MockPromise */
|
||||
'use strict';
|
||||
(function(exports) {
|
||||
require('/shared/test/unit/mocks/mock_promise.js');
|
||||
|
||||
var MockMozNfc = {
|
||||
onpeerready: null,
|
||||
notifySendFileStatus: function() {
|
||||
},
|
||||
MockNFCPeer: {
|
||||
isLost: false,
|
||||
sendNDEF: function(records) {
|
||||
return new MockPromise();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
exports.MockMozNfc = MockMozNfc;
|
||||
})(window);
|
||||
9
gaia/shared/test/unit/mocks/mock_moz_phone_number_service.js
Executable file
9
gaia/shared/test/unit/mocks/mock_moz_phone_number_service.js
Executable file
|
|
@ -0,0 +1,9 @@
|
|||
'use strict';
|
||||
/* global SimplePhoneMatcher */
|
||||
/* exported MockPhoneNumberService */
|
||||
|
||||
var MockPhoneNumberService = {
|
||||
normalize: function(number) {
|
||||
return SimplePhoneMatcher.sanitizedNumber(number);
|
||||
}
|
||||
};
|
||||
15
gaia/shared/test/unit/mocks/mock_multi_contact.js
Executable file
15
gaia/shared/test/unit/mocks/mock_multi_contact.js
Executable file
|
|
@ -0,0 +1,15 @@
|
|||
'use strict';
|
||||
|
||||
/* globals Promise */
|
||||
|
||||
var MockMultiContact = {
|
||||
_data: Object.create(null),
|
||||
|
||||
getData: function(entry) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var id = entry.entryData[0].uid;
|
||||
|
||||
resolve(MockMultiContact._data[id]);
|
||||
});
|
||||
}
|
||||
};
|
||||
22
gaia/shared/test/unit/mocks/mock_multi_sim_action_button.js
Executable file
22
gaia/shared/test/unit/mocks/mock_multi_sim_action_button.js
Executable file
|
|
@ -0,0 +1,22 @@
|
|||
/* exported MockMultiSimActionButton */
|
||||
|
||||
'use strict';
|
||||
|
||||
var MockMultiSimActionButtonSingleton = {
|
||||
mIsInitialized: false,
|
||||
performAction: function() {
|
||||
|
||||
},
|
||||
_phoneNumberGetter: null,
|
||||
_click: function() {}
|
||||
};
|
||||
|
||||
var MockMultiSimActionButton =
|
||||
function(button, callCallback, settings, phoneNumberGetter) {
|
||||
MockMultiSimActionButtonSingleton.mIsInitialized = true;
|
||||
MockMultiSimActionButtonSingleton._phoneNumberGetter = phoneNumberGetter;
|
||||
button.addEventListener('click', MockMultiSimActionButtonSingleton._click);
|
||||
|
||||
return MockMultiSimActionButtonSingleton;
|
||||
};
|
||||
|
||||
27
gaia/shared/test/unit/mocks/mock_mutation_observer.js
Executable file
27
gaia/shared/test/unit/mocks/mock_mutation_observer.js
Executable file
|
|
@ -0,0 +1,27 @@
|
|||
'use strict';
|
||||
|
||||
(function(exports) {
|
||||
var id = 0;
|
||||
var MockMutationObserver = function MockMutationObserver(callback) {
|
||||
var o = {
|
||||
id: id++,
|
||||
type: 'MockMutationObserver',
|
||||
|
||||
observe: function(element, config) {},
|
||||
|
||||
disconnect: function() {},
|
||||
|
||||
mTriggerCallback: function(mutations) {
|
||||
callback(mutations);
|
||||
}
|
||||
};
|
||||
|
||||
MockMutationObserver.mLastObserver = o;
|
||||
return o;
|
||||
};
|
||||
MockMutationObserver.mTeardown = function() {
|
||||
this.mLastObserver = null;
|
||||
};
|
||||
|
||||
exports.MockMutationObserver = MockMutationObserver;
|
||||
})(window);
|
||||
221
gaia/shared/test/unit/mocks/mock_navigator_datastore.js
Executable file
221
gaia/shared/test/unit/mocks/mock_navigator_datastore.js
Executable file
|
|
@ -0,0 +1,221 @@
|
|||
'use strict';
|
||||
/* exports MockDatastore, MockDatastoreObj */
|
||||
|
||||
function MockDatastoreObj(name, owner, records) {
|
||||
this.name = name || 'Mock_Datastore';
|
||||
this.owner = owner;
|
||||
this._records = records || Object.create(null);
|
||||
}
|
||||
|
||||
MockDatastoreObj.prototype = {
|
||||
readOnly: false,
|
||||
revisionId: '123456',
|
||||
|
||||
_nextId: 1,
|
||||
_inError: false,
|
||||
_raceCondition: null,
|
||||
_cb: null,
|
||||
|
||||
_clone: function(obj) {
|
||||
var out = null;
|
||||
|
||||
if (obj) {
|
||||
out = JSON.parse(JSON.stringify(obj));
|
||||
}
|
||||
return out;
|
||||
},
|
||||
|
||||
_reject: function(errorName, errorMessage) {
|
||||
return new window.Promise(function(resolve, reject) {
|
||||
reject({
|
||||
name: errorName || 'UnknownError',
|
||||
message: errorMessage
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
get: function() {
|
||||
if (this._inError === true) {
|
||||
return this._reject();
|
||||
}
|
||||
|
||||
var self = this;
|
||||
var funcArgs = arguments;
|
||||
|
||||
return new window.Promise(function(resolve, reject) {
|
||||
var dsIds;
|
||||
var args = [];
|
||||
for (var j = 0; j < funcArgs.length; j++) {
|
||||
args.push(funcArgs[j]);
|
||||
}
|
||||
|
||||
if (args.length === 1) {
|
||||
dsIds = Array.isArray(args[0]) ? args[0] : [args[0]];
|
||||
} else {
|
||||
dsIds = args;
|
||||
}
|
||||
|
||||
var results = [];
|
||||
|
||||
dsIds.forEach(function(aId) {
|
||||
var record = self._clone(self._records[aId]);
|
||||
results.push(record);
|
||||
});
|
||||
|
||||
var out = args.length > 1 ? results : results[0];
|
||||
|
||||
resolve(out);
|
||||
});
|
||||
},
|
||||
|
||||
put: function(obj, dsId, revisionId) {
|
||||
if (this._inError === true) {
|
||||
return this._reject();
|
||||
}
|
||||
|
||||
if (revisionId && this._raceCondition) {
|
||||
return this._reject('ConstraintError', 'RevisionId is not up-to-date');
|
||||
}
|
||||
|
||||
if (dsId === this._nextId) {
|
||||
this._nextId++;
|
||||
}
|
||||
|
||||
this._records[dsId] = this._clone(obj);
|
||||
var self = this;
|
||||
return new window.Promise(function(resolve, reject) {
|
||||
resolve();
|
||||
self._cb && self._cb({
|
||||
operation: 'updated',
|
||||
id: dsId
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
add: function(obj, dsId, revisionId) {
|
||||
if (this._inError === true) {
|
||||
return this._reject();
|
||||
}
|
||||
|
||||
if (revisionId && this._raceCondition) {
|
||||
return this._reject('ConstraintError', 'RevisionId is not up-to-date');
|
||||
}
|
||||
|
||||
var newId = dsId || this._nextId;
|
||||
this._nextId++;
|
||||
if (typeof this._records[newId] !== 'undefined') {
|
||||
return this._reject('ConstraintError');
|
||||
}
|
||||
this._records[newId] = this._clone(obj);
|
||||
var self = this;
|
||||
return new window.Promise(function(resolve, reject) {
|
||||
resolve(newId);
|
||||
self._cb && self._cb({
|
||||
operation: 'added',
|
||||
id: newId
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
remove: function(dsId, revisionId) {
|
||||
if (this._inError === true) {
|
||||
return this._reject();
|
||||
}
|
||||
|
||||
if (revisionId && this._raceCondition) {
|
||||
return this._reject('ConstraintError', 'RevisionId is not up-to-date');
|
||||
}
|
||||
|
||||
delete this._records[dsId];
|
||||
return new window.Promise(function(resolve, reject) {
|
||||
resolve(true);
|
||||
});
|
||||
},
|
||||
|
||||
sync: function(revisionId) {
|
||||
return {
|
||||
next: () => {
|
||||
if (!this._tasks[this._taskCounter]) {
|
||||
this._taskCounter = 0;
|
||||
}
|
||||
|
||||
return Promise.resolve(this._tasks[this._taskCounter++]);
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
_taskCounter: 0,
|
||||
// Please make sure there is always a 'done' task at the end.
|
||||
_tasks: [
|
||||
{
|
||||
operation: 'update',
|
||||
id: 0,
|
||||
data: {}
|
||||
},
|
||||
{
|
||||
operation: 'done',
|
||||
id: 0,
|
||||
data: null
|
||||
}
|
||||
],
|
||||
|
||||
getLength: function() {
|
||||
if (this._inError === true) {
|
||||
return this._reject();
|
||||
}
|
||||
|
||||
var total = Object.keys(this._records).length;
|
||||
return new window.Promise(function(resolve, reject) {
|
||||
resolve(total);
|
||||
});
|
||||
},
|
||||
|
||||
clear: function(revisionId) {
|
||||
if (this._inError === true) {
|
||||
return this._reject();
|
||||
}
|
||||
|
||||
if (revisionId && this._raceCondition) {
|
||||
return this._reject('ConstraintError', 'RevisionId is not up-to-date');
|
||||
}
|
||||
|
||||
this._records = {};
|
||||
this._nextId = 1;
|
||||
|
||||
return new window.Promise(function(resolve, reject) {
|
||||
resolve();
|
||||
});
|
||||
},
|
||||
|
||||
addEventListener: function(type, cb) {
|
||||
if (type === 'change') {
|
||||
this._cb = cb;
|
||||
}
|
||||
},
|
||||
|
||||
removeEventListener: function() {
|
||||
this._cb = null;
|
||||
}
|
||||
};
|
||||
|
||||
var MockDatastore = new MockDatastoreObj();
|
||||
|
||||
var MockNavigatorDatastore = {
|
||||
_datastores: null,
|
||||
|
||||
getDataStores: function() {
|
||||
if (MockNavigatorDatastore._notFound === true) {
|
||||
return new window.Promise(function(resolve, reject) {
|
||||
resolve([]);
|
||||
});
|
||||
}
|
||||
|
||||
return new window.Promise(function(resolve, reject) {
|
||||
if (!MockNavigatorDatastore._datastores) {
|
||||
resolve([MockDatastore]);
|
||||
} else {
|
||||
resolve(MockNavigatorDatastore._datastores);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
9
gaia/shared/test/unit/mocks/mock_navigator_get_feature.js
Executable file
9
gaia/shared/test/unit/mocks/mock_navigator_get_feature.js
Executable file
|
|
@ -0,0 +1,9 @@
|
|||
'use strict';
|
||||
/* global Promise */
|
||||
window.MockNavigatorGetFeature = function(key) {
|
||||
return new Promise((resolve, reject) => {
|
||||
resolve(window.MockNavigatorGetFeature._values[key]);
|
||||
});
|
||||
};
|
||||
|
||||
window.MockNavigatorGetFeature._values = {};
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue