mirror of
https://github.com/RocketChat/Rocket.Chat.git
synced 2025-12-28 06:47:25 +00:00
fix: Global Search "Jump to message" failing due to incorrect URL generation (#37717)
Some checks are pending
Deploy GitHub Pages / deploy-preview (push) Waiting to run
CI / ⚙️ Variables Setup (push) Waiting to run
CI / 🚀 Notify external services - draft (push) Blocked by required conditions
CI / 📦 Build Packages (push) Blocked by required conditions
CI / 📦 Meteor Build (${{ matrix.type }}) (coverage) (push) Blocked by required conditions
CI / 📦 Meteor Build (${{ matrix.type }}) (production) (push) Blocked by required conditions
CI / 🚢 Build Docker (amd64, [account-service presence-service stream-hub-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Blocked by required conditions
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Blocked by required conditions
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Blocked by required conditions
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Blocked by required conditions
CI / 🚢 Build Docker (arm64, [account-service presence-service stream-hub-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Blocked by required conditions
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Blocked by required conditions
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Blocked by required conditions
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Blocked by required conditions
CI / 🚢 Publish Docker Images (ghcr.io) (push) Blocked by required conditions
CI / 📦 Track Image Sizes (push) Blocked by required conditions
CI / 🔎 Code Check (push) Blocked by required conditions
CI / 🔨 Test Storybook (push) Blocked by required conditions
CI / 🔨 Test Unit (push) Blocked by required conditions
CI / 🔨 Test API (CE) (push) Blocked by required conditions
CI / 🔨 Test UI (CE) (push) Blocked by required conditions
CI / 🔨 Test API (EE) (push) Blocked by required conditions
CI / 🔨 Test UI (EE) (push) Blocked by required conditions
CI / 🔨 Test Federation Matrix (push) Blocked by required conditions
CI / 📊 Report Coverage (push) Blocked by required conditions
CI / ✅ Tests Done (push) Blocked by required conditions
CI / 🚀 Publish build assets (push) Blocked by required conditions
CI / 🚀 Publish Docker Images (DockerHub) (push) Blocked by required conditions
CI / 🚀 Notify external services (push) Blocked by required conditions
CI / Update Version Durability (push) Blocked by required conditions
Code scanning - action / CodeQL-Build (push) Waiting to run
Some checks are pending
Deploy GitHub Pages / deploy-preview (push) Waiting to run
CI / ⚙️ Variables Setup (push) Waiting to run
CI / 🚀 Notify external services - draft (push) Blocked by required conditions
CI / 📦 Build Packages (push) Blocked by required conditions
CI / 📦 Meteor Build (${{ matrix.type }}) (coverage) (push) Blocked by required conditions
CI / 📦 Meteor Build (${{ matrix.type }}) (production) (push) Blocked by required conditions
CI / 🚢 Build Docker (amd64, [account-service presence-service stream-hub-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Blocked by required conditions
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Blocked by required conditions
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Blocked by required conditions
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Blocked by required conditions
CI / 🚢 Build Docker (arm64, [account-service presence-service stream-hub-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Blocked by required conditions
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Blocked by required conditions
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Blocked by required conditions
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Blocked by required conditions
CI / 🚢 Publish Docker Images (ghcr.io) (push) Blocked by required conditions
CI / 📦 Track Image Sizes (push) Blocked by required conditions
CI / 🔎 Code Check (push) Blocked by required conditions
CI / 🔨 Test Storybook (push) Blocked by required conditions
CI / 🔨 Test Unit (push) Blocked by required conditions
CI / 🔨 Test API (CE) (push) Blocked by required conditions
CI / 🔨 Test UI (CE) (push) Blocked by required conditions
CI / 🔨 Test API (EE) (push) Blocked by required conditions
CI / 🔨 Test UI (EE) (push) Blocked by required conditions
CI / 🔨 Test Federation Matrix (push) Blocked by required conditions
CI / 📊 Report Coverage (push) Blocked by required conditions
CI / ✅ Tests Done (push) Blocked by required conditions
CI / 🚀 Publish build assets (push) Blocked by required conditions
CI / 🚀 Publish Docker Images (DockerHub) (push) Blocked by required conditions
CI / 🚀 Notify external services (push) Blocked by required conditions
CI / Update Version Durability (push) Blocked by required conditions
Code scanning - action / CodeQL-Build (push) Waiting to run
Co-authored-by: Douglas Fabris <27704687+dougfabris@users.noreply.github.com>
This commit is contained in:
parent
d821cd3ffc
commit
25a10b65bc
5
.changeset/olive-pens-think.md
Normal file
5
.changeset/olive-pens-think.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'@rocket.chat/meteor': patch
|
||||
---
|
||||
|
||||
Fixes incorrect URL generation in Global Search "Jump to message" feature, resolving navigation issues when jumping to messages across different channels.
|
||||
@ -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 {
|
||||
@ -88,7 +88,7 @@ class RoomCoordinatorClient extends RoomCoordinator {
|
||||
router.navigate(
|
||||
{
|
||||
pattern: config.route.path ?? '/home',
|
||||
params: routeData,
|
||||
params: { ..._routeData, ...options.routeParamsOverrides },
|
||||
search: queryParams,
|
||||
},
|
||||
options,
|
||||
|
||||
@ -8,7 +8,12 @@ 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;
|
||||
}
|
||||
@ -16,10 +21,10 @@ export const goToRoomById = async (rid: IRoom['_id']): Promise<void> => {
|
||||
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);
|
||||
};
|
||||
|
||||
@ -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 */
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
78
apps/meteor/tests/e2e/global-search.spec.ts
Normal file
78
apps/meteor/tests/e2e/global-search.spec.ts
Normal file
@ -0,0 +1,78 @@
|
||||
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.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),
|
||||
]),
|
||||
);
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
poHomeChannel = new HomeChannel(page);
|
||||
await page.goto('/home');
|
||||
});
|
||||
|
||||
test('should open the correct message when jumping from global search in group to channel thread', async ({ page }) => {
|
||||
await poHomeChannel.sidenav.openChat(targetGroup.name);
|
||||
await poHomeChannel.roomToolbar.btnSearchMessages.click();
|
||||
|
||||
await poHomeChannel.tabs.searchMessages.search(threadMessage.msg.slice(10), { global: true }); // fill partial text to match search
|
||||
|
||||
const message = await poHomeChannel.tabs.searchMessages.getResultItem(threadMessage.msg);
|
||||
await message.hover();
|
||||
const jumpToMessageButton = message.getByRole('button', { name: 'Jump to message' });
|
||||
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();
|
||||
});
|
||||
});
|
||||
@ -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 { SearchMessagesFlexTab } from './searchMessages-flextab';
|
||||
|
||||
export class HomeFlextab {
|
||||
private readonly page: Page;
|
||||
@ -25,6 +26,8 @@ export class HomeFlextab {
|
||||
|
||||
readonly pruneMessages: HomeFlextabPruneMessages;
|
||||
|
||||
readonly searchMessages: SearchMessagesFlexTab;
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page;
|
||||
this.members = new HomeFlextabMembers(page);
|
||||
@ -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 SearchMessagesFlexTab(page);
|
||||
}
|
||||
|
||||
get toolbarPrimaryActions(): Locator {
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { FlexTab } from './flextab';
|
||||
|
||||
export class SearchMessagesFlexTab extends FlexTab {
|
||||
constructor(page: Page) {
|
||||
super(page.getByRole('dialog', { name: 'Search Messages' }));
|
||||
}
|
||||
|
||||
async search(text: string, { global = false }: { global?: boolean } = {}) {
|
||||
if (global) {
|
||||
await this.root.getByText('Global search').click();
|
||||
}
|
||||
await this.root.getByPlaceholder('Search Messages').fill(text);
|
||||
}
|
||||
|
||||
async getResultItem(messageText: string) {
|
||||
return this.root.getByRole('listitem', { name: messageText });
|
||||
}
|
||||
}
|
||||
@ -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' });
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user