Browse Source

feat(hybrid-cloud): Update useParams to inject orgId parameter whenever a customer domain is used (#41611)

Alberto Leal 2 years ago
parent
commit
b8c8d7c987
3 changed files with 124 additions and 3 deletions
  1. 5 0
      static/app/constants/index.tsx
  2. 110 1
      static/app/utils/useParams.spec.tsx
  3. 9 2
      static/app/utils/useParams.tsx

+ 5 - 0
static/app/constants/index.tsx

@@ -13,6 +13,11 @@ export const ROOT_ELEMENT = 'blk_router';
 export const usingCustomerDomain =
   typeof window !== 'undefined' ? Boolean(window?.__initialData?.customerDomain) : false;
 
+export const customerDomain =
+  typeof window !== 'undefined'
+    ? window?.__initialData?.customerDomain?.subdomain
+    : undefined;
+
 // This is considered the "default" route/view that users should be taken
 // to when the application does not have any further context
 //

+ 110 - 1
static/app/utils/useParams.spec.tsx

@@ -1,10 +1,29 @@
 import {createMemoryHistory, Route, Router, RouterContext} from 'react-router';
 
-import {render} from 'sentry-test/reactTestingLibrary';
+import {render, screen} from 'sentry-test/reactTestingLibrary';
 
 import {useParams} from 'sentry/utils/useParams';
+import {useRouteContext} from 'sentry/utils/useRouteContext';
 import {RouteContext} from 'sentry/views/routeContext';
 
+const mockUsingCustomerDomain = jest.fn();
+const mockCustomerDomain = jest.fn();
+
+jest.mock('sentry/constants', () => {
+  const sentryConstant = jest.requireActual('sentry/constants');
+  return {
+    ...sentryConstant,
+
+    get usingCustomerDomain() {
+      return mockUsingCustomerDomain();
+    },
+
+    get customerDomain() {
+      return mockCustomerDomain();
+    },
+  };
+});
+
 describe('useParams', () => {
   describe('when the path has no params', () => {
     it('returns an empty object', () => {
@@ -64,4 +83,94 @@ describe('useParams', () => {
       expect(params).toEqual({slug: 'sentry'});
     });
   });
+
+  describe('customer domains', function () {
+    afterEach(function () {
+      jest.resetAllMocks();
+    });
+
+    it('populates orgId when customer domain is being used', function () {
+      mockUsingCustomerDomain.mockReturnValue(true);
+      mockCustomerDomain.mockReturnValue('albertos-apples');
+
+      let originalParams;
+      let useParamsValue;
+
+      function Component() {
+        const {params} = useRouteContext();
+        originalParams = params;
+        useParamsValue = useParams();
+        return (
+          <div>rendered component for org: {useParamsValue.orgId ?? 'no org id'}</div>
+        );
+      }
+
+      const memoryHistory = createMemoryHistory();
+      memoryHistory.push('/issues/?hello');
+
+      render(
+        <Router
+          history={memoryHistory}
+          render={props => {
+            return (
+              <RouteContext.Provider value={props}>
+                <RouterContext {...props} />
+              </RouteContext.Provider>
+            );
+          }}
+        >
+          <Route path="/issues/" component={Component} />
+        </Router>
+      );
+
+      expect(
+        screen.getByText('rendered component for org: albertos-apples')
+      ).toBeInTheDocument();
+      expect(originalParams).toEqual({});
+      expect(useParamsValue).toEqual({
+        orgId: 'albertos-apples',
+      });
+    });
+
+    it('does not populate orgId when customer domain is not being used', function () {
+      mockUsingCustomerDomain.mockReturnValue(false);
+      mockCustomerDomain.mockReturnValue(undefined);
+
+      let originalParams;
+      let useParamsValue;
+
+      function Component() {
+        const {params} = useRouteContext();
+        originalParams = params;
+        useParamsValue = useParams();
+        return (
+          <div>rendered component for org: {useParamsValue.orgId ?? 'no org id'}</div>
+        );
+      }
+
+      const memoryHistory = createMemoryHistory();
+      memoryHistory.push('/issues/?hello');
+
+      render(
+        <Router
+          history={memoryHistory}
+          render={props => {
+            return (
+              <RouteContext.Provider value={props}>
+                <RouterContext {...props} />
+              </RouteContext.Provider>
+            );
+          }}
+        >
+          <Route path="/issues/" component={Component} />
+        </Router>
+      );
+
+      expect(
+        screen.getByText('rendered component for org: no org id')
+      ).toBeInTheDocument();
+      expect(originalParams).toEqual({});
+      expect(useParamsValue).toEqual({});
+    });
+  });
 });

+ 9 - 2
static/app/utils/useParams.tsx

@@ -1,6 +1,13 @@
+import {customerDomain, usingCustomerDomain} from 'sentry/constants';
 import {useRouteContext} from 'sentry/utils/useRouteContext';
 
 export function useParams() {
-  const route = useRouteContext();
-  return route.params;
+  const {params} = useRouteContext();
+
+  if (usingCustomerDomain && customerDomain) {
+    // We do not know if the caller of this hook requires orgId, so we populate orgId implicitly.
+    return {...params, orgId: customerDomain};
+  }
+
+  return params;
 }