diff --git a/e2e-tests/playwright/support/ui/components/global_header.ts b/e2e-tests/playwright/support/ui/components/global_header.ts
index 33d90ef14f..4dff67f135 100644
--- a/e2e-tests/playwright/support/ui/components/global_header.ts
+++ b/e2e-tests/playwright/support/ui/components/global_header.ts
@@ -46,7 +46,7 @@ export default class GlobalHeader {
async closeSearch() {
await expect(this.searchBox).toBeVisible();
- await this.searchBox.getByTestId('input-clear').click();
+ await this.searchBox.getByTestId('searchBoxClose').click();
}
}
diff --git a/e2e-tests/playwright/tests/functional/channels/search/team_selector.spec.ts b/e2e-tests/playwright/tests/functional/channels/search/team_selector.spec.ts
new file mode 100644
index 0000000000..e6696990de
--- /dev/null
+++ b/e2e-tests/playwright/tests/functional/channels/search/team_selector.spec.ts
@@ -0,0 +1,100 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import {createRandomTeam} from '@e2e-support/server';
+import {expect, test} from '@e2e-support/test_fixture';
+
+test('team selector must show all my teams', async ({pw}) => {
+ const {adminClient, adminConfig, user, team} = await pw.initSetup();
+
+ // # Enable Cross Team Search Feature Flag
+ const newConfig = {
+ ...adminConfig,
+ FeatureFlags: {
+ ...adminConfig.FeatureFlags,
+ ExperimentalCrossTeamSearch: true,
+ },
+ };
+ await adminClient.updateConfig(newConfig);
+
+ // # create 2 more teams and add the user to them
+ const teams = [team];
+ for (let i = 0; i < 2; i++) {
+ const newTeam = await adminClient.createTeam(createRandomTeam('team', 'Team', 'O', true));
+ await adminClient.addUsersToTeam(newTeam.id, [user.id]);
+ teams.push(newTeam);
+ }
+
+ // # Log in a user in new browser context
+ const {channelsPage} = await pw.testBrowser.login(user);
+
+ // # Visit a default channel page
+ await channelsPage.goto(team.name);
+ await channelsPage.toBeVisible();
+
+ // # Open the search UI
+ await channelsPage.globalHeader.openSearch();
+
+ // * Check that the team selector is visible
+ const page = channelsPage.page;
+ await expect(page.getByTestId('searchTeamsSelectorMenuButton')).toBeVisible();
+
+ // # Click on the team selector
+ await page.getByTestId('searchTeamsSelectorMenuButton').click();
+
+ // * Check that the team selector is visible
+ const teamSelector = page.getByRole('menu', {name: 'Select team'});
+ await expect(teamSelector).toBeVisible();
+ // * Check that the team selector has the 3 teams
+ teams.forEach(async (t) => {
+ await expect(teamSelector.getByText(t.display_name)).toBeVisible();
+ });
+ // * Check that All teams is also visible
+ await expect(teamSelector.getByText('All teams')).toBeVisible();
+ // * No should be visible in the menu
+ await expect(teamSelector.getByLabel('Search teams')).not.toBeVisible();
+
+ // now create and join 3 more teams
+ for (let i = 0; i < 3; i++) {
+ const newTeam = await adminClient.createTeam(createRandomTeam('team', 'Team', 'O', true));
+ await adminClient.addUsersToTeam(newTeam.id, [user.id]);
+ teams.push(newTeam);
+ }
+
+ // refresh the page
+ await channelsPage.goto(team.name);
+
+ // # Open the search UI
+ await channelsPage.globalHeader.openSearch();
+
+ // # Click on the team selector
+ await page.getByTestId('searchTeamsSelectorMenuButton').click();
+
+ // * Check that the team selector is visible
+ await expect(teamSelector).toBeVisible();
+ // * Check that the team selector has the 6 teams
+ teams.forEach(async (t) => {
+ await expect(teamSelector.getByText(t.display_name)).toBeVisible();
+ });
+ // * Check that All teams is also visible
+ await expect(teamSelector.getByText('All teams')).toBeVisible();
+
+ // because there's more than 4 teams, the filter input should be visible
+ await expect(teamSelector.getByLabel('Search teams')).toBeVisible();
+
+ // # Type the name of the first team
+ await page.getByLabel('Search teams').fill(teams[3].display_name);
+
+ // * Check that the team selector is visible
+ await expect(teamSelector).toBeVisible();
+
+ // * Noew team [0] and [3] should be visible - 0 is visible because it was currently selected.
+ await expect(teamSelector.getByText(teams[0].display_name)).toBeVisible();
+ await expect(teamSelector.getByText(teams[3].display_name)).toBeVisible();
+ // * Check that All teams is also visible
+ await expect(teamSelector.getByText('All teams')).toBeVisible();
+ // * Check that the other teams are not visible
+ teams.slice(1, 3).forEach(async (t) => {
+ await expect(teamSelector.getByText(t.display_name)).not.toBeVisible();
+ });
+});
diff --git a/webapp/channels/src/actions/channel_actions.ts b/webapp/channels/src/actions/channel_actions.ts
index 3dbbf6b707..cfb4e41b1b 100644
--- a/webapp/channels/src/actions/channel_actions.ts
+++ b/webapp/channels/src/actions/channel_actions.ts
@@ -154,6 +154,22 @@ export function autocompleteChannelsForSearch(term: string, success?: (channels:
};
}
+export function autocompleteChannelsForSearchInTeam(term: string, teamId: string, success?: (channels: Channel[]) => void, error?: (err: ServerError) => void): ActionFuncAsync {
+ return async (dispatch) => {
+ if (!teamId) {
+ return {data: false};
+ }
+
+ const {data, error: err} = await dispatch(ChannelActions.autocompleteChannelsForSearch(teamId, term));
+ if (data && success) {
+ success(data);
+ } else if (err && error) {
+ error({id: err.server_error_id, ...err});
+ }
+ return {data: true};
+ };
+}
+
export function addUsersToChannel(channelId: Channel['id'], userIds: Array): ActionFuncAsync {
return async (dispatch) => {
const error = await dispatch(ChannelActions.addChannelMembers(channelId, userIds));
diff --git a/webapp/channels/src/actions/user_actions.ts b/webapp/channels/src/actions/user_actions.ts
index 021048e427..073f4fa541 100644
--- a/webapp/channels/src/actions/user_actions.ts
+++ b/webapp/channels/src/actions/user_actions.ts
@@ -406,7 +406,7 @@ export async function loadProfilesForDM() {
await dispatch(loadCustomEmojisForCustomStatusesByUserIds(profileIds));
}
-export function autocompleteUsersInTeam(username: string): ThunkActionFunc> {
+export function autocompleteUsersInCurrentTeam(username: string): ThunkActionFunc> {
return async (doDispatch, doGetState) => {
const currentTeamId = getCurrentTeamId(doGetState());
const {data} = await doDispatch(UserActions.autocompleteUsers(username, currentTeamId));
@@ -414,6 +414,13 @@ export function autocompleteUsersInTeam(username: string): ThunkActionFunc> {
+ return async (doDispatch) => {
+ const {data} = await doDispatch(UserActions.autocompleteUsers(username, teamId));
+ return data!;
+ };
+}
+
export function autocompleteUsers(username: string): ThunkActionFunc> {
return async (doDispatch) => {
const {data} = await doDispatch(UserActions.autocompleteUsers(username));
diff --git a/webapp/channels/src/components/dot_menu/__snapshots__/dot_menu.test.tsx.snap b/webapp/channels/src/components/dot_menu/__snapshots__/dot_menu.test.tsx.snap
index c87388ca68..9d6839e0d7 100644
--- a/webapp/channels/src/components/dot_menu/__snapshots__/dot_menu.test.tsx.snap
+++ b/webapp/channels/src/components/dot_menu/__snapshots__/dot_menu.test.tsx.snap
@@ -345,7 +345,7 @@ exports[`components/dot_menu/DotMenu should match snapshot, on Center 1`] = `
size={16}
/>,
"class": "post-menu__item",
- "dateTestId": "PostDotMenu-Button-post_id_1",
+ "dataTestId": "PostDotMenu-Button-post_id_1",
"id": "CENTER_button_post_id_1",
}
}
diff --git a/webapp/channels/src/components/dot_menu/dot_menu.tsx b/webapp/channels/src/components/dot_menu/dot_menu.tsx
index 791f2aecb7..e9748653c5 100644
--- a/webapp/channels/src/components/dot_menu/dot_menu.tsx
+++ b/webapp/channels/src/components/dot_menu/dot_menu.tsx
@@ -492,7 +492,7 @@ export class DotMenuClass extends React.PureComponent {