diff options
author | Mathieu Suen <mathieu.suen@sonarsource.com> | 2023-07-04 17:51:30 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2023-07-18 20:03:22 +0000 |
commit | 3c41d8d0f24af35018ce0274b7d51b5c66dd27ee (patch) | |
tree | 8f8328b8f65f8d3269f44316c29e33dde070c809 /server/sonar-web/src/main/js/app/components/extensions | |
parent | 5ebbed2a0f508d5bef63de4ed1e89a57e67e25df (diff) | |
download | sonarqube-3c41d8d0f24af35018ce0274b7d51b5c66dd27ee.tar.gz sonarqube-3c41d8d0f24af35018ce0274b7d51b5c66dd27ee.zip |
SONAR-19840 Move branch[es], branch-status, branch-warning state to react-query
Diffstat (limited to 'server/sonar-web/src/main/js/app/components/extensions')
5 files changed, 67 insertions, 41 deletions
diff --git a/server/sonar-web/src/main/js/app/components/extensions/Extension.tsx b/server/sonar-web/src/main/js/app/components/extensions/Extension.tsx index d3535c539be..179d690caa9 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/Extension.tsx +++ b/server/sonar-web/src/main/js/app/components/extensions/Extension.tsx @@ -18,6 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import { withTheme } from '@emotion/react'; +import { QueryClient } from '@tanstack/react-query'; import { Theme } from 'design-system'; import * as React from 'react'; import { Helmet } from 'react-helmet-async'; @@ -28,6 +29,7 @@ import { addGlobalErrorMessage } from '../../../helpers/globalMessages'; import { translate } from '../../../helpers/l10n'; import { getCurrentL10nBundle } from '../../../helpers/l10nBundle'; import { getBaseUrl } from '../../../helpers/system'; +import { withQueryClient } from '../../../queries/withQueryClientHoc'; import { AppState } from '../../../types/appstate'; import { ExtensionStartMethod } from '../../../types/extension'; import { Dict, Extension as TypeExtension } from '../../../types/types'; @@ -44,6 +46,7 @@ export interface ExtensionProps extends WrappedComponentProps { location: Location; options?: Dict<any>; router: Router; + queryClient: QueryClient; updateCurrentUserHomepage: (homepage: HomePage) => void; } @@ -74,7 +77,7 @@ class Extension extends React.PureComponent<ExtensionProps, State> { } handleStart = (start: ExtensionStartMethod) => { - const { theme: dsTheme } = this.props; + const { theme: dsTheme, queryClient } = this.props; const result = start({ appState: this.props.appState, el: this.container, @@ -90,6 +93,7 @@ class Extension extends React.PureComponent<ExtensionProps, State> { // See SONAR-16207 and core-extension-enterprise-server/src/main/js/portfolios/components/Header.tsx // for more information on why we're passing this as a prop to an extension. updateCurrentUserHomepage: this.props.updateCurrentUserHomepage, + queryClient, ...this.props.options, }); @@ -134,5 +138,5 @@ class Extension extends React.PureComponent<ExtensionProps, State> { } export default injectIntl( - withRouter(withTheme(withAppStateContext(withCurrentUserContext(Extension)))) + withRouter(withTheme(withAppStateContext(withCurrentUserContext(withQueryClient(Extension))))) ); diff --git a/server/sonar-web/src/main/js/app/components/extensions/ProjectAdminPageExtension.tsx b/server/sonar-web/src/main/js/app/components/extensions/ProjectAdminPageExtension.tsx index 83046f78c3a..26ed70a56e9 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/ProjectAdminPageExtension.tsx +++ b/server/sonar-web/src/main/js/app/components/extensions/ProjectAdminPageExtension.tsx @@ -19,13 +19,17 @@ */ import * as React from 'react'; import { useParams } from 'react-router-dom'; +import { useRefreshBranches } from '../../../queries/branch'; import NotFound from '../NotFound'; import { ComponentContext } from '../componentContext/ComponentContext'; import Extension from './Extension'; export default function ProjectAdminPageExtension() { const { extensionKey, pluginKey } = useParams(); - const { component, onBranchesChange, onComponentChange } = React.useContext(ComponentContext); + const { component, onComponentChange } = React.useContext(ComponentContext); + + // We keep that for compatibility but ideally should advocate to use tanstack query + const onBranchesChange = useRefreshBranches(); const extension = component && @@ -35,7 +39,7 @@ export default function ProjectAdminPageExtension() { ); return extension ? ( - <Extension extension={extension} options={{ component, onBranchesChange, onComponentChange }} /> + <Extension extension={extension} options={{ component, onComponentChange, onBranchesChange }} /> ) : ( <NotFound withContainer={false} /> ); diff --git a/server/sonar-web/src/main/js/app/components/extensions/ProjectPageExtension.tsx b/server/sonar-web/src/main/js/app/components/extensions/ProjectPageExtension.tsx index 747504f02a8..33b78f11844 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/ProjectPageExtension.tsx +++ b/server/sonar-web/src/main/js/app/components/extensions/ProjectPageExtension.tsx @@ -19,6 +19,7 @@ */ import * as React from 'react'; import { useParams } from 'react-router-dom'; +import { useBranchesQuery } from '../../../queries/branch'; import NotFound from '../NotFound'; import { ComponentContext } from '../componentContext/ComponentContext'; import Extension from './Extension'; @@ -32,12 +33,14 @@ export interface ProjectPageExtensionProps { export default function ProjectPageExtension({ params }: ProjectPageExtensionProps) { const { extensionKey, pluginKey } = useParams(); - const { branchLike, component } = React.useContext(ComponentContext); + const { component } = React.useContext(ComponentContext); + const { data } = useBranchesQuery(component); - if (component === undefined) { + if (component === undefined || data === undefined) { return null; } + const { branchLike } = data; const fullKey = params !== undefined ? `${params.pluginKey}/${params.extensionKey}` diff --git a/server/sonar-web/src/main/js/app/components/extensions/__tests__/ProjectAdminPageExtension-test.tsx b/server/sonar-web/src/main/js/app/components/extensions/__tests__/ProjectAdminPageExtension-test.tsx index e0d6a4c327d..5d7ed345ae8 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/__tests__/ProjectAdminPageExtension-test.tsx +++ b/server/sonar-web/src/main/js/app/components/extensions/__tests__/ProjectAdminPageExtension-test.tsx @@ -17,6 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { render, screen } from '@testing-library/react'; import * as React from 'react'; import { HelmetProvider } from 'react-helmet-async'; @@ -59,17 +60,20 @@ function renderProjectAdminPageExtension( } ) { const { pluginKey, extensionKey } = params; + const queryClient = new QueryClient(); return render( - <HelmetProvider context={{}}> - <IntlProvider defaultLocale="en" locale="en"> - <ComponentContext.Provider value={{ component } as ComponentContextShape}> - <MemoryRouter initialEntries={[`/${pluginKey}/${extensionKey}`]}> - <Routes> - <Route path="/:pluginKey/:extensionKey" element={<ProjectAdminPageExtension />} /> - </Routes> - </MemoryRouter> - </ComponentContext.Provider> - </IntlProvider> - </HelmetProvider> + <QueryClientProvider client={queryClient}> + <HelmetProvider context={{}}> + <IntlProvider defaultLocale="en" locale="en"> + <ComponentContext.Provider value={{ component } as ComponentContextShape}> + <MemoryRouter initialEntries={[`/${pluginKey}/${extensionKey}`]}> + <Routes> + <Route path="/:pluginKey/:extensionKey" element={<ProjectAdminPageExtension />} /> + </Routes> + </MemoryRouter> + </ComponentContext.Provider> + </IntlProvider> + </HelmetProvider> + </QueryClientProvider> ); } diff --git a/server/sonar-web/src/main/js/app/components/extensions/__tests__/ProjectPageExtension-test.tsx b/server/sonar-web/src/main/js/app/components/extensions/__tests__/ProjectPageExtension-test.tsx index c2f8e871846..d61aeee9739 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/__tests__/ProjectPageExtension-test.tsx +++ b/server/sonar-web/src/main/js/app/components/extensions/__tests__/ProjectPageExtension-test.tsx @@ -17,11 +17,13 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { render, screen } from '@testing-library/react'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { render, screen, waitFor } from '@testing-library/react'; import * as React from 'react'; import { HelmetProvider } from 'react-helmet-async'; import { IntlProvider } from 'react-intl'; import { MemoryRouter, Route, Routes } from 'react-router-dom'; +import BranchesServiceMock from '../../../../api/mocks/BranchesServiceMock'; import { getExtensionStart } from '../../../../helpers/extensions'; import { mockComponent } from '../../../../helpers/mocks/component'; import { ComponentContextShape } from '../../../../types/component'; @@ -33,51 +35,60 @@ jest.mock('../../../../helpers/extensions', () => ({ getExtensionStart: jest.fn().mockResolvedValue(jest.fn()), })); +const handler = new BranchesServiceMock(); + +beforeEach(() => { + handler.reset(); +}); + it('should not render when no component is passed', () => { renderProjectPageExtension(); expect(screen.queryByText('page_not_found')).not.toBeInTheDocument(); expect(getExtensionStart).not.toHaveBeenCalledWith('pluginId/extensionId'); }); -it('should render correctly when the extension is found', () => { +it('should render correctly when the extension is found', async () => { renderProjectPageExtension( mockComponent({ extensions: [{ key: 'pluginId/extensionId', name: 'name' }] }), { params: { pluginKey: 'pluginId', extensionKey: 'extensionId' } } ); - expect(getExtensionStart).toHaveBeenCalledWith('pluginId/extensionId'); + await waitFor(() => expect(getExtensionStart).toHaveBeenCalledWith('pluginId/extensionId')); }); -it('should render correctly when the extension is not found', () => { +it('should render correctly when the extension is not found', async () => { renderProjectPageExtension( mockComponent({ extensions: [{ key: 'pluginId/extensionId', name: 'name' }] }), { params: { pluginKey: 'not-found-plugin', extensionKey: 'not-found-extension' } } ); - expect(screen.getByText('page_not_found')).toBeInTheDocument(); + expect(await screen.findByText('page_not_found')).toBeInTheDocument(); }); function renderProjectPageExtension( component?: Component, props?: Partial<ProjectPageExtensionProps> ) { + const queryClient = new QueryClient(); return render( - <HelmetProvider context={{}}> - <IntlProvider defaultLocale="en" locale="en"> - <ComponentContext.Provider value={{ component } as ComponentContextShape}> - <MemoryRouter> - <Routes> - <Route - path="*" - element={ - <ProjectPageExtension - params={{ extensionKey: 'extensionId', pluginKey: 'pluginId' }} - {...props} - /> - } - /> - </Routes> - </MemoryRouter> - </ComponentContext.Provider> - </IntlProvider> - </HelmetProvider> + <QueryClientProvider client={queryClient}> + <HelmetProvider context={{}}> + <IntlProvider defaultLocale="en" locale="en"> + <ComponentContext.Provider value={{ component } as ComponentContextShape}> + <MemoryRouter initialEntries={[`/?id=${component?.key}`]}> + <Routes> + <Route + path="*" + element={ + <ProjectPageExtension + params={{ extensionKey: 'extensionId', pluginKey: 'pluginId' }} + {...props} + /> + } + /> + </Routes> + </MemoryRouter> + </ComponentContext.Provider> + </IntlProvider> + </HelmetProvider> + </QueryClientProvider> ); } |