Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/apps/system/test/unit/updatable_test.js
diff options
context:
space:
mode:
Diffstat (limited to 'apps/system/test/unit/updatable_test.js')
-rw-r--r--apps/system/test/unit/updatable_test.js630
1 files changed, 630 insertions, 0 deletions
diff --git a/apps/system/test/unit/updatable_test.js b/apps/system/test/unit/updatable_test.js
new file mode 100644
index 0000000..7af2abf
--- /dev/null
+++ b/apps/system/test/unit/updatable_test.js
@@ -0,0 +1,630 @@
+'use strict';
+
+requireApp('system/js/updatable.js');
+
+requireApp('system/test/unit/mock_app.js');
+requireApp('system/test/unit/mock_asyncStorage.js');
+requireApp('system/test/unit/mock_update_manager.js');
+requireApp('system/test/unit/mock_window_manager.js');
+requireApp('system/test/unit/mock_apps_mgmt.js');
+requireApp('system/test/unit/mock_chrome_event.js');
+requireApp('system/test/unit/mock_custom_dialog.js');
+requireApp('system/test/unit/mock_utility_tray.js');
+requireApp('system/test/unit/mock_manifest_helper.js');
+requireApp('system/test/unit/mocks_helper.js');
+
+
+var mocksForUpdatable = [
+ 'CustomDialog',
+ 'UpdateManager',
+ 'WindowManager',
+ 'UtilityTray',
+ 'ManifestHelper',
+ 'asyncStorage'
+];
+
+mocksForUpdatable.forEach(function(mockName) {
+ if (!window[mockName]) {
+ window[mockName] = null;
+ }
+});
+
+suite('system/Updatable', function() {
+ var subject;
+ var mockApp;
+
+ var realDispatchEvent;
+ var realL10n;
+
+ var mocksHelper;
+
+ var lastDispatchedEvent = null;
+ var fakeDispatchEvent;
+
+ suiteSetup(function() {
+ realL10n = navigator.mozL10n;
+ navigator.mozL10n = {
+ get: function get(key) {
+ return key;
+ }
+ };
+
+ mocksHelper = new MocksHelper(mocksForUpdatable);
+ mocksHelper.suiteSetup();
+ });
+
+ suiteTeardown(function() {
+ navigator.mozL10n = realL10n;
+ mocksHelper.suiteTeardown();
+ });
+
+ setup(function() {
+ mockApp = new MockApp();
+ subject = new AppUpdatable(mockApp);
+ subject._mgmt = MockAppsMgmt;
+
+ fakeDispatchEvent = function(type, value) {
+ lastDispatchedEvent = {
+ type: type,
+ value: value
+ };
+ };
+ subject._dispatchEvent = fakeDispatchEvent;
+
+ mocksHelper.setup();
+ });
+
+ teardown(function() {
+ MockAppsMgmt.mTeardown();
+ mocksHelper.teardown();
+
+ subject._dispatchEvent = realDispatchEvent;
+ lastDispatchedEvent = null;
+ });
+
+ function downloadAvailableSuite(name, setupFunc) {
+ suite(name, function() {
+ setup(setupFunc);
+
+ test('should add self to the available downloads', function() {
+ assert.isNotNull(MockUpdateManager.mLastUpdatesAdd);
+ assert.equal(MockUpdateManager.mLastUpdatesAdd.app.mId,
+ mockApp.mId);
+ });
+
+ suite('first progress', function() {
+ setup(function() {
+ mockApp.mTriggerDownloadProgress(42);
+ });
+
+ test('should add self to active downloads', function() {
+ assert.isNotNull(MockUpdateManager.mLastDownloadsAdd);
+ assert.equal(MockUpdateManager.mLastDownloadsAdd.app.mId,
+ mockApp.mId);
+ });
+
+ test('should start with first progress value', function() {
+ assert.equal(42, subject.progress);
+ });
+ });
+ });
+ }
+
+ suite('init', function() {
+ test('should keep a reference to the app', function() {
+ assert.equal(mockApp, subject.app);
+ });
+
+ test('should handle fresh app with just an updateManifest', function() {
+ var freshApp = new MockApp();
+ freshApp.manifest = undefined;
+ subject = new AppUpdatable(freshApp);
+ assert.equal(freshApp, subject.app);
+ });
+
+ test('should add itself to updatable apps', function() {
+ assert.equal(MockUpdateManager.mLastUpdatableAdd, subject);
+ });
+
+ test('should remember about the update on startup', function() {
+ asyncStorage.mItems[SystemUpdatable.KNOWN_UPDATE_FLAG] = true;
+ var systemUpdatable = new SystemUpdatable();
+ assert.equal(MockUpdateManager.mCheckForUpdatesCalledWith, true);
+ });
+
+ downloadAvailableSuite('app has a download available', function() {
+ mockApp.downloadAvailable = true;
+ subject = new AppUpdatable(mockApp);
+ });
+
+ test('should apply update if downloaded', function() {
+ mockApp.readyToApplyDownload = true;
+ subject = new AppUpdatable(mockApp);
+ // We cannot test for this._mgmt methods because it's created in
+ // a constructor, so we check if the window is killed because
+ // WindowManager.kill() is also called in applyUpdate() method
+ assert.equal(MockWindowManager.mLastKilledOrigin, subject.app.origin);
+ });
+ });
+
+ suite('infos', function() {
+ suite('name', function() {
+ test('should give a name for system updates', function() {
+ subject = new SystemUpdatable(42);
+ assert.equal('systemUpdate', subject.name);
+ });
+
+ test('should give a name for app updates', function() {
+ assert.equal('Mock app', subject.name);
+ });
+ });
+
+ suite('size', function() {
+ test('should give packaged app update size', function() {
+ assert.equal(null, subject.size);
+ });
+
+ test('should return null for hosted apps', function() {
+ mockApp.updateManifest = null;
+ subject = new AppUpdatable(mockApp);
+ assert.isNull(subject.size);
+ });
+
+ test('should update size on download available', function() {
+ mockApp.updateManifest = null;
+ subject = new AppUpdatable(mockApp);
+ assert.isNull(subject.size);
+
+ mockApp.mTriggerDownloadAvailable(45678);
+ assert.equal(45678, subject.size);
+ });
+ });
+ });
+
+ suite('actions', function() {
+ suite('ask for download', function() {
+ setup(function() {
+ mockApp.mTriggerDownloadAvailable();
+ subject.download();
+ });
+
+ test('should call download on the app', function() {
+ assert.isTrue(mockApp.mDownloadCalled);
+ });
+ });
+
+ suite('download system update', function() {
+ setup(function() {
+ subject = new SystemUpdatable(42);
+ subject._dispatchEvent = fakeDispatchEvent;
+ subject.progress = 42;
+ subject.download();
+ });
+
+ test('should send download message for system updates', function() {
+ assert.equal('update-available-result', lastDispatchedEvent.type);
+ assert.equal('download', lastDispatchedEvent.value);
+ });
+
+ test('should add system updates to active downloads too', function() {
+ assert.isNotNull(MockUpdateManager.mLastDownloadsAdd);
+ assert.equal(subject, MockUpdateManager.mLastDownloadsAdd);
+ });
+
+ test('should start system updates with progress 0 too', function() {
+ assert.equal(subject.progress, 0);
+ });
+
+ test('should do nothing if already downloading', function() {
+ lastDispatchedEvent = null;
+ subject.progress = 42;
+ subject.download();
+
+ assert.equal(subject.progress, 42);
+ assert.isNull(lastDispatchedEvent);
+ });
+ });
+
+ suite('cancel app update download', function() {
+ setup(function() {
+ subject.cancelDownload();
+ });
+
+ test('should call cancelDownload on the app', function() {
+ assert.isTrue(mockApp.mCancelCalled);
+ });
+ });
+
+ suite('cancel system update download', function() {
+ setup(function() {
+ asyncStorage.setItem(SystemUpdatable.KNOWN_UPDATE_FLAG, true);
+ subject = new SystemUpdatable(42);
+ subject.download();
+ subject._dispatchEvent = fakeDispatchEvent;
+ subject.cancelDownload();
+ });
+
+ test('should send cancel message', function() {
+ assert.equal('update-download-cancel', lastDispatchedEvent.type);
+ });
+
+ test('should remove the downloading flag', function() {
+ assert.isFalse(subject.downloading);
+ });
+ });
+ });
+
+ suite('events', function() {
+ suite('apps events', function() {
+ // This function checks that we release the callbacks properly
+ // at the end of a download. Assumes subject.download() was called.
+ function testCleanup() {
+ test('should stop responding to progress', function() {
+ mockApp.mTriggerDownloadProgress(42);
+ assert.notEqual(subject.progress, 42);
+ });
+
+ test('should stop responding to error', function() {
+ MockUpdateManager.mErrorBannerRequested = false;
+ mockApp.mTriggerDownloadError();
+ assert.isFalse(MockUpdateManager.mErrorBannerRequested);
+ });
+
+ test('progress should be reset', function() {
+ assert.isNull(subject.progress);
+ });
+ }
+
+ downloadAvailableSuite('ondownloadavailable', function() {
+ mockApp.mTriggerDownloadAvailable();
+ });
+
+ suite('ondownloadavailable when not installed', function() {
+ setup(function() {
+ mockApp.installState = 'pending';
+ mockApp.mTriggerDownloadAvailable();
+ });
+
+ test('should not add self to the available downloads', function() {
+ assert.isNull(MockUpdateManager.mLastUpdatesAdd);
+ });
+
+ test('should not answer to progress', function() {
+ mockApp.mTriggerDownloadSuccess();
+ assert.isNull(MockUpdateManager.mLastDownloadsRemoval);
+ });
+ });
+
+ suite('downloadavailable at init when not installed', function() {
+ setup(function() {
+ mockApp.installState = 'pending';
+ subject = new AppUpdatable(mockApp);
+ mockApp.mTriggerDownloadAvailable();
+ });
+
+ test('should not add self to the available downloads', function() {
+ assert.isNull(MockUpdateManager.mLastUpdatesAdd);
+ });
+
+ test('should not answer to progress', function() {
+ mockApp.mTriggerDownloadSuccess();
+ assert.isNull(MockUpdateManager.mLastDownloadsRemoval);
+ });
+ });
+
+ suite('ondownloadsuccess', function() {
+ test('should remove self from active downloads', function() {
+ mockApp.mTriggerDownloadAvailable();
+ mockApp.mTriggerDownloadProgress(42);
+ mockApp.mTriggerDownloadSuccess();
+ assert.isNotNull(MockUpdateManager.mLastDownloadsRemoval);
+ assert.equal(MockUpdateManager.mLastDownloadsRemoval.app.mId,
+ mockApp.mId);
+ });
+
+ test('should not remove self if not downloading', function() {
+ mockApp.mTriggerDownloadSuccess();
+ assert.isNull(MockUpdateManager.mLastDownloadsRemoval);
+ });
+
+ test('should remove self from available downloads', function() {
+ mockApp.mTriggerDownloadAvailable();
+ mockApp.mTriggerDownloadProgress(42);
+ mockApp.mTriggerDownloadSuccess();
+ assert.isNotNull(MockUpdateManager.mLastUpdatesRemoval);
+ assert.equal(MockUpdateManager.mLastUpdatesRemoval.app.mId,
+ mockApp.mId);
+ });
+
+ suite('application of the download', function() {
+ test('should apply if the app is not in foreground', function() {
+ mockApp.mTriggerDownloadAvailable();
+ MockWindowManager.mDisplayedApp =
+ 'http://homescreen.gaiamobile.org';
+ mockApp.mTriggerDownloadSuccess();
+ assert.isNotNull(MockAppsMgmt.mLastAppApplied);
+ assert.equal(MockAppsMgmt.mLastAppApplied.mId, mockApp.mId);
+ });
+
+ test('should wait for appwillclose if it is', function() {
+ var origin = 'http://testapp.gaiamobile.org';
+ mockApp.origin = origin;
+ MockWindowManager.mDisplayedApp = origin;
+
+ mockApp.mTriggerDownloadAvailable();
+ mockApp.mTriggerDownloadSuccess();
+ assert.isNull(MockAppsMgmt.mLastAppApplied);
+
+ var evt = document.createEvent('CustomEvent');
+ evt.initCustomEvent('appwillclose', true, false,
+ { origin: origin });
+ window.dispatchEvent(evt);
+
+ assert.isNotNull(MockAppsMgmt.mLastAppApplied);
+ assert.equal(MockAppsMgmt.mLastAppApplied.mId, mockApp.mId);
+ });
+
+ test('should kill the app before applying the update', function() {
+ mockApp.mTriggerDownloadAvailable();
+ mockApp.mTriggerDownloadSuccess();
+ assert.equal('https://testapp.gaiamobile.org',
+ MockWindowManager.mLastKilledOrigin);
+ });
+ });
+ });
+
+ suite('ondownloaderror', function() {
+ setup(function() {
+ mockApp.mTriggerDownloadAvailable();
+ mockApp.mTriggerDownloadError();
+ });
+
+ test('should request error banner', function() {
+ assert.isTrue(MockUpdateManager.mErrorBannerRequested);
+ });
+
+ test('should remove self from active downloads', function() {
+ assert.isNotNull(MockUpdateManager.mLastDownloadsRemoval);
+ assert.equal(MockUpdateManager.mLastDownloadsRemoval.app.mId,
+ mockApp.mId);
+ });
+
+ test('progress should be reset', function() {
+ assert.isNull(subject.progress);
+ });
+
+ test('should still answer to progress events', function() {
+ mockApp.mTriggerDownloadProgress(42);
+ assert.equal(42, subject.progress);
+ });
+ });
+
+ suite('onprogress', function() {
+ setup(function() {
+ mockApp.mTriggerDownloadAvailable();
+ });
+
+ test('should send progress to update manager', function() {
+ mockApp.mTriggerDownloadProgress(1234);
+ assert.equal(1234, MockUpdateManager.mProgressCalledWith);
+ });
+
+ test('should send progress delta to update manager', function() {
+ mockApp.mTriggerDownloadProgress(1234);
+ mockApp.mTriggerDownloadProgress(2234);
+ assert.equal(1000, MockUpdateManager.mProgressCalledWith);
+ });
+ });
+
+ suite('ondownloadapplied', function() {
+ setup(function() {
+ mockApp.mTriggerDownloadAvailable();
+ mockApp.mTriggerDownloadApplied();
+ });
+
+ testCleanup();
+ });
+ });
+
+ suite('system update events', function() {
+ setup(function() {
+ subject = new SystemUpdatable(42);
+ subject._dispatchEvent = fakeDispatchEvent;
+ subject.download();
+ });
+
+ suite('update-downloaded', function() {
+ setup(function() {
+ asyncStorage.setItem(SystemUpdatable.KNOWN_UPDATE_FLAG, true);
+ var event = new MockChromeEvent({
+ type: 'update-downloaded'
+ });
+ subject.handleEvent(event);
+ });
+
+ test('should reset the downloading flag', function() {
+ assert.isFalse(subject.downloading);
+ });
+
+ test('should reset SystemUpdatable.KNOWN_UPDATE_FLAG', function() {
+ assert.isUndefined(asyncStorage.mItems[SystemUpdatable.KNOWN_UPDATE_FLAG]);
+ });
+
+ testSystemApplyPrompt();
+ });
+
+ suite('update-prompt-apply', function() {
+ setup(function() {
+ asyncStorage.setItem(SystemUpdatable.KNOWN_UPDATE_FLAG, true);
+ MockUtilityTray.show();
+ var event = new MockChromeEvent({
+ type: 'update-prompt-apply'
+ });
+ subject.handleEvent(event);
+ });
+
+ test('should reset SystemUpdatable.KNOWN_UPDATE_FLAG', function() {
+ assert.isUndefined(asyncStorage.mItems[SystemUpdatable.KNOWN_UPDATE_FLAG]);
+ });
+
+ testSystemApplyPrompt();
+ });
+
+ suite('update-error', function() {
+ setup(function() {
+ subject = new SystemUpdatable(42);
+ var event = new MockChromeEvent({
+ type: 'update-error'
+ });
+ subject.handleEvent(event);
+ });
+
+ test('should request error banner', function() {
+ assert.isTrue(MockUpdateManager.mErrorBannerRequested);
+ });
+
+ test('should remove self from active downloads', function() {
+ assert.isNotNull(MockUpdateManager.mLastDownloadsRemoval);
+ assert.equal(subject, MockUpdateManager.mLastDownloadsRemoval);
+ });
+
+ test('should remove the downloading flag', function() {
+ assert.isFalse(subject.downloading);
+ });
+ });
+
+ suite('update download events', function() {
+ var event;
+ setup(function() {
+ subject = new SystemUpdatable(98734);
+ subject.download();
+ });
+
+ suite('when the download starts', function() {
+ setup(function() {
+ event = new MockChromeEvent({
+ type: 'update-download-started',
+ total: 98734
+ });
+ });
+
+ test('should clear paused flag', function() {
+ subject.paused = true;
+ subject.handleEvent(event);
+ assert.isFalse(subject.paused);
+ });
+ });
+
+ suite('when the download receives progress', function() {
+ setup(function() {
+ event = new MockChromeEvent({
+ type: 'update-download-progress',
+ progress: 1234,
+ total: 98734
+ });
+ });
+
+ test('should send progress to update manager', function() {
+ subject.handleEvent(event);
+ assert.equal(1234, MockUpdateManager.mProgressCalledWith);
+ });
+
+ test('should send progress delta to update manager', function() {
+ subject.handleEvent(event);
+ event.detail.progress = 2234;
+ subject.handleEvent(event);
+ assert.equal(1000, MockUpdateManager.mProgressCalledWith);
+ });
+ });
+
+ suite('when the download is paused', function() {
+ setup(function() {
+ asyncStorage.setItem(SystemUpdatable.KNOWN_UPDATE_FLAG, true);
+ event = new MockChromeEvent({
+ type: 'update-download-stopped',
+ paused: true
+ });
+ subject.handleEvent(event);
+ });
+
+ test('should set the paused flag', function() {
+ assert.isTrue(subject.paused);
+ });
+ test('shouldn\'t signal "started uncompressing"', function() {
+ assert.isFalse(MockUpdateManager.mStartedUncompressingCalled);
+ });
+ test('should not reset SystemUpdatable.KNOWN_UPDATE_FLAG', function() {
+ assert.isTrue(asyncStorage.mItems[SystemUpdatable.KNOWN_UPDATE_FLAG]);
+ });
+ });
+
+ suite('when the download is complete', function() {
+ setup(function() {
+ asyncStorage.setItem(SystemUpdatable.KNOWN_UPDATE_FLAG, true);
+ event = new MockChromeEvent({
+ type: 'update-download-stopped',
+ paused: false
+ });
+ subject.handleEvent(event);
+ });
+
+ test('should clear the paused flag', function() {
+ assert.isFalse(subject.paused);
+ });
+
+ test('should signal the UpdateManager', function() {
+ assert.isTrue(MockUpdateManager.mStartedUncompressingCalled);
+ });
+ test('should not reset SystemUpdatable.KNOWN_UPDATE_FLAG', function() {
+ assert.isTrue(asyncStorage.mItems[SystemUpdatable.KNOWN_UPDATE_FLAG]);
+ });
+ });
+ });
+ });
+ });
+
+
+ function testSystemApplyPrompt() {
+ test('apply prompt shown', function() {
+ assert.isTrue(MockCustomDialog.mShown);
+ assert.equal('systemUpdateReady', MockCustomDialog.mShowedTitle);
+ assert.equal('wantToInstall', MockCustomDialog.mShowedMsg);
+
+ assert.equal('later', MockCustomDialog.mShowedCancel.title);
+ assert.equal('installNow', MockCustomDialog.mShowedConfirm.title);
+ });
+
+ test('utility tray hidden', function() {
+ assert.isFalse(MockUtilityTray.mShown);
+ });
+
+ test('apply prompt cancel callback', function() {
+ assert.equal(subject.declineInstall.name,
+ MockCustomDialog.mShowedCancel.callback.name);
+
+ subject.declineInstall();
+ assert.isFalse(MockCustomDialog.mShown);
+
+ assert.equal('update-prompt-apply-result', lastDispatchedEvent.type);
+ assert.equal('wait', lastDispatchedEvent.value);
+ });
+
+ test('canceling should remove from downloads queue', function() {
+ subject.declineInstall();
+
+ assert.isNotNull(MockUpdateManager.mLastDownloadsRemoval);
+ assert.equal(subject, MockUpdateManager.mLastDownloadsRemoval);
+ });
+
+ test('apply prompt confirm callback', function() {
+ assert.equal(subject.acceptInstall.name,
+ MockCustomDialog.mShowedConfirm.callback.name);
+
+ subject.acceptInstall();
+ assert.isFalse(MockCustomDialog.mShown);
+
+ assert.equal('update-prompt-apply-result', lastDispatchedEvent.type);
+ assert.equal('restart', lastDispatchedEvent.value);
+ });
+ }
+});