Browse Source

ref(onboarding-docs): Convert remaining node platforms (#63098)

- part of https://github.com/getsentry/sentry/issues/56549
ArthurKnaus 1 year ago
parent
commit
d8feacb538

+ 64 - 24
static/app/gettingStartedDocs/node/awslambda.spec.tsx

@@ -1,26 +1,66 @@
-import {render, screen} from 'sentry-test/reactTestingLibrary';
-
-import {StepTitle} from 'sentry/components/onboarding/gettingStartedDoc/step';
-
-import {GettingStartedWithAwsLambda, steps} from './awslambda';
-
-describe('GettingStartedWithAwsLambda', function () {
-  it('renders doc correctly', function () {
-    render(<GettingStartedWithAwsLambda dsn="test-dsn" projectSlug="test-project" />);
-
-    // Steps
-    for (const step of steps({
-      installSnippetYarn: 'test-install-snippet-yarn',
-      installSnippetNpm: 'test-install-snippet-npm',
-      importContent: 'test-import-content',
-      initContent: 'test-init-content',
-      sourceMapStep: {
-        title: 'Upload Source Maps',
-      },
-    })) {
-      expect(
-        screen.getByRole('heading', {name: step.title ?? StepTitle[step.type]})
-      ).toBeInTheDocument();
-    }
+import {renderWithOnboardingLayout} from 'sentry-test/onboarding/renderWithOnboardingLayout';
+import {screen} from 'sentry-test/reactTestingLibrary';
+import {textWithMarkupMatcher} from 'sentry-test/utils';
+
+import {ProductSolution} from 'sentry/components/onboarding/productSelection';
+
+import docs from './awslambda';
+
+describe('awslambda onboarding docs', function () {
+  it('renders onboarding docs correctly', () => {
+    renderWithOnboardingLayout(docs);
+
+    // 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();
+
+    // Includes import statement
+    expect(
+      screen.getByText(
+        textWithMarkupMatcher(/const Sentry = require\("@sentry\/serverless"\);/)
+      )
+    ).toBeInTheDocument();
+  });
+
+  it('displays sample rates by default', () => {
+    renderWithOnboardingLayout(docs, {
+      selectedProducts: [
+        ProductSolution.ERROR_MONITORING,
+        ProductSolution.PERFORMANCE_MONITORING,
+        ProductSolution.PROFILING,
+      ],
+    });
+
+    expect(
+      screen.queryByText(textWithMarkupMatcher(/tracesSampleRate/))
+    ).toBeInTheDocument();
+    expect(
+      screen.queryByText(textWithMarkupMatcher(/profilesSampleRate/))
+    ).toBeInTheDocument();
+  });
+
+  it('enables performance setting the tracesSampleRate to 1', () => {
+    renderWithOnboardingLayout(docs, {
+      selectedProducts: [
+        ProductSolution.ERROR_MONITORING,
+        ProductSolution.PERFORMANCE_MONITORING,
+      ],
+    });
+
+    expect(
+      screen.getByText(textWithMarkupMatcher(/tracesSampleRate: 1\.0/))
+    ).toBeInTheDocument();
+  });
+
+  it('enables profiling by setting profiling samplerates', () => {
+    renderWithOnboardingLayout(docs, {
+      selectedProducts: [ProductSolution.ERROR_MONITORING, ProductSolution.PROFILING],
+    });
+
+    expect(
+      screen.getByText(textWithMarkupMatcher(/profilesSampleRate: 1\.0/))
+    ).toBeInTheDocument();
   });
 });

+ 118 - 136
static/app/gettingStartedDocs/node/awslambda.tsx

@@ -1,154 +1,136 @@
-import {Layout, LayoutProps} from 'sentry/components/onboarding/gettingStartedDoc/layout';
-import {ModuleProps} from 'sentry/components/onboarding/gettingStartedDoc/sdkDocumentation';
-import {StepProps, StepType} from 'sentry/components/onboarding/gettingStartedDoc/step';
+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 {
   getDefaulServerlessImports,
-  getDefaultInitParams,
   getInstallSnippet,
-  getProductInitParams,
-  getProductIntegrations,
-  getProductSelectionMap,
-  joinWithIndentation,
+  ProductSelectionMap,
 } from 'sentry/utils/gettingStartedDocs/node';
 
-interface StepsParams {
-  importContent: string;
-  initContent: string;
-  installSnippetNpm: string;
-  installSnippetYarn: string;
-  sourceMapStep: StepProps;
-}
+type Params = DocsParams;
 
-export const steps = ({
-  installSnippetYarn,
-  installSnippetNpm,
-  importContent,
-  initContent,
-  sourceMapStep,
-}: StepsParams): LayoutProps['steps'] => [
-  {
-    type: StepType.INSTALL,
-    description: t('Add the Sentry Serverless SDK as a dependency:'),
-    configurations: [
-      {
-        code: [
-          {
-            label: 'npm',
-            value: 'npm',
-            language: 'bash',
-            code: installSnippetNpm,
-          },
-          {
-            label: 'yarn',
-            value: 'yarn',
-            language: 'bash',
-            code: installSnippetYarn,
-          },
-        ],
-      },
-    ],
-  },
-  {
-    type: StepType.CONFIGURE,
-    description: (
-      <p>
-        {tct("Wrap your lambda handler with Sentry's [code:wraphandler] function:", {
-          code: <code />,
-        })}
-      </p>
-    ),
-    configurations: [
-      {
-        language: 'javascript',
-        code: `
-${importContent}
+const productSelection = (params: Params): ProductSelectionMap => {
+  return {
+    [ProductSolution.ERROR_MONITORING]: true,
+    [ProductSolution.PROFILING]: params.isProfilingSelected,
+    [ProductSolution.PERFORMANCE_MONITORING]: params.isPerformanceSelected,
+    [ProductSolution.SESSION_REPLAY]: params.isReplaySelected,
+  };
+};
+
+const getSdkSetupSnippet = (params: Params) => `
+${getDefaulServerlessImports({productSelection: productSelection(params)}).join('\n')}
 
 Sentry.AWSLambda.init({
-${initContent}
+  dsn: "${params.dsn}",
+  integrations: [${
+    params.isProfilingSelected
+      ? `
+      new ProfilingIntegration(),`
+      : ''
+  }
+],${
+  params.isPerformanceSelected
+    ? `
+      // Performance Monitoring
+      tracesSampleRate: 1.0, //  Capture 100% of the transactions`
+    : ''
+}${
+  params.isProfilingSelected
+    ? `
+    // Set sampling rate for profiling - this is relative to tracesSampleRate
+    profilesSampleRate: 1.0,`
+    : ''
+}
 });
 
 exports.handler = Sentry.AWSLambda.wrapHandler(async (event, context) => {
   // Your handler code
-});
-`,
-      },
-    ],
-  },
-  sourceMapStep,
-  {
-    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: `
-        exports.handler = Sentry.AWSLambda.wrapHandler(async (event, context) => {
-          throw new Error("This should show up in Sentry!")
-        });
-        `,
-      },
-    ],
-  },
-];
+});`;
 
-export function GettingStartedWithAwsLambda({
-  dsn,
-  newOrg,
-  platformKey,
-  activeProductSelection = [],
-  organization,
-  projectId,
-  ...props
-}: ModuleProps) {
-  const productSelection = getProductSelectionMap(activeProductSelection);
-
-  const imports = getDefaulServerlessImports({productSelection});
-  const integrations = getProductIntegrations({productSelection});
-
-  const integrationParam =
-    integrations.length > 0
-      ? `integrations: [\n${joinWithIndentation(integrations)}\n],`
-      : null;
+const getVerifySnippet = () => `
+exports.handler = Sentry.AWSLambda.wrapHandler(async (event, context) => {
+  throw new Error("This should show up in Sentry!")
+});`;
 
-  const initContent = joinWithIndentation([
-    ...getDefaultInitParams({dsn}),
-    ...(integrationParam ? [integrationParam] : []),
-    ...getProductInitParams({productSelection}),
-  ]);
+const onboarding: OnboardingConfig = {
+  install: params => [
+    {
+      type: StepType.INSTALL,
+      description: t('Add the Sentry Serverless SDK as a dependency:'),
+      configurations: [
+        {
+          code: [
+            {
+              label: 'npm',
+              value: 'npm',
+              language: 'bash',
+              code: getInstallSnippet({
+                basePackage: '@sentry/serverless',
+                productSelection: productSelection(params),
+                packageManager: 'npm',
+              }),
+            },
+            {
+              label: 'yarn',
+              value: 'yarn',
+              language: 'bash',
+              code: getInstallSnippet({
+                basePackage: '@sentry/serverless',
+                productSelection: productSelection(params),
+                packageManager: 'yarn',
+              }),
+            },
+          ],
+        },
+      ],
+    },
+  ],
+  configure: params => [
+    {
+      type: StepType.CONFIGURE,
+      description: tct(
+        "Wrap your lambda handler with Sentry's [code:wraphandler] function:",
+        {
+          code: <code />,
+        }
+      ),
+      configurations: [
+        {
+          language: 'javascript',
+          code: getSdkSetupSnippet(params),
+        },
+      ],
+    },
+    getUploadSourceMapsStep({
+      guideLink: 'https://docs.sentry.io/platforms/node/guides/aws-lambda/sourcemaps/',
+      ...params,
+    }),
+  ],
+  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: [
+        {
+          language: 'javascript',
+          code: getVerifySnippet(),
+        },
+      ],
+    },
+  ],
+};
 
-  return (
-    <Layout
-      steps={steps({
-        installSnippetNpm: getInstallSnippet({
-          basePackage: '@sentry/serverless',
-          productSelection,
-          packageManager: 'npm',
-        }),
-        installSnippetYarn: getInstallSnippet({
-          basePackage: '@sentry/serverless',
-          productSelection,
-          packageManager: 'yarn',
-        }),
-        importContent: imports.join('\n'),
-        initContent,
-        sourceMapStep: getUploadSourceMapsStep({
-          guideLink:
-            'https://docs.sentry.io/platforms/node/guides/aws-lambda/sourcemaps/',
-          organization,
-          platformKey,
-          projectId,
-          newOrg,
-        }),
-      })}
-      newOrg={newOrg}
-      platformKey={platformKey}
-      {...props}
-    />
-  );
-}
+const docs: Docs = {
+  onboarding,
+};
 
-export default GettingStartedWithAwsLambda;
+export default docs;

+ 61 - 26
static/app/gettingStartedDocs/node/azurefunctions.spec.tsx

@@ -1,28 +1,63 @@
-import {render, screen} from 'sentry-test/reactTestingLibrary';
-
-import {StepTitle} from 'sentry/components/onboarding/gettingStartedDoc/step';
-
-import {GettingStartedWithAzurefunctions, steps} from './azurefunctions';
-
-describe('GettingStartedWithAzurefunctions', function () {
-  it('renders doc correctly', function () {
-    render(
-      <GettingStartedWithAzurefunctions dsn="test-dsn" projectSlug="test-project" />
-    );
-
-    // Steps
-    for (const step of steps({
-      installSnippetYarn: 'test-install-snippet-yarn',
-      installSnippetNpm: 'test-install-snippet-npm',
-      importContent: 'test-import-content',
-      initContent: 'test-init-content',
-      sourceMapStep: {
-        title: 'Upload Source Maps',
-      },
-    })) {
-      expect(
-        screen.getByRole('heading', {name: step.title ?? StepTitle[step.type]})
-      ).toBeInTheDocument();
-    }
+import {renderWithOnboardingLayout} from 'sentry-test/onboarding/renderWithOnboardingLayout';
+import {screen} from 'sentry-test/reactTestingLibrary';
+import {textWithMarkupMatcher} from 'sentry-test/utils';
+
+import {ProductSolution} from 'sentry/components/onboarding/productSelection';
+
+import docs from './azurefunctions';
+
+describe('express onboarding docs', function () {
+  it('renders onboarding docs correctly', () => {
+    renderWithOnboardingLayout(docs);
+
+    // 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();
+
+    // Includes import statement
+    expect(
+      screen.getByText(textWithMarkupMatcher(/import \* as Sentry from "@sentry\/node"/))
+    ).toBeInTheDocument();
+  });
+
+  it('displays sample rates by default', () => {
+    renderWithOnboardingLayout(docs, {
+      selectedProducts: [
+        ProductSolution.ERROR_MONITORING,
+        ProductSolution.PERFORMANCE_MONITORING,
+        ProductSolution.PROFILING,
+      ],
+    });
+
+    expect(
+      screen.queryByText(textWithMarkupMatcher(/tracesSampleRate/))
+    ).toBeInTheDocument();
+    expect(
+      screen.queryByText(textWithMarkupMatcher(/profilesSampleRate/))
+    ).toBeInTheDocument();
+  });
+
+  it('enables performance setting the tracesSampleRate to 1', () => {
+    renderWithOnboardingLayout(docs, {
+      selectedProducts: [
+        ProductSolution.ERROR_MONITORING,
+        ProductSolution.PERFORMANCE_MONITORING,
+      ],
+    });
+
+    expect(
+      screen.getByText(textWithMarkupMatcher(/tracesSampleRate: 1\.0/))
+    ).toBeInTheDocument();
+  });
+
+  it('enables profiling by setting profiling samplerates', () => {
+    renderWithOnboardingLayout(docs, {
+      selectedProducts: [ProductSolution.ERROR_MONITORING, ProductSolution.PROFILING],
+    });
+
+    expect(
+      screen.getByText(textWithMarkupMatcher(/profilesSampleRate: 1\.0/))
+    ).toBeInTheDocument();
   });
 });

+ 104 - 119
static/app/gettingStartedDocs/node/azurefunctions.tsx

@@ -1,68 +1,55 @@
-import {Layout, LayoutProps} from 'sentry/components/onboarding/gettingStartedDoc/layout';
-import {ModuleProps} from 'sentry/components/onboarding/gettingStartedDoc/sdkDocumentation';
-import {StepProps, StepType} from 'sentry/components/onboarding/gettingStartedDoc/step';
+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 {
-  getDefaultInitParams,
   getDefaultNodeImports,
   getInstallSnippet,
-  getProductInitParams,
-  getProductIntegrations,
-  getProductSelectionMap,
-  joinWithIndentation,
+  ProductSelectionMap,
 } from 'sentry/utils/gettingStartedDocs/node';
 
-interface StepsParams {
-  importContent: string;
-  initContent: string;
-  installSnippetNpm: string;
-  installSnippetYarn: string;
-  sourceMapStep: StepProps;
-}
+type Params = DocsParams;
+
+const productSelection = (params: Params): ProductSelectionMap => {
+  return {
+    [ProductSolution.ERROR_MONITORING]: true,
+    [ProductSolution.PROFILING]: params.isProfilingSelected,
+    [ProductSolution.PERFORMANCE_MONITORING]: params.isPerformanceSelected,
+    [ProductSolution.SESSION_REPLAY]: params.isReplaySelected,
+  };
+};
 
-export const steps = ({
-  installSnippetYarn,
-  installSnippetNpm,
-  importContent,
-  initContent,
-  sourceMapStep,
-}: StepsParams): LayoutProps['steps'] => [
-  {
-    type: StepType.INSTALL,
-    description: t('Add the Sentry Node SDK as a dependency:'),
-    configurations: [
-      {
-        code: [
-          {
-            label: 'npm',
-            value: 'npm',
-            language: 'bash',
-            code: installSnippetNpm,
-          },
-          {
-            label: 'yarn',
-            value: 'yarn',
-            language: 'bash',
-            code: installSnippetYarn,
-          },
-        ],
-      },
-    ],
-  },
-  {
-    type: StepType.CONFIGURE,
-    description: t('To set up Sentry error logging for an Azure Function:'),
-    configurations: [
-      {
-        language: 'javascript',
-        code: `
-        "use strict";
+const getSdkSetupSnippet = (params: Params) => `
+"use strict";
 
-${importContent}
+${getDefaultNodeImports({productSelection: productSelection(params)}).join('\n')}
 
-Sentry.init({
-${initContent}
+Sentry..init({
+  dsn: "${params.dsn}",
+  integrations: [${
+    params.isProfilingSelected
+      ? `
+    new ProfilingIntegration(),`
+      : ''
+  }
+  ],${
+    params.isPerformanceSelected
+      ? `
+  // Performance Monitoring
+  tracesSampleRate: 1.0, //  Capture 100% of the transactions`
+      : ''
+  }${
+    params.isProfilingSelected
+      ? `
+  // Set sampling rate for profiling - this is relative to tracesSampleRate
+  profilesSampleRate: 1.0,`
+      : ''
+  }
 });
 
 module.exports = async function (context, req) {
@@ -78,70 +65,68 @@ module.exports = async function (context, req) {
     body: "Hello from Azure Cloud Function!",
   };
 };
-        `,
-      },
-      {
-        language: 'javascript',
-        description: (
-          <p>
-            {tct(
-              'Note: You need to call both [captureExceptionCode:captureException] and [flushCode:flush] for captured events to be successfully delivered to Sentry.',
-              {captureExceptionCode: <code />, flushCode: <code />}
-            )}
-          </p>
-        ),
-      },
-    ],
-  },
-  sourceMapStep,
-];
+`;
 
-export function GettingStartedWithAzurefunctions({
-  dsn,
-  newOrg,
-  platformKey,
-  activeProductSelection = [],
-  organization,
-  projectId,
-  ...props
-}: ModuleProps) {
-  const productSelection = getProductSelectionMap(activeProductSelection);
-
-  const imports = getDefaultNodeImports({productSelection});
-  const integrations = getProductIntegrations({productSelection});
-
-  const integrationParam =
-    integrations.length > 0
-      ? `integrations: [\n${joinWithIndentation(integrations)}\n],`
-      : null;
-
-  const initContent = joinWithIndentation([
-    ...getDefaultInitParams({dsn}),
-    ...(integrationParam ? [integrationParam] : []),
-    ...getProductInitParams({productSelection}),
-  ]);
+const onboarding: OnboardingConfig = {
+  install: params => [
+    {
+      type: StepType.INSTALL,
+      description: t('Add the Sentry Node SDK as a dependency:'),
+      configurations: [
+        {
+          code: [
+            {
+              label: 'npm',
+              value: 'npm',
+              language: 'bash',
+              code: getInstallSnippet({
+                productSelection: productSelection(params),
+                packageManager: 'npm',
+              }),
+            },
+            {
+              label: 'yarn',
+              value: 'yarn',
+              language: 'bash',
+              code: getInstallSnippet({
+                productSelection: productSelection(params),
+                packageManager: 'yarn',
+              }),
+            },
+          ],
+        },
+      ],
+    },
+  ],
+  configure: params => [
+    {
+      type: StepType.CONFIGURE,
+      description: t('To set up Sentry error logging for an Azure Function:'),
+      configurations: [
+        {
+          language: 'javascript',
+          code: getSdkSetupSnippet(params),
+        },
+        {
+          language: 'javascript',
+          description: tct(
+            'Note: You need to call both [captureExceptionCode:captureException] and [flushCode:flush] for captured events to be successfully delivered to Sentry.',
+            {captureExceptionCode: <code />, flushCode: <code />}
+          ),
+        },
+      ],
+    },
+    getUploadSourceMapsStep({
+      guideLink:
+        'https://docs.sentry.io/platforms/node/guides/azure-functions/sourcemaps/',
+      ...params,
+    }),
+  ],
+  verify: () => [],
+};
 
-  return (
-    <Layout
-      steps={steps({
-        installSnippetNpm: getInstallSnippet({productSelection, packageManager: 'npm'}),
-        installSnippetYarn: getInstallSnippet({productSelection, packageManager: 'yarn'}),
-        importContent: imports.join('\n'),
-        initContent,
-        sourceMapStep: getUploadSourceMapsStep({
-          guideLink:
-            'https://docs.sentry.io/platforms/node/guides/azure-functions/sourcemaps/',
-          organization,
-          platformKey,
-          projectId,
-          newOrg,
-        }),
-      })}
-      newOrg={newOrg}
-      platformKey={platformKey}
-      {...props}
-    />
-  );
-}
+const docs: Docs = {
+  onboarding,
+};
 
-export default GettingStartedWithAzurefunctions;
+export default docs;

+ 61 - 24
static/app/gettingStartedDocs/node/connect.spec.tsx

@@ -1,26 +1,63 @@
-import {render, screen} from 'sentry-test/reactTestingLibrary';
-
-import {StepTitle} from 'sentry/components/onboarding/gettingStartedDoc/step';
-
-import {GettingStartedWithConnect, steps} from './connect';
-
-describe('GettingStartedWithConnect', function () {
-  it('renders doc correctly', function () {
-    render(<GettingStartedWithConnect dsn="test-dsn" projectSlug="test-project" />);
-
-    // Steps
-    for (const step of steps({
-      installSnippetYarn: 'test-install-snippet-yarn',
-      installSnippetNpm: 'test-install-snippet-npm',
-      importContent: 'test-import-content',
-      initContent: 'test-init-content',
-      sourceMapStep: {
-        title: 'Upload Source Maps',
-      },
-    })) {
-      expect(
-        screen.getByRole('heading', {name: step.title ?? StepTitle[step.type]})
-      ).toBeInTheDocument();
-    }
+import {renderWithOnboardingLayout} from 'sentry-test/onboarding/renderWithOnboardingLayout';
+import {screen} from 'sentry-test/reactTestingLibrary';
+import {textWithMarkupMatcher} from 'sentry-test/utils';
+
+import {ProductSolution} from 'sentry/components/onboarding/productSelection';
+
+import docs from './connect';
+
+describe('connect onboarding docs', function () {
+  it('renders onboarding docs correctly', () => {
+    renderWithOnboardingLayout(docs);
+
+    // 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();
+
+    // Includes import statement
+    expect(
+      screen.getByText(textWithMarkupMatcher(/import \* as Sentry from "@sentry\/node"/))
+    ).toBeInTheDocument();
+  });
+
+  it('displays sample rates by default', () => {
+    renderWithOnboardingLayout(docs, {
+      selectedProducts: [
+        ProductSolution.ERROR_MONITORING,
+        ProductSolution.PERFORMANCE_MONITORING,
+        ProductSolution.PROFILING,
+      ],
+    });
+
+    expect(
+      screen.queryByText(textWithMarkupMatcher(/tracesSampleRate/))
+    ).toBeInTheDocument();
+    expect(
+      screen.queryByText(textWithMarkupMatcher(/profilesSampleRate/))
+    ).toBeInTheDocument();
+  });
+
+  it('enables performance setting the tracesSampleRate to 1', () => {
+    renderWithOnboardingLayout(docs, {
+      selectedProducts: [
+        ProductSolution.ERROR_MONITORING,
+        ProductSolution.PERFORMANCE_MONITORING,
+      ],
+    });
+
+    expect(
+      screen.getByText(textWithMarkupMatcher(/tracesSampleRate: 1\.0/))
+    ).toBeInTheDocument();
+  });
+
+  it('enables profiling by setting profiling samplerates', () => {
+    renderWithOnboardingLayout(docs, {
+      selectedProducts: [ProductSolution.ERROR_MONITORING, ProductSolution.PROFILING],
+    });
+
+    expect(
+      screen.getByText(textWithMarkupMatcher(/profilesSampleRate: 1\.0/))
+    ).toBeInTheDocument();
   });
 });

+ 95 - 106
static/app/gettingStartedDocs/node/connect.tsx

@@ -1,67 +1,55 @@
-import {Layout, LayoutProps} from 'sentry/components/onboarding/gettingStartedDoc/layout';
-import {ModuleProps} from 'sentry/components/onboarding/gettingStartedDoc/sdkDocumentation';
-import {StepProps, StepType} from 'sentry/components/onboarding/gettingStartedDoc/step';
+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} from 'sentry/locale';
 import {
-  getDefaultInitParams,
   getDefaultNodeImports,
   getInstallSnippet,
-  getProductInitParams,
-  getProductIntegrations,
-  getProductSelectionMap,
-  joinWithIndentation,
+  ProductSelectionMap,
 } from 'sentry/utils/gettingStartedDocs/node';
 
-interface StepsParams {
-  importContent: string;
-  initContent: string;
-  installSnippetNpm: string;
-  installSnippetYarn: string;
-  sourceMapStep: StepProps;
-}
+type Params = DocsParams;
 
-export const steps = ({
-  installSnippetYarn,
-  installSnippetNpm,
-  importContent,
-  initContent,
-  sourceMapStep,
-}: StepsParams): LayoutProps['steps'] => [
-  {
-    type: StepType.INSTALL,
-    description: t('Add the Sentry Node SDK as a dependency:'),
-    configurations: [
-      {
-        code: [
-          {
-            label: 'npm',
-            value: 'npm',
-            language: 'bash',
-            code: installSnippetNpm,
-          },
-          {
-            label: 'yarn',
-            value: 'yarn',
-            language: 'bash',
-            code: installSnippetYarn,
-          },
-        ],
-      },
-    ],
-  },
-  {
-    type: StepType.CONFIGURE,
-    description: t('Configure Sentry as a middleware:'),
-    configurations: [
-      {
-        language: 'javascript',
-        code: `
-${importContent}
+const productSelection = (params: Params): ProductSelectionMap => {
+  return {
+    [ProductSolution.ERROR_MONITORING]: true,
+    [ProductSolution.PROFILING]: params.isProfilingSelected,
+    [ProductSolution.PERFORMANCE_MONITORING]: params.isPerformanceSelected,
+    [ProductSolution.SESSION_REPLAY]: params.isReplaySelected,
+  };
+};
+
+const getSdkSetupSnippet = (params: Params) => `
+${getDefaultNodeImports({productSelection: productSelection(params)}).join('\n')}
+import connect from "connect";
 
 // Configure Sentry before doing anything else
 Sentry.init({
-${initContent}
+  dsn: "${params.dsn}",
+  integrations: [${
+    params.isProfilingSelected
+      ? `
+      new ProfilingIntegration(),`
+      : ''
+  }
+],${
+  params.isPerformanceSelected
+    ? `
+      // Performance Monitoring
+      tracesSampleRate: 1.0, //  Capture 100% of the transactions`
+    : ''
+}${
+  params.isProfilingSelected
+    ? `
+    // Set sampling rate for profiling - this is relative to tracesSampleRate
+    profilesSampleRate: 1.0,`
+    : ''
+}
 });
 
 function mainHandler(req, res) {
@@ -89,59 +77,60 @@ connect(
   // Optional fallthrough error handler
   onError
 ).listen(3000);
-`,
-      },
-    ],
-  },
-  sourceMapStep,
-];
+`;
 
-export function GettingStartedWithConnect({
-  dsn,
-  newOrg,
-  platformKey,
-  activeProductSelection = [],
-  organization,
-  projectId,
-  ...props
-}: ModuleProps) {
-  const productSelection = getProductSelectionMap(activeProductSelection);
+const onboarding: OnboardingConfig = {
+  install: params => [
+    {
+      type: StepType.INSTALL,
+      description: t('Add the Sentry Node SDK as a dependency:'),
+      configurations: [
+        {
+          code: [
+            {
+              label: 'npm',
+              value: 'npm',
+              language: 'bash',
+              code: getInstallSnippet({
+                productSelection: productSelection(params),
+                packageManager: 'npm',
+              }),
+            },
+            {
+              label: 'yarn',
+              value: 'yarn',
+              language: 'bash',
+              code: getInstallSnippet({
+                productSelection: productSelection(params),
+                packageManager: 'yarn',
+              }),
+            },
+          ],
+        },
+      ],
+    },
+  ],
+  configure: params => [
+    {
+      type: StepType.CONFIGURE,
+      description: t('Configure Sentry as a middleware:'),
+      configurations: [
+        {
+          language: 'javascript',
+          code: getSdkSetupSnippet(params),
+        },
+      ],
+    },
+    getUploadSourceMapsStep({
+      guideLink: 'https://docs.sentry.io/platforms/node/guides/connect/sourcemaps/',
+      ...params,
+    }),
+  ],
+  verify: () => [],
+};
 
-  const imports = getDefaultNodeImports({productSelection});
-  imports.push('import connect from "connect";');
-
-  const integrations = getProductIntegrations({productSelection});
-  const integrationParam =
-    integrations.length > 0
-      ? `integrations: [\n${joinWithIndentation(integrations)}\n],`
-      : null;
-
-  const initContent = joinWithIndentation([
-    ...getDefaultInitParams({dsn}),
-    ...(integrationParam ? [integrationParam] : []),
-    ...getProductInitParams({productSelection}),
-  ]);
-
-  return (
-    <Layout
-      steps={steps({
-        installSnippetNpm: getInstallSnippet({productSelection, packageManager: 'npm'}),
-        installSnippetYarn: getInstallSnippet({productSelection, packageManager: 'yarn'}),
-        importContent: imports.join('\n'),
-        initContent,
-        sourceMapStep: getUploadSourceMapsStep({
-          guideLink: 'https://docs.sentry.io/platforms/node/guides/connect/sourcemaps/',
-          organization,
-          platformKey,
-          projectId,
-          newOrg,
-        }),
-      })}
-      newOrg={newOrg}
-      platformKey={platformKey}
-      {...props}
-    />
-  );
-}
+const docs: Docs = {
+  onboarding,
+};
 
-export default GettingStartedWithConnect;
+export default docs;

+ 1 - 0
static/app/gettingStartedDocs/node/express.tsx

@@ -144,6 +144,7 @@ const onboarding: OnboardingConfig = {
     },
     getUploadSourceMapsStep({
       guideLink: 'https://docs.sentry.io/platforms/node/sourcemaps/',
+      ...params,
     }),
   ],
   verify: () => [

+ 64 - 23
static/app/gettingStartedDocs/node/gcpfunctions.spec.tsx

@@ -1,25 +1,66 @@
-import {render, screen} from 'sentry-test/reactTestingLibrary';
-
-import {StepTitle} from 'sentry/components/onboarding/gettingStartedDoc/step';
-
-import {GettingStartedWithGCPFunctions, steps} from './gcpfunctions';
-
-describe('GettingStartedWithGCPFunctions', function () {
-  it('all products are selected', function () {
-    render(<GettingStartedWithGCPFunctions dsn="test-dsn" projectSlug="test-project" />);
-
-    // Steps
-    for (const step of steps({
-      installSnippet: 'test-install-snippet',
-      importContent: 'test-import-content',
-      initContent: 'test-init-content',
-      sourceMapStep: {
-        title: 'Upload Source Maps',
-      },
-    })) {
-      expect(
-        screen.getByRole('heading', {name: step.title ?? StepTitle[step.type]})
-      ).toBeInTheDocument();
-    }
+import {renderWithOnboardingLayout} from 'sentry-test/onboarding/renderWithOnboardingLayout';
+import {screen} from 'sentry-test/reactTestingLibrary';
+import {textWithMarkupMatcher} from 'sentry-test/utils';
+
+import {ProductSolution} from 'sentry/components/onboarding/productSelection';
+
+import docs from './gcpfunctions';
+
+describe('gcpfunctions onboarding docs', function () {
+  it('renders onboarding docs correctly', () => {
+    renderWithOnboardingLayout(docs);
+
+    // 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();
+
+    // Includes import statement
+    expect(
+      screen.getByText(
+        textWithMarkupMatcher(/const Sentry = require\("@sentry\/serverless"\);/)
+      )
+    ).toBeInTheDocument();
+  });
+
+  it('displays sample rates by default', () => {
+    renderWithOnboardingLayout(docs, {
+      selectedProducts: [
+        ProductSolution.ERROR_MONITORING,
+        ProductSolution.PERFORMANCE_MONITORING,
+        ProductSolution.PROFILING,
+      ],
+    });
+
+    expect(
+      screen.queryByText(textWithMarkupMatcher(/tracesSampleRate/))
+    ).toBeInTheDocument();
+    expect(
+      screen.queryByText(textWithMarkupMatcher(/profilesSampleRate/))
+    ).toBeInTheDocument();
+  });
+
+  it('enables performance setting the tracesSampleRate to 1', () => {
+    renderWithOnboardingLayout(docs, {
+      selectedProducts: [
+        ProductSolution.ERROR_MONITORING,
+        ProductSolution.PERFORMANCE_MONITORING,
+      ],
+    });
+
+    expect(
+      screen.getByText(textWithMarkupMatcher(/tracesSampleRate: 1\.0/))
+    ).toBeInTheDocument();
+  });
+
+  it('enables profiling by setting profiling samplerates', () => {
+    renderWithOnboardingLayout(docs, {
+      selectedProducts: [ProductSolution.ERROR_MONITORING, ProductSolution.PROFILING],
+    });
+
+    expect(
+      screen.getByText(textWithMarkupMatcher(/profilesSampleRate: 1\.0/))
+    ).toBeInTheDocument();
   });
 });

+ 109 - 130
static/app/gettingStartedDocs/node/gcpfunctions.tsx

@@ -1,64 +1,64 @@
-import {Layout, LayoutProps} from 'sentry/components/onboarding/gettingStartedDoc/layout';
-import {ModuleProps} from 'sentry/components/onboarding/gettingStartedDoc/sdkDocumentation';
-import {StepProps, StepType} from 'sentry/components/onboarding/gettingStartedDoc/step';
+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 {
   getDefaulServerlessImports,
-  getDefaultInitParams,
-  getProductInitParams,
-  getProductIntegrations,
-  getProductSelectionMap,
-  joinWithIndentation,
+  ProductSelectionMap,
 } from 'sentry/utils/gettingStartedDocs/node';
 
-interface StepsParams {
-  importContent: string;
-  initContent: string;
-  installSnippet: string;
-  sourceMapStep: StepProps;
-}
+type Params = DocsParams;
+
+const productSelection = (params: Params): ProductSelectionMap => {
+  return {
+    [ProductSolution.ERROR_MONITORING]: true,
+    [ProductSolution.PROFILING]: params.isProfilingSelected,
+    [ProductSolution.PERFORMANCE_MONITORING]: params.isPerformanceSelected,
+    [ProductSolution.SESSION_REPLAY]: params.isReplaySelected,
+  };
+};
+
+const getInstallSnippet = (params: Params) => `
+dependencies: {
+  //...
+  "@sentry/serverless": "^7",${
+    params.isProfilingSelected
+      ? `
+  "@sentry/profiling-node": "^1",`
+      : ''
+  }
+  //...
+}`;
 
-export const steps = ({
-  installSnippet,
-  importContent,
-  initContent,
-  sourceMapStep,
-}: StepsParams): LayoutProps['steps'] => [
-  {
-    type: StepType.INSTALL,
-    description: (
-      <p>
-        {tct(
-          'Add the Sentry Serverless SDK as a dependency to your [code:package.json]:',
-          {code: <code />}
-        )}
-      </p>
-    ),
-    configurations: [
-      {
-        language: 'json',
-        code: installSnippet,
-      },
-    ],
-  },
-  {
-    type: StepType.CONFIGURE,
-    description: (
-      <p>
-        {tct('Use the Sentry SDK to wrap your functions:', {
-          code: <code />,
-        })}
-      </p>
-    ),
-    configurations: [
-      {
-        language: 'javascript',
-        code: `
-${importContent}
+const getSdkSetupSnippet = (params: Params) => `
+${getDefaulServerlessImports({productSelection: productSelection(params)}).join('\n')}
 
 Sentry.GCPFunction.init({
-  ${initContent}
+  dsn: "${params.dsn}",
+  integrations: [${
+    params.isProfilingSelected
+      ? `
+      new ProfilingIntegration(),`
+      : ''
+  }
+],${
+  params.isPerformanceSelected
+    ? `
+      // Performance Monitoring
+      tracesSampleRate: 1.0, //  Capture 100% of the transactions`
+    : ''
+}${
+  params.isProfilingSelected
+    ? `
+    // Set sampling rate for profiling - this is relative to tracesSampleRate
+    profilesSampleRate: 1.0,`
+    : ''
+}
 });
 
 // Use wrapHttpFunction to instrument your http functions
@@ -78,86 +78,65 @@ exports.helloEvents = Sentry.GCPFunction.wrapCloudEventFunction(
   (context, callback) => {
     /* Your function code */
   }
-);
-`,
-      },
-    ],
-  },
-  sourceMapStep,
-  {
-    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: `
+);`;
+
+const getVerifySnippet = () => `
 exports.helloHttp = Sentry.GCPFunction.wrapHttpFunction((req, res) => {
   throw new Error("oh, hello there!");
-});
-        `,
-      },
-    ],
-  },
-];
-
-export function GettingStartedWithGCPFunctions({
-  dsn,
-  newOrg,
-  platformKey,
-  activeProductSelection = [],
-  organization,
-  projectId,
-  ...props
-}: ModuleProps) {
-  const productSelection = getProductSelectionMap(activeProductSelection);
-
-  const installSnippet: string[] = [
-    'dependencies: {',
-    '  //...',
-    `  "@sentry/serverless": "^7",`,
-  ];
-
-  if (productSelection.profiling) {
-    installSnippet.push(`  "@sentry/profiling-node": "^1",`);
-  }
-  installSnippet.push('  //...', '}');
-
-  const imports = getDefaulServerlessImports({productSelection});
-  const integrations = getProductIntegrations({productSelection});
+});`;
 
-  const integrationParam =
-    integrations.length > 0
-      ? `integrations: [\n${joinWithIndentation(integrations)}\n],`
-      : null;
+const onboarding: OnboardingConfig = {
+  install: params => [
+    {
+      type: StepType.INSTALL,
+      description: tct(
+        'Add the Sentry Serverless SDK as a dependency to your [code:package.json]:',
+        {code: <code />}
+      ),
+      configurations: [
+        {
+          language: 'json',
+          code: getInstallSnippet(params),
+        },
+      ],
+    },
+  ],
+  configure: params => [
+    {
+      type: StepType.CONFIGURE,
+      description: tct('Use the Sentry SDK to wrap your functions:', {
+        code: <code />,
+      }),
+      configurations: [
+        {
+          language: 'javascript',
+          code: getSdkSetupSnippet(params),
+        },
+      ],
+    },
+    getUploadSourceMapsStep({
+      guideLink: 'https://docs.sentry.io/platforms/node/guides/gcp-functions/sourcemaps/',
+      ...params,
+    }),
+  ],
+  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: [
+        {
+          language: 'javascript',
+          code: getVerifySnippet(),
+        },
+      ],
+    },
+  ],
+};
 
-  const initContent = joinWithIndentation([
-    ...getDefaultInitParams({dsn}),
-    ...(integrationParam ? [integrationParam] : []),
-    ...getProductInitParams({productSelection}),
-  ]);
-
-  return (
-    <Layout
-      steps={steps({
-        installSnippet: installSnippet.join('\n'),
-        importContent: imports.join('\n'),
-        initContent,
-        sourceMapStep: getUploadSourceMapsStep({
-          guideLink:
-            'https://docs.sentry.io/platforms/node/guides/gcp-functions/sourcemaps/',
-          organization,
-          platformKey,
-          projectId,
-          newOrg,
-        }),
-      })}
-      newOrg={newOrg}
-      platformKey={platformKey}
-      {...props}
-    />
-  );
-}
+const docs: Docs = {
+  onboarding,
+};
 
-export default GettingStartedWithGCPFunctions;
+export default docs;

+ 62 - 25
static/app/gettingStartedDocs/node/koa.spec.tsx

@@ -1,27 +1,64 @@
-import {render, screen} from 'sentry-test/reactTestingLibrary';
-
-import {StepTitle} from 'sentry/components/onboarding/gettingStartedDoc/step';
-
-import {GettingStartedWithKoa, steps} from './koa';
-
-describe('GettingStartedWithKoa', function () {
-  it('all products are selected', function () {
-    render(<GettingStartedWithKoa dsn="test-dsn" projectSlug="test-project" />);
-
-    // Steps
-    for (const step of steps({
-      installSnippetYarn: 'test-install-snippet-yarn',
-      installSnippetNpm: 'test-install-snippet-npm',
-      importContent: 'test-import-content',
-      initContent: 'test-init-content',
-      hasPerformanceMonitoring: true,
-      sourceMapStep: {
-        title: 'Upload Source Maps',
-      },
-    })) {
-      expect(
-        screen.getByRole('heading', {name: step.title ?? StepTitle[step.type]})
-      ).toBeInTheDocument();
-    }
+import {renderWithOnboardingLayout} from 'sentry-test/onboarding/renderWithOnboardingLayout';
+import {screen} from 'sentry-test/reactTestingLibrary';
+import {textWithMarkupMatcher} from 'sentry-test/utils';
+
+import {ProductSolution} from 'sentry/components/onboarding/productSelection';
+
+import docs from './koa';
+
+describe('koa onboarding docs', function () {
+  it('renders onboarding docs correctly', () => {
+    renderWithOnboardingLayout(docs);
+
+    // 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();
+
+    // Includes import statement
+    expect(
+      screen.getByText(textWithMarkupMatcher(/import \* as Sentry from "@sentry\/node"/))
+    ).toBeInTheDocument();
+  });
+
+  it('displays sample rates by default', () => {
+    renderWithOnboardingLayout(docs, {
+      selectedProducts: [
+        ProductSolution.ERROR_MONITORING,
+        ProductSolution.PERFORMANCE_MONITORING,
+        ProductSolution.PROFILING,
+      ],
+    });
+
+    expect(
+      screen.queryByText(textWithMarkupMatcher(/tracesSampleRate/))
+    ).toBeInTheDocument();
+    expect(
+      screen.queryByText(textWithMarkupMatcher(/profilesSampleRate/))
+    ).toBeInTheDocument();
+  });
+
+  it('enables performance setting the tracesSampleRate to 1', () => {
+    renderWithOnboardingLayout(docs, {
+      selectedProducts: [
+        ProductSolution.ERROR_MONITORING,
+        ProductSolution.PERFORMANCE_MONITORING,
+      ],
+    });
+
+    expect(
+      screen.getByText(textWithMarkupMatcher(/tracesSampleRate: 1\.0/))
+    ).toBeInTheDocument();
+  });
+
+  it('enables profiling by setting profiling samplerates', () => {
+    renderWithOnboardingLayout(docs, {
+      selectedProducts: [ProductSolution.ERROR_MONITORING, ProductSolution.PROFILING],
+    });
+
+    expect(
+      screen.getByText(textWithMarkupMatcher(/profilesSampleRate: 1\.0/))
+    ).toBeInTheDocument();
   });
 });

Some files were not shown because too many files changed in this diff