mirror of
https://github.com/mattermost/mattermost.git
synced 2026-05-12 20:00:48 +00:00
MM-67904 Fix inflated count in search results Messages tab (#36465)
* MM-67904 Fix inflated count in search results Messages tab The "Messages" counter in the search results RHS was rendering `results.length`, but `results` is the array produced by `makeAddDateSeparatorsForSearchResults`, which interleaves date-line strings between posts (one per date group). A search returning a single post therefore showed "2", and N posts spread across D dates showed N+D. Filter date-line strings out of `results` before computing the counter so it reflects only the actual matching posts. File results are unaffected. Co-authored-by: Miguel de la Cruz <mgdelacroix@users.noreply.github.com> * Address review feedback: simplify count predicate, drop unnecessary type casts in tests - Count non-string entries in results directly. The Props type already declares results as Array<Post | string>, so any string entry is a separator; this is clearer than checking isDateLine and is more defensive against future marker strings. - Drop the as any casts on the new test results props. The literals are assignable to Array<Post | string>, so the casts only suppressed type checking. Co-authored-by: Miguel de la Cruz <mgdelacroix@users.noreply.github.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Miguel de la Cruz <mgdelacroix@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
69fbaeced9
commit
81f3af4738
@@ -4,6 +4,8 @@
|
||||
import {within} from '@testing-library/react';
|
||||
import React from 'react';
|
||||
|
||||
import {DATE_LINE} from 'mattermost-redux/utils/post_list';
|
||||
|
||||
import SearchResults, {arePropsEqual} from 'components/search_results/search_results';
|
||||
|
||||
import {renderWithContext} from 'tests/react_testing_utils';
|
||||
@@ -168,6 +170,59 @@ describe('components/SearchResults', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('messagesCounter', () => {
|
||||
// Render with the Files tab selected so the body of the panel does not
|
||||
// try to render the message Post items (whose connected components
|
||||
// require Redux state that is out of scope for these tests). The
|
||||
// messagesCounter is rendered on the Messages tab regardless of the
|
||||
// active tab, so this still exercises the count calculation.
|
||||
test('should not count date separators in the messages counter', () => {
|
||||
const post = TestHelper.getPostMock({id: 'post1', message: 'unique message'});
|
||||
const dateLine = DATE_LINE + new Date('2026-03-12').getTime();
|
||||
|
||||
const {container} = renderSearchResults({
|
||||
results: [dateLine, post],
|
||||
searchType: 'files',
|
||||
isSearchAtEnd: true,
|
||||
});
|
||||
|
||||
const counter = container.querySelector('.messages-tab .counter');
|
||||
expect(counter).not.toBeNull();
|
||||
expect(counter?.textContent).toBe('1');
|
||||
});
|
||||
|
||||
test('should count only posts when multiple date separators are present', () => {
|
||||
const post1 = TestHelper.getPostMock({id: 'post1', message: 'unique message 1'});
|
||||
const post2 = TestHelper.getPostMock({id: 'post2', message: 'unique message 2'});
|
||||
const dateLine1 = DATE_LINE + new Date('2026-03-12').getTime();
|
||||
const dateLine2 = DATE_LINE + new Date('2026-03-13').getTime();
|
||||
|
||||
const {container} = renderSearchResults({
|
||||
results: [dateLine1, post1, dateLine2, post2],
|
||||
searchType: 'files',
|
||||
isSearchAtEnd: true,
|
||||
});
|
||||
|
||||
const counter = container.querySelector('.messages-tab .counter');
|
||||
expect(counter?.textContent).toBe('2');
|
||||
});
|
||||
|
||||
test('should append "+" to the messages counter when more results may be available', () => {
|
||||
const post = TestHelper.getPostMock({id: 'post1', message: 'unique message'});
|
||||
const dateLine = DATE_LINE + new Date('2026-03-12').getTime();
|
||||
|
||||
const {container} = renderSearchResults({
|
||||
results: [dateLine, post],
|
||||
searchType: 'files',
|
||||
isSearchAtEnd: false,
|
||||
searchPage: 1,
|
||||
});
|
||||
|
||||
const counter = container.querySelector('.messages-tab .counter');
|
||||
expect(counter?.textContent).toBe('1+');
|
||||
});
|
||||
});
|
||||
|
||||
describe('arePropsEqual', () => {
|
||||
const result1 = {test: 'test'};
|
||||
const result2 = {test: 'test'};
|
||||
|
||||
@@ -150,6 +150,13 @@ const SearchResults: React.FC<Props> = (props: Props): JSX.Element => {
|
||||
|
||||
const noResults = (!results || !Array.isArray(results) || results.length === 0);
|
||||
const noFileResults = (!fileResults || !Array.isArray(fileResults) || fileResults.length === 0);
|
||||
|
||||
// The `results` prop is typed as `Array<Post | string>`. Strings are
|
||||
// non-Post entries (date separators injected by
|
||||
// makeAddDateSeparatorsForSearchResults), so the messages counter only
|
||||
// counts the non-string entries. Otherwise the count is inflated by one
|
||||
// per date group (see MM-67904).
|
||||
const messagesCount = Array.isArray(results) ? results.filter((item) => typeof item !== 'string').length : 0;
|
||||
const isLoading = isSearchingTerm || isSearchingFlaggedPost || isSearchingPinnedPost || !isOpened;
|
||||
const isAtEnd = (searchType === DataSearchTypes.MESSAGES_SEARCH_TYPE && isSearchAtEnd) || (searchType === DataSearchTypes.FILES_SEARCH_TYPE && isSearchFilesAtEnd);
|
||||
const showLoadMore = !isAtEnd && !isChannelFiles && !isFlaggedPosts && !isPinnedPosts;
|
||||
@@ -390,7 +397,7 @@ const SearchResults: React.FC<Props> = (props: Props): JSX.Element => {
|
||||
selected={searchType}
|
||||
selectedFilter={searchFilterType}
|
||||
isFileAttachmentsEnabled={isFileAttachmentsEnabled(config)}
|
||||
messagesCounter={isSearchAtEnd || props.searchPage === 0 ? `${results.length}` : `${results.length}+`}
|
||||
messagesCounter={isSearchAtEnd || props.searchPage === 0 ? `${messagesCount}` : `${messagesCount}+`}
|
||||
filesCounter={isSearchFilesAtEnd || props.searchPage === 0 ? `${fileResults.length}` : `${fileResults.length}+`}
|
||||
onChange={setSearchType}
|
||||
onFilter={setSearchFilterType}
|
||||
|
||||
Reference in New Issue
Block a user