@theia/core
Version:
Theia is a cloud & desktop IDE framework implemented in TypeScript.
162 lines • 9.28 kB
JavaScript
// *****************************************************************************
// Copyright (C) 2018 TypeFox and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************
Object.defineProperty(exports, "__esModule", { value: true });
const jsdom_1 = require("../browser/test/jsdom");
let disableJSDOM = (0, jsdom_1.enableJSDOM)();
const frontend_application_config_provider_1 = require("./frontend-application-config-provider");
frontend_application_config_provider_1.FrontendApplicationConfigProvider.set({});
const chai_1 = require("chai");
const connection_status_service_1 = require("./connection-status-service");
const mock_connection_status_service_1 = require("./test/mock-connection-status-service");
const sinon = require("sinon");
const inversify_1 = require("inversify");
const ws_connection_provider_1 = require("./messaging/ws-connection-provider");
const common_1 = require("../common");
disableJSDOM();
describe('connection-status', function () {
let connectionStatusService;
before(() => {
disableJSDOM = (0, jsdom_1.enableJSDOM)();
});
after(() => {
disableJSDOM();
});
beforeEach(() => {
connectionStatusService = new mock_connection_status_service_1.MockConnectionStatusService();
});
afterEach(() => {
if (connectionStatusService !== undefined) {
connectionStatusService.dispose();
}
});
it('should go from online to offline if the connection is down', async () => {
(0, chai_1.expect)(connectionStatusService.currentStatus).to.be.equal(connection_status_service_1.ConnectionStatus.ONLINE);
connectionStatusService.alive = false;
await pause();
(0, chai_1.expect)(connectionStatusService.currentStatus).to.be.equal(connection_status_service_1.ConnectionStatus.OFFLINE);
});
it('should go from offline to online if the connection is re-established', async () => {
(0, chai_1.expect)(connectionStatusService.currentStatus).to.be.equal(connection_status_service_1.ConnectionStatus.ONLINE);
connectionStatusService.alive = false;
await pause();
(0, chai_1.expect)(connectionStatusService.currentStatus).to.be.equal(connection_status_service_1.ConnectionStatus.OFFLINE);
connectionStatusService.alive = true;
await pause();
(0, chai_1.expect)(connectionStatusService.currentStatus).to.be.equal(connection_status_service_1.ConnectionStatus.ONLINE);
});
});
describe('frontend-connection-status', function () {
const OFFLINE_TIMEOUT = 10;
let testContainer;
const mockSocketOpenedEmitter = new common_1.Emitter();
const mockSocketClosedEmitter = new common_1.Emitter();
const mockIncomingMessageActivityEmitter = new common_1.Emitter();
before(() => {
disableJSDOM = (0, jsdom_1.enableJSDOM)();
});
after(() => {
disableJSDOM();
});
let timer;
let pingSpy;
beforeEach(() => {
const mockWebSocketConnectionProvider = sinon.createStubInstance(ws_connection_provider_1.WebSocketConnectionProvider);
const mockPingService = {
ping() {
return Promise.resolve(undefined);
}
};
const mockILogger = {
error(loggable) {
return Promise.resolve(undefined);
}
};
testContainer = new inversify_1.Container();
testContainer.bind(connection_status_service_1.FrontendConnectionStatusService).toSelf().inSingletonScope();
testContainer.bind(connection_status_service_1.PingService).toConstantValue(mockPingService);
testContainer.bind(common_1.ILogger).toConstantValue(mockILogger);
testContainer.bind(connection_status_service_1.ConnectionStatusOptions).toConstantValue({ offlineTimeout: OFFLINE_TIMEOUT });
testContainer.bind(ws_connection_provider_1.WebSocketConnectionProvider).toConstantValue(mockWebSocketConnectionProvider);
sinon.stub(mockWebSocketConnectionProvider, 'onSocketDidOpen').value(mockSocketOpenedEmitter.event);
sinon.stub(mockWebSocketConnectionProvider, 'onSocketDidClose').value(mockSocketClosedEmitter.event);
sinon.stub(mockWebSocketConnectionProvider, 'onIncomingMessageActivity').value(mockIncomingMessageActivityEmitter.event);
timer = sinon.useFakeTimers();
pingSpy = sinon.spy(mockPingService, 'ping');
});
afterEach(() => {
pingSpy.restore();
timer.restore();
testContainer.unbindAll();
});
it('should switch status to offline on websocket close', () => {
const frontendConnectionStatusService = testContainer.get(connection_status_service_1.FrontendConnectionStatusService);
frontendConnectionStatusService['init']();
(0, chai_1.expect)(frontendConnectionStatusService.currentStatus).to.be.equal(connection_status_service_1.ConnectionStatus.ONLINE);
mockSocketClosedEmitter.fire(undefined);
(0, chai_1.expect)(frontendConnectionStatusService.currentStatus).to.be.equal(connection_status_service_1.ConnectionStatus.OFFLINE);
});
it('should switch status to online on websocket established', () => {
const frontendConnectionStatusService = testContainer.get(connection_status_service_1.FrontendConnectionStatusService);
frontendConnectionStatusService['init']();
mockSocketClosedEmitter.fire(undefined);
(0, chai_1.expect)(frontendConnectionStatusService.currentStatus).to.be.equal(connection_status_service_1.ConnectionStatus.OFFLINE);
mockSocketOpenedEmitter.fire(undefined);
(0, chai_1.expect)(frontendConnectionStatusService.currentStatus).to.be.equal(connection_status_service_1.ConnectionStatus.ONLINE);
});
it('should switch status to online on any websocket activity', () => {
const frontendConnectionStatusService = testContainer.get(connection_status_service_1.FrontendConnectionStatusService);
frontendConnectionStatusService['init']();
mockSocketClosedEmitter.fire(undefined);
(0, chai_1.expect)(frontendConnectionStatusService.currentStatus).to.be.equal(connection_status_service_1.ConnectionStatus.OFFLINE);
mockIncomingMessageActivityEmitter.fire(undefined);
(0, chai_1.expect)(frontendConnectionStatusService.currentStatus).to.be.equal(connection_status_service_1.ConnectionStatus.ONLINE);
});
it('should perform ping request after socket activity', () => {
const frontendConnectionStatusService = testContainer.get(connection_status_service_1.FrontendConnectionStatusService);
frontendConnectionStatusService['init']();
mockIncomingMessageActivityEmitter.fire(undefined);
(0, chai_1.expect)(frontendConnectionStatusService.currentStatus).to.be.equal(connection_status_service_1.ConnectionStatus.ONLINE);
sinon.assert.notCalled(pingSpy);
timer.tick(OFFLINE_TIMEOUT);
sinon.assert.calledOnce(pingSpy);
});
it('should not perform ping request before desired timeout', () => {
const frontendConnectionStatusService = testContainer.get(connection_status_service_1.FrontendConnectionStatusService);
frontendConnectionStatusService['init']();
mockIncomingMessageActivityEmitter.fire(undefined);
(0, chai_1.expect)(frontendConnectionStatusService.currentStatus).to.be.equal(connection_status_service_1.ConnectionStatus.ONLINE);
sinon.assert.notCalled(pingSpy);
timer.tick(OFFLINE_TIMEOUT - 1);
sinon.assert.notCalled(pingSpy);
});
it('should switch to offline mode if ping request was rejected', () => {
const pingService = testContainer.get(connection_status_service_1.PingService);
pingSpy.restore();
const stub = sinon.stub(pingService, 'ping').onFirstCall().throws('failed to make a ping request');
const frontendConnectionStatusService = testContainer.get(connection_status_service_1.FrontendConnectionStatusService);
frontendConnectionStatusService['init']();
mockIncomingMessageActivityEmitter.fire(undefined);
(0, chai_1.expect)(frontendConnectionStatusService.currentStatus).to.be.equal(connection_status_service_1.ConnectionStatus.ONLINE);
timer.tick(OFFLINE_TIMEOUT);
sinon.assert.calledOnce(stub);
(0, chai_1.expect)(frontendConnectionStatusService.currentStatus).to.be.equal(connection_status_service_1.ConnectionStatus.OFFLINE);
});
});
function pause(time = 1) {
return new Promise(resolve => setTimeout(resolve, time));
}
//# sourceMappingURL=connection-status-service.spec.js.map
;