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
530
gaia/apps/system/test/unit/activities_test.js
Executable file
530
gaia/apps/system/test/unit/activities_test.js
Executable file
|
|
@ -0,0 +1,530 @@
|
|||
'use strict';
|
||||
/* global MocksHelper, MockApplications, MockL10n, MockDefaultActivityHelper,
|
||||
ActionMenu, BaseModule, DefaultActivityHelper, MockService
|
||||
*/
|
||||
|
||||
require('/shared/test/unit/mocks/mock_l10n.js');
|
||||
require('/shared/test/unit/mocks/mock_default_activity_helper.js');
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
requireApp('system/test/unit/mock_applications.js');
|
||||
requireApp('system/shared/test/unit/mocks/mock_service.js');
|
||||
requireApp('system/test/unit/mock_action_menu.js');
|
||||
requireApp('system/shared/js/manifest_helper.js');
|
||||
requireApp('system/js/base_module.js');
|
||||
|
||||
var mocksForActivities = new MocksHelper([
|
||||
'Applications',
|
||||
'LazyLoader',
|
||||
'ActionMenu'
|
||||
]).init();
|
||||
|
||||
suite('system/Activities', function() {
|
||||
var realL10n;
|
||||
var realDefaultActivityHelper;
|
||||
var subject;
|
||||
var realApplications;
|
||||
var realService;
|
||||
|
||||
var fakeLaunchConfig1 = {
|
||||
'isActivity': false,
|
||||
'url': 'app://fakeapp1.gaiamobile.org/pick.html',
|
||||
'name': 'Fake App 1',
|
||||
'manifestURL': 'app://fakeapp1.gaiamobile.org/manifest.webapp',
|
||||
'origin': 'app://fakeapp1.gaiamobile.org',
|
||||
'manifest': {
|
||||
'name': 'Fake App 1'
|
||||
},
|
||||
target: {}
|
||||
};
|
||||
|
||||
mocksForActivities.attachTestHelpers();
|
||||
|
||||
suiteSetup(function(done) {
|
||||
realL10n = navigator.mozL10n;
|
||||
navigator.mozL10n = MockL10n;
|
||||
realApplications = window.applications;
|
||||
realDefaultActivityHelper = window.DefaultActivityHelper;
|
||||
realService = window.Service;
|
||||
window.Service = MockService;
|
||||
window.applications = MockApplications;
|
||||
window.DefaultActivityHelper = MockDefaultActivityHelper;
|
||||
requireApp('system/js/activities.js', done);
|
||||
});
|
||||
|
||||
suiteTeardown(function() {
|
||||
navigator.mozL10n = realL10n;
|
||||
window.applications = realApplications;
|
||||
window.Service = realService;
|
||||
window.DefaultActivityHelper = realDefaultActivityHelper;
|
||||
realApplications = null;
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
this.sinon.useFakeTimers();
|
||||
});
|
||||
|
||||
suite('constructor', function() {
|
||||
test('adds event listeners', function() {
|
||||
var expected = [];
|
||||
subject = BaseModule.instantiate('Activities');
|
||||
this.sinon.stub(subject, 'handleEvent', function(evt) {
|
||||
expected.push(evt.type);
|
||||
});
|
||||
subject.start();
|
||||
var events = {};
|
||||
var eventsToListen = [
|
||||
'mozChromeEvent',
|
||||
'appopened',
|
||||
'lockscreen-appopened',
|
||||
'applicationinstall'
|
||||
];
|
||||
|
||||
eventsToListen.forEach(function(name) {
|
||||
events[name] = new CustomEvent(name);
|
||||
window.dispatchEvent(events[name]);
|
||||
assert.isTrue(expected[expected.length - 1] === name);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('handleEvent', function() {
|
||||
test('calls chooseActivity', function() {
|
||||
var stub = this.sinon.stub(subject, 'chooseActivity');
|
||||
var detail = {
|
||||
type: 'activity-choice'
|
||||
};
|
||||
subject.handleEvent({
|
||||
type: 'mozChromeEvent',
|
||||
detail: detail
|
||||
});
|
||||
assert.ok(stub.calledWith(detail));
|
||||
});
|
||||
|
||||
test('hides actionMenu on appopended if it exists', function() {
|
||||
this.sinon.stub(ActionMenu.prototype, 'hide');
|
||||
subject.actionMenu = new ActionMenu();
|
||||
subject.handleEvent({type: 'appopened'});
|
||||
assert.ok(ActionMenu.prototype.hide.calledOnce);
|
||||
});
|
||||
|
||||
test('cancel choice when locked', function() {
|
||||
subject._detail = {
|
||||
id: 'foo',
|
||||
name: 'testactivity',
|
||||
activityType: 'testtype',
|
||||
choices: [{
|
||||
manifest: 'manifest'
|
||||
}]
|
||||
};
|
||||
this.sinon.stub(subject, 'cancel');
|
||||
subject.handleEvent({type: 'lockscreen-appopened'});
|
||||
assert.ok(subject.cancel.calledOnce);
|
||||
});
|
||||
|
||||
test('cancel choice when pressing home button', function() {
|
||||
subject._detail = {
|
||||
id: 'foo',
|
||||
name: 'testactivity',
|
||||
activityType: 'testtype',
|
||||
choices: [{
|
||||
manifest: 'manifest'
|
||||
}]
|
||||
};
|
||||
this.sinon.stub(subject, 'cancel');
|
||||
subject.handleEvent({type: 'home'});
|
||||
assert.ok(subject.cancel.calledOnce);
|
||||
});
|
||||
});
|
||||
|
||||
suite('activity (multi)selection', function() {
|
||||
setup(function() {
|
||||
this.sinon.stub(DefaultActivityHelper, 'getDefaultAction')
|
||||
.returns({ // instead of Promise.resolve() to return in same cycle
|
||||
then: function(cb) { cb(null); }
|
||||
});
|
||||
});
|
||||
|
||||
test('choice when only one item', function() {
|
||||
var stub = this.sinon.stub(subject, 'choose', function(obj) {
|
||||
console.log('called with ' + obj);
|
||||
});
|
||||
subject.chooseActivity({
|
||||
id: 'single',
|
||||
choices: ['first']
|
||||
});
|
||||
assert.ok(stub.calledWith('0'));
|
||||
});
|
||||
|
||||
test('opens action menu with multiple choice', function() {
|
||||
this.sinon.stub(window, 'dispatchEvent');
|
||||
subject.chooseActivity({
|
||||
id: 'single',
|
||||
choices: ['first', 'second']
|
||||
});
|
||||
this.sinon.clock.tick();
|
||||
assert.equal(window.dispatchEvent.getCall(0).args[0].type,
|
||||
'activityrequesting');
|
||||
assert.equal(window.dispatchEvent.getCall(1).args[0].type,
|
||||
'activitymenuwillopen');
|
||||
});
|
||||
|
||||
test('only opens once if we get two activity-choice events', function() {
|
||||
subject.actionMenu = null;
|
||||
this.sinon.stub(ActionMenu.prototype, 'show', function() {
|
||||
subject.actionMenu.active = true;
|
||||
});
|
||||
var evt = {
|
||||
type: 'mozChromeEvent',
|
||||
detail: {
|
||||
type: 'activity-choice',
|
||||
choices: ['first', 'second']
|
||||
}
|
||||
};
|
||||
subject.handleEvent(evt);
|
||||
this.sinon.clock.tick();
|
||||
subject.handleEvent(evt);
|
||||
this.sinon.clock.tick();
|
||||
assert.ok(ActionMenu.prototype.show.calledOnce);
|
||||
});
|
||||
|
||||
test('does not allow a choice that would subvert forward lock', function() {
|
||||
var stub = this.sinon.stub(subject, 'choose');
|
||||
var dispatchStub = this.sinon.stub(window, 'dispatchEvent');
|
||||
subject.chooseActivity({
|
||||
id: 'single',
|
||||
name: 'view',
|
||||
choices: [{
|
||||
manifest: 'app://fl.example.com/manifest.webapp'
|
||||
},{
|
||||
manifest: 'app://fl.gaiamobile.org/manifest.webapp'
|
||||
}]
|
||||
});
|
||||
|
||||
// If it is a view activity and one of the choices is the FL app, we
|
||||
// must always choose the FL app.
|
||||
assert.ok(stub.calledWith('1'));
|
||||
// Ensure that we're not dispatching an activitymenuwillopen event
|
||||
this.sinon.clock.tick();
|
||||
assert.ok(dispatchStub.calledOnce);
|
||||
assert.notEqual(dispatchStub.firstCall.args[0].type,
|
||||
'activitymenuwillopen');
|
||||
});
|
||||
|
||||
test('does not allow another choice that would subvert forward lock',
|
||||
function() {
|
||||
var stub = this.sinon.stub(subject, 'choose');
|
||||
var dispatchStub = this.sinon.stub(window, 'dispatchEvent');
|
||||
subject.chooseActivity({
|
||||
id: 'single',
|
||||
name: 'view',
|
||||
choices: [{
|
||||
manifest: 'app://fl.example.com/e//fl.gaiamobile.org/' +
|
||||
'manifest.webapp'
|
||||
},{
|
||||
manifest: 'app://fl.gaiamobile.org/manifest.webapp'
|
||||
}]
|
||||
});
|
||||
|
||||
// If it is a view activity and one of the choices is the FL app, we
|
||||
// must always choose the FL app.
|
||||
assert.ok(stub.calledWith('1'));
|
||||
// Ensure that we're not dispatching an activitymenuwillopen event
|
||||
this.sinon.clock.tick();
|
||||
assert.ok(dispatchStub.calledOnce);
|
||||
assert.notEqual(dispatchStub.firstCall.args[0].type,
|
||||
'activitymenuwillopen');
|
||||
});
|
||||
|
||||
test('allows choice for non-forward lock view activities', function() {
|
||||
var stub = this.sinon.stub(window, 'dispatchEvent');
|
||||
subject.chooseActivity({
|
||||
id: 'single',
|
||||
name: 'view',
|
||||
choices: [{
|
||||
manifest: 'app://gallery.gaiamobile.org/manifest.webapp'
|
||||
},{
|
||||
manifest: 'app://video.gaiamobile.org/manifest.webapp'
|
||||
}]
|
||||
});
|
||||
|
||||
// If this is a view activity without the FL app as one of the choices
|
||||
// we must allow the user to make a choice.
|
||||
this.sinon.clock.tick();
|
||||
assert.equal(stub.firstCall.args[0].type, 'activityrequesting');
|
||||
assert.equal(stub.secondCall.args[0].type, 'activitymenuwillopen');
|
||||
});
|
||||
|
||||
test('allows choice for non-view activities that include FL', function() {
|
||||
var stub = this.sinon.stub(window, 'dispatchEvent');
|
||||
subject.chooseActivity({
|
||||
id: 'single',
|
||||
name: 'pick',
|
||||
choices: [{
|
||||
manifest: 'app://gallery.gaiamobile.org/manifest.webapp'
|
||||
},{
|
||||
manifest: 'app://fl.gaiamobile.org/manifest.webapp'
|
||||
}]
|
||||
});
|
||||
|
||||
// If this is a not a view activity then we must allow the user to make
|
||||
// a choice even if the FL app is one of the choices.
|
||||
this.sinon.clock.tick();
|
||||
assert.equal(stub.firstCall.args[0].type, 'activityrequesting');
|
||||
assert.equal(stub.secondCall.args[0].type, 'activitymenuwillopen');
|
||||
});
|
||||
|
||||
test('checks for default app on the list', function() {
|
||||
var activity = {
|
||||
id: 'single',
|
||||
name: 'view',
|
||||
activityType: 'image/*',
|
||||
choices: [{
|
||||
manifest: 'app://gallery.gaiamobile.org/manifest.webapp'
|
||||
},{
|
||||
manifest: 'app://camera.gaiamobile.org/manifest.webapp'
|
||||
}]
|
||||
};
|
||||
|
||||
subject.chooseActivity(activity);
|
||||
assert.ok(DefaultActivityHelper.getDefaultAction.calledWith(
|
||||
activity.name, activity.activityType));
|
||||
});
|
||||
|
||||
test('if not on the list, ignore', function() {
|
||||
this.sinon.spy(subject, '_gotDefaultAction');
|
||||
|
||||
var activity = {
|
||||
id: 'single',
|
||||
name: 'pick',
|
||||
activityType: 'image/*',
|
||||
choices: [{
|
||||
manifest: 'app://gallery.gaiamobile.org/manifest.webapp'
|
||||
},{
|
||||
manifest: 'app://camera.gaiamobile.org/manifest.webapp'
|
||||
}]
|
||||
};
|
||||
|
||||
subject.chooseActivity(activity);
|
||||
assert.ok(DefaultActivityHelper.getDefaultAction.calledWith(
|
||||
activity.name, activity.activityType));
|
||||
assert.ok(subject._gotDefaultAction.calledWith(null));
|
||||
});
|
||||
|
||||
test('if on the list, check for default launch associated', function() {
|
||||
DefaultActivityHelper.getDefaultAction
|
||||
.returns({
|
||||
then: function(cb) { cb('fakeManifest'); }
|
||||
});
|
||||
this.sinon.spy(subject, '_gotDefaultAction');
|
||||
|
||||
var activity = {
|
||||
id: 'single',
|
||||
name: 'pick',
|
||||
activityType: 'image/*',
|
||||
choices: [{
|
||||
manifest: 'app://gallery.gaiamobile.org/manifest.webapp'
|
||||
},{
|
||||
manifest: 'app://camera.gaiamobile.org/manifest.webapp'
|
||||
}]
|
||||
};
|
||||
|
||||
subject.chooseActivity(activity);
|
||||
assert.ok(DefaultActivityHelper.getDefaultAction.calledWith(
|
||||
activity.name, activity.activityType));
|
||||
assert.ok(subject._gotDefaultAction.calledWith('fakeManifest'));
|
||||
});
|
||||
|
||||
suite('choosing an activity ', function() {
|
||||
var sendEvent,
|
||||
defaultAct,
|
||||
formatted;
|
||||
|
||||
setup(function() {
|
||||
subject._detail = {
|
||||
id: 'foo',
|
||||
name: 'testactivity',
|
||||
activityType: 'testtype',
|
||||
choices: [{
|
||||
manifest: 'manifest'
|
||||
}]
|
||||
};
|
||||
|
||||
formatted = {
|
||||
id: 'foo',
|
||||
type: 'activity-choice',
|
||||
value: 0,
|
||||
setAsDefault: false
|
||||
};
|
||||
|
||||
sendEvent = this.sinon.stub(subject, '_sendEvent');
|
||||
defaultAct = this.sinon.stub(DefaultActivityHelper, 'setDefaultAction');
|
||||
});
|
||||
|
||||
test('without default activity set >', function() {
|
||||
var set_default = false;
|
||||
formatted.setAsDefault = set_default;
|
||||
subject.choose(0, set_default);
|
||||
|
||||
assert.ok(sendEvent.calledWith(formatted),
|
||||
'calls _sendEvent WITHOUT default activity set');
|
||||
assert.isFalse(defaultAct.called, 'should not call the helper');
|
||||
});
|
||||
|
||||
test('with a default activity set >', function() {
|
||||
var set_default = true;
|
||||
formatted.setAsDefault = set_default;
|
||||
this.sinon.stub(subject, 'publish');
|
||||
subject.choose(0, set_default);
|
||||
|
||||
assert.ok(sendEvent.calledWith(formatted),
|
||||
'calls _sendEvent WITH default activity set');
|
||||
assert.ok(defaultAct.calledWith('testactivity', 'testtype', 'manifest'),
|
||||
'should call the helper with the proper values');
|
||||
assert.ok(subject.publish.calledWith('activitychoosen'));
|
||||
});
|
||||
});
|
||||
|
||||
suite('cancel selection', function() {
|
||||
test('calls _sendEvent', function() {
|
||||
subject._detail = {
|
||||
id: 'foo'
|
||||
};
|
||||
this.sinon.stub(subject, 'publish');
|
||||
var stub = this.sinon.stub(subject, '_sendEvent');
|
||||
var formatted = {
|
||||
id: 'foo',
|
||||
type: 'activity-choice',
|
||||
value: -1
|
||||
};
|
||||
subject.cancel();
|
||||
assert.ok(stub.calledWith(formatted));
|
||||
assert.ok(subject.publish.calledWith('activitycanceled'));
|
||||
});
|
||||
|
||||
test('does not destroy the action menu', function() {
|
||||
subject._detail = {
|
||||
id: 'foo'
|
||||
};
|
||||
var stub = this.sinon.stub(subject.actionMenu, 'hide');
|
||||
subject.cancel();
|
||||
assert.ok(stub.called);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('when a new app is installed', function() {
|
||||
var app,
|
||||
listedName,
|
||||
listedType;
|
||||
|
||||
setup(function() {
|
||||
this.sinon.stub(DefaultActivityHelper, 'getDefaultAction');
|
||||
this.sinon.stub(DefaultActivityHelper, 'setDefaultAction');
|
||||
|
||||
app = {
|
||||
'manifest': {
|
||||
'activities': {
|
||||
'browse': {
|
||||
'filters': {
|
||||
'type': 'photos'
|
||||
}
|
||||
},
|
||||
'pick': {
|
||||
'filters': {
|
||||
'type': ['image/*']
|
||||
}
|
||||
},
|
||||
'open': {
|
||||
'filters': {
|
||||
'type': ['video/*']
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
listedName = 'pick';
|
||||
listedType = 'image/*';
|
||||
|
||||
subject = BaseModule.instantiate('Activities');
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
subject.destroy();
|
||||
});
|
||||
|
||||
test('correctly handles apps without activities', function() {
|
||||
var appWithoutActivities = {
|
||||
'manifest': {}
|
||||
};
|
||||
|
||||
assert.doesNotThrow(
|
||||
() => subject._onNewAppInstalled(appWithoutActivities)
|
||||
);
|
||||
});
|
||||
|
||||
test('manages the default launch for the app\'s activities', function() {
|
||||
DefaultActivityHelper.getDefaultAction
|
||||
.returns({ // instead of Promise.resolve() to return in same cycle
|
||||
then: function(cb) {
|
||||
cb(null);
|
||||
}
|
||||
})
|
||||
.withArgs(listedName, listedType).returns({
|
||||
then: function(cb) {
|
||||
cb('app://fakeapp1.gaiamobile.org/manifest.webapp');
|
||||
}
|
||||
});
|
||||
|
||||
window.dispatchEvent(new CustomEvent('applicationinstall',{
|
||||
detail: {
|
||||
application: app
|
||||
}
|
||||
}));
|
||||
|
||||
assert.ok(DefaultActivityHelper.getDefaultAction
|
||||
.calledWith('browse', 'photos'),
|
||||
'check the list for the first activity');
|
||||
assert.ok(DefaultActivityHelper.getDefaultAction
|
||||
.calledWith('pick', 'image/*'),
|
||||
'check the list for the second activity');
|
||||
assert.ok(DefaultActivityHelper.getDefaultAction
|
||||
.calledWith('open', 'video/*'),
|
||||
'check the list for the third activity');
|
||||
|
||||
assert.ok(DefaultActivityHelper.setDefaultAction
|
||||
.calledWith(listedName, listedType, null),
|
||||
'removes the default app when the activity has it associated');
|
||||
|
||||
assert.ok(DefaultActivityHelper.setDefaultAction.calledOnce,
|
||||
'not called for any other activity');
|
||||
});
|
||||
});
|
||||
|
||||
suite('_sendEvent', function() {
|
||||
test('dispatches a mozContentEvent', function() {
|
||||
var dispatchStub = this.sinon.stub(window, 'dispatchEvent');
|
||||
subject._sendEvent();
|
||||
assert.equal(dispatchStub.getCall(0).args[0].type, 'mozContentEvent');
|
||||
});
|
||||
});
|
||||
|
||||
suite('_listItems', function() {
|
||||
test('called with empty array', function() {
|
||||
var result = subject._listItems([]);
|
||||
assert.equal(result.length, 0);
|
||||
});
|
||||
|
||||
test('returns formatted result', function() {
|
||||
MockApplications.mRegisterMockApp(fakeLaunchConfig1);
|
||||
|
||||
var result = subject._listItems([
|
||||
{
|
||||
manifest: fakeLaunchConfig1.manifestURL,
|
||||
icon: 'http://mozilla'
|
||||
}
|
||||
]);
|
||||
assert.equal(result.length, 1);
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
Reference in a new issue