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
295
gaia/apps/camera/test/unit/controllers/activity_test.js
Executable file
295
gaia/apps/camera/test/unit/controllers/activity_test.js
Executable file
|
|
@ -0,0 +1,295 @@
|
|||
suite('controllers/activity', function() {
|
||||
/*jshint maxlen:false*/
|
||||
'use strict';
|
||||
|
||||
suiteSetup(function(done) {
|
||||
var self = this;
|
||||
requirejs([
|
||||
'app',
|
||||
'controllers/activity',
|
||||
'lib/setting',
|
||||
], function(App, ActivityController, Setting) {
|
||||
self.ActivityController = ActivityController.ActivityController;
|
||||
self.Setting = Setting;
|
||||
self.App = App;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
this.sandbox = sinon.sandbox.create();
|
||||
|
||||
this.app = sinon.createStubInstance(this.App);
|
||||
this.app.win = { location: {} };
|
||||
this.app.activity = {};
|
||||
this.app.settings = {
|
||||
mode: sinon.createStubInstance(this.Setting),
|
||||
pictureSizes: sinon.createStubInstance(this.Setting),
|
||||
recorderProfiles: sinon.createStubInstance(this.Setting),
|
||||
activity: sinon.createStubInstance(this.Setting)
|
||||
};
|
||||
|
||||
// Stub `mozSetMessageHandler`
|
||||
navigator.mozSetMessageHandler = navigator.mozSetMessageHandler || function() {};
|
||||
this.sandbox.stub(navigator, 'mozSetMessageHandler');
|
||||
|
||||
// Aliases
|
||||
this.settings = this.app.settings;
|
||||
this.activity = this.app.activity;
|
||||
|
||||
this.controller = new this.ActivityController(this.app);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
this.sandbox.restore();
|
||||
});
|
||||
|
||||
suite('ActivityController#configure()', function() {
|
||||
test('Should should store the activity type on `app.activity`', function() {
|
||||
this.controller.getName = sinon.stub().returns('pick');
|
||||
this.controller.configure();
|
||||
assert.equal(this.app.activity.pick, true);
|
||||
});
|
||||
});
|
||||
|
||||
suite('ActivityController#bindEvents()', function() {
|
||||
setup(function() {
|
||||
sinon.spy(this.controller, 'setupListener');
|
||||
});
|
||||
|
||||
test('It binds a listener straight away if an activity name was found', function() {
|
||||
this.controller.name = 'pick';
|
||||
this.controller.bindEvents();
|
||||
sinon.assert.calledWith(navigator.mozSetMessageHandler, 'activity');
|
||||
});
|
||||
|
||||
test('It binds a listener straight after critical path if no activity name was found', function() {
|
||||
this.controller.name = undefined;
|
||||
this.controller.bindEvents();
|
||||
sinon.assert.calledWith(this.app.once, 'criticalpathdone');
|
||||
|
||||
// Call the callback
|
||||
this.app.once.withArgs('criticalpathdone').args[0][1]();
|
||||
sinon.assert.calledWith(navigator.mozSetMessageHandler, 'activity');
|
||||
});
|
||||
});
|
||||
|
||||
suite('ActivityController#getName()', function() {
|
||||
test('It returns the name after the #', function() {
|
||||
this.app.win.location.hash = '#pick';
|
||||
var name = this.controller.getName();
|
||||
assert.equal(name, 'pick');
|
||||
});
|
||||
|
||||
test('It returns undefined if no hash fragment is present', function() {
|
||||
this.app.win.location.hash = '';
|
||||
var name = this.controller.getName();
|
||||
assert.equal(name, undefined);
|
||||
});
|
||||
});
|
||||
|
||||
suite('Activity#confgureMode()', function() {
|
||||
test('Should get \'picture\' and \'video\' modes for SMS \'pick\' activity', function() {
|
||||
var activity = {
|
||||
'source': {
|
||||
'data': {
|
||||
'type': ['image/*', 'audio/*', 'video/*'],
|
||||
'maxFileSizeBytes': 307200
|
||||
},
|
||||
'name': 'pick'
|
||||
}
|
||||
};
|
||||
|
||||
this.controller.configureMode(activity);
|
||||
var modes = this.settings.mode.filterOptions.args[0][0];
|
||||
assert.deepEqual(modes, ['picture', 'audio', 'video']);
|
||||
});
|
||||
|
||||
test('Should get \'picture\' and \'video\' modes input[type="file"] \'pick\' activity', function() {
|
||||
var activity = {
|
||||
'source': {
|
||||
'data': {
|
||||
'type': [],
|
||||
'nocrop': true
|
||||
},
|
||||
'name': 'pick'
|
||||
}
|
||||
};
|
||||
|
||||
this.controller.configureMode(activity);
|
||||
var modes = this.settings.mode.filterOptions.args[0][0];
|
||||
assert.deepEqual(modes, ['picture', 'video']);
|
||||
});
|
||||
|
||||
test('Should get \'picture\' mode for input[type="file"] \'pick\' activity', function() {
|
||||
var activity = {
|
||||
'source': {
|
||||
'data': {
|
||||
'type': ['image/gif', 'image/jpeg', 'image/pjpeg',
|
||||
'image/png', 'image/svg+xml', 'image/tiff',
|
||||
'image/vnd.microsoft.icon'],
|
||||
'nocrop': true
|
||||
},
|
||||
'name': 'pick'
|
||||
}
|
||||
};
|
||||
|
||||
this.controller.configureMode(activity);
|
||||
var modes = this.settings.mode.filterOptions.args[0][0];
|
||||
assert.deepEqual(modes, ['picture']);
|
||||
});
|
||||
|
||||
test('Should be able to cope with String as well as Array', function() {
|
||||
var activity = {
|
||||
source: {
|
||||
data: { type: 'image/jpeg' },
|
||||
name: 'pick'
|
||||
}
|
||||
};
|
||||
|
||||
this.controller.configureMode(activity);
|
||||
var modes = this.settings.mode.filterOptions.args[0][0];
|
||||
assert.deepEqual(modes, ['picture']);
|
||||
});
|
||||
|
||||
test('Should get [\'picture\', \'video\'] modes for Lockscreen/Gallery \'record\' activity', function() {
|
||||
var activity = {
|
||||
source: {
|
||||
data: { type: 'photos' },
|
||||
name: 'record'
|
||||
}
|
||||
};
|
||||
|
||||
this.controller.configureMode(activity);
|
||||
var modes = this.settings.mode.filterOptions.args[0][0];
|
||||
assert.deepEqual(modes, ['picture', 'video']);
|
||||
});
|
||||
|
||||
test('Should get [\'video\', \'picture\'] modes for ' +
|
||||
'Video \'record\' activity', function() {
|
||||
var activity = {
|
||||
source: {
|
||||
data: { type: 'videos' },
|
||||
name: 'record'
|
||||
}
|
||||
};
|
||||
|
||||
this.controller.configureMode(activity);
|
||||
var modes = this.settings.mode.filterOptions.args[0][0];
|
||||
assert.deepEqual(modes, ['video', 'picture']);
|
||||
});
|
||||
});
|
||||
|
||||
suite('ActivityController#onMessage()', function() {
|
||||
setup(function() {
|
||||
this.activity = {
|
||||
source: {
|
||||
name: 'pick',
|
||||
data: {
|
||||
type: 'image/jpeg',
|
||||
maxFileSizeBytes: 100
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
sinon.spy(this.controller, 'configureMode');
|
||||
sinon.stub(this.controller, 'getMaxPixelSize').returns('<max-pixel-size>');
|
||||
this.controller.onMessage(this.activity);
|
||||
});
|
||||
|
||||
test('Should emit app events', function() {
|
||||
sinon.assert.calledWith(this.app.emit, 'activity');
|
||||
sinon.assert.calledWith(this.app.emit, 'activity:pick');
|
||||
});
|
||||
|
||||
test('Should configure mode', function() {
|
||||
sinon.assert.called(this.controller.configureMode);
|
||||
});
|
||||
|
||||
test('Should keep a reference to the activity', function() {
|
||||
assert.equal(this.controller.activity, this.activity);
|
||||
});
|
||||
|
||||
test('Should pass `data.maxFileSizeBytes`', function() {
|
||||
var data = this.app.emit.withArgs('activity:pick').args[0][1];
|
||||
assert.equal(data.maxFileSizeBytes, 100);
|
||||
});
|
||||
|
||||
test('Should pass `data.name`', function() {
|
||||
var data = this.app.emit.withArgs('activity:pick').args[0][1];
|
||||
assert.equal(data.name, 'pick');
|
||||
});
|
||||
|
||||
test('Should pass `data.maxPixelSize`', function() {
|
||||
var data = this.app.emit.withArgs('activity:pick').args[0][1];
|
||||
assert.equal(data.maxPixelSize, '<max-pixel-size>');
|
||||
});
|
||||
|
||||
test('Should not do anything if name is unrecognised', function() {
|
||||
this.app.emit.reset();
|
||||
|
||||
this.activity.source.name = 'unknown';
|
||||
this.controller.onMessage(this.activity);
|
||||
|
||||
assert.isFalse(this.app.emit.calledWith('activity'));
|
||||
assert.isFalse(this.app.emit.calledWith('activity:unknown'));
|
||||
});
|
||||
});
|
||||
|
||||
suite('ActivityController#getMaxPixelSize()', function() {
|
||||
setup(function() {
|
||||
|
||||
this.activity = {
|
||||
source: {
|
||||
name: 'pick',
|
||||
data: {
|
||||
type: 'image/jpeg',
|
||||
maxFileSizeBytes: 100,
|
||||
width: 100,
|
||||
height: 100
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
this.settings.activity.get
|
||||
.withArgs('maxPickPixelSize')
|
||||
.returns(480000);
|
||||
|
||||
this.settings.activity.get
|
||||
.withArgs('maxPixelSizeScaleFactor')
|
||||
.returns(2.5);
|
||||
});
|
||||
|
||||
test('Should return pixel estimate of maxFileSizeBytes if supplied', function() {
|
||||
var result = this.controller.getMaxPixelSize(this.activity);
|
||||
assert.equal(result, 267);
|
||||
});
|
||||
|
||||
test('Should return a pixel estimate based on width height if supplied', function() {
|
||||
delete this.activity.source.data.maxFileSizeBytes;
|
||||
var result = this.controller.getMaxPixelSize(this.activity);
|
||||
assert.equal(result, 25000);
|
||||
});
|
||||
|
||||
test('Should return `maxPickPixelSize` if neither supplied', function() {
|
||||
delete this.activity.source.data.maxFileSizeBytes;
|
||||
delete this.activity.source.data.width;
|
||||
delete this.activity.source.data.height;
|
||||
|
||||
var result = this.controller.getMaxPixelSize(this.activity);
|
||||
assert.equal(result, this.settings.activity.get('maxPickPixelSize'));
|
||||
});
|
||||
|
||||
test('Should be able to cope with only one dimension being specified', function() {
|
||||
delete this.activity.source.data.maxFileSizeBytes;
|
||||
delete this.activity.source.data.height;
|
||||
var result = this.controller.getMaxPixelSize(this.activity);
|
||||
assert.equal(result, (1/3 * 100000));
|
||||
|
||||
delete this.activity.source.data.width;
|
||||
this.activity.source.data.height = 100;
|
||||
result = this.controller.getMaxPixelSize(this.activity);
|
||||
assert.equal(result, (1/3 * 100000));
|
||||
});
|
||||
});
|
||||
});
|
||||
235
gaia/apps/camera/test/unit/controllers/battery_test.js
Executable file
235
gaia/apps/camera/test/unit/controllers/battery_test.js
Executable file
|
|
@ -0,0 +1,235 @@
|
|||
suite('controllers/battery', function() {
|
||||
'use strict';
|
||||
|
||||
suiteSetup(function(done) {
|
||||
var self = this;
|
||||
requirejs([
|
||||
'app',
|
||||
'controllers/battery',
|
||||
'lib/settings',
|
||||
'lib/setting',
|
||||
'views/notification'
|
||||
], function(
|
||||
App, BatteryController, Settings, Setting, NotificationView) {
|
||||
self.BatteryController = BatteryController.BatteryController;
|
||||
self.NotificationView = NotificationView;
|
||||
self.Settings = Settings;
|
||||
self.Setting = Setting;
|
||||
self.App = App;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
var levels = {
|
||||
low: 15,
|
||||
verylow: 10,
|
||||
critical: 6,
|
||||
shutdown: 5,
|
||||
healthy: 100
|
||||
};
|
||||
|
||||
this.app = sinon.createStubInstance(this.App);
|
||||
this.app.settings = sinon.createStubInstance(this.Settings);
|
||||
this.app.settings.battery = sinon.createStubInstance(this.Setting);
|
||||
this.app.settings.battery.get.withArgs('levels').returns(levels);
|
||||
this.app.l10n = { get: sinon.stub() };
|
||||
this.app.localized = sinon.stub().returns(true);
|
||||
this.app.views = {
|
||||
notification: sinon.createStubInstance(this.NotificationView)
|
||||
};
|
||||
|
||||
// Fake battery
|
||||
this.app.battery = {
|
||||
addEventListener: sinon.stub(),
|
||||
level: 1,
|
||||
charging: false
|
||||
};
|
||||
|
||||
// Shortcuts
|
||||
this.notification = this.app.views.notification;
|
||||
|
||||
// Keep reference of
|
||||
// things we want to restore
|
||||
this.backup = {
|
||||
mozSettings: navigator.mozSettings
|
||||
};
|
||||
|
||||
// Mock object that mimicks
|
||||
// mozSettings get API. Inside
|
||||
// tests set this.mozSettingsGetResult
|
||||
// define the result of the mock call.
|
||||
navigator.mozSettings = {
|
||||
createLock: function() { return this; },
|
||||
get: sinon.stub(),
|
||||
set: sinon.stub(),
|
||||
addObserver: sinon.stub()
|
||||
};
|
||||
|
||||
navigator.mozSettings.get.withArgs('powersave.enabled').returns(
|
||||
Promise.resolve({'powersave.enabled': false})
|
||||
);
|
||||
|
||||
// Our test instance
|
||||
this.controller = new this.BatteryController(this.app);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
navigator.mozSettings = this.backup.mozSettings;
|
||||
});
|
||||
|
||||
suite('BatteryController()', function() {
|
||||
test('Should listen to the following events', function() {
|
||||
assert.ok(this.app.on.calledWith('change:batteryStatus'));
|
||||
assert.ok(this.app.on.calledWith('change:recording'));
|
||||
assert.ok(this.app.battery.addEventListener.calledWith('levelchange'));
|
||||
assert.ok(this.app.battery.addEventListener.calledWith('chargingchange'));
|
||||
assert.ok(navigator.mozSettings.addObserver.calledWith('powersave.enabled'));
|
||||
});
|
||||
|
||||
test('Should update the status initially', function() {
|
||||
assert.ok(this.app.set.calledWith('batteryStatus', 'healthy'));
|
||||
});
|
||||
|
||||
test('Should query power save state', function() {
|
||||
assert.ok(navigator.mozSettings.get.calledWith('powersave.enabled'));
|
||||
});
|
||||
});
|
||||
|
||||
suite('BatteryController#updateStatus()', function() {
|
||||
test('should call app.set with batteryStatus and battery charging' +
|
||||
' on updateStatus', function() {
|
||||
this.app.battery.charging = true;
|
||||
this.controller.updateStatus();
|
||||
assert.ok(this.app.set.calledWith('batteryStatus', 'charging'));
|
||||
});
|
||||
|
||||
test('should call app.set with batteryStatus and low battery level' +
|
||||
' on updateStatus', function() {
|
||||
this.app.battery.level = 0.11;
|
||||
this.controller.app.get
|
||||
.withArgs('batteryStatus')
|
||||
.returns('charging');
|
||||
|
||||
this.controller.updateStatus();
|
||||
assert.ok(this.app.set.calledWith('batteryStatus', 'low'));
|
||||
});
|
||||
|
||||
test('should call app.set with batteryStatus and verylow battery' +
|
||||
' level on updateStatus', function() {
|
||||
this.app.battery.level = 0.10;
|
||||
this.controller.app.get
|
||||
.withArgs('batteryStatus')
|
||||
.returns('low');
|
||||
|
||||
this.controller.updateStatus();
|
||||
assert.ok(this.app.set.calledWith('batteryStatus', 'verylow'));
|
||||
});
|
||||
|
||||
test('should call app.set with batteryStatus and critical battery' +
|
||||
' level on updateStatus', function() {
|
||||
this.app.battery.level = 0.06;
|
||||
this.controller.app.get
|
||||
.withArgs('batteryStatus')
|
||||
.returns('verylow');
|
||||
|
||||
this.controller.updateStatus();
|
||||
assert.ok(this.app.set.calledWith('batteryStatus', 'critical'));
|
||||
});
|
||||
|
||||
test('should call app.set with batteryStatus and battery shutdown' +
|
||||
' level on updateStatus', function() {
|
||||
this.app.battery.level = 0.05;
|
||||
this.controller.app.get
|
||||
.withArgs('batteryStatus')
|
||||
.returns('critical');
|
||||
|
||||
this.controller.updateStatus();
|
||||
assert.ok(this.app.set.calledWith('batteryStatus', 'shutdown'));
|
||||
});
|
||||
|
||||
test('should call app.set with batteryStatus and battery healthy' +
|
||||
' level on updateStatus', function() {
|
||||
this.app.battery.level = 1;
|
||||
this.controller.app.get
|
||||
.withArgs('batteryStatus')
|
||||
.returns('charging');
|
||||
|
||||
this.controller.updateStatus();
|
||||
assert.ok(this.app.set.calledWith('batteryStatus', 'healthy'));
|
||||
});
|
||||
});
|
||||
|
||||
suite('BatteryController#onStatusChange()', function() {
|
||||
test('Should display notification if required', function() {
|
||||
this.controller.onStatusChange('low');
|
||||
assert.isTrue(this.notification.display.called);
|
||||
this.notification.display.reset();
|
||||
|
||||
this.controller.onStatusChange('verylow');
|
||||
assert.isTrue(this.notification.display.called);
|
||||
this.notification.display.reset();
|
||||
|
||||
this.controller.onStatusChange('critical');
|
||||
assert.isTrue(this.notification.display.called);
|
||||
this.notification.display.reset();
|
||||
|
||||
this.controller.onStatusChange('healthy');
|
||||
assert.isFalse(this.notification.display.called);
|
||||
this.notification.display.reset();
|
||||
|
||||
this.controller.onStatusChange('shutdown');
|
||||
assert.isFalse(this.notification.display.called);
|
||||
this.notification.display.reset();
|
||||
});
|
||||
|
||||
test('Should always clear the last notification', function() {
|
||||
this.controller.onStatusChange('low');
|
||||
assert.isTrue(this.notification.clear.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('BatteryController#updatePowerSave()', function() {
|
||||
setup(function() {
|
||||
this.controller.powerSave = true;
|
||||
this.controller.powerSaveEnabled = true;
|
||||
this.app.get.withArgs('recording').returns(false);
|
||||
});
|
||||
|
||||
test('Should emit `battery:powersave` if changed', function() {
|
||||
this.controller.powerSave = false;
|
||||
this.controller.updatePowerSave();
|
||||
assert.isTrue(this.controller.powerSave);
|
||||
assert.ok(this.app.emit.calledWith('battery:powersave', true));
|
||||
});
|
||||
|
||||
test('Should disable if recording', function() {
|
||||
this.app.get.withArgs('recording').returns(true);
|
||||
this.controller.updatePowerSave();
|
||||
assert.isFalse(this.controller.powerSave);
|
||||
assert.ok(this.app.emit.calledWith('battery:powersave', false));
|
||||
});
|
||||
|
||||
test('Should disable if power save disabled', function() {
|
||||
this.controller.powerSaveEnabled = false;
|
||||
this.controller.updatePowerSave();
|
||||
assert.isFalse(this.controller.powerSave);
|
||||
assert.ok(this.app.emit.calledWith('battery:powersave', false));
|
||||
});
|
||||
});
|
||||
|
||||
suite('BatteryController#onPowerSaveChange()', function() {
|
||||
setup(function() {
|
||||
sinon.stub(this.controller, 'updatePowerSave');
|
||||
this.controller.onPowerSaveChange({settingValue: 'result'});
|
||||
});
|
||||
|
||||
test('Should cache power save enabled state', function() {
|
||||
assert.isTrue(this.controller.powerSaveEnabled === 'result');
|
||||
});
|
||||
|
||||
test('Should call `updatePowerSave`', function() {
|
||||
assert.ok(this.controller.updatePowerSave.called);
|
||||
});
|
||||
});
|
||||
});
|
||||
762
gaia/apps/camera/test/unit/controllers/camera_test.js
Executable file
762
gaia/apps/camera/test/unit/controllers/camera_test.js
Executable file
|
|
@ -0,0 +1,762 @@
|
|||
/*jshint maxlen:false*/
|
||||
|
||||
suite('controllers/camera', function() {
|
||||
'use strict';
|
||||
|
||||
suiteSetup(function(done) {
|
||||
var self = this;
|
||||
requirejs([
|
||||
'app',
|
||||
'controllers/camera',
|
||||
'lib/camera/camera',
|
||||
'lib/settings',
|
||||
'lib/setting',
|
||||
'lib/geo-location'
|
||||
], function(
|
||||
App, CameraController, Camera, Settings, Setting, GeoLocation) {
|
||||
self.CameraController = CameraController.CameraController;
|
||||
self.GeoLocation = GeoLocation;
|
||||
self.Settings = Settings;
|
||||
self.Setting = Setting;
|
||||
self.Camera = Camera;
|
||||
self.App = App;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
this.sandbox = sinon.sandbox.create();
|
||||
this.app = sinon.createStubInstance(this.App);
|
||||
this.app.camera = sinon.createStubInstance(this.Camera);
|
||||
this.app.geolocation = sinon.createStubInstance(this.GeoLocation);
|
||||
this.app.views = {
|
||||
notification: {
|
||||
display: sinon.spy()
|
||||
}
|
||||
};
|
||||
|
||||
// Activity
|
||||
this.app.activity = {};
|
||||
|
||||
this.app.storage = {
|
||||
getItem: sinon.stub(),
|
||||
setItem: sinon.stub()
|
||||
};
|
||||
|
||||
this.app.get.withArgs('batteryStatus').returns('healthy');
|
||||
|
||||
// Settings
|
||||
this.app.settings = sinon.createStubInstance(this.Settings);
|
||||
this.app.settings.cameras = sinon.createStubInstance(this.Setting);
|
||||
this.app.settings.mode = sinon.createStubInstance(this.Setting);
|
||||
this.app.settings.pictureSizes = sinon.createStubInstance(this.Setting);
|
||||
this.app.settings.isoModes = sinon.createStubInstance(this.Setting);
|
||||
this.app.settings.recorderProfiles = sinon.createStubInstance(this.Setting);
|
||||
this.app.settings.flashModes = sinon.createStubInstance(this.Setting);
|
||||
this.app.settings.whiteBalance = sinon.createStubInstance(this.Setting);
|
||||
this.app.settings.hdr = sinon.createStubInstance(this.Setting);
|
||||
this.app.settings.flashModesPicture = sinon.createStubInstance(this.Setting);
|
||||
this.app.settings.countdown = sinon.createStubInstance(this.Setting);
|
||||
|
||||
// Aliases
|
||||
this.settings = this.app.settings;
|
||||
this.notification = this.app.views.notification;
|
||||
this.storage = this.app.storage;
|
||||
this.camera = this.app.camera;
|
||||
|
||||
this.camera.cameraList = ['back', 'front'];
|
||||
|
||||
// Test instance (some tests create there own)
|
||||
this.controller = new this.CameraController(this.app);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
this.sandbox.restore();
|
||||
});
|
||||
|
||||
suite('CameraController()', function() {
|
||||
setup(function() {
|
||||
this.sandbox.stub(this.CameraController.prototype, 'shutdownCamera');
|
||||
});
|
||||
|
||||
test('Should filter the `cameras` setting based on the camera list', function() {
|
||||
sinon.assert.calledWith(this.settings.cameras.filterOptions, this.camera.cameraList);
|
||||
});
|
||||
|
||||
test('Should load camera on app `visible`', function() {
|
||||
assert.isTrue(this.app.on.calledWith('visible', this.controller.loadCamera));
|
||||
});
|
||||
|
||||
test('Should teardown camera on app `hidden`', function() {
|
||||
assert.isTrue(this.app.on.calledWith('hidden', this.controller.shutdownCamera));
|
||||
});
|
||||
|
||||
test('Should relay focus change events', function() {
|
||||
assert.isTrue(this.camera.on.calledWith('change:focus'));
|
||||
assert.isTrue(this.app.firer.calledWith('camera:focusstatechanged'));
|
||||
});
|
||||
|
||||
test('Should listen to storage:changed', function() {
|
||||
assert.isTrue(this.app.on.calledWith('storage:changed'));
|
||||
});
|
||||
|
||||
test('Should listen to \'configured\' event', function() {
|
||||
assert.isTrue(this.camera.on.calledWith('configured'));
|
||||
});
|
||||
|
||||
test('Should listen to the \'activity:pick\' event', function() {
|
||||
sinon.assert.calledWith(this.app.on, 'activity:pick');
|
||||
});
|
||||
|
||||
test('Should query battery status', function() {
|
||||
sinon.assert.calledWith(this.app.get, 'batteryStatus');
|
||||
assert.isFalse(this.controller.lowBattery);
|
||||
});
|
||||
});
|
||||
|
||||
suite('camera.on(\'configured\')', function() {
|
||||
test('Should relay via app event', function() {
|
||||
sinon.assert.calledWith(this.camera.on, 'configured');
|
||||
sinon.assert.calledWith(this.app.firer, 'camera:configured');
|
||||
});
|
||||
});
|
||||
|
||||
suite('on(\'activity:pick\')', function() {
|
||||
setup(function() {
|
||||
var spy = this.app.on.withArgs('activity:pick');
|
||||
this.callback = spy.args[0][1];
|
||||
|
||||
this.data = { maxFileSizeBytes: 100 };
|
||||
this.callback(this.data);
|
||||
});
|
||||
|
||||
test('Should set `maxFileSizeBytes` on camera', function() {
|
||||
sinon.assert.calledWith(this.camera.set, 'maxFileSizeBytes', 100);
|
||||
});
|
||||
|
||||
test('Should disable the camera boot config caching', function() {
|
||||
this.camera.cacheConfig = true;
|
||||
this.callback({});
|
||||
assert.isFalse(this.camera.cacheConfig);
|
||||
});
|
||||
});
|
||||
|
||||
suite('CameraController#onSettingsConfigured()', function() {
|
||||
setup(function() {
|
||||
|
||||
// Mock object that mimicks
|
||||
// mozSettings get API. Inside
|
||||
// tests set this.mozSettingsGetResult
|
||||
// define the result of the mock call.
|
||||
navigator.mozSettings = {
|
||||
createLock: function() { return this; },
|
||||
get: function(key) {
|
||||
var mozSettings = this;
|
||||
setTimeout(function() {
|
||||
var result = {};
|
||||
result[key] = 'the-result';
|
||||
mozSettings.onsuccess({
|
||||
target: {
|
||||
result: result
|
||||
}
|
||||
});
|
||||
});
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
this.app.settings.flashModes.selected.returns('on');
|
||||
this.app.settings.isoModes.get = sinon.spy();
|
||||
this.app.settings.isoModes.selected.returns({key: 'auto'});
|
||||
this.app.settings.pictureSizes.selected.returns({ width: 480, height: 640 });
|
||||
this.app.settings.recorderProfiles.selected.returns('cif');
|
||||
this.app.settings.hdr.selected.returns('on');
|
||||
|
||||
// Returns `this` to allow chaining
|
||||
this.app.camera.setRecorderProfile.returns(this.app.camera);
|
||||
this.app.camera.setPictureSize.returns(this.app.camera);
|
||||
this.app.camera.configureZoom.returns(this.app.camera);
|
||||
|
||||
this.controller = new this.CameraController(this.app);
|
||||
this.controller.onSettingsConfigured();
|
||||
});
|
||||
|
||||
test('Should set flashMode', function() {
|
||||
assert.ok(this.camera.setFlashMode.called);
|
||||
});
|
||||
|
||||
test('Should set hdr', function() {
|
||||
assert.ok(this.camera.setHDR.calledWith('on'));
|
||||
});
|
||||
|
||||
test('Should set recorderProfile', function() {
|
||||
assert.ok(this.camera.setRecorderProfile.calledWith('cif'));
|
||||
});
|
||||
|
||||
test('Should set pictureSize', function() {
|
||||
var arg = this.app.camera.setPictureSize.args[0][0];
|
||||
|
||||
assert.ok(arg.width === 480);
|
||||
assert.ok(arg.height === 640);
|
||||
});
|
||||
});
|
||||
|
||||
suite('CameraController#onRecordingChange', function() {
|
||||
test('Should set `recording` to true if started', function() {
|
||||
this.controller.onRecordingChange('started');
|
||||
assert.ok(this.app.set.calledWith('recording', true));
|
||||
});
|
||||
|
||||
test('Should set `recording` to true if stopped', function() {
|
||||
this.controller.onRecordingChange('stopped');
|
||||
assert.ok(this.app.set.calledWith('recording', false));
|
||||
});
|
||||
|
||||
test('Should not set `recording` if starting or stopping', function() {
|
||||
var self = this;
|
||||
['error', 'starting', 'stopping'].forEach(function(recording) {
|
||||
self.controller.onRecordingChange(recording);
|
||||
sinon.assert.notCalled(self.app.set);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('CameraController#onCaptureKey', function() {
|
||||
setup(function() {
|
||||
this.app.busy = false;
|
||||
this.controller.lowBattery = false;
|
||||
});
|
||||
|
||||
test('`keydown:capture` triggers capture', function() {
|
||||
var callback = this.app.on.withArgs('keydown:capture').args[0][1];
|
||||
var event = { preventDefault: sinon.spy() };
|
||||
|
||||
callback(event);
|
||||
sinon.assert.called(this.camera.capture);
|
||||
});
|
||||
|
||||
test('It calls preventDefault if the capture call doesn\'t return false', function() {
|
||||
var callback = this.app.on.withArgs('keydown:capture').args[0][1];
|
||||
var event = { preventDefault: sinon.spy() };
|
||||
|
||||
this.camera.capture.returns(false);
|
||||
callback(event);
|
||||
sinon.assert.notCalled(event.preventDefault);
|
||||
|
||||
this.camera.capture.returns(undefined);
|
||||
callback(event);
|
||||
sinon.assert.called(event.preventDefault);
|
||||
});
|
||||
|
||||
test('It doesnt capture if countdown is active', function() {
|
||||
this.controller.countdown = 999;
|
||||
var callback = this.app.on.withArgs('keydown:capture').args[0][1];
|
||||
var event = { preventDefault: sinon.spy() };
|
||||
|
||||
callback(event);
|
||||
sinon.assert.notCalled(this.camera.capture);
|
||||
});
|
||||
|
||||
test('It doesnt capture if confirm overlay is shown', function() {
|
||||
this.app.get.withArgs('confirmViewVisible').returns(true);
|
||||
var callback = this.app.on.withArgs('keydown:capture').args[0][1];
|
||||
var event = { preventDefault: sinon.spy() };
|
||||
|
||||
callback(event);
|
||||
sinon.assert.notCalled(this.camera.capture);
|
||||
});
|
||||
|
||||
test('It doesnt capture if busy', function() {
|
||||
this.app.busy = true;
|
||||
var callback = this.app.on.withArgs('keydown:capture').args[0][1];
|
||||
var event = { preventDefault: sinon.spy() };
|
||||
|
||||
callback(event);
|
||||
sinon.assert.notCalled(this.camera.capture);
|
||||
});
|
||||
});
|
||||
|
||||
suite('CameraController#onFocusKey', function() {
|
||||
setup(function() {
|
||||
this.app.busy = false;
|
||||
this.camera.focus = {
|
||||
focus: this.sinon.spy()
|
||||
};
|
||||
});
|
||||
|
||||
test('`keydown:focus` triggers focus', function() {
|
||||
var callback = this.app.on.withArgs('keydown:focus').args[0][1];
|
||||
var event = { preventDefault: sinon.spy() };
|
||||
|
||||
callback(event);
|
||||
sinon.assert.called(this.camera.focus.focus);
|
||||
});
|
||||
|
||||
test('It doesnt focus if busy', function() {
|
||||
this.app.busy = true;
|
||||
var callback = this.app.on.withArgs('keydown:focus').args[0][1];
|
||||
var event = { preventDefault: sinon.spy() };
|
||||
|
||||
callback(event);
|
||||
sinon.assert.notCalled(this.camera.focus.focus);
|
||||
});
|
||||
});
|
||||
|
||||
suite('CameraController#setMode()', function() {
|
||||
test('It sets the flash mode', function() {
|
||||
this.controller.setMode();
|
||||
sinon.assert.called(this.notification.display);
|
||||
sinon.assert.called(this.camera.setFlashMode);
|
||||
});
|
||||
|
||||
test('It emits `camera:willchange` event', function() {
|
||||
this.controller.setMode();
|
||||
sinon.assert.calledWith(this.app.emit, 'camera:willchange');
|
||||
});
|
||||
|
||||
test('It sets the mode once the viewfinder is hidden', function() {
|
||||
this.controller.setMode('my-mode');
|
||||
sinon.assert.calledWith(this.app.once, 'viewfinder:hidden');
|
||||
|
||||
// call the callback
|
||||
this.app.once.withArgs('viewfinder:hidden').args[0][1]();
|
||||
sinon.assert.calledWith(this.camera.setMode, 'my-mode');
|
||||
});
|
||||
|
||||
test('It doesn\'t set the do anything if the mode didn\'t change', function() {
|
||||
this.camera.isMode.returns(true);
|
||||
this.controller.setMode('my-mode');
|
||||
assert.isFalse(this.app.emit.calledWith('camera:willchange'));
|
||||
});
|
||||
});
|
||||
|
||||
suite('CameraController#setCamera()', function() {
|
||||
test('It emits `camera:willchange` event', function() {
|
||||
this.controller.setMode();
|
||||
sinon.assert.calledWith(this.app.emit, 'camera:willchange');
|
||||
});
|
||||
|
||||
test('It sets the camera once the viewfinder is hidden', function() {
|
||||
this.controller.setCamera('back');
|
||||
sinon.assert.calledWith(this.app.once, 'viewfinder:hidden');
|
||||
|
||||
// call the callback
|
||||
this.app.once.withArgs('viewfinder:hidden').args[0][1]();
|
||||
sinon.assert.calledWith(this.camera.setCamera, 'back');
|
||||
});
|
||||
});
|
||||
|
||||
suite('CameraController#updatePictureSize()', function() {
|
||||
setup(function() {
|
||||
this.settings.mode.selected
|
||||
.withArgs('key')
|
||||
.returns('picture');
|
||||
|
||||
this.settings.pictureSizes.selected
|
||||
.withArgs('data')
|
||||
.returns({ width: 400, height: 300 });
|
||||
});
|
||||
|
||||
test('It emits `camera:willchange` event', function() {
|
||||
this.controller.updatePictureSize();
|
||||
sinon.assert.calledWith(this.app.emit, 'camera:willchange');
|
||||
});
|
||||
|
||||
test('It sets the camera once the viewfinder is hidden', function() {
|
||||
this.controller.updatePictureSize();
|
||||
sinon.assert.calledWith(this.app.once, 'viewfinder:hidden');
|
||||
|
||||
// call the callback
|
||||
this.app.once.withArgs('viewfinder:hidden').args[0][1]();
|
||||
sinon.assert.calledWith(this.camera.setPictureSize, { width: 400, height: 300 });
|
||||
});
|
||||
|
||||
test('It doesn\'t proceed if `pictureSize` didn\'t change', function() {
|
||||
this.camera.isPictureSize.returns(true);
|
||||
this.controller.updatePictureSize();
|
||||
assert.isFalse(this.app.emit.calledWith('camera:willchange'));
|
||||
});
|
||||
|
||||
suite('`video` mode', function() {
|
||||
setup(function() {
|
||||
this.settings.mode.selected
|
||||
.withArgs('key')
|
||||
.returns('video');
|
||||
});
|
||||
|
||||
test('It doesn\'t emit `camera:willchange` if in `video` mode', function() {
|
||||
this.controller.updatePictureSize();
|
||||
assert.isFalse(this.app.emit.calledWith('camera:willchange'));
|
||||
});
|
||||
|
||||
test('It calls `camera.setPictureSize`, but doesn\'t reconfigure camera', function() {
|
||||
this.controller.updatePictureSize();
|
||||
sinon.assert.calledWith(
|
||||
this.camera.setPictureSize,
|
||||
{ width: 400, height: 300 },
|
||||
{ configure: false }
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('CameraController#updateRecorderProfile()', function() {
|
||||
setup(function() {
|
||||
this.settings.mode.selected
|
||||
.withArgs('key')
|
||||
.returns('video');
|
||||
|
||||
this.settings.recorderProfiles.selected
|
||||
.withArgs('key')
|
||||
.returns('720p');
|
||||
});
|
||||
|
||||
test('It emits `camera:willchange` event', function() {
|
||||
this.controller.updateRecorderProfile();
|
||||
sinon.assert.calledWith(this.app.emit, 'camera:willchange');
|
||||
});
|
||||
|
||||
test('It sets the camera once the viewfinder is hidden', function() {
|
||||
this.controller.updateRecorderProfile();
|
||||
sinon.assert.calledWith(this.app.once, 'viewfinder:hidden');
|
||||
|
||||
// call the callback
|
||||
this.app.once.withArgs('viewfinder:hidden').args[0][1]();
|
||||
sinon.assert.calledWith(this.camera.setRecorderProfile, '720p');
|
||||
});
|
||||
|
||||
test('It doesn\'t proceed if `recorderProfile` didn\'t change', function() {
|
||||
this.camera.isRecorderProfile.returns(true);
|
||||
this.controller.updateRecorderProfile();
|
||||
assert.isFalse(this.app.emit.calledWith('camera:willchange'));
|
||||
});
|
||||
|
||||
suite('`picture` mode', function() {
|
||||
setup(function() {
|
||||
this.settings.mode.selected
|
||||
.withArgs('key')
|
||||
.returns('picture');
|
||||
});
|
||||
|
||||
test('It doesn\'t emit `camera:willchange` if in `video` mode', function() {
|
||||
this.controller.updateRecorderProfile();
|
||||
assert.isFalse(this.app.emit.calledWith('camera:willchange'));
|
||||
});
|
||||
|
||||
test('It calls `camera.setRecorderProfile`, but doesn\'t reconfigure camera', function() {
|
||||
this.controller.updateRecorderProfile();
|
||||
sinon.assert.calledWith(
|
||||
this.camera.setRecorderProfile,
|
||||
'720p',
|
||||
{ configure: false }
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('CameraController#onHDRChange()', function() {
|
||||
test('Should set flashModesPicture \'off\' when hdr is set to \'on\'',
|
||||
function() {
|
||||
var flashModesPicture = this.app.settings.flashModesPicture;
|
||||
|
||||
flashModesPicture.selected.withArgs('key').returns('on');
|
||||
this.controller.onHDRChange('on');
|
||||
|
||||
assert.ok(flashModesPicture.select.calledWith('off'));
|
||||
});
|
||||
});
|
||||
|
||||
suite('CameraController#setHDR()', function() {
|
||||
setup(function() {
|
||||
this.settings.hdr.selected
|
||||
.withArgs('key')
|
||||
.returns('on');
|
||||
});
|
||||
|
||||
test('Should call camera.setHDR with given value', function() {
|
||||
this.controller.setHDR();
|
||||
sinon.assert.calledWith(this.camera.setHDR, 'on');
|
||||
});
|
||||
|
||||
test('Should not call camera.setHDR if `hdrDisabled`', function() {
|
||||
this.controller.hdrDisabled = true;
|
||||
this.controller.setHDR();
|
||||
sinon.assert.notCalled(this.camera.setHDR);
|
||||
});
|
||||
});
|
||||
|
||||
suite('CameraController#onFlashModeChange()', function() {
|
||||
setup(function() {
|
||||
this.settings.hdr.selected
|
||||
.withArgs('key')
|
||||
.returns('on');
|
||||
});
|
||||
|
||||
test('Should change hdr to off if flash is on', function() {
|
||||
this.controller.hdrDisabled = false;
|
||||
this.controller.onFlashModeChange('on');
|
||||
assert.ok(this.settings.hdr.select.calledWith('off'));
|
||||
});
|
||||
|
||||
test('Should not change HDR if flash is off', function() {
|
||||
this.controller.hdrDisabled = false;
|
||||
this.controller.onFlashModeChange('off');
|
||||
assert.ok(!this.settings.hdr.select.called);
|
||||
});
|
||||
|
||||
test('Should not change HDR if HDR is off', function() {
|
||||
this.settings.hdr.selected.withArgs('key').returns('off');
|
||||
this.controller.hdrDisabled = true;
|
||||
this.controller.onFlashModeChange('auto');
|
||||
assert.ok(!this.settings.hdr.select.called);
|
||||
});
|
||||
|
||||
test('Should not change HDR if HDR is disabled', function() {
|
||||
this.controller.hdrDisabled = true;
|
||||
this.controller.onFlashModeChange('auto');
|
||||
assert.ok(!this.settings.hdr.select.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('CameraController#capture()', function() {
|
||||
setup(function() {
|
||||
this.controller.galleryOpen = false;
|
||||
this.controller.lowBattery = false;
|
||||
sinon.spy(this.controller, 'startCountdown');
|
||||
});
|
||||
|
||||
test('Should not start countdown if no countdown setting is set', function() {
|
||||
this.app.settings.countdown.selected.returns(0);
|
||||
this.app.get.withArgs('timerActive').returns(false);
|
||||
this.app.get.withArgs('recording').returns(false);
|
||||
this.controller.capture();
|
||||
sinon.assert.notCalled(this.controller.startCountdown);
|
||||
});
|
||||
|
||||
test('Should not start countdown if countdown is already active', function() {
|
||||
this.app.settings.countdown.selected.returns(5);
|
||||
this.controller.countdown = 999;
|
||||
this.app.get.withArgs('recording').returns(false);
|
||||
this.controller.capture();
|
||||
sinon.assert.notCalled(this.controller.startCountdown);
|
||||
});
|
||||
|
||||
test('Should not start countdown if recording', function() {
|
||||
this.app.settings.countdown.selected.returns(5);
|
||||
this.app.get.withArgs('timerActive').returns(false);
|
||||
this.app.get.withArgs('recording').returns(true);
|
||||
this.controller.capture();
|
||||
sinon.assert.notCalled(this.controller.startCountdown);
|
||||
});
|
||||
|
||||
test('Should otherwise start countdown', function() {
|
||||
this.app.settings.countdown.selected.returns(5);
|
||||
this.app.get.withArgs('timerActive').returns(false);
|
||||
this.app.get.withArgs('recording').returns(false);
|
||||
this.controller.capture();
|
||||
sinon.assert.calledOnce(this.controller.startCountdown);
|
||||
});
|
||||
|
||||
test('Should pass the current geolocation position', function() {
|
||||
this.app.geolocation.position = 123;
|
||||
this.controller.capture();
|
||||
assert.ok(this.app.camera.capture.args[0][0].position === 123);
|
||||
});
|
||||
|
||||
test('Should return false if low battery', function() {
|
||||
this.controller.lowBattery = true;
|
||||
assert.ok(this.controller.capture() === false);
|
||||
});
|
||||
|
||||
test('Should return false if gallery open', function() {
|
||||
this.controller.galleryOpen = true;
|
||||
assert.ok(this.controller.capture() === false);
|
||||
});
|
||||
});
|
||||
|
||||
suite('CameraController#onBatteryStatusChange()', function() {
|
||||
setup(function() {
|
||||
this.controller.loadCamera = sinon.stub();
|
||||
sinon.spy(this.controller, 'shutdownCamera');
|
||||
this.controller.clearCountdown = sinon.stub();
|
||||
});
|
||||
|
||||
test('Should call onBatteryStatuchange on \'change:batteryStatus\'',
|
||||
function() {
|
||||
this.app.on.calledWith('change:batteryStatus', this.onBatteryStatusChange);
|
||||
});
|
||||
|
||||
test('Should load camera on `healthy` status', function() {
|
||||
this.controller.onBatteryStatusChange('healthy');
|
||||
assert.isTrue(this.controller.loadCamera.called);
|
||||
});
|
||||
|
||||
test('Should shutdown camera on `shutdown` status', function() {
|
||||
this.controller.onBatteryStatusChange('shutdown');
|
||||
assert.isTrue(this.controller.shutdownCamera.called);
|
||||
});
|
||||
|
||||
test('Should clear countdown on `shutdown` status', function() {
|
||||
this.controller.onBatteryStatusChange('shutdown');
|
||||
sinon.assert.calledOnce(this.controller.clearCountdown);
|
||||
});
|
||||
|
||||
test('Should prevent capture on low battery', function() {
|
||||
this.controller.onBatteryStatusChange('shutdown');
|
||||
this.controller.capture();
|
||||
assert.isFalse(this.camera.capture.called);
|
||||
|
||||
this.controller.onBatteryStatusChange('healthy');
|
||||
this.controller.capture();
|
||||
assert.isTrue(this.camera.capture.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('CameraController#startCountdown()', function() {
|
||||
setup(function() {
|
||||
this.app.settings.countdown.selected.withArgs('value').returns(5);
|
||||
this.clock = this.sinon.useFakeTimers();
|
||||
this.controller.lowBattery = false;
|
||||
});
|
||||
|
||||
test('Emits a `countdown:started` event', function() {
|
||||
this.controller.startCountdown();
|
||||
sinon.assert.calledWith(this.app.emit, 'countdown:started', 5);
|
||||
});
|
||||
|
||||
test('Emits a `countdown:tick` event each second', function() {
|
||||
this.controller.startCountdown();
|
||||
this.clock.tick(1000);
|
||||
sinon.assert.calledWith(this.app.emit, 'countdown:tick', 4);
|
||||
this.clock.tick(1000);
|
||||
sinon.assert.calledWith(this.app.emit, 'countdown:tick', 3);
|
||||
this.clock.tick(1000);
|
||||
sinon.assert.calledWith(this.app.emit, 'countdown:tick', 2);
|
||||
this.clock.tick(1000);
|
||||
sinon.assert.calledWith(this.app.emit, 'countdown:tick', 1);
|
||||
});
|
||||
|
||||
test('Emits a `countdown:ended` event once it reaches 0', function() {
|
||||
this.controller.startCountdown();
|
||||
this.clock.tick(5000);
|
||||
sinon.assert.calledWith(this.app.emit, 'countdown:ended');
|
||||
});
|
||||
|
||||
test('It calls camera.capture once ended', function() {
|
||||
this.controller.startCountdown();
|
||||
this.clock.tick(5000);
|
||||
sinon.assert.calledOnce(this.camera.capture);
|
||||
});
|
||||
|
||||
test('It clears the coundown when the app base el is clicked', function() {
|
||||
var proto = this.controller.constructor.prototype;
|
||||
var clearCountdown = this.sinon.spy(proto, 'clearCountdown');
|
||||
|
||||
this.app.on.reset();
|
||||
|
||||
var controller = new this.CameraController(this.app);
|
||||
var callback = this.app.on.withArgs('click').args[0][1];
|
||||
|
||||
controller.startCountdown();
|
||||
this.clock.tick(2000);
|
||||
callback();
|
||||
|
||||
sinon.assert.calledOnce(clearCountdown);
|
||||
});
|
||||
});
|
||||
|
||||
suite('CameraController#loadCamera()', function() {
|
||||
setup(function() {
|
||||
this.app.hidden = false;
|
||||
this.app.activity.pick = false;
|
||||
this.app.isSharingActivity = sinon.stub();
|
||||
this.app.isSharingActivity.returns(false);
|
||||
this.app.showSpinner = sinon.stub();
|
||||
this.controller.galleryOpen = false;
|
||||
this.controller.lowBattery = false;
|
||||
});
|
||||
|
||||
test('It doesn\'t load the camera if the battery is low', function() {
|
||||
this.controller.lowBattery = true;
|
||||
this.controller.loadCamera();
|
||||
sinon.assert.notCalled(this.camera.load);
|
||||
});
|
||||
|
||||
test('It does load the camera if the battery is not low', function() {
|
||||
this.controller.loadCamera();
|
||||
sinon.assert.called(this.camera.load);
|
||||
});
|
||||
|
||||
test('It doesn\'t load the camera if gallery is open', function() {
|
||||
this.controller.galleryOpen = true;
|
||||
this.controller.loadCamera();
|
||||
sinon.assert.notCalled(this.camera.load);
|
||||
});
|
||||
|
||||
test('It does load the camera if gallery is closed', function() {
|
||||
this.controller.loadCamera();
|
||||
sinon.assert.called(this.camera.load);
|
||||
});
|
||||
|
||||
test('It doesn\'t load the camera if app is hidden', function() {
|
||||
this.app.hidden = true;
|
||||
this.controller.loadCamera();
|
||||
sinon.assert.notCalled(this.camera.load);
|
||||
sinon.assert.notCalled(this.app.showSpinner);
|
||||
});
|
||||
|
||||
test('It does load the camera if app is visible', function() {
|
||||
this.controller.loadCamera();
|
||||
sinon.assert.called(this.camera.load);
|
||||
sinon.assert.notCalled(this.app.showSpinner);
|
||||
});
|
||||
|
||||
test('It shows the spinner if loading and requested', function() {
|
||||
this.controller.loadCamera(true);
|
||||
sinon.assert.called(this.app.showSpinner);
|
||||
});
|
||||
});
|
||||
|
||||
suite('CameraController#shutdownCamera()', function() {
|
||||
setup(function() {
|
||||
this.controller.shutdownCamera();
|
||||
});
|
||||
|
||||
test('Should stop shutdown the camera', function() {
|
||||
assert.isTrue(this.camera.shutdown.called);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
suite('CameraController#onStorageChanged()', function() {
|
||||
test('Should stop recording if not available', function() {
|
||||
this.controller.onStorageChanged('unavailable');
|
||||
assert.isTrue(this.camera.stopRecording.called);
|
||||
});
|
||||
|
||||
test('Should not stop recording if available', function() {
|
||||
this.controller.onStorageChanged('available');
|
||||
assert.isTrue(this.camera.stopRecording.notCalled);
|
||||
});
|
||||
});
|
||||
|
||||
suite('CameraController#onGalleryOpened()', function() {
|
||||
test('Should store gallery open state', function() {
|
||||
this.controller.shutdownCamera = sinon.stub();
|
||||
this.controller.galleryOpen = false;
|
||||
this.controller.onGalleryOpened();
|
||||
assert.isTrue(this.controller.galleryOpen);
|
||||
sinon.assert.called(this.controller.shutdownCamera);
|
||||
});
|
||||
});
|
||||
|
||||
suite('CameraController#onGalleryClosed()', function() {
|
||||
test('It loads the camera', function() {
|
||||
this.controller.loadCamera = sinon.stub();
|
||||
this.controller.galleryOpen = true;
|
||||
this.controller.onGalleryClosed();
|
||||
assert.isFalse(this.controller.galleryOpen);
|
||||
sinon.assert.calledWith(this.controller.loadCamera, true);
|
||||
});
|
||||
});
|
||||
});
|
||||
88
gaia/apps/camera/test/unit/controllers/confirm_test.js
Executable file
88
gaia/apps/camera/test/unit/controllers/confirm_test.js
Executable file
|
|
@ -0,0 +1,88 @@
|
|||
/*jshint maxlen:false*/
|
||||
'use strict';
|
||||
|
||||
suite('controllers/confirm', function() {
|
||||
suiteSetup(function(done) {
|
||||
var modules = this.modules = {};
|
||||
requirejs([
|
||||
'controllers/confirm',
|
||||
'views/confirm'
|
||||
], function(Controller, ConfirmView) {
|
||||
modules.controller = Controller;
|
||||
modules.ConfirmView = ConfirmView;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
var ConfirmView = this.modules.ConfirmView;
|
||||
var Controller = this.modules.controller;
|
||||
|
||||
this.app = {
|
||||
activity: {},
|
||||
camera: { on: sinon.spy() },
|
||||
ConfirmView: ConfirmView,
|
||||
on: sinon.spy()
|
||||
};
|
||||
|
||||
this.controller = new Controller(this.app);
|
||||
this.sandbox = sinon.sandbox.create();
|
||||
this.sandbox.spy(this.app, 'ConfirmView');
|
||||
this.sandbox.stub(ConfirmView.prototype);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
this.sandbox.restore();
|
||||
});
|
||||
|
||||
suite('ConfirmController()', function() {
|
||||
test('Should bind to app `newmedia` event', function() {
|
||||
assert.ok(this.app.on.calledWith('newmedia'));
|
||||
});
|
||||
});
|
||||
|
||||
suite('ConfirmController#onRecordingChange()', function() {
|
||||
setup(function() {
|
||||
this.app.activity.pick = true;
|
||||
this.controller.recording = true;
|
||||
sinon.stub(this.controller, 'renderView');
|
||||
});
|
||||
|
||||
test('Should set `recording` to true if starting', function() {
|
||||
this.controller.recording = false;
|
||||
this.controller.onRecordingChange('starting');
|
||||
assert.isTrue(this.controller.recording);
|
||||
});
|
||||
|
||||
test('Should set `recording` to false if error', function() {
|
||||
this.controller.onRecordingChange('error');
|
||||
assert.isFalse(this.controller.recording);
|
||||
});
|
||||
|
||||
test('Should render view if stopped', function() {
|
||||
this.controller.onRecordingChange('stopped');
|
||||
sinon.assert.called(this.controller.renderView);
|
||||
});
|
||||
|
||||
test('Should not do anything if recording failed and stopped', function() {
|
||||
this.controller.recording = false;
|
||||
this.controller.onRecordingChange('stopped');
|
||||
sinon.assert.notCalled(this.controller.renderView);
|
||||
});
|
||||
|
||||
test('Should not do anything if there is no active activity', function() {
|
||||
this.app.activity.pick = false;
|
||||
this.controller.onRecordingChange('stopped');
|
||||
sinon.assert.notCalled(this.controller.renderView);
|
||||
});
|
||||
});
|
||||
|
||||
suite('ConfirmController#onNewMedia()', function() {
|
||||
test('Should not do anything if there is no active activity', function() {
|
||||
this.app.activity.pick = false;
|
||||
this.controller.onNewMedia({});
|
||||
assert.ok(this.app.ConfirmView.notCalled);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
214
gaia/apps/camera/test/unit/controllers/controls_test.js
Executable file
214
gaia/apps/camera/test/unit/controllers/controls_test.js
Executable file
|
|
@ -0,0 +1,214 @@
|
|||
|
||||
suite('controllers/controls', function() {
|
||||
/*jshint maxlen:false*/
|
||||
'use strict';
|
||||
suiteSetup(function(done) {
|
||||
var self = this;
|
||||
requirejs([
|
||||
'app',
|
||||
'lib/camera/camera',
|
||||
'controllers/controls',
|
||||
'views/controls',
|
||||
'lib/settings',
|
||||
'lib/setting'
|
||||
], function(
|
||||
App, Camera, ControlsController, ControlsView, Settings, Setting) {
|
||||
self.App = App;
|
||||
self.Camera = Camera;
|
||||
self.ControlsController = ControlsController.ControlsController;
|
||||
self.ControlsView = ControlsView;
|
||||
self.Settings = Settings;
|
||||
self.Setting = Setting;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
this.app = sinon.createStubInstance(this.App);
|
||||
this.app.camera = sinon.createStubInstance(this.Camera);
|
||||
this.app.settings = sinon.createStubInstance(this.Settings);
|
||||
this.app.settings.mode = sinon.createStubInstance(this.Setting);
|
||||
this.app.views = { controls: sinon.createStubInstance(this.ControlsView) };
|
||||
this.app.activity = { allowedTypes: {} };
|
||||
|
||||
// Fake available modes
|
||||
this.app.settings.mode.get
|
||||
.withArgs('options')
|
||||
.returns([{ key: 'picture' }, { key: 'video' }]);
|
||||
|
||||
// Aliases
|
||||
this.controls = this.app.views.controls;
|
||||
this.view = this.app.views.controls;
|
||||
this.settings = this.app.settings;
|
||||
|
||||
this.controller = new this.ControlsController(this.app);
|
||||
this.state = {};
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
delete this.controller;
|
||||
});
|
||||
|
||||
suite('ControlsController()', function() {
|
||||
test('Should listen to the following events', function() {
|
||||
assert.ok(this.app.on.calledWith('localized', this.view.localize));
|
||||
assert.ok(this.app.on.calledWith('previewgallery:opened',
|
||||
this.view.hide));
|
||||
assert.ok(this.app.on.calledWith('previewgallery:closed',
|
||||
this.view.show));
|
||||
});
|
||||
|
||||
test('Should *not* show the cancel button when *not* within a \'pick\' activity', function() {
|
||||
assert.isTrue(this.app.views.controls.set.calledWith('cancel', false));
|
||||
});
|
||||
|
||||
test('Should show the cancel button when within activity', function() {
|
||||
this.app.activity.pick = true;
|
||||
this.state.controller = new this.ControlsController(this.app);
|
||||
assert.isTrue(this.app.views.controls.set.calledWith('cancel', true));
|
||||
});
|
||||
|
||||
test('It sets the mode to the value of the \'mode\' setting', function() {
|
||||
|
||||
// Test 'picture'
|
||||
this.app.settings.mode.selected.returns('picture');
|
||||
var controller = new this.ControlsController(this.app);
|
||||
sinon.assert.calledWith(this.view.setMode, 'picture');
|
||||
this.view.set.reset();
|
||||
|
||||
// Test 'video'
|
||||
this.app.settings.mode.selected.returns('video');
|
||||
controller = new this.ControlsController(this.app);
|
||||
sinon.assert.calledWith(this.view.setMode, 'video');
|
||||
this.view.set.reset();
|
||||
});
|
||||
|
||||
test('Should call the preview when click on thumbnail', function() {
|
||||
assert.ok(this.view.on.calledWith('click:thumbnail'));
|
||||
});
|
||||
|
||||
test('Should remove the capture button highlight when shutter fires', function() {
|
||||
sinon.assert.calledWith(this.app.on, 'camera:shutter');
|
||||
|
||||
// Call the callback
|
||||
this.app.on.withArgs('camera:shutter').args[0][1]();
|
||||
|
||||
sinon.assert.calledWith(this.view.unset, 'capture-active');
|
||||
});
|
||||
|
||||
test('Should disable the controls when the camera is busy', function() {
|
||||
// Call the callback and check the view was disabled
|
||||
this.app.on.withArgs('busy').args[0][1]();
|
||||
sinon.assert.called(this.view.disable);
|
||||
});
|
||||
|
||||
suite('app.once(\'loaded\')', function() {
|
||||
setup(function() {
|
||||
// Call the callback
|
||||
this.app.once.withArgs('loaded').args[0][1]();
|
||||
});
|
||||
|
||||
test('It enables the controls', function() {
|
||||
sinon.assert.called(this.view.enable);
|
||||
});
|
||||
|
||||
test('It \'restores\' the controls when the camera is \'ready\' from thereon after', function() {
|
||||
sinon.assert.calledWith(this.app.on, 'ready', this.controller.restore);
|
||||
});
|
||||
});
|
||||
|
||||
test('Should hide the controls when the countdown is started', function() {
|
||||
sinon.assert.calledWith(
|
||||
this.app.on,
|
||||
'countdown:started',
|
||||
this.controller.onCountdownStarted
|
||||
);
|
||||
});
|
||||
|
||||
test('Should restore the controls when the countdown is cleared', function() {
|
||||
sinon.assert.calledWith(
|
||||
this.app.on,
|
||||
'countdown:ended',
|
||||
this.controller.onCountdownStopped
|
||||
);
|
||||
});
|
||||
|
||||
test('Should disable the view intitially until camera is ready', function() {
|
||||
sinon.assert.called(this.view.disable);
|
||||
});
|
||||
});
|
||||
|
||||
suite('Set view screen reader visibility based on settings opened/closed',
|
||||
function() {
|
||||
test('settings opened -> hide view from screen reader', function() {
|
||||
// Check the view is hidden from the screen reader.
|
||||
this.app.on.withArgs('settings:opened').args[0][1]();
|
||||
sinon.assert.calledWith(this.view.setScreenReaderVisible, false);
|
||||
});
|
||||
|
||||
test('settings closed -> show view to screen reader', function() {
|
||||
// Check the view is visible to the screen reader.
|
||||
this.app.on.withArgs('settings:closed').args[0][1]();
|
||||
sinon.assert.calledWith(this.view.setScreenReaderVisible, true);
|
||||
});
|
||||
});
|
||||
|
||||
suite('ControlsController#configureMode()', function() {
|
||||
test('It\'s not switchable when only one mode is available', function() {
|
||||
|
||||
// Fake avaialable modes
|
||||
this.app.settings.mode.get
|
||||
.withArgs('options')
|
||||
.returns([{ key: 'picture' }]);
|
||||
|
||||
this.controller.configureMode();
|
||||
assert.isTrue(this.view.disable.calledWith('switch'));
|
||||
});
|
||||
});
|
||||
|
||||
suite('ControlsController#onCaptureClick', function() {
|
||||
setup(function() {
|
||||
sinon.spy(this.controller, 'captureHighlightOn');
|
||||
this.controller.onCaptureClick();
|
||||
});
|
||||
|
||||
test('Should highlight the capture button', function() {
|
||||
assert.isTrue(this.controller.captureHighlightOn.calledOnce);
|
||||
});
|
||||
|
||||
test('Should fire a \'capture\' event on the app', function() {
|
||||
assert.isTrue(this.app.emit.calledWith('capture'));
|
||||
});
|
||||
});
|
||||
|
||||
suite('ControlsController#onCameraWillChange', function() {
|
||||
test('When camera is reconfiguring it suspends the mode switch', function() {
|
||||
this.controller.onCameraWillChange();
|
||||
assert.isTrue(this.view.suspendModeSwitch.calledWith(true));
|
||||
});
|
||||
});
|
||||
|
||||
suite('ControlsController#onCameraConfigured', function() {
|
||||
test('When camera is configured it unsuspends the mode switch', function() {
|
||||
this.controller.onCameraConfigured();
|
||||
assert.isTrue(this.view.suspendModeSwitch.calledWith(false));
|
||||
});
|
||||
});
|
||||
|
||||
suite('ControlsController#onRecordingChange', function() {
|
||||
test('When recording view\'s setCaptureLabel should be called', function() {
|
||||
[true, false].forEach(function(recording) {
|
||||
this.controller.onRecordingChange(recording);
|
||||
assert.isTrue(this.view.setCaptureLabel.calledWith(recording));
|
||||
}, this);
|
||||
});
|
||||
});
|
||||
|
||||
suite('ControlsController.onViewModeChanged()', function() {
|
||||
test('It switches to the next mode setting', function() {
|
||||
this.controller.onViewModeChanged();
|
||||
sinon.assert.notCalled(this.view.enable);
|
||||
sinon.assert.called(this.settings.mode.next);
|
||||
});
|
||||
});
|
||||
});
|
||||
242
gaia/apps/camera/test/unit/controllers/hud_test.js
Executable file
242
gaia/apps/camera/test/unit/controllers/hud_test.js
Executable file
|
|
@ -0,0 +1,242 @@
|
|||
suite('controllers/hud', function() {
|
||||
/*jshint maxlen:false*/
|
||||
'use strict';
|
||||
|
||||
suiteSetup(function(done) {
|
||||
var self = this;
|
||||
requirejs([
|
||||
'app',
|
||||
'lib/camera/camera',
|
||||
'controllers/hud',
|
||||
'views/hud',
|
||||
'views/controls',
|
||||
'views/viewfinder',
|
||||
'views/notification',
|
||||
'lib/settings',
|
||||
'lib/setting'
|
||||
], function(
|
||||
App, Camera, HudController, HudView, ControlsView,
|
||||
ViewfinderView, NotificationView, Settings, Setting
|
||||
) {
|
||||
self.HudController = HudController.HudController;
|
||||
self.NotificationView = NotificationView;
|
||||
self.ViewfinderView = ViewfinderView;
|
||||
self.ControlsView = ControlsView;
|
||||
self.Settings = Settings;
|
||||
self.Setting = Setting;
|
||||
self.HudView = HudView;
|
||||
self.Camera = Camera;
|
||||
self.App = App;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
this.app = sinon.createStubInstance(this.App);
|
||||
this.app.camera = sinon.createStubInstance(this.Camera);
|
||||
this.app.l10n = { get: sinon.spy(function(value) { return value; }) };
|
||||
this.app.views = {
|
||||
notification: sinon.createStubInstance(this.NotificationView),
|
||||
viewfinder: sinon.createStubInstance(this.ViewfinderView),
|
||||
controls: sinon.createStubInstance(this.ControlsView),
|
||||
hud: sinon.createStubInstance(this.HudView)
|
||||
};
|
||||
|
||||
// Stub 'cameras' setting
|
||||
this.app.settings = {};
|
||||
this.app.settings.cameras = sinon.createStubInstance(this.Setting);
|
||||
this.app.settings.flashModes = sinon.createStubInstance(this.Setting);
|
||||
this.app.settings.settingsMenu = sinon.createStubInstance(this.Setting);
|
||||
this.app.settings.mode = sinon.createStubInstance(this.Setting);
|
||||
this.app.settings.cameras.get.withArgs('options').returns([]);
|
||||
|
||||
// For convenience
|
||||
this.notification = this.app.views.notification;
|
||||
this.viewfinder = this.app.views.viewfinder;
|
||||
this.controls = this.app.views.controls;
|
||||
this.settings = this.app.settings;
|
||||
this.camera = this.app.camera;
|
||||
this.view = this.app.views.hud;
|
||||
|
||||
// Our test instance
|
||||
this.controller = new this.HudController(this.app);
|
||||
});
|
||||
|
||||
suite('HudController()', function() {
|
||||
test('Should listen to the following events', function() {
|
||||
assert.ok(this.app.settings.flashModes.on.calledWith('change:selected'));
|
||||
assert.ok(this.app.settings.mode.on.calledWith('change:selected'));
|
||||
assert.ok(this.app.settings.cameras.on.calledWith('change:selected'));
|
||||
|
||||
assert.ok(this.app.on.calledWith('settings:configured'));
|
||||
assert.ok(this.app.on.calledWith('ready'));
|
||||
assert.ok(this.app.on.calledWith('busy'));
|
||||
assert.ok(this.app.on.calledWith('localized'));
|
||||
assert.ok(this.app.on.calledWith('change:recording'));
|
||||
assert.ok(this.app.on.calledWith('countdown:started'));
|
||||
assert.ok(this.app.on.calledWith('countdown:ended'));
|
||||
assert.ok(this.app.on.calledWith('settings:opened'));
|
||||
assert.ok(this.app.on.calledWith('settings:closed'));
|
||||
|
||||
assert.ok(this.app.on.calledWith('previewgallery:opened',
|
||||
this.view.hide));
|
||||
assert.ok(this.app.on.calledWith('previewgallery:closed',
|
||||
this.view.show));
|
||||
});
|
||||
|
||||
test('Should update the flash support once settings are configured', function() {
|
||||
sinon.assert.calledWith(this.app.on, 'settings:configured', this.controller.updateFlashSupport);
|
||||
});
|
||||
|
||||
test('Should set \'camera\' to \'busy\' on view when busy', function() {
|
||||
assert.ok(this.view.setter.calledWith('camera', 'busy'));
|
||||
assert.ok(this.app.on.calledWith('busy'));
|
||||
});
|
||||
|
||||
test('Should set \'camera\' to \'ready\' on view when ready', function() {
|
||||
assert.ok(this.view.setter.calledWith('camera', 'ready'));
|
||||
assert.ok(this.app.on.calledWith('ready'));
|
||||
});
|
||||
|
||||
test('Should set \'countdown\' to \'active\' on view when started', function() {
|
||||
assert.ok(this.view.setter.calledWith('countdown', 'active'));
|
||||
assert.ok(this.app.on.calledWith('countdown:started'));
|
||||
});
|
||||
|
||||
test('Should set \'countdown\' to \'inactive\' on view when countdown ended or cleared', function() {
|
||||
assert.ok(this.view.setter.calledWith('countdown', 'inactive'));
|
||||
assert.ok(this.app.on.calledWith('countdown:ended'));
|
||||
});
|
||||
|
||||
test('Should set `recording` state on hud', function() {
|
||||
assert.ok(this.view.setter.calledWith('recording'));
|
||||
assert.ok(this.app.on.calledWith('change:recording'));
|
||||
});
|
||||
|
||||
test('Should enable camera button depending on support', function() {
|
||||
this.settings.cameras.get
|
||||
.withArgs('options')
|
||||
.returns(['back']);
|
||||
|
||||
sinon.assert.calledWith(this.view.enable, 'camera', false);
|
||||
|
||||
this.settings.cameras.get
|
||||
.withArgs('options')
|
||||
.returns(['back', 'front']);
|
||||
|
||||
this.controller = new this.HudController(this.app);
|
||||
sinon.assert.calledWith(this.view.enable, 'camera', true);
|
||||
});
|
||||
|
||||
test('Should disable flash initially until support is known', function() {
|
||||
sinon.assert.calledWith(this.view.disable, 'flash');
|
||||
});
|
||||
});
|
||||
|
||||
suite('HudController#localize()', function() {
|
||||
setup(function() {
|
||||
this.controller.view = {
|
||||
setFlashModeLabel: sinon.spy(),
|
||||
setCameraLabel: sinon.spy(),
|
||||
setMenuLabel: sinon.spy()
|
||||
};
|
||||
});
|
||||
|
||||
test('Should cycle to the next flash setting', function() {
|
||||
this.controller.localize();
|
||||
assert.ok(this.controller.view.setFlashModeLabel.called);
|
||||
assert.ok(this.controller.view.setCameraLabel.called);
|
||||
assert.ok(this.controller.view.setMenuLabel.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('HudController#onFlashClick()', function() {
|
||||
setup(function() {
|
||||
this.settings.hdr = {
|
||||
selected: sinon.spy()
|
||||
};
|
||||
});
|
||||
|
||||
test('Should cycle to the next flash setting', function() {
|
||||
this.controller.onFlashClick();
|
||||
assert.ok(this.settings.flashModes.next.calledOnce);
|
||||
});
|
||||
|
||||
test('Should set the new value on the hud view', function() {
|
||||
this.settings.flashModes.selected.withArgs('key').returns('auto');
|
||||
this.controller.onFlashClick();
|
||||
assert.ok(this.view.set.calledWith('flashMode', 'auto'));
|
||||
});
|
||||
|
||||
test('Should notify', function() {
|
||||
sinon.spy(this.controller, 'notify');
|
||||
this.controller.onFlashClick();
|
||||
assert.ok(this.controller.notify.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('HudController#notify()', function() {
|
||||
setup(function() {
|
||||
this.settings.hdr = {
|
||||
selected: sinon.spy()
|
||||
};
|
||||
});
|
||||
|
||||
test('Should display a notification', function() {
|
||||
this.controller.onFlashClick();
|
||||
assert.ok(this.notification.display.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('HudController#updateFlashMode()', function() {
|
||||
setup(function() {
|
||||
this.settings.flashModes = {
|
||||
selected: sinon.spy()
|
||||
};
|
||||
});
|
||||
|
||||
test('Should update the flash mode', function() {
|
||||
this.controller.updateFlashMode();
|
||||
assert.ok(this.settings.flashModes.selected.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('HudController#updateCamera()', function() {
|
||||
setup(function() {
|
||||
this.settings.cameras = {
|
||||
selected: sinon.spy()
|
||||
};
|
||||
});
|
||||
|
||||
test('Should update the camera', function() {
|
||||
this.controller.updateCamera();
|
||||
assert.ok(this.settings.cameras.selected.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('HudController#onCameraClick()', function() {
|
||||
setup(function() {
|
||||
this.callback = this.view.on.withArgs('click:camera').args[0][1];
|
||||
});
|
||||
|
||||
test('Should clear notifications', function() {
|
||||
this.callback();
|
||||
sinon.assert.called(this.notification.clear);
|
||||
});
|
||||
|
||||
test('Should call move to next available camera', function() {
|
||||
this.callback();
|
||||
sinon.assert.calledOnce(this.settings.cameras.next);
|
||||
});
|
||||
|
||||
test('Should debounce (immediate) rapid button taps', function() {
|
||||
this.callback();
|
||||
sinon.assert.called(this.settings.cameras.next);
|
||||
this.callback();
|
||||
this.callback();
|
||||
this.callback();
|
||||
this.callback();
|
||||
sinon.assert.calledOnce(this.settings.cameras.next);
|
||||
});
|
||||
});
|
||||
});
|
||||
100
gaia/apps/camera/test/unit/controllers/indicators_test.js
Executable file
100
gaia/apps/camera/test/unit/controllers/indicators_test.js
Executable file
|
|
@ -0,0 +1,100 @@
|
|||
suite('controllers/indicators', function() {
|
||||
/*jshint maxlen:false*/
|
||||
'use strict';
|
||||
|
||||
suiteSetup(function(done) {
|
||||
var self = this;
|
||||
requirejs([
|
||||
'controllers/indicators',
|
||||
'views/indicators',
|
||||
'lib/setting',
|
||||
'app'
|
||||
], function(IndicatorsController, IndicatorsView, Setting, App) {
|
||||
self.IndicatorsController = IndicatorsController.IndicatorsController;
|
||||
self.IndicatorsView = IndicatorsView;
|
||||
self.Setting = Setting;
|
||||
self.App = App;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
this.app = sinon.createStubInstance(this.App);
|
||||
this.app.settings = {
|
||||
hdr: sinon.createStubInstance(this.Setting),
|
||||
mode: sinon.createStubInstance(this.Setting),
|
||||
countdown: sinon.createStubInstance(this.Setting),
|
||||
indicators: sinon.createStubInstance(this.Setting)
|
||||
};
|
||||
this.app.views = {
|
||||
indicators: sinon.createStubInstance(this.IndicatorsView)
|
||||
};
|
||||
|
||||
// Shortcuts
|
||||
this.view = this.app.views.indicators;
|
||||
this.settings = this.app.settings;
|
||||
|
||||
// Return values
|
||||
this.settings.hdr.selected.returns('on');
|
||||
this.settings.countdown.selected.returns('on');
|
||||
this.app.get.withArgs('batteryStatus').returns('healthy');
|
||||
|
||||
// Create our test instance
|
||||
this.controller = new this.IndicatorsController(this.app);
|
||||
});
|
||||
|
||||
suite('IndicatorsController()', function() {
|
||||
test('Should bind settings change events', function() {
|
||||
assert.ok(this.app.settings.countdown.on.calledWith('change:selected'));
|
||||
assert.ok(this.app.settings.mode.on.calledWith('change:selected'));
|
||||
assert.ok(this.app.settings.hdr.on.calledWith('change:selected'));
|
||||
assert.ok(this.app.on.calledWith('change:batteryStatus'));
|
||||
assert.ok(this.app.on.calledWith('settings:configured'));
|
||||
assert.ok(this.app.on.calledWith('settings:opened'));
|
||||
assert.ok(this.app.on.calledWith('settings:closed'));
|
||||
|
||||
assert.ok(this.app.on.calledWith('previewgallery:opened',
|
||||
this.view.hide));
|
||||
assert.ok(this.app.on.calledWith('previewgallery:closed',
|
||||
this.view.show));
|
||||
});
|
||||
|
||||
test('It sets the battery status initially', function() {
|
||||
sinon.assert.calledWith(this.view.set, 'battery', 'healthy');
|
||||
});
|
||||
|
||||
test('It sets hdr status initially', function() {
|
||||
sinon.assert.calledWith(this.view.set, 'hdr', 'on');
|
||||
});
|
||||
|
||||
test('It sets countdown status initially', function() {
|
||||
sinon.assert.calledWith(this.view.set, 'countdown', 'on');
|
||||
});
|
||||
|
||||
test('It reconfigures when the settings change', function() {
|
||||
sinon.assert.calledWith(this.app.on, 'settings:configured', this.controller.configure);
|
||||
});
|
||||
|
||||
test('It binds view setter for aria-hidden true', function() {
|
||||
sinon.assert.calledWith(this.view.setter, 'ariaHidden', true);
|
||||
});
|
||||
|
||||
test('It binds view setter for aria-hidden false', function() {
|
||||
sinon.assert.calledWith(this.view.setter, 'ariaHidden', false);
|
||||
});
|
||||
});
|
||||
|
||||
suite('IndicatorsController#configure()', function() {
|
||||
test('Should set the current \'hdr\' and \'countdown\' keys' +
|
||||
'on the view', function() {
|
||||
var view = this.app.views.indicators;
|
||||
|
||||
this.app.settings.indicators.get.returns(this.enabledValues);
|
||||
this.controller = new this.IndicatorsController(this.app);
|
||||
this.controller.configure();
|
||||
|
||||
assert.ok(view.set.calledWith('countdown', 'on'));
|
||||
assert.ok(view.set.calledWith('hdr', 'on'));
|
||||
});
|
||||
});
|
||||
});
|
||||
127
gaia/apps/camera/test/unit/controllers/media_test.js
Executable file
127
gaia/apps/camera/test/unit/controllers/media_test.js
Executable file
|
|
@ -0,0 +1,127 @@
|
|||
suite('controllers/media', function() {
|
||||
'use strict';
|
||||
|
||||
suiteSetup(function(done) {
|
||||
var self = this;
|
||||
requirejs([
|
||||
'app',
|
||||
'controllers/media',
|
||||
'lib/settings',
|
||||
], function(App, MediaController, Settings) {
|
||||
self.MediaController =
|
||||
MediaController.MediaController;
|
||||
self.Settings = Settings;
|
||||
self.App = App;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
this.app = sinon.createStubInstance(this.App);
|
||||
this.app.settings = sinon.createStubInstance(this.Settings);
|
||||
this.app.require = sinon.stub();
|
||||
this.app.activity = {};
|
||||
this.app.settings.previewGallery = {
|
||||
get: sinon.spy()
|
||||
};
|
||||
|
||||
// Our test instance
|
||||
this.controller = new this.MediaController(this.app);
|
||||
});
|
||||
|
||||
suite('MediaController()', function() {
|
||||
setup(function() {
|
||||
this.controller.settings = {
|
||||
previewGallery: {
|
||||
get: sinon.spy()
|
||||
}
|
||||
};
|
||||
|
||||
this.clock = sinon.useFakeTimers();
|
||||
});
|
||||
|
||||
test('Should listen to the following events', function() {
|
||||
assert.ok(this.app.on.calledWith('storage:itemdeleted'));
|
||||
assert.ok(this.app.on.calledWith('storage:changed'));
|
||||
assert.ok(this.app.on.calledWith('previewgallery:deletevideo'));
|
||||
assert.ok(this.app.on.calledWith('previewgallery:deletepicture'));
|
||||
assert.ok(this.app.on.calledWith('newmedia'));
|
||||
assert.ok(this.app.on.calledWith('hidden'));
|
||||
assert.ok(this.app.on.calledWith('lazyloaded'));
|
||||
});
|
||||
|
||||
test('Check onNewMedia callback', function() {
|
||||
var item = {
|
||||
blob: {},
|
||||
filepath: 'root/fileName',
|
||||
isVideo: true
|
||||
};
|
||||
|
||||
this.app.activity = {
|
||||
active: false
|
||||
};
|
||||
|
||||
this.controller.items.unshift = sinon.spy();
|
||||
this.controller.updateThumbnail = sinon.spy();
|
||||
this.controller.onNewMedia(item);
|
||||
assert.ok(this.controller.items.unshift.called);
|
||||
assert.ok(this.controller.updateThumbnail.called);
|
||||
});
|
||||
|
||||
test('Should Check Storage Changed', function() {
|
||||
var item = {
|
||||
blob: {},
|
||||
filepath: 'root/fileName',
|
||||
isVideo: true
|
||||
};
|
||||
|
||||
var data = {
|
||||
path: 'root/fileName'
|
||||
};
|
||||
|
||||
this.app.activity = {
|
||||
active: false
|
||||
};
|
||||
|
||||
this.controller.configure = sinon.spy();
|
||||
this.controller.updateThumbnail = sinon.spy();
|
||||
this.controller.onNewMedia(item);
|
||||
this.controller.onStorageChanged('unavailable');
|
||||
assert.ok(this.controller.configure.called);
|
||||
assert.ok(this.controller.updateThumbnail.called);
|
||||
});
|
||||
|
||||
test('Should Check the Item Deleted', function() {
|
||||
var item = {
|
||||
blob: {},
|
||||
filepath: 'root/fileName',
|
||||
isVideo: true
|
||||
};
|
||||
|
||||
var data = {
|
||||
path: 'root/fileName'
|
||||
};
|
||||
|
||||
this.app.activity = {
|
||||
active: false
|
||||
};
|
||||
|
||||
this.controller.updateThumbnail = sinon.spy();
|
||||
this.controller.updatePreviewGallery = sinon.spy();
|
||||
this.controller.onNewMedia(item);
|
||||
this.controller.onItemDeleted(data);
|
||||
sinon.assert.calledWith(this.app.emit, 'media:deleted');
|
||||
});
|
||||
|
||||
test('Should close the preview on blur if in \'secureMode\'', function() {
|
||||
this.app.inSecureMode = true;
|
||||
this.controller.closePreview = sinon.spy();
|
||||
this.controller.configure = sinon.spy();
|
||||
this.controller.updateThumbnail = sinon.spy();
|
||||
this.controller.onHidden();
|
||||
assert.ok(this.controller.configure.called);
|
||||
assert.ok(this.controller.updateThumbnail.called);
|
||||
sinon.assert.calledWith(this.app.emit, 'media:configured');
|
||||
});
|
||||
});
|
||||
});
|
||||
141
gaia/apps/camera/test/unit/controllers/overlay_test.js
Executable file
141
gaia/apps/camera/test/unit/controllers/overlay_test.js
Executable file
|
|
@ -0,0 +1,141 @@
|
|||
/*jshint maxlen:false*/
|
||||
'use strict';
|
||||
|
||||
suite('controllers/overlay', function() {
|
||||
suiteSetup(function(done) {
|
||||
var self = this;
|
||||
requirejs([
|
||||
'app',
|
||||
'controllers/overlay',
|
||||
'views/overlay'
|
||||
], function(App, controller, Overlay) {
|
||||
self.Controller = controller;
|
||||
self.Overlay = Overlay;
|
||||
self.App = App;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
this.app = sinon.createStubInstance(this.App);
|
||||
this.app.activity = {
|
||||
pick: false,
|
||||
cancel: sinon.spy()
|
||||
};
|
||||
this.app.require = sinon.stub();
|
||||
this.app.require.callsArgWith(1, this.Overlay);
|
||||
|
||||
this.controller = new this.Controller(this.app);
|
||||
});
|
||||
|
||||
suite('OverlayController()', function() {
|
||||
test('Should bind to events', function() {
|
||||
assert.ok(this.app.on.calledWith('storage:changed'));
|
||||
assert.ok(this.app.on.calledWith('change:batteryStatus'));
|
||||
assert.ok(this.app.on.calledWith('camera:requesting'));
|
||||
assert.ok(this.app.on.calledWith('camera:error'));
|
||||
});
|
||||
});
|
||||
|
||||
suite('OverlayController#onStorageChanged()', function() {
|
||||
setup(function() {
|
||||
sinon.stub(this.controller, 'updateOverlay');
|
||||
});
|
||||
|
||||
test('Should *not* insert a new overlay', function() {
|
||||
this.controller.onStorageChanged('available');
|
||||
sinon.assert.calledWith(this.controller.updateOverlay, 'storage', false, 'available');
|
||||
});
|
||||
|
||||
test('Should create overlay whenever the value is not \'available\'', function() {
|
||||
this.controller.onStorageChanged('foo');
|
||||
sinon.assert.calledWith(this.controller.updateOverlay, 'storage', true, 'foo');
|
||||
});
|
||||
});
|
||||
|
||||
suite('OverlayController#onBatteryChanged()', function() {
|
||||
setup(function() {
|
||||
sinon.stub(this.controller, 'updateOverlay');
|
||||
});
|
||||
|
||||
test('Should create overlay if status is shutdown', function() {
|
||||
this.controller.onBatteryChanged('shutdown');
|
||||
sinon.assert.calledWith(this.controller.updateOverlay, 'battery', true, 'shutdown');
|
||||
});
|
||||
|
||||
test('Should destroy overlay if previous is shutdown', function() {
|
||||
this.controller.onBatteryChanged('foo');
|
||||
sinon.assert.calledWith(this.controller.updateOverlay, 'battery', false, 'foo');
|
||||
});
|
||||
});
|
||||
|
||||
suite('OverlayController#onCameraRequesting()', function() {
|
||||
setup(function() {
|
||||
sinon.stub(this.controller, 'updateOverlay');
|
||||
});
|
||||
|
||||
test('Should destroy overlay', function() {
|
||||
this.controller.onCameraRequesting();
|
||||
sinon.assert.calledWith(this.controller.updateOverlay, 'cameraError', false);
|
||||
});
|
||||
});
|
||||
|
||||
suite('OverlayController#onCameraError()', function() {
|
||||
setup(function() {
|
||||
sinon.stub(this.controller, 'updateOverlay');
|
||||
});
|
||||
|
||||
test('Should create overlay', function() {
|
||||
this.controller.onCameraError('foo');
|
||||
sinon.assert.calledWith(this.controller.updateOverlay, 'cameraError', true, 'foo');
|
||||
});
|
||||
});
|
||||
|
||||
suite('OverlayController#updateOverlay()', function() {
|
||||
setup(function() {
|
||||
this.OverlayProto = this.Overlay.prototype;
|
||||
sinon.spy(this.OverlayProto, 'initialize');
|
||||
sinon.stub(this.OverlayProto, 'appendTo', function() { return this; });
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
this.OverlayProto.initialize.restore();
|
||||
this.OverlayProto.appendTo.restore();
|
||||
});
|
||||
|
||||
test('Should not insert overlay when key is unknown', function() {
|
||||
this.controller.updateOverlay('storage', true, 'foobar');
|
||||
assert.isFalse(this.OverlayProto.appendTo.called);
|
||||
});
|
||||
|
||||
test('Should insert overlay when key is known', function() {
|
||||
this.controller.updateOverlay('storage', true, 'unavailable');
|
||||
assert.isTrue(this.OverlayProto.appendTo.called);
|
||||
});
|
||||
|
||||
test('Should not be closable if type is \'request-fail\'', function() {
|
||||
this.controller.updateOverlay('cameraError', true, 'request-fail');
|
||||
assert.isFalse(this.OverlayProto.initialize.args[0][0].closable);
|
||||
|
||||
this.app.activity.pick = true;
|
||||
this.controller.updateOverlay('cameraError', true, 'request-fail');
|
||||
assert.isFalse(this.OverlayProto.initialize.args[0][0].closable);
|
||||
});
|
||||
|
||||
test('Should not be closable if activity not pending', function() {
|
||||
this.controller.updateOverlay('storage', true, 'unavailable');
|
||||
assert.isFalse(this.OverlayProto.initialize.args[0][0].closable);
|
||||
});
|
||||
|
||||
test('Should be closable only if activity is pending', function() {
|
||||
this.app.activity.pick = true;
|
||||
this.controller.updateOverlay('storage', true, 'unavailable');
|
||||
assert.isTrue(this.OverlayProto.initialize.args[0][0].closable);
|
||||
});
|
||||
|
||||
test('Should append the overlay to the body', function() {
|
||||
this.controller.updateOverlay('storage', true, 'unavailable');
|
||||
assert.isTrue(this.OverlayProto.appendTo.calledWith(document.body));
|
||||
});
|
||||
});
|
||||
});
|
||||
294
gaia/apps/camera/test/unit/controllers/preview-gallery_test.js
Executable file
294
gaia/apps/camera/test/unit/controllers/preview-gallery_test.js
Executable file
|
|
@ -0,0 +1,294 @@
|
|||
suite('controllers/preview-gallery', function() {
|
||||
'use strict';
|
||||
|
||||
suiteSetup(function(done) {
|
||||
var self = this;
|
||||
requirejs([
|
||||
'app',
|
||||
'controllers/preview-gallery',
|
||||
'lib/settings',
|
||||
'views/preview-gallery',
|
||||
'lib/storage',
|
||||
'lib/orientation'
|
||||
], function(
|
||||
App,PreviewGalleryController, Settings, PreviewGalleryView,
|
||||
Storage, orientation) {
|
||||
self.PreviewGalleryController =
|
||||
PreviewGalleryController.PreviewGalleryController;
|
||||
self.Settings = Settings;
|
||||
self.PreviewGalleryView = PreviewGalleryView;
|
||||
self.Storage = Storage;
|
||||
self.App = App;
|
||||
self.orientation = orientation;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
this.app = sinon.createStubInstance(this.App);
|
||||
this.app.settings = sinon.createStubInstance(this.Settings);
|
||||
this.app.require = sinon.stub();
|
||||
this.app.activity = {};
|
||||
|
||||
// Fake dialog calls the
|
||||
// 'delete' callback sync.
|
||||
this.app.dialog = {
|
||||
show: function(title, msg, cancel, del) { del.callback(); },
|
||||
hide: sinon.stub()
|
||||
};
|
||||
|
||||
// Our test instance
|
||||
this.previewGalleryController = new this.PreviewGalleryController(this.app);
|
||||
|
||||
// For convenience
|
||||
this.camera = this.app.camera;
|
||||
this.previewGallery = this.previewGalleryController.view;
|
||||
this.controller = this.previewGalleryController;
|
||||
this.storage = this.app.storage;
|
||||
this.dialog = this.app.dialog;
|
||||
});
|
||||
|
||||
suite('PreviewGalleryController()', function() {
|
||||
setup(function() {
|
||||
var MozActivity = function() {};
|
||||
if (!window.MozActivity) {
|
||||
window.MozActivity = MozActivity;
|
||||
}
|
||||
sinon.stub(window, 'MozActivity');
|
||||
|
||||
this.previewGalleryController.storage = {
|
||||
deleteImage: sinon.spy(),
|
||||
deleteVideo: sinon.spy(),
|
||||
on: sinon.spy()
|
||||
};
|
||||
|
||||
this.previewGalleryController.settings = {
|
||||
activity: {
|
||||
get: sinon.spy()
|
||||
},
|
||||
};
|
||||
|
||||
this.previewGalleryController.resizeImageAndSave =
|
||||
function(options, done) {
|
||||
done(options.blob);
|
||||
};
|
||||
|
||||
this.app.require.callsArgWith(1,
|
||||
this.previewGalleryController.resizeImageAndSave);
|
||||
|
||||
this.clock = sinon.useFakeTimers();
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
window.MozActivity.restore();
|
||||
});
|
||||
|
||||
test('Should listen to the following events', function() {
|
||||
this.previewGalleryController.bindEvents();
|
||||
|
||||
assert.ok(this.app.on.calledWith('preview', this.controller.openPreview));
|
||||
assert.ok(this.app.on.calledWith('hidden', this.controller.closePreview));
|
||||
assert.ok(this.app.on.calledWith('media:configured', this.controller.updatePreviewGallery));
|
||||
assert.ok(this.app.on.calledWith('media:deleted', this.controller.updatePreviewGallery));
|
||||
});
|
||||
|
||||
test('Should open the gallery app when gallery button is pressed',
|
||||
function() {
|
||||
this.previewGalleryController.onGalleryButtonClick();
|
||||
var arg = window.MozActivity.args[0][0];
|
||||
|
||||
assert.ok(arg.name === 'browse');
|
||||
assert.ok(arg.data.type === 'photos');
|
||||
});
|
||||
|
||||
test('Should shareCurrentItem whose type is image', function() {
|
||||
var item = {
|
||||
blob: new Blob(['empty-image'], {'type': 'image/jpeg'}),
|
||||
filepath: 'root/folder1/folder2/fileName',
|
||||
isImage: true
|
||||
};
|
||||
this.previewGalleryController.items = [item];
|
||||
this.previewGalleryController.currentItemIndex = 0;
|
||||
this.previewGalleryController.shareCurrentItem();
|
||||
|
||||
assert.ok(this.app.emit.calledWith('busy', 'resizingImage'));
|
||||
|
||||
// Get first argument, of first call
|
||||
var arg = window.MozActivity.args[0][0];
|
||||
|
||||
assert.ok(arg.name === 'share');
|
||||
assert.ok(arg.data.type === 'image/*');
|
||||
assert.ok(arg.data.number === 1);
|
||||
assert.ok(arg.data.blobs[0] === item.blob);
|
||||
assert.ok(arg.data.filenames[0] === 'fileName');
|
||||
assert.ok(arg.data.filepaths[0] === item.filepath);
|
||||
});
|
||||
|
||||
test('Should shareCurrentItem whose type is video', function() {
|
||||
var item = {
|
||||
blob: {},
|
||||
filepath: 'root/folder1/folder2/fileName',
|
||||
isVideo: true
|
||||
};
|
||||
this.previewGalleryController.items = [item];
|
||||
this.previewGalleryController.currentItemIndex = 0;
|
||||
this.previewGalleryController.shareCurrentItem();
|
||||
|
||||
// Get first argument, of first call
|
||||
var arg = window.MozActivity.args[0][0];
|
||||
|
||||
assert.ok(arg.name === 'share');
|
||||
assert.ok(arg.data.type === 'video/*');
|
||||
assert.ok(arg.data.number === 1);
|
||||
assert.ok(arg.data.blobs[0] === item.blob);
|
||||
assert.ok(arg.data.filenames[0] === 'fileName');
|
||||
assert.ok(arg.data.filepaths[0] === item.filepath);
|
||||
});
|
||||
|
||||
suite('PreviewGalleryController#deleteCurrentItem()', function() {
|
||||
setup(function() {
|
||||
|
||||
});
|
||||
|
||||
test('Should deleteCurrentItem which is image', function() {
|
||||
var item = {
|
||||
blob: {},
|
||||
filepath: 'root/fileName',
|
||||
isVideo: false
|
||||
};
|
||||
|
||||
this.previewGalleryController.items = [item];
|
||||
this.previewGalleryController.currentItemIndex = 0;
|
||||
this.previewGalleryController.deleteCurrentItem();
|
||||
|
||||
assert.ok(this.app.emit.calledWith('previewgallery:deletepicture', 'root/fileName'));
|
||||
});
|
||||
|
||||
test('Should deleteCurrentItem which is video', function() {
|
||||
var item = {
|
||||
blob: {},
|
||||
filepath: 'root/fileName',
|
||||
isVideo: true
|
||||
};
|
||||
|
||||
this.previewGalleryController.items = [item];
|
||||
this.previewGalleryController.currentItemIndex = 0;
|
||||
this.previewGalleryController.deleteCurrentItem();
|
||||
|
||||
assert.ok(this.app.emit.calledWith('previewgallery:deletevideo', 'root/fileName'));
|
||||
});
|
||||
});
|
||||
|
||||
test('Should go to next image on handleSwipe(\'left\')', function() {
|
||||
this.previewGalleryController.items = [1,2,3];
|
||||
this.previewGalleryController.currentItemIndex = 1;
|
||||
this.previewGalleryController.previewItem = sinon.spy();
|
||||
this.previewGalleryController.handleSwipe('left');
|
||||
assert.ok(this.previewGalleryController.previewItem.called);
|
||||
assert.equal(this.previewGalleryController.currentItemIndex, 2);
|
||||
});
|
||||
|
||||
test('Should go to previous image on handleSwipe(\'right\')', function() {
|
||||
this.previewGalleryController.items = [1,2,3];
|
||||
this.previewGalleryController.currentItemIndex = 1;
|
||||
this.previewGalleryController.previewItem = sinon.spy();
|
||||
this.previewGalleryController.handleSwipe('right');
|
||||
assert.ok(this.previewGalleryController.previewItem.called);
|
||||
assert.equal(this.previewGalleryController.currentItemIndex, 0);
|
||||
});
|
||||
|
||||
test('Should not go to next image if there is not one', function() {
|
||||
this.previewGalleryController.items = [1,2];
|
||||
this.previewGalleryController.currentItemIndex = 1;
|
||||
this.previewGalleryController.previewItem = sinon.spy();
|
||||
this.previewGalleryController.handleSwipe('left');
|
||||
assert.isFalse(this.previewGalleryController.previewItem.called);
|
||||
assert.equal(this.previewGalleryController.currentItemIndex, 1);
|
||||
});
|
||||
|
||||
test('Should not go to previous image if there is not one', function() {
|
||||
this.previewGalleryController.items = [1,2];
|
||||
this.previewGalleryController.currentItemIndex = 0;
|
||||
this.previewGalleryController.previewItem = sinon.spy();
|
||||
this.previewGalleryController.handleSwipe('right');
|
||||
assert.isFalse(this.previewGalleryController.previewItem.called);
|
||||
assert.equal(this.previewGalleryController.currentItemIndex, 0);
|
||||
});
|
||||
});
|
||||
|
||||
suite('PreviewGalleryController#openPreview()', function() {
|
||||
setup(function() {
|
||||
this.app.require.callsArgWith(1, this.PreviewGalleryView, sinon.stub());
|
||||
sinon.stub(this.controller, 'previewItem');
|
||||
this.controller.settings = {
|
||||
activity: {
|
||||
get: sinon.spy()
|
||||
},
|
||||
previewGallery: {
|
||||
get: sinon.spy()
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
test('Should call previewItem', function() {
|
||||
this.controller.openPreview();
|
||||
assert.isTrue(this.controller.previewItem.called);
|
||||
});
|
||||
|
||||
// XXX: this is really a view test, but we don't have tests for the view yet
|
||||
test('Should lock and unlock orientation when opening and closing view',
|
||||
function() {
|
||||
this.orientation.unlock = sinon.spy();
|
||||
this.orientation.lock = sinon.spy();
|
||||
this.previewGalleryController.previewItem = sinon.spy();
|
||||
this.previewGalleryController.openPreview();
|
||||
assert.isTrue(this.orientation.unlock.called);
|
||||
assert.isTrue(this.previewGalleryController.previewItem.called);
|
||||
assert.isFalse(this.orientation.lock.called);
|
||||
this.previewGalleryController.closePreview();
|
||||
assert.isTrue(this.orientation.lock.called);
|
||||
});
|
||||
|
||||
// XXX: this is really a view test, but we don't have tests for the view yet
|
||||
test('Should add and remove a resize handler when opening and closing view',
|
||||
function() {
|
||||
var add = sinon.spy(window, 'addEventListener').withArgs('resize');
|
||||
var remove =
|
||||
sinon.spy(window, 'removeEventListener').withArgs('resize');
|
||||
this.previewGalleryController.previewItem = sinon.spy();
|
||||
this.previewGalleryController.openPreview();
|
||||
assert.ok(add.calledTwice); // twice because VideoPlayer does too
|
||||
this.previewGalleryController.closePreview();
|
||||
assert.equal(remove.callCount, 1);
|
||||
});
|
||||
});
|
||||
|
||||
suite('PreviewGalleryController#closePreview()', function() {
|
||||
setup(function() {
|
||||
this.controller.view = new this.PreviewGalleryView();
|
||||
this.previewGalleryView = this.controller.view;
|
||||
this.controller.view.close = sinon.spy();
|
||||
this.controller.view.destroy = sinon.spy();
|
||||
this.controller.closePreview();
|
||||
});
|
||||
|
||||
test('Should set `previewGalleryOpen` to `false` on app', function() {
|
||||
assert.isTrue(this.previewGalleryView.close.called);
|
||||
assert.isTrue(this.previewGalleryView.destroy.called);
|
||||
assert.isTrue(this.controller.view === null);
|
||||
});
|
||||
});
|
||||
|
||||
suite('PreviewGalleryController#onPreviewOptionClick()', function() {
|
||||
setup(function() {
|
||||
this.controller.view = new this.PreviewGalleryView();
|
||||
this.controller.view.showOptionsMenu = sinon.spy();
|
||||
this.controller.onOptionsClick();
|
||||
});
|
||||
|
||||
test('Should open previewOption on onPreviewOptionClick', function() {
|
||||
assert.isTrue(this.controller.view.showOptionsMenu.called);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
84
gaia/apps/camera/test/unit/controllers/recording-timer_test.js
Executable file
84
gaia/apps/camera/test/unit/controllers/recording-timer_test.js
Executable file
|
|
@ -0,0 +1,84 @@
|
|||
'use strict';
|
||||
|
||||
suite('controllers/recording-timer', function() {
|
||||
suiteSetup(function(done) {
|
||||
var self = this;
|
||||
requirejs([
|
||||
'app',
|
||||
'controllers/recording-timer',
|
||||
'views/recording-timer'
|
||||
], function(App, RecordingTimerController, RecordingTimerView) {
|
||||
self.RecordingTimerController = RecordingTimerController.RecordingTimerController;
|
||||
self.RecordingTimerView = RecordingTimerView;
|
||||
self.App = App;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
this.app = sinon.createStubInstance(this.App);
|
||||
this.app.view = sinon.createStubInstance(this.RecordingTimerView);
|
||||
this.app.el = {};
|
||||
|
||||
// Alias
|
||||
this.view = this.app.view;
|
||||
|
||||
// Create out test instance
|
||||
this.controller = new this.RecordingTimerController(this.app);
|
||||
});
|
||||
|
||||
suite('RecordingTimerController()', function() {
|
||||
test('Should respond to recording change', function() {
|
||||
assert.isTrue(this.app.on.calledWith('change:recording'));
|
||||
});
|
||||
|
||||
test('Should put the view in the DOM', function() {
|
||||
assert.isTrue(this.view.appendTo.calledWith(this.app.el));
|
||||
});
|
||||
|
||||
test('Should update the view value when the recording time changes', function() {
|
||||
assert.isTrue(this.app.on.calledWith('camera:recorderTimeUpdate', this.view.value));
|
||||
});
|
||||
});
|
||||
|
||||
suite('RecordingTimerController#onRecordingChange()', function() {
|
||||
test('Should hide the view if not recording', function() {
|
||||
this.controller.onRecordingChange(false);
|
||||
assert.isTrue(this.view.hide.called);
|
||||
});
|
||||
|
||||
test('Should show and reset the view if recording', function() {
|
||||
this.controller.onRecordingChange(true);
|
||||
assert.isTrue(this.view.show.called);
|
||||
assert.isTrue(this.view.value.calledWith(0));
|
||||
});
|
||||
});
|
||||
|
||||
suite('Accessibility Tests', function() {
|
||||
|
||||
var app,
|
||||
view,
|
||||
controller;
|
||||
|
||||
setup(function() {
|
||||
app = sinon.createStubInstance(this.App);
|
||||
app.view = new this.RecordingTimerView();
|
||||
view = app.view;
|
||||
controller = new this.RecordingTimerController(app);
|
||||
});
|
||||
|
||||
test('Explicitly test for RecordingTimer visibility', function() {
|
||||
// App is in its initialized state
|
||||
assert.isFalse(view.el.classList.contains('visible'));
|
||||
|
||||
// Fire start recording event
|
||||
controller.onRecordingChange(true);
|
||||
assert.isTrue(view.el.classList.contains('visible'));
|
||||
|
||||
// Fire stop recording event
|
||||
controller.onRecordingChange(false);
|
||||
assert.isFalse(view.el.classList.contains('visible'));
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
504
gaia/apps/camera/test/unit/controllers/settings_test.js
Executable file
504
gaia/apps/camera/test/unit/controllers/settings_test.js
Executable file
|
|
@ -0,0 +1,504 @@
|
|||
suite('controllers/settings', function() {
|
||||
/*jshint maxlen:false*/
|
||||
'use strict';
|
||||
|
||||
suiteSetup(function(done) {
|
||||
var self = this;
|
||||
requirejs([
|
||||
'controllers/settings',
|
||||
'lib/settings',
|
||||
'lib/setting',
|
||||
'app',
|
||||
'views/notification',
|
||||
'views/settings'
|
||||
], function(
|
||||
SettingsController, Settings, Setting,
|
||||
App, NotificationViews, SettingsView) {
|
||||
self.SettingsController = SettingsController.SettingsController;
|
||||
self.NotificationViews = NotificationViews;
|
||||
self.SettingsView = SettingsView;
|
||||
self.Settings = Settings;
|
||||
self.Setting = Setting;
|
||||
self.App = App;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
var self = this;
|
||||
|
||||
this.app = sinon.createStubInstance(this.App);
|
||||
this.app.require = sinon.stub();
|
||||
this.app.require.callsArgWith(1, this.SettingsView);
|
||||
|
||||
// Settings
|
||||
this.app.el = {};
|
||||
this.app.activity = { active: false };
|
||||
this.app.formatPictureSizes = sinon.stub();
|
||||
this.app.formatRecorderProfiles = sinon.stub();
|
||||
this.app.settings = sinon.createStubInstance(this.Settings);
|
||||
this.app.settings.mode = sinon.createStubInstance(this.Setting);
|
||||
this.app.settings.pictureSizes = sinon.createStubInstance(this.Setting);
|
||||
this.app.settings.pictureSizesFront = sinon.createStubInstance(this.Setting);
|
||||
this.app.settings.pictureSizesBack = sinon.createStubInstance(this.Setting);
|
||||
this.app.settings.recorderProfiles = sinon.createStubInstance(this.Setting);
|
||||
this.app.settings.recorderProfilesFront = sinon.createStubInstance(this.Setting);
|
||||
this.app.settings.recorderProfilesBack = sinon.createStubInstance(this.Setting);
|
||||
this.app.settings.flashModesPicture = sinon.createStubInstance(this.Setting);
|
||||
this.app.settings.flashModesVideo = sinon.createStubInstance(this.Setting);
|
||||
this.app.settings.hdr = sinon.createStubInstance(this.Setting);
|
||||
this.app.views = {
|
||||
notification: sinon.createStubInstance(this.NotificationViews)
|
||||
};
|
||||
|
||||
// SettingsView mock
|
||||
this.app.SettingsView = sinon.spy(function() {
|
||||
var view = sinon.createStubInstance(self.SettingsView);
|
||||
view.render.returns(view);
|
||||
view.appendTo.returns(view);
|
||||
view.on.returns(view);
|
||||
view.fadeOut.callsArg(0);
|
||||
return view;
|
||||
});
|
||||
|
||||
document.l10n = {
|
||||
formatValue: key => {
|
||||
return {
|
||||
then(fn) { fn('LOCALIZED'); }
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// Shortcut
|
||||
this.notification = this.app.views.notification;
|
||||
this.settings = this.app.settings;
|
||||
|
||||
// Create test instance
|
||||
this.controller = new this.SettingsController(this.app);
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
delete document.l10n;
|
||||
});
|
||||
|
||||
suite('SettingsController()', function() {
|
||||
test('Should setup aliases for `recorderProfiles`, `pictureSizes` and `flashModes`', function() {
|
||||
sinon.assert.calledThrice(this.settings.alias);
|
||||
});
|
||||
|
||||
test('Should toggle the settings menu on \'settings:toggle\'', function() {
|
||||
assert.isTrue(this.app.on.calledWith('settings:toggle', this.controller.toggleSettings));
|
||||
});
|
||||
|
||||
test('Should update the settings when the camera hardware changes', function() {
|
||||
assert.isTrue(this.app.on.calledWith('camera:newcamera', this.controller.onNewCamera));
|
||||
});
|
||||
|
||||
test('Should format pictreSize titles when the app is localized', function() {
|
||||
assert.isTrue(this.app.on.calledWith('localized', this.controller.formatPictureSizeTitles));
|
||||
});
|
||||
|
||||
test('Should listen to \'camera:newcamera\'', function() {
|
||||
assert.isTrue(this.app.on.calledWith('camera:newcamera', this.controller.onNewCamera));
|
||||
});
|
||||
});
|
||||
|
||||
suite('SettingsController#configurePictureSizes()', function() {
|
||||
setup(function() {
|
||||
this.pictureSizes = [];
|
||||
this.exclude = ['480x320'];
|
||||
|
||||
this.app.formatPictureSizes.returns('formatted');
|
||||
|
||||
this.settings.pictureSizes.get
|
||||
.withArgs('exclude')
|
||||
.returns(this.exclude);
|
||||
|
||||
this.settings.pictureSizes.current = sinon.stub()
|
||||
.returns(this.settings.pictureSizesBack);
|
||||
|
||||
document.l10n = {
|
||||
formatValue: function(id, args) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
};
|
||||
|
||||
this.settings.pictureSizes.get
|
||||
.withArgs('options')
|
||||
.returns([]);
|
||||
|
||||
// Run it
|
||||
this.controller.configurePictureSizes({
|
||||
pictureSize: { height: 1536, width: 2048 },
|
||||
capabilities: {
|
||||
pictureSizes: this.pictureSizes
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('Should format the raw pictureSizes list', function() {
|
||||
assert.isTrue(this.app.formatPictureSizes.calledWith(this.pictureSizes));
|
||||
});
|
||||
|
||||
test('Should reset pictureSize options with formatted list', function() {
|
||||
assert.isTrue(this.settings.pictureSizes.resetOptions.calledWith('formatted'));
|
||||
});
|
||||
|
||||
test('Should pass the raw recorderProfiles into formatRecorderProfiles', function() {
|
||||
var arg1 = this.app.formatPictureSizes.args[0][0];
|
||||
assert.equal(arg1, this.pictureSizes);
|
||||
});
|
||||
|
||||
test('Should pass the `exclude`', function() {
|
||||
var options = this.app.formatPictureSizes.args[0][1];
|
||||
assert.equal(options.exclude, this.exclude);
|
||||
});
|
||||
});
|
||||
|
||||
suite('SettingsController#configureRecorderProfiles()', function() {
|
||||
setup(function() {
|
||||
this.recorderProfiles = {};
|
||||
this.formatted = ['1080p', '720p', '480p'];
|
||||
this.exclude = ['1080p'];
|
||||
|
||||
this.newCamera = {
|
||||
recorderProfile: '720p',
|
||||
pictureSize: { height: 1536, width: 2048 },
|
||||
capabilities: {
|
||||
recorderProfiles: this.recorderProfiles
|
||||
}
|
||||
};
|
||||
|
||||
this.app.formatRecorderProfiles
|
||||
.returns(this.formatted);
|
||||
|
||||
this.settings.recorderProfiles.get
|
||||
.withArgs('exclude')
|
||||
.returns(this.exclude);
|
||||
|
||||
this.settings.recorderProfiles.current = sinon.stub()
|
||||
.returns(this.settings.recorderProfilesBack);
|
||||
|
||||
// Run it
|
||||
this.controller.configureRecorderProfiles(this.newCamera);
|
||||
});
|
||||
|
||||
test('Should format the raw recorderProfiles list', function() {
|
||||
assert.isTrue(this.app.formatRecorderProfiles.calledWith(this.recorderProfiles));
|
||||
});
|
||||
|
||||
test('Should reset recorderProfiles options with formatted list', function() {
|
||||
var resetOptions = this.settings.recorderProfiles.resetOptions;
|
||||
assert.isTrue(resetOptions.calledWith(this.formatted));
|
||||
});
|
||||
|
||||
test('Should pass the raw recorderProfiles into formatRecorderProfiles', function() {
|
||||
var arg1 = this.app.formatRecorderProfiles.args[0][0];
|
||||
assert.equal(arg1, this.recorderProfiles);
|
||||
});
|
||||
|
||||
test('Should pass `exclude` option to formatRecorderProfiles', function() {
|
||||
var options = this.app.formatRecorderProfiles.args[0][1];
|
||||
assert.equal(options.exclude, this.exclude);
|
||||
});
|
||||
|
||||
test('Should pick the last formatted recorderProfile if `maxFileSize` is defined', function() {
|
||||
this.settings.recorderProfiles.resetOptions.reset();
|
||||
|
||||
this.settings.recorderProfiles.get
|
||||
.withArgs('maxFileSizeBytes')
|
||||
.returns(100);
|
||||
|
||||
this.controller.configureRecorderProfiles(this.newCamera);
|
||||
var arg = this.settings.recorderProfiles.resetOptions.args[0][0];
|
||||
|
||||
assert.deepEqual(arg, ['480p']);
|
||||
});
|
||||
});
|
||||
|
||||
suite('SettingsController#onOptionTap()', function() {
|
||||
setup(function() {
|
||||
this.setting = sinon.createStubInstance(this.Setting);
|
||||
sinon.stub(this.controller, 'closeSettings').callsArg(0);
|
||||
sinon.stub(this.controller, 'notify');
|
||||
});
|
||||
|
||||
test('Should select the given key on the given option', function() {
|
||||
this.controller.onOptionTap('the-key', this.setting);
|
||||
assert.isTrue(this.setting.select.calledWith('the-key'));
|
||||
});
|
||||
|
||||
test('Should close the settings menu', function() {
|
||||
this.controller.onOptionTap('the-key', this.setting);
|
||||
assert.isTrue(this.controller.closeSettings.called);
|
||||
});
|
||||
|
||||
test('It shows a notification after the settings have closed', function() {
|
||||
this.controller.onOptionTap('the-key', this.setting);
|
||||
assert.isTrue(this.controller.notify.calledAfter(this.controller.closeSettings));
|
||||
});
|
||||
});
|
||||
|
||||
suite('SettingsController#notify()', function() {
|
||||
setup(function() {
|
||||
this.setting = sinon.createStubInstance(this.Setting);
|
||||
this.setting.selected.withArgs('title').returns('l10n-key');
|
||||
});
|
||||
|
||||
test('Should display a notification', function() {
|
||||
this.controller.notify(this.setting);
|
||||
assert.isTrue(this.notification.display.called);
|
||||
});
|
||||
|
||||
test('Should not display a notification if flagged `false`', function() {
|
||||
this.setting.get.withArgs('notifications').returns(false);
|
||||
this.controller.notify(this.setting);
|
||||
sinon.assert.notCalled(this.notification.display);
|
||||
});
|
||||
});
|
||||
|
||||
suite('SettingsController#validMenuItem()', function() {
|
||||
test('Should return `true` if supported', function() {
|
||||
var output;
|
||||
|
||||
this.app.settings.hdr.supported.returns(true);
|
||||
output = this.controller.validMenuItem({ key: 'hdr' });
|
||||
assert.isTrue(output);
|
||||
|
||||
this.app.settings.hdr.supported.returns(false);
|
||||
output = this.controller.validMenuItem({ key: 'hdr' });
|
||||
assert.isFalse(output);
|
||||
});
|
||||
|
||||
test('Should cope with undefined settings', function() {
|
||||
assert.isFalse(this.controller.validMenuItem({ key: 'fake' }));
|
||||
});
|
||||
});
|
||||
|
||||
suite('SettingsController#onNewCamera()', function() {
|
||||
setup(function() {
|
||||
this.newCamera = {
|
||||
recorderProfile: '720p',
|
||||
pictureSize: { height: 1536, width: 2048 },
|
||||
capabilities: {
|
||||
hdr: ['on', 'off'],
|
||||
pictureSizes: [],
|
||||
recorderProfiles: [],
|
||||
flashModes: []
|
||||
}
|
||||
};
|
||||
|
||||
this.settings.pictureSizes.current = sinon.stub()
|
||||
.returns(this.settings.pictureSizesBack);
|
||||
|
||||
this.settings.recorderProfiles.current = sinon.stub()
|
||||
.returns(this.settings.recorderProfilesBack);
|
||||
|
||||
this.app.settings.pictureSizes.get.returns([]);
|
||||
this.app.formatRecorderProfiles
|
||||
.returns(['1080p', '720p', '480p' ]);
|
||||
});
|
||||
|
||||
test('Should filter both \'picture\' and \'video\' flashModes', function() {
|
||||
var picture = this.settings.flashModesPicture;
|
||||
var video = this.settings.flashModesVideo;
|
||||
var capabilities = this.newCamera.capabilities;
|
||||
|
||||
this.controller.onNewCamera(this.newCamera);
|
||||
|
||||
assert.ok(picture.filterOptions.calledWith(capabilities.flashModes));
|
||||
assert.ok(video.filterOptions.calledWith(capabilities.flashModes));
|
||||
});
|
||||
|
||||
test('Should filter hdr', function() {
|
||||
var capabilities = this.newCamera.capabilities;
|
||||
this.controller.onNewCamera(this.newCamera);
|
||||
assert.ok(this.settings.hdr.filterOptions.calledWith(capabilities.hdr));
|
||||
});
|
||||
|
||||
test('Should reset pictureSizes and recorderProfiles options', function() {
|
||||
var recorderProfiles = this.settings.recorderProfiles;
|
||||
var pictureSizes = this.settings.pictureSizes;
|
||||
|
||||
this.controller.onNewCamera(this.newCamera);
|
||||
|
||||
assert.ok(recorderProfiles.resetOptions.called);
|
||||
assert.ok(pictureSizes.resetOptions.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('SettingsController#toggleSettings()', function() {
|
||||
setup(function() {
|
||||
sinon.stub(this.controller, 'closeSettings');
|
||||
sinon.stub(this.controller, 'openSettings');
|
||||
});
|
||||
|
||||
test('Should close the settings if a `view` is present', function() {
|
||||
this.controller.view = 'defined';
|
||||
this.controller.toggleSettings();
|
||||
assert.isTrue(this.controller.closeSettings.called);
|
||||
});
|
||||
|
||||
test('Should open the settings if a `view` is not present', function() {
|
||||
this.controller.view = undefined;
|
||||
this.controller.toggleSettings();
|
||||
assert.isTrue(this.controller.openSettings.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('SettingsController#openSettings()', function() {
|
||||
setup(function() {
|
||||
this.menuItems = [];
|
||||
sinon.stub(this.controller, 'menuItems').returns(this.menuItems);
|
||||
|
||||
// Call it
|
||||
this.controller.openSettings();
|
||||
});
|
||||
|
||||
|
||||
test('Should create a new SettingsView passing menu items', function() {
|
||||
var options = this.app.SettingsView.args[0][0];
|
||||
|
||||
assert.isTrue(this.app.SettingsView.called);
|
||||
assert.equal(options.items, this.menuItems);
|
||||
});
|
||||
|
||||
test('Should render and appendTo app.el', function() {
|
||||
assert.isTrue(this.controller.view.render.called);
|
||||
assert.isTrue(this.controller.view.appendTo.calledWith(this.app.el));
|
||||
});
|
||||
|
||||
test('Should bind to `click:close` and `click:option` events', function() {
|
||||
assert.isTrue(this.controller.view.on.calledWith('click:close'));
|
||||
assert.isTrue(this.controller.view.on.calledWith('click:option'));
|
||||
});
|
||||
|
||||
test('Should emit a `settings:open` event', function() {
|
||||
assert.isTrue(this.app.emit.calledWith('settings:opened'));
|
||||
});
|
||||
|
||||
test('Should not do anything if a view already exists', function() {
|
||||
this.app.SettingsView.reset();
|
||||
this.controller.view = 'defined';
|
||||
this.controller.openSettings();
|
||||
assert.isFalse(this.app.SettingsView.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('SettingsController#closeSettings()', function() {
|
||||
setup(function() {
|
||||
// Open settings first so we have a view
|
||||
sinon.stub(this.controller, 'menuItems').returns(this.menuItems);
|
||||
this.controller.openSettings();
|
||||
this.view = this.controller.view;
|
||||
});
|
||||
|
||||
test('Should not do anything if no view exists', function() {
|
||||
this.controller.view = undefined;
|
||||
this.controller.closeSettings();
|
||||
assert.isFalse(this.app.emit.calledWith('settings:closed'));
|
||||
});
|
||||
|
||||
test('Should destroy the view', function() {
|
||||
this.controller.closeSettings();
|
||||
assert.isTrue(this.view.destroy.called);
|
||||
});
|
||||
|
||||
test('Should null out `view`', function() {
|
||||
this.controller.closeSettings();
|
||||
assert.equal(this.controller.view, null);
|
||||
});
|
||||
});
|
||||
|
||||
suite('SettingsController#formatPictureSizeTitles()', function() {
|
||||
setup(function(done) {
|
||||
this.options = [
|
||||
{
|
||||
key: '400x300',
|
||||
data: {
|
||||
mp: 0,
|
||||
width: 400,
|
||||
height: 300,
|
||||
aspect: '4:3'
|
||||
}
|
||||
},
|
||||
{
|
||||
key: '1600x900',
|
||||
data: {
|
||||
mp: 1,
|
||||
width: 1600,
|
||||
height: 900,
|
||||
aspect: '16:9'
|
||||
}
|
||||
},
|
||||
{
|
||||
key: '3200x1800',
|
||||
data: {
|
||||
mp: 6,
|
||||
width: 3200,
|
||||
height: 1800,
|
||||
aspect: '16:9'
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
this.settings.pictureSizes.get
|
||||
.withArgs('options')
|
||||
.returns(this.options);
|
||||
|
||||
document.l10n = {
|
||||
formatValue: function(id, args) {
|
||||
return Promise.resolve('MP');
|
||||
}
|
||||
};
|
||||
|
||||
// Call the test subject
|
||||
this.controller.formatPictureSizeTitles().then(() => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('Should include MP value for > 1MP', function() {
|
||||
assert.isTrue(this.options[2].title.indexOf('6MP') > -1, this.options[2].title);
|
||||
assert.isFalse(this.options[0].title.indexOf('MP') > -1, this.options[0].title);
|
||||
});
|
||||
|
||||
test('Should include the resolution', function() {
|
||||
assert.isTrue(this.options[0].title.indexOf('400x300') > -1);
|
||||
});
|
||||
|
||||
test('Should use localized \'MP\' string', function() {
|
||||
document.l10n = {
|
||||
formatValue: function(id, args) {
|
||||
return Promise.resolve('MP');
|
||||
}
|
||||
};
|
||||
|
||||
this.controller.formatPictureSizeTitles();
|
||||
assert.isTrue(this.options[2].title.indexOf('MP') > -1, this.options[2].title);
|
||||
});
|
||||
});
|
||||
|
||||
suite('SettingsController#onPickActivity()', function() {
|
||||
setup(function() {
|
||||
this.onPickActivity = this.app.on.withArgs('activity:pick').args[0][1];
|
||||
});
|
||||
|
||||
test('Should not save settings changes when in \'pick\' activity', function() {
|
||||
this.onPickActivity({});
|
||||
sinon.assert.called(this.settings.dontSave);
|
||||
});
|
||||
|
||||
test('Should set maxPixelSize on pictureSizes settings', function() {
|
||||
this.onPickActivity({ maxPixelSize: 100 });
|
||||
sinon.assert.calledWith(this.settings.pictureSizesFront.set, 'maxPixelSize', 100);
|
||||
sinon.assert.calledWith(this.settings.pictureSizesBack.set, 'maxPixelSize', 100);
|
||||
});
|
||||
|
||||
test('Should set maxPixelSize on pictureSizes settings', function() {
|
||||
this.onPickActivity({ maxFileSizeBytes: 100 });
|
||||
sinon.assert.calledWith(this.settings.recorderProfilesFront.set, 'maxFileSizeBytes', 100);
|
||||
sinon.assert.calledWith(this.settings.recorderProfilesBack.set, 'maxFileSizeBytes', 100);
|
||||
});
|
||||
});
|
||||
});
|
||||
164
gaia/apps/camera/test/unit/controllers/storage_test.js
Executable file
164
gaia/apps/camera/test/unit/controllers/storage_test.js
Executable file
|
|
@ -0,0 +1,164 @@
|
|||
suite('controllers/storage', function() {
|
||||
'use strict';
|
||||
|
||||
suiteSetup(function(done) {
|
||||
var self = this;
|
||||
requirejs([
|
||||
'controllers/storage',
|
||||
'lib/setting',
|
||||
'lib/storage',
|
||||
'app'
|
||||
], function(StorageController, Setting, Storage, App) {
|
||||
self.StorageController = StorageController.StorageController;
|
||||
self.Setting = Setting;
|
||||
self.Storage = Storage;
|
||||
self.App = App;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
this.app = sinon.createStubInstance(this.App);
|
||||
this.app.storage = sinon.createStubInstance(this.Storage);
|
||||
this.app.storage.createVideoFilepath = 'test';
|
||||
this.app.camera = {};
|
||||
this.app.settings = {
|
||||
pictureSizes: sinon.createStubInstance(this.Setting)
|
||||
};
|
||||
|
||||
// Aliases
|
||||
this.camera = this.app.camera;
|
||||
this.settings = this.app.settings;
|
||||
this.storage = this.app.storage;
|
||||
|
||||
this.settings.pictureSizes.selected
|
||||
.withArgs('data')
|
||||
.returns({ width: 400, height: 300 });
|
||||
|
||||
// Create a test instance
|
||||
this.controller = new this.StorageController(this.app);
|
||||
});
|
||||
|
||||
suite('StorageController()', function() {
|
||||
test('Should set the camera `camera.createVideoFilepath`', function() {
|
||||
assert.equal(this.camera.createVideoFilepath, 'test');
|
||||
});
|
||||
|
||||
test('Should update maxFileSize when picture size changes', function() {
|
||||
var on = this.settings.pictureSizes.on;
|
||||
assert.isTrue(on.calledWith('change:selected', this.controller.updateMaxFileSize));
|
||||
});
|
||||
|
||||
test('Should update maxFileSize when settings are configured', function() {
|
||||
assert.isTrue(this.app.on.calledWith('settings:configured', this.controller.updateMaxFileSize));
|
||||
});
|
||||
|
||||
test('Should delete a picture from storage when one is deleted from the preview gallery', function() {
|
||||
assert.isTrue(this.app.on.calledWith('previewgallery:deletepicture', this.storage.deletePicture));
|
||||
});
|
||||
|
||||
test('Should delete a video from storage when one is deleted from the preview gallery', function() {
|
||||
assert.isTrue(this.app.on.calledWith('previewgallery:deletevideo', this.storage.deleteVideo));
|
||||
});
|
||||
|
||||
test('Should media when the camera generates it', function() {
|
||||
assert.isTrue(this.app.on.calledWith('camera:newimage', this.controller.storePicture));
|
||||
assert.isTrue(this.app.on.calledWith('camera:newvideo', this.controller.storeVideo));
|
||||
});
|
||||
|
||||
test('Should check storage when the app becomes visible', function() {
|
||||
assert.isTrue(this.app.on.calledWith('visible', this.storage.check));
|
||||
});
|
||||
|
||||
test('Should set the maxFileSize initially', function() {
|
||||
assert.isTrue(this.storage.setMaxFileSize.calledOnce);
|
||||
});
|
||||
|
||||
test('Should run an intitial storage check', function() {
|
||||
this.storage.setMaxFileSize.restore();
|
||||
this.controller = new this.StorageController(this.app);
|
||||
assert.isTrue(this.storage.check.calledOnce);
|
||||
});
|
||||
});
|
||||
|
||||
suite('StorageController#storePicture()', function() {
|
||||
setup(function() {
|
||||
this.storage.addPicture.callsArgWith(1, null, '<filepath>', '<abspath>', '<file-blob>');
|
||||
|
||||
this.picture = { blob: '<memory-blob>' };
|
||||
this.controller.storePicture(this.picture);
|
||||
});
|
||||
|
||||
test('Should store the picture', function() {
|
||||
assert.isTrue(this.storage.addPicture.calledWith('<memory-blob>'));
|
||||
});
|
||||
|
||||
test('Should emit a `newmedia` app event', function() {
|
||||
assert.isTrue(this.app.emit.calledWith('newmedia', this.picture));
|
||||
});
|
||||
|
||||
test('Should switch the <memory-blob> with the <file-blob>', function() {
|
||||
assert.equal(this.picture.blob, '<file-blob>');
|
||||
});
|
||||
|
||||
test('Should store the <filepath>', function() {
|
||||
assert.equal(this.picture.filepath, '<filepath>');
|
||||
});
|
||||
});
|
||||
|
||||
suite('StorageController#storeVideo()', function() {
|
||||
setup(function() {
|
||||
this.storage.addPicture.callsArgWith(2, null, '<filepath>', '<abspath>', '<file-blob>');
|
||||
|
||||
this.video = {
|
||||
blob: '<file-blob>',
|
||||
filepath: 'path/to/video.3gp',
|
||||
poster: { blob: '<poster-memory-blob>' }
|
||||
};
|
||||
|
||||
this.controller.storeVideo(this.video);
|
||||
});
|
||||
|
||||
test('Should store the picture', function() {
|
||||
assert.isTrue(this.storage.addPicture.calledWith('<poster-memory-blob>'));
|
||||
});
|
||||
|
||||
test('Should store the poster image', function() {
|
||||
var blob = this.storage.addPicture.args[0][0];
|
||||
var options = this.storage.addPicture.args[0][1];
|
||||
|
||||
assert.equal(blob, '<poster-memory-blob>');
|
||||
assert.equal(options.filepath, 'path/to/video.jpg');
|
||||
});
|
||||
|
||||
test('Should emit a `newmedia` app event', function() {
|
||||
assert.isTrue(this.app.emit.calledWith('newmedia', this.video));
|
||||
});
|
||||
|
||||
test('Should switch the <poster-memory-blob> with the <file-blob>', function() {
|
||||
assert.equal(this.video.poster.blob, '<file-blob>');
|
||||
})
|
||||
|
||||
test('Should flag it as `isVideo`', function() {
|
||||
assert.equal(this.video.isVideo, true);
|
||||
});
|
||||
});
|
||||
|
||||
suite('StorageController#updateMaxFileSize()', function() {
|
||||
setup(function() {
|
||||
// Reset calls in constructor
|
||||
this.storage.setMaxFileSize.reset();
|
||||
});
|
||||
|
||||
test('Should call `storage.setMaxFileSize` with picture file size estimate', function() {
|
||||
this.settings.pictureSizes.selected.withArgs('data').returns({ width: 400, height: 300 });
|
||||
this.controller.updateMaxFileSize();
|
||||
|
||||
var expected = (400 * 300 / 2) + 25000;
|
||||
var bytes = this.storage.setMaxFileSize.args[0][0];
|
||||
|
||||
assert.equal(this.storage.setMaxFileSize.callCount, 1);
|
||||
assert.equal(bytes, expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
360
gaia/apps/camera/test/unit/controllers/viewfinder_test.js
Executable file
360
gaia/apps/camera/test/unit/controllers/viewfinder_test.js
Executable file
|
|
@ -0,0 +1,360 @@
|
|||
'use strict';
|
||||
|
||||
suite('controllers/viewfinder', function() {
|
||||
suiteSetup(function(done) {
|
||||
var self = this;
|
||||
|
||||
requirejs([
|
||||
'app',
|
||||
'lib/camera/camera',
|
||||
'controllers/viewfinder',
|
||||
'views/viewfinder',
|
||||
'views/focus',
|
||||
'views/faces',
|
||||
'lib/settings',
|
||||
'lib/setting'
|
||||
], function(
|
||||
App, Camera, ViewfinderController, ViewfinderView,
|
||||
FocusView, FacesView, Settings, Setting) {
|
||||
self.ViewfinderController = ViewfinderController.ViewfinderController;
|
||||
self.ViewfinderView = ViewfinderView;
|
||||
self.FocusView = FocusView;
|
||||
self.FacesView = FacesView;
|
||||
self.Settings = Settings;
|
||||
self.Setting = Setting;
|
||||
self.Camera = Camera;
|
||||
self.App = App;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
this.sandbox = sinon.sandbox.create();
|
||||
|
||||
// App
|
||||
this.app = sinon.createStubInstance(this.App);
|
||||
this.app.camera = sinon.createStubInstance(this.Camera);
|
||||
this.app.activity = {};
|
||||
this.app.settings = sinon.createStubInstance(this.Settings);
|
||||
this.app.settings.grid = sinon.createStubInstance(this.Setting);
|
||||
this.app.views = {
|
||||
viewfinder: sinon.createStubInstance(this.ViewfinderView),
|
||||
focus: sinon.createStubInstance(this.FocusView),
|
||||
faces: sinon.createStubInstance(this.FacesView)
|
||||
};
|
||||
this.app.Pinch = sinon.stub();
|
||||
this.app.Pinch.prototype.on = sinon.stub();
|
||||
|
||||
// Fake elements
|
||||
this.app.views.viewfinder.els = { video: {} };
|
||||
|
||||
// Settings
|
||||
this.app.settings = sinon.createStubInstance(this.Settings);
|
||||
this.app.settings.grid = sinon.createStubInstance(this.Setting);
|
||||
this.app.settings.viewfinder = sinon.createStubInstance(this.Setting);
|
||||
this.app.settings.cameras = sinon.createStubInstance(this.Setting);
|
||||
this.app.settings.zoom = sinon.createStubInstance(this.Setting);
|
||||
|
||||
// Default return values
|
||||
this.app.settings.viewfinder.get.withArgs('scaleType').returns('fill');
|
||||
this.app.settings.grid.selected.withArgs('key').returns('off');
|
||||
|
||||
// Test instance
|
||||
this.controller = new this.ViewfinderController(this.app);
|
||||
|
||||
// Shortcuts
|
||||
this.viewfinder = this.controller.views.viewfinder;
|
||||
this.focusRing = this.controller.views.focus;
|
||||
this.faces = this.controller.views.faces;
|
||||
this.focus = this.controller.views.focus;
|
||||
this.settings = this.app.settings;
|
||||
this.camera = this.app.camera;
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
this.sandbox.restore();
|
||||
});
|
||||
|
||||
suite('ViewfinderController()', function() {
|
||||
test('Should stop the stream when the PreviewGallery is opened', function() {
|
||||
assert.isTrue(this.app.on.calledWith('previewgallery:opened',
|
||||
this.controller.onGalleryOpened));
|
||||
});
|
||||
|
||||
test('Should start the stream when the PreviewGallery is closed', function() {
|
||||
assert.isTrue(this.app.on.calledWith('previewgallery:closed',
|
||||
this.controller.onGalleryClosed));
|
||||
});
|
||||
|
||||
test('Should stop the stream preview is false', function() {
|
||||
assert.isTrue(this.app.on.calledWith('camera:previewactive', this.controller.onPreviewActive));
|
||||
});
|
||||
|
||||
test('Should hide the grid when the settings menu opened', function() {
|
||||
assert.isTrue(this.app.on.calledWith('settings:opened',
|
||||
this.controller.onSettingsOpened));
|
||||
});
|
||||
|
||||
test('Should show the grid again when the settings menu is closed', function() {
|
||||
assert.isTrue(this.app.on.calledWith('settings:closed',
|
||||
this.controller.onSettingsClosed));
|
||||
});
|
||||
|
||||
test('Should flash viewfinder shutter when camera shutter fires', function() {
|
||||
assert.isTrue(this.app.on.calledWith('camera:shutter', this.viewfinder.shutter));
|
||||
});
|
||||
|
||||
test('Should respond to `zoomchanged` event', function() {
|
||||
assert.isTrue(this.camera.on.calledWith('zoomchanged'));
|
||||
});
|
||||
|
||||
test('Should should set the foucsRing state when focus changes', function() {
|
||||
assert.isTrue(this.app.on.calledWith('camera:focusstatechanged', this.focusRing.setFocusState));
|
||||
});
|
||||
|
||||
test('Should set the scaleType on the view', function() {
|
||||
assert.equal(this.viewfinder.scaleType, 'fill');
|
||||
});
|
||||
|
||||
test('Should set grid on/off', function() {
|
||||
assert.isTrue(this.viewfinder.set.calledWith('grid', 'off'));
|
||||
this.app.settings.grid.selected.withArgs('key').returns('on');
|
||||
this.viewfinder.set.reset();
|
||||
|
||||
this.controller = new this.ViewfinderController(this.app);
|
||||
assert.isTrue(this.viewfinder.set.calledWith('grid', 'on'));
|
||||
});
|
||||
});
|
||||
|
||||
suite('ViewfinderController#createViews()', function() {
|
||||
setup(function() {
|
||||
this.controller.createViews();
|
||||
});
|
||||
|
||||
test('It appends views to the viewfinder views', function() {
|
||||
assert.isTrue(this.focus.appendTo.calledWith(this.viewfinder.el));
|
||||
assert.isTrue(this.faces.appendTo.calledWith(this.viewfinder.el));
|
||||
assert.isTrue(this.viewfinder.appendTo.calledWith(this.app.el));
|
||||
});
|
||||
});
|
||||
|
||||
suite('ViewfinderController#show()', function() {
|
||||
setup(function() {
|
||||
this.sandbox.stub(window, 'clearTimeout');
|
||||
this.sandbox.stub(window, 'setTimeout').returns('<timeout-id>');
|
||||
this.app.criticalPathDone = true;
|
||||
});
|
||||
|
||||
test('It fades the viewfinder in straight away if the critical path is incomplete', function() {
|
||||
this.app.criticalPathDone = false;
|
||||
this.controller.show();
|
||||
sinon.assert.called(this.viewfinder.fadeIn);
|
||||
sinon.assert.notCalled(window.setTimeout);
|
||||
});
|
||||
|
||||
test('It fades the viewfinder in after 280ms timeout to avoid flicker', function() {
|
||||
this.controller.show();
|
||||
sinon.assert.calledWith(window.setTimeout, this.viewfinder.fadeIn, 280);
|
||||
});
|
||||
|
||||
test('It clears any existing timeouts to avoid multiple scheduled timeouts', function() {
|
||||
this.controller.show();
|
||||
this.controller.show();
|
||||
sinon.assert.calledWith(window.clearTimeout, '<timeout-id>');
|
||||
});
|
||||
});
|
||||
|
||||
suite('ViewfinderController#hide()', function() {
|
||||
setup(function() {
|
||||
this.sandbox.stub(window, 'setTimeout').returns('<timeout-id>');
|
||||
this.sandbox.stub(window, 'clearTimeout');
|
||||
});
|
||||
|
||||
test('It fades out the viewfinder', function() {
|
||||
this.controller.hide();
|
||||
sinon.assert.called(this.viewfinder.fadeOut);
|
||||
});
|
||||
|
||||
test('It clears any fadeTimeout hanging around', function() {
|
||||
this.controller.show();
|
||||
this.controller.hide();
|
||||
sinon.assert.called(window.clearTimeout, '<timeout-id>');
|
||||
});
|
||||
});
|
||||
|
||||
suite('ViewfinderController#loadStream()', function() {
|
||||
test('Should load preview stream into viewfinder video element', function() {
|
||||
var video = this.viewfinder.els.video;
|
||||
this.controller.loadStream();
|
||||
assert.isTrue(this.camera.loadStreamInto.calledWith(video));
|
||||
});
|
||||
});
|
||||
|
||||
suite('ViewfinderController#configurePreview()', function() {
|
||||
setup(function() {
|
||||
this.settings.cameras.selected.withArgs('key').returns('back');
|
||||
this.camera.getSensorAngle.returns(90);
|
||||
this.camera.previewSize.returns({ width: 400, height: 300 });
|
||||
});
|
||||
|
||||
test('Should pass current previewSize', function() {
|
||||
this.controller.configurePreview();
|
||||
var previewSize = this.viewfinder.updatePreview.args[0][0];
|
||||
assert.deepEqual(previewSize, { width: 400, height: 300 });
|
||||
});
|
||||
|
||||
test('Should pass the sensor angle', function() {
|
||||
this.controller.configurePreview();
|
||||
var arg = this.viewfinder.updatePreview.args[0][1];
|
||||
assert.equal(arg, 90);
|
||||
});
|
||||
|
||||
test('Should indicate if selected camera is front', function() {
|
||||
var arg;
|
||||
|
||||
// Back
|
||||
this.controller.configurePreview();
|
||||
arg = this.viewfinder.updatePreview.args[0][2];
|
||||
assert.equal(arg, false);
|
||||
this.viewfinder.updatePreview.reset();
|
||||
|
||||
// Front
|
||||
this.settings.cameras.selected.withArgs('key').returns('front');
|
||||
this.controller.configurePreview();
|
||||
arg = this.viewfinder.updatePreview.args[0][2];
|
||||
assert.equal(arg, true);
|
||||
});
|
||||
});
|
||||
|
||||
suite('ViewfinderController#onZoomConfigured()', function() {
|
||||
setup(function() {
|
||||
this.camera.isZoomSupported.returns(true);
|
||||
this.settings.zoom.enabled.returns(true);
|
||||
|
||||
this.camera.getMinimumZoom.returns(0);
|
||||
this.camera.getMaximumZoom.returns(3);
|
||||
});
|
||||
|
||||
test('Should call enableZoom on the viewfinder', function() {
|
||||
this.controller.onZoomConfigured();
|
||||
assert.isTrue(this.viewfinder.enableZoom.calledWith(0, 3));
|
||||
});
|
||||
|
||||
test('Should disable zoom if camera doesn\'t support zoom', function() {
|
||||
this.camera.isZoomSupported.returns(false);
|
||||
|
||||
this.controller.onZoomConfigured();
|
||||
assert.isTrue(this.viewfinder.disableZoom.called);
|
||||
});
|
||||
|
||||
test('Should disable zoom if zoom disabled in settings', function() {
|
||||
this.settings.zoom.enabled.returns(false);
|
||||
|
||||
this.controller.onZoomConfigured();
|
||||
assert.isTrue(this.viewfinder.disableZoom.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('ViewfinderController#onSettingsOpened()', function() {
|
||||
setup(function() {
|
||||
sinon.spy(this.controller, 'hideGrid');
|
||||
this.controller.onSettingsOpened();
|
||||
});
|
||||
|
||||
test('Hide grid and hide viewfinder view from the screen reader',
|
||||
function() {
|
||||
sinon.assert.called(this.controller.hideGrid);
|
||||
assert.isTrue(this.viewfinder.set.calledWith('ariaHidden', true));
|
||||
});
|
||||
});
|
||||
|
||||
suite('ViewfinderController#onSettingsClosed()', function() {
|
||||
setup(function() {
|
||||
sinon.spy(this.controller, 'configureGrid');
|
||||
this.controller.onSettingsClosed();
|
||||
});
|
||||
|
||||
test('Configure grid and show viewfinder view to the screen reader',
|
||||
function() {
|
||||
sinon.assert.called(this.controller.configureGrid);
|
||||
assert.isTrue(this.viewfinder.set.calledWith('ariaHidden', false));
|
||||
});
|
||||
});
|
||||
|
||||
suite('ViewfinderController#onGalleryOpened()', function() {
|
||||
setup(function() {
|
||||
this.controller.onGalleryOpened();
|
||||
});
|
||||
|
||||
test('When gallery is open, the viewfinder view should be disabled and ' +
|
||||
'hidden from screen reader', function() {
|
||||
sinon.assert.called(this.viewfinder.disable);
|
||||
assert.isTrue(this.viewfinder.set.calledWith('ariaHidden', true));
|
||||
});
|
||||
});
|
||||
|
||||
suite('ViewfinderController#onGalleryClosed()', function() {
|
||||
setup(function() {
|
||||
this.controller.onGalleryClosed();
|
||||
});
|
||||
|
||||
test('When gallery is closed, the viewfinder view should be enabled and ' +
|
||||
'visible to screen reader', function() {
|
||||
sinon.assert.called(this.viewfinder.enable);
|
||||
assert.isTrue(this.viewfinder.set.calledWith('ariaHidden', false));
|
||||
});
|
||||
});
|
||||
|
||||
suite('ViewfinderController#onPowerSave', function() {
|
||||
test('When power save enabled, the viewfinder should disable screen ' +
|
||||
'wakelocks', function() {
|
||||
this.controller.onPowerSave(false);
|
||||
assert.isTrue(this.viewfinder.els.video.mozUseScreenWakeLock);
|
||||
});
|
||||
|
||||
test('When power save disabled, the viewfinder should enable screen ' +
|
||||
'wakelocks', function() {
|
||||
this.controller.onPowerSave(true);
|
||||
assert.isFalse(this.viewfinder.els.video.mozUseScreenWakeLock);
|
||||
});
|
||||
});
|
||||
|
||||
suite('click:viewfinder', function() {
|
||||
test('Should set the grid depending on the setting', function() {
|
||||
this.app.settings.grid.selected.withArgs('key').returns('on');
|
||||
this.controller = new this.ViewfinderController(this.app);
|
||||
assert.isTrue(this.viewfinder.set.calledWith('grid', 'on'));
|
||||
|
||||
this.app.settings.grid.selected.withArgs('key').returns('off');
|
||||
this.controller = new this.ViewfinderController(this.app);
|
||||
assert.isTrue(this.viewfinder.set.calledWith('grid', 'off'));
|
||||
});
|
||||
|
||||
test('Should set viewfinder fill depending on the setting', function() {
|
||||
this.app.settings.viewfinder.get.withArgs('scaleType').returns('fill');
|
||||
this.controller = new this.ViewfinderController(this.app);
|
||||
assert.equal(this.viewfinder.scaleType, 'fill');
|
||||
|
||||
this.app.settings.viewfinder.get.withArgs('scaleType').returns('fit');
|
||||
this.controller = new this.ViewfinderController(this.app);
|
||||
assert.equal(this.viewfinder.scaleType, 'fit');
|
||||
});
|
||||
});
|
||||
|
||||
suite('ViewfinderController#calculateFaceCircle()', function() {
|
||||
test('Draw circle from a square', function() {
|
||||
var circle = this.controller.calculateFaceCircle({top: 50, left: 50, width: 10, height: 10});
|
||||
assert.deepEqual(circle, {x: 50, y: 50, diameter: 10});
|
||||
});
|
||||
|
||||
test('Draw circle from a 2:1 rectangle', function() {
|
||||
var circle = this.controller.calculateFaceCircle({top: 100, left: 50, width: 20, height: 10});
|
||||
assert.deepEqual(circle, {x: 50, y: 95, diameter: 20});
|
||||
});
|
||||
|
||||
test('Draw circle from a 1:2 rectangle', function() {
|
||||
var circle = this.controller.calculateFaceCircle({top: 100, left: 50, width: 10, height: 20});
|
||||
assert.deepEqual(circle, {x: 45, y: 100, diameter: 20});
|
||||
});
|
||||
});
|
||||
});
|
||||
135
gaia/apps/camera/test/unit/controllers/zoom-bar_test.js
Executable file
135
gaia/apps/camera/test/unit/controllers/zoom-bar_test.js
Executable file
|
|
@ -0,0 +1,135 @@
|
|||
'use strict';
|
||||
|
||||
suite('controllers/zoom-bar', function() {
|
||||
suiteSetup(function(done) {
|
||||
var self = this;
|
||||
|
||||
requirejs([
|
||||
'app',
|
||||
'lib/camera/camera',
|
||||
'lib/settings',
|
||||
'lib/setting',
|
||||
'controllers/zoom-bar',
|
||||
'views/zoom-bar'
|
||||
], function(
|
||||
App, Camera, Settings, Setting, ZoomBarController, ZoomBarView) {
|
||||
self.ZoomBarController = ZoomBarController.ZoomBarController;
|
||||
self.ZoomBarView = ZoomBarView;
|
||||
self.Camera = Camera;
|
||||
self.App = App;
|
||||
self.Settings = Settings;
|
||||
self.Setting = Setting;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
this.sandbox = sinon.sandbox.create();
|
||||
|
||||
// App
|
||||
this.app = sinon.createStubInstance(this.App);
|
||||
this.app.camera = sinon.createStubInstance(this.Camera);
|
||||
this.app.views = {
|
||||
zoombar: sinon.createStubInstance(this.ZoomBarView)
|
||||
};
|
||||
|
||||
// Settings
|
||||
this.app.settings = sinon.createStubInstance(this.Settings);
|
||||
this.app.settings.zoom = sinon.createStubInstance(this.Setting);
|
||||
|
||||
// Test instance
|
||||
this.controller = new this.ZoomBarController(this.app);
|
||||
|
||||
// Shortcuts
|
||||
this.zoombar = this.controller.view;
|
||||
this.camera = this.app.camera;
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
this.sandbox.restore();
|
||||
});
|
||||
|
||||
suite('ViewfinderController()', function() {
|
||||
test('Should configure zoom when zoomconfigured event is emitted', function() {
|
||||
assert.isTrue(this.camera.on.calledWith('zoomconfigured',
|
||||
this.controller.onZoomConfigured));
|
||||
});
|
||||
|
||||
test('Should set the zoom when zoomchanged event is emitted', function() {
|
||||
assert.isTrue(this.camera.on.calledWith('zoomchanged',
|
||||
this.controller.setZoom));
|
||||
});
|
||||
});
|
||||
|
||||
suite('ViewfinderController#createViews()', function() {
|
||||
setup(function() {
|
||||
this.controller.createView();
|
||||
});
|
||||
|
||||
test('It appends view', function() {
|
||||
assert.isTrue(this.zoombar.appendTo.calledWith(this.zoombar.el));
|
||||
});
|
||||
});
|
||||
|
||||
suite('ZoomBar#onChange()', function() {
|
||||
setup(function() {
|
||||
this.camera.getMaximumZoom.returns(10);
|
||||
this.camera.getMinimumZoom.returns(1);
|
||||
this.controller.onChange(5);
|
||||
});
|
||||
|
||||
test('It calls setZoom with the correct value', function() {
|
||||
assert.isTrue(this.camera.setZoom.calledWith(1.45));
|
||||
});
|
||||
});
|
||||
|
||||
suite('ZoomBar#onZoomConfigured()', function() {
|
||||
setup(function() {
|
||||
sinon.stub(this.controller, 'configureZoomBar');
|
||||
sinon.stub(this.controller, 'setZoom');
|
||||
this.controller.onZoomConfigured(5);
|
||||
});
|
||||
|
||||
test('It sets zoom and hides', function() {
|
||||
assert.isTrue(this.controller.configureZoomBar.calledOnce);
|
||||
assert.isTrue(this.controller.setZoom.calledWith(5));
|
||||
assert.isTrue(this.zoombar.hide.called);
|
||||
});
|
||||
});
|
||||
|
||||
suite('ZoomBar#configureZoomBar()', function() {
|
||||
test('It disables zoom if not supported by camera', function() {
|
||||
this.camera.isZoomSupported.returns(false);
|
||||
this.app.settings.zoom.enabled.returns(true);
|
||||
this.controller.configureZoomBar();
|
||||
assert.isFalse(this.controller.enableZoom);
|
||||
});
|
||||
|
||||
test('It enables zoom if supported by camera', function() {
|
||||
this.camera.isZoomSupported.returns(true);
|
||||
this.app.settings.zoom.enabled.returns(true);
|
||||
this.controller.configureZoomBar();
|
||||
assert.isTrue(this.controller.enableZoom);
|
||||
});
|
||||
});
|
||||
|
||||
suite('ZoomBar#setZoom()', function() {
|
||||
setup(function() {
|
||||
this.camera.getMaximumZoom.returns(11);
|
||||
this.camera.getMinimumZoom.returns(1);
|
||||
});
|
||||
|
||||
test('It sets the zoom with the correct value if enabled', function() {
|
||||
this.controller.enableZoom = true;
|
||||
this.controller.setZoom(4);
|
||||
assert.isTrue(this.zoombar.setValue.calledWith(30));
|
||||
});
|
||||
|
||||
test('It does not set the zoom if disabled', function() {
|
||||
this.controller.enableZoom = false;
|
||||
this.controller.setZoom(4);
|
||||
assert.isFalse(this.zoombar.setValue.calledWith(30));
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
Loading…
Reference in a new issue