VulpesOS/gaia/apps/system/test/unit/wallpaper_manager_test.js
OverSu b38dea0597 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.
2026-09-30 23:13:03 +02:00

519 lines
19 KiB
JavaScript
Executable file

'use strict';
/* global WallpaperManager, MockLazyLoader, ImageUtils,
MockNavigatorSettings, MockService, MocksHelper */
require('/shared/test/unit/mocks/mock_navigator_moz_settings.js');
require('/shared/js/image_utils.js');
require('/apps/system/js/wallpaper_manager.js');
require('/shared/test/unit/mocks/mock_service.js');
requireApp('system/test/unit/mock_lazy_loader.js');
var mocksForWallpaperManager = new MocksHelper([
'Service',
'LazyLoader'
]).init();
suite('WallpaperManager', function() {
mocksForWallpaperManager.attachTestHelpers();
var subject; // The WallpaperManager instance we're testing.
var wallpaperBlob, bigWallpaperBlob, smallWallpaperBlob;
var dataURL, bigDataURL, smallDataURL, mockPublish;
const DEFAULT_WALLPAPER = 'resources/images/backgrounds/default.png';
suiteSetup(function(done) {
var self = this;
var sw, sh;
// Don't display debug output
WallpaperManager.DEBUG = false;
// Fake URLs. Our xhr mock will recognize these strings and return blobs
dataURL = 'data://justright';
bigDataURL = 'data://toobig';
smallDataURL = 'data://toosmall';
// Map urls to blobs for the fake XHR
var urlToBlobMap = this.urlToBlobMap = {};
this.xhr = sinon.useFakeXMLHttpRequest();
this.xhr.onCreate = function(request) {
setTimeout(function() {
var blob = urlToBlobMap[request.url];
if (blob) {
request.response = blob;
request.onload();
}
else {
request.onerror();
}
});
};
// How big (in device pixels) is the screen in its default orientation?
if (MockService.mockQueryWith('isDefaultPortrait')) {
sw = Math.max(screen.width, screen.height);
sh = Math.min(screen.width, screen.height);
} else {
// Otherwise, the width is the smaller dimension
sw = Math.min(screen.width, screen.height);
sh = Math.max(screen.width, screen.height);
}
this.screenWidth = sw * window.devicePixelRatio;
this.screenHeight = sh * window.devicePixelRatio;
// Create some image blobs
var canvas = document.createElement('canvas');
canvas.width = this.screenWidth;
canvas.height = this.screenHeight;
canvas.toBlob(function(blob) {
wallpaperBlob = blob;
canvas.width = self.screenWidth + 1;
canvas.height = self.screenHeight + 1;
canvas.toBlob(function(blob) {
bigWallpaperBlob = blob;
canvas.width = self.screenWidth >> 1;
canvas.height = self.screenHeight >> 1;
canvas.toBlob(function(blob) {
smallWallpaperBlob = blob;
// Now that we have the images defined, set up the URL mapping
urlToBlobMap[DEFAULT_WALLPAPER] = wallpaperBlob;
urlToBlobMap[dataURL] = wallpaperBlob;
urlToBlobMap[bigDataURL] = bigWallpaperBlob;
urlToBlobMap[smallDataURL] = smallWallpaperBlob;
done();
}, 'image/jpeg');
}, 'image/jpeg');
}, 'image/jpeg');
});
suiteTeardown(function() {
this.xhr.restore();
});
setup(function() {
this.sinon.stub(document, 'getElementById', function() {
return document.createElement('div');
});
var self = this;
// Mock settings
this.realMozSettings = navigator.mozSettings;
navigator.mozSettings = MockNavigatorSettings;
mockPublish = function(e) {
if (self.onWallpaperChange) {
setTimeout(function() {
if (self.onWallpaperChange) {
self.onWallpaperChange('wallpaperchange', e.detail);
}
});
}
};
window.addEventListener('wallpaperchange', mockPublish);
this.sinon.spy(MockLazyLoader, 'load');
// Spy on WallpaperManager methods
var proto = WallpaperManager.prototype;
this.setWallpaperSpy = sinon.spy(proto, '_setWallpaper');
this.toBlobSpy = sinon.spy(proto, '_toBlob');
this.checkSizeSpy = sinon.spy(proto, '_checkSize');
this.saveSpy = sinon.spy(proto, '_save');
this.validateSpy = sinon.spy(proto, '_validate');
this.publishSpy = sinon.spy(proto, '_publish');
subject = new WallpaperManager();
});
teardown(function() {
subject.stop();
this.setWallpaperSpy.restore();
this.toBlobSpy.restore();
this.checkSizeSpy.restore();
this.saveSpy.restore();
this.validateSpy.restore();
this.publishSpy.restore();
window.removeEventListener('wallpaperchange', mockPublish);
navigator.mozSettings = this.realMozSettings;
MockNavigatorSettings.mTeardown();
MockService.mockQueryWith('isDefaultPortrait', true);
this.onWallpaperChange = null;
});
test('start() throws if called twice', function() {
subject.start();
assert.throws(function() { subject.start(); });
});
//
// Test normal startup where we have a validated wallpaper blob in
// the settings db. Verify that a wallpaperchange event is published
// with a blob uri, and that the size of the image is not checked
// or changed, and that the lazy loader is not invoked.
//
test('start with validated blob', function(done) {
var self = this;
// Start with a validated blob in the settings db
MockNavigatorSettings.mSettings['wallpaper.image'] = wallpaperBlob;
MockNavigatorSettings.mSettings['wallpaper.image.valid'] = true;
// We do our assertions once we see a wallpaperchange event published.
this.onWallpaperChange = function(type, data) {
done(() => {
// Check event type
assert.equal(type, 'wallpaperchange');
// Check that we get a blob url
assert.equal(data.url.substring(0, 5), 'blob:');
// Check that the methods were called the expected number of times
sinon.assert.calledOnce(self.setWallpaperSpy);
sinon.assert.notCalled(self.toBlobSpy);
sinon.assert.notCalled(MockLazyLoader.load);
sinon.assert.notCalled(self.checkSizeSpy);
sinon.assert.notCalled(self.saveSpy);
sinon.assert.calledOnce(self.publishSpy);
});
};
subject.start();
});
//
// Test normal startup followed by a change to a new wallpaper blob that
// is too small. Verify that the wallpaper is changed and that the
// resulting wallpaper has the expected size and type. And that the
// LazyLoader is used
//
test('change to new small wallpaper blob', function(done) {
var self = this;
// Start with a validated blob in the settings db
MockNavigatorSettings.mSettings['wallpaper.image'] = wallpaperBlob;
MockNavigatorSettings.mSettings['wallpaper.image.valid'] = true;
// Wait 'till the initial wallpaper is published
this.onWallpaperChange = function(type, data) {
// Test assertions when we get the changed wallpaper
self.onWallpaperChange = function(type, data) {
// Check event type
assert.equal(type, 'wallpaperchange');
// Check that we get a blob url
assert.equal(data.url.substring(0, 5), 'blob:');
// Check that the methods were called the expected number of times
// 3 times: initial, changed, and saved wallpapers
assert.equal(self.setWallpaperSpy.callCount, 3);
assert.ok(self.toBlobSpy.notCalled, '_toBlob called');
assert.ok(MockLazyLoader.load.calledOnce);
assert.ok(self.checkSizeSpy.calledOnce, 'checkSize called');
assert.ok(self.saveSpy.calledOnce, 'save called');
assert.ok(self.validateSpy.notCalled,
'validate not called');
assert.equal(self.publishSpy.callCount, 2, 'publish called');
assert.notEqual(MockNavigatorSettings.mSettings['wallpaper.image'],
smallWallpaperBlob);
assert.notEqual(MockNavigatorSettings.mSettings['wallpaper.image'],
wallpaperBlob);
assert.equal(MockNavigatorSettings.mSettings['wallpaper.image.valid'],
true);
var blob = MockNavigatorSettings.mSettings['wallpaper.image'];
assert.equal(blob.type, ImageUtils.PNG);
ImageUtils.getSizeAndType(blob).then(function resolve(data) {
assert.equal(data.type, ImageUtils.PNG);
assert.equal(data.width, self.screenWidth);
assert.equal(data.height, self.screenHeight);
done();
});
};
navigator.mozSettings.createLock().set({
'wallpaper.image': smallWallpaperBlob
});
};
subject.start();
});
//
// Test normal startup followed by a change to a new wallpaper blob that
// is the right size. Verify that the wallpaper is changed and that the
// resulting wallpaper has the expected size and type. And that the
// LazyLoader is used
//
test('change to new right-size wallpaper blob', function(done) {
var self = this;
// Start with a validated blob in the settings db
MockNavigatorSettings.mSettings['wallpaper.image'] = wallpaperBlob;
MockNavigatorSettings.mSettings['wallpaper.image.valid'] = true;
// Wait 'till the initial wallpaper is published
this.onWallpaperChange = function(type, data) {
// Test assertions when we get the changed wallpaper
self.onWallpaperChange = function(type, data) {
// Check event type
assert.equal(type, 'wallpaperchange');
// Check that we get a blob url
assert.equal(data.url.substring(0, 5), 'blob:');
// Check that the methods were called the expected number of times
assert.equal(self.setWallpaperSpy.callCount, 2);
assert.ok(self.toBlobSpy.notCalled, '_toBlob called');
assert.ok(MockLazyLoader.load.calledOnce);
assert.ok(self.checkSizeSpy.calledOnce, 'checkSize called');
assert.ok(self.saveSpy.notCalled, 'save not called');
assert.ok(self.validateSpy.calledOnce, 'validate called');
assert.equal(self.publishSpy.callCount, 2, 'publish called');
assert.equal(MockNavigatorSettings.mSettings['wallpaper.image'],
wallpaperBlob);
assert.equal(MockNavigatorSettings.mSettings['wallpaper.image.valid'],
true);
done();
};
navigator.mozSettings.createLock().set({
'wallpaper.image': wallpaperBlob
});
};
subject.start();
});
//
// Test the startup process with a blob that has not been validated yet.
// This seems to be what happens on first boot (Somewhere in the build
// system the data uri is converted to a real blob.)
//
test('start with non-validated right-size blob', function(done) {
var self = this;
// Start with an unvalidated blob in the settings db
MockNavigatorSettings.mSettings['wallpaper.image'] = wallpaperBlob;
// We do our assertions once we see a wallpaperchange event published.
this.onWallpaperChange = function(type, data) {
// Check event type
assert.equal(type, 'wallpaperchange');
// Check that we get a blob url
assert.equal(data.url.substring(0, 5), 'blob:');
// Check that the methods were called the expected number of times
assert.ok(self.setWallpaperSpy.calledOnce);
assert.ok(self.toBlobSpy.notCalled);
assert.ok(MockLazyLoader.load.calledOnce);
assert.ok(self.checkSizeSpy.calledOnce);
assert.ok(self.saveSpy.notCalled);
assert.ok(self.validateSpy.calledOnce);
assert.ok(self.publishSpy.calledOnce);
assert.equal(MockNavigatorSettings.mSettings['wallpaper.image'],
wallpaperBlob);
assert.equal(MockNavigatorSettings.mSettings['wallpaper.image.valid'],
true);
done();
};
subject.start();
});
//
// Test the startup process with a blob that has not been validated yet
// and is not the right size. (This happens on first boot if we use a
// FWVGA wallpaper on an WVGA device or vice versa, e.g.)
//
test('start with non-validated wrong-size blob', function(done) {
var self = this;
// Start with an unvalidated blob in the settings db
MockNavigatorSettings.mSettings['wallpaper.image'] = bigWallpaperBlob;
// We do our assertions once we see a wallpaperchange event published.
this.onWallpaperChange = function(type, data) {
// Check event type
assert.equal(type, 'wallpaperchange');
// Check that we get a blob url
assert.equal(data.url.substring(0, 5), 'blob:');
// Check that the methods were called the expected number of times
assert.ok(self.toBlobSpy.notCalled, '_toBlob not called');
assert.ok(MockLazyLoader.load.calledOnce);
assert.ok(self.checkSizeSpy.calledOnce, 'checkSize called');
assert.ok(self.saveSpy.calledOnce, 'save called');
assert.ok(self.validateSpy.notCalled, 'validate not called');
assert.ok(self.publishSpy.calledOnce, 'publish called');
assert.notEqual(MockNavigatorSettings.mSettings['wallpaper.image'],
wallpaperBlob);
assert.equal(MockNavigatorSettings.mSettings['wallpaper.image.valid'],
true);
var blob = MockNavigatorSettings.mSettings['wallpaper.image'];
assert.equal(blob.type, ImageUtils.PNG);
ImageUtils.getSizeAndType(blob).then(function resolve(data) {
assert.equal(data.type, ImageUtils.PNG);
assert.equal(data.width, self.screenWidth);
assert.equal(data.height, self.screenHeight);
done();
});
};
subject.start();
});
//
// Test changed wallpaper in landscape orientation. Verify that
// the wallpaper is resized and that the resulting wallpaper has
// the expected size.
//
test('start and change wallpaper in landscape mode', function(done) {
var self = this;
MockService.mockQueryWith('isDefaultPortrait', false);
// Start with a validated blob in the settings db
MockNavigatorSettings.mSettings['wallpaper.image'] = wallpaperBlob;
MockNavigatorSettings.mSettings['wallpaper.image.valid'] = true;
// Wait 'till the initial wallpaper is published
this.onWallpaperChange = function(type, data) {
// Test assertions when we get the changed wallpaper
self.onWallpaperChange = function(type, data) {
// Check event type
assert.equal(type, 'wallpaperchange');
// Check that we get a blob url
assert.equal(data.url.substring(0, 5), 'blob:');
// Check that the methods were called the expected number of times
// 3 times: initial, changed, and saved wallpapers
assert.equal(self.setWallpaperSpy.callCount, 3);
assert.ok(self.toBlobSpy.notCalled, '_toBlob not called');
assert.ok(MockLazyLoader.load.calledOnce);
assert.ok(self.checkSizeSpy.calledOnce, 'checkSize called');
assert.ok(self.saveSpy.calledOnce, 'save called');
assert.ok(self.validateSpy.notCalled,
'validate not called');
assert.equal(self.publishSpy.callCount, 2, 'publish called');
assert.notEqual(MockNavigatorSettings.mSettings['wallpaper.image'],
wallpaperBlob);
assert.equal(MockNavigatorSettings.mSettings['wallpaper.image.valid'],
true);
var blob = MockNavigatorSettings.mSettings['wallpaper.image'];
ImageUtils.getSizeAndType(blob).then(function resolve(data) {
// Check the resized wallpaper in landscape orientation to have
// width as bigger dimension that equals screenHeight.
assert.equal(data.width, self.screenHeight);
assert.equal(data.height, self.screenWidth);
done();
});
};
navigator.mozSettings.createLock().set({
'wallpaper.image': wallpaperBlob
});
};
subject.start();
});
//
// The tests that follow call this utility function and test what happens
// when we use URLs and invalid values as the wallpaper value.
//
function testWallpaperValue(self, input, expectedOutput, done,
toBlobCallCount,
checkSizeCallCount) {
MockNavigatorSettings.mSettings['wallpaper.image'] = input;
// We do our assertions once we see a wallpaperchange event published.
self.onWallpaperChange = function(type, data) {
try {
// Check that the methods were called the expected number of times
assert.equal(self.toBlobSpy.callCount,
toBlobCallCount || 1,
'convert to blob call count');
assert.ok(MockLazyLoader.load.called,
'lazy loader used');
assert.equal(self.checkSizeSpy.callCount,
checkSizeCallCount || 1,
'check wallpaper called');
assert.ok(self.saveSpy.calledOnce,
'save called once');
assert.ok(self.publishSpy.calledOnce, 'publish called once');
assert.equal(MockNavigatorSettings.mSettings['wallpaper.image.valid'],
true);
var blob = MockNavigatorSettings.mSettings['wallpaper.image'];
if (expectedOutput) {
assert.equal(blob, expectedOutput, 'saved blob is as expected');
done();
}
else {
ImageUtils.getSizeAndType(blob).then(function resolve(data) {
assert.equal(data.width, self.screenWidth);
assert.equal(data.height, self.screenHeight);
done();
})['catch'](function(err) {
assert.isFalse(err);
});
}
}
catch(ex) {
done(ex);
}
};
subject.start();
}
// No value in the settings db at all
test('undefined wallpaper', function(done) {
testWallpaperValue(this, undefined, wallpaperBlob, done);
});
// Non-blob, non-URL value in the settings db
test('invalid wallpaper', function(done) {
testWallpaperValue(this, 1, wallpaperBlob, done);
});
// default wallpaper url in settings db
test('default wallpaper url', function(done) {
testWallpaperValue(this, DEFAULT_WALLPAPER, wallpaperBlob, done);
});
// Data url that resolves to a right-size image
test('right-size data uri', function(done) {
testWallpaperValue(this, this.dataURL, wallpaperBlob, done);
});
// Data url that resolves to a small image
test('small data uri', function(done) {
testWallpaperValue(this, this.smallDataURL, null, done);
});
// Data url that resolves to a big image
test('big data uri', function(done) {
testWallpaperValue(this, this.bigDataURL, null, done);
});
// URL that causes an XHR error and forces fallback on default
test('broken URL', function(done) {
testWallpaperValue(this, '/foo/bar', wallpaperBlob, done, 2);
});
// Invalid image blob that forces fallback on default
test('broken image blob', function(done) {
var badBlob = new Blob(['GIF89a'], { type: 'image/gif' });
testWallpaperValue(this, badBlob, wallpaperBlob, done, 1, 2);
});
// default wallpaper is wrong size
test('default wallpaper url', function(done) {
this.urlToBlobMap[DEFAULT_WALLPAPER] = smallWallpaperBlob;
testWallpaperValue(this, DEFAULT_WALLPAPER, null, done);
});
});