SuitestAutomation/suitest-js-api

View on GitHub
lib/utils/testHelpers/mockWebSocket.js

Summary

Maintainability
A
1 hr
Test Coverage
F
0%
/* istanbul ignore file */
/**
 * Mocked WebSockets client module.
 */
const MockWebSocket = require('mock-socket').WebSocket;
const {v1: uuid} = require('uuid');
const {config} = require('../../../index');
const SuitestError = require('../SuitestError');
const texts = require('../../texts');
const {handleProgress} = require('../progressHandler');
const mock = require('mock-require');

let ws = null,
    mockedResponse,
    requestPromises = {},
    connectionPromise = null;

/**
 * Mocked connect to ws server
 */
function connect(connectionOps = {}) {
    disconnect();

    ws = new MockWebSocket(config.wsUrl, connectionOps);

    ws.onmessage = msg => {
        handleResponse(JSON.parse(msg.data));
    };

    ws.onopen = () => {
        connectionPromise.resolve();
        connectionPromise = null;
    };

    ws.onclose = () => {
        disconnect();
    };

    ws.onerror = error => {
        connectionPromise && connectionPromise.reject(
            new SuitestError(texts.wsNotConnected() + (error ? ` ${error}.` : ''), SuitestError.WS_ERROR));
        disconnect();
    };

    return new Promise((resolve, reject) => {
        connectionPromise = {
            resolve,
            reject,
        };
    });
}

/**
 * Handle ws response, resolve promise from requestPromises map by response messageId
 * @param {*} msg
 */
function handleResponse(msg) {
    const messageId = msg.messageId;
    const res = msg.content.response || msg.content;
    const req = requestPromises[messageId];

    if (mockedResponse) {
        req.resolve(mockedResponse);

        return;
    }

    /* istanbul ignore else */
    if (req) {
        if (['query', 'testLine', 'eval'].includes(req.contentType)) {
            req.resolve({
                ...res,
                contentType: req.contentType,
            }); // resolve chain requests
        } else if (res.result === 'success') {
            req.resolve(res);
        } else {
            req.reject(new SuitestError(res.error ? res.error : '', SuitestError.UNKNOWN_ERROR));
        }

        delete requestPromises[messageId];
    }
    if (res.type === 'progress') {
        handleProgress(res);
    }
}

/**
 * Handle ws request, add promise to requestPromises map by request messageId
 * @param {string} messageId
 * @param contentType
 * @returns {Promise}
 */
function handleRequest(messageId, contentType) {
    return new Promise((resolve, reject) => {
        requestPromises[messageId] = {
            resolve,
            reject,
            contentType,
        };
    });
}

/**
 * Send ws message
 * @param {Object} content
 * @returns {Promise}
 */
function send(content) {
    if (ws) {
        const messageId = uuid();

        const msg = JSON.stringify({
            messageId,
            content,
        });

        ws.send(msg);

        return handleRequest(messageId, content.type);
    }

    return Promise.reject(new SuitestError(texts.wsNotConnected(), SuitestError.WS_ERROR));
}

/**
 * Disconnect from ws server
 */
function disconnect() {
    if (ws) {
        ws.close(1000, 'mocked ws good bye!');
    }

    ws = null;
    requestPromises = {};
    connectionPromise = null;
}

/**
 * Check if ws client is connected to server
 */
function isConnected() {
    return !!ws;
}

/**
 * Mock WS response
 */
function mockResponse(resp) {
    mockedResponse = resp;
}
function restoreResponse() {
    mockedResponse = undefined;
}

module.exports = {
    mockResponse,
    restoreResponse,
};

mock('../../api/webSockets', {
    connect,
    disconnect,
    send,
    isConnected,
    mockResponse,
    restoreResponse,
});