Browse Source

ref(onboarding docs): convert react.tsx (#61277)

relates to https://github.com/getsentry/sentry/issues/61266
Michelle Zhang 1 year ago
parent
commit
09cf3966f1

+ 1 - 1
static/app/gettingStartedDocs/javascript/astro.tsx

@@ -51,7 +51,7 @@ const onboarding: OnboardingConfig = {
     tct("Sentry's integration with [astroLink:Astro] supports Astro 3.0.0 and above.", {
       astroLink: <ExternalLink href="https://astro.build/" />,
     }),
-  install: (_params: Params) => [
+  install: () => [
     {
       type: StepType.INSTALL,
       configurations: [

+ 56 - 54
static/app/gettingStartedDocs/javascript/react.spec.tsx

@@ -1,71 +1,73 @@
-import {render, screen} from 'sentry-test/reactTestingLibrary';
+import {renderWithOnboardingLayout} from 'sentry-test/onboarding/renderWithOnboardingLayout';
+import {screen} from 'sentry-test/reactTestingLibrary';
+import {textWithMarkupMatcher} from 'sentry-test/utils';
 
-import {StepTitle} from 'sentry/components/onboarding/gettingStartedDoc/step';
 import {ProductSolution} from 'sentry/components/onboarding/productSelection';
 
-import GettingStartedWithReact, {nextSteps, steps} from './react';
+import docs from './react';
 
-describe('GettingStartedWithReact', function () {
-  it('all products are selected', function () {
-    render(
-      <GettingStartedWithReact
-        dsn="test-dsn"
-        projectSlug="test-project"
-        activeProductSelection={[
-          ProductSolution.PERFORMANCE_MONITORING,
-          ProductSolution.SESSION_REPLAY,
-        ]}
-      />
-    );
+describe('javascript-react onboarding docs', function () {
+  it('renders onboarding docs correctly', () => {
+    renderWithOnboardingLayout(docs);
 
-    // Steps
-    for (const step of steps()) {
-      expect(
-        screen.getByRole('heading', {name: step.title ?? StepTitle[step.type]})
-      ).toBeInTheDocument();
-    }
+    // Renders main headings
+    expect(screen.getByRole('heading', {name: 'Install'})).toBeInTheDocument();
+    expect(screen.getByRole('heading', {name: 'Configure SDK'})).toBeInTheDocument();
+    expect(screen.getByRole('heading', {name: 'Upload Source Maps'})).toBeInTheDocument();
+    expect(screen.getByRole('heading', {name: 'Verify'})).toBeInTheDocument();
 
-    // Next Steps
-    const filteredNextStepsLinks = nextSteps.filter(
-      nextStep =>
-        ![
-          ProductSolution.PERFORMANCE_MONITORING,
-          ProductSolution.SESSION_REPLAY,
-        ].includes(nextStep.id as ProductSolution)
-    );
+    // Includes import statement
+    expect(
+      screen.getByText(textWithMarkupMatcher(/import \* as Sentry from "@sentry\/react"/))
+    ).toBeInTheDocument();
+  });
+
+  it('displays sample rates by default', () => {
+    renderWithOnboardingLayout(docs, {
+      selectedProducts: [
+        ProductSolution.ERROR_MONITORING,
+        ProductSolution.PERFORMANCE_MONITORING,
+        ProductSolution.SESSION_REPLAY,
+      ],
+    });
 
-    for (const filteredNextStepsLink of filteredNextStepsLinks) {
-      expect(
-        screen.getByRole('link', {name: filteredNextStepsLink.name})
-      ).toBeInTheDocument();
-    }
+    expect(
+      screen.queryByText(textWithMarkupMatcher(/tracesSampleRate/))
+    ).toBeInTheDocument();
+    expect(
+      screen.queryByText(textWithMarkupMatcher(/replaysSessionSampleRate/))
+    ).toBeInTheDocument();
+    expect(
+      screen.queryByText(textWithMarkupMatcher(/replaysOnErrorSampleRate/))
+    ).toBeInTheDocument();
   });
 
-  it('performance product is not selected', function () {
-    render(
-      <GettingStartedWithReact
-        dsn="test-dsn"
-        projectSlug="test-project"
-        activeProductSelection={[ProductSolution.SESSION_REPLAY]}
-      />
-    );
+  it('enables performance setting the tracesSampleRate to 1', () => {
+    renderWithOnboardingLayout(docs, {
+      selectedProducts: [
+        ProductSolution.ERROR_MONITORING,
+        ProductSolution.PERFORMANCE_MONITORING,
+      ],
+    });
 
-    // Next Steps
     expect(
-      screen.getByRole('link', {name: 'Performance Monitoring'})
+      screen.getByText(textWithMarkupMatcher(/tracesSampleRate: 1.0/))
     ).toBeInTheDocument();
   });
 
-  it('session replay product is not selected', function () {
-    render(
-      <GettingStartedWithReact
-        dsn="test-dsn"
-        projectSlug="test-project"
-        activeProductSelection={[ProductSolution.PERFORMANCE_MONITORING]}
-      />
-    );
+  it('enables replay by setting replay samplerates', () => {
+    renderWithOnboardingLayout(docs, {
+      selectedProducts: [
+        ProductSolution.ERROR_MONITORING,
+        ProductSolution.SESSION_REPLAY,
+      ],
+    });
 
-    // Next Steps
-    expect(screen.getByRole('link', {name: 'Session Replay'})).toBeInTheDocument();
+    expect(
+      screen.getByText(textWithMarkupMatcher(/replaysSessionSampleRate: 0.1/))
+    ).toBeInTheDocument();
+    expect(
+      screen.getByText(textWithMarkupMatcher(/replaysOnErrorSampleRate: 1.0/))
+    ).toBeInTheDocument();
   });
 });

+ 154 - 192
static/app/gettingStartedDocs/javascript/react.tsx

@@ -1,209 +1,171 @@
-import {Layout, LayoutProps} from 'sentry/components/onboarding/gettingStartedDoc/layout';
-import {ModuleProps} from 'sentry/components/onboarding/gettingStartedDoc/sdkDocumentation';
 import {StepType} from 'sentry/components/onboarding/gettingStartedDoc/step';
+import {
+  Docs,
+  DocsParams,
+  OnboardingConfig,
+} from 'sentry/components/onboarding/gettingStartedDoc/types';
 import {getUploadSourceMapsStep} from 'sentry/components/onboarding/gettingStartedDoc/utils';
-import {ProductSolution} from 'sentry/components/onboarding/productSelection';
 import {t, tct} from 'sentry/locale';
-import type {Organization, PlatformKey} from 'sentry/types';
 
-type StepProps = {
-  newOrg: boolean;
-  organization: Organization;
-  platformKey: PlatformKey;
-  projectId: string;
-  sentryInitContent: string;
-};
-
-// Configuration Start
-const replayIntegration = `
-new Sentry.Replay(),
-`;
-
-const replayOtherConfig = `
-// Session Replay
-replaysSessionSampleRate: 0.1, // This sets the sample rate at 10%. You may want to change it to 100% while in development and then sample at a lower rate in production.
-replaysOnErrorSampleRate: 1.0, // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur.
-`;
-
-const performanceIntegration = `
-new Sentry.BrowserTracing({
-  // Set 'tracePropagationTargets' to control for which URLs distributed tracing should be enabled
-  tracePropagationTargets: ["localhost", /^https:\\/\\/yourserver\\.io\\/api/],
-}),
-`;
+type Params = DocsParams;
 
-const performanceOtherConfig = `
-// Performance Monitoring
-tracesSampleRate: 1.0, // Capture 100% of the transactions`;
-
-export const steps = ({
-  sentryInitContent,
-  ...props
-}: Partial<StepProps> = {}): LayoutProps['steps'] => [
-  {
-    type: StepType.INSTALL,
-    description: (
-      <p>
-        {tct(
-          'Add the Sentry SDK as a dependency using [codeNpm:npm] or [codeYarn:yarn]:',
-          {
-            codeYarn: <code />,
-            codeNpm: <code />,
-          }
-        )}
-      </p>
-    ),
-    configurations: [
-      {
-        language: 'bash',
-        code: [
-          {
-            label: 'npm',
-            value: 'npm',
-            language: 'bash',
-            code: 'npm install --save @sentry/react',
-          },
-          {
-            label: 'yarn',
-            value: 'yarn',
-            language: 'bash',
-            code: 'yarn add @sentry/react',
-          },
-        ],
-      },
-    ],
-  },
-  {
-    type: StepType.CONFIGURE,
-    description: t(
-      "Initialize Sentry as early as possible in your application's lifecycle."
-    ),
-    configurations: [
-      {
-        language: 'javascript',
-        code: `
+const getSdkSetupSnippet = (params: Params) => `
 //...
 import * as Sentry from "@sentry/react";
 
 Sentry.init({
-  ${sentryInitContent}
+  dsn: "${params.dsn}",
+  integrations: [${
+    params.isPerformanceSelected
+      ? `
+        new Sentry.BrowserTracing({
+          // Set 'tracePropagationTargets' to control for which URLs distributed tracing should be enabled
+          tracePropagationTargets: ["localhost", /^https:\\/\\/yourserver\\.io\\/api/],
+        }),`
+      : ''
+  }${
+    params.isReplaySelected
+      ? `
+        new Sentry.Replay(),`
+      : ''
+  }
+],${
+  params.isPerformanceSelected
+    ? `
+      // Performance Monitoring
+      tracesSampleRate: 1.0, //  Capture 100% of the transactions`
+    : ''
+}${
+  params.isReplaySelected
+    ? `
+      // Session Replay
+      replaysSessionSampleRate: 0.1, // This sets the sample rate at 10%. You may want to change it to 100% while in development and then sample at a lower rate in production.
+      replaysOnErrorSampleRate: 1.0, // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur.`
+    : ''
+}
 });
 
 const container = document.getElementById(“app”);
 const root = createRoot(container);
 root.render(<App />);
-        `,
-      },
-    ],
-  },
-  getUploadSourceMapsStep({
-    guideLink: 'https://docs.sentry.io/platforms/javascript/guides/react/sourcemaps/',
-    ...props,
-  }),
-  {
-    type: StepType.VERIFY,
-    description: t(
-      "This snippet contains an intentional error and can be used as a test to make sure that everything's working as expected."
-    ),
-    configurations: [
-      {
-        language: 'javascript',
-        code: `
-return <button onClick={() => methodDoesNotExist()}>Break the world</button>;
-        `,
-      },
-    ],
-  },
-];
-
-export const nextSteps = [
-  {
-    id: 'react-features',
-    name: t('React Features'),
-    description: t('Learn about our first class integration with the React framework.'),
-    link: 'https://docs.sentry.io/platforms/javascript/guides/react/features/',
-  },
-  {
-    id: 'react-router',
-    name: t('React Router'),
-    description: t(
-      'Configure routing, so Sentry can generate parameterized transaction names for a better overview in Performance Monitoring.'
-    ),
-    link: 'https://docs.sentry.io/platforms/javascript/guides/react/configuration/integrations/react-router/',
-  },
-  {
-    id: 'performance-monitoring',
-    name: t('Performance Monitoring'),
-    description: t(
-      'Track down transactions to connect the dots between 10-second page loads and poor-performing API calls or slow database queries.'
-    ),
-    link: 'https://docs.sentry.io/platforms/javascript/guides/react/performance/',
-  },
-  {
-    id: 'session-replay',
-    name: t('Session Replay'),
-    description: t(
-      'Get to the root cause of an error or latency issue faster by seeing all the technical details related to that issue in one visual replay on your web application.'
-    ),
-    link: 'https://docs.sentry.io/platforms/javascript/guides/react/session-replay/',
-  },
-];
-// Configuration End
-
-export function GettingStartedWithReact({
-  dsn,
-  activeProductSelection = [],
-  organization,
-  newOrg,
-  platformKey,
-  projectId,
-  ...props
-}: ModuleProps) {
-  const integrations: string[] = [];
-  const otherConfigs: string[] = [];
-  let nextStepDocs = [...nextSteps];
-
-  if (activeProductSelection.includes(ProductSolution.PERFORMANCE_MONITORING)) {
-    integrations.push(performanceIntegration.trim());
-    otherConfigs.push(performanceOtherConfig.trim());
-    nextStepDocs = nextStepDocs.filter(
-      step => step.id !== ProductSolution.PERFORMANCE_MONITORING
-    );
-  }
-
-  if (activeProductSelection.includes(ProductSolution.SESSION_REPLAY)) {
-    integrations.push(replayIntegration.trim());
-    otherConfigs.push(replayOtherConfig.trim());
-    nextStepDocs = nextStepDocs.filter(
-      step => step.id !== ProductSolution.SESSION_REPLAY
-    );
-  }
-
-  let sentryInitContent: string[] = [`dsn: "${dsn}",`];
-
-  if (integrations.length > 0) {
-    sentryInitContent = sentryInitContent.concat('integrations: [', integrations, '],');
-  }
+`;
 
-  if (otherConfigs.length > 0) {
-    sentryInitContent = sentryInitContent.concat(otherConfigs);
-  }
+const getVerifyReactSnippet = () => `
+return <button onClick={() => methodDoesNotExist()}>Break the world</button>;
+        `;
+
+const onboarding: OnboardingConfig = {
+  introduction: () => [],
+  install: () => [
+    {
+      type: StepType.INSTALL,
+      configurations: [
+        {
+          description: tct(
+            'Add the Sentry SDK as a dependency using [codeNpm:npm] or [codeYarn:yarn]:',
+            {
+              codeYarn: <code />,
+              codeNpm: <code />,
+            }
+          ),
+          language: 'bash',
+          code: [
+            {
+              label: 'npm',
+              value: 'npm',
+              language: 'bash',
+              code: 'npm install --save @sentry/react',
+            },
+            {
+              label: 'yarn',
+              value: 'yarn',
+              language: 'bash',
+              code: 'yarn add @sentry/react',
+            },
+          ],
+        },
+      ],
+    },
+  ],
+  configure: (params: Params) => [
+    {
+      type: StepType.CONFIGURE,
+      description: t(
+        "Initialize Sentry as early as possible in your application's lifecycle."
+      ),
+      configurations: [
+        {
+          code: [
+            {
+              label: 'JavaScript',
+              value: 'javascript',
+              language: 'javascript',
+              code: getSdkSetupSnippet(params),
+            },
+          ],
+        },
+      ],
+    },
+    getUploadSourceMapsStep({
+      guideLink: 'https://docs.sentry.io/platforms/javascript/guides/react/sourcemaps/',
+    }),
+  ],
+  verify: () => [
+    {
+      type: StepType.VERIFY,
+      description: t(
+        "This snippet contains an intentional error and can be used as a test to make sure that everything's working as expected."
+      ),
+      configurations: [
+        {
+          code: [
+            {
+              label: 'React',
+              value: 'react',
+              language: 'javascript',
+              code: getVerifyReactSnippet(),
+            },
+          ],
+        },
+      ],
+    },
+  ],
+  nextSteps: () => [
+    {
+      id: 'react-features',
+      name: t('React Features'),
+      description: t('Learn about our first class integration with the React framework.'),
+      link: 'https://docs.sentry.io/platforms/javascript/guides/react/features/',
+    },
+    {
+      id: 'react-router',
+      name: t('React Router'),
+      description: t(
+        'Configure routing, so Sentry can generate parameterized transaction names for a better overview in Performance Monitoring.'
+      ),
+      link: 'https://docs.sentry.io/platforms/javascript/guides/react/configuration/integrations/react-router/',
+    },
+    {
+      id: 'performance-monitoring',
+      name: t('Performance Monitoring'),
+      description: t(
+        'Track down transactions to connect the dots between 10-second page loads and poor-performing API calls or slow database queries.'
+      ),
+      link: 'https://docs.sentry.io/platforms/javascript/guides/react/performance/',
+    },
+    {
+      id: 'session-replay',
+      name: t('Session Replay'),
+      description: t(
+        'Get to the root cause of an error or latency issue faster by seeing all the technical details related to that issue in one visual replay on your web application.'
+      ),
+      link: 'https://docs.sentry.io/platforms/javascript/guides/react/session-replay/',
+    },
+  ],
+};
 
-  return (
-    <Layout
-      steps={steps({
-        sentryInitContent: sentryInitContent.join('\n'),
-        organization,
-        newOrg,
-        platformKey,
-        projectId,
-      })}
-      nextSteps={nextStepDocs}
-      newOrg={newOrg}
-      platformKey={platformKey}
-      {...props}
-    />
-  );
-}
+const docs: Docs = {
+  onboarding,
+};
 
-export default GettingStartedWithReact;
+export default docs;