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
27
gaia/apps/verticalhome/test/build/integration/verticalhome_test.js
Executable file
27
gaia/apps/verticalhome/test/build/integration/verticalhome_test.js
Executable file
|
|
@ -0,0 +1,27 @@
|
|||
'use strict';
|
||||
|
||||
/* jshint node: true, mocha: true */
|
||||
/* global suiteSetup */
|
||||
|
||||
var helper = require('helper');
|
||||
|
||||
suite('Verticalhome tests', function() {
|
||||
suiteSetup(helper.cleanupWorkspace);
|
||||
teardown(helper.cleanupWorkspace);
|
||||
|
||||
test('APP=verticalhome make', function(done) {
|
||||
helper.exec('APP=verticalhome make', function(error, stdout, stderr) {
|
||||
helper.checkError(error, stdout, stderr);
|
||||
|
||||
var zipPath = process.cwd() +
|
||||
'/profile/webapps/verticalhome.gaiamobile.org/application.zip';
|
||||
var checkList = ['manifest.webapp'];
|
||||
|
||||
checkList.forEach(function(filePath) {
|
||||
helper.checkFilePathInZip(zipPath, filePath);
|
||||
});
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
19
gaia/apps/verticalhome/test/marionette/.jshintrc
Executable file
19
gaia/apps/verticalhome/test/marionette/.jshintrc
Executable file
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"extends": "../../../../.jshintrc",
|
||||
"predef": [
|
||||
"__dirname",
|
||||
"module",
|
||||
"suite",
|
||||
"test",
|
||||
"setup",
|
||||
"teardown",
|
||||
"suiteSetup",
|
||||
"suiteTeardown",
|
||||
"marionette",
|
||||
"marionetteScriptFinished",
|
||||
"require",
|
||||
"define",
|
||||
"requireApp",
|
||||
"sinon"
|
||||
]
|
||||
}
|
||||
70
gaia/apps/verticalhome/test/marionette/app_appcache_pending_test.js
Executable file
70
gaia/apps/verticalhome/test/marionette/app_appcache_pending_test.js
Executable file
|
|
@ -0,0 +1,70 @@
|
|||
/* global __dirname */
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var AppInstall =
|
||||
require('../../../../apps/system/test/marionette/lib/app_install');
|
||||
var createAppServer = require('./server/parent');
|
||||
|
||||
var iconAppState = require('./lib/icon_app_state');
|
||||
|
||||
marionette('Vertical Home - Hosted app failed icon fetch', function() {
|
||||
var client = marionette.client({
|
||||
profile: require(__dirname + '/client_options.js')
|
||||
});
|
||||
var server;
|
||||
setup(function(done) {
|
||||
var app = __dirname + '/fixtures/appcache';
|
||||
createAppServer(app, client, function(err, _server) {
|
||||
server = _server;
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
var subject;
|
||||
var system;
|
||||
var appInstall;
|
||||
setup(function() {
|
||||
subject = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
appInstall = new AppInstall(client);
|
||||
|
||||
system.waitForFullyLoaded();
|
||||
subject.waitForLaunch();
|
||||
});
|
||||
|
||||
teardown(function(done) {
|
||||
server.close(done);
|
||||
});
|
||||
|
||||
test('shows spinner while downloading', function() {
|
||||
// correctly install the app...
|
||||
client.switchToFrame();
|
||||
|
||||
// ensure appcache path is delayed
|
||||
server.cork(server.manifest.appcache_path);
|
||||
appInstall.install(server.manifestURL);
|
||||
|
||||
// switch back to the homescreen
|
||||
client.switchToFrame();
|
||||
client.switchToFrame(system.getHomescreenIframe());
|
||||
|
||||
var icon = subject.getIcon(server.manifestURL);
|
||||
|
||||
// wait until we see the nice spinner thing
|
||||
client.waitFor(function() {
|
||||
return iconAppState(icon) === 'loading';
|
||||
});
|
||||
|
||||
// let the rest of the app come through
|
||||
server.uncork(server.manifest.appcache_path);
|
||||
// wait until it is no longer loading
|
||||
client.waitFor(function() {
|
||||
return iconAppState(icon) !== 'loading';
|
||||
});
|
||||
|
||||
// ensure the app launches!
|
||||
subject.launchAndSwitchToApp(server.manifestURL);
|
||||
assert.equal(client.title(), 'iwrotethis');
|
||||
});
|
||||
});
|
||||
65
gaia/apps/verticalhome/test/marionette/app_failed_icon_fetch_test.js
Executable file
65
gaia/apps/verticalhome/test/marionette/app_failed_icon_fetch_test.js
Executable file
|
|
@ -0,0 +1,65 @@
|
|||
/* global __dirname */
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var AppInstall =
|
||||
require('../../../../apps/system/test/marionette/lib/app_install');
|
||||
|
||||
var createAppServer = require('./server/parent');
|
||||
var iconSrc = require('./lib/icon_src');
|
||||
|
||||
marionette('Vertical Home - Hosted app failed icon fetch', function() {
|
||||
var client = marionette.client({
|
||||
profile: require(__dirname + '/client_options.js')
|
||||
});
|
||||
var server;
|
||||
setup(function(done) {
|
||||
var app = __dirname + '/fixtures/template_app';
|
||||
createAppServer(app, client, function(err, _server) {
|
||||
server = _server;
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
var subject;
|
||||
var system;
|
||||
var appInstall;
|
||||
setup(function() {
|
||||
subject = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
appInstall = new AppInstall(client);
|
||||
|
||||
system.waitForFullyLoaded();
|
||||
subject.waitForLaunch();
|
||||
});
|
||||
|
||||
teardown(function(done) {
|
||||
server.close(done);
|
||||
});
|
||||
|
||||
test('fallback to default icon', function() {
|
||||
var iconURL = server.manifest.icons['128'];
|
||||
// correctly install the app...
|
||||
client.switchToFrame();
|
||||
|
||||
// ensure the icon fails to download!
|
||||
server.fail(iconURL);
|
||||
appInstall.install(server.manifestURL);
|
||||
|
||||
// switch back to the homescreen
|
||||
client.switchToFrame();
|
||||
client.switchToFrame(system.getHomescreenIframe());
|
||||
|
||||
var icon = subject.getIcon(server.manifestURL);
|
||||
|
||||
// ensure the default icon is shown
|
||||
client.waitFor(function() {
|
||||
var src = iconSrc(icon);
|
||||
return src && src.indexOf('default') !== -1;
|
||||
});
|
||||
|
||||
// ensure the icon can be launched!
|
||||
subject.launchAndSwitchToApp(server.manifestURL);
|
||||
assert.equal(client.title(), 'iwrotethis');
|
||||
});
|
||||
});
|
||||
67
gaia/apps/verticalhome/test/marionette/app_hosted_failed_icon_fetch_test.js
Executable file
67
gaia/apps/verticalhome/test/marionette/app_hosted_failed_icon_fetch_test.js
Executable file
|
|
@ -0,0 +1,67 @@
|
|||
/* global __dirname */
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var AppInstall =
|
||||
require('../../../../apps/system/test/marionette/lib/app_install');
|
||||
var createAppServer = require('./server/parent');
|
||||
|
||||
var iconSrc = require('./lib/icon_src');
|
||||
|
||||
marionette('Vertical Home - Hosted app failed icon fetch', function() {
|
||||
var client = marionette.client({
|
||||
profile: require(__dirname + '/client_options.js')
|
||||
});
|
||||
var server;
|
||||
setup(function(done) {
|
||||
var app = __dirname + '/fixtures/template_app';
|
||||
createAppServer(app, client, function(err, _server) {
|
||||
server = _server;
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
var subject;
|
||||
var system;
|
||||
var appInstall;
|
||||
setup(function() {
|
||||
subject = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
appInstall = new AppInstall(client);
|
||||
|
||||
system.waitForFullyLoaded();
|
||||
subject.waitForLaunch();
|
||||
});
|
||||
|
||||
teardown(function(done) {
|
||||
server.close(done);
|
||||
});
|
||||
|
||||
test('fallback to default icon', function() {
|
||||
var iconURL = server.manifest.icons['128'];
|
||||
// correctly install the app...
|
||||
client.switchToFrame();
|
||||
|
||||
// ensure the icon fails to download!
|
||||
server.fail(iconURL);
|
||||
appInstall.install(server.manifestURL);
|
||||
|
||||
// switch back to the homescreen
|
||||
client.switchToFrame();
|
||||
client.switchToFrame(system.getHomescreenIframe());
|
||||
|
||||
var icon = subject.getIcon(server.manifestURL);
|
||||
|
||||
// ensure the default icon is shown
|
||||
client.waitFor(function() {
|
||||
var src = iconSrc(icon);
|
||||
return src && src.indexOf('default') !== -1;
|
||||
});
|
||||
|
||||
// ensure the icon can be launched!
|
||||
subject.launchAndSwitchToApp(server.manifestURL);
|
||||
assert.equal(client.title(), 'iwrotethis');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
45
gaia/apps/verticalhome/test/marionette/app_hosted_install_test.js
Executable file
45
gaia/apps/verticalhome/test/marionette/app_hosted_install_test.js
Executable file
|
|
@ -0,0 +1,45 @@
|
|||
/* global __dirname */
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var AppInstall =
|
||||
require('../../../../apps/system/test/marionette/lib/app_install');
|
||||
var createAppServer = require('./server/parent');
|
||||
|
||||
marionette('Vertical Home - Hosted App Install', function() {
|
||||
var client = marionette.client({
|
||||
profile: require(__dirname + '/client_options.js')
|
||||
});
|
||||
var server;
|
||||
setup(function(done) {
|
||||
var app = __dirname + '/fixtures/template_app';
|
||||
createAppServer(app, client, function(err, _server) {
|
||||
server = _server;
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
var subject;
|
||||
var system;
|
||||
var appInstall;
|
||||
setup(function() {
|
||||
subject = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
appInstall = new AppInstall(client);
|
||||
|
||||
system.waitForFullyLoaded();
|
||||
subject.waitForLaunch();
|
||||
});
|
||||
|
||||
teardown(function(done) {
|
||||
server.close(done);
|
||||
});
|
||||
|
||||
test('install app', function() {
|
||||
client.switchToFrame();
|
||||
appInstall.install(server.manifestURL);
|
||||
subject.launchAndSwitchToApp(server.manifestURL);
|
||||
assert.equal(client.title(), 'iwrotethis');
|
||||
});
|
||||
});
|
||||
|
||||
93
gaia/apps/verticalhome/test/marionette/app_hosted_use_cached_icon_test.js
Executable file
93
gaia/apps/verticalhome/test/marionette/app_hosted_use_cached_icon_test.js
Executable file
|
|
@ -0,0 +1,93 @@
|
|||
/* global __dirname */
|
||||
'use strict';
|
||||
|
||||
var AppInstall =
|
||||
require('../../../../apps/system/test/marionette/lib/app_install');
|
||||
|
||||
var createAppServer = require('./server/parent');
|
||||
var iconSrc = require('./lib/icon_src');
|
||||
var iconCached = require('./lib/icon_cached');
|
||||
|
||||
marionette('Vertical Home - Hosted app cached icon fetch', function() {
|
||||
var client = marionette.client({
|
||||
profile: require(__dirname + '/client_options.js'),
|
||||
desiredCapabilities: { raisesAccessibilityExceptions: false }
|
||||
});
|
||||
var server;
|
||||
setup(function(done) {
|
||||
var app = __dirname + '/fixtures/template_app';
|
||||
createAppServer(app, client, function(err, _server) {
|
||||
server = _server;
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
var subject;
|
||||
var system;
|
||||
var appInstall;
|
||||
setup(function() {
|
||||
subject = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
appInstall = new AppInstall(client);
|
||||
|
||||
system.waitForFullyLoaded();
|
||||
subject.waitForLaunch();
|
||||
});
|
||||
|
||||
teardown(function(done) {
|
||||
server.close(done);
|
||||
});
|
||||
|
||||
test('fallback to default icon', function() {
|
||||
var iconURL = server.manifest.icons['128'];
|
||||
// correctly install the app...
|
||||
client.switchToFrame();
|
||||
appInstall.install(server.manifestURL);
|
||||
|
||||
// switch back to the homescreen
|
||||
client.switchToFrame();
|
||||
client.switchToFrame(system.getHomescreenIframe());
|
||||
var icon = subject.getIcon(server.manifestURL);
|
||||
|
||||
// ensure it is cached
|
||||
client.waitFor(function() {
|
||||
var src = iconSrc(icon);
|
||||
|
||||
if (!src) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var hasSource = src.indexOf(iconURL) !== -1;
|
||||
var isCached = iconCached(icon);
|
||||
|
||||
return hasSource && isCached;
|
||||
});
|
||||
|
||||
// ensure http falls so we use the cached icon
|
||||
server.fail(iconURL);
|
||||
|
||||
// kill the window
|
||||
subject.restart();
|
||||
icon = subject.getIcon(server.manifestURL);
|
||||
|
||||
// check for the cached icon...
|
||||
client.waitFor(function() {
|
||||
return iconSrc(icon) === 'blobcache';
|
||||
});
|
||||
|
||||
// allow the request to succeed
|
||||
server.unfail(iconURL);
|
||||
|
||||
// trigger the download of a new icon
|
||||
client.executeScript(function() {
|
||||
window.dispatchEvent(new CustomEvent('online'));
|
||||
});
|
||||
|
||||
// now shows the freshly redownloaded icon
|
||||
client.waitFor(function() {
|
||||
var src = iconSrc(icon);
|
||||
return src && src.indexOf(iconURL) !== -1;
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
73
gaia/apps/verticalhome/test/marionette/app_packaged_fail_test.js
Executable file
73
gaia/apps/verticalhome/test/marionette/app_packaged_fail_test.js
Executable file
|
|
@ -0,0 +1,73 @@
|
|||
/* global __dirname */
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var AppInstall =
|
||||
require('../../../../apps/system/test/marionette/lib/app_install');
|
||||
var createAppServer = require('./server/parent');
|
||||
|
||||
var iconAppState = require('./lib/icon_app_state');
|
||||
var launchIcon = require('./lib/launch_icon');
|
||||
|
||||
marionette('Vertical Home - Packaged App Failed Download', function() {
|
||||
var client = marionette.client({
|
||||
profile: require(__dirname + '/client_options.js'),
|
||||
desiredCapabilities: { raisesAccessibilityExceptions: false }
|
||||
});
|
||||
var server;
|
||||
setup(function(done) {
|
||||
var app = __dirname + '/fixtures/template_app';
|
||||
createAppServer(app, client, function(err, _server) {
|
||||
server = _server;
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
var subject;
|
||||
var system;
|
||||
var appInstall;
|
||||
setup(function() {
|
||||
subject = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
appInstall = new AppInstall(client);
|
||||
|
||||
system.waitForFullyLoaded();
|
||||
subject.waitForLaunch();
|
||||
});
|
||||
|
||||
teardown(function(done) {
|
||||
server.close(done);
|
||||
});
|
||||
|
||||
function expectAppState(icon, state) {
|
||||
client.waitFor(function() {
|
||||
var currentState = iconAppState(icon);
|
||||
return currentState === state;
|
||||
});
|
||||
}
|
||||
|
||||
test('failed state then retry and launch', function() {
|
||||
client.switchToFrame();
|
||||
|
||||
server.fail(server.applicationZipUri);
|
||||
appInstall.installPackage(server.packageManifestURL);
|
||||
|
||||
client.switchToFrame(system.getHomescreenIframe());
|
||||
|
||||
var icon = subject.getIcon(server.packageManifestURL);
|
||||
expectAppState(icon, 'error');
|
||||
|
||||
server.unfail(server.applicationZipUri);
|
||||
|
||||
// helps marionette finding the icon: Bug 1046706
|
||||
subject.moveIconToIndex(icon, 0);
|
||||
|
||||
launchIcon(icon);
|
||||
subject.confirmDialog('resume');
|
||||
expectAppState(icon, 'ready');
|
||||
|
||||
subject.launchAndSwitchToApp(server.packageManifestURL);
|
||||
assert.equal(client.title(), 'iwrotethis');
|
||||
});
|
||||
});
|
||||
|
||||
54
gaia/apps/verticalhome/test/marionette/app_packaged_install_test.js
Executable file
54
gaia/apps/verticalhome/test/marionette/app_packaged_install_test.js
Executable file
|
|
@ -0,0 +1,54 @@
|
|||
/* global __dirname */
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var AppInstall =
|
||||
require('../../../../apps/system/test/marionette/lib/app_install');
|
||||
var iconAppState = require('./lib/icon_app_state');
|
||||
var createAppServer = require('./server/parent');
|
||||
|
||||
marionette('Vertical Home - Packaged App Install', function() {
|
||||
var client = marionette.client({
|
||||
profile: require(__dirname + '/client_options.js')
|
||||
});
|
||||
var server;
|
||||
setup(function(done) {
|
||||
var app = __dirname + '/fixtures/template_app';
|
||||
createAppServer(app, client, function(err, _server) {
|
||||
server = _server;
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
var subject;
|
||||
var system;
|
||||
var appInstall;
|
||||
setup(function() {
|
||||
subject = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
appInstall = new AppInstall(client);
|
||||
|
||||
system.waitForFullyLoaded();
|
||||
subject.waitForLaunch();
|
||||
});
|
||||
|
||||
teardown(function(done) {
|
||||
server.close(done);
|
||||
});
|
||||
|
||||
test('install app', function() {
|
||||
client.switchToFrame();
|
||||
appInstall.installPackage(server.packageManifestURL);
|
||||
|
||||
client.switchToFrame(system.getHomescreenIframe());
|
||||
|
||||
var appIcon = subject.getIcon(server.packageManifestURL);
|
||||
// ensure the app is ready
|
||||
client.waitFor(function() {
|
||||
return iconAppState(appIcon) === 'ready';
|
||||
});
|
||||
|
||||
subject.launchAndSwitchToApp(server.packageManifestURL);
|
||||
assert.equal(client.title(), 'iwrotethis');
|
||||
});
|
||||
});
|
||||
67
gaia/apps/verticalhome/test/marionette/app_packaged_pending_test.js
Executable file
67
gaia/apps/verticalhome/test/marionette/app_packaged_pending_test.js
Executable file
|
|
@ -0,0 +1,67 @@
|
|||
/* global __dirname */
|
||||
'use strict';
|
||||
|
||||
var AppInstall =
|
||||
require('../../../../apps/system/test/marionette/lib/app_install');
|
||||
var AppInstall =
|
||||
require('../../../../apps/system/test/marionette/lib/app_install');
|
||||
|
||||
var createAppServer = require('./server/parent');
|
||||
var iconAppState = require('./lib/icon_app_state');
|
||||
|
||||
marionette('Vertical Home - Packaged App Pending', function() {
|
||||
var client = marionette.client({
|
||||
profile: require(__dirname + '/client_options.js')
|
||||
});
|
||||
|
||||
var server;
|
||||
setup(function(done) {
|
||||
var app = __dirname + '/fixtures/template_app';
|
||||
createAppServer(app, client, function(err, _server) {
|
||||
server = _server;
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
var subject;
|
||||
var system;
|
||||
var appInstall;
|
||||
setup(function() {
|
||||
subject = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
appInstall = new AppInstall(client);
|
||||
|
||||
system.waitForFullyLoaded();
|
||||
subject.waitForLaunch();
|
||||
});
|
||||
|
||||
teardown(function(done) {
|
||||
server.close(done);
|
||||
});
|
||||
|
||||
test('app loading spinner', function() {
|
||||
// go to the system app
|
||||
client.switchToFrame();
|
||||
|
||||
// don't let the server send the zip archive
|
||||
server.cork(server.applicationZipUri);
|
||||
appInstall.installPackage(server.packageManifestURL);
|
||||
|
||||
// switch back to the homescreen
|
||||
client.switchToFrame(system.getHomescreenIframe());
|
||||
|
||||
var appIcon = subject.getIcon(server.packageManifestURL);
|
||||
// wait until the icon is spinning!
|
||||
client.waitFor(function() {
|
||||
return iconAppState(appIcon) === 'loading';
|
||||
});
|
||||
|
||||
// let the rest of the app come through
|
||||
server.uncork(server.applicationZipUri);
|
||||
|
||||
// wait until it is no longer loading
|
||||
client.waitFor(function() {
|
||||
return iconAppState(appIcon) !== 'loading';
|
||||
});
|
||||
});
|
||||
});
|
||||
90
gaia/apps/verticalhome/test/marionette/app_packaged_resume_test.js
Executable file
90
gaia/apps/verticalhome/test/marionette/app_packaged_resume_test.js
Executable file
|
|
@ -0,0 +1,90 @@
|
|||
/* global __dirname */
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var AppInstall =
|
||||
require('../../../../apps/system/test/marionette/lib/app_install');
|
||||
var createAppServer = require('./server/parent');
|
||||
|
||||
var iconAppState = require('./lib/icon_app_state');
|
||||
var launchIcon = require('./lib/launch_icon');
|
||||
|
||||
marionette('Vertical Home - Packaged App Resuming Downloads', function() {
|
||||
var client = marionette.client({
|
||||
profile: require(__dirname + '/client_options.js'),
|
||||
desiredCapabilities: { raisesAccessibilityExceptions: false }
|
||||
});
|
||||
|
||||
var server;
|
||||
var subject;
|
||||
var system;
|
||||
var appInstall;
|
||||
setup(function(done) {
|
||||
var app = __dirname + '/fixtures/template_app';
|
||||
createAppServer(app, client, function(err, _server) {
|
||||
server = _server;
|
||||
|
||||
subject = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
appInstall = new AppInstall(client);
|
||||
|
||||
system.waitForFullyLoaded();
|
||||
subject.waitForLaunch();
|
||||
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function(done) {
|
||||
server.close(done);
|
||||
});
|
||||
|
||||
function expectAppState(icon, state) {
|
||||
client.waitFor(function() {
|
||||
var currentState = iconAppState(icon);
|
||||
return currentState === state;
|
||||
});
|
||||
}
|
||||
|
||||
test('failed state then retry and launch', function() {
|
||||
client.switchToFrame();
|
||||
|
||||
server.cork(server.applicationZipUri);
|
||||
appInstall.installPackage(server.packageManifestURL);
|
||||
|
||||
client.switchToFrame(system.getHomescreenIframe());
|
||||
|
||||
// pause the download
|
||||
var icon = subject.getIcon(server.packageManifestURL);
|
||||
// this helps marionette finding the icon: Bug 1046706
|
||||
subject.moveIconToIndex(icon, 0);
|
||||
launchIcon(icon);
|
||||
|
||||
subject.confirmDialog('pause');
|
||||
expectAppState(icon, 'paused');
|
||||
|
||||
// resume the download
|
||||
launchIcon(icon);
|
||||
subject.confirmDialog('resume');
|
||||
expectAppState(icon, 'loading');
|
||||
|
||||
// pause it again!
|
||||
launchIcon(icon);
|
||||
subject.confirmDialog('pause');
|
||||
expectAppState(icon, 'paused');
|
||||
|
||||
// uncork so next resume works...
|
||||
server.uncork(server.applicationZipUri);
|
||||
|
||||
// finally download the entire app
|
||||
launchIcon(icon);
|
||||
subject.confirmDialog('resume');
|
||||
expectAppState(icon, 'ready');
|
||||
|
||||
// now it should work!
|
||||
subject.launchAndSwitchToApp(server.packageManifestURL);
|
||||
assert.equal(client.title(), 'iwrotethis');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
106
gaia/apps/verticalhome/test/marionette/app_packaged_resume_update_test.js
Executable file
106
gaia/apps/verticalhome/test/marionette/app_packaged_resume_update_test.js
Executable file
|
|
@ -0,0 +1,106 @@
|
|||
/* global __dirname */
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var AppInstall =
|
||||
require('../../../../apps/system/test/marionette/lib/app_install');
|
||||
var AppInstall =
|
||||
require('../../../../apps/system/test/marionette/lib/app_install');
|
||||
|
||||
var createAppServer = require('./server/parent');
|
||||
var iconAppState = require('./lib/icon_app_state');
|
||||
var launchIcon = require('./lib/launch_icon');
|
||||
|
||||
marionette('Vertical Home - Packaged App Update', function() {
|
||||
var client = marionette.client({
|
||||
profile: require(__dirname + '/client_options.js'),
|
||||
desiredCapabilities: { raisesAccessibilityExceptions: false }
|
||||
});
|
||||
|
||||
var server;
|
||||
setup(function(done) {
|
||||
var app = __dirname + '/fixtures/template_app';
|
||||
createAppServer(app, client, function(err, _server) {
|
||||
server = _server;
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
var subject;
|
||||
var system;
|
||||
var appInstall;
|
||||
setup(function() {
|
||||
subject = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
appInstall = new AppInstall(client);
|
||||
|
||||
// wait for the system app to be running
|
||||
system.waitForFullyLoaded();
|
||||
subject.waitForLaunch();
|
||||
|
||||
// install the app
|
||||
client.switchToFrame();
|
||||
appInstall.installPackage(server.packageManifestURL);
|
||||
|
||||
// switch to the homescreen
|
||||
client.switchToFrame(system.getHomescreenIframe());
|
||||
});
|
||||
|
||||
teardown(function(done) {
|
||||
server.close(done);
|
||||
});
|
||||
|
||||
function expectAppState(icon, state) {
|
||||
client.waitFor(function() {
|
||||
var currentState = iconAppState(icon);
|
||||
return currentState === state;
|
||||
});
|
||||
}
|
||||
|
||||
test('resume update', function() {
|
||||
var appIcon = subject.getIcon(server.packageManifestURL);
|
||||
|
||||
// helps marionette finding the icon: Bug 1046706
|
||||
subject.moveIconToIndex(appIcon, 0);
|
||||
|
||||
// ensure the app is installed before updating it
|
||||
client.waitFor(function() {
|
||||
return iconAppState(appIcon) === 'ready';
|
||||
});
|
||||
|
||||
// Cork the zip so we can see the loading spinner.
|
||||
server.cork('/app.zip');
|
||||
|
||||
// Update the manifests.
|
||||
server.setRoot(__dirname + '/fixtures/template_app_updated');
|
||||
|
||||
// Ensure we have an update.
|
||||
appInstall.update(server.packageManifestURL);
|
||||
|
||||
// Ensure we see the loading signs...
|
||||
client.waitFor(function() {
|
||||
return iconAppState(appIcon) === 'loading';
|
||||
});
|
||||
|
||||
// pause the update
|
||||
launchIcon(appIcon);
|
||||
subject.confirmDialog('pause');
|
||||
expectAppState(appIcon, 'paused');
|
||||
|
||||
// resume the update
|
||||
launchIcon(appIcon);
|
||||
subject.confirmDialog('resume');
|
||||
expectAppState(appIcon, 'loading');
|
||||
|
||||
// Wait for the download to be complete.
|
||||
server.uncork('/app.zip');
|
||||
client.waitFor(function() {
|
||||
return iconAppState(appIcon) === 'ready';
|
||||
});
|
||||
|
||||
// verify the app was really updated
|
||||
subject.launchAndSwitchToApp(server.packageManifestURL);
|
||||
assert.equal(client.title(), 'updatedwow');
|
||||
});
|
||||
});
|
||||
|
||||
65
gaia/apps/verticalhome/test/marionette/app_packaged_role_hidden_test.js
Executable file
65
gaia/apps/verticalhome/test/marionette/app_packaged_role_hidden_test.js
Executable file
|
|
@ -0,0 +1,65 @@
|
|||
/* global __dirname */
|
||||
'use strict';
|
||||
|
||||
var AppInstall =
|
||||
require('../../../../apps/system/test/marionette/lib/app_install');
|
||||
var AppInstall =
|
||||
require('../../../../apps/system/test/marionette/lib/app_install');
|
||||
|
||||
var createAppServer = require('./server/parent');
|
||||
var iconAppState = require('./lib/icon_app_state');
|
||||
|
||||
marionette('Vertical Home - Packaged App Pending', function() {
|
||||
var client = marionette.client({
|
||||
profile: require(__dirname + '/client_options.js')
|
||||
});
|
||||
|
||||
var server;
|
||||
setup(function(done) {
|
||||
var app = __dirname + '/fixtures/role_homescreen';
|
||||
createAppServer(app, client, function(err, _server) {
|
||||
server = _server;
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
var subject;
|
||||
var system;
|
||||
var appInstall;
|
||||
setup(function() {
|
||||
subject = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
appInstall = new AppInstall(client);
|
||||
|
||||
system.waitForFullyLoaded();
|
||||
subject.waitForLaunch();
|
||||
});
|
||||
|
||||
teardown(function(done) {
|
||||
server.close(done);
|
||||
});
|
||||
|
||||
test('app is displayed until determined role=homescreen', function() {
|
||||
// go to the system app
|
||||
client.switchToFrame();
|
||||
|
||||
// don't let the server send the zip archive
|
||||
server.cork(server.applicationZipUri);
|
||||
appInstall.installPackage(server.packageManifestURL);
|
||||
|
||||
// switch back to the homescreen
|
||||
client.switchToFrame(system.getHomescreenIframe());
|
||||
|
||||
var appIcon = subject.getIcon(server.packageManifestURL);
|
||||
// wait until the icon is spinning!
|
||||
client.waitFor(function() {
|
||||
return iconAppState(appIcon) === 'loading';
|
||||
});
|
||||
|
||||
// let the rest of the app come through
|
||||
server.uncork(server.applicationZipUri);
|
||||
|
||||
// wait until the icon is hidden
|
||||
client.helper.waitForElementToDisappear(appIcon);
|
||||
});
|
||||
});
|
||||
102
gaia/apps/verticalhome/test/marionette/app_packaged_update_test.js
Executable file
102
gaia/apps/verticalhome/test/marionette/app_packaged_update_test.js
Executable file
|
|
@ -0,0 +1,102 @@
|
|||
/* global __dirname */
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var AppInstall =
|
||||
require('../../../../apps/system/test/marionette/lib/app_install');
|
||||
var AppInstall =
|
||||
require('../../../../apps/system/test/marionette/lib/app_install');
|
||||
|
||||
var createAppServer = require('./server/parent');
|
||||
var iconAppState = require('./lib/icon_app_state');
|
||||
var iconSrc = require('./lib/icon_src');
|
||||
|
||||
marionette('Vertical Home - Packaged App Update', function() {
|
||||
var client = marionette.client({
|
||||
profile: require(__dirname + '/client_options.js')
|
||||
});
|
||||
|
||||
var server;
|
||||
setup(function(done) {
|
||||
var app = __dirname + '/fixtures/template_app';
|
||||
createAppServer(app, client, function(err, _server) {
|
||||
server = _server;
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
var subject;
|
||||
var system;
|
||||
var appInstall;
|
||||
setup(function() {
|
||||
subject = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
appInstall = new AppInstall(client);
|
||||
|
||||
// wait for the system app to be running
|
||||
system.waitForFullyLoaded();
|
||||
|
||||
// Launch the homescreen first, then go to the system app.
|
||||
// Make sure we do this before installing an application.
|
||||
subject.waitForLaunch();
|
||||
client.switchToFrame();
|
||||
|
||||
// install the app
|
||||
appInstall.installPackage(server.packageManifestURL);
|
||||
|
||||
// switch to the homescreen
|
||||
client.switchToFrame(system.getHomescreenIframe());
|
||||
});
|
||||
|
||||
teardown(function(done) {
|
||||
server.close(done);
|
||||
});
|
||||
|
||||
test('update an installed app', function() {
|
||||
var appIcon = subject.getIcon(server.packageManifestURL);
|
||||
|
||||
// ensure the app is installed before updating it
|
||||
client.waitFor(function() {
|
||||
return iconAppState(appIcon) === 'ready';
|
||||
});
|
||||
|
||||
var iconTitle = appIcon.findElement('.title').text();
|
||||
|
||||
// Cork the zip so we can see the loading spinner.
|
||||
server.cork('/app.zip');
|
||||
|
||||
// Update the manifests.
|
||||
server.setRoot(__dirname + '/fixtures/template_app_updated');
|
||||
|
||||
// Ensure we have an update.
|
||||
appInstall.update(server.packageManifestURL);
|
||||
|
||||
// Ensure we see the loading signs...
|
||||
client.waitFor(function() {
|
||||
return iconAppState(appIcon) === 'loading';
|
||||
});
|
||||
|
||||
// Wait for the download to be complete.
|
||||
server.uncork('/app.zip');
|
||||
client.waitFor(function() {
|
||||
return iconAppState(appIcon) === 'ready';
|
||||
});
|
||||
|
||||
// See bug 826555 for rationale for the title not changing.
|
||||
assert.equal(
|
||||
appIcon.findElement('.title').text(),
|
||||
iconTitle,
|
||||
'app name should not be updated'
|
||||
);
|
||||
|
||||
// Ensure the icon is updated
|
||||
client.waitFor(function() {
|
||||
var src = iconSrc(appIcon);
|
||||
return src.indexOf(server.manifest.icons[128]) !== -1;
|
||||
});
|
||||
|
||||
// verify the app was really updated
|
||||
subject.launchAndSwitchToApp(server.packageManifestURL);
|
||||
assert.equal(client.title(), 'updatedwow');
|
||||
});
|
||||
});
|
||||
71
gaia/apps/verticalhome/test/marionette/app_pending_update_test.js
Executable file
71
gaia/apps/verticalhome/test/marionette/app_pending_update_test.js
Executable file
|
|
@ -0,0 +1,71 @@
|
|||
/* global __dirname */
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var AppInstall =
|
||||
require('../../../../apps/system/test/marionette/lib/app_install');
|
||||
var AppInstall =
|
||||
require('../../../../apps/system/test/marionette/lib/app_install');
|
||||
|
||||
var createAppServer = require('./server/parent');
|
||||
var iconAppState = require('./lib/icon_app_state');
|
||||
|
||||
marionette('Vertical Home - Packaged App Update', function() {
|
||||
var client = marionette.client({
|
||||
profile: require(__dirname + '/client_options.js')
|
||||
});
|
||||
|
||||
var server;
|
||||
setup(function(done) {
|
||||
var app = __dirname + '/fixtures/template_app';
|
||||
createAppServer(app, client, function(err, _server) {
|
||||
server = _server;
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
var subject;
|
||||
var system;
|
||||
var appInstall;
|
||||
setup(function() {
|
||||
subject = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
appInstall = new AppInstall(client);
|
||||
|
||||
// wait for the system app to be running
|
||||
system.waitForFullyLoaded();
|
||||
client.apps.launch(subject.URL);
|
||||
subject.waitForLaunch();
|
||||
|
||||
// install the app
|
||||
client.switchToFrame();
|
||||
appInstall.installPackage(server.packageManifestURL);
|
||||
|
||||
// switch to the homescreen
|
||||
client.switchToFrame(system.getHomescreenIframe());
|
||||
});
|
||||
|
||||
teardown(function(done) {
|
||||
server.close(done);
|
||||
});
|
||||
|
||||
test('update an installed app', function() {
|
||||
var appIcon = subject.getIcon(server.packageManifestURL);
|
||||
|
||||
// ensure the app is installed before updating it
|
||||
client.waitFor(function() {
|
||||
return iconAppState(appIcon) === 'ready';
|
||||
});
|
||||
|
||||
// Update the manifests.
|
||||
server.setRoot(__dirname + '/fixtures/template_app_updated');
|
||||
|
||||
// Stage the update
|
||||
appInstall.stageUpdate(server.packageManifestURL);
|
||||
|
||||
// ensure we can still launch an app in the older version
|
||||
subject.launchAndSwitchToApp(server.packageManifestURL);
|
||||
assert.equal(client.title(), 'iwrotethis');
|
||||
});
|
||||
});
|
||||
|
||||
128
gaia/apps/verticalhome/test/marionette/app_retry_icon_fetch_test.js
Executable file
128
gaia/apps/verticalhome/test/marionette/app_retry_icon_fetch_test.js
Executable file
|
|
@ -0,0 +1,128 @@
|
|||
/* global __dirname */
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var AppInstall =
|
||||
require('../../../../apps/system/test/marionette/lib/app_install');
|
||||
|
||||
var createAppServer = require('./server/parent');
|
||||
var iconSrc = require('./lib/icon_src');
|
||||
var iconAppState = require('./lib/icon_app_state');
|
||||
var launchIcon = require('./lib/launch_icon');
|
||||
|
||||
marionette('Vertical Home - Hosted app failed icon fetch', function() {
|
||||
var client = marionette.client({
|
||||
profile: require(__dirname + '/client_options.js'),
|
||||
desiredCapabilities: { raisesAccessibilityExceptions: false }
|
||||
});
|
||||
var server;
|
||||
setup(function(done) {
|
||||
var app = __dirname + '/fixtures/template_app';
|
||||
createAppServer(app, client, function(err, _server) {
|
||||
server = _server;
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
var subject;
|
||||
var system;
|
||||
var appInstall;
|
||||
setup(function() {
|
||||
subject = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
appInstall = new AppInstall(client);
|
||||
|
||||
system.waitForFullyLoaded();
|
||||
subject.waitForLaunch();
|
||||
});
|
||||
|
||||
teardown(function(done) {
|
||||
server.close(done);
|
||||
});
|
||||
|
||||
function expectAppState(icon, state) {
|
||||
client.waitFor(function() {
|
||||
var currentState = iconAppState(icon);
|
||||
return currentState === state;
|
||||
});
|
||||
}
|
||||
|
||||
test('shows icon after a restart', function() {
|
||||
// go to the system app
|
||||
client.switchToFrame();
|
||||
|
||||
// don't let the server send the zip archive
|
||||
server.cork(server.applicationZipUri);
|
||||
appInstall.installPackage(server.packageManifestURL);
|
||||
|
||||
// switch back to the homescreen
|
||||
client.switchToFrame(system.getHomescreenIframe());
|
||||
|
||||
var appIcon = subject.getIcon(server.packageManifestURL);
|
||||
expectAppState(appIcon, 'loading');
|
||||
|
||||
// this helps marionette finding the icon: Bug 1046706
|
||||
subject.moveIconToIndex(appIcon, 0);
|
||||
|
||||
// stop the download
|
||||
launchIcon(appIcon);
|
||||
subject.confirmDialog('pause');
|
||||
expectAppState(appIcon, 'paused');
|
||||
|
||||
// Restart the download
|
||||
server.uncork(server.applicationZipUri);
|
||||
|
||||
// resume the download from the ui
|
||||
launchIcon(appIcon);
|
||||
subject.confirmDialog('resume');
|
||||
|
||||
// wait until we are showing our desired icon
|
||||
var iconURL = server.manifest.icons['128'];
|
||||
client.waitFor(function() {
|
||||
appIcon = subject.getIcon(server.packageManifestURL);
|
||||
var src = iconSrc(appIcon);
|
||||
return src && src.indexOf(iconURL) !== -1;
|
||||
});
|
||||
});
|
||||
|
||||
test('fallback to default icon when icon fails', function() {
|
||||
var iconURL = server.manifest.icons['128'];
|
||||
// correctly install the app...
|
||||
client.switchToFrame();
|
||||
|
||||
// ensure the icon fails to download!
|
||||
server.fail(iconURL);
|
||||
appInstall.install(server.manifestURL);
|
||||
|
||||
// switch back to the homescreen
|
||||
client.switchToFrame();
|
||||
client.switchToFrame(system.getHomescreenIframe());
|
||||
|
||||
var icon = subject.getIcon(server.manifestURL);
|
||||
|
||||
// ensure the default icon is shown
|
||||
client.waitFor(function() {
|
||||
var src = iconSrc(icon);
|
||||
return src && src.indexOf('default') !== -1;
|
||||
});
|
||||
|
||||
server.unfail(iconURL);
|
||||
|
||||
// XXX: We don't have real network access but we can sorta emulate it by
|
||||
// failing then switching back to an online state.
|
||||
client.executeScript(function() {
|
||||
window.dispatchEvent(new CustomEvent('online'));
|
||||
});
|
||||
|
||||
// wait until we are showing our desired icon
|
||||
client.waitFor(function() {
|
||||
var src = iconSrc(icon);
|
||||
return src && src.indexOf(iconURL) !== -1;
|
||||
});
|
||||
|
||||
// ensure the icon can be launched!
|
||||
subject.launchAndSwitchToApp(server.manifestURL);
|
||||
assert.equal(client.title(), 'iwrotethis');
|
||||
});
|
||||
});
|
||||
|
||||
33
gaia/apps/verticalhome/test/marionette/app_short_name_test.js
Executable file
33
gaia/apps/verticalhome/test/marionette/app_short_name_test.js
Executable file
|
|
@ -0,0 +1,33 @@
|
|||
/* global __dirname */
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
|
||||
marionette('Vertical Home - App manifest', function() {
|
||||
var manifestName = 'shortnameapp.gaiamobile.org';
|
||||
var manifestUrl = 'app://' + manifestName + '/manifest.webapp';
|
||||
|
||||
var clientOptions = require(__dirname + '/client_options.js');
|
||||
clientOptions.apps = {};
|
||||
clientOptions.apps[manifestName] = __dirname + '/fixtures/short_name_app';
|
||||
var client = marionette.client({
|
||||
profile: clientOptions
|
||||
});
|
||||
|
||||
var home, system;
|
||||
|
||||
setup(function() {
|
||||
home = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
system.waitForFullyLoaded();
|
||||
|
||||
client.apps.launch(home.URL);
|
||||
home.waitForLaunch();
|
||||
});
|
||||
|
||||
test('short_name', function() {
|
||||
var title = home.getIcon(manifestUrl).findElement('.title');
|
||||
assert.equal(title.text(), 'Short name');
|
||||
});
|
||||
});
|
||||
|
||||
89
gaia/apps/verticalhome/test/marionette/app_uninstall_pending_test.js
Executable file
89
gaia/apps/verticalhome/test/marionette/app_uninstall_pending_test.js
Executable file
|
|
@ -0,0 +1,89 @@
|
|||
/* global __dirname */
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
|
||||
var AppInstall =
|
||||
require('../../../../apps/system/test/marionette/lib/app_install');
|
||||
|
||||
var createAppServer = require('./server/parent');
|
||||
var getIconId = require('./lib/icon_id');
|
||||
|
||||
marionette('Vertical - App uninstall while pending', function() {
|
||||
|
||||
var client = marionette.client({
|
||||
profile: require(__dirname + '/client_options.js'),
|
||||
desiredCapabilities: { raisesAccessibilityExceptions: false }
|
||||
});
|
||||
var actions, home, system, appInstall;
|
||||
var selectors;
|
||||
|
||||
var server;
|
||||
setup(function(done) {
|
||||
var app = __dirname + '/fixtures/template_app';
|
||||
createAppServer(app, client, function(err, _server) {
|
||||
server = _server;
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
appInstall = new AppInstall(client);
|
||||
|
||||
actions = client.loader.getActions();
|
||||
home = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
selectors = home.Selectors;
|
||||
|
||||
// ensure that the zip file does not get sent
|
||||
server.cork(server.applicationZipUri);
|
||||
|
||||
// wait for the system app to be running
|
||||
system.waitForFullyLoaded();
|
||||
client.apps.launch(home.URL);
|
||||
home.waitForLaunch();
|
||||
|
||||
// install the app
|
||||
client.switchToFrame();
|
||||
appInstall.installPackage(server.packageManifestURL);
|
||||
|
||||
// switch to the homescreen
|
||||
client.switchToFrame(system.getHomescreenIframe());
|
||||
|
||||
// this helps marionette finding the icon: Bug 1046706
|
||||
var icon = home.getIcon(server.packageManifestURL);
|
||||
home.moveIconToIndex(icon, 0);
|
||||
|
||||
home.enterEditMode();
|
||||
});
|
||||
|
||||
test('use edit mode to uninstall the app', function() {
|
||||
var icon = home.getIcon(server.packageManifestURL);
|
||||
var iconId = getIconId(icon);
|
||||
var remove = icon.findElement('.remove');
|
||||
|
||||
// XXX: work around issues where the icon is hidden by other
|
||||
// status messages on the system app.
|
||||
icon.scriptWith(function(el) {
|
||||
// effectively scroll to the bottom of the screen.
|
||||
el.scrollIntoView(false);
|
||||
});
|
||||
|
||||
// remove the icon
|
||||
remove.tap();
|
||||
// confirm the dialog to ensure it was removed.
|
||||
client.switchToFrame();
|
||||
home.confirmDialog('remove');
|
||||
// ensure the icon disappears
|
||||
client.switchToFrame(system.getHomescreenIframe());
|
||||
client.helper.waitForElementToDisappear(icon);
|
||||
|
||||
home.restart();
|
||||
|
||||
var allIconIds = home.getIconIdentifiers();
|
||||
assert.ok(allIconIds.indexOf(iconId) === -1, 'app was removed');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
75
gaia/apps/verticalhome/test/marionette/app_uninstall_test.js
Executable file
75
gaia/apps/verticalhome/test/marionette/app_uninstall_test.js
Executable file
|
|
@ -0,0 +1,75 @@
|
|||
/* global __dirname */
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
|
||||
var AppInstall =
|
||||
require('../../../../apps/system/test/marionette/lib/app_install');
|
||||
|
||||
var createAppServer = require('./server/parent');
|
||||
var getIconId = require('./lib/icon_id');
|
||||
|
||||
marionette('Vertical - App Uninstall', function() {
|
||||
|
||||
var client = marionette.client({
|
||||
profile: require(__dirname + '/client_options.js'),
|
||||
desiredCapabilities: { raisesAccessibilityExceptions: false }
|
||||
});
|
||||
var actions, home, system, appInstall;
|
||||
var selectors;
|
||||
|
||||
var server;
|
||||
setup(function(done) {
|
||||
var app = __dirname + '/fixtures/template_app';
|
||||
createAppServer(app, client, function(err, _server) {
|
||||
server = _server;
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
appInstall = new AppInstall(client);
|
||||
|
||||
actions = client.loader.getActions();
|
||||
home = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
system.waitForFullyLoaded();
|
||||
|
||||
selectors = home.Selectors;
|
||||
|
||||
client.apps.launch(home.URL);
|
||||
home.waitForLaunch();
|
||||
|
||||
// install an app
|
||||
client.switchToFrame();
|
||||
appInstall.install(server.manifestURL);
|
||||
|
||||
client.switchToFrame(system.getHomescreenIframe());
|
||||
home.enterEditMode();
|
||||
});
|
||||
|
||||
test('use edit mode to uninstall the app', function() {
|
||||
var icon = home.getIcon(server.manifestURL);
|
||||
var iconId = getIconId(icon);
|
||||
// helps marionette finding the icon: Bug 1046706
|
||||
home.moveIconToIndex(icon, 0);
|
||||
|
||||
var remove = icon.findElement('.remove');
|
||||
|
||||
// remove the icon
|
||||
remove.tap();
|
||||
// confirm the dialog to ensure it was removed.
|
||||
client.switchToFrame();
|
||||
home.confirmDialog('remove');
|
||||
// ensure the icon disappears
|
||||
client.switchToFrame(system.getHomescreenIframe());
|
||||
client.helper.waitForElementToDisappear(icon);
|
||||
|
||||
home.restart();
|
||||
|
||||
var allIconIds = home.getIconIdentifiers();
|
||||
assert.ok(allIconIds.indexOf(iconId) === -1, 'app was removed');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
81
gaia/apps/verticalhome/test/marionette/app_unrecoverable_error_test.js
Executable file
81
gaia/apps/verticalhome/test/marionette/app_unrecoverable_error_test.js
Executable file
|
|
@ -0,0 +1,81 @@
|
|||
/* global __dirname */
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var AppInstall =
|
||||
require('../../../../apps/system/test/marionette/lib/app_install');
|
||||
var createAppServer = require('./server/parent');
|
||||
|
||||
var iconAppState = require('./lib/icon_app_state');
|
||||
var launchIcon = require('./lib/launch_icon');
|
||||
var getIconId = require('./lib/icon_id');
|
||||
|
||||
marionette('Vertical Home - App unrecoverable error', function() {
|
||||
var client = marionette.client({
|
||||
profile: require(__dirname + '/client_options.js'),
|
||||
desiredCapabilities: { raisesAccessibilityExceptions: false }
|
||||
});
|
||||
var server;
|
||||
setup(function(done) {
|
||||
var app = __dirname + '/fixtures/template_app';
|
||||
createAppServer(app, client, function(err, _server) {
|
||||
server = _server;
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
var subject;
|
||||
var system;
|
||||
var appInstall;
|
||||
setup(function() {
|
||||
subject = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
appInstall = new AppInstall(client);
|
||||
|
||||
system.waitForFullyLoaded();
|
||||
subject.waitForLaunch();
|
||||
});
|
||||
|
||||
teardown(function(done) {
|
||||
server.close(done);
|
||||
});
|
||||
|
||||
function expectAppState(icon, state) {
|
||||
client.waitFor(function() {
|
||||
var currentState = iconAppState(icon);
|
||||
return currentState === state;
|
||||
});
|
||||
}
|
||||
|
||||
test('remove an app that was in an unrecoverable state', function() {
|
||||
client.switchToFrame();
|
||||
|
||||
server.serverError(server.applicationZipUri);
|
||||
appInstall.installPackage(server.packageManifestURL);
|
||||
|
||||
client.switchToFrame(system.getHomescreenIframe());
|
||||
|
||||
// if the server returns a 500 error the app is assumed to be in an
|
||||
// unrecoverable state.
|
||||
var icon = subject.getIcon(server.packageManifestURL);
|
||||
var iconId = getIconId(icon);
|
||||
expectAppState(icon, 'unrecoverable');
|
||||
|
||||
// helps marionette finding the icon: Bug 1046706
|
||||
subject.moveIconToIndex(icon, 0);
|
||||
|
||||
// agree to uninstall the app
|
||||
launchIcon(icon);
|
||||
client.switchToFrame();
|
||||
subject.confirmDialog('unrecoverable');
|
||||
|
||||
// ensure the icon disappears
|
||||
client.switchToFrame(system.getHomescreenIframe());
|
||||
client.helper.waitForElementToDisappear(icon);
|
||||
// verify that the app was uninstalled
|
||||
subject.restart();
|
||||
|
||||
var allIconIds = subject.getIconIdentifiers();
|
||||
assert.ok(allIconIds.indexOf(iconId) === -1, 'app was removed');
|
||||
});
|
||||
});
|
||||
59
gaia/apps/verticalhome/test/marionette/bookmark_edit_test.js
Executable file
59
gaia/apps/verticalhome/test/marionette/bookmark_edit_test.js
Executable file
|
|
@ -0,0 +1,59 @@
|
|||
'use strict';
|
||||
/* global __dirname */
|
||||
|
||||
var Bookmark = require('../../../../apps/system/test/marionette/lib/bookmark');
|
||||
var Server = require('../../../../shared/test/integration/server');
|
||||
|
||||
marionette('Vertical - Bookmark EDIT', function() {
|
||||
var options = require(__dirname + '/client_options.js');
|
||||
options.settings['dev.gaia.pinning_the_web'] = false;
|
||||
var client = marionette.client({
|
||||
profile: options,
|
||||
desiredCapabilities: { raisesAccessibilityExceptions: false }
|
||||
});
|
||||
var bookmark, home, server, system;
|
||||
|
||||
suiteSetup(function(done) {
|
||||
Server.create(__dirname + '/fixtures/', function(err, _server) {
|
||||
server = _server;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
server.stop();
|
||||
});
|
||||
|
||||
var url;
|
||||
setup(function() {
|
||||
home = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
bookmark = new Bookmark(client, server);
|
||||
system.waitForFullyLoaded();
|
||||
|
||||
client.apps.launch(home.URL);
|
||||
|
||||
url = server.url('sample.html');
|
||||
bookmark.openAndSave(url);
|
||||
|
||||
system.goHome();
|
||||
client.switchToFrame(system.getHomescreenIframe());
|
||||
home.enterEditMode();
|
||||
});
|
||||
|
||||
test('pressing enter after editing the bookmark', function() {
|
||||
// select the icon in edit mode and click remove
|
||||
var icon = home.getIcon(url);
|
||||
home.moveIconToIndex(icon, 0);
|
||||
icon.tap();
|
||||
|
||||
client.switchToFrame();
|
||||
bookmark.renameAndPressEnter('renamed');
|
||||
client.switchToFrame(system.getHomescreenIframe());
|
||||
|
||||
client.waitFor(function() {
|
||||
var icon = home.getIcon(url);
|
||||
return icon.text() === 'renamed';
|
||||
});
|
||||
});
|
||||
});
|
||||
59
gaia/apps/verticalhome/test/marionette/bookmark_invalid_favicon_test.js
Executable file
59
gaia/apps/verticalhome/test/marionette/bookmark_invalid_favicon_test.js
Executable file
|
|
@ -0,0 +1,59 @@
|
|||
'use strict';
|
||||
/* global __dirname */
|
||||
|
||||
var iconSrc = require('./lib/icon_src');
|
||||
var Bookmark = require('../../../../apps/system/test/marionette/lib/bookmark');
|
||||
var Server = require('../../../../shared/test/integration/server');
|
||||
|
||||
marionette('Vertical - Bookmark Favicon Failure', function() {
|
||||
|
||||
var options = require(__dirname + '/client_options.js');
|
||||
options.settings['dev.gaia.pinning_the_web'] = false;
|
||||
var client = marionette.client({
|
||||
profile: options,
|
||||
desiredCapabilities: { raisesAccessibilityExceptions: false }
|
||||
});
|
||||
var bookmark, home, server, system;
|
||||
|
||||
suiteSetup(function(done) {
|
||||
Server.create(__dirname + '/fixtures/invalid_favicon/',
|
||||
function(err, _server) {
|
||||
server = _server;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
server.stop();
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
home = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
bookmark = new Bookmark(client, server);
|
||||
system.waitForFullyLoaded();
|
||||
|
||||
client.apps.launch(home.URL);
|
||||
});
|
||||
|
||||
test('Invalid icons get default icon assigned', function() {
|
||||
system.tapHome();
|
||||
client.switchToFrame(system.getHomescreenIframe());
|
||||
var url = server.url('sample.html');
|
||||
|
||||
client.switchToFrame();
|
||||
bookmark.openAndSave(url);
|
||||
|
||||
system.tapHome();
|
||||
client.switchToFrame(system.getHomescreenIframe());
|
||||
|
||||
var icon = home.getIcon(url);
|
||||
|
||||
// ensure the default icon is shown
|
||||
client.waitFor(function() {
|
||||
var src = iconSrc(icon);
|
||||
return src && src.indexOf('default') !== -1;
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
58
gaia/apps/verticalhome/test/marionette/bookmark_test.js
Executable file
58
gaia/apps/verticalhome/test/marionette/bookmark_test.js
Executable file
|
|
@ -0,0 +1,58 @@
|
|||
'use strict';
|
||||
/* global __dirname */
|
||||
|
||||
var assert = require('assert');
|
||||
|
||||
var Bookmark = require('../../../../apps/system/test/marionette/lib/bookmark');
|
||||
var Server = require('../../../../shared/test/integration/server');
|
||||
|
||||
marionette('Vertical - Bookmark', function() {
|
||||
var options = require(__dirname + '/client_options.js');
|
||||
options.settings['dev.gaia.pinning_the_web'] = false;
|
||||
var client = marionette.client({
|
||||
profile: options,
|
||||
desiredCapabilities: { raisesAccessibilityExceptions: false }
|
||||
});
|
||||
var bookmark, home, server, system;
|
||||
|
||||
suiteSetup(function(done) {
|
||||
Server.create(__dirname + '/fixtures/', function(err, _server) {
|
||||
server = _server;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
server.stop();
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
home = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
bookmark = new Bookmark(client, server);
|
||||
system.waitForFullyLoaded();
|
||||
|
||||
client.apps.launch(home.URL);
|
||||
});
|
||||
|
||||
test('Bookmarking appends to last group', function() {
|
||||
system.tapHome();
|
||||
client.switchToFrame(system.getHomescreenIframe());
|
||||
|
||||
var numIcons = home.numIcons;
|
||||
var numDividers = home.numDividers;
|
||||
var url = server.url('sample.html');
|
||||
|
||||
client.switchToFrame();
|
||||
bookmark.openAndSave(url);
|
||||
|
||||
system.tapHome();
|
||||
client.switchToFrame(system.getHomescreenIframe());
|
||||
|
||||
client.waitFor(function() {
|
||||
return numIcons + 1 === home.numIcons;
|
||||
});
|
||||
assert.equal(numDividers, home.numDividers);
|
||||
});
|
||||
|
||||
});
|
||||
64
gaia/apps/verticalhome/test/marionette/bookmark_uninstall_test.js
Executable file
64
gaia/apps/verticalhome/test/marionette/bookmark_uninstall_test.js
Executable file
|
|
@ -0,0 +1,64 @@
|
|||
'use strict';
|
||||
/* global __dirname */
|
||||
|
||||
var assert = require('assert');
|
||||
|
||||
var Bookmark = require('../../../../apps/system/test/marionette/lib/bookmark');
|
||||
var Server = require('../../../../shared/test/integration/server');
|
||||
|
||||
marionette('Vertical - Bookmark Uninstall', function() {
|
||||
|
||||
var options = require(__dirname + '/client_options.js');
|
||||
options.settings['dev.gaia.pinning_the_web'] = false;
|
||||
var client = marionette.client({
|
||||
profile: options,
|
||||
desiredCapabilities: { raisesAccessibilityExceptions: false }
|
||||
});
|
||||
var bookmark, home, server, system;
|
||||
|
||||
suiteSetup(function(done) {
|
||||
Server.create(__dirname + '/fixtures/', function(err, _server) {
|
||||
server = _server;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
server.stop();
|
||||
});
|
||||
|
||||
var url;
|
||||
setup(function() {
|
||||
home = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
bookmark = new Bookmark(client, server);
|
||||
system.waitForFullyLoaded();
|
||||
|
||||
client.apps.launch(home.URL);
|
||||
|
||||
url = server.url('sample.html');
|
||||
bookmark.openAndSave(url);
|
||||
|
||||
system.goHome();
|
||||
client.switchToFrame(system.getHomescreenIframe());
|
||||
home.enterEditMode();
|
||||
});
|
||||
|
||||
test('removal of bookmark', function() {
|
||||
// select the icon in edit mode and click remove
|
||||
var icon = home.getIcon(url);
|
||||
home.moveIconToIndex(icon, 0);
|
||||
var remove = icon.findElement('.remove');
|
||||
remove.tap();
|
||||
home.confirmDialog('remove');
|
||||
|
||||
// ensure the icon disappears
|
||||
client.helper.waitForElementToDisappear(icon);
|
||||
|
||||
home.restart();
|
||||
|
||||
// ensure bookmark is gone upon restart
|
||||
var allIconIds = home.getIconIdentifiers();
|
||||
assert.ok(allIconIds.indexOf(url) === -1, 'bookmark was removed');
|
||||
});
|
||||
});
|
||||
8
gaia/apps/verticalhome/test/marionette/client_options.js
Executable file
8
gaia/apps/verticalhome/test/marionette/client_options.js
Executable file
|
|
@ -0,0 +1,8 @@
|
|||
module.exports = {
|
||||
settings: {
|
||||
'devtools.pseudolocalization.enabled': false,
|
||||
'language.current': 'en-US',
|
||||
'homescreen.manifestURL':
|
||||
'app://verticalhome.gaiamobile.org/manifest.webapp'
|
||||
}
|
||||
};
|
||||
31
gaia/apps/verticalhome/test/marionette/edit_mode_test.js
Executable file
31
gaia/apps/verticalhome/test/marionette/edit_mode_test.js
Executable file
|
|
@ -0,0 +1,31 @@
|
|||
'use strict';
|
||||
|
||||
marionette('Vertical - Edit Mode', function() {
|
||||
|
||||
var client = marionette.client({
|
||||
profile: require(__dirname + '/client_options.js')
|
||||
});
|
||||
var actions, home, system;
|
||||
var selectors;
|
||||
|
||||
setup(function() {
|
||||
actions = client.loader.getActions();
|
||||
home = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
system.waitForFullyLoaded();
|
||||
selectors = home.Selectors;
|
||||
|
||||
client.apps.launch(home.URL);
|
||||
|
||||
home.waitForLaunch();
|
||||
});
|
||||
|
||||
test('Exit edit mode using done button', function() {
|
||||
home.enterEditMode();
|
||||
var header = client.findElement(selectors.editHeaderText);
|
||||
var done = client.helper.waitForElement(selectors.editHeaderDone);
|
||||
done.click();
|
||||
client.helper.waitForElementToDisappear(header);
|
||||
});
|
||||
|
||||
});
|
||||
0
gaia/apps/verticalhome/test/marionette/fixtures/appcache/Blank.png
Executable file
0
gaia/apps/verticalhome/test/marionette/fixtures/appcache/Blank.png
Executable file
4
gaia/apps/verticalhome/test/marionette/fixtures/appcache/cache.appcache
Executable file
4
gaia/apps/verticalhome/test/marionette/fixtures/appcache/cache.appcache
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
CACHE MANIFEST
|
||||
# v1 2014-06-10
|
||||
index.html
|
||||
style/icons/Blank.png
|
||||
10
gaia/apps/verticalhome/test/marionette/fixtures/appcache/index.html
Executable file
10
gaia/apps/verticalhome/test/marionette/fixtures/appcache/index.html
Executable file
|
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<title>iwrotethis</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="test-app"></div>
|
||||
</body>
|
||||
</html>
|
||||
61
gaia/apps/verticalhome/test/marionette/fixtures/appcache/manifest.webapp
Executable file
61
gaia/apps/verticalhome/test/marionette/fixtures/appcache/manifest.webapp
Executable file
|
|
@ -0,0 +1,61 @@
|
|||
{
|
||||
"name": "Template",
|
||||
"description": "Web app template",
|
||||
"launch_path": "/index.html",
|
||||
"developer": {
|
||||
"name": "The Gaia Team",
|
||||
"url": "https://github.com/mozilla-b2g/gaia"
|
||||
},
|
||||
"locales": {
|
||||
"ar": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"de": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"el": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"en-US": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"es": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"fr": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"it": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"pt-BR": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"ru": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"tr": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"zh-TW": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
}
|
||||
},
|
||||
"default_locale": "en-US",
|
||||
"appcache_path": "/cache.appcache",
|
||||
"icons": {
|
||||
"128": "/style/icons/Blank.png"
|
||||
}
|
||||
}
|
||||
|
||||
BIN
gaia/apps/verticalhome/test/marionette/fixtures/appcache/style/icons/Blank.png
Executable file
BIN
gaia/apps/verticalhome/test/marionette/fixtures/appcache/style/icons/Blank.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
|
|
@ -0,0 +1 @@
|
|||
This is an invalid favicon for testing purposes.
|
||||
11
gaia/apps/verticalhome/test/marionette/fixtures/invalid_favicon/sample.html
Executable file
11
gaia/apps/verticalhome/test/marionette/fixtures/invalid_favicon/sample.html
Executable file
|
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Sample page</title>
|
||||
</head>
|
||||
<body>
|
||||
<header><h1>Mozilla</h1></header>
|
||||
<section>We are global community with a common purpose</section>
|
||||
</body>
|
||||
</html>
|
||||
10
gaia/apps/verticalhome/test/marionette/fixtures/role_homescreen/index.html
Executable file
10
gaia/apps/verticalhome/test/marionette/fixtures/role_homescreen/index.html
Executable file
|
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<title>iwrotethis</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="test-app"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
{
|
||||
"name": "Template",
|
||||
"description": "Web app template",
|
||||
"launch_path": "/index.html",
|
||||
"developer": {
|
||||
"name": "The Gaia Team",
|
||||
"url": "https://github.com/mozilla-b2g/gaia"
|
||||
},
|
||||
"locales": {
|
||||
"ar": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"de": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"el": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"en-US": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"es": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"fr": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"it": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"pt-BR": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"ru": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"tr": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"zh-TW": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
}
|
||||
},
|
||||
"role": "homescreen",
|
||||
"default_locale": "en-US",
|
||||
"icons": {
|
||||
"128": "/style/icons/Blank.png"
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
11
gaia/apps/verticalhome/test/marionette/fixtures/sample.html
Executable file
11
gaia/apps/verticalhome/test/marionette/fixtures/sample.html
Executable file
|
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Sample page</title>
|
||||
</head>
|
||||
<body>
|
||||
<header><h1>Mozilla</h1></header>
|
||||
<section>We are global community with a common purpose</section>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<title>App with a short name</title>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "Loooooooooooooooooooooooooooooong name",
|
||||
"short_name": "Short name",
|
||||
"description": "Web app with a short name in the manifest",
|
||||
"launch_path": "/index.html",
|
||||
"developer": {
|
||||
"name": "The Gaia Team",
|
||||
"url": "https://github.com/mozilla-b2g/gaia"
|
||||
},
|
||||
"icons": {
|
||||
"128": "/style/icons/Blank.png"
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
0
gaia/apps/verticalhome/test/marionette/fixtures/template_app/Blank.png
Executable file
0
gaia/apps/verticalhome/test/marionette/fixtures/template_app/Blank.png
Executable file
10
gaia/apps/verticalhome/test/marionette/fixtures/template_app/index.html
Executable file
10
gaia/apps/verticalhome/test/marionette/fixtures/template_app/index.html
Executable file
|
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<title>iwrotethis</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="test-app"></div>
|
||||
</body>
|
||||
</html>
|
||||
60
gaia/apps/verticalhome/test/marionette/fixtures/template_app/manifest.webapp
Executable file
60
gaia/apps/verticalhome/test/marionette/fixtures/template_app/manifest.webapp
Executable file
|
|
@ -0,0 +1,60 @@
|
|||
{
|
||||
"name": "Template",
|
||||
"description": "Web app template",
|
||||
"launch_path": "/index.html",
|
||||
"developer": {
|
||||
"name": "The Gaia Team",
|
||||
"url": "https://github.com/mozilla-b2g/gaia"
|
||||
},
|
||||
"locales": {
|
||||
"ar": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"de": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"el": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"en-US": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"es": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"fr": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"it": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"pt-BR": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"ru": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"tr": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"zh-TW": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
}
|
||||
},
|
||||
"default_locale": "en-US",
|
||||
"icons": {
|
||||
"128": "/style/icons/Blank.png"
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
|
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<title>updatedwow</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="test-app"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
{
|
||||
"name": "Template",
|
||||
"description": "Web app template",
|
||||
"launch_path": "/index.html",
|
||||
"developer": {
|
||||
"name": "The Gaia Team",
|
||||
"url": "https://github.com/mozilla-b2g/gaia"
|
||||
},
|
||||
"locales": {
|
||||
"ar": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"de": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"el": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"en-US": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"es": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"fr": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"it": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"pt-BR": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"ru": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"tr": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
},
|
||||
"zh-TW": {
|
||||
"name": "Template",
|
||||
"description": "Web app template"
|
||||
}
|
||||
},
|
||||
"default_locale": "en-US",
|
||||
"icons": {
|
||||
"128": "/style/icons/MagicIcon.png"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
74
gaia/apps/verticalhome/test/marionette/grid_layout_test.js
Executable file
74
gaia/apps/verticalhome/test/marionette/grid_layout_test.js
Executable file
|
|
@ -0,0 +1,74 @@
|
|||
'use strict';
|
||||
var assert = require('assert');
|
||||
|
||||
marionette('Vertical - grid', function() {
|
||||
|
||||
var client = marionette.client({
|
||||
profile: require(__dirname + '/client_options.js')
|
||||
});
|
||||
var actions, home, system;
|
||||
|
||||
setup(function() {
|
||||
actions = client.loader.getActions();
|
||||
home = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
system.waitForFullyLoaded();
|
||||
home.waitForLaunch();
|
||||
});
|
||||
|
||||
test('apps grid is LTR in LTR language', function() {
|
||||
var app1Location = home.getNthIcon(1).location();
|
||||
var app2Location = home.getNthIcon(2).location();
|
||||
var app3Location = home.getNthIcon(3).location();
|
||||
var gridWidth = client.helper.waitForElement(home.Selectors.grid).size()
|
||||
.width;
|
||||
|
||||
// check that they are all on the same line
|
||||
assert.equal(app1Location.y, app2Location.y,
|
||||
'1st and 2nd apps should be on the same line.');
|
||||
assert.equal(app2Location.y, app3Location.y,
|
||||
'2nd and 3rd apps should be on the same line.');
|
||||
|
||||
// check left-alignement
|
||||
assert.ok(app1Location.x < gridWidth / 3, 'First app is left-aligned');
|
||||
// check the ordering
|
||||
assert.ok(app1Location.x < app2Location.x,
|
||||
'App1 icon should be on the left of app2 icon');
|
||||
assert.ok(app2Location.x < app3Location.x,
|
||||
'App2 icon should be on the left of app3 icon');
|
||||
});
|
||||
|
||||
test('apps grid is RTL in RTL language', function() {
|
||||
var communicationManifestUrl =
|
||||
'app://communications.gaiamobile.org/manifest.webapp';
|
||||
|
||||
client.settings.set('language.current', 'ar-x-psbidi');
|
||||
|
||||
// Localization can be async, wait for the content to update
|
||||
client.waitFor(function() {
|
||||
var phoneIcon = home.getIcon(communicationManifestUrl, 'dialer');
|
||||
return phoneIcon.text() ===
|
||||
home.localizedAppName('communications', 'dialer', 'ar-x-psbidi');
|
||||
});
|
||||
|
||||
var app1Location = home.getNthIcon(1).location();
|
||||
var app2Location = home.getNthIcon(2).location();
|
||||
var app3Location = home.getNthIcon(3).location();
|
||||
var gridWidth = client.helper.waitForElement(home.Selectors.grid).size()
|
||||
.width;
|
||||
|
||||
// check that they are all on the same line
|
||||
assert.equal(app1Location.y, app2Location.y,
|
||||
'1st and 2nd apps should be on the same line.');
|
||||
assert.equal(app2Location.y, app3Location.y,
|
||||
'2st and 3nd apps should be on the same line.');
|
||||
|
||||
// check right-alignement
|
||||
assert.ok(app1Location.x > gridWidth / 2, 'First app is right-aligned');
|
||||
// check the ordering
|
||||
assert.ok(app1Location.x > app2Location.x,
|
||||
'App1 icon should be on the right of app2 icon');
|
||||
assert.ok(app2Location.x > app3Location.x,
|
||||
'App2 icon should be on the right of app3 icon');
|
||||
});
|
||||
});
|
||||
42
gaia/apps/verticalhome/test/marionette/group_alternate_bg_color_test.js
Executable file
42
gaia/apps/verticalhome/test/marionette/group_alternate_bg_color_test.js
Executable file
|
|
@ -0,0 +1,42 @@
|
|||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
|
||||
marionette('Vertical - Group', function() {
|
||||
|
||||
var client = marionette.client({
|
||||
profile: require(__dirname + '/client_options.js')
|
||||
});
|
||||
var actions, home, system;
|
||||
|
||||
setup(function() {
|
||||
actions = client.loader.getActions();
|
||||
home = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
system.waitForFullyLoaded();
|
||||
|
||||
client.apps.launch(home.URL);
|
||||
home.waitForLaunch();
|
||||
});
|
||||
|
||||
test('check that group backgrounds alternate', function() {
|
||||
var groupSelector = '#icons .group';
|
||||
var oddGroupSelector = '#icons .group.odd';
|
||||
|
||||
// Now get groups and make sure they alternate
|
||||
var groups = client.findElements(groupSelector);
|
||||
var oddGroups = client.findElements(oddGroupSelector);
|
||||
|
||||
assert.ok(groups.length >= 3);
|
||||
assert.equal(oddGroups.length, Math.floor(groups.length / 2));
|
||||
|
||||
for (var i = 0, iLen = groups.length; i < iLen; i++) {
|
||||
var isOdd = groups[i].getAttribute('className').indexOf('odd') !== -1;
|
||||
if ((i % 2) === 1) {
|
||||
assert.ok(isOdd);
|
||||
} else {
|
||||
assert.ok(!isOdd);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
53
gaia/apps/verticalhome/test/marionette/group_collapse_context_menu_test.js
Executable file
53
gaia/apps/verticalhome/test/marionette/group_collapse_context_menu_test.js
Executable file
|
|
@ -0,0 +1,53 @@
|
|||
'use strict';
|
||||
|
||||
marionette('Vertical - Group', function() {
|
||||
|
||||
var client = marionette.client({
|
||||
profile: require(__dirname + '/client_options.js')
|
||||
});
|
||||
var actions, home, system;
|
||||
|
||||
setup(function() {
|
||||
actions = client.loader.getActions();
|
||||
home = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
system.waitForFullyLoaded();
|
||||
|
||||
client.apps.launch(home.URL);
|
||||
home.waitForLaunch();
|
||||
});
|
||||
|
||||
test('check dragging icon into collapsed group', function() {
|
||||
function scrollIntoView(el) {
|
||||
el.scrollIntoView(false);
|
||||
}
|
||||
|
||||
// Store a reference to the first icon
|
||||
var firstIcon = client.helper.waitForElement(home.Selectors.firstIcon);
|
||||
|
||||
// Enter edit mode
|
||||
home.enterEditMode();
|
||||
var header = client.helper.waitForElement(home.Selectors.editHeaderText);
|
||||
|
||||
// Drag icon to its own group
|
||||
actions.press(firstIcon).wait(1).move(header).release().wait(1).perform();
|
||||
|
||||
// Leave edit mode
|
||||
home.exitEditMode();
|
||||
|
||||
// Collapse new group
|
||||
var toggle = client.findElements(home.Selectors.groupToggle).pop();
|
||||
toggle.scriptWith(scrollIntoView);
|
||||
actions.tap(toggle).wait(1).perform();
|
||||
|
||||
// Long-press the home-screen in the middle of the collapsed group
|
||||
var groupBg = client.findElements(home.Selectors.groupBackground).pop();
|
||||
var grid = client.findElement(home.Selectors.grid);
|
||||
var x = groupBg.location().x + groupBg.size().width/2;
|
||||
var y = groupBg.location().y + groupBg.size().height/2;
|
||||
actions.press(grid, x, y).wait(1).perform();
|
||||
|
||||
// Wait for the context menu to appear
|
||||
client.helper.waitForElement(home.contextMenu);
|
||||
});
|
||||
});
|
||||
58
gaia/apps/verticalhome/test/marionette/group_collapse_drag_into_test.js
Executable file
58
gaia/apps/verticalhome/test/marionette/group_collapse_drag_into_test.js
Executable file
|
|
@ -0,0 +1,58 @@
|
|||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
|
||||
marionette('Vertical - Group', function() {
|
||||
|
||||
var client = marionette.client({
|
||||
profile: require(__dirname + '/client_options.js'),
|
||||
desiredCapabilities: { raisesAccessibilityExceptions: false }
|
||||
});
|
||||
var actions, home, system;
|
||||
|
||||
setup(function() {
|
||||
actions = client.loader.getActions();
|
||||
home = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
system.waitForFullyLoaded();
|
||||
|
||||
client.apps.launch(home.URL);
|
||||
home.waitForLaunch();
|
||||
});
|
||||
|
||||
test('check dragging icon into collapsed group', function() {
|
||||
function scrollIntoView(el) {
|
||||
el.scrollIntoView(false);
|
||||
}
|
||||
|
||||
// Store a reference to the first icon
|
||||
var firstIcon = client.helper.waitForElement(home.Selectors.firstIcon);
|
||||
var secondIcon = client.findElements(home.Selectors.firstIcon)[1];
|
||||
var collapse = client.findElement('.group .toggle');
|
||||
|
||||
// Enter edit mode
|
||||
home.enterEditMode();
|
||||
var header = client.helper.waitForElement(home.Selectors.editHeaderText);
|
||||
|
||||
// Drag icon to its own group
|
||||
actions.press(firstIcon).wait(1).move(header).release().wait(1).perform();
|
||||
|
||||
// Collapse the original group
|
||||
actions.tap(collapse).wait(1).perform();
|
||||
|
||||
// Count the number of collapsed icons
|
||||
var collapsedIconsSelector = '#icons div.icon.collapsed';
|
||||
var collapsedIconsBefore =
|
||||
client.findElements(collapsedIconsSelector).length;
|
||||
|
||||
// Drag icon into collapsed group
|
||||
firstIcon.scriptWith(scrollIntoView);
|
||||
actions.press(firstIcon).wait(1).move(secondIcon).release().
|
||||
wait(1).perform();
|
||||
|
||||
// Make sure there's one more collapsed icon
|
||||
var collapsedIconsAfter =
|
||||
client.findElements(collapsedIconsSelector).length;
|
||||
assert.equal(collapsedIconsAfter, collapsedIconsBefore + 1);
|
||||
});
|
||||
});
|
||||
35
gaia/apps/verticalhome/test/marionette/group_collapse_icon_launch_test.js
Executable file
35
gaia/apps/verticalhome/test/marionette/group_collapse_icon_launch_test.js
Executable file
|
|
@ -0,0 +1,35 @@
|
|||
'use strict';
|
||||
|
||||
marionette('Vertical - Group', function() {
|
||||
|
||||
var client = marionette.client({
|
||||
profile: require(__dirname + '/client_options.js')
|
||||
});
|
||||
var actions, home, system;
|
||||
|
||||
setup(function() {
|
||||
actions = client.loader.getActions();
|
||||
home = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
system.waitForFullyLoaded();
|
||||
|
||||
client.apps.launch(home.URL);
|
||||
home.waitForLaunch();
|
||||
});
|
||||
|
||||
test('collapse the first group', function() {
|
||||
// Get a reference for the first icon
|
||||
var icon = client.helper.waitForElement(home.Selectors.firstIcon);
|
||||
|
||||
// Retrieve the icon's manifest URL
|
||||
var manifestURL = icon.getAttribute('data-identifier');
|
||||
manifestURL = manifestURL.slice(0, manifestURL.lastIndexOf('-'));
|
||||
|
||||
// Collapse first group
|
||||
var collapse = client.findElement(home.Selectors.groupToggle);
|
||||
actions.tap(collapse).wait(1).perform();
|
||||
|
||||
// Try to launch the app
|
||||
home.launchAndSwitchToApp(manifestURL);
|
||||
});
|
||||
});
|
||||
47
gaia/apps/verticalhome/test/marionette/group_collapse_icon_size_test.js
Executable file
47
gaia/apps/verticalhome/test/marionette/group_collapse_icon_size_test.js
Executable file
|
|
@ -0,0 +1,47 @@
|
|||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
|
||||
marionette('Vertical - Group', function() {
|
||||
|
||||
var client = marionette.client({
|
||||
profile: require(__dirname + '/client_options.js')
|
||||
});
|
||||
var actions, home, system;
|
||||
|
||||
setup(function() {
|
||||
actions = client.loader.getActions();
|
||||
home = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
system.waitForFullyLoaded();
|
||||
|
||||
client.apps.launch(home.URL);
|
||||
home.waitForLaunch();
|
||||
});
|
||||
|
||||
test('check collapsed icon size vs. column width', function() {
|
||||
function getRect(el) {
|
||||
return el.getBoundingClientRect();
|
||||
}
|
||||
|
||||
// Collapse the first group
|
||||
var collapse = client.findElement('.group .toggle');
|
||||
actions.tap(collapse).wait(1).perform();
|
||||
|
||||
// Store the collapsed icon size
|
||||
var icon = client.helper.waitForElement(home.Selectors.firstIcon);
|
||||
var rect3col = icon.scriptWith(getRect);
|
||||
|
||||
// Change the column width
|
||||
client.executeScript(function() {
|
||||
window.wrappedJSObject.verticalPreferences.put('grid.cols', 4);
|
||||
});
|
||||
|
||||
actions.wait(1).perform();
|
||||
var rect4col = icon.scriptWith(getRect);
|
||||
|
||||
// Assert that the icons are the same size
|
||||
assert.equal(rect3col.width, rect4col.width);
|
||||
assert.equal(rect3col.height, rect4col.height);
|
||||
});
|
||||
});
|
||||
55
gaia/apps/verticalhome/test/marionette/group_collapse_test.js
Executable file
55
gaia/apps/verticalhome/test/marionette/group_collapse_test.js
Executable file
|
|
@ -0,0 +1,55 @@
|
|||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
|
||||
marionette('Vertical - Group', function() {
|
||||
|
||||
var client = marionette.client({
|
||||
profile: require(__dirname + '/client_options.js')
|
||||
});
|
||||
var actions, home, system;
|
||||
|
||||
setup(function() {
|
||||
actions = client.loader.getActions();
|
||||
home = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
system.waitForFullyLoaded();
|
||||
|
||||
client.apps.launch(home.URL);
|
||||
home.waitForLaunch();
|
||||
});
|
||||
|
||||
test('collapse the first group', function() {
|
||||
function getRect(el) {
|
||||
return el.getBoundingClientRect();
|
||||
}
|
||||
|
||||
function scrollIntoView(el) {
|
||||
el.scrollIntoView(false);
|
||||
}
|
||||
|
||||
// Store the metrics of the first icon before collapsing
|
||||
var icon = client.helper.waitForElement(home.Selectors.firstIcon);
|
||||
var rectBefore = icon.scriptWith(getRect);
|
||||
|
||||
// Enter edit mode
|
||||
home.enterEditMode();
|
||||
var header = client.helper.waitForElement(home.Selectors.editHeaderText);
|
||||
|
||||
// Drag icon to its own group before collapsing (to test alignment)
|
||||
actions.press(icon).wait(1).move(header).release().perform();
|
||||
client.helper.waitForElement(home.Selectors.editHeaderDone).click();
|
||||
|
||||
// Collapse group
|
||||
var collapse = client.findElements(home.Selectors.groupToggle).pop();
|
||||
collapse.scriptWith(scrollIntoView);
|
||||
actions.wait(1).tap(collapse).wait(1).perform();
|
||||
|
||||
// Retrieve the metrics of the first icon after collapsing
|
||||
var rectAfter = icon.scriptWith(getRect);
|
||||
|
||||
// Make sure that the icon got smaller and that it's left-aligned
|
||||
assert.ok(rectAfter.width < rectBefore.width);
|
||||
assert.ok(rectAfter.x < rectAfter.width);
|
||||
});
|
||||
});
|
||||
43
gaia/apps/verticalhome/test/marionette/group_drag_expanded_test.js
Executable file
43
gaia/apps/verticalhome/test/marionette/group_drag_expanded_test.js
Executable file
|
|
@ -0,0 +1,43 @@
|
|||
'use strict';
|
||||
|
||||
var Actions = require('marionette-client').Actions;
|
||||
var assert = require('assert');
|
||||
|
||||
marionette('Vertical - Group', function() {
|
||||
|
||||
var client = marionette.client({
|
||||
profile: require(__dirname + '/client_options.js')
|
||||
});
|
||||
var actions, home, system;
|
||||
|
||||
setup(function() {
|
||||
actions = new Actions(client);
|
||||
home = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
system.waitForFullyLoaded();
|
||||
|
||||
client.apps.launch(home.URL);
|
||||
home.waitForLaunch();
|
||||
});
|
||||
|
||||
test('check that dragging an expanded group collapses correctly', function() {
|
||||
function getRect(el) {
|
||||
return el.getBoundingClientRect();
|
||||
}
|
||||
|
||||
// Store the metrics of the first group
|
||||
var background = client.findElement(home.Selectors.groupBackground);
|
||||
var bgRect = background.scriptWith(getRect);
|
||||
|
||||
// Initiate a drag by long-pressing at the top-middle of the background
|
||||
// element, then wait for it to collapse
|
||||
actions.press(background, bgRect.width/2, 0).wait(3).perform();
|
||||
|
||||
var bgRectAfter = background.scriptWith(getRect);
|
||||
|
||||
// Check that the background is smaller, but still in the same position
|
||||
assert.equal(bgRect.x, bgRectAfter.x);
|
||||
assert.equal(bgRect.y, bgRectAfter.y);
|
||||
assert.ok(bgRectAfter.height < bgRect.height);
|
||||
});
|
||||
});
|
||||
41
gaia/apps/verticalhome/test/marionette/group_highlight_hovered_test.js
Executable file
41
gaia/apps/verticalhome/test/marionette/group_highlight_hovered_test.js
Executable file
|
|
@ -0,0 +1,41 @@
|
|||
'use strict';
|
||||
|
||||
var Actions = require('marionette-client').Actions;
|
||||
var assert = require('assert');
|
||||
|
||||
marionette('Vertical - Group', function() {
|
||||
|
||||
var client = marionette.client({
|
||||
profile: require(__dirname + '/client_options.js')
|
||||
});
|
||||
var actions, home, system;
|
||||
|
||||
setup(function() {
|
||||
actions = new Actions(client);
|
||||
home = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
system.waitForFullyLoaded();
|
||||
|
||||
client.apps.launch(home.URL);
|
||||
home.waitForLaunch();
|
||||
});
|
||||
|
||||
test('check that group backgrounds highlight when hovered over', function() {
|
||||
var groupSelector = '#icons .group';
|
||||
|
||||
// Store the metrics of the first icon before collapsing
|
||||
var icon = client.helper.waitForElement(home.Selectors.firstIcon);
|
||||
|
||||
// Long press on the icon and don't let go so we can see the styling of
|
||||
// the group underneath it
|
||||
actions.press(icon).wait(1).perform();
|
||||
|
||||
// Check that it has the styling that would highlight its background
|
||||
var group = client.findElement(groupSelector);
|
||||
assert.ok(group.getAttribute('className').indexOf('drop-target') !== -1);
|
||||
|
||||
// Make sure the highlight is removed after releasing
|
||||
actions.release().wait(1).perform();
|
||||
assert.ok(group.getAttribute('className').indexOf('drop-target') === -1);
|
||||
});
|
||||
});
|
||||
16
gaia/apps/verticalhome/test/marionette/lib/icon_app_state.js
Executable file
16
gaia/apps/verticalhome/test/marionette/lib/icon_app_state.js
Executable file
|
|
@ -0,0 +1,16 @@
|
|||
/* global module */
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
Determines the current state of the icon on the grid.
|
||||
|
||||
@param {Marionette.Element} element of particular icon.
|
||||
@return {String} state of the app icon.
|
||||
*/
|
||||
module.exports = function iconState(element) {
|
||||
// XXX: this syncs up with the stamping logic in `renderIcon` in gaia_grid
|
||||
return element.scriptWith(function(el) {
|
||||
return el.dataset.appState;
|
||||
});
|
||||
};
|
||||
16
gaia/apps/verticalhome/test/marionette/lib/icon_cached.js
Executable file
16
gaia/apps/verticalhome/test/marionette/lib/icon_cached.js
Executable file
|
|
@ -0,0 +1,16 @@
|
|||
/* global module */
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
Helper function to determine if the icon is cached in idb.
|
||||
|
||||
@param {Marionette.Element} element of particular icon.
|
||||
@return {String} url/uri for element.
|
||||
*/
|
||||
module.exports = function iconCached(element) {
|
||||
// This syncs up with the logic after iconblobload event in app.js
|
||||
var list = element.getAttribute('className');
|
||||
return list && list.indexOf('test-icon-cached') !== 1;
|
||||
};
|
||||
|
||||
15
gaia/apps/verticalhome/test/marionette/lib/icon_id.js
Executable file
15
gaia/apps/verticalhome/test/marionette/lib/icon_id.js
Executable file
|
|
@ -0,0 +1,15 @@
|
|||
/* global module */
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
Return the id of a particular icon.
|
||||
|
||||
@param {Marionette.Element} element of particular icon.
|
||||
@return {String} id for the icon.
|
||||
*/
|
||||
module.exports = function iconId(element) {
|
||||
return element.scriptWith(function(el) {
|
||||
return el.dataset.identifier;
|
||||
});
|
||||
};
|
||||
16
gaia/apps/verticalhome/test/marionette/lib/icon_src.js
Executable file
16
gaia/apps/verticalhome/test/marionette/lib/icon_src.js
Executable file
|
|
@ -0,0 +1,16 @@
|
|||
/* global module */
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
Helper function to determine which icon an grid item element is using.
|
||||
|
||||
@param {Marionette.Element} element of particular icon.
|
||||
@return {String} url/uri for element.
|
||||
*/
|
||||
module.exports = function waitForIcon(element) {
|
||||
// XXX: this syncs up with the stamping logic in `renderIcon` in gaia_grid
|
||||
return element.scriptWith(function(el) {
|
||||
return el.dataset.testIcon;
|
||||
});
|
||||
};
|
||||
38
gaia/apps/verticalhome/test/marionette/lib/launch_icon.js
Executable file
38
gaia/apps/verticalhome/test/marionette/lib/launch_icon.js
Executable file
|
|
@ -0,0 +1,38 @@
|
|||
/* global module */
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
Launches an icon (which may be a real app launch or download retry)
|
||||
|
||||
@param {Marionette.Element} element of particular icon.
|
||||
*/
|
||||
module.exports = function launchIcon(element) {
|
||||
// XXX: work around focus issues by ensuring we clicked the thing
|
||||
element.scriptWith(function(e) {
|
||||
e.scrollIntoView(false);
|
||||
e.__ensureClick__ = function() {
|
||||
e.removeEventListener('click', e.__ensureClick__);
|
||||
e.setAttribute('data-test-was-clicked', true);
|
||||
};
|
||||
e.addEventListener('click', e.__ensureClick__);
|
||||
});
|
||||
|
||||
element.client.waitFor(function() {
|
||||
// try to click it
|
||||
element.tap();
|
||||
|
||||
return element.scriptWith(function(e) {
|
||||
// if it was clicked clear the state if we want to run this again
|
||||
if (e.getAttribute('data-test-was-clicked')) {
|
||||
e.removeEventListener('click', e.__ensureClick__);
|
||||
e.removeAttribute('data-test-was-clicked');
|
||||
return true;
|
||||
}
|
||||
|
||||
// otherwise try again
|
||||
return false;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
354
gaia/apps/verticalhome/test/marionette/lib/verticalhome.js
Executable file
354
gaia/apps/verticalhome/test/marionette/lib/verticalhome.js
Executable file
|
|
@ -0,0 +1,354 @@
|
|||
'use strict';
|
||||
|
||||
var getIconId = require('./icon_id');
|
||||
|
||||
/**
|
||||
* Abstraction around homescreen.
|
||||
* @constructor
|
||||
*/
|
||||
function VerticalHome(client) {
|
||||
this.client = client;
|
||||
this.system = client.loader.getAppClass('system');
|
||||
}
|
||||
|
||||
/**
|
||||
* @type String Origin of VerticalHome app
|
||||
*/
|
||||
VerticalHome.URL = 'app://verticalhome.gaiamobile.org';
|
||||
|
||||
VerticalHome.Selectors = {
|
||||
grid: '#icons',
|
||||
editHeaderText: '#edit-header h1',
|
||||
editHeaderDone: '#exit-edit-mode',
|
||||
editGroup: '#edit-group',
|
||||
editGroupTitle: '#edit-group-title',
|
||||
editGroupSave: '#edit-group-save',
|
||||
editGroupTitleClear: '#edit-group-title-clear',
|
||||
search: '#search',
|
||||
firstIcon: '#icons div.icon:not(.placeholder)',
|
||||
groupHeader: '#icons .group .header',
|
||||
groupTitle: '#icons .group .header .title',
|
||||
groupBackground: '#icons .group .background',
|
||||
groupToggle: '#icons .group .toggle',
|
||||
dividers: '#icons section.divider',
|
||||
contextmenu: '#contextmenu-dialog',
|
||||
themeColor: 'head meta[name="theme-color"]',
|
||||
placeholders: '#icons .placeholder'
|
||||
};
|
||||
|
||||
/**
|
||||
* Launches our new homescreen and focuses on it.
|
||||
*/
|
||||
VerticalHome.prototype = {
|
||||
|
||||
URL: VerticalHome.URL,
|
||||
Selectors: VerticalHome.Selectors,
|
||||
|
||||
get numIcons() {
|
||||
return this.client.findElements(VerticalHome.Selectors.firstIcon).length;
|
||||
},
|
||||
|
||||
get numDividers() {
|
||||
return this.dividers.length;
|
||||
},
|
||||
|
||||
get dividers() {
|
||||
return this.client.findElements(VerticalHome.Selectors.dividers);
|
||||
},
|
||||
|
||||
get contextMenu() {
|
||||
return this.client.findElement(VerticalHome.Selectors.contextmenu);
|
||||
},
|
||||
|
||||
/**
|
||||
Fetch a particular type of a gaia-confirm dialog.
|
||||
|
||||
@param {String} type of dialog.
|
||||
*/
|
||||
getConfirmDialog: function(type) {
|
||||
var selector = 'gaia-confirm[data-type="' + type + '"]';
|
||||
return this.client.helper.waitForElement(selector);
|
||||
},
|
||||
|
||||
/**
|
||||
Click confirm on a particular type of confirmation dialog.
|
||||
|
||||
@param {String} type of dialog.
|
||||
@param {String} selector of the button. Defaults to .confirm.
|
||||
*/
|
||||
confirmDialog: function(type, button) {
|
||||
var dialog = this.getConfirmDialog(type);
|
||||
var confirm;
|
||||
|
||||
this.client.waitFor(function() {
|
||||
confirm = dialog.findElement(button || '.confirm');
|
||||
return confirm && confirm.displayed();
|
||||
});
|
||||
|
||||
// XXX: Hack to use faster polling
|
||||
var quickly = this.client.scope({ searchTimeout: 50 });
|
||||
confirm.client = quickly;
|
||||
|
||||
// tricky logic to ensure the dialog has been removed and clicked
|
||||
this.client.waitFor(function() {
|
||||
try {
|
||||
// click the dialog to dismiss it
|
||||
confirm.click();
|
||||
// ensure it is either hidden or hits the stale element ref
|
||||
return !confirm.displayed();
|
||||
} catch (e) {
|
||||
if (e.type === 'StaleElementReference') {
|
||||
// element was successfully removed
|
||||
return true;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Enter edit mode by long pressing a given icon, or the first icon on the
|
||||
* grid if not specified.
|
||||
*/
|
||||
enterEditMode: function(icon) {
|
||||
var actions = this.client.loader.getActions();
|
||||
var firstIcon = icon ||
|
||||
this.client.helper.waitForElement(VerticalHome.Selectors.firstIcon);
|
||||
|
||||
actions.longPress(firstIcon, 1).perform();
|
||||
this.client.helper.waitForElement(VerticalHome.Selectors.editHeaderText);
|
||||
},
|
||||
|
||||
/**
|
||||
* Exits the edit mode by long-pressing the done button and waiting for it
|
||||
* to disappear.
|
||||
*/
|
||||
exitEditMode: function() {
|
||||
var done = this.client.findElement(VerticalHome.Selectors.editHeaderDone);
|
||||
done.click();
|
||||
this.client.helper.waitForElementToDisappear(done);
|
||||
},
|
||||
|
||||
/**
|
||||
* Emulates pressing of the hardware home button.
|
||||
*/
|
||||
pressHomeButton: function() {
|
||||
this.client.executeScript(function() {
|
||||
var home = new CustomEvent('home');
|
||||
window.dispatchEvent(home);
|
||||
});
|
||||
},
|
||||
|
||||
focusRocketBar: function() {
|
||||
this.client.helper.waitForElement(VerticalHome.Selectors.search).tap();
|
||||
this.client.switchToFrame();
|
||||
},
|
||||
|
||||
/**
|
||||
Tap an app icon in the homescreen
|
||||
|
||||
@param {String} manifestURL full manifest url path.
|
||||
*/
|
||||
launchApp: function(manifestURL) {
|
||||
// switch back to the homescreen
|
||||
this.client.switchToFrame();
|
||||
this.client.switchToFrame(this.system.getHomescreenIframe());
|
||||
|
||||
// tap the app in the homescreen
|
||||
var newApp = this.getIcon(manifestURL);
|
||||
newApp.tap();
|
||||
|
||||
// go to the system app
|
||||
this.client.switchToFrame();
|
||||
},
|
||||
|
||||
/**
|
||||
Tap an app icon and switch to it's application iframe.
|
||||
|
||||
@param {String} manifestURL full manifest url path.
|
||||
*/
|
||||
launchAndSwitchToApp: function(manifestURL) {
|
||||
var client = this.client.scope({ searchTimeout: 100 });
|
||||
var frame;
|
||||
client.waitFor(function() {
|
||||
this.launchApp(manifestURL);
|
||||
// wait for the app to show up
|
||||
try {
|
||||
frame = client.findElement(
|
||||
'iframe[mozapp="' + manifestURL + '"]'
|
||||
);
|
||||
} catch (e) {
|
||||
// try again...
|
||||
return false;
|
||||
}
|
||||
client.switchToFrame(frame);
|
||||
return true;
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
Restart the homescreen then refocus on it.
|
||||
*/
|
||||
restart: function() {
|
||||
this.client.executeScript(function() {
|
||||
window.close();
|
||||
});
|
||||
|
||||
// initialize our frames again since we killed the iframe
|
||||
this.client.switchToFrame();
|
||||
this.client.switchToFrame(this.system.getHomescreenIframe());
|
||||
},
|
||||
|
||||
/**
|
||||
Find and return every id for all the items on the grid... Each element
|
||||
can be used with `.getIcon` to find the element for a given id.
|
||||
|
||||
@return {Array[String]}
|
||||
*/
|
||||
getIconIdentifiers: function() {
|
||||
return this.client.findElements('[data-identifier]').map(function(el) {
|
||||
return getIconId(el);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
Fetch an icon element on the homescreen.
|
||||
|
||||
@param {String} manifestURL must be a fully qualified manifest url.
|
||||
@return {Marionette.Element}
|
||||
*/
|
||||
getIcon: function(manifestUrl, entryPoint) {
|
||||
return this.client.helper.waitForElement(
|
||||
'[data-identifier*="' + manifestUrl +
|
||||
(entryPoint ? '-' + entryPoint : '') + '"]'
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
Fetch the nth icon on the homescreen.
|
||||
|
||||
@param {number} the icon number we want
|
||||
@return {Marionette.Element}
|
||||
*/
|
||||
getNthIcon: function(number) {
|
||||
return this.client.helper.waitForElement(
|
||||
'.icon:nth-of-type(' + number + ')'
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
Get the the current meta=theme-color of the homescreen
|
||||
|
||||
@return {String}
|
||||
*/
|
||||
getThemeColor: function() {
|
||||
var meta = this.client.findElement(VerticalHome.Selectors.themeColor);
|
||||
return meta.getAttribute('content');
|
||||
},
|
||||
|
||||
/**
|
||||
* Waits for the homescreen to launch and switches to the frame.
|
||||
*/
|
||||
waitForLaunch: function() {
|
||||
this.client.helper.waitForElement('body');
|
||||
this.client.apps.switchToApp(VerticalHome.URL);
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets a localized application name from a manifest.
|
||||
* @param {String} app to open
|
||||
* @param {String} entryPoint to open
|
||||
* @param {String} locale
|
||||
*/
|
||||
localizedAppName: function(app, entryPoint, locale) {
|
||||
if (!locale) {
|
||||
locale = entryPoint;
|
||||
entryPoint = null;
|
||||
}
|
||||
|
||||
var file = 'app://' + app + '.gaiamobile.org/manifest.webapp';
|
||||
// use a chrome-scoped Marionette client for the cross-domain XHR
|
||||
var chromeClient = this.client.scope({context: 'chrome'});
|
||||
var manifest = chromeClient.executeAsyncScript(function(file) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', file, true);
|
||||
xhr.onload = function(o) {
|
||||
var data = JSON.parse(xhr.response);
|
||||
marionetteScriptFinished(data);
|
||||
};
|
||||
xhr.send(null);
|
||||
}, [file]);
|
||||
|
||||
var locales;
|
||||
if (entryPoint) {
|
||||
locales = manifest.entry_points[entryPoint].locales;
|
||||
} else {
|
||||
locales = manifest.locales;
|
||||
}
|
||||
|
||||
if (!locales) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (locale.indexOf('-x-ps') > -1) {
|
||||
return this.client.executeScript(function(locale, name) {
|
||||
var mozL10n = window.wrappedJSObject.navigator.mozL10n;
|
||||
return mozL10n.qps[locale].translate(name);
|
||||
}, [locale, locales['en-US'].name]);
|
||||
}
|
||||
|
||||
return locales[locale].name;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a localized string from a properties file.
|
||||
* @param {String} key of the string to lookup.
|
||||
*/
|
||||
l10n: function(key) {
|
||||
var string = this.client.executeScript(function(key) {
|
||||
return window.wrappedJSObject.navigator.mozL10n.get(key);
|
||||
}, [key]);
|
||||
|
||||
return string;
|
||||
},
|
||||
|
||||
containsClass: function(selector, clazz) {
|
||||
return this.client.executeScript(function(selector, clazz) {
|
||||
return document.querySelector(selector).classList.contains(clazz);
|
||||
}, [selector, clazz]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper function to move an icon to a specified index. Currently uses
|
||||
* executeScript() and manually fiddles with the homescreen grid logic,
|
||||
* this is because scripted drag/drop does not work too well within the
|
||||
* vertically scrolling homescreen on b2g desktop.
|
||||
* @param {Element} icon The grid icon object.
|
||||
* @param {Integer} index The position to insert the icon into.
|
||||
*/
|
||||
moveIconToIndex: function(icon, index) {
|
||||
this.client.executeScript(function(identifier, newPos) {
|
||||
var app = window.wrappedJSObject.app;
|
||||
var icon = app.grid.getIcon(identifier);
|
||||
app.grid.moveTo(icon.detail.index, newPos);
|
||||
app.grid.render();
|
||||
}, [icon.getAttribute('data-identifier'), index]);
|
||||
|
||||
// Wait for the icon to animate into place
|
||||
var actions = this.client.loader.getActions();
|
||||
actions.wait(1).perform();
|
||||
},
|
||||
|
||||
/**
|
||||
* Opens the context menu by long-pressing on the first available placeholder.
|
||||
* If there is no placeholder, the first icon will be dragged to the top of
|
||||
* the grid to create a new group, and thus new placeholders.
|
||||
*/
|
||||
openContextMenu: function() {
|
||||
var actions = this.client.loader.getActions();
|
||||
var body = this.client.findElement('body');
|
||||
actions.longPress(body, 1).perform();
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = VerticalHome;
|
||||
67
gaia/apps/verticalhome/test/marionette/localization_test.js
Executable file
67
gaia/apps/verticalhome/test/marionette/localization_test.js
Executable file
|
|
@ -0,0 +1,67 @@
|
|||
'use strict';
|
||||
var assert = require('assert');
|
||||
|
||||
marionette('Vertical - Localization', function() {
|
||||
|
||||
var client = marionette.client({
|
||||
profile: require(__dirname + '/client_options.js')
|
||||
});
|
||||
var actions, home, system;
|
||||
|
||||
setup(function() {
|
||||
actions = client.loader.getActions();
|
||||
home = client.loader.getAppClass('verticalhome');
|
||||
system = client.loader.getAppClass('system');
|
||||
system.waitForFullyLoaded();
|
||||
home.waitForLaunch();
|
||||
});
|
||||
|
||||
test('Localization updates icon names', function() {
|
||||
var settingsManifestUrl = 'app://settings.gaiamobile.org/manifest.webapp';
|
||||
var settingsIcon = home.getIcon(settingsManifestUrl);
|
||||
assert.equal(
|
||||
settingsIcon.text(),
|
||||
home.localizedAppName('settings', 'en-US'));
|
||||
|
||||
client.executeScript(function() {
|
||||
navigator.mozSettings.createLock().set({
|
||||
'language.current': 'fr-x-psaccent'
|
||||
});
|
||||
});
|
||||
|
||||
// Localization can be async, wait for the content to update
|
||||
client.waitFor(function() {
|
||||
settingsIcon = home.getIcon(settingsManifestUrl);
|
||||
return settingsIcon.text() ===
|
||||
home.localizedAppName('settings', 'fr-x-psaccent');
|
||||
});
|
||||
});
|
||||
|
||||
test('Menu option localization', function() {
|
||||
var selectors = home.Selectors;
|
||||
|
||||
// Change the language to french
|
||||
client.executeAsyncScript(function() {
|
||||
var req = navigator.mozSettings.createLock().set({
|
||||
'language.current': 'fr-x-psaccent'
|
||||
});
|
||||
|
||||
req.onsuccess = function() {
|
||||
marionetteScriptFinished();
|
||||
};
|
||||
});
|
||||
|
||||
home.openContextMenu();
|
||||
|
||||
// Element.text() does not return the content of the shadow dom,
|
||||
// so enter the shadow dom manually for now to get the text.
|
||||
var expected = home.l10n('cancel');
|
||||
client.waitFor(function(){
|
||||
var menu = client.helper.waitForElement(selectors.contextmenu);
|
||||
var content = menu.scriptWith(function(menu) {
|
||||
return menu.shadowRoot.querySelector('button').innerHTML;
|
||||
});
|
||||
return content === expected;
|
||||
});
|
||||
});
|
||||
});
|
||||
55
gaia/apps/verticalhome/test/marionette/search_string_test.js
Executable file
55
gaia/apps/verticalhome/test/marionette/search_string_test.js
Executable file
|
|
@ -0,0 +1,55 @@
|
|||
/* global __dirname */
|
||||
|
||||
'use strict';
|
||||
|
||||
var Rocketbar = require(
|
||||
'../../../../apps/system/test/marionette/lib/rocketbar.js');
|
||||
var Server = require('../../../../shared/test/integration/server');
|
||||
|
||||
marionette('Vertical - Search Terms: URI scheme', function() {
|
||||
|
||||
var client = marionette.client({
|
||||
profile: require(__dirname + '/client_options.js'),
|
||||
desiredCapabilities: { raisesAccessibilityExceptions: false }
|
||||
});
|
||||
var home, rocketbar, search, system, server;
|
||||
|
||||
suiteSetup(function(done) {
|
||||
Server.create(__dirname + '/fixtures/', function(err, _server) {
|
||||
server = _server;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
server.stop();
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
home = client.loader.getAppClass('verticalhome');
|
||||
search = client.loader.getAppClass('search');
|
||||
rocketbar = new Rocketbar(client);
|
||||
system = client.loader.getAppClass('system');
|
||||
system.waitForFullyLoaded();
|
||||
});
|
||||
|
||||
function searchAndVerifyBrowser(searchTerms) {
|
||||
var searchUrl = server.url('search.html') + '?q={searchTerms}';
|
||||
client.settings.set('search.urlTemplate', searchUrl);
|
||||
|
||||
// Lauch the rocketbar and trigger its first run notice
|
||||
home.waitForLaunch();
|
||||
home.focusRocketBar();
|
||||
search.triggerFirstRun(rocketbar);
|
||||
|
||||
rocketbar.enterText(searchTerms + '\uE006');
|
||||
|
||||
// Ensure the browser is launched
|
||||
rocketbar.switchToBrowserFrame(searchTerms);
|
||||
}
|
||||
|
||||
test('Testing URI Scheme - DATA:', function() {
|
||||
searchAndVerifyBrowser('data:text/html, <html>Hello World</html>');
|
||||
});
|
||||
|
||||
});
|
||||
315
gaia/apps/verticalhome/test/marionette/server/child.js
Executable file
315
gaia/apps/verticalhome/test/marionette/server/child.js
Executable file
|
|
@ -0,0 +1,315 @@
|
|||
/* global Buffer, process */
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
App server for fixtures. Serves up packaged apps.
|
||||
*/
|
||||
|
||||
|
||||
var debug = require('debug')('appserver:child');
|
||||
var http = require('http');
|
||||
var fs = require('fs');
|
||||
var fsPath = require('path');
|
||||
var mime = require('mime');
|
||||
var archiver = require('archiver');
|
||||
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
|
||||
function readdirRecursive(dir) {
|
||||
dir = fsPath.join(dir, '/');
|
||||
var results = [];
|
||||
var files = fs.readdirSync(dir);
|
||||
|
||||
var file;
|
||||
while((file = files.shift())) {
|
||||
file = fsPath.join(dir, file);
|
||||
var stat = fs.statSync(file);
|
||||
if (stat.isDirectory()) {
|
||||
results = results.concat(readdirRecursive(file));
|
||||
} else {
|
||||
results.push(file);
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
function writeJSON(res, object) {
|
||||
var json = JSON.stringify(object);
|
||||
res.writeHead(200, {
|
||||
'Content-Length': Buffer.byteLength(json),
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
res.end(json);
|
||||
}
|
||||
|
||||
function decorateHandlerForJSON(method) {
|
||||
return function(req, res) {
|
||||
// if it is not json just skip it
|
||||
var type = req.headers['content-type'];
|
||||
if (!type || type.indexOf('json') === -1) {
|
||||
return method.call(this, req, res);
|
||||
}
|
||||
|
||||
var buffer = '';
|
||||
req.on('data', function(data) {
|
||||
buffer += data;
|
||||
});
|
||||
|
||||
req.once('end', function() {
|
||||
req.body = JSON.parse(buffer);
|
||||
method.call(this, req, res);
|
||||
}.bind(this));
|
||||
};
|
||||
}
|
||||
|
||||
function defaultSettings() {
|
||||
return {
|
||||
corked: false,
|
||||
fail: false
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} root directory where content is.@
|
||||
* @param {Object} routes for the app server.
|
||||
* @constructor
|
||||
*/
|
||||
function AppServer(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 = {};
|
||||
}
|
||||
|
||||
AppServer.prototype = {
|
||||
__proto__: EventEmitter.prototype,
|
||||
|
||||
/**
|
||||
* @return {Object} default settings for a given url.
|
||||
*/
|
||||
settings: function(url) {
|
||||
return (this._settings[url] = this._settings[url] || defaultSettings());
|
||||
},
|
||||
|
||||
requestHandler: function() {
|
||||
var routes = this.routes;
|
||||
return function(req, res) {
|
||||
debug('request', req.method, req.url);
|
||||
var handler = routes[req.url] || routes['*'];
|
||||
var settings = this.settings(req.url);
|
||||
|
||||
// If this url has a http error on it just return without calling the
|
||||
// handler.
|
||||
if (settings.response) {
|
||||
res.writeHead(settings.response.status, settings.response.headers);
|
||||
res.end(settings.response.body);
|
||||
return;
|
||||
}
|
||||
|
||||
// routes are always invoked with the context of the app server.
|
||||
return handler.call(this, req, res);
|
||||
}.bind(this);
|
||||
},
|
||||
};
|
||||
|
||||
var routes = {
|
||||
|
||||
/**
|
||||
Change the root serving directory for this server.
|
||||
*/
|
||||
'/settings/set_root': decorateHandlerForJSON(function(req, res) {
|
||||
this.root = req.body;
|
||||
writeJSON(res, req.body);
|
||||
}),
|
||||
|
||||
/**
|
||||
Override or set the response of a particular url.
|
||||
*/
|
||||
'/settings/set_response': decorateHandlerForJSON(function(req, res) {
|
||||
var options = req.body;
|
||||
var settings = this.settings(options.path);
|
||||
|
||||
settings.response = options;
|
||||
writeJSON(res, options.path);
|
||||
}),
|
||||
|
||||
/**
|
||||
Clear the response override.
|
||||
*/
|
||||
'/settings/clear_response': decorateHandlerForJSON(function(req, res) {
|
||||
var url = req.body;
|
||||
var settings = this.settings(url);
|
||||
delete settings.response;
|
||||
writeJSON(res, url);
|
||||
}),
|
||||
|
||||
/**
|
||||
A 'corked' request will send headers but no body until 'uncork' is used.
|
||||
*/
|
||||
'/settings/cork': decorateHandlerForJSON(function(req, res) {
|
||||
var url = req.body;
|
||||
var settings = this.settings(url);
|
||||
settings.corked = true;
|
||||
|
||||
// issue a cork to the particular endpoint
|
||||
var event = 'corked ' + url;
|
||||
debug('cork event', event);
|
||||
this.emit('corked ' + url);
|
||||
writeJSON(res, url);
|
||||
}),
|
||||
|
||||
/**
|
||||
The inverse of 'cork' will uncork a uri and send the body through.
|
||||
*/
|
||||
'/settings/uncork': decorateHandlerForJSON(function(req, res) {
|
||||
var url = req.body;
|
||||
var settings = this.settings(url);
|
||||
settings.corked = false;
|
||||
|
||||
var event = 'uncorked ' + url;
|
||||
debug('uncork event', event);
|
||||
this.emit(event);
|
||||
writeJSON(res, url);
|
||||
}),
|
||||
|
||||
/**
|
||||
Fail is a combination of 'cork' and a flag which will cause the incoming http
|
||||
request to be closed after a short delay.
|
||||
*/
|
||||
'/settings/fail': decorateHandlerForJSON(function(req, res) {
|
||||
var url = req.body;
|
||||
var settings = this.settings(url);
|
||||
|
||||
// must be corked to ensure we don't send the body
|
||||
settings.corked = true;
|
||||
settings.fail = true;
|
||||
writeJSON(res, url);
|
||||
}),
|
||||
|
||||
/**
|
||||
The inverse to fail but unlike uncork this cannot be called in the middle of
|
||||
a request (for obvious reasons).
|
||||
*/
|
||||
'/settings/unfail': decorateHandlerForJSON(function(req, res) {
|
||||
var url = req.body;
|
||||
var settings = this.settings(url);
|
||||
|
||||
settings.fail = settings.corked = false;
|
||||
writeJSON(res, url);
|
||||
}),
|
||||
|
||||
'/package.manifest': function(req, res) {
|
||||
var json = JSON.parse(fs.readFileSync(this.root + '/manifest.webapp'));
|
||||
json.package_path = 'http://' + req.headers.host + '/app.zip';
|
||||
// TODO: Remove this once we add the ability to override requests
|
||||
delete json.role;
|
||||
|
||||
var body = JSON.stringify(json, null, 2);
|
||||
res.writeHead(200, {
|
||||
'Content-Length': Buffer.byteLength(body),
|
||||
'Content-Type': 'application/x-web-app-manifest+json'
|
||||
});
|
||||
res.end(body);
|
||||
},
|
||||
|
||||
'/app.zip': function(req, res) {
|
||||
var url = req.url;
|
||||
var settings = this.settings(url);
|
||||
// always write the head we need it in all cases
|
||||
res.writeHead(200, {
|
||||
'Content-Type': 'application/zip'
|
||||
});
|
||||
|
||||
var root = this.root;
|
||||
function writeZip() {
|
||||
// read the entire app directory
|
||||
var files = readdirRecursive(root);
|
||||
var zip = archiver.create('zip');
|
||||
|
||||
files.forEach(function(file) {
|
||||
debug('packaged app zip file', file);
|
||||
var zipPath = file.replace(root, '');
|
||||
zip.append(fs.createReadStream(file), { name: zipPath });
|
||||
});
|
||||
zip.finalize();
|
||||
zip.pipe(res);
|
||||
}
|
||||
|
||||
if (settings.fail) {
|
||||
process.nextTick(function() {
|
||||
req.socket.destroy();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// if we are not corked just write the zip and we are done
|
||||
if (!settings.corked) {
|
||||
return writeZip();
|
||||
} else {
|
||||
this.once('uncorked ' + url, writeZip);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
Catch all handler which serves up static assets.
|
||||
*/
|
||||
'*': function(req, res) {
|
||||
var url = req.url;
|
||||
var settings = this.settings(url);
|
||||
var filePath = fsPath.join(this.root, url);
|
||||
|
||||
// XXX: This is not a production quality server don't use sync methods in
|
||||
// in servers in your user facing node code.
|
||||
if (!fs.existsSync(filePath)) {
|
||||
res.writeHead(404);
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
var contentType = mime.lookup(filePath);
|
||||
var contentLength = fs.statSync(filePath).size;
|
||||
debug('static asset', filePath, contentType, contentLength);
|
||||
|
||||
// write out the head
|
||||
res.writeHead(200, {
|
||||
'Content-Type': contentType,
|
||||
'Content-Length': contentLength
|
||||
});
|
||||
|
||||
function writeContent() {
|
||||
fs.createReadStream(filePath).pipe(res);
|
||||
}
|
||||
|
||||
if (settings.fail) {
|
||||
process.nextTick(function() {
|
||||
req.socket.destroy();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!settings.corked) {
|
||||
// if we are not corked just return the stream
|
||||
return writeContent();
|
||||
} else {
|
||||
// otherwise wait for the uncork
|
||||
this.once('uncorked ' + url, writeContent);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var port = parseInt((process.argv[3] || 0), 10);
|
||||
var appServer = new AppServer(process.argv[2], routes);
|
||||
var server = http.createServer(appServer.requestHandler());
|
||||
|
||||
server.listen(port, function() {
|
||||
if (process.send) {
|
||||
process.send({ type: 'started', port: server.address().port });
|
||||
}
|
||||
});
|
||||
74
gaia/apps/verticalhome/test/marionette/server/cli.js
Executable file
74
gaia/apps/verticalhome/test/marionette/server/cli.js
Executable file
|
|
@ -0,0 +1,74 @@
|
|||
/* global process, __dirname */
|
||||
'use strict';
|
||||
|
||||
// server cli stuff
|
||||
var fork = require('child_process').fork;
|
||||
var fs = require('fs');
|
||||
var fsPath = require('path');
|
||||
|
||||
function exit() {
|
||||
console.error();
|
||||
console.error.apply(console, arguments);
|
||||
commandHelp(console.error);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
function commandHelp(log) {
|
||||
log = log || console.log;
|
||||
|
||||
log();
|
||||
log(' App server cli');
|
||||
log();
|
||||
log(' Comamnds: ');
|
||||
log();
|
||||
log(' help - Your looking at it');
|
||||
log(' interactive <directory> [port] - ' +
|
||||
'Begin an interactive session with the app server');
|
||||
log();
|
||||
}
|
||||
|
||||
function commandInteractive(directory, port) {
|
||||
port = parseInt((port || 60234), 10);
|
||||
|
||||
if (!directory) {
|
||||
return exit('Directory must be given');
|
||||
}
|
||||
|
||||
directory = fsPath.resolve(directory);
|
||||
|
||||
if (!fs.existsSync(directory)) {
|
||||
return exit('Given app directory "%s" does not exist', directory);
|
||||
}
|
||||
|
||||
// start the server up
|
||||
console.log('Starting server...');
|
||||
|
||||
function onError(e) {
|
||||
exit('server process failed to start: ', e);
|
||||
}
|
||||
|
||||
var proc = fork(__dirname + '/child.js', [directory, port]);
|
||||
proc.once('error', onError);
|
||||
proc.on('message', function(msg) {
|
||||
if (msg.type !== 'started') {
|
||||
return;
|
||||
}
|
||||
proc.removeListener('error', onError);
|
||||
|
||||
var interactive = require('./cli/interactive');
|
||||
interactive(proc, 'http://localhost:' + msg.port + '/');
|
||||
});
|
||||
}
|
||||
|
||||
switch (process.argv[2]) {
|
||||
case 'interactive':
|
||||
commandInteractive(process.argv[3]);
|
||||
break;
|
||||
|
||||
case 'help':
|
||||
commandHelp();
|
||||
break;
|
||||
|
||||
default:
|
||||
commandHelp();
|
||||
}
|
||||
175
gaia/apps/verticalhome/test/marionette/server/cli/interactive.js
Executable file
175
gaia/apps/verticalhome/test/marionette/server/cli/interactive.js
Executable file
|
|
@ -0,0 +1,175 @@
|
|||
/* global process, Buffer, module */
|
||||
'use strict';
|
||||
var http = require('http');
|
||||
var url = require('url');
|
||||
|
||||
function Interactive(serverProc, url, commands) {
|
||||
this.server = serverProc;
|
||||
this.url = url;
|
||||
this.stream = process.stdin;
|
||||
this.commands = commands;
|
||||
}
|
||||
|
||||
Interactive.prototype = {
|
||||
|
||||
help: function() {
|
||||
console.log(' Commands: ');
|
||||
console.log();
|
||||
Object.keys(this.commands).forEach(function(command) {
|
||||
var desc = this.commands[command].description;
|
||||
console.log(' %s - %s', command, desc);
|
||||
}, this);
|
||||
console.log();
|
||||
},
|
||||
|
||||
get: function(uri) {
|
||||
var req = http.get(this.url + uri);
|
||||
console.log('>> GET ' + uri);
|
||||
|
||||
req.once('response', function(res) {
|
||||
console.log(' response %s [%s]', uri, res.statusCode);
|
||||
for (var key in res.headers) {
|
||||
console.log(' response header %s : %s', key, res.headers[key]);
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
post: function(uri, body, callback) {
|
||||
var json = JSON.stringify(body);
|
||||
|
||||
var options = url.parse(this.url + uri);
|
||||
options.method = 'POST';
|
||||
var req = http.request(options);
|
||||
req.setHeader('Content-Length', Buffer.byteLength(json));
|
||||
req.setHeader('Content-Type', 'application/json');
|
||||
|
||||
req.once('response', function(res) {
|
||||
var data = '';
|
||||
res.on('data', function(buffer) {
|
||||
data += buffer;
|
||||
});
|
||||
|
||||
res.once('end', function() {
|
||||
callback(null, JSON.parse(data));
|
||||
});
|
||||
});
|
||||
|
||||
req.end(json);
|
||||
},
|
||||
|
||||
onReadable: function() {
|
||||
var stream = this.stream;
|
||||
|
||||
var content = stream.read();
|
||||
// noting to read return...
|
||||
if (!content) {
|
||||
return;
|
||||
}
|
||||
|
||||
// read until we have a newline
|
||||
if (content.indexOf('\n') === -1) {
|
||||
stream.unshift(content);
|
||||
return;
|
||||
}
|
||||
|
||||
// ignore blank lines
|
||||
if (content.trim() === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
// the first word is the command parse it out...
|
||||
var commandParts = content.split(' ').map(function(part) {
|
||||
return part.trim();
|
||||
});
|
||||
|
||||
var commandName = commandParts.shift();
|
||||
var command = this.commands[commandName];
|
||||
|
||||
if (!command) {
|
||||
console.error(commandName, ' is not a recognized command');
|
||||
return this.help();
|
||||
}
|
||||
|
||||
command.handler.apply(this, commandParts);
|
||||
},
|
||||
|
||||
start: function() {
|
||||
// don't stop reading from stdin
|
||||
this.stream.setEncoding('utf8');
|
||||
this.stream.on('readable', this.onReadable.bind(this));
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
var commands = {
|
||||
help: {
|
||||
description: 'Shows all commands',
|
||||
handler: function() { this.help(); }
|
||||
},
|
||||
|
||||
cork: {
|
||||
description: '<uri> Cork a particular url',
|
||||
handler: function(uri) {
|
||||
// leading slash for consistency with get
|
||||
this.post('settings/cork', '/' + uri, function(err, body) {
|
||||
console.log('corked : %s', body);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
uncork: {
|
||||
description: '<uri> uncork a particular uri',
|
||||
handler: function(uri) {
|
||||
// leading slash for consistency with get
|
||||
this.post('settings/uncork', '/' + uri, function(err, body) {
|
||||
console.log('uncorked : %s', body);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
fail: {
|
||||
description: '<uri> Cause a particular url to fail',
|
||||
handler: function(uri) {
|
||||
// leading slash for consistency with get
|
||||
this.post('settings/fail', '/' + uri, function(err, body) {
|
||||
console.log('failed: %s', body);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
unfail: {
|
||||
description: '<uri> remove failng status from particular url',
|
||||
handler: function(uri) {
|
||||
// leading slash for consistency with get
|
||||
this.post('settings/unfail', '/' + uri, function(err, body) {
|
||||
console.log('unfail: %s', body);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
get: {
|
||||
description: '<uri> Issue a http get an show the body',
|
||||
handler: function(uri) {
|
||||
this.get(uri);
|
||||
}
|
||||
},
|
||||
|
||||
url: {
|
||||
description: 'display the server url',
|
||||
handler: function() {
|
||||
console.log(this.url);
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
function main(process, url) {
|
||||
var handler = new Interactive(process, url, commands);
|
||||
handler.start();
|
||||
|
||||
process.once('SIGINT', function() {
|
||||
process.stderr.write('Shutting down...\n');
|
||||
process.exit();
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = main;
|
||||
187
gaia/apps/verticalhome/test/marionette/server/parent.js
Executable file
187
gaia/apps/verticalhome/test/marionette/server/parent.js
Executable file
|
|
@ -0,0 +1,187 @@
|
|||
'use strict';
|
||||
/* global module, __dirname */
|
||||
var fork = require('child_process').fork;
|
||||
|
||||
/**
|
||||
* Issue a POST request via marionette.
|
||||
*/
|
||||
function post(client, url, 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 AppServer(root, marionette, port, proc) {
|
||||
this.root = root;
|
||||
this.marionette = marionette;
|
||||
this.url = 'http://localhost:' + port;
|
||||
this.process = proc;
|
||||
}
|
||||
|
||||
AppServer.prototype = {
|
||||
|
||||
/**
|
||||
issues a GET request to the server and returns the parsed body.
|
||||
*/
|
||||
get: function(uri) {
|
||||
// must run in chrome so we can do cross domain xhr
|
||||
var client = this.marionette.scope({ context: 'chrome' });
|
||||
|
||||
return client.executeAsyncScript(function(url) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', url, true);
|
||||
xhr.onload = function() {
|
||||
marionetteScriptFinished(xhr.response);
|
||||
};
|
||||
xhr.send();
|
||||
}, [this.url + uri]);
|
||||
},
|
||||
|
||||
/**
|
||||
Changes the root of the server.
|
||||
|
||||
@param {String} path relative to the file system.
|
||||
*/
|
||||
setRoot: function(path) {
|
||||
return post(this.marionette, this.url + '/settings/set_root', path);
|
||||
},
|
||||
|
||||
/**
|
||||
Set the http response of a particular url.
|
||||
|
||||
@param {String} path to set the response of.
|
||||
@param {Number} status code to set.
|
||||
@param {Object} headers to override.
|
||||
@param {String} body of the request.
|
||||
*/
|
||||
setResponse: function(path, status, headers, body) {
|
||||
var options = {
|
||||
path: path,
|
||||
status: status,
|
||||
headers: headers || {},
|
||||
body: body
|
||||
};
|
||||
|
||||
return post(this.marionette, this.url + '/settings/set_response', options);
|
||||
},
|
||||
|
||||
/**
|
||||
Clear the response override set by `setResponse`
|
||||
*/
|
||||
clearResponse: function(url) {
|
||||
return post(
|
||||
this.marionette, this.url + '/settings/clear_response', url
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
Trigger a 500 error for a particular url and return an empty body.
|
||||
|
||||
@param {String} url to fail (/index.html).
|
||||
*/
|
||||
serverError: function(url) {
|
||||
return this.setResponse(url, 500, {}, '');
|
||||
},
|
||||
|
||||
/**
|
||||
Clears the server error for a particular url.
|
||||
|
||||
@param {String} url to fail (/index.html).
|
||||
*/
|
||||
clearServerError: function(url) {
|
||||
return this.clearResponse();
|
||||
},
|
||||
|
||||
/**
|
||||
Indicate to the server that all requests to the given url should be
|
||||
given a response with headers but then the socket should be closed shortly
|
||||
after that time.
|
||||
|
||||
@param {String} url to ban (/index.html).
|
||||
*/
|
||||
fail: function(url) {
|
||||
return post(this.marionette, this.url + '/settings/fail', url);
|
||||
},
|
||||
|
||||
/**
|
||||
Allow requests to the given url to proceed without failure after calling
|
||||
`.fail`.
|
||||
|
||||
@param {String} url to unban.
|
||||
*/
|
||||
unfail: function(url) {
|
||||
return post(this.marionette, this.url + '/settings/unfail', url);
|
||||
},
|
||||
|
||||
/**
|
||||
Cork the response body of the given url while allowing headers.
|
||||
|
||||
@param {String} url to cork.
|
||||
*/
|
||||
cork: function(url) {
|
||||
return post(this.marionette, this.url + '/settings/cork', url);
|
||||
},
|
||||
|
||||
/**
|
||||
Allow the body to be sent after calling `.cork`.
|
||||
|
||||
@param {String} url to uncork.
|
||||
*/
|
||||
uncork: function(url) {
|
||||
return post(this.marionette, this.url + '/settings/uncork', url);
|
||||
},
|
||||
|
||||
close: function(callback) {
|
||||
this.process.kill();
|
||||
this.process.once('exit', callback.bind(this, null));
|
||||
},
|
||||
|
||||
get manifest() {
|
||||
return JSON.parse(this.get('/manifest.webapp'));
|
||||
},
|
||||
|
||||
/**
|
||||
URI where the application zip lives this defined in child.js
|
||||
*/
|
||||
get applicationZipUri() {
|
||||
return '/app.zip';
|
||||
},
|
||||
|
||||
get manifestURL() {
|
||||
return this.url + '/manifest.webapp';
|
||||
},
|
||||
|
||||
get packageManifestURL() {
|
||||
return this.url + '/package.manifest';
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a app server for use in marionette tests.
|
||||
*
|
||||
* @param {String} appRoot path to the root of the app.
|
||||
* @param {Marionette.Client} client for marionette.
|
||||
* @param {Function} callback [Error]
|
||||
*/
|
||||
module.exports = function create(appRoot, client, callback) {
|
||||
var proc = fork(__dirname + '/child.js', [appRoot]);
|
||||
|
||||
proc.once('error', callback);
|
||||
proc.on('message', function(msg) {
|
||||
if (msg.type !== 'started') {
|
||||
return;
|
||||
}
|
||||
proc.removeListener('error', callback);
|
||||
callback(null, new AppServer(appRoot, client, msg.port, proc));
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.AppServer;
|
||||
19
gaia/apps/verticalhome/test/unit/.jshintrc
Executable file
19
gaia/apps/verticalhome/test/unit/.jshintrc
Executable file
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"extends": "../../../../.jshintrc",
|
||||
"predef": [
|
||||
"assert",
|
||||
"suite",
|
||||
"test",
|
||||
"setup",
|
||||
"teardown",
|
||||
"suiteSetup",
|
||||
"suiteTeardown",
|
||||
"suiteTemplate",
|
||||
"require",
|
||||
"requireApp",
|
||||
"requireElements",
|
||||
"sinon",
|
||||
"mocha",
|
||||
"loadBodyHTML"
|
||||
]
|
||||
}
|
||||
54
gaia/apps/verticalhome/test/unit/app_manager_test.js
Executable file
54
gaia/apps/verticalhome/test/unit/app_manager_test.js
Executable file
|
|
@ -0,0 +1,54 @@
|
|||
'use strict';
|
||||
/* global loadBodyHTML, MockNavigatormozApps, appManager, MockL10n */
|
||||
|
||||
require('/shared/test/unit/mocks/mock_navigator_moz_apps.js');
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
require('/shared/test/unit/load_body_html_helper.js');
|
||||
require('/shared/js/component_utils.js');
|
||||
require('/shared/elements/gaia_confirm/script.js');
|
||||
require('/shared/js/homescreens/confirm_dialog_helper.js');
|
||||
|
||||
suite('app_manager.js > ', function() {
|
||||
|
||||
var realMozApps = null,
|
||||
realL10n = null,
|
||||
app = {};
|
||||
|
||||
suiteSetup(function(done) {
|
||||
loadBodyHTML('/index.html');
|
||||
realMozApps = navigator.mozApps;
|
||||
navigator.mozApps = MockNavigatormozApps;
|
||||
realL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockL10n;
|
||||
require('/js/app_manager.js', done);
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozApps = realMozApps;
|
||||
MockNavigatormozApps.mTeardown();
|
||||
navigator.mozL10n = realL10n;
|
||||
realL10n = realMozApps = null;
|
||||
});
|
||||
|
||||
test('The library was initialized properly', function() {
|
||||
MockNavigatormozApps.mTriggerLastRequestSuccess(app);
|
||||
assert.equal(appManager.self, app);
|
||||
});
|
||||
|
||||
test('Can\'t show delete dialog more than once', function() {
|
||||
var showDialogSpy = sinon.spy();
|
||||
sinon.stub(window, 'ConfirmDialogHelper').returns({ show: showDialogSpy });
|
||||
|
||||
var removeItemEvent = new CustomEvent('removeitem',
|
||||
{ detail:
|
||||
{ detail: { type: null } }
|
||||
});
|
||||
|
||||
appManager.handleEvent(removeItemEvent);
|
||||
assert(appManager.dialogVisible);
|
||||
|
||||
appManager.handleEvent(removeItemEvent);
|
||||
assert(showDialogSpy.calledOnce);
|
||||
});
|
||||
|
||||
});
|
||||
122
gaia/apps/verticalhome/test/unit/app_test.js
Executable file
122
gaia/apps/verticalhome/test/unit/app_test.js
Executable file
|
|
@ -0,0 +1,122 @@
|
|||
'use strict';
|
||||
/* global app */
|
||||
/* global MocksHelper, loadBodyHTML */
|
||||
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
require('/shared/test/unit/mocks/mock_settings_listener.js');
|
||||
require('/shared/test/unit/load_body_html_helper.js');
|
||||
require('/shared/elements/gaia_grid/js/grid_dragdrop.js');
|
||||
require('/shared/elements/gaia_grid/js/grid_icon_renderer.js');
|
||||
require('/shared/elements/gaia_grid/js/grid_layout.js');
|
||||
require('/shared/elements/gaia_grid/js/grid_view.js');
|
||||
require('/shared/elements/gaia_grid/script.js');
|
||||
require('/shared/elements/gaia_grid/js/items/grid_item.js');
|
||||
require('/shared/elements/gaia_grid/js/items/divider.js');
|
||||
require('/shared/elements/gaia_grid/js/items/placeholder.js');
|
||||
require('/test/unit/mock_item_store.js');
|
||||
|
||||
var mocksHelperForApp = new MocksHelper([
|
||||
'LazyLoader',
|
||||
'ItemStore',
|
||||
'SettingsListener'
|
||||
]).init();
|
||||
|
||||
suite('app.js > ', function() {
|
||||
|
||||
mocksHelperForApp.attachTestHelpers();
|
||||
|
||||
var raf, scrollStub;
|
||||
var documentHiddenValue = false;
|
||||
|
||||
suiteSetup(function() {
|
||||
Object.defineProperty(document, 'hidden', {
|
||||
configurable: true,
|
||||
get: function() {
|
||||
return documentHiddenValue;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
setup(function(done) {
|
||||
raf = sinon.stub(window, 'requestAnimationFrame',
|
||||
function(callback) { callback(); });
|
||||
scrollStub = sinon.stub(window, 'scrollTo');
|
||||
loadBodyHTML('/index.html');
|
||||
var grid = document.querySelector('gaia-grid')._grid;
|
||||
// Some features are loaded after rendering like dragdrop
|
||||
grid.render();
|
||||
require('/js/app.js', done);
|
||||
this.sinon.useFakeTimers();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
raf.restore();
|
||||
scrollStub.restore();
|
||||
documentHiddenValue = false;
|
||||
});
|
||||
|
||||
test('Scrolls on hashchange', function() {
|
||||
window.scrollY = 100000;
|
||||
window.dispatchEvent(new CustomEvent('hashchange'));
|
||||
|
||||
assert.ok(scrollStub.called);
|
||||
});
|
||||
|
||||
test('Scrolls on gaiagrid-attention', function() {
|
||||
window.scrollY = 100000;
|
||||
app.grid.dispatchEvent(
|
||||
new CustomEvent('gaiagrid-attention', {detail: {y: 0, height: 0}}));
|
||||
assert.ok(scrollStub.called);
|
||||
});
|
||||
|
||||
test('No scrolling while context menu is displayed', function() {
|
||||
window.dispatchEvent(new CustomEvent('context-menu-open'));
|
||||
window.dispatchEvent(new CustomEvent('hashchange'));
|
||||
assert.isFalse(raf.called);
|
||||
window.dispatchEvent(new CustomEvent('context-menu-close'));
|
||||
});
|
||||
|
||||
test('Transition property in edit-mode', function() {
|
||||
app.grid.dispatchEvent(new CustomEvent('editmode-start'));
|
||||
assert.equal(app.grid.style.transition, app.EDIT_MODE_TRANSITION_STYLE);
|
||||
|
||||
app.grid.dispatchEvent(new CustomEvent('editmode-end'));
|
||||
assert.equal(app.grid.style.transition, '');
|
||||
});
|
||||
|
||||
test('Hashchange event without dragdrop', function() {
|
||||
var oldDragdrop = app.grid._grid.dragdrop;
|
||||
app.grid._grid.dragdrop = undefined;
|
||||
app.handleEvent({type: 'hashchange'});
|
||||
app.grid._grid.dragdrop = oldDragdrop;
|
||||
// This test was added for bug 1051061. If the test passes it means that
|
||||
// the test did not throw an error and that bug is not a problem.
|
||||
// No assertion is needed.
|
||||
});
|
||||
|
||||
suite('When the homescreen is hidden', function() {
|
||||
setup(function() {
|
||||
documentHiddenValue = true;
|
||||
document.dispatchEvent(new CustomEvent('visibilitychange'));
|
||||
});
|
||||
|
||||
test('should hide the overflow to prevent displayport rendering',
|
||||
function() {
|
||||
assert.equal(document.body.style.overflow, 'hidden');
|
||||
});
|
||||
|
||||
suite('then displayed again',function() {
|
||||
setup(function() {
|
||||
documentHiddenValue = false;
|
||||
document.dispatchEvent(new CustomEvent('visibilitychange'));
|
||||
});
|
||||
|
||||
test('should let the homescreen scroll after a tick', function() {
|
||||
assert.equal(document.body.style.overflow, 'hidden');
|
||||
this.sinon.clock.tick();
|
||||
assert.equal(document.body.style.overflow, '');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
370
gaia/apps/verticalhome/test/unit/configurator_test.js
Executable file
370
gaia/apps/verticalhome/test/unit/configurator_test.js
Executable file
|
|
@ -0,0 +1,370 @@
|
|||
'use strict';
|
||||
|
||||
/* global Configurator, MockNavigatorSettings, IccHelper,
|
||||
MocksHelper, MockVersionHelper, verticalPreferences,
|
||||
MockNavigatorGetFeature, LazyLoader */
|
||||
|
||||
require('/shared/js/homescreens/vertical_preferences.js');
|
||||
require('/shared/test/unit/mocks/mock_navigator_moz_settings.js');
|
||||
require('/shared/test/unit/mocks/mock_navigator_get_feature.js');
|
||||
require('/shared/test/unit/mocks/mock_icc_helper.js');
|
||||
require('/test/unit/mock_version_helper.js');
|
||||
require('/shared/js/lazy_loader.js');
|
||||
|
||||
var mocksHelperForConfigurator = new MocksHelper([
|
||||
'VersionHelper',
|
||||
'IccHelper'
|
||||
]).init();
|
||||
|
||||
suite('configurator.js >', function() {
|
||||
mocksHelperForConfigurator.attachTestHelpers();
|
||||
|
||||
var realGetFeature;
|
||||
var realMozSettings;
|
||||
var requests = [];
|
||||
var configurator;
|
||||
|
||||
var confGridOK = {
|
||||
'preferences': {},
|
||||
'prediction': {
|
||||
'enabled': true,
|
||||
'lookahead': 16
|
||||
},
|
||||
'grid': [
|
||||
[
|
||||
{
|
||||
'entry_point': 'dialer',
|
||||
'name': 'Phone',
|
||||
'manifestURL': 'app://communications.gaiamobile.org/manifest.webapp',
|
||||
'icon':
|
||||
'app://communications.gaiamobile.org/dialer/style/icons/Dialer_60.png'
|
||||
}
|
||||
]
|
||||
]};
|
||||
|
||||
var confSV = {
|
||||
'214-007': [
|
||||
{
|
||||
'location': 14,
|
||||
'manifestURL':
|
||||
'https://marketplace.firefox.com/app/' +
|
||||
'9f96ce77-5b2d-42ca-a0d9-10a933dd84c4/manifest.webapp'
|
||||
},{
|
||||
'location': 1000,
|
||||
'manifestURL': 'https://mobile.twitter.com/cache/twitter.webapp'
|
||||
},{
|
||||
'location': 6,
|
||||
'manifestURL':
|
||||
'https://bits.wikimedia.org/WikipediaMobileFirefoxOS/manifest.webapp'
|
||||
},{
|
||||
'manifestURL':
|
||||
'https://owdstore.hi.inet/operRes/latam/operatorResourcesLatam.webapp'
|
||||
}
|
||||
]};
|
||||
|
||||
suiteSetup(function() {
|
||||
mocksHelperForConfigurator.suiteSetup();
|
||||
realMozSettings = navigator.mozSettings;
|
||||
realGetFeature = navigator.getFeature;
|
||||
navigator.getFeature = MockNavigatorGetFeature;
|
||||
navigator.mozSettings = MockNavigatorSettings;
|
||||
MockNavigatorSettings.mSyncRepliesOnly = true;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
mocksHelperForConfigurator.suiteTeardown();
|
||||
navigator.getFeature = realGetFeature;
|
||||
navigator.mozSettings = realMozSettings;
|
||||
MockNavigatorSettings.mSyncRepliesOnly = false;
|
||||
});
|
||||
|
||||
setup(function(done) {
|
||||
mocksHelperForConfigurator.setup();
|
||||
requireApp('verticalhome/js/configurator.js', function() {
|
||||
configurator = new Configurator();
|
||||
requests = [];
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
mocksHelperForConfigurator.teardown();
|
||||
navigator.mozSettings.mTeardown();
|
||||
});
|
||||
|
||||
test('Sections >', function(done) {
|
||||
this.sinon.stub(LazyLoader, 'getJSON')
|
||||
.returns(Promise.resolve(confGridOK));
|
||||
configurator.load();
|
||||
|
||||
window.addEventListener('configuration-ready', function ready() {
|
||||
window.removeEventListener('configuration-ready', ready);
|
||||
var grid = configurator.getGrid();
|
||||
assert.equal(grid[0][0].entry_point, confGridOK.grid[0][0].entry_point);
|
||||
assert.equal(grid[0][0].name, confGridOK.grid[0][0].name);
|
||||
assert.equal(grid[0][0].manifestURL, confGridOK.grid[0][0].manifestURL);
|
||||
assert.equal(grid[0][0].icon, confGridOK.grid[0][0].icon);
|
||||
|
||||
var prediction = configurator.getSection('prediction');
|
||||
assert.equal(prediction.enabled, confGridOK.prediction.enabled);
|
||||
assert.equal(prediction.lookahead, confGridOK.prediction.lookahead);
|
||||
|
||||
// This section should be undefined
|
||||
assert.isUndefined(configurator.getSection('noExiste'));
|
||||
|
||||
// For configurator remove the listener
|
||||
IccHelper.mProps.iccInfo = {mcc:'214', mnc:'007'};
|
||||
IccHelper.mTriggerEventListeners('iccinfochange', {});
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
function assertLoadFile(okLoad, done) {
|
||||
window.addEventListener('configuration-ready', function ready() {
|
||||
window.removeEventListener('configuration-ready', ready);
|
||||
var grid = configurator.getGrid();
|
||||
if (okLoad) {
|
||||
assert.notEqual(grid, undefined);
|
||||
} else {
|
||||
assert.equal(grid, undefined);
|
||||
}
|
||||
// For remove listener
|
||||
IccHelper.mProps.iccInfo = {mcc:'214', mnc:'007'};
|
||||
IccHelper.mTriggerEventListeners('iccinfochange', {});
|
||||
done();
|
||||
});
|
||||
|
||||
configurator.load();
|
||||
}
|
||||
|
||||
test('Correct load conf file >', function(done) {
|
||||
this.sinon.stub(LazyLoader, 'getJSON')
|
||||
.returns(Promise.resolve(confGridOK));
|
||||
assertLoadFile(true, done);
|
||||
});
|
||||
|
||||
test('Wrong load conf file >', function(done) {
|
||||
this.sinon.stub(LazyLoader, 'getJSON')
|
||||
.returns(Promise.reject({'type': 'expected error'}));
|
||||
assertLoadFile(false, done);
|
||||
});
|
||||
|
||||
function assertSV(xhrOk, done) {
|
||||
sinon.useFakeTimers();
|
||||
|
||||
IccHelper.mProps.iccInfo = {mcc:'214', mnc:'007'};
|
||||
IccHelper.mTriggerEventListeners('iccinfochange', {});
|
||||
|
||||
window.addEventListener('singlevariant-ready', function svReady() {
|
||||
window.removeEventListener('singlevariant-ready', svReady);
|
||||
var svApp;
|
||||
if (xhrOk) {
|
||||
svApp =
|
||||
configurator.getSingleVariantApp(confSV['214-007'][0].manifestURL);
|
||||
assert.equal(svApp.manifestURL, confSV['214-007'][0].manifestURL);
|
||||
assert.equal(svApp.location, confSV['214-007'][0].location);
|
||||
svApp =
|
||||
configurator.getSingleVariantApp('nonexistent_manifest');
|
||||
assert.isUndefined(svApp);
|
||||
} else {
|
||||
svApp =
|
||||
configurator.getSingleVariantApp(confSV['214-007'][0].manifestURL);
|
||||
assert.isUndefined(svApp);
|
||||
}
|
||||
done();
|
||||
});
|
||||
|
||||
configurator.load();
|
||||
}
|
||||
|
||||
/*
|
||||
* It tests the public method 'getSingleVariantApps' getting properties/values
|
||||
*/
|
||||
test('getSingleVariantApps - Correct conf file >', function(done) {
|
||||
this.sinon.stub(LazyLoader, 'getJSON')
|
||||
.returns(Promise.resolve(confSV));
|
||||
assertSV(true, done);
|
||||
});
|
||||
|
||||
test('getSingleVariantApps - Wrong conf file >', function(done) {
|
||||
this.sinon.stub(LazyLoader, 'getJSON')
|
||||
.returns(Promise.reject({'type': 'expected error'}));
|
||||
assertSV(false, done);
|
||||
});
|
||||
|
||||
const KEY_SIM_ON_1ST_RUN = 'ftu.simPresentOnFirstBoot';
|
||||
/*
|
||||
* Checks isSimPresentOnFirstBoot function
|
||||
*/
|
||||
|
||||
var testCases = [
|
||||
{
|
||||
'preValSet': undefined,
|
||||
'currentMccMnc': '214-007',
|
||||
'expecValSet': true,
|
||||
'title': KEY_SIM_ON_1ST_RUN +
|
||||
'setting value is undefined - isSimPresentOnFirstBoot is true'
|
||||
}, {
|
||||
'preValSet': '000-000',
|
||||
'currentMccMnc': '214-007',
|
||||
'expecValSet': false,
|
||||
'title': KEY_SIM_ON_1ST_RUN +
|
||||
'setting value different to the current mcc-mnc - ' +
|
||||
'isSimPresentOnFirstBoot is false'
|
||||
}, {
|
||||
'preValSet': '214-007',
|
||||
'currentMccMnc': '214-007',
|
||||
'expecValSet': true,
|
||||
'title': KEY_SIM_ON_1ST_RUN +
|
||||
'setting value the same as current mcc-mnc - ' +
|
||||
'isSimPresentOnFirstBoot is true'
|
||||
}
|
||||
];
|
||||
|
||||
testCases.forEach(function(testCase) {
|
||||
test(testCase.title, function() {
|
||||
this.sinon.useFakeTimers();
|
||||
MockNavigatorSettings.mSettings[KEY_SIM_ON_1ST_RUN] = testCase.preValSet;
|
||||
configurator.loadSettingSIMPresent(testCase.currentMccMnc);
|
||||
this.sinon.clock.tick();
|
||||
assert.equal(configurator.isSimPresentOnFirstBoot,
|
||||
testCase.expecValSet);
|
||||
});
|
||||
});
|
||||
|
||||
suite('migration> ', function() {
|
||||
var updateHandler = null;
|
||||
var vpGetStub = null;
|
||||
var vpEvtUpdateStub = null;
|
||||
|
||||
var mGrid_layout = {
|
||||
'grid': [
|
||||
[
|
||||
{
|
||||
'name': 'Phone',
|
||||
'manifestURL': 'app://communications/manifest.webapp',
|
||||
'icon': 'app://communications/icons/Dialer_60.png',
|
||||
'entry_point': 'dialer'
|
||||
},
|
||||
{
|
||||
'name': 'Messages',
|
||||
'manifestURL': 'app://sms/manifest.webapp',
|
||||
'icon': 'app://sms/icons/Sms_60.png'
|
||||
}
|
||||
],
|
||||
[
|
||||
{ 'id': 289, 'role': 'collection' },
|
||||
{ 'id': 207, 'role': 'collection' }
|
||||
],
|
||||
[
|
||||
{
|
||||
'name': 'Contacts',
|
||||
'manifestURL': 'app://communications/manifest.webapp',
|
||||
'icon': 'app://communications/icons/Contacts_60.png',
|
||||
'entry_point': 'contacts'
|
||||
},
|
||||
{
|
||||
'name': 'Settings',
|
||||
'manifestURL': 'app://settings/manifest.webapp',
|
||||
'icon': 'app://settings/icons/Settings_60.png'
|
||||
}
|
||||
]
|
||||
]
|
||||
};
|
||||
|
||||
var mGrid_layout2 = {
|
||||
'grid': [
|
||||
[
|
||||
{
|
||||
'name': 'Messages2',
|
||||
'manifestURL': 'app://sms/manifest.webapp',
|
||||
'icon': 'app://sms/icons/Sms_60.png'
|
||||
}
|
||||
],
|
||||
[
|
||||
{ 'id': 200, 'role': 'collection' },
|
||||
{ 'id': 100, 'role': 'collection' }
|
||||
],
|
||||
[
|
||||
{
|
||||
'name': 'Contacts2',
|
||||
'manifestURL': 'app://communications/manifest.webapp',
|
||||
'icon': 'app://communications/icons/Contacts_60.png',
|
||||
'entry_point': 'contacts'
|
||||
}
|
||||
]
|
||||
]
|
||||
};
|
||||
|
||||
function dispatchUpdatedEvent(grid) {
|
||||
updateHandler({
|
||||
type: 'updated',
|
||||
target: {
|
||||
name: 'grid.layout',
|
||||
value: grid
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setup(function() {
|
||||
vpGetStub = sinon.stub(verticalPreferences, 'get', function(field) {
|
||||
return {
|
||||
then: function(cb) {
|
||||
cb(mGrid_layout);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
vpEvtUpdateStub = sinon.stub(verticalPreferences, 'addEventListener',
|
||||
function(type, handler) {
|
||||
updateHandler = handler;
|
||||
}
|
||||
);
|
||||
|
||||
MockVersionHelper.mIsUpgrade = true;
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
vpGetStub.restore();
|
||||
vpEvtUpdateStub.restore();
|
||||
});
|
||||
|
||||
function assertGridOk(gridTest, gridOk) {
|
||||
assert.notEqual(gridTest, undefined);
|
||||
assert.equal(gridTest.length, gridOk.length);
|
||||
for (var i = 0, iLen = gridOk.length; i < iLen; i++) {
|
||||
assert.equal(gridTest[i].length, gridOk[i].length);
|
||||
for (var j = 0, jLen = gridOk[i].length; j < jLen; j++) {
|
||||
assert.equal(gridTest[i].length, gridOk[i].length);
|
||||
assert.equal(gridTest[i][j].name, gridOk[i][j].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test('Upgrade from old homescreen - grid.layout ready >', function(done) {
|
||||
window.addEventListener('configuration-ready', function ready() {
|
||||
window.removeEventListener('configuration-ready', ready);
|
||||
var grid = configurator.getGrid();
|
||||
assertGridOk(grid, mGrid_layout.grid);
|
||||
done();
|
||||
});
|
||||
|
||||
configurator.load();
|
||||
sinon.assert.callCount(vpEvtUpdateStub, 0);
|
||||
});
|
||||
|
||||
test('Upgrade from old homescreen - grid.layout not ready >', function() {
|
||||
var gridTest = mGrid_layout;
|
||||
mGrid_layout = undefined;
|
||||
configurator.load();
|
||||
sinon.assert.calledOnce(vpEvtUpdateStub);
|
||||
var grid = configurator.getGrid();
|
||||
assert.equal(grid, undefined);
|
||||
|
||||
dispatchUpdatedEvent(mGrid_layout2);
|
||||
grid = configurator.getGrid();
|
||||
assertGridOk(grid, mGrid_layout2.grid);
|
||||
mGrid_layout = gridTest;
|
||||
});
|
||||
});
|
||||
});
|
||||
74
gaia/apps/verticalhome/test/unit/contextmenu_handler_test.js
Executable file
74
gaia/apps/verticalhome/test/unit/contextmenu_handler_test.js
Executable file
|
|
@ -0,0 +1,74 @@
|
|||
'use strict';
|
||||
|
||||
/* global MocksHelper, MockL10n, contextMenuUI, loadBodyHTML,
|
||||
contextMenuHandler, App */
|
||||
|
||||
require('/shared/test/unit/load_body_html_helper.js');
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
require('/test/unit/mock_app.js');
|
||||
require('/js/contextmenu_ui.js');
|
||||
|
||||
var mocksHelperForContextMenuHandler = new MocksHelper([
|
||||
'App',
|
||||
'LazyLoader'
|
||||
]).init();
|
||||
|
||||
suite('contextmenu_handler.js >', function() {
|
||||
|
||||
var realL10n = null;
|
||||
var clock = null;
|
||||
|
||||
mocksHelperForContextMenuHandler.attachTestHelpers();
|
||||
|
||||
suiteSetup(function(done) {
|
||||
realL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockL10n;
|
||||
clock = sinon.useFakeTimers();
|
||||
loadBodyHTML('/index.html');
|
||||
require('/js/contextmenu_handler.js', done);
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozL10n = realL10n;
|
||||
realL10n = null;
|
||||
});
|
||||
|
||||
function dispatchContextMenu() {
|
||||
contextMenuHandler.container.dispatchEvent(new CustomEvent('contextmenu'));
|
||||
clock.tick();
|
||||
}
|
||||
|
||||
test(' Handling contextmenu event', function() {
|
||||
window.app = new App();
|
||||
var stub = sinon.stub(contextMenuUI, 'show');
|
||||
|
||||
dispatchContextMenu();
|
||||
sinon.assert.called(stub);
|
||||
|
||||
stub.restore();
|
||||
delete window.app;
|
||||
});
|
||||
|
||||
test(' Handling contextmenu event in edit mode', function() {
|
||||
window.app = new App();
|
||||
window.app.grid._grid.dragdrop.inEditMode = true;
|
||||
var stub = sinon.stub(contextMenuUI, 'show');
|
||||
|
||||
dispatchContextMenu();
|
||||
sinon.assert.notCalled(stub);
|
||||
|
||||
stub.restore();
|
||||
delete window.app;
|
||||
});
|
||||
|
||||
test(' Handling hashchange event', function() {
|
||||
var stub = sinon.stub(contextMenuUI, 'hide');
|
||||
|
||||
window.dispatchEvent(new CustomEvent('hashchange'));
|
||||
sinon.assert.called(stub);
|
||||
|
||||
stub.restore();
|
||||
});
|
||||
|
||||
});
|
||||
96
gaia/apps/verticalhome/test/unit/contextmenu_ui_test.js
Executable file
96
gaia/apps/verticalhome/test/unit/contextmenu_ui_test.js
Executable file
|
|
@ -0,0 +1,96 @@
|
|||
'use strict';
|
||||
|
||||
/* global app, contextMenuUI, wallpaper, MocksHelper */
|
||||
|
||||
require('/shared/elements/gaia_grid/js/grid_dragdrop.js');
|
||||
require('/shared/elements/gaia_grid/js/grid_icon_renderer.js');
|
||||
require('/shared/elements/gaia_grid/js/grid_layout.js');
|
||||
require('/shared/elements/gaia_grid/js/grid_view.js');
|
||||
require('/shared/elements/gaia_grid/js/grid_zoom.js');
|
||||
require('/shared/elements/gaia_grid/js/items/grid_item.js');
|
||||
require('/shared/elements/gaia_grid/js/items/placeholder.js');
|
||||
require('/shared/elements/gaia_grid/script.js');
|
||||
require('/test/unit/mock_item_store.js');
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
require('/shared/test/unit/load_body_html_helper.js');
|
||||
require('/js/wallpaper.js');
|
||||
requireElements('verticalhome/elements/contextmenu.html');
|
||||
|
||||
var mocksHelperForContextMenuUI = new MocksHelper([
|
||||
'LazyLoader',
|
||||
'ItemStore'
|
||||
]).init();
|
||||
|
||||
suite('contextmenu_ui.js >', function() {
|
||||
|
||||
mocksHelperForContextMenuUI.attachTestHelpers();
|
||||
|
||||
var fakeEvt = {};
|
||||
|
||||
suiteSetup(function(done) {
|
||||
loadBodyHTML('/index.html');
|
||||
require('/js/app.js', done);
|
||||
});
|
||||
|
||||
setup(function(done) {
|
||||
app.init();
|
||||
this.sinon.stub(app.grid._grid, 'getNearestItemIndex').returns(0);
|
||||
require('/js/contextmenu_ui.js', done);
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
document.body.innerHTML = '';
|
||||
});
|
||||
|
||||
function assertDisplayed() {
|
||||
assert.isTrue(!contextMenuUI.dialog.hasAttribute('hidden'));
|
||||
}
|
||||
|
||||
function assertHidden() {
|
||||
assert.isTrue(contextMenuUI.dialog.hasAttribute('hidden'));
|
||||
}
|
||||
|
||||
test(' Show and hide context menu', function() {
|
||||
var clock = sinon.useFakeTimers();
|
||||
contextMenuUI.show(fakeEvt);
|
||||
clock.tick(50);
|
||||
assertDisplayed();
|
||||
contextMenuUI.hide();
|
||||
assertHidden();
|
||||
});
|
||||
|
||||
test(' Change wallpaper action', function(done) {
|
||||
var stub = sinon.stub(wallpaper, 'change', function() {
|
||||
stub.restore;
|
||||
done();
|
||||
});
|
||||
|
||||
contextMenuUI.show(fakeEvt);
|
||||
contextMenuUI.dialog.querySelector('#change-wallpaper-action').click();
|
||||
assertHidden();
|
||||
});
|
||||
|
||||
test(' Cancel action', function() {
|
||||
contextMenuUI.show(fakeEvt);
|
||||
contextMenuUI.dialog.dispatchEvent(new CustomEvent('gaiamenu-cancel'));
|
||||
assertHidden();
|
||||
});
|
||||
|
||||
test(' Hide the context menu when the document is hidden', function() {
|
||||
Object.defineProperty(document, 'hidden', {
|
||||
configurable: true,
|
||||
get: function() {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
contextMenuUI.show(fakeEvt);
|
||||
contextMenuUI.handleEvent({
|
||||
'type': 'visibilitychange'
|
||||
});
|
||||
|
||||
delete document.hidden;
|
||||
assertHidden();
|
||||
});
|
||||
|
||||
});
|
||||
60
gaia/apps/verticalhome/test/unit/mock_app.js
Executable file
60
gaia/apps/verticalhome/test/unit/mock_app.js
Executable file
|
|
@ -0,0 +1,60 @@
|
|||
'use strict';
|
||||
|
||||
function MockApp() {
|
||||
MockApp.initialized = false;
|
||||
MockApp.mIcons = {};
|
||||
MockApp.mItems = [];
|
||||
}
|
||||
|
||||
MockApp.prototype = {
|
||||
HIDDEN_ROLES: [
|
||||
'system', 'keyboard', 'homescreen', 'search', 'addon', 'langpack'
|
||||
],
|
||||
init: function() {
|
||||
MockApp.initialized = true;
|
||||
},
|
||||
mGetInitialized: function () {
|
||||
return MockApp.initialized;
|
||||
},
|
||||
itemStore: {
|
||||
save: function() {},
|
||||
deferredSave: function() {}
|
||||
},
|
||||
grid: {
|
||||
add: function(detail) {
|
||||
if (detail) {
|
||||
MockApp.mItems.push(detail);
|
||||
}
|
||||
},
|
||||
appendItemToExpandedGroup: function(detail) {
|
||||
if (detail) {
|
||||
MockApp.mItems.push(detail);
|
||||
}
|
||||
},
|
||||
removeIconByIdentifier: function(identifier) {
|
||||
delete MockApp.mIcons[identifier];
|
||||
},
|
||||
removeItemByIndex: function(idx) {
|
||||
MockApp.mItems.splice(idx, 1);
|
||||
},
|
||||
getIcons: function() {
|
||||
return MockApp.mIcons;
|
||||
},
|
||||
getItems: function() {
|
||||
return MockApp.mItems;
|
||||
},
|
||||
render: function() {},
|
||||
|
||||
_grid: {
|
||||
dragdrop: {
|
||||
inEditMode: false
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MockApp.mTeardown = function mp_mTeardown() {
|
||||
delete MockApp.initialized;
|
||||
MockApp.mIcons = {};
|
||||
MockApp.mItems = [];
|
||||
};
|
||||
50
gaia/apps/verticalhome/test/unit/mock_application_source.js
Executable file
50
gaia/apps/verticalhome/test/unit/mock_application_source.js
Executable file
|
|
@ -0,0 +1,50 @@
|
|||
/* global GaiaGrid */
|
||||
'use strict';
|
||||
|
||||
var apps = [
|
||||
{
|
||||
'manifestURL': 'app://gallery.gaiamobile.org/manifest.webapp'
|
||||
},{
|
||||
'manifestURL': 'app://clock.gaiamobile.org/manifest.webapp'
|
||||
},{
|
||||
'manifestURL': 'app://keyboard.gaiamobile.org/manifest.webapp'
|
||||
},{
|
||||
'manifestURL': 'app://camera.gaiamobile.org/manifest.webapp'
|
||||
},{
|
||||
'manifestURL': 'app://music.gaiamobile.org/manifest.webapp'
|
||||
},{
|
||||
'manifestURL': 'app://browser.gaiamobile.org/manifest.webapp'
|
||||
},{
|
||||
'manifestURL': 'app://email.gaiamobile.org/manifest.webapp'
|
||||
},{
|
||||
'entryPoint': 'contacts',
|
||||
'manifestURL': 'app://communications.gaiamobile.org/manifest.webapp'
|
||||
},{
|
||||
'entryPoint': 'dialer',
|
||||
'manifestURL': 'app://communications.gaiamobile.org/manifest.webapp'
|
||||
}
|
||||
];
|
||||
|
||||
function MockApplicationSource() {
|
||||
this.entries = [];
|
||||
var mozApp;
|
||||
for (var i = 0, iLen = apps.length; i < iLen; i++){
|
||||
if (apps[i].entryPoint) {
|
||||
mozApp = new GaiaGrid.Mozapp(apps[i], apps[i].entryPoint);
|
||||
} else {
|
||||
mozApp = new GaiaGrid.Mozapp(apps[i]);
|
||||
}
|
||||
mozApp.detail.index = i;
|
||||
this.entries.push(mozApp);
|
||||
}
|
||||
}
|
||||
|
||||
MockApplicationSource.prototype = {
|
||||
addPreviouslyInstalledSvApp: function(manifestURL) {
|
||||
},
|
||||
mapToApp: function (item) {
|
||||
},
|
||||
populate: function (next){
|
||||
next(this.entries);
|
||||
}
|
||||
};
|
||||
11
gaia/apps/verticalhome/test/unit/mock_bookmark_source.js
Executable file
11
gaia/apps/verticalhome/test/unit/mock_bookmark_source.js
Executable file
|
|
@ -0,0 +1,11 @@
|
|||
'use strict';
|
||||
|
||||
function MockBookmarkSource() {
|
||||
this.entries = [];
|
||||
}
|
||||
|
||||
MockBookmarkSource.prototype = {
|
||||
populate: function(next) {
|
||||
next(this.entries);
|
||||
}
|
||||
};
|
||||
56
gaia/apps/verticalhome/test/unit/mock_configurator.js
Executable file
56
gaia/apps/verticalhome/test/unit/mock_configurator.js
Executable file
|
|
@ -0,0 +1,56 @@
|
|||
'use strict';
|
||||
|
||||
var confSV = {
|
||||
'https://owdstore.hi.inet/operRes/spainResources.webapp':
|
||||
{
|
||||
'manifestURL': 'https://owdstore.hi.inet/operRes/spainResources.webapp'
|
||||
},
|
||||
'https://url/path/appSV.webapp':
|
||||
{
|
||||
'manifestURL': 'https://url/path/appSV.webapp',
|
||||
'location': 1
|
||||
}
|
||||
};
|
||||
|
||||
var mcGrid = [
|
||||
[
|
||||
{
|
||||
'manifestURL': 'app://communications.gaiamobile.org/manifest.webapp',
|
||||
'name': 'Phone',
|
||||
'entry_point': 'dialer',
|
||||
'icon': 'app://communications.gaiamobile.org/dialer/icons/Dialer_120.png'
|
||||
},{
|
||||
'manifestURL': 'app://email.gaiamobile.org/manifest.webapp',
|
||||
'name': 'email',
|
||||
'icon': 'app://email.gaiamobile.org/style/icons/Email_120.png'
|
||||
}
|
||||
],[
|
||||
{
|
||||
'manifestURL': 'app://communications.gaiamobile.org/manifest.webapp',
|
||||
'entry_point': 'contacts',
|
||||
'name': 'contacts',
|
||||
'icon': 'app://communications.gaiamobile.org/contacts/style/icons/Cont'
|
||||
}
|
||||
],[
|
||||
{
|
||||
'manifestURL': 'app://browser.gaiamobile.org/manifest.webapp',
|
||||
'name': 'browser',
|
||||
'icon': 'app://browser.gaiamobile.esources/branding/Browser_120.png'
|
||||
},{
|
||||
'manifestURL': 'app://music.gaiamobile.org/manifest.webapp',
|
||||
'icon': 'app://music.gaiamobile.org/style/icons/Music_120.png'
|
||||
}
|
||||
]
|
||||
];
|
||||
|
||||
var configurator = {
|
||||
getGrid: function() {
|
||||
return mcGrid;
|
||||
},
|
||||
isSingleVariantReady: true,
|
||||
getSingleVariantApp: function(manifestURL) {
|
||||
return confSV[manifestURL];
|
||||
}
|
||||
};
|
||||
|
||||
window.configurator = configurator;
|
||||
14
gaia/apps/verticalhome/test/unit/mock_item_store.js
Executable file
14
gaia/apps/verticalhome/test/unit/mock_item_store.js
Executable file
|
|
@ -0,0 +1,14 @@
|
|||
'use strict';
|
||||
|
||||
function MockItemStore() {}
|
||||
|
||||
MockItemStore.prototype = {
|
||||
mNextPosition: 0,
|
||||
all: function() {},
|
||||
deferredSave: function() {},
|
||||
getNextPosition: function() {
|
||||
var nextPosition = this.mNextPosition;
|
||||
this.mNextPosition++;
|
||||
return nextPosition;
|
||||
}
|
||||
};
|
||||
19
gaia/apps/verticalhome/test/unit/mock_version_helper.js
Executable file
19
gaia/apps/verticalhome/test/unit/mock_version_helper.js
Executable file
|
|
@ -0,0 +1,19 @@
|
|||
'use strict';
|
||||
|
||||
var MockVersionHelper = {
|
||||
|
||||
mIsUpgrade: false,
|
||||
mVersionInfo: {
|
||||
isUpgrade: function() {
|
||||
return MockVersionHelper.mIsUpgrade;
|
||||
}
|
||||
},
|
||||
|
||||
getVersionInfo: function() {
|
||||
return {
|
||||
then: function(cb) {
|
||||
cb(MockVersionHelper.mVersionInfo);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
5
gaia/apps/verticalhome/test/unit/setup.js
Executable file
5
gaia/apps/verticalhome/test/unit/setup.js
Executable file
|
|
@ -0,0 +1,5 @@
|
|||
'use strict';
|
||||
|
||||
/* global require */
|
||||
|
||||
require('/shared/test/unit/mocks/mocks_helper.js');
|
||||
67
gaia/apps/verticalhome/test/unit/sources/application_test.js
Executable file
67
gaia/apps/verticalhome/test/unit/sources/application_test.js
Executable file
|
|
@ -0,0 +1,67 @@
|
|||
'use strict';
|
||||
/* global App, ApplicationSource, GaiaGrid, ItemStore */
|
||||
/* global MocksHelper, MockNavigatormozApps, loadBodyHTML */
|
||||
|
||||
require('/shared/js/l10n.js');
|
||||
require('/shared/test/unit/load_body_html_helper.js');
|
||||
require('/shared/elements/gaia_grid/js/grid_dragdrop.js');
|
||||
require('/shared/elements/gaia_grid/js/grid_icon_renderer.js');
|
||||
require('/shared/elements/gaia_grid/js/grid_layout.js');
|
||||
require('/shared/elements/gaia_grid/js/grid_view.js');
|
||||
require('/shared/elements/gaia_grid/js/grid_zoom.js');
|
||||
require('/shared/elements/gaia_grid/script.js');
|
||||
require('/shared/elements/gaia_grid/js/items/grid_item.js');
|
||||
require('/shared/elements/gaia_grid/js/items/placeholder.js');
|
||||
require('/shared/elements/gaia_grid/js/items/mozapp.js');
|
||||
require('/shared/test/unit/mocks/mock_navigator_moz_apps.js');
|
||||
|
||||
require('/test/unit/mock_app.js');
|
||||
require('/test/unit/mock_item_store.js');
|
||||
require('/shared/test/unit/mocks/mock_navigator_moz_apps.js');
|
||||
|
||||
var mocksHelperForApp = new MocksHelper([
|
||||
'App',
|
||||
'ItemStore'
|
||||
]).init();
|
||||
|
||||
suite('app.js > ', function() {
|
||||
|
||||
mocksHelperForApp.attachTestHelpers();
|
||||
|
||||
var subject;
|
||||
var realMozApps;
|
||||
|
||||
suiteSetup(function(done) {
|
||||
window.app = new App();
|
||||
realMozApps = navigator.mozApps;
|
||||
navigator.mozApps = MockNavigatormozApps;
|
||||
require('/js/sources/application.js', done);
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozApps = realMozApps;
|
||||
MockNavigatormozApps.mTeardown();
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
loadBodyHTML('/index.html');
|
||||
subject = new ApplicationSource(new ItemStore());
|
||||
});
|
||||
|
||||
test('synchronize removes app', function() {
|
||||
var removeStub = this.sinon.stub(subject, 'removeIconFromGrid');
|
||||
|
||||
subject.store._allItems = [
|
||||
new GaiaGrid.Mozapp({
|
||||
manifestURL: 'mozilla'
|
||||
}),
|
||||
new GaiaGrid.Mozapp({
|
||||
manifestURL: 'removeme'
|
||||
})
|
||||
];
|
||||
|
||||
subject.synchronize();
|
||||
assert.ok(removeStub.calledTwice);
|
||||
});
|
||||
|
||||
});
|
||||
138
gaia/apps/verticalhome/test/unit/stores/item_test.js
Executable file
138
gaia/apps/verticalhome/test/unit/stores/item_test.js
Executable file
|
|
@ -0,0 +1,138 @@
|
|||
'use strict';
|
||||
|
||||
/* global MocksHelper, MockIndexedDB, ItemStore, configurator */
|
||||
|
||||
require('/shared/js/l10n.js');
|
||||
require('/shared/test/unit/mocks/mock_indexedDB.js');
|
||||
require('/test/unit/mock_application_source.js');
|
||||
require('/test/unit/mock_bookmark_source.js');
|
||||
require('/test/unit/mock_configurator.js');
|
||||
|
||||
require('/shared/elements/gaia_grid/js/grid_icon_renderer.js');
|
||||
require('/shared/elements/gaia_grid/script.js');
|
||||
require('/shared/elements/gaia_grid/js/items/grid_item.js');
|
||||
require('/shared/elements/gaia_grid/js/items/divider.js');
|
||||
require('/shared/elements/gaia_grid/js/items/mozapp.js');
|
||||
|
||||
// Unit tests for item library
|
||||
requireApp('verticalhome/js/stores/item.js');
|
||||
|
||||
var mocksHelperForItemStore = new MocksHelper([
|
||||
'ApplicationSource',
|
||||
'BookmarkSource'
|
||||
]).init();
|
||||
|
||||
suite('item.js >', function() {
|
||||
var mockIndexedDB;
|
||||
var realSetMessageHandler;
|
||||
|
||||
var dataStoreItems = {
|
||||
'0': {
|
||||
'type': 'app',
|
||||
'manifestURL': 'app://gallery.gaiamobile.org/manifest.webapp',
|
||||
'index': 0
|
||||
},
|
||||
'1': {
|
||||
'type': 'app',
|
||||
'manifestURL': 'app://clock.gaiamobile.org/manifest.webapp',
|
||||
'index': 1
|
||||
},
|
||||
'2': {
|
||||
'type': 'app',
|
||||
'manifestURL': 'app://keyboard.gaiamobile.org/manifest.webapp',
|
||||
'index': 2
|
||||
},
|
||||
'3': {
|
||||
'type': 'app',
|
||||
'manifestURL': 'app://camera.gaiamobile.org/manifest.webapp',
|
||||
'index': 3
|
||||
},
|
||||
'4': {
|
||||
'type': 'app',
|
||||
'manifestURL': 'app://music.gaiamobile.org/manifest.webapp',
|
||||
'index': 4
|
||||
},
|
||||
'5': {
|
||||
'type': 'app',
|
||||
'manifestURL': 'app://browser.gaiamobile.org/manifest.webapp',
|
||||
'index': 5
|
||||
},
|
||||
'6': {
|
||||
'type': 'app',
|
||||
'manifestURL': 'app://email.gaiamobile.org/manifest.webapp',
|
||||
'index': 6
|
||||
},
|
||||
'7': {
|
||||
'type': 'app',
|
||||
'manifestURL': 'app://communications.gaiamobile.org/manifest.webapp',
|
||||
'entryPoint': 'contacts',
|
||||
'index': 7
|
||||
},
|
||||
'8': {
|
||||
'type': 'app',
|
||||
'manifestURL': 'app://communications.gaiamobile.org/manifest.webapp',
|
||||
'entryPoint': 'dialer',
|
||||
'index': 8
|
||||
}
|
||||
};
|
||||
|
||||
mocksHelperForItemStore.attachTestHelpers();
|
||||
|
||||
suiteSetup(function() {
|
||||
mockIndexedDB = new MockIndexedDB();
|
||||
mocksHelperForItemStore.suiteSetup();
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
mocksHelperForItemStore.suiteTeardown();
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
mocksHelperForItemStore.setup();
|
||||
realSetMessageHandler = navigator.mozSetMessageHandler;
|
||||
navigator.mozSetMessageHandler = () => {};
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
mocksHelperForItemStore.teardown();
|
||||
navigator.mozSetMessageHandler = realSetMessageHandler;
|
||||
});
|
||||
|
||||
test('ItemStore new >', function() {
|
||||
mockIndexedDB.options.upgradeNeededDbs = ['verticalhome'];
|
||||
|
||||
mockIndexedDB.storedDataDbs = {
|
||||
'verticalhome': dataStoreItems
|
||||
};
|
||||
/*jshint unused:false*/
|
||||
var itemStore = new ItemStore();
|
||||
window.dispatchEvent(new CustomEvent('configuration-ready'));
|
||||
window.dispatchEvent(new CustomEvent('gaiagrid-cached-icons-rendered'));
|
||||
|
||||
var savedElem = mockIndexedDB.dbs[0].receivedData;
|
||||
var grid = configurator.getGrid();
|
||||
|
||||
var gridInd = 0;
|
||||
var keys = Object.keys(savedElem);
|
||||
for (var i = 0, iLen = savedElem.length, gLen = grid.length;
|
||||
i < iLen && gridInd < gLen; i++) {
|
||||
if (savedElem[i].type === 'app') {
|
||||
assert.equal(savedElem[i].manifestURL, grid[gridInd][0].manifestURL);
|
||||
if (savedElem[i].entryPoint) {
|
||||
assert.equal(savedElem[i].entryPoint, grid[gridInd][0].entry_point);
|
||||
}
|
||||
grid[gridInd].shift();
|
||||
} else if (savedElem[i].type === 'divider') {
|
||||
gridInd += 1;
|
||||
}
|
||||
}
|
||||
var moreDivider = false;
|
||||
for (;i < iLen && !moreDivider; i++) {
|
||||
moreDivider = savedElem[keys[i]].type === 'divider';
|
||||
}
|
||||
assert.isFalse(moreDivider);
|
||||
for (i = 0, iLen = grid.length; i < iLen; i++) {
|
||||
assert.equal(grid[i].length, 0);
|
||||
}
|
||||
});
|
||||
});
|
||||
130
gaia/apps/verticalhome/test/unit/vertical_preferences_test.js
Executable file
130
gaia/apps/verticalhome/test/unit/vertical_preferences_test.js
Executable file
|
|
@ -0,0 +1,130 @@
|
|||
'use strict';
|
||||
|
||||
/* global verticalPreferences, MockDatastore, MockNavigatorDatastore */
|
||||
|
||||
require('/shared/test/unit/mocks/mock_navigator_datastore.js');
|
||||
require('/shared/js/homescreens/vertical_preferences.js');
|
||||
|
||||
suite('vertical_preferences.js >', function() {
|
||||
|
||||
var realDatastore = null,
|
||||
gridCols = 'grid.cols',
|
||||
cols = 3;
|
||||
|
||||
suiteSetup(function() {
|
||||
realDatastore = navigator.getDataStores;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.getDataStores = realDatastore;
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
navigator.getDataStores = MockNavigatorDatastore.getDataStores;
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
MockDatastore._inError = false;
|
||||
MockDatastore._records = Object.create(null);
|
||||
});
|
||||
|
||||
test('testing not getDataStores defined >', function(done) {
|
||||
navigator.getDataStores = undefined;
|
||||
verticalPreferences.get(gridCols).then(function(value) {
|
||||
// Do noting
|
||||
}, function(e) {
|
||||
assert.equal(e.name, 'NO_DATASTORE');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('testing no access to datastore >', function(done) {
|
||||
navigator.getDataStores = function() {
|
||||
return {
|
||||
then: function(resolve, reject) {
|
||||
resolve({
|
||||
length: 0
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
verticalPreferences.get(gridCols).then(function(value) {
|
||||
// Do noting
|
||||
}, function(e) {
|
||||
assert.equal(e.name, 'NO_ACCESS_TO_DATASTORE');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('calling to put method - added >', function(done) {
|
||||
verticalPreferences.put(gridCols, cols).then(done);
|
||||
});
|
||||
|
||||
test('calling to put method - failed >', function(done) {
|
||||
MockDatastore._inError = true;
|
||||
verticalPreferences.put(gridCols, cols).then(function() {
|
||||
// Do nothing here
|
||||
}, function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('calling to get method - OK >', function(done) {
|
||||
verticalPreferences.put(gridCols, cols).then(function() {
|
||||
verticalPreferences.get(gridCols).then(function(value) {
|
||||
assert.equal(value, cols);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('calling to get method - failed >', function(done) {
|
||||
MockDatastore._inError = true;
|
||||
verticalPreferences.get(gridCols).then(function() {
|
||||
// Do nothing here
|
||||
}, function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('testing addEventListener for "updated" event >', function(done) {
|
||||
verticalPreferences.addEventListener('updated', function onUpdated(event) {
|
||||
verticalPreferences.removeEventListener('updated', onUpdated);
|
||||
assert.equal(event.type, 'updated');
|
||||
assert.equal(event.target.name, gridCols);
|
||||
assert.equal(event.target.value, cols);
|
||||
done();
|
||||
});
|
||||
|
||||
verticalPreferences.put(gridCols, cols);
|
||||
});
|
||||
|
||||
test('testing removeEventListener >', function(done) {
|
||||
var onUpdated = function() {
|
||||
done(new Error('The "updated" listener should NOT be called!!!'));
|
||||
};
|
||||
|
||||
verticalPreferences.addEventListener('updated', onUpdated);
|
||||
var ret = verticalPreferences.removeEventListener('updated', onUpdated);
|
||||
assert.isTrue(ret);
|
||||
|
||||
verticalPreferences.put(gridCols, cols).then(function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('testing removeEventListener unknown type >', function() {
|
||||
assert.isFalse(verticalPreferences.removeEventListener('dog', function() {
|
||||
// Do nothing...
|
||||
}));
|
||||
});
|
||||
|
||||
test('testing removeEventListener unknown callback >', function() {
|
||||
assert.isFalse(verticalPreferences.removeEventListener('updated',
|
||||
function() {
|
||||
// Do nothing...
|
||||
}
|
||||
));
|
||||
});
|
||||
});
|
||||
110
gaia/apps/verticalhome/test/unit/wallpaper_test.js
Executable file
110
gaia/apps/verticalhome/test/unit/wallpaper_test.js
Executable file
|
|
@ -0,0 +1,110 @@
|
|||
'use strict';
|
||||
|
||||
/* global MocksHelper, MockMozActivity, MockNavigatorSettings, wallpaper */
|
||||
|
||||
require('/shared/test/unit/mocks/mock_navigator_moz_settings.js');
|
||||
require('/shared/test/unit/mocks/mock_moz_activity.js');
|
||||
require('/js/wallpaper.js');
|
||||
|
||||
var mocksHelperForWallpaper = new MocksHelper([
|
||||
'MozActivity'
|
||||
]).init();
|
||||
|
||||
// A simple mock for shared/js/omadrm/fl.js so we don't have to
|
||||
// create a more complicated settings mock than what we already have here.
|
||||
// If I put this in suiteSetup, I get a test error for a leaking global.
|
||||
window.ForwardLock = { getKey: function(f) { f(null); } };
|
||||
|
||||
mocksHelperForWallpaper.attachTestHelpers();
|
||||
|
||||
suite('wallpaper.js >', function() {
|
||||
|
||||
var realMozSettings, activitySub;
|
||||
|
||||
suiteSetup(function() {
|
||||
activitySub = sinon.stub(window, 'MozActivity', function(info) {
|
||||
MockMozActivity.calls.push(info);
|
||||
MockMozActivity.instances.push(this);
|
||||
});
|
||||
realMozSettings = navigator.mozSettings;
|
||||
navigator.mozSettings = MockNavigatorSettings;
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
activitySub.restore();
|
||||
navigator.mozSettings = realMozSettings;
|
||||
delete window.ForwardLock;
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
wallpaper.change();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
window.MockNavigatorSettings.mSettings['wallpaper.image'] = null;
|
||||
});
|
||||
|
||||
function FakeBlob(data) {
|
||||
return {
|
||||
type: 'image/png',
|
||||
data: data
|
||||
};
|
||||
}
|
||||
|
||||
function startMozActivity(methodName, blob) {
|
||||
var instance = MockMozActivity.instances[0];
|
||||
|
||||
instance.result = {
|
||||
blob: blob
|
||||
};
|
||||
|
||||
instance[methodName]();
|
||||
}
|
||||
|
||||
test('The MozActivity was initialized correctly ', function() {
|
||||
// There is only one activity running
|
||||
var activities = MockMozActivity.calls;
|
||||
assert.equal(activities.length, 1);
|
||||
|
||||
var instances = MockMozActivity.instances;
|
||||
assert.equal(instances.length, 1);
|
||||
|
||||
// Activity data
|
||||
var activity = activities[0];
|
||||
assert.equal(activity.name, 'pick');
|
||||
assert.ok(activity.data.type === 'wallpaper' ||
|
||||
(Array.isArray(activity.data.type) &&
|
||||
activity.data.type.indexOf('wallpaper') >= 0),
|
||||
'activity type is or includes "wallpaper"');
|
||||
|
||||
// Activity callbacks
|
||||
assert.isFunction(instances[0].onsuccess);
|
||||
});
|
||||
|
||||
test('Pick activity returns a blob ', function() {
|
||||
var fakeblob = FakeBlob('banana');
|
||||
|
||||
// This is the blob returned by the activity
|
||||
startMozActivity('onsuccess', fakeblob);
|
||||
|
||||
// We set the wallpaper.image property to "banana"
|
||||
assert.deepEqual(window.MockNavigatorSettings.mSettings['wallpaper.image'],
|
||||
fakeblob);
|
||||
});
|
||||
|
||||
test('Pick activity returns nothing (no blob) ', function() {
|
||||
// MozActivity doesn't return a blob
|
||||
startMozActivity('onsuccess');
|
||||
|
||||
// No blob then wallpaper.image property is not defined
|
||||
assert.isNull(window.MockNavigatorSettings.mSettings['wallpaper.image']);
|
||||
});
|
||||
|
||||
test('Pick activity has been cancelled ', function() {
|
||||
// User cancels
|
||||
startMozActivity('onerror');
|
||||
|
||||
// Then wallpaper.image property is not defined
|
||||
assert.isNull(window.MockNavigatorSettings.mSettings['wallpaper.image']);
|
||||
});
|
||||
});
|
||||
Loading…
Reference in a new issue