Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/olive-pens-think.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---

Fixed incorrect URL generation in Global Search "Jump to message" feature, resolving navigation issues when jumping to messages across different channels.
10 changes: 5 additions & 5 deletions apps/meteor/client/lib/rooms/roomCoordinator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,18 +67,18 @@ class RoomCoordinatorClient extends RoomCoordinator {
roomType: RoomType,
subData: RoomIdentification,
queryParams?: Record<string, string>,
options: { replace?: boolean } = {},
options: { replace?: boolean; routeParamsOverrides?: Record<string, string> } = {},
): void {
const config = this.getRoomTypeConfig(roomType);
if (!config?.route) {
return;
}

let routeData = {};
let _routeData = {};
if (config.route.link) {
routeData = config.route.link(subData);
_routeData = config.route.link(subData);
} else if (subData?.name) {
routeData = {
_routeData = {
name: subData.name,
};
} else {
Expand All @@ -88,7 +88,7 @@ class RoomCoordinatorClient extends RoomCoordinator {
router.navigate(
{
pattern: config.route.path ?? '/home',
params: routeData,
params: { ..._routeData, ...options.routeParamsOverrides },
search: queryParams,
},
options,
Expand Down
11 changes: 8 additions & 3 deletions apps/meteor/client/lib/utils/goToRoomById.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,23 @@ import { roomCoordinator } from '../rooms/roomCoordinator';

const getRoomById = memoize((rid: IRoom['_id']) => callWithErrorHandling('getRoomById', rid));

export const goToRoomById = async (rid: IRoom['_id']): Promise<void> => {
export type GoToRoomByIdOptions = {
replace?: boolean;
routeParamsOverrides?: Record<string, string>;
};

export const goToRoomById = async (rid: IRoom['_id'], options: GoToRoomByIdOptions = {}): Promise<void> => {
if (!rid) {
return;
}

const subscription = Subscriptions.state.find((record) => record.rid === rid);

if (subscription) {
roomCoordinator.openRouteLink(subscription.t, subscription, router.getSearchParameters());
roomCoordinator.openRouteLink(subscription.t, subscription, router.getSearchParameters(), options);
return;
}

const room = await getRoomById(rid);
roomCoordinator.openRouteLink(room.t, { rid: room._id, ...room }, router.getSearchParameters());
roomCoordinator.openRouteLink(room.t, { rid: room._id, ...room }, router.getSearchParameters(), options);
};
23 changes: 5 additions & 18 deletions apps/meteor/client/lib/utils/legacyJumpToMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { isThreadMessage } from '@rocket.chat/core-typings';
import { goToRoomById } from './goToRoomById';
import { RoomHistoryManager } from '../../../app/ui-utils/client';
import { router } from '../../providers/RouterProvider';
import { Rooms } from '../../stores';
import { RoomManager } from '../RoomManager';

/** @deprecated */
Expand All @@ -15,24 +14,12 @@ export const legacyJumpToMessage = async (message: IMessage) => {
if (tab === 'thread' && (context === message.tmid || context === message._id)) {
return;
}
router.navigate(
{
name: router.getRouteName()!,
params: {
tab: 'thread',
context: message.tmid || message._id,
rid: message.rid,
name: Rooms.state.get(message.rid)?.name ?? '',
},
search: {
...router.getSearchParameters(),
msg: message._id,
},
},
{ replace: false },
);
await RoomHistoryManager.getSurroundingMessages(message);

await goToRoomById(message.rid, {
routeParamsOverrides: { tab: 'thread', context: message.tmid || message._id },
replace: RoomManager.opened === message.rid,
});
await RoomHistoryManager.getSurroundingMessages(message);
return;
}

Expand Down
82 changes: 82 additions & 0 deletions apps/meteor/tests/e2e/global-search.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import type { IMessage } from '@rocket.chat/core-typings';
import { Random } from '@rocket.chat/random';

import { Users } from './fixtures/userStates';
import { HomeChannel } from './page-objects';
import { setSettingValueById } from './utils';
import type { BaseTest } from './utils/test';
import { expect, test } from './utils/test';

test.use({ storageState: Users.admin.state });
test.describe.serial('Global Search', () => {
let targetChannel: { name: string; _id: string };
let targetGroup: { name: string; _id: string };
let threadMessage: IMessage;
let poHomeChannel: HomeChannel;

const fillMessages = async (api: BaseTest['api']) => {
const { message: parentMessage } = await (
await api.post('/chat.postMessage', { roomId: targetChannel._id, text: 'This is main message in channel' })
).json();

const { message: childMessage } = await (
await api.post('/chat.postMessage', { roomId: targetChannel._id, text: `This is thread message in channel`, tmid: parentMessage._id })
).json();
threadMessage = childMessage;
};

test.beforeAll(async ({ api }) => {
await Promise.all([
api
.post('/channels.create', { name: Random.id() })
.then((res) => res.json())
.then((data) => {
targetChannel = data.channel;
}),
api
.post('/groups.create', {
name: Random.id(),
extraData: { encrypted: false },
})
.then((res) => res.json())
.then((data) => {
targetGroup = data.group;
}),
setSettingValueById(api, 'Search.Provider', 'defaultProvider'),
setSettingValueById(api, 'Search.defaultProvider.GlobalSearchEnabled', true),
]);
await fillMessages(api);
});

test.afterAll(({ api }) =>
Promise.all([
api.post('/channels.delete', { roomId: targetChannel._id }),
api.post('/groups.delete', { roomId: targetGroup._id }),
setSettingValueById(api, 'Search.defaultProvider.GlobalSearchEnabled', false),
setSettingValueById(api, 'Search.Provider', 'defaultProvider'),
]),
);

test.beforeEach(async ({ page }) => {
poHomeChannel = new HomeChannel(page);
await page.goto('/home');
});

test('opens correct message when jumping from global search in group to channel thread', async ({ page }) => {
// await poHomeChannel.goto(`/group/${targetGroup.name}`);
await poHomeChannel.sidenav.openChat(targetGroup.name);
await poHomeChannel.roomToolbar.btnSearchMessages.click();

await poHomeChannel.tabs.searchMessages.search(threadMessage.msg.slice(10), { global: true, timeout: 10000 }); // fill partial text to match search

const message = await poHomeChannel.tabs.searchMessages.getResultItem(threadMessage.msg);
await expect(message).toBeVisible();
await message.hover();
const jumpToMessageButton = message.getByTitle('Jump to message');
await expect(jumpToMessageButton).toBeVisible();
await jumpToMessageButton.click();

await expect(page.locator('header').getByRole('button').filter({ hasText: targetChannel.name })).toBeVisible(); // match channel name in room header
await expect(page.getByText(threadMessage.msg)).toBeVisible();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { Locator, Page } from '@playwright/test';

export class HomeFlextabSearchMessages {
readonly searchTab: Locator;

constructor(protected page: Page) {
this.searchTab = this.page.getByRole('dialog', { name: 'Search Messages' });
}

async search(text: string, { global = false, timeout }: { global?: boolean; timeout?: number } = {}) {
if (global) {
await this.searchTab.getByText('Global search').click({ timeout });
}
await this.searchTab.getByPlaceholder('Search Messages').fill(text, { timeout });
}

async getResultItem(messageText: string) {
return this.searchTab.getByRole('listitem', { name: messageText });
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { HomeFlextabNotificationPreferences } from './home-flextab-notificationP
import { HomeFlextabOtr } from './home-flextab-otr';
import { HomeFlextabPruneMessages } from './home-flextab-pruneMessages';
import { HomeFlextabRoom } from './home-flextab-room';
import { HomeFlextabSearchMessages } from './home-flextab-searchMessages';

export class HomeFlextab {
private readonly page: Page;
Expand All @@ -25,6 +26,8 @@ export class HomeFlextab {

readonly pruneMessages: HomeFlextabPruneMessages;

readonly searchMessages: HomeFlextabSearchMessages;

constructor(page: Page) {
this.page = page;
this.members = new HomeFlextabMembers(page);
Expand All @@ -34,6 +37,7 @@ export class HomeFlextab {
this.otr = new HomeFlextabOtr(page);
this.exportMessages = new ExportMessagesTab(page);
this.pruneMessages = new HomeFlextabPruneMessages(page);
this.searchMessages = new HomeFlextabSearchMessages(page);
}

get toolbarPrimaryActions(): Locator {
Expand Down
4 changes: 4 additions & 0 deletions apps/meteor/tests/e2e/page-objects/fragments/toolbar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ export class RoomToolbar extends Toolbar {
return this.root.getByRole('button', { name: 'Options' });
}

get btnSearchMessages(): Locator {
return this.root.getByRole('button', { name: 'Search Messages' });
}

get btnDisableE2EEncryption(): Locator {
return this.root.getByRole('button', { name: 'Disable E2E encryption' });
}
Expand Down
Loading