0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-09 16:30:37 -05:00
penpot/frontend/playwright/scripts/MockWebSocket.js
2024-07-01 10:29:57 +02:00

238 lines
5 KiB
JavaScript

window.WebSocket = class MockWebSocket extends EventTarget {
static CONNECTING = 0;
static OPEN = 1;
static CLOSING = 2;
static CLOSED = 3;
static #mocks = new Map();
static getAll() {
return this.#mocks.values();
}
static getByURL(url) {
if (this.#mocks.has(url)) {
return this.#mocks.get(url);
}
for (const [wsURL, ws] of this.#mocks) {
if (wsURL.includes(url)) {
return ws;
}
}
return undefined;
}
#url;
#protocols;
#protocol = "";
#binaryType = "blob";
#bufferedAmount = 0;
#extensions = "";
#readyState = MockWebSocket.CONNECTING;
#onopen = null;
#onerror = null;
#onmessage = null;
#onclose = null;
#spyMessage = null;
#spyClose = null;
constructor(url, protocols) {
super();
this.#url = url;
this.#protocols = protocols || [];
MockWebSocket.#mocks.set(this.#url, this);
if (typeof window["onMockWebSocketConstructor"] === "function") {
onMockWebSocketConstructor(this.#url, this.#protocols);
}
if (typeof window["onMockWebSocketSpyMessage"] === "function") {
this.#spyMessage = onMockWebSocketSpyMessage;
}
if (typeof window["onMockWebSocketSpyClose"] === "function") {
this.#spyClose = onMockWebSocketSpyClose;
}
}
set binaryType(binaryType) {
if (!["blob", "arraybuffer"].includes(binaryType)) {
return;
}
this.#binaryType = binaryType;
}
get binaryType() {
return this.#binaryType;
}
get bufferedAmount() {
return this.#bufferedAmount;
}
get extensions() {
return this.#extensions;
}
get readyState() {
return this.#readyState;
}
get protocol() {
return this.#protocol;
}
get url() {
return this.#url;
}
set onopen(callback) {
this.removeEventListener("open", this.#onopen);
this.#onopen = null;
if (typeof callback === "function") {
this.addEventListener("open", callback);
this.#onopen = callback;
}
}
get onopen() {
return this.#onopen;
}
set onerror(callback) {
this.removeEventListener("error", this.#onerror);
this.#onerror = null;
if (typeof callback === "function") {
this.addEventListener("error", callback);
this.#onerror = callback;
}
}
get onerror() {
return this.#onerror;
}
set onmessage(callback) {
this.removeEventListener("message", this.#onmessage);
this.#onmessage = null;
if (typeof callback === "function") {
this.addEventListener("message", callback);
this.#onmessage = callback;
}
}
get onmessage() {
return this.#onmessage;
}
set onclose(callback) {
this.removeEventListener("close", this.#onclose);
this.#onclose = null;
if (typeof callback === "function") {
this.addEventListener("close", callback);
this.#onclose = callback;
}
}
get onclose() {
return this.#onclose;
}
get mockProtocols() {
return this.#protocols;
}
spyClose(callback) {
if (typeof callback !== "function") {
throw new TypeError("Invalid callback");
}
this.#spyClose = callback;
return this;
}
spyMessage(callback) {
if (typeof callback !== "function") {
throw new TypeError("Invalid callback");
}
this.#spyMessage = callback;
return this;
}
mockOpen(options) {
this.#protocol = options?.protocol || "";
this.#extensions = options?.extensions || "";
this.#readyState = MockWebSocket.OPEN;
this.dispatchEvent(new Event("open"));
return this;
}
mockError(error) {
this.#readyState = MockWebSocket.CLOSED;
this.dispatchEvent(new ErrorEvent("error", { error }));
return this;
}
mockMessage(data) {
if (this.#readyState !== MockWebSocket.OPEN) {
throw new Error("MockWebSocket is not connected");
}
this.dispatchEvent(new MessageEvent("message", { data }));
return this;
}
mockClose(code, reason) {
this.#readyState = MockWebSocket.CLOSED;
this.dispatchEvent(
new CloseEvent("close", { code: code || 1000, reason: reason || "" }),
);
return this;
}
send(data) {
if (this.#readyState === MockWebSocket.CONNECTING) {
throw new DOMException(
"InvalidStateError",
"MockWebSocket is not connected",
);
}
if (this.#spyMessage) {
this.#spyMessage(this.url, data);
}
}
close(code, reason) {
if (
code &&
!Number.isInteger(code) &&
code !== 1000 &&
(code < 3000 || code > 4999)
) {
throw new DOMException("InvalidAccessError", "Invalid code");
}
if (reason && typeof reason === "string") {
const reasonBytes = new TextEncoder().encode(reason);
if (reasonBytes.length > 123) {
throw new DOMException("SyntaxError", "Reason is too long");
}
}
if (
[MockWebSocket.CLOSED, MockWebSocket.CLOSING].includes(this.#readyState)
) {
return;
}
this.#readyState = MockWebSocket.CLOSING;
if (this.#spyClose) {
this.#spyClose(this.url, code, reason);
}
}
};