diff --git a/lib/Controller/OpenProjectAPIController.php b/lib/Controller/OpenProjectAPIController.php index b7b314cd7..24d92f504 100644 --- a/lib/Controller/OpenProjectAPIController.php +++ b/lib/Controller/OpenProjectAPIController.php @@ -154,17 +154,21 @@ public function getNotifications(): DataResponse { * * @return DataResponse */ - public function getSearchedWorkPackages(?string $searchQuery = null, ?int $fileId = null): DataResponse { + public function getSearchedWorkPackages(?string $searchQuery = null, ?int $fileId = null, bool $isSmartPicker = false): DataResponse { if ($this->accessToken === '') { return new DataResponse('', Http::STATUS_UNAUTHORIZED); } elseif (!OpenProjectAPIService::validateURL($this->openprojectUrl)) { return new DataResponse('', Http::STATUS_BAD_REQUEST); } - + $onlyLinkableWorkPackages = true; + if ($isSmartPicker) { + $onlyLinkableWorkPackages = false; + } $result = $this->openprojectAPIService->searchWorkPackage( $this->userId, $searchQuery, - $fileId + $fileId, + $onlyLinkableWorkPackages ); if (!isset($result['error'])) { diff --git a/src/components/tab/SearchInput.vue b/src/components/tab/SearchInput.vue index 5cd68a350..969216910 100644 --- a/src/components/tab/SearchInput.vue +++ b/src/components/tab/SearchInput.vue @@ -132,13 +132,9 @@ export default { }, async asyncFind(query) { this.resetState() - if (this.isSmartPicker) { - await this.debounceMakeSearchRequest(query) - } else { - await this.debounceMakeSearchRequest(query, this.fileInfo.id) - } + await this.debounceMakeSearchRequest(query, this.fileInfo.id, this.isSmartPicker) }, - async getFileLink(selectedOption) { + async getWorkPackageLink(selectedOption) { return this.openprojectUrl + '/projects/' + selectedOption.projectId + '/work_packages/' + selectedOption.id }, debounceMakeSearchRequest: debounce(function(...args) { @@ -147,7 +143,7 @@ export default { }, DEBOUNCE_THRESHOLD), async linkWorkPackageToFile(selectedOption) { if (this.isSmartPicker) { - const link = await this.getFileLink(selectedOption) + const link = await this.getWorkPackageLink(selectedOption) this.$emit('submit', link) return } @@ -176,12 +172,13 @@ export default { ) } }, - async makeSearchRequest(search, fileId = null) { + async makeSearchRequest(search, fileId = null, isSmartPicker = false) { this.state = STATE.LOADING const url = generateUrl('/apps/integration_openproject/work-packages') const req = {} req.params = { searchQuery: search, + isSmartPicker, } let response try { diff --git a/tests/jest/components/tab/SearchInput.spec.js b/tests/jest/components/tab/SearchInput.spec.js index ac51ffed8..fdf585103 100644 --- a/tests/jest/components/tab/SearchInput.spec.js +++ b/tests/jest/components/tab/SearchInput.spec.js @@ -9,7 +9,7 @@ import workPackagesSearchResponseNoAssignee from '../../fixtures/workPackagesSea import workPackageSearchReqResponse from '../../fixtures/workPackageSearchReqResponse.json' import workPackageObjectsInSearchResults from '../../fixtures/workPackageObjectsInSearchResults.json' import { STATE } from '../../../../src/utils.js' -import * as initialState from "@nextcloud/initial-state"; +import * as initialState from '@nextcloud/initial-state' jest.mock('@nextcloud/axios') jest.mock('@nextcloud/dialogs') @@ -24,13 +24,13 @@ jest.mock('lodash/debounce', () => }) ) +// eslint-disable-next-line no-import-assign,import/namespace initialState.loadState = jest.fn(() => { return { openproject_instance_url: null, } }) - global.t = (app, text) => text const localVue = createLocalVue() @@ -151,6 +151,7 @@ describe('SearchInput.vue', () => { { params: { searchQuery: 'orga', + isSmartPicker: false, }, }, ) @@ -495,7 +496,55 @@ describe('SearchInput.vue', () => { }) }) }) + + describe('search with smartpicker', () => { + let axiosGetSpy + beforeEach(async () => { + axiosGetSpy = jest.spyOn(axios, 'get') + .mockImplementationOnce(() => Promise.resolve({ + status: 200, + data: [], + })) + wrapper = mountSearchInput() + const inputField = wrapper.find(inputSelector) + await inputField.setValue('orga') + await wrapper.setData({ + searchResults: [{ + id: 999, + projectId: 1, + }], + openprojectUrl: 'https://openproject.com', + }) + await localVue.nextTick() + await wrapper.setProps({ + isSmartPicker: true, + }) + await localVue.nextTick() + }) + afterEach(() => { + axiosGetSpy.mockRestore() + }) + it('should emit an action', async () => { + const ncSelectItem = wrapper.find(firstWorkPackageSelector) + await ncSelectItem.trigger('click') + const savedEvent = wrapper.emitted('submit') + expect(savedEvent).toHaveLength(1) + expect(savedEvent[0][0]).toEqual('https://openproject.com/projects/1/work_packages/999') + }) + + it('should not send a request to link file to workpackage', async () => { + const postSpy = jest.spyOn(axios, 'post') + .mockImplementationOnce(() => Promise.resolve({ + status: 200, + })) + const ncSelectItem = wrapper.find(firstWorkPackageSelector) + await ncSelectItem.trigger('click') + expect(postSpy).not.toBeCalled() + postSpy.mockRestore() + }) + }) }) + function mountSearchInput(fileInfo = {}, linkedWorkPackages = [], data = {}) { return mount(SearchInput, { localVue,