Publish Vulpes Preview 15 sources for desktop, Android and Tundra

Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
OverSu 2026-09-30 23:13:03 +02:00
commit b38dea0597
25901 changed files with 9982925 additions and 369 deletions

View file

@ -0,0 +1,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);
});
});
});