diff --git a/frontend/playwright/helpers/MockWebSocket.js b/frontend/playwright/helpers/MockWebSocket.js index 18134ff78..1a6c8eb81 100644 --- a/frontend/playwright/helpers/MockWebSocket.js +++ b/frontend/playwright/helpers/MockWebSocket.js @@ -1,5 +1,72 @@ -export class WebSocketManager { +export class MockWebSocket extends EventTarget { + static #mocks = new Map(); + static async init(page) { + await page.exposeFunction("MockWebSocket$$constructor", (url, protocols) => { + console.log("MockWebSocket$$constructor", MockWebSocket, url, protocols); + const webSocket = new MockWebSocket(page, url, protocols); + this.#mocks.set(url, webSocket); + }); + await page.exposeFunction("MockWebSocket$$spyMessage", (url, data) => { + console.log("MockWebSocket$$spyMessage", url, data); + this.#mocks.get(url).dispatchEvent(new MessageEvent("message", { data })); + }); + await page.exposeFunction("MockWebSocket$$spyClose", (url, code, reason) => { + console.log("MockWebSocket$$spyClose", url, code, reason); + this.#mocks.get(url).dispatchEvent(new CloseEvent("close", { code, reason })); + }); await page.addInitScript({ path: "playwright/scripts/MockWebSocket.js" }); } + + static waitForURL(url) { + return new Promise((resolve) => { + const intervalID = setInterval(() => { + for (const [wsURL, ws] of this.#mocks) { + console.log('waitForURL', wsURL); + if (wsURL.includes(url)) { + clearInterval(intervalID); + return resolve(ws); + } + } + }, 30); + }); + } + + #page = null; + #url; + #protocols; + + constructor(page, url, protocols) { + super(); + this.#page = page; + this.#url = url; + this.#protocols = protocols; + } + + mockOpen(options) { + return this.#page.evaluate(({ url, options }) => { + if (typeof WebSocket.getByURL !== 'function') { + throw new Error('WebSocket.getByURL is not a function. Did you forget to call MockWebSocket.init(page)?') + } + WebSocket.getByURL(url).mockOpen(options); + }, { url: this.#url, options }); + } + + mockMessage(data) { + return this.#page.evaluate(({ url, data }) => { + if (typeof WebSocket.getByURL !== 'function') { + throw new Error('WebSocket.getByURL is not a function. Did you forget to call MockWebSocket.init(page)?') + } + WebSocket.getByURL(url).mockMessage(data); + }, { url: this.#url, data }); + } + + mockClose() { + return this.#page.evaluate(({ url }) => { + if (typeof WebSocket.getByURL !== 'function') { + throw new Error('WebSocket.getByURL is not a function. Did you forget to call MockWebSocket.init(page)?') + } + WebSocket.getByURL(url).mockClose(); + }, { url: this.#url }); + } } diff --git a/frontend/playwright/scripts/MockWebSocket.js b/frontend/playwright/scripts/MockWebSocket.js index a7449827e..60723eb29 100644 --- a/frontend/playwright/scripts/MockWebSocket.js +++ b/frontend/playwright/scripts/MockWebSocket.js @@ -11,20 +11,15 @@ window.WebSocket = class MockWebSocket extends EventTarget { } static getByURL(url) { - return this.#mocks.get(url); - } - - static waitForURL(url) { - return new Promise((resolve) => { - let intervalID = setInterval(() => { - for (const [wsURL, ws] of this.#mocks) { - if (wsURL.includes(url)) { - clearInterval(intervalID); - resolve(ws); - } - } - }, 30); - }); + 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; diff --git a/frontend/playwright/workspace.spec.js b/frontend/playwright/workspace.spec.js index ff0bc5fee..07e8762ca 100644 --- a/frontend/playwright/workspace.spec.js +++ b/frontend/playwright/workspace.spec.js @@ -1,6 +1,6 @@ import { test, expect } from "@playwright/test"; import { interceptRPC, interceptRPCByRegex } from "./helpers/MockAPI"; -import { WebSocketManager } from "./helpers/MockWebSocket"; +import { MockWebSocket } from "./helpers/MockWebSocket"; import { presenceFixture } from "./fixtures/workspace/ws-notifications"; const anyProjectId = "c7ce0794-0992-8105-8004-38e630f7920b"; @@ -30,7 +30,7 @@ const setupWorkspaceUser = (page) => { }; test.beforeEach(async ({ page }) => { - await WebSocketManager.init(page); + await MockWebSocket.init(page); }); test("User loads worskpace with empty file", async ({ page }) => { @@ -45,13 +45,15 @@ test.only("User receives notifications updates in the workspace", async ({ page await setupWorkspaceUser(page); await page.goto(`/#/workspace/${anyProjectId}/${anyFileId}?page-id=${anyPageId}`); - await page.evaluate(async () => { - const ws = await WebSocket.waitForURL("ws://0.0.0.0:3500/ws/notifications"); - ws.mockOpen(); - }); + const ws = await MockWebSocket.waitForURL("ws://0.0.0.0:3500/ws/notifications") + await ws.mockOpen(); + console.log('JEEEEEE', ws) await expect(page.getByTestId("page-name")).toHaveText("Page 1"); + await ws.mockMessage(JSON.stringify(presenceFixture)); + + /* await page.evaluate( async ({ presenceFixture }) => { const ws = await WebSocket.waitForURL("ws://0.0.0.0:3500/ws/notifications"); @@ -59,11 +61,16 @@ test.only("User receives notifications updates in the workspace", async ({ page }, { presenceFixture }, ); + */ - expect(page.getByTestId("active-users-list").getByAltText("Princesa Leia")).toHaveCount(2); + await expect(page.getByTestId("active-users-list").getByAltText("Princesa Leia")).toHaveCount(2); + await ws.mockClose(); + + /* await page.evaluate(async () => { const ws = await WebSocket.waitForURL("ws://0.0.0.0:3500/ws/notifications"); ws.mockClose(); }); + */ });