diff --git a/packages/web-app-files/src/extensions.ts b/packages/web-app-files/src/extensions.ts index a66d5e57499..6c6a7765595 100644 --- a/packages/web-app-files/src/extensions.ts +++ b/packages/web-app-files/src/extensions.ts @@ -38,7 +38,9 @@ export const extensions = (appInfo: ApplicationInformation) => { const { currentFolder } = storeToRefs(useResourcesStore()) const { currentSpace } = storeToRefs(useSpacesStore()) const router = useRouter() - const { search: searchFunction } = useSearch() + // preview and list search need their own (restartable) tasks, so that one doesn't cancel the other + const { search: previewSearchFunction } = useSearch() + const { search: listSearchFunction } = useSearch() const { $gettext } = useGettext() const { can } = useAbility() @@ -51,7 +53,12 @@ export const extensions = (appInfo: ApplicationInformation) => { const folderViewExtensions = useFolderViews() const sideBarPanelExtensions = useSideBarPanels() const vaultIndicator = useVaultIndicator() - const searchProvider = new SDKSearch(capabilityStore, searchFunction, configStore) + const searchProvider = new SDKSearch( + capabilityStore, + previewSearchFunction, + configStore, + listSearchFunction + ) return computed(() => [ ...fileActionExtensions, diff --git a/packages/web-app-files/src/search/sdk/index.ts b/packages/web-app-files/src/search/sdk/index.ts index cddaf34e643..7c4d2a3ba8e 100644 --- a/packages/web-app-files/src/search/sdk/index.ts +++ b/packages/web-app-files/src/search/sdk/index.ts @@ -20,12 +20,13 @@ export default class Provider implements SearchProvider { constructor( capabilityStore: CapabilityStore, searchFunction: SearchFunction, - configStore: ConfigStore + configStore: ConfigStore, + listSearchFunction: SearchFunction = searchFunction ) { this.id = 'files.sdk' this.displayName = $gettext('Files') this.previewSearch = new Preview(searchFunction, configStore) - this.listSearch = new List(searchFunction) + this.listSearch = new List(listSearchFunction) this.capabilityStore = capabilityStore } diff --git a/packages/web-app-files/tests/unit/extensions.spec.ts b/packages/web-app-files/tests/unit/extensions.spec.ts new file mode 100644 index 00000000000..e3afb7e8c48 --- /dev/null +++ b/packages/web-app-files/tests/unit/extensions.spec.ts @@ -0,0 +1,36 @@ +import { mock } from 'vitest-mock-extended' +import { unref } from 'vue' +import { ApplicationInformation, SearchExtension } from '@opencloud-eu/web-pkg' +import { SearchResource } from '@opencloud-eu/web-client' +import { defaultComponentMocks, getComposableWrapper } from '@opencloud-eu/web-test-helpers' +import { extensions } from '../../src/extensions' + +describe('files app extensions', () => { + describe('search provider', () => { + it('does not cancel a running list search when a preview search starts', async () => { + const mocks = defaultComponentMocks() + const listResources = [mock({ id: '1', name: 'foo' })] + let resolveListRequest: (value: { resources: SearchResource[]; totalResults: number }) => void + mocks.$clientService.webdav.search + .mockImplementationOnce(() => new Promise((resolve) => (resolveListRequest = resolve))) + .mockResolvedValue({ resources: [], totalResults: 0 }) + + const wrapper = getComposableWrapper( + () => { + const searchExtension = unref(extensions(mock())).find( + ({ type }) => type === 'search' + ) as SearchExtension + return { searchProvider: searchExtension.searchProvider } + }, + { mocks, provide: mocks } + ) + const { listSearch, previewSearch } = wrapper.vm.searchProvider + + const listResult = listSearch.search('foo') + await previewSearch.search('foo') + resolveListRequest({ resources: listResources, totalResults: 1 }) + + await expect(listResult).resolves.toMatchObject({ totalResults: 1 }) + }) + }) +})