From 9c5eb9630b1c5c2f3af45e0b3e63dc9b25b08617 Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Wed, 8 May 2024 17:04:20 +0200 Subject: [PATCH] Merge pull request #18222 from overleaf/jpa-socket-io-mock [web] replace socket.io-mock with simple EventEmitter based interface GitOrigin-RevId: 012e4263367a83e16efea3947f310a2de9a65279 --- package-lock.json | 20 ------- .../js/ide/connection/SocketIoShim.js | 20 +++++++ .../web/frontend/js/utils/EventEmitter.js | 54 +++++++------------ .../web/frontend/stories/decorators/scope.tsx | 6 +-- .../frontend/stories/file-tree.stories.jsx | 35 ++++-------- services/web/package.json | 1 - .../chat/context/chat-context.test.jsx | 44 +++++++-------- .../components/file-tree-root.spec.tsx | 12 ++--- .../file-tree/flows/create-folder.spec.tsx | 28 +++++----- .../file-tree/flows/delete-entity.spec.tsx | 38 ++++++------- .../file-tree/flows/rename-entity.spec.tsx | 16 +++--- .../frontend/helpers/editor-providers.jsx | 6 +-- 12 files changed, 120 insertions(+), 160 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9192411c30..3ff920d673 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36399,15 +36399,6 @@ "ultron": "1.0.x" } }, - "node_modules/socket.io-mock": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/socket.io-mock/-/socket.io-mock-1.3.2.tgz", - "integrity": "sha512-p4MQBue3NAR8bXIHynRJxK/C+J3I3NpnnpgjptgLFSWv4u9Bdkubf2t0GCmyLmUTi03up0Cx/hQwzQfOpD187g==", - "dev": true, - "dependencies": { - "component-emitter": "^1.3.0" - } - }, "node_modules/socket.io/node_modules/redis": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/redis/-/redis-0.7.3.tgz", @@ -44209,7 +44200,6 @@ "sinon": "^7.5.0", "sinon-chai": "^3.7.0", "sinon-mongoose": "^2.3.0", - "socket.io-mock": "^1.3.1", "storybook": "^8.0.4", "stylelint-config-standard-scss": "^13.1.0", "terser-webpack-plugin": "^5.3.9", @@ -52659,7 +52649,6 @@ "sinon": "^7.5.0", "sinon-chai": "^3.7.0", "sinon-mongoose": "^2.3.0", - "socket.io-mock": "^1.3.1", "storybook": "^8.0.4", "stylelint-config-standard-scss": "^13.1.0", "terser-webpack-plugin": "^5.3.9", @@ -75993,15 +75982,6 @@ } } }, - "socket.io-mock": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/socket.io-mock/-/socket.io-mock-1.3.2.tgz", - "integrity": "sha512-p4MQBue3NAR8bXIHynRJxK/C+J3I3NpnnpgjptgLFSWv4u9Bdkubf2t0GCmyLmUTi03up0Cx/hQwzQfOpD187g==", - "dev": true, - "requires": { - "component-emitter": "^1.3.0" - } - }, "sockjs": { "version": "0.3.24", "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", diff --git a/services/web/frontend/js/ide/connection/SocketIoShim.js b/services/web/frontend/js/ide/connection/SocketIoShim.js index c27e01b795..7c9b863046 100644 --- a/services/web/frontend/js/ide/connection/SocketIoShim.js +++ b/services/web/frontend/js/ide/connection/SocketIoShim.js @@ -1,6 +1,7 @@ /* global io */ import { debugConsole } from '@/utils/debugging' +import EventEmitter from '@/utils/EventEmitter' class SocketShimBase { static connect(url, options) { @@ -218,6 +219,25 @@ if (typeof io === 'undefined' || !io) { current = SocketShimV2 } +export class SocketIOMock extends EventEmitter { + addListener(event, listener) { + this.on(event, listener) + } + + removeListener(event, listener) { + this.off(event, listener) + } + + disconnect() { + this.emitToClient('disconnect') + } + + emitToClient(...args) { + // Round-trip through JSON.parse/stringify to simulate (de-)serializing on network layer. + this.emit(...JSON.parse(JSON.stringify(args))) + } +} + export default { SocketShimNoop, SocketShimV0, diff --git a/services/web/frontend/js/utils/EventEmitter.js b/services/web/frontend/js/utils/EventEmitter.js index a2c86e70c3..84e8c2fc2c 100644 --- a/services/web/frontend/js/utils/EventEmitter.js +++ b/services/web/frontend/js/utils/EventEmitter.js @@ -1,18 +1,3 @@ -/* eslint-disable - camelcase, - max-len, - no-return-assign, - no-unused-vars, -*/ -// TODO: This file was created by bulk-decaffeinate. -// Fix any style issues and re-enable lint. -/* - * decaffeinate suggestions: - * DS101: Remove unnecessary use of Array.from - * DS102: Remove unnecessary code created because of implicit returns - * DS207: Consider shorter variations of null checks - * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md - */ // Simple event emitter implementation, but has a slightly unusual API for // removing specific listeners. If a specific listener needs to be removed // (instead of all listeners), then it needs to use a "namespace": @@ -23,43 +8,44 @@ export default class EventEmitter { on(event, callback) { - let namespace if (!this.events) { this.events = {} } + let namespace ;[event, namespace] = Array.from(event.split('.')) if (!this.events[event]) { this.events[event] = [] } - return this.events[event].push({ + this.events[event].push({ callback, namespace, }) } - off(event) { + off(event, cb) { if (!this.events) { this.events = {} } - if (event != null) { + if (event) { let namespace - ;[event, namespace] = Array.from(event.split('.')) - if (namespace == null) { + ;[event, namespace] = event.split('.') + if (!this.events[event]) { + this.events[event] = [] + } + if (cb) { + this.events[event] = this.events[event].filter(e => e.callback !== cb) + } else if (!namespace) { // Clear all listeners for event - return delete this.events[event] + delete this.events[event] } else { // Clear only namespaced listeners - const remaining_events = [] - for (const callback of Array.from(this.events[event] || [])) { - if (callback.namespace !== namespace) { - remaining_events.push(callback) - } - } - return (this.events[event] = remaining_events) + this.events[event] = this.events[event].filter( + e => e.namespace !== namespace + ) } } else { // Remove all listeners - return (this.events = {}) + this.events = {} } } @@ -67,12 +53,12 @@ export default class EventEmitter { if (!this.events) { this.events = {} } - return Array.from(this.events[event] || []).map(callback => - callback.callback(...Array.from(args || [])) - ) + if (this.events[event]) { + this.events[event].forEach(e => e.callback(...args)) + } } emit(...args) { - return this.trigger(...Array.from(args || [])) + this.trigger(...args) } } diff --git a/services/web/frontend/stories/decorators/scope.tsx b/services/web/frontend/stories/decorators/scope.tsx index 311655c2ed..54cd27e627 100644 --- a/services/web/frontend/stories/decorators/scope.tsx +++ b/services/web/frontend/stories/decorators/scope.tsx @@ -24,6 +24,7 @@ import { FileTreePathProvider } from '@/features/file-tree/contexts/file-tree-pa import { UserSettingsProvider } from '@/shared/context/user-settings-context' import { OutlineProvider } from '@/features/ide-react/context/outline-context' import { ChatProvider } from '@/features/chat/context/chat-context' +import { SocketIOMock } from '@/ide/connection/SocketIoShim' const scopeWatchers: [string, (value: any) => void][] = [] @@ -105,10 +106,7 @@ const initialize = () => { const ide = { $scope: scope, - socket: { - on: () => {}, - removeListener: () => {}, - }, + socket: new SocketIOMock(), editorManager: { getCurrentDocId: () => 'foo', openDoc: (id: string, options: unknown) => { diff --git a/services/web/frontend/stories/file-tree.stories.jsx b/services/web/frontend/stories/file-tree.stories.jsx index d7373094d0..1832024e25 100644 --- a/services/web/frontend/stories/file-tree.stories.jsx +++ b/services/web/frontend/stories/file-tree.stories.jsx @@ -1,5 +1,3 @@ -import MockedSocket from 'socket.io-mock' - import { rootFolderBase } from './fixtures/file-tree-base' import { rootFolderLimit } from './fixtures/file-tree-limit' import FileTreeRoot from '../js/features/file-tree/components/file-tree-root' @@ -7,13 +5,10 @@ import FileTreeError from '../js/features/file-tree/components/file-tree-error' import useFetchMock from './hooks/use-fetch-mock' import { ScopeDecorator } from './decorators/scope' import { useScope } from './hooks/use-scope' +import { useIdeContext } from '@/shared/context/ide-context' const MOCK_DELAY = 2000 -window._ide = { - ...window._ide, - socket: new MockedSocket(), -} const DEFAULT_PROJECT = { _id: '123abc', name: 'Some Project', @@ -21,18 +16,14 @@ const DEFAULT_PROJECT = { rootFolder: rootFolderBase, } -function defaultSetupMocks(fetchMock) { +function defaultSetupMocks(fetchMock, socket) { fetchMock .post( /\/project\/\w+\/(file|doc|folder)\/\w+\/rename/, (path, req) => { const body = JSON.parse(req.body) const entityId = path.match(/([^/]+)\/rename$/)[1] - window._ide.socket.socketClient.emit( - 'reciveEntityRename', - entityId, - body.name - ) + socket.emitToClient('reciveEntityRename', entityId, body.name) return 204 }, @@ -51,11 +42,7 @@ function defaultSetupMocks(fetchMock) { _id: Math.random().toString(16).replace(/0\./, 'random-test-id-'), name: body.name, } - window._ide.socket.socketClient.emit( - 'reciveNewFolder', - body.parent_folder_id, - newFolder - ) + socket.emitToClient('reciveNewFolder', body.parent_folder_id, newFolder) return newFolder }, { @@ -66,7 +53,7 @@ function defaultSetupMocks(fetchMock) { /\/project\/\w+\/(file|doc|folder)\/\w+/, path => { const entityId = path.match(/[^/]+$/)[0] - window._ide.socket.socketClient.emit('removeEntity', entityId) + socket.emitToClient('removeEntity', entityId) return 204 }, { @@ -76,17 +63,14 @@ function defaultSetupMocks(fetchMock) { .post(/\/project\/\w+\/(file|doc|folder)\/\w+\/move/, (path, req) => { const body = JSON.parse(req.body) const entityId = path.match(/([^/]+)\/move/)[1] - window._ide.socket.socketClient.emit( - 'reciveEntityMove', - entityId, - body.folder_id - ) + socket.emitToClient('reciveEntityMove', entityId, body.folder_id) return 204 }) } export const FullTree = args => { - useFetchMock(defaultSetupMocks) + const { socket } = useIdeContext() + useFetchMock(fetchMock => defaultSetupMocks(fetchMock, socket)) useScope({ project: DEFAULT_PROJECT, @@ -149,7 +133,8 @@ export const FallbackError = args => { } export const FilesLimit = args => { - useFetchMock(defaultSetupMocks) + const { socket } = useIdeContext() + useFetchMock(fetchMock => defaultSetupMocks(fetchMock, socket)) useScope({ project: { diff --git a/services/web/package.json b/services/web/package.json index 756b71deca..f29ef2df8c 100644 --- a/services/web/package.json +++ b/services/web/package.json @@ -347,7 +347,6 @@ "sinon": "^7.5.0", "sinon-chai": "^3.7.0", "sinon-mongoose": "^2.3.0", - "socket.io-mock": "^1.3.1", "storybook": "^8.0.4", "stylelint-config-standard-scss": "^13.1.0", "terser-webpack-plugin": "^5.3.9", diff --git a/services/web/test/frontend/features/chat/context/chat-context.test.jsx b/services/web/test/frontend/features/chat/context/chat-context.test.jsx index 14beb70aa3..4266a490eb 100644 --- a/services/web/test/frontend/features/chat/context/chat-context.test.jsx +++ b/services/web/test/frontend/features/chat/context/chat-context.test.jsx @@ -5,7 +5,6 @@ import { renderHook, act } from '@testing-library/react-hooks/dom' import { expect } from 'chai' import sinon from 'sinon' import fetchMock from 'fetch-mock' -import EventEmitter from 'events' import { useChatContext, chatClientIdGenerator, @@ -15,6 +14,7 @@ import { cleanUpContext, } from '../../../helpers/render-with-context' import { stubMathJax, tearDownMathJaxStubs } from '../components/stubs' +import { SocketIOMock } from '@/ide/connection/SocketIoShim' describe('ChatContext', function () { const user = { @@ -57,26 +57,26 @@ describe('ChatContext', function () { }) it('subscribes when mounted', function () { - const socket = new EventEmitter() + const socket = new SocketIOMock() renderChatContextHook({ socket }) // Assert that there is 1 listener - expect(socket.rawListeners('new-chat-message').length).to.equal(1) + expect(socket.events['new-chat-message'].length).to.equal(1) }) it('unsubscribes when unmounted', function () { - const socket = new EventEmitter() + const socket = new SocketIOMock() const { unmount } = renderChatContextHook({ socket }) unmount() // Assert that there is 0 listeners - expect(socket.rawListeners('new-chat-message').length).to.equal(0) + expect(socket.events['new-chat-message'].length).to.equal(0) }) it('adds received messages to the list', async function () { // Mock socket: we only need to emit events, not mock actual connections - const socket = new EventEmitter() + const socket = new SocketIOMock() const { result, waitForNextUpdate } = renderChatContextHook({ socket, }) @@ -89,7 +89,7 @@ describe('ChatContext', function () { expect(result.current.messages).to.deep.equal([]) // Mock message being received from another user - socket.emit('new-chat-message', { + socket.emitToClient('new-chat-message', { id: 'msg_1', content: 'new message', timestamp: Date.now(), @@ -107,7 +107,7 @@ describe('ChatContext', function () { it('deduplicate messages from preloading', async function () { // Mock socket: we only need to emit events, not mock actual connections - const socket = new EventEmitter() + const socket = new SocketIOMock() const { result, waitForNextUpdate } = renderChatContextHook({ socket, }) @@ -130,7 +130,7 @@ describe('ChatContext', function () { ) // Mock message being received from another user - socket.emit('new-chat-message', { + socket.emitToClient('new-chat-message', { id: 'msg_1', content: 'new message', timestamp: Date.now(), @@ -158,7 +158,7 @@ describe('ChatContext', function () { it('deduplicate messages from websocket', async function () { // Mock socket: we only need to emit events, not mock actual connections - const socket = new EventEmitter() + const socket = new SocketIOMock() const { result, waitForNextUpdate } = renderChatContextHook({ socket, }) @@ -188,7 +188,7 @@ describe('ChatContext', function () { expect(result.current.messages).to.have.length(1) // Mock message being received from another user - socket.emit('new-chat-message', { + socket.emitToClient('new-chat-message', { id: 'msg_1', content: 'new message', timestamp: Date.now(), @@ -208,7 +208,7 @@ describe('ChatContext', function () { }) it("doesn't add received messages from the current user if a message was just sent", async function () { - const socket = new EventEmitter() + const socket = new SocketIOMock() const { result, waitForNextUpdate } = renderChatContextHook({ socket, }) @@ -223,7 +223,7 @@ describe('ChatContext', function () { act(() => { // Receive a message from the current user - socket.emit('new-chat-message', { + socket.emitToClient('new-chat-message', { id: 'msg_1', content: 'received message', timestamp: Date.now(), @@ -240,7 +240,7 @@ describe('ChatContext', function () { }) it('adds the new message from the current user if another message was received after sending', async function () { - const socket = new EventEmitter() + const socket = new SocketIOMock() const { result, waitForNextUpdate } = renderChatContextHook({ socket, }) @@ -260,7 +260,7 @@ describe('ChatContext', function () { act(() => { // Receive a message from another user. - socket.emit('new-chat-message', { + socket.emitToClient('new-chat-message', { id: 'msg_1', content: otherMsg, timestamp: Date.now(), @@ -278,7 +278,7 @@ describe('ChatContext', function () { act(() => { // Receive a message from the current user - socket.emit('new-chat-message', { + socket.emitToClient('new-chat-message', { id: 'msg_2', content: 'received message from current user', timestamp: Date.now(), @@ -441,7 +441,7 @@ describe('ChatContext', function () { }) ) - const socket = new EventEmitter() + const socket = new SocketIOMock() const { result, waitForNextUpdate } = renderChatContextHook({ socket, }) @@ -451,7 +451,7 @@ describe('ChatContext', function () { // Mock message being received from the socket while the request is in // flight - socket.emit('new-chat-message', { + socket.emitToClient('new-chat-message', { id: 'socket_msg', content: 'socket message', timestamp: Date.now(), @@ -563,11 +563,11 @@ describe('ChatContext', function () { }) it('increments unreadMessageCount when a new message is received', function () { - const socket = new EventEmitter() + const socket = new SocketIOMock() const { result } = renderChatContextHook({ socket }) // Receive a new message from the socket - socket.emit('new-chat-message', { + socket.emitToClient('new-chat-message', { id: 'msg_1', content: 'new message', timestamp: Date.now(), @@ -578,12 +578,12 @@ describe('ChatContext', function () { }) it('resets unreadMessageCount when markMessagesAsRead is called', function () { - const socket = new EventEmitter() + const socket = new SocketIOMock() const { result } = renderChatContextHook({ socket }) // Receive a new message from the socket, incrementing unreadMessageCount // by 1 - socket.emit('new-chat-message', { + socket.emitToClient('new-chat-message', { id: 'msg_1', content: 'new message', timestamp: Date.now(), diff --git a/services/web/test/frontend/features/file-tree/components/file-tree-root.spec.tsx b/services/web/test/frontend/features/file-tree/components/file-tree-root.spec.tsx index 58a1fe98f2..fa95db490d 100644 --- a/services/web/test/frontend/features/file-tree/components/file-tree-root.spec.tsx +++ b/services/web/test/frontend/features/file-tree/components/file-tree-root.spec.tsx @@ -1,7 +1,6 @@ -// @ts-ignore -import MockedSocket from 'socket.io-mock' import FileTreeRoot from '../../../../../frontend/js/features/file-tree/components/file-tree-root' import { EditorProviders } from '../../../helpers/editor-providers' +import { SocketIOMock } from '@/ide/connection/SocketIoShim' describe('', function () { beforeEach(function () { @@ -287,7 +286,9 @@ describe('', function () { }) describe('when deselecting files', function () { + let socket: SocketIOMock beforeEach(function () { + socket = new SocketIOMock() const rootFolder = [ { _id: 'root-folder-id', @@ -313,7 +314,7 @@ describe('', function () { rootDocId="456def" features={{} as any} permissionsLevel="owner" - socket={new MockedSocket()} + socket={socket} > ', function () { cy.findByRole('button', { name: /new file/i }).click() cy.findByRole('button', { name: /create/i }).click() - cy.window().then(win => { - // @ts-ignore - win._ide.socket.socketClient.emit('reciveNewDoc', 'root-folder-id', { + cy.then(() => { + socket.emitToClient('reciveNewDoc', 'root-folder-id', { _id: '12345', name: 'abcdef.tex', docs: [], diff --git a/services/web/test/frontend/features/file-tree/flows/create-folder.spec.tsx b/services/web/test/frontend/features/file-tree/flows/create-folder.spec.tsx index bb2dc1adbe..1731dd8189 100644 --- a/services/web/test/frontend/features/file-tree/flows/create-folder.spec.tsx +++ b/services/web/test/frontend/features/file-tree/flows/create-folder.spec.tsx @@ -1,10 +1,11 @@ -// @ts-ignore -import MockedSocket from 'socket.io-mock' import FileTreeRoot from '../../../../../frontend/js/features/file-tree/components/file-tree-root' import { EditorProviders } from '../../../helpers/editor-providers' +import { SocketIOMock } from '@/ide/connection/SocketIoShim' describe('FileTree Create Folder Flow', function () { + let socket: SocketIOMock beforeEach(function () { + socket = new SocketIOMock() cy.window().then(win => { win.metaAttributesCache.set('ol-user', { id: 'user1' }) }) @@ -25,7 +26,7 @@ describe('FileTree Create Folder Flow', function () { { - // @ts-ignore - win._ide.socket.socketClient.emit('reciveNewFolder', 'root-folder-id', { + cy.then(() => { + socket.emitToClient('reciveNewFolder', 'root-folder-id', { _id: fakeId(), name, docs: [], @@ -96,7 +96,7 @@ describe('FileTree Create Folder Flow', function () { rootFolder={rootFolder as any} projectId="123abc" rootDocId="789ghi" - socket={new MockedSocket()} + socket={socket} > { - // @ts-ignore - win._ide.socket.socketClient.emit('reciveNewFolder', '789ghi', { + cy.then(() => { + socket.emitToClient('reciveNewFolder', '789ghi', { _id: fakeId(), name, docs: [], @@ -174,7 +173,7 @@ describe('FileTree Create Folder Flow', function () { rootFolder={rootFolder as any} projectId="123abc" rootDocId="456def" - socket={new MockedSocket()} + socket={socket} > { - // @ts-ignore - win._ide.socket.socketClient.emit('reciveNewFolder', '789ghi', { + cy.then(() => { + socket.emitToClient('reciveNewFolder', '789ghi', { _id: fakeId(), name, docs: [], @@ -242,7 +240,7 @@ describe('FileTree Create Folder Flow', function () { rootFolder={rootFolder as any} projectId="123abc" rootDocId="456def" - socket={new MockedSocket()} + socket={socket} > { - // @ts-ignore - win._ide.socket.socketClient.emit('removeEntity', '456def') + cy.then(() => { + socket.emitToClient('removeEntity', '456def') }) cy.findByRole('treeitem', { @@ -99,9 +99,8 @@ describe('FileTree Delete Entity Flow', function () { cy.findByRole('button', { name: 'Delete' }).click() - cy.window().then(win => { - // @ts-ignore - win._ide.socket.socketClient.emit('removeEntity', '456def') + cy.then(() => { + socket.emitToClient('removeEntity', '456def') }) cy.findByRole('treeitem', { @@ -133,7 +132,9 @@ describe('FileTree Delete Entity Flow', function () { }) describe('folders', function () { + let socket: SocketIOMock beforeEach(function () { + socket = new SocketIOMock() const rootFolder = [ { _id: 'root-folder-id', @@ -157,7 +158,7 @@ describe('FileTree Delete Entity Flow', function () { { - // @ts-ignore - win._ide.socket.socketClient.emit('removeEntity', '123abc') + cy.then(() => { + socket.emitToClient('removeEntity', '123abc') }) }) @@ -204,7 +204,9 @@ describe('FileTree Delete Entity Flow', function () { }) describe('multiple entities', function () { + let socket: SocketIOMock beforeEach(function () { + socket = new SocketIOMock() const rootFolder = [ { _id: 'root-folder-id', @@ -220,7 +222,7 @@ describe('FileTree Delete Entity Flow', function () { { - // @ts-ignore - win._ide.socket.socketClient.emit('removeEntity', '456def') - // @ts-ignore - win._ide.socket.socketClient.emit('removeEntity', '789ghi') + cy.then(() => { + socket.emitToClient('removeEntity', '456def') + socket.emitToClient('removeEntity', '789ghi') }) for (const name of ['main.tex', 'my.bib']) { diff --git a/services/web/test/frontend/features/file-tree/flows/rename-entity.spec.tsx b/services/web/test/frontend/features/file-tree/flows/rename-entity.spec.tsx index 35bec4261d..b03676621f 100644 --- a/services/web/test/frontend/features/file-tree/flows/rename-entity.spec.tsx +++ b/services/web/test/frontend/features/file-tree/flows/rename-entity.spec.tsx @@ -1,7 +1,6 @@ -// @ts-ignore -import MockedSocket from 'socket.io-mock' import FileTreeRoot from '../../../../../frontend/js/features/file-tree/components/file-tree-root' import { EditorProviders } from '../../../helpers/editor-providers' +import { SocketIOMock } from '@/ide/connection/SocketIoShim' describe('FileTree Rename Entity Flow', function () { beforeEach(function () { @@ -10,7 +9,9 @@ describe('FileTree Rename Entity Flow', function () { }) }) + let socket: SocketIOMock beforeEach(function () { + socket = new SocketIOMock() const rootFolder = [ { _id: 'root-folder-id', @@ -37,7 +38,7 @@ describe('FileTree Rename Entity Flow', function () { { - // @ts-ignore - win._ide.socket.socketClient.emit( - 'reciveEntityRename', - '456def', - 'socket.tex' - ) + cy.then(() => { + socket.emitToClient('reciveEntityRename', '456def', 'socket.tex') }) cy.findByRole('treeitem', { name: 'socket.tex' }) diff --git a/services/web/test/frontend/helpers/editor-providers.jsx b/services/web/test/frontend/helpers/editor-providers.jsx index cc8ec2f506..644fd11334 100644 --- a/services/web/test/frontend/helpers/editor-providers.jsx +++ b/services/web/test/frontend/helpers/editor-providers.jsx @@ -16,6 +16,7 @@ import { ProjectSettingsProvider } from '@/features/editor-left-menu/context/pro import { FileTreePathProvider } from '@/features/file-tree/contexts/file-tree-path' import { UserSettingsProvider } from '@/shared/context/user-settings-context' import { OutlineProvider } from '@/features/ide-react/context/outline-context' +import { SocketIOMock } from '@/ide/connection/SocketIoShim' // these constants can be imported in tests instead of // using magic strings @@ -46,10 +47,7 @@ export function EditorProviders({ email: 'owner@example.com', }, rootDocId = '_root_doc_id', - socket = { - on: sinon.stub(), - removeListener: sinon.stub(), - }, + socket = new SocketIOMock(), isRestrictedTokenMember = false, clsiServerId = '1234', scope = {},