bus/static/tests/helpers/mock_websocket.js

109 lines
3.3 KiB
JavaScript
Raw Normal View History

2024-05-03 15:03:07 +03:00
/** @odoo-module **/
import { WebsocketWorker } from "@bus/workers/websocket_worker";
import { browser } from "@web/core/browser/browser";
import { patchWithCleanup } from "@web/../tests/helpers/utils";
import { registerCleanup } from "@web/../tests/helpers/cleanup";
class WebSocketMock extends EventTarget {
constructor() {
super();
this.readyState = 0;
queueMicrotask(() => {
this.readyState = 1;
const openEv = new Event("open");
this.onopen(openEv);
this.dispatchEvent(openEv);
});
}
close(code = 1000, reason) {
this.readyState = 3;
const closeEv = new CloseEvent("close", {
code,
reason,
wasClean: code === 1000,
});
this.onclose(closeEv);
this.dispatchEvent(closeEv);
}
onclose(closeEv) {}
onerror(errorEv) {}
onopen(openEv) {}
send(data) {
if (this.readyState !== 1) {
const errorEv = new Event("error");
this.onerror(errorEv);
this.dispatchEvent(errorEv);
throw new DOMException("Failed to execute 'send' on 'WebSocket': State is not OPEN");
}
}
}
class SharedWorkerMock extends EventTarget {
constructor(websocketWorker) {
super();
this._websocketWorker = websocketWorker;
this._messageChannel = new MessageChannel();
this.port = this._messageChannel.port1;
// port 1 should be started by the service itself.
this._messageChannel.port2.start();
this._websocketWorker.registerClient(this._messageChannel.port2);
}
}
class WorkerMock extends SharedWorkerMock {
constructor(websocketWorker) {
super(websocketWorker);
this.port.start();
this.postMessage = this.port.postMessage.bind(this.port);
}
}
let websocketWorker;
/**
* @param {*} params Parameters used to patch the websocket worker.
* @returns {WebsocketWorker} Instance of the worker which will run during the
* test. Usefull to interact with the worker in order to test the
* websocket behavior.
*/
export function patchWebsocketWorkerWithCleanup(params = {}) {
patchWithCleanup(window, {
WebSocket: function () {
return new WebSocketMock();
},
});
patchWithCleanup(websocketWorker || WebsocketWorker.prototype, params);
websocketWorker = websocketWorker || new WebsocketWorker();
websocketWorker.INITIAL_RECONNECT_DELAY = 0;
websocketWorker.RECONNECT_JITTER = 0;
patchWithCleanup(browser, {
SharedWorker: function () {
const sharedWorker = new SharedWorkerMock(websocketWorker);
registerCleanup(() => {
sharedWorker._messageChannel.port1.close();
sharedWorker._messageChannel.port2.close();
});
return sharedWorker;
},
Worker: function () {
const worker = new WorkerMock(websocketWorker);
registerCleanup(() => {
worker._messageChannel.port1.close();
worker._messageChannel.port2.close();
});
return worker;
},
});
registerCleanup(() => {
if (websocketWorker) {
clearTimeout(websocketWorker.connectTimeout);
websocketWorker = null;
}
});
return websocketWorker;
}