@copperjs/copper
Version:
A lightweight chromium grid
104 lines • 4.67 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const sinon = require("sinon");
const WebSocket = require("ws");
const httpProxy = require("http-proxy");
const chai_1 = require("chai");
const fastify_1 = require("fastify");
const websockets_1 = require("./websockets");
const utils_1 = require("./utils");
const config_1 = require("../standalone/config");
describe('sessionProxy', () => {
let fastifyInstance;
let httpProxyStub;
let httpProxyWSStub;
let proxyEventHandlers;
let port;
let handlerMock;
beforeEach(async () => {
const wsServer = new WebSocket.Server({ noServer: true });
proxyEventHandlers = {};
httpProxyWSStub = sinon.stub().callsFake((req, socket, head) => {
wsServer.handleUpgrade(req, socket, head, (socket) => {
wsServer.emit('connection', socket);
});
});
httpProxyStub = sinon.stub(httpProxy, 'createProxyServer').returns({
ws: httpProxyWSStub,
on: sinon.stub().callsFake((name, handle) => {
proxyEventHandlers[name] = handle;
}),
});
handlerMock = {
getWebSocketUrl: sinon.stub().returns('wsUrl'),
getSession: sinon.stub().returns({ id: 'id' }),
createSession: sinon.stub().resolves({ id: 'id' }),
};
fastifyInstance = fastify_1.default();
websockets_1.registerWebsocket(fastifyInstance, handlerMock, () => ({}));
await fastifyInstance.listen(0);
port = fastifyInstance.server.address().port;
await fastifyInstance.ready();
});
afterEach(async () => {
config_1.copperConfig.reset();
httpProxyStub.restore();
handlerMock.createSession.reset();
handlerMock.getSession.reset();
handlerMock.getWebSocketUrl.reset();
await fastifyInstance.close();
});
it('should return a sessions websocket url', async () => {
const response = await fastifyInstance.inject({
url: '/ws/id/json/version',
method: 'GET',
});
chai_1.expect(response.statusCode).to.equal(200);
chai_1.expect(response.body).to.equal(JSON.stringify({ id: 'id', webSocketDebuggerUrl: 'ws://localhost:80/ws/id' }));
});
it('should proxy websocket connections', async () => {
const ws = new WebSocket(`ws://localhost:${port}/ws/id`);
await new Promise((resolve) => ws.once('open', () => resolve()));
chai_1.expect(httpProxyWSStub).to.have.been.calledOnce;
chai_1.expect(handlerMock.getWebSocketUrl).to.have.been.calledOnce;
chai_1.expect(handlerMock.getWebSocketUrl).to.have.been.calledWith('id');
ws.close();
await new Promise((resolve) => ws.on('close', () => resolve()));
});
it('should create a session if id not passed', async () => {
const ws = new WebSocket(`ws://localhost:${port}`);
await new Promise((resolve) => ws.once('open', () => resolve()));
chai_1.expect(handlerMock.createSession).to.have.been.calledOnce;
chai_1.expect(handlerMock.createSession).to.have.been.calledWith(undefined);
ws.close();
await new Promise((resolve) => ws.on('close', () => resolve()));
});
it('should use default session options from config', async () => {
const config = { chromeFlags: ['--headless'] };
config_1.copperConfig.value.defaultSessionOptions = config;
const ws = new WebSocket(`ws://localhost:${port}`);
await new Promise((resolve) => ws.once('open', () => resolve()));
chai_1.expect(handlerMock.createSession).to.have.been.calledOnce;
chai_1.expect(handlerMock.createSession).to.have.been.calledWithMatch({ chromeOptions: config });
ws.close();
await new Promise((resolve) => ws.on('close', () => resolve()));
});
it('should log and ignore errors', async () => {
handlerMock.getWebSocketUrl.throws('err');
const ws = new WebSocket(`ws://localhost:${port}/ws/id`, { timeout: 5 });
ws.on('error', () => ({}));
ws.on('unexpected-response', () => ({}));
await utils_1.delay(10);
chai_1.expect(httpProxyWSStub).not.to.have.been.called;
chai_1.expect(ws.readyState).to.equal(ws.CLOSED);
try {
ws.close();
}
catch (_a) { } //ignore error
});
it('should handle proxy error', async () => {
chai_1.expect(proxyEventHandlers.error).to.be.a('function');
chai_1.expect(() => proxyEventHandlers.error({})).to.not.throw();
});
});
//# sourceMappingURL=websockets.test.js.map