packagemanager-service.test.js 13.4 KB
/*
 *
 * ADOBE CONFIDENTIAL
 * __________________
 *
 *  Copyright 2017 Adobe Systems Incorporated
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Adobe Systems Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Adobe Systems Incorporated and its
 * suppliers and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Adobe Systems Incorporated.
 */

/* eslint max-nested-callbacks: [2, 10]*/

/* globals sinon, describe, it, expect, before, beforeEach, afterEach */
define([
    'screens/player/firmware/packagemanager/packagemanager',
    'screens/player/firmware/packagemanager/impl/packagemanager-service',
    'screens/player/firmware/packagemanager/spi/sync',
    'screens/player/firmware/filesystem/filesystem',
    'screens/player/store/store',
    'screens/player/firmware/preferences/preferences',
    'screens/player/shared/serviceadmin',
    'screens/player/shared/test-helper/service',
    'screens/player/shared/test-helper/stub-service-interface'
], function(PackageManager, PackageManagerService, SyncSpi, FilesystemService, Store, Preferences, ServiceAdmin, serviceTestHelper, stubServiceInterface) {
    'use strict';

    var PACKAGE_URL = '/some/some.zip';
    var TARGET_PATH = 'path';
    var UPDATE_MODE = 'replace';
    var TITLE = 'title';
    var UID = 'uid';

    var SERVER_URL = 'http://aem-instance:4502';
    var USER_DATA_PATH = '/some/path';

    var PACKAGE_TIMESTAMP = 100;
    var TIMESTAMP_NOT_EXPIRED = 50;
    var TIMESTAMP_EXPIRED = 150;
    var TIMESTAMP_FORCE_UPDATE = 0;
    var PROGRESS = 1;
    var STATUS = 1;

    describe('screens/player/firmware/packagemanager/impl/packagemanager-service', function() {

        var packageManager;
        var sync;
        var filesystem;
        var preferences;

        var someError;
        var expectedResolvedPayload;
        var expectedRejectedPayload;
        var expectedStartedEventPayload;
        var expectedProgressEventPayload;

        beforeEach(function() {
            packageManager = new PackageManagerService();

            sync = stubServiceInterface(ServiceAdmin, SyncSpi);

            filesystem = stubServiceInterface(ServiceAdmin, FilesystemService);
            filesystem.api.getUserDataPath.returns(Promise.resolve(USER_DATA_PATH));
            filesystem.api.joinPath.returns(USER_DATA_PATH + '/www');

            preferences = stubServiceInterface(ServiceAdmin, Preferences);
            preferences.api.getPreferences.returns({ server: SERVER_URL });

            someError = new Error('some error');
            expectedResolvedPayload = {
                title: TITLE,
                url: SERVER_URL + PACKAGE_URL
            };
            expectedRejectedPayload = {
                title: TITLE,
                url: SERVER_URL + PACKAGE_URL,
                error: someError
            };
            expectedStartedEventPayload = {
                title: TITLE,
                url: SERVER_URL + PACKAGE_URL
            };
            expectedProgressEventPayload = {
                progress: PROGRESS,
                status: STATUS,
                title: TITLE,
                url: SERVER_URL + PACKAGE_URL
            };

        });

        afterEach(function() {
            sync.restore();
            filesystem.restore();
            preferences.restore();
        });

        before(function() {
            serviceTestHelper.runDefaultTests(packageManager, PackageManager.serviceName);
        });

        describe('updatePackage', function() {

            describe('updates a package when package does not exist yet', function() {
                beforeEach(function() {
                    filesystem.api.readFileAsText.returns(Promise.reject(someError));
                });
                it('returns resolved promise with newly synced package', function() {
                    sync.api.sync.returns(Promise.resolve());
                    return packageManager.updatePackage(PACKAGE_URL, TARGET_PATH, TIMESTAMP_EXPIRED, UPDATE_MODE, TITLE, UID).then(function(payload) {
                        expectFilesystemToBeCalled();
                        expectSyncToBeCalled();
                        expect(payload).to.deep.equal(expectedResolvedPayload);
                    });
                });
                it('emits "STARTED" event', function() {
                    var spy = sinon.spy();
                    packageManager.on(PackageManager.EVENTS.SYNC_STARTED, spy);
                    sync.api.sync.returns(Promise.resolve());
                    return packageManager.updatePackage(PACKAGE_URL, TARGET_PATH, TIMESTAMP_EXPIRED, UPDATE_MODE, TITLE, UID).then(function(payload) {
                        expect(spy).to.have.been.calledWithExactly(expectedStartedEventPayload);
                    });
                });
                it('emits "PROGRESS" event', function() {
                    var spy = sinon.spy();
                    packageManager.on(PackageManager.EVENTS.SYNC_PROGRESS, spy);
                    sync.api.sync.returns(Promise.resolve());
                    sync.api.sync.callsArgWith(3, {status: STATUS, progress: PROGRESS});
                    return packageManager.updatePackage(PACKAGE_URL, TARGET_PATH, TIMESTAMP_EXPIRED, UPDATE_MODE, TITLE, UID).then(function(payload) {
                        expect(spy).to.have.been.calledWithExactly(expectedProgressEventPayload);
                    });
                });
                it('returns rejected promise in case sync fails', function(done) {
                    sync.api.sync.returns(Promise.reject(someError));
                    return packageManager.updatePackage(PACKAGE_URL, TARGET_PATH, TIMESTAMP_EXPIRED, UPDATE_MODE, TITLE, UID).catch(function(payload) {
                        expectFilesystemToBeCalled();
                        expectSyncToBeCalled();
                        expect(payload).to.deep.equal(expectedRejectedPayload);
                        done();
                    });
                });
            });

            describe('does not update a package that has not expired', function() {
                beforeEach(function() {
                    sync.api.sync.returns(Promise.resolve());
                    filesystem.api.readFileAsText.returns(Promise.resolve('{ "lastModified": ' + PACKAGE_TIMESTAMP + ' }'));
                });
                it('returns resolved promise with existing package infos', function() {
                    return packageManager.updatePackage(PACKAGE_URL, TARGET_PATH, TIMESTAMP_NOT_EXPIRED, UPDATE_MODE, TITLE, UID).then(function(payload) {
                        expectFilesystemToBeCalled();
                        expectSyncNotToBeCalled();
                        expect(payload).to.deep.equal(expectedResolvedPayload);
                    });
                });
                it('does not emit "STARTED" event', function() {
                    var spy = sinon.spy();
                    packageManager.on(PackageManager.EVENTS.SYNC_STARTED, spy);
                    return packageManager.updatePackage(PACKAGE_URL, TARGET_PATH, TIMESTAMP_NOT_EXPIRED, UPDATE_MODE, TITLE, UID).then(function(payload) {
                        expect(spy).not.called;
                    });
                });
                it('does not emit "PROGRESS" event', function() {
                    var spy = sinon.spy();
                    packageManager.on(PackageManager.EVENTS.SYNC_PROGRESS, spy);
                    sync.api.sync.callsArgWith(3, {status: STATUS, progress: PROGRESS});
                    return packageManager.updatePackage(PACKAGE_URL, TARGET_PATH, TIMESTAMP_NOT_EXPIRED, UPDATE_MODE, TITLE, UID).then(function(payload) {
                        expect(spy).not.called;
                    });
                });
            });

            describe('updates a package that has expired', function() {
                beforeEach(function() {
                    filesystem.api.readFileAsText.returns(Promise.resolve('{ "lastModified": ' + PACKAGE_TIMESTAMP + ' }'));
                });
                it('returns resolved promise with newly synced package', function() {
                    sync.api.sync.returns(Promise.resolve());
                    return packageManager.updatePackage(PACKAGE_URL, TARGET_PATH, TIMESTAMP_EXPIRED, UPDATE_MODE, TITLE, UID).then(function(payload) {
                        expectFilesystemToBeCalled();
                        expectSyncToBeCalled();
                        expect(payload).to.deep.equal(expectedResolvedPayload);
                    });
                });
                it('emits "STARTED" event', function() {
                    var spy = sinon.spy();
                    packageManager.on(PackageManager.EVENTS.SYNC_STARTED, spy);
                    sync.api.sync.returns(Promise.resolve());
                    return packageManager.updatePackage(PACKAGE_URL, TARGET_PATH, TIMESTAMP_EXPIRED, UPDATE_MODE, TITLE, UID).then(function(payload) {
                        expect(spy).to.have.been.calledWithExactly(expectedStartedEventPayload);
                    });
                });
                it('emits "PROGRESS" event', function() {
                    var spy = sinon.spy();
                    packageManager.on(PackageManager.EVENTS.SYNC_PROGRESS, spy);
                    sync.api.sync.returns(Promise.resolve());
                    sync.api.sync.callsArgWith(3, {status: STATUS, progress: PROGRESS});
                    return packageManager.updatePackage(PACKAGE_URL, TARGET_PATH, TIMESTAMP_EXPIRED, UPDATE_MODE, TITLE, UID).then(function(payload) {
                        expect(spy).to.have.been.calledWithExactly(expectedProgressEventPayload);
                    });
                });
                it('returns rejected promise in case sync fails', function(done) {
                    sync.api.sync.returns(Promise.reject(someError));
                    return packageManager.updatePackage(PACKAGE_URL, TARGET_PATH, TIMESTAMP_EXPIRED, UPDATE_MODE, TITLE, UID).catch(function(payload) {
                        expectFilesystemToBeCalled();
                        expectSyncToBeCalled();
                        expect(payload).to.deep.equal(expectedRejectedPayload);
                        done();
                    });
                });
            });

            describe('forces the update of an existing package when given timestamp is 0', function() {
                beforeEach(function() {
                    filesystem.api.readFileAsText.returns(Promise.resolve('{ "lastModified": ' + PACKAGE_TIMESTAMP + ' }'));
                });
                it('returns resolved promise with newly synced package', function() {
                    sync.api.sync.returns(Promise.resolve());
                    return packageManager.updatePackage(PACKAGE_URL, TARGET_PATH, TIMESTAMP_FORCE_UPDATE, UPDATE_MODE, TITLE, UID).then(function(payload) {
                        expectSyncToBeCalled();
                        expect(payload).to.deep.equal(expectedResolvedPayload);
                    });
                });
                it('emits "STARTED" event', function() {
                    var spy = sinon.spy();
                    packageManager.on(PackageManager.EVENTS.SYNC_STARTED, spy);
                    sync.api.sync.returns(Promise.resolve());
                    return packageManager.updatePackage(PACKAGE_URL, TARGET_PATH, TIMESTAMP_FORCE_UPDATE, UPDATE_MODE, TITLE, UID).then(function(payload) {
                        expect(spy).to.have.been.calledWithExactly(expectedStartedEventPayload);
                    });
                });
                it('emits "PROGRESS" event', function() {
                    var spy = sinon.spy();
                    packageManager.on(PackageManager.EVENTS.SYNC_PROGRESS, spy);
                    sync.api.sync.returns(Promise.resolve());
                    sync.api.sync.callsArgWith(3, {status: STATUS, progress: PROGRESS});
                    return packageManager.updatePackage(PACKAGE_URL, TARGET_PATH, TIMESTAMP_FORCE_UPDATE, UPDATE_MODE, TITLE, UID).then(function(payload) {
                        expect(spy).to.have.been.calledWithExactly(expectedProgressEventPayload);
                    });
                });
                it('returns rejected promise in case sync fails', function(done) {
                    sync.api.sync.returns(Promise.reject(someError));
                    return packageManager.updatePackage(PACKAGE_URL, TARGET_PATH, TIMESTAMP_FORCE_UPDATE, UPDATE_MODE, TITLE, UID).catch(function(payload) {
                        expectSyncToBeCalled();
                        expect(payload).to.deep.equal(expectedRejectedPayload);
                        done();
                    });
                });
            });
        });

        function expectFilesystemToBeCalled() {
            expect(filesystem.api.getUserDataPath.called);
            expect(filesystem.api.readFileAsText.called);
            expect(filesystem.api.readFileAsText.getCall(0).args[0]).contain(USER_DATA_PATH);
        }

        function expectSyncToBeCalled() {
            expect(sync.api.sync.called);
            expect(sync.api.sync.getCall(0).args[0]).contain(PACKAGE_URL);
            expect(sync.api.sync.getCall(0).args[2]).equal(UPDATE_MODE);
        }

        function expectSyncNotToBeCalled() {
            expect(sync.api.sync).not.called;
        }
    });
});