diff options
author | Mathieu Suen <59278745+mathieu-suen-sonarsource@users.noreply.github.com> | 2024-04-22 14:31:11 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2024-04-22 20:02:38 +0000 |
commit | 3a0102ec7c2bcfaf9fa9859e66cd2ef8a94dfd08 (patch) | |
tree | d9dc9d66df45065ec447f3245897490274b0030f /server/sonar-web/src/main | |
parent | a827904491975f559a9122503a13be039f242017 (diff) | |
download | sonarqube-3a0102ec7c2bcfaf9fa9859e66cd2ef8a94dfd08.tar.gz sonarqube-3a0102ec7c2bcfaf9fa9859e66cd2ef8a94dfd08.zip |
SONAR-22102 Fixing missing udpate of project tags update (#11002)
Diffstat (limited to 'server/sonar-web/src/main')
2 files changed, 42 insertions, 28 deletions
diff --git a/server/sonar-web/src/main/js/apps/projectInformation/about/components/MetaTags.tsx b/server/sonar-web/src/main/js/apps/projectInformation/about/components/MetaTags.tsx index 7d43bf16fd1..81653411f40 100644 --- a/server/sonar-web/src/main/js/apps/projectInformation/about/components/MetaTags.tsx +++ b/server/sonar-web/src/main/js/apps/projectInformation/about/components/MetaTags.tsx @@ -17,9 +17,10 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { Spinner } from '@sonarsource/echoes-react'; import { MultiSelector, SubHeading, Tags } from 'design-system'; import { difference, without } from 'lodash'; -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { searchProjectTags, setApplicationTags, setProjectTags } from '../../../../api/components'; import Tooltip from '../../../../components/controls/Tooltip'; import { PopupPlacement } from '../../../../components/ui/popups'; @@ -33,7 +34,11 @@ interface Props { } export default function MetaTags(props: Props) { - const [open, setOpen] = React.useState(false); + const [loading, setLoading] = useState(false); + + useEffect(() => { + setLoading(false); + }, [props.component.tags]); const canUpdateTags = () => { const { configuration } = props.component; @@ -57,6 +62,7 @@ export default function MetaTags(props: Props) { }; const handleSetProjectTags = (values: string[]) => { + setLoading(true); setTags(values).then( () => props.onComponentChange({ tags: values }), () => {}, @@ -73,13 +79,15 @@ export default function MetaTags(props: Props) { ariaTagsListLabel={translate('tags')} className="project-info-tags" emptyText={translate('no_tags')} - overlay={<MetaTagsSelector selectedTags={tags} setProjectTags={handleSetProjectTags} />} + overlay={ + <Spinner isLoading={loading}> + <MetaTagsSelector selectedTags={tags} setProjectTags={handleSetProjectTags} /> + </Spinner> + } popupPlacement={PopupPlacement.Bottom} tags={tags} tagsToDisplay={2} tooltip={Tooltip} - open={open} - onClose={() => setOpen(false)} /> </> ); diff --git a/server/sonar-web/src/main/js/apps/projectInformation/about/components/__tests__/MetaTags-test.tsx b/server/sonar-web/src/main/js/apps/projectInformation/about/components/__tests__/MetaTags-test.tsx index fea012025a3..8267fa68ff1 100644 --- a/server/sonar-web/src/main/js/apps/projectInformation/about/components/__tests__/MetaTags-test.tsx +++ b/server/sonar-web/src/main/js/apps/projectInformation/about/components/__tests__/MetaTags-test.tsx @@ -24,6 +24,7 @@ import { setApplicationTags, setProjectTags } from '../../../../../api/component import { mockComponent } from '../../../../../helpers/mocks/component'; import { renderComponent } from '../../../../../helpers/testReactTestingUtils'; import { ComponentQualifier } from '../../../../../types/component'; +import { Component } from '../../../../../types/types'; import MetaTags from '../MetaTags'; jest.mock('../../../../../api/components', () => ({ @@ -45,8 +46,6 @@ it('should render without tags and admin rights', async () => { it('should allow to edit tags for a project', async () => { const user = userEvent.setup(); - - const onComponentChange = jest.fn(); const component = mockComponent({ key: 'my-second-project', tags: ['foo', 'bar'], @@ -56,7 +55,7 @@ it('should allow to edit tags for a project', async () => { name: 'MySecondProject', }); - renderMetaTags({ component, onComponentChange }); + renderMetaTags(component); expect(await screen.findByText('foo, bar')).toBeInTheDocument(); expect(screen.getByRole('button')).toBeInTheDocument(); @@ -66,15 +65,11 @@ it('should allow to edit tags for a project', async () => { expect(await screen.findByRole('checkbox', { name: 'best' })).toBeInTheDocument(); await user.click(screen.getByRole('checkbox', { name: 'best' })); - expect(onComponentChange).toHaveBeenCalledWith({ tags: ['foo', 'bar', 'best'] }); - - onComponentChange.mockClear(); + expect(await screen.findByRole('button', { name: 'foo bar ... +' })).toBeInTheDocument(); - /* - * Since we're not actually updating the tags, we're back to having the foo, bar only - */ await user.click(screen.getByRole('checkbox', { name: 'bar' })); - expect(onComponentChange).toHaveBeenCalledWith({ tags: ['foo'] }); + + expect(await screen.findByRole('button', { name: 'foo best +' })).toBeInTheDocument(); expect(setProjectTags).toHaveBeenCalled(); expect(setApplicationTags).not.toHaveBeenCalled(); @@ -85,14 +80,14 @@ it('should allow to edit tags for a project', async () => { it('should set tags for an app', async () => { const user = userEvent.setup(); - renderMetaTags({ - component: mockComponent({ + renderMetaTags( + mockComponent({ configuration: { showSettings: true, }, qualifier: ComponentQualifier.Application, }), - }); + ); await user.click(screen.getByRole('button', { name: 'no_tags +' })); @@ -102,14 +97,25 @@ it('should set tags for an app', async () => { expect(setApplicationTags).toHaveBeenCalled(); }); -function renderMetaTags(overrides: Partial<Parameters<typeof MetaTags>[0]> = {}) { - const component = mockComponent({ - configuration: { - showSettings: false, - }, - }); - - return renderComponent( - <MetaTags component={component} onComponentChange={jest.fn()} {...overrides} />, - ); +function renderMetaTags(componentOverride: Partial<Component> = {}) { + function Component(componentOverride: Partial<Parameters<typeof MetaTags>[0]>) { + const [component, setComponent] = React.useState( + mockComponent({ + configuration: { + showSettings: false, + }, + ...componentOverride, + }), + ); + + const handleComponentChange = ({ tags }: { tags: string[] }) => { + setComponent((c) => { + return { ...c, tags }; + }); + }; + + return <MetaTags component={component} onComponentChange={handleComponentChange} />; + } + + return renderComponent(<Component {...componentOverride} />); } |