From e8e7329bf6e762a8f2147d09c09db5cea10bdcbf Mon Sep 17 00:00:00 2001 From: lucasgarfield Date: Tue, 22 Feb 2022 14:35:05 +0100 Subject: [PATCH] CreateImageWizard: Get all matching packages from package search When searching for a package, all matching packages are now returned. First an attempt is made using the api's default limit and if there are more matching packages than the default limit a second request is made with an increased limit. To facilitate this, api.getPackages() now accepts an optional limit parameter. Retrieving all matching packages is necessary because of the sorting logic. --- .../formComponents/Packages.js | 23 ++++++++--- src/api.js | 3 +- .../CreateImageWizard.test.js | 39 ++++++++++++++++++- 3 files changed, 57 insertions(+), 8 deletions(-) diff --git a/src/Components/CreateImageWizard/formComponents/Packages.js b/src/Components/CreateImageWizard/formComponents/Packages.js index 1f038a58..7502c70e 100644 --- a/src/Components/CreateImageWizard/formComponents/Packages.js +++ b/src/Components/CreateImageWizard/formComponents/Packages.js @@ -88,15 +88,26 @@ const Packages = ({ defaultArch, ...props }) => { }); }); - // call api to list available packages - const handlePackagesAvailableSearch = async () => { - const { data } = await api.getPackages( + const getAllPackages = async () => { + const args = [ getState()?.values?.release, getState()?.values?.architecture || defaultArch, packagesSearchName.current - ); - if (data) { - const packagesAvailableFiltered = filterPackagesAvailable(data); + ]; + let { data, meta } = await api.getPackages(...args); + if (data?.length === meta.count) { + return data; + } else if (data) { + ({ data } = await api.getPackages(...args, meta.count)); + return data; + } + }; + + // call api to list available packages + const handlePackagesAvailableSearch = async () => { + const packageList = await getAllPackages(); + if (packageList) { + const packagesAvailableFiltered = filterPackagesAvailable(packageList); sortPackages(packagesAvailableFiltered); setPackagesAvailableFound(true); } else { diff --git a/src/api.js b/src/api.js index edd2fb16..efd3d7a2 100644 --- a/src/api.js +++ b/src/api.js @@ -28,12 +28,13 @@ async function getComposeStatus(id) { return request.data; } -async function getPackages(distribution, architecture, search) { +async function getPackages(distribution, architecture, search, limit) { const params = new URLSearchParams({ distribution, architecture, search, }); + limit && params.append('limit', limit); let path = '/packages?' + params.toString(); const request = await axios.get(IMAGE_BUILDER_API.concat(path)); return request.data; diff --git a/src/test/Components/CreateImageWizard/CreateImageWizard.test.js b/src/test/Components/CreateImageWizard/CreateImageWizard.test.js index 6c2bf1d1..6c2b0966 100644 --- a/src/test/Components/CreateImageWizard/CreateImageWizard.test.js +++ b/src/test/Components/CreateImageWizard/CreateImageWizard.test.js @@ -28,7 +28,7 @@ function verifyCancelButton(cancel, history) { // packages const mockPkgResult = { - meta: { count: 100 }, + meta: { count: 3 }, links: { first: '', last: '' }, data: [ { @@ -49,6 +49,22 @@ const mockPkgResult = { ] }; +const mockPkgResultPartial = { + meta: { count: 132 }, + links: { first: '', last: '' }, + data: new Array(100).fill().map((_, i) => { + return { name: 'testPkg-' + i, summary: 'test package summary', version: '1.0' }; + }) +}; + +const mockPkgResultAll = { + meta: { count: 132 }, + links: { first: '', last: '' }, + data: new Array(132).fill().map((_, i) => { + return { name: 'testPkg-' + i, summary: 'test package summary', version: '1.0' }; + }) +}; + const mockPkgResultEmpty = { meta: { count: 0 }, links: { first: '', last: '' }, @@ -731,6 +747,27 @@ describe('Step Packages', () => { expect(chosenPackagesItems).toHaveLength(1); within(chosenPackagesList).getByRole('option', { name: /testPkg test package summary/ }); }); + + test('should get all packages, regardless of api default limit', async () => { + await setUp(); + + const searchbox = screen.getAllByRole('textbox')[0]; // searching by id doesn't update the input ref + + searchbox.click(); + + const getPackages = jest + .spyOn(api, 'getPackages') + .mockImplementation((distribution, architecture, search, limit) => { + return limit ? Promise.resolve(mockPkgResultAll) : Promise.resolve(mockPkgResultPartial); + }); + + await searchForAvailablePackages(searchbox, 'testPkg'); + expect(getPackages).toHaveBeenCalledTimes(2); + + const availablePackagesList = screen.getByTestId('available-pkgs-list'); + const availablePackagesItems = within(availablePackagesList).getAllByRole('option'); + expect(availablePackagesItems).toHaveLength(132); + }); }); describe('Step Review', () => {