aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/app/components/extensions
diff options
context:
space:
mode:
authorMathieu Suen <mathieu.suen@sonarsource.com>2023-07-04 17:51:30 +0200
committersonartech <sonartech@sonarsource.com>2023-07-18 20:03:22 +0000
commit3c41d8d0f24af35018ce0274b7d51b5c66dd27ee (patch)
tree8f8328b8f65f8d3269f44316c29e33dde070c809 /server/sonar-web/src/main/js/app/components/extensions
parent5ebbed2a0f508d5bef63de4ed1e89a57e67e25df (diff)
downloadsonarqube-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')
-rw-r--r--server/sonar-web/src/main/js/app/components/extensions/Extension.tsx8
-rw-r--r--server/sonar-web/src/main/js/app/components/extensions/ProjectAdminPageExtension.tsx8
-rw-r--r--server/sonar-web/src/main/js/app/components/extensions/ProjectPageExtension.tsx7
-rw-r--r--server/sonar-web/src/main/js/app/components/extensions/__tests__/ProjectAdminPageExtension-test.tsx26
-rw-r--r--server/sonar-web/src/main/js/app/components/extensions/__tests__/ProjectPageExtension-test.tsx59
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>
);
}