fix: allow substring matching when searching channel members (#35017)

* fix: allow substring matching when searching channel members

* fix lint error

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
This commit is contained in:
Seongbin Hong 2026-03-25 04:45:59 +09:00 committed by GitHub
parent 4b1b3cee69
commit 8bfa1ff09f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 19 additions and 11 deletions

View file

@ -41,6 +41,8 @@ describe('Selectors.Users', () => {
const user7 = TestHelper.fakeUserWithId();
user7.delete_at = 1;
user7.roles = 'system_admin system_user';
const user8 = TestHelper.fakeUserWithId();
user8.nickname = 'vertex_to_edge';
const profiles: Record<string, UserProfile> = {};
profiles[user1.id] = user1;
profiles[user2.id] = user2;
@ -49,6 +51,7 @@ describe('Selectors.Users', () => {
profiles[user5.id] = user5;
profiles[user6.id] = user6;
profiles[user7.id] = user7;
profiles[user8.id] = user8;
const profilesInTeam: Record<Team['id'], Set<UserProfile['id']>> = {};
profilesInTeam[team1.id] = new Set([user1.id, user2.id, user7.id]);
@ -75,7 +78,7 @@ describe('Selectors.Users', () => {
profilesNotInTeam[team1.id] = new Set([user3.id, user4.id]);
const profilesInChannel: Record<Channel['id'], Set<UserProfile['id']>> = {};
profilesInChannel[channel1.id] = new Set([user1.id]);
profilesInChannel[channel1.id] = new Set([user1.id, user8.id]);
profilesInChannel[channel2.id] = new Set([user1.id, user2.id]);
const membersInChannel: Record<Channel['id'], Record<UserProfile['id'], ChannelMembership>> = {};
@ -85,6 +88,10 @@ describe('Selectors.Users', () => {
scheme_user: true,
scheme_admin: true,
};
membersInChannel[channel1.id][user8.id] = {
...TestHelper.fakeChannelMember(user8.id, channel1.id),
scheme_user: true,
};
membersInChannel[channel2.id] = {};
membersInChannel[channel2.id][user1.id] = {
...TestHelper.fakeChannelMember(user1.id, channel2.id),
@ -264,7 +271,7 @@ describe('Selectors.Users', () => {
describe('getProfiles', () => {
it('getProfiles without filter', () => {
const users = [user1, user2, user3, user4, user5, user6, user7].sort(sortByUsername);
const users = [user1, user2, user3, user4, user5, user6, user7, user8].sort(sortByUsername);
expect(Selectors.getProfiles(testState)).toEqual(users);
});
@ -277,7 +284,7 @@ describe('Selectors.Users', () => {
expect(Selectors.getProfiles(testState, {inactive: true})).toEqual(users);
});
it('getProfiles with active', () => {
const users = [user1, user3, user4, user5, user6].sort(sortByUsername);
const users = [user1, user3, user4, user5, user6, user8].sort(sortByUsername);
expect(Selectors.getProfiles(testState, {active: true})).toEqual(users);
});
it('getProfiles with multiple filters', () => {
@ -465,6 +472,7 @@ describe('Selectors.Users', () => {
expect(Selectors.searchProfilesInCurrentChannel(testState, user1.username)).toEqual([user1]);
expect(Selectors.searchProfilesInCurrentChannel(testState, 'engineer at mattermost')).toEqual([user1]);
expect(Selectors.searchProfilesInCurrentChannel(testState, user1.username, true)).toEqual([]);
expect(Selectors.searchProfilesInCurrentChannel(testState, 'to_edge', true)).toEqual([user8]);
});
it('searchProfilesNotInCurrentChannel', () => {
@ -525,7 +533,7 @@ describe('Selectors.Users', () => {
it('makeGetProfilesInChannel', () => {
const getProfilesInChannel = Selectors.makeGetProfilesInChannel();
expect(getProfilesInChannel(testState, channel1.id)).toEqual([user1]);
expect(getProfilesInChannel(testState, channel1.id)).toEqual([user1, user8]);
const users = [user1, user2].sort(sortByUsername);
expect(getProfilesInChannel(testState, channel2.id)).toEqual(users);
@ -555,8 +563,8 @@ describe('Selectors.Users', () => {
};
const getProfilesInChannel = Selectors.makeGetProfilesInChannel();
expect(getProfilesInChannel(state, channel1.id)).toEqual([user1]);
expect(getProfilesInChannel(state, channel1.id, {})).toEqual([user1]);
expect(getProfilesInChannel(state, channel1.id)).toEqual([user1, user8]);
expect(getProfilesInChannel(state, channel1.id, {})).toEqual([user1, user8]);
});
it('makeGetProfilesNotInChannel', () => {
@ -874,7 +882,7 @@ describe('Selectors.Users', () => {
describe('filterProfiles', () => {
it('no filter, return all users', () => {
expect(Object.keys(Selectors.filterProfiles(profiles)).length).toEqual(7);
expect(Object.keys(Selectors.filterProfiles(profiles)).length).toEqual(8);
});
it('filter role', () => {
@ -901,7 +909,7 @@ describe('Selectors.Users', () => {
const filter = {
exclude_roles: ['system_admin'],
};
expect(Object.keys(Selectors.filterProfiles(profiles, filter)).length).toEqual(4);
expect(Object.keys(Selectors.filterProfiles(profiles, filter)).length).toEqual(5);
});
it('exclude bots', () => {
@ -920,7 +928,7 @@ describe('Selectors.Users', () => {
...profiles,
[botUser.id]: botUser,
};
expect(Object.keys(Selectors.filterProfiles(newProfiles, filter)).length).toEqual(7);
expect(Object.keys(Selectors.filterProfiles(newProfiles, filter)).length).toEqual(8);
});
it('filter inactive', () => {
@ -934,7 +942,7 @@ describe('Selectors.Users', () => {
const filter = {
active: true,
};
expect(Object.keys(Selectors.filterProfiles(profiles, filter)).length).toEqual(5);
expect(Object.keys(Selectors.filterProfiles(profiles, filter)).length).toEqual(6);
});
});
});

View file

@ -510,7 +510,7 @@ export function makeSearchProfilesInChannel() {
}
export function searchProfilesInCurrentChannel(state: GlobalState, term: string, skipCurrent = false): UserProfile[] {
const profiles = filterProfilesStartingWithTerm(getProfilesInCurrentChannel(state), term);
const profiles = filterProfilesMatchingWithTerm(getProfilesInCurrentChannel(state), term);
if (skipCurrent) {
removeCurrentUserFromList(profiles, getCurrentUserId(state));