diff --git a/.changeset/smooth-knives-turn.md b/.changeset/smooth-knives-turn.md new file mode 100644 index 00000000000..3964ecc8481 --- /dev/null +++ b/.changeset/smooth-knives-turn.md @@ -0,0 +1,7 @@ +--- +"@rocket.chat/meteor": patch +--- + +Executing a logout and login action in the same "tab/instance", some streams were not being recreated, causing countless types of bugs. + +PS: as a workaround reloading after logout or login in also solves the problem. diff --git a/apps/meteor/app/ui-cached-collection/client/models/CachedCollection.ts b/apps/meteor/app/ui-cached-collection/client/models/CachedCollection.ts index 77190992612..545e1e73342 100644 --- a/apps/meteor/app/ui-cached-collection/client/models/CachedCollection.ts +++ b/apps/meteor/app/ui-cached-collection/client/models/CachedCollection.ts @@ -356,12 +356,6 @@ export class CachedCollection extends Emitter< this.trySync(); }); - if (!this.userRelated) { - return this.setupListener(); - } - - CachedCollectionManager.onLogin(async () => { - await this.setupListener(); - }); + return this.setupListener(); } } diff --git a/apps/meteor/app/utils/client/lib/SDKClient.ts b/apps/meteor/app/utils/client/lib/SDKClient.ts index 18ff309970d..c174f9125f4 100644 --- a/apps/meteor/app/utils/client/lib/SDKClient.ts +++ b/apps/meteor/app/utils/client/lib/SDKClient.ts @@ -51,6 +51,7 @@ type EventMap = Str type StreamMapValue = { stop: () => void; + error: (cb: (...args: any[]) => void) => void; onChange: ReturnType['onChange']; ready: () => Promise; isReady: boolean; @@ -62,6 +63,7 @@ const createNewMeteorStream = (streamName: StreamNames, key: StreamKeys { - console.error(err); ee.emit('ready', [err]); + ee.emit('error', err); }, }, ); @@ -115,6 +117,11 @@ const createNewMeteorStream = (streamName: StreamNames, key: StreamKeys void) => + ee.once('error', (error) => { + cb(error); + }), + get isReady() { return meta.ready; }, @@ -179,6 +186,7 @@ const createStreamManager = () => { if (!streams.has(eventLiteral)) { streams.set(eventLiteral, stream); } + stream.error(() => stop()); return { id: '', diff --git a/apps/meteor/client/providers/UserProvider/UserProvider.tsx b/apps/meteor/client/providers/UserProvider/UserProvider.tsx index 62ed7070737..27c540928e8 100644 --- a/apps/meteor/client/providers/UserProvider/UserProvider.tsx +++ b/apps/meteor/client/providers/UserProvider/UserProvider.tsx @@ -12,6 +12,7 @@ import { sdk } from '../../../app/utils/client/lib/SDKClient'; import { afterLogoutCleanUpCallback } from '../../../lib/callbacks/afterLogoutCleanUpCallback'; import { useReactiveValue } from '../../hooks/useReactiveValue'; import { createReactiveSubscriptionFactory } from '../../lib/createReactiveSubscriptionFactory'; +import { queryClient } from '../../lib/queryClient'; import { useCreateFontStyleElement } from '../../views/account/accessibility/hooks/useCreateFontStyleElement'; import { useClearRemovedRoomsHistory } from './hooks/useClearRemovedRoomsHistory'; import { useDeleteUser } from './hooks/useDeleteUser'; @@ -92,6 +93,12 @@ const UserProvider = ({ children }: UserProviderProps): ReactElement => { } }, [preferedLanguage, setPreferedLanguage, setUserLanguage, user?.language, userLanguage, userId, setUserPreferences]); + useEffect(() => { + if (!userId) { + queryClient.clear(); + } + }, [userId]); + return ; }; diff --git a/apps/meteor/tests/e2e/omnichannel/omnichannel-manual-selection-logout.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-manual-selection-logout.spec.ts new file mode 100644 index 00000000000..f995f6b87b1 --- /dev/null +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-manual-selection-logout.spec.ts @@ -0,0 +1,74 @@ +import { Page } from '@playwright/test'; + +import { DEFAULT_USER_CREDENTIALS } from '../config/constants'; +import injectInitialData from '../fixtures/inject-initial-data'; +import { Users } from '../fixtures/userStates'; +import { HomeOmnichannel } from '../page-objects'; +import { createAgent, makeAgentAvailable } from '../utils/omnichannel/agents'; +import { createConversation } from '../utils/omnichannel/rooms'; +import { test, expect } from '../utils/test'; + +test.use({ storageState: Users.user1.state }); + +test.describe('OC - Manual Selection', () => { + let poOmnichannel: HomeOmnichannel; + let agent: Awaited>; + + // Change routing method to manual selection + test.beforeAll(async ({ api }) => { + const res = await api.post('/settings/Livechat_Routing_Method', { value: 'Manual_Selection' }); + expect(res.status()).toBe(200); + }); + + // Create agent and make it available + test.beforeAll(async ({ api }) => { + agent = await createAgent(api, 'user1'); + await makeAgentAvailable(api, agent.data._id); + }); + + // Create page object and redirect to home + test.beforeEach(async ({ page }: { page: Page }) => { + poOmnichannel = new HomeOmnichannel(page); + await page.goto('/home'); + + await poOmnichannel.sidenav.logout(); + await poOmnichannel.page.locator('role=textbox[name=/username/i]').waitFor({ state: 'visible' }); + await poOmnichannel.page.locator('role=textbox[name=/username/i]').fill('user1'); + await poOmnichannel.page.locator('[name=password]').fill(DEFAULT_USER_CREDENTIALS.password); + await poOmnichannel.page.locator('role=button[name="Login"]').click(); + + await poOmnichannel.page.locator('.main-content').waitFor(); + }); + + // Delete all data + test.afterAll(async ({ api }) => { + await agent.delete() + await api.post('/settings/Livechat_Routing_Method', { value: 'Auto_Selection' }); + await injectInitialData(); + }); + + test('OC - Manual Selection - Logout & Login', async ({ api }) => { + expect(await poOmnichannel.page.locator('#omnichannel-status-toggle').getAttribute('title')).toEqual('Turn off answer chats'); + + const { data: { room } } = await createConversation(api); + + await test.step('expect login and see the chat in queue after login', async () => { + await poOmnichannel.sidenav.getSidebarItemByName(room.fname).click(); + await expect(poOmnichannel.content.inputMessage).not.toBeVisible(); + }); + + await test.step('expect take chat to be visible and return to queue not visible', async () => { + await expect(poOmnichannel.content.btnTakeChat).toBeVisible(); + await expect(poOmnichannel.content.btnReturnToQueue).not.toBeVisible(); + }); + + await test.step('expect to be able take chat', async () => { + await poOmnichannel.content.btnTakeChat.click(); + await expect(poOmnichannel.content.lastSystemMessageBody).toHaveText('joined the channel'); + await expect(poOmnichannel.content.inputMessage).toBeVisible(); + await expect(poOmnichannel.content.btnTakeChat).not.toBeVisible(); + await expect(poOmnichannel.content.btnReturnToQueue).toBeVisible(); + await expect(poOmnichannel.sidenav.getSidebarItemByName(room.fname)).toBeVisible(); + }); + }); +});