diff --git a/.changeset/many-falcons-joke.md b/.changeset/many-falcons-joke.md
new file mode 100644
index 0000000000..6254dcae40
--- /dev/null
+++ b/.changeset/many-falcons-joke.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-search-react': patch
+---
+
+Skip the very first empty search when going to the landing page
diff --git a/plugins/search-react/src/components/SearchPagination/SearchPagination.test.tsx b/plugins/search-react/src/components/SearchPagination/SearchPagination.test.tsx
index e482dc3a75..d9cd564ae2 100644
--- a/plugins/search-react/src/components/SearchPagination/SearchPagination.test.tsx
+++ b/plugins/search-react/src/components/SearchPagination/SearchPagination.test.tsx
@@ -69,7 +69,7 @@ describe('SearchPagination', () => {
expect(screen.getByText('Results per page:')).toBeInTheDocument();
expect(screen.getByText('25')).toBeInTheDocument();
expect(screen.getByText('1-25')).toBeInTheDocument();
- expect(screen.getByLabelText('Next page')).toBeEnabled();
+ expect(screen.getByLabelText('Next page')).toBeDisabled();
expect(screen.getByLabelText('Previous page')).toBeDisabled();
});
@@ -176,6 +176,12 @@ describe('SearchPagination', () => {
});
it('Set page limit in the context', async () => {
+ const initialState = {
+ term: 'a',
+ types: [],
+ filters: {},
+ };
+
await renderInTestApp(
{
[configApiRef, configApiMock],
]}
>
-
+
,
@@ -205,7 +211,7 @@ describe('SearchPagination', () => {
it('Set page cursor in the context', async () => {
const initialState = {
- term: '',
+ term: 'a',
types: [],
filters: {},
pageCursor: 'MQ==', // page: 1
@@ -253,7 +259,7 @@ describe('SearchPagination', () => {
it('Resets page cursor when page limit changes', async () => {
const initialState = {
- term: '',
+ term: 'a',
types: [],
filters: {},
pageCursor: 'Mg==', // page: 2
@@ -280,9 +286,7 @@ describe('SearchPagination', () => {
pageCursor: undefined,
pageLimit: 10,
}),
- {
- signal: expect.any(AbortSignal),
- },
+ { signal: expect.any(AbortSignal) },
);
});
});
diff --git a/plugins/search-react/src/components/SearchResultGroup/SearchResultGroup.test.tsx b/plugins/search-react/src/components/SearchResultGroup/SearchResultGroup.test.tsx
index cb274be0a0..e1f61f088b 100644
--- a/plugins/search-react/src/components/SearchResultGroup/SearchResultGroup.test.tsx
+++ b/plugins/search-react/src/components/SearchResultGroup/SearchResultGroup.test.tsx
@@ -66,7 +66,7 @@ describe('SearchResultGroup', () => {
});
it('Renders without exploding', async () => {
- query.mockResolvedValueOnce({
+ query.mockResolvedValue({
results,
});
@@ -96,7 +96,7 @@ describe('SearchResultGroup', () => {
});
it('Renders search results from context', async () => {
- query.mockResolvedValueOnce({
+ query.mockResolvedValue({
results,
});
@@ -107,7 +107,9 @@ describe('SearchResultGroup', () => {
[analyticsApiRef, analyticsApiMock],
]}
>
-
+
}
title="Documentation"
@@ -128,7 +130,7 @@ describe('SearchResultGroup', () => {
});
it('Renders search results using extensions', async () => {
- query.mockResolvedValueOnce({
+ query.mockResolvedValue({
results,
});
@@ -166,7 +168,7 @@ describe('SearchResultGroup', () => {
});
it('Defines a default link', async () => {
- query.mockResolvedValueOnce({
+ query.mockResolvedValue({
results,
});
@@ -190,7 +192,7 @@ describe('SearchResultGroup', () => {
});
it('Defines a default render result item', async () => {
- query.mockResolvedValueOnce({
+ query.mockResolvedValue({
results,
});
@@ -221,6 +223,10 @@ describe('SearchResultGroup', () => {
});
it('Could be customized with no results text', async () => {
+ query.mockResolvedValue({
+ results: [],
+ });
+
await renderInTestApp(
{
});
it('Could be customized with filters', async () => {
- query.mockResolvedValueOnce({
+ query.mockResolvedValue({
results,
});
@@ -272,7 +278,7 @@ describe('SearchResultGroup', () => {
});
it('Could have a text search filter field', async () => {
- query.mockResolvedValueOnce({
+ query.mockResolvedValue({
results,
});
@@ -323,7 +329,7 @@ describe('SearchResultGroup', () => {
});
it('Could have a select search filter field', async () => {
- query.mockResolvedValueOnce({
+ query.mockResolvedValue({
results,
});
@@ -376,7 +382,7 @@ describe('SearchResultGroup', () => {
});
it('Shows a progress bar when loading results', async () => {
- query.mockReturnValueOnce(new Promise(() => {}));
+ query.mockReturnValue(new Promise(() => {}));
await renderInTestApp(
{
});
it('Does not render result group if no results returned and disableRenderingWithNoResults prop is provided', async () => {
- query.mockResolvedValueOnce({ results: [] });
+ query.mockResolvedValue({ results: [] });
await renderInTestApp(
{
});
it('Should render custom component when no results returned', async () => {
- query.mockResolvedValueOnce({ results: [] });
+ query.mockResolvedValue({ results: [] });
await renderInTestApp(
{
});
it('Shows an error panel when results rendering fails', async () => {
- query.mockRejectedValueOnce(new Error());
+ query.mockRejectedValue(new Error());
await renderInTestApp(
(
initialValue.pageCursor,
);
+ const isFirstEmptyMount = useRef(true);
const prevTerm = usePrevious(term);
const prevFilters = usePrevious(filters);
const abortControllerRef = useRef(null);
- const result = useAsync(async () => {
+ const result = useAsync(async (): Promise => {
+ if (isFirstEmptyMount.current) {
+ if (!term && !types.length && !Object.keys(filters).length) {
+ return {
+ results: [],
+ numberOfResults: 0,
+ };
+ }
+
+ isFirstEmptyMount.current = false;
+ }
+
// Here we cancel the previous request before making a new one
if (abortControllerRef.current) {
abortControllerRef.current.abort();
diff --git a/plugins/search/report-alpha.api.md b/plugins/search/report-alpha.api.md
index 5353fec09e..b129d4ab6c 100644
--- a/plugins/search/report-alpha.api.md
+++ b/plugins/search/report-alpha.api.md
@@ -264,8 +264,8 @@ export const searchTranslationRef: TranslationRef<
readonly 'searchType.tabs.allTitle': 'All';
readonly 'searchType.allResults': 'All Results';
readonly 'searchType.accordion.collapse': 'Collapse';
- readonly 'searchType.accordion.allTitle': 'All';
readonly 'searchType.accordion.numberOfResults': '{{number}} results';
+ readonly 'searchType.accordion.allTitle': 'All';
readonly 'sidebarSearchModal.title': 'Search';
}
>;
diff --git a/plugins/search/src/components/HomePageComponent/HomePageSearchBar.test.tsx b/plugins/search/src/components/HomePageComponent/HomePageSearchBar.test.tsx
index e7c47b7d30..270bdbb2eb 100644
--- a/plugins/search/src/components/HomePageComponent/HomePageSearchBar.test.tsx
+++ b/plugins/search/src/components/HomePageComponent/HomePageSearchBar.test.tsx
@@ -46,12 +46,7 @@ describe('', () => {
},
);
- expect(searchApiMock.query).toHaveBeenCalledWith(
- expect.objectContaining({ term: '' }),
- {
- signal: expect.any(AbortSignal),
- },
- );
+ expect(searchApiMock.query).not.toHaveBeenCalled();
await userEvent.type(screen.getByLabelText('Search'), 'term{enter}');
diff --git a/plugins/search/src/components/SearchModal/SearchModal.test.tsx b/plugins/search/src/components/SearchModal/SearchModal.test.tsx
index 8d8e1bb9b9..9424599130 100644
--- a/plugins/search/src/components/SearchModal/SearchModal.test.tsx
+++ b/plugins/search/src/components/SearchModal/SearchModal.test.tsx
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-import { screen } from '@testing-library/react';
+import { screen, waitFor } from '@testing-library/react';
import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils';
import userEvent from '@testing-library/user-event';
import { configApiRef } from '@backstage/core-plugin-api';
@@ -63,7 +63,6 @@ describe('SearchModal', () => {
);
expect(screen.getByRole('dialog')).toBeInTheDocument();
- expect(searchApiMock.query).toHaveBeenCalledTimes(1);
});
it('Should use parent search context if defined', async () => {
@@ -106,15 +105,21 @@ describe('SearchModal', () => {
);
expect(screen.getByRole('dialog')).toBeInTheDocument();
- expect(searchApiMock.query).toHaveBeenCalledWith(
- {
- term: '',
- filters: {},
- types: [],
- pageCursor: undefined,
- },
- { signal: expect.any(AbortSignal) },
- );
+
+ const input = screen.getByLabelText('Search');
+ await userEvent.type(input, 'text');
+
+ await waitFor(() => {
+ expect(searchApiMock.query).toHaveBeenCalledWith(
+ {
+ term: 'text',
+ filters: {},
+ types: [],
+ pageCursor: undefined,
+ },
+ { signal: expect.any(AbortSignal) },
+ );
+ });
});
it('Should render a custom Modal correctly', async () => {
@@ -146,7 +151,6 @@ describe('SearchModal', () => {
},
);
- expect(searchApiMock.query).toHaveBeenCalledTimes(1);
await userEvent.keyboard('{Escape}');
expect(toggleModal).toHaveBeenCalledTimes(1);
});