Browse Source

ref(onboarding): Convert other dotnet platforms to new structure (#58335)

- relates to https://github.com/getsentry/sentry/issues/56549
ArthurKnaus 1 year ago
parent
commit
763b9f5514

+ 1 - 1
static/app/gettingStartedDocs/dotnet/aspnet.spec.tsx

@@ -5,7 +5,7 @@ import {textWithMarkupMatcher} from 'sentry-test/utils';
 import docs from './aspnet';
 import docs from './aspnet';
 
 
 describe('aspnet onboarding docs', function () {
 describe('aspnet onboarding docs', function () {
-  it('renders gradle docs correctly', async function () {
+  it('renders docs correctly', async function () {
     renderWithOnboardingLayout(docs, {
     renderWithOnboardingLayout(docs, {
       releaseRegistry: {
       releaseRegistry: {
         'sentry.dotnet.aspnet': {
         'sentry.dotnet.aspnet': {

+ 1 - 1
static/app/gettingStartedDocs/dotnet/aspnetcore.spec.tsx

@@ -5,7 +5,7 @@ import {textWithMarkupMatcher} from 'sentry-test/utils';
 import docs from './aspnetcore';
 import docs from './aspnetcore';
 
 
 describe('aspnetcore onboarding docs', function () {
 describe('aspnetcore onboarding docs', function () {
-  it('renders gradle docs correctly', async function () {
+  it('renders docs correctly', async function () {
     renderWithOnboardingLayout(docs, {
     renderWithOnboardingLayout(docs, {
       releaseRegistry: {
       releaseRegistry: {
         'sentry.dotnet.aspnetcore': {
         'sentry.dotnet.aspnetcore': {

+ 1 - 1
static/app/gettingStartedDocs/dotnet/dotnet.spec.tsx

@@ -5,7 +5,7 @@ import {textWithMarkupMatcher} from 'sentry-test/utils';
 import docs from './dotnet';
 import docs from './dotnet';
 
 
 describe('dotnet onboarding docs', function () {
 describe('dotnet onboarding docs', function () {
-  it('renders gradle docs correctly', async function () {
+  it('renders docs correctly', async function () {
     renderWithOnboardingLayout(docs, {
     renderWithOnboardingLayout(docs, {
       releaseRegistry: {
       releaseRegistry: {
         'sentry.dotnet': {
         'sentry.dotnet': {

+ 27 - 12
static/app/gettingStartedDocs/dotnet/maui.spec.tsx

@@ -1,18 +1,33 @@
-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 docs from './maui';
 
 
-import {GettingStartedWithMaui, steps} from './maui';
+describe('maui onboarding docs', function () {
+  it('renders docs correctly', async function () {
+    renderWithOnboardingLayout(docs, {
+      releaseRegistry: {
+        'sentry.dotnet.maui': {
+          version: '1.99.9',
+        },
+      },
+    });
 
 
-describe('GettingStartedWithMaui', function () {
-  it('renders doc correctly', function () {
-    render(<GettingStartedWithMaui dsn="test-dsn" projectSlug="test-project" />);
+    // Renders main headings
+    expect(screen.getByRole('heading', {name: 'Install'})).toBeInTheDocument();
+    expect(screen.getByRole('heading', {name: 'Configure SDK'})).toBeInTheDocument();
+    expect(screen.getByRole('heading', {name: 'Verify'})).toBeInTheDocument();
+    expect(
+      screen.getByRole('heading', {name: 'Performance Monitoring'})
+    ).toBeInTheDocument();
+    expect(screen.getByRole('heading', {name: 'Sample Application'})).toBeInTheDocument();
 
 
-    // Steps
-    for (const step of steps()) {
-      expect(
-        screen.getByRole('heading', {name: step.title ?? StepTitle[step.type]})
-      ).toBeInTheDocument();
-    }
+    // Renders SDK version from registry
+    expect(
+      await screen.findByText(
+        textWithMarkupMatcher(/Install-Package Sentry\.Maui -Version 1\.99\.9/)
+      )
+    ).toBeInTheDocument();
   });
   });
 });
 });

+ 162 - 161
static/app/gettingStartedDocs/dotnet/maui.tsx

@@ -1,65 +1,32 @@
 import {Fragment} from 'react';
 import {Fragment} from 'react';
 
 
 import ExternalLink from 'sentry/components/links/externalLink';
 import ExternalLink from 'sentry/components/links/externalLink';
-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 {StepType} from 'sentry/components/onboarding/gettingStartedDoc/step';
+import type {
+  Docs,
+  DocsParams,
+  OnboardingConfig,
+} from 'sentry/components/onboarding/gettingStartedDoc/types';
 import {t, tct} from 'sentry/locale';
 import {t, tct} from 'sentry/locale';
+import {getPackageVersion} from 'sentry/utils/gettingStartedDocs/getPackageVersion';
 
 
-// Configuration Start
-export const steps = ({
-  dsn,
-  sourcePackageRegistries,
-}: Partial<
-  Pick<ModuleProps, 'dsn' | 'sourcePackageRegistries'>
-> = {}): LayoutProps['steps'] => [
-  {
-    type: StepType.INSTALL,
-    description: (
-      <p>
-        {tct('Install the [strong:NuGet] package:', {
-          strong: <strong />,
-        })}
-      </p>
-    ),
-    configurations: [
-      {
-        language: 'shell',
-        partialLoading: sourcePackageRegistries?.isLoading,
-        code: `dotnet add package Sentry.Maui -v ${
-          sourcePackageRegistries?.isLoading
-            ? t('\u2026loading')
-            : sourcePackageRegistries?.data?.['sentry.dotnet.maui']?.version ?? '3.34.0'
-        }`,
-      },
-      {
-        language: 'powershell',
-        partialLoading: sourcePackageRegistries?.isLoading,
-        code: `Install-Package Sentry.Maui -Version ${
-          sourcePackageRegistries?.isLoading
-            ? t('\u2026loading')
-            : sourcePackageRegistries?.data?.['sentry.dotnet.maui']?.version ?? '3.34.0'
-        }`,
-      },
-    ],
-  },
-  {
-    type: StepType.CONFIGURE,
-    description: (
-      <p>
-        {tct(
-          'Then add Sentry to [mauiProgram:MauiProgram.cs] through the [mauiAppBuilderCode:MauiAppBuilder]:',
-          {
-            mauiAppBuilderCode: <code />,
-            mauiProgram: <code />,
-          }
-        )}
-      </p>
-    ),
-    configurations: [
-      {
-        language: 'csharp',
-        code: `
+type Params = DocsParams;
+
+const getInstallSnippetPackageManager = (params: Params) => `
+Install-Package Sentry.Maui -Version ${getPackageVersion(
+  params,
+  'sentry.dotnet.maui',
+  '3.34.0'
+)}`;
+
+const getInstallSnippetCoreCli = (params: Params) => `
+dotnet add package Sentry.Maui -v ${getPackageVersion(
+  params,
+  'sentry.dotnet.maui',
+  '3.34.0'
+)}`;
+
+const getConfigureSnippet = (params: Params) => `
 public static MauiApp CreateMauiApp()
 public static MauiApp CreateMauiApp()
 {
 {
   var builder = MauiApp.CreateBuilder();
   var builder = MauiApp.CreateBuilder();
@@ -69,7 +36,7 @@ public static MauiApp CreateMauiApp()
     // Add this section anywhere on the builder:
     // Add this section anywhere on the builder:
     .UseSentry(options => {
     .UseSentry(options => {
       // The DSN is the only required setting.
       // The DSN is the only required setting.
-      options.Dsn = "${dsn}";
+      options.Dsn = "${params.dsn}";
 
 
       // Use debug mode if you want to see what the SDK is doing.
       // Use debug mode if you want to see what the SDK is doing.
       // Debug messages are written to stdout with Console.Writeline,
       // Debug messages are written to stdout with Console.Writeline,
@@ -87,78 +54,13 @@ public static MauiApp CreateMauiApp()
   // ... the remainder of your MAUI app setup
   // ... the remainder of your MAUI app setup
 
 
   return builder.Build();
   return builder.Build();
-}
-        `,
-      },
-    ],
-  },
-  {
-    type: StepType.VERIFY,
-    description: t(
-      'To verify your set up, you can capture a message with the SDK, anywhere in your code after the application is built, such as in a page constructor or button click event handler:'
-    ),
-    configurations: [
-      {
-        language: 'csharp',
-        code: 'SentrySdk.CaptureMessage("Hello Sentry");',
-      },
-    ],
-  },
-  {
-    title: t('Performance Monitoring'),
-    description: (
-      <Fragment>
-        {t(
-          'We do not yet have automatic performance instrumentation for .NET MAUI. We will be adding that in a future release. However, if desired you can still manually instrument parts of your application.'
-        )}
-        <p>
-          {tct(
-            'For some parts of your code, [automaticInstrumentationLink:automatic instrumentation] is available across all of our .NET SDKs, and can be used with MAUI as well:',
-            {
-              automaticInstrumentationLink: (
-                <ExternalLink href="https://docs.sentry.io/platforms/dotnet/guides/maui/performance/instrumentation/automatic-instrumentation/" />
-              ),
-            }
-          )}
-        </p>
-      </Fragment>
-    ),
-    configurations: [
-      {
-        description: (
-          <p>
-            {tct(
-              'If your app uses [code:HttpClient], you can instrument your HTTP calls by passing our HTTP message handler:',
-              {code: <code />}
-            )}
-          </p>
-        ),
-        language: 'csharp',
-        code: `
+}`;
+
+const getPerformanceMessageHandlerSnippet = () => `
 var httpHandler = new SentryHttpMessageHandler();
 var httpHandler = new SentryHttpMessageHandler();
-var httpClient = new HttpClient(httpHandler);
-        `,
-      },
-      {
-        description: (
-          <Fragment>
-            {t(
-              'If your app uses Entity Framework Core or SQL Client, we will automatically instrument that for you without any additional code.'
-            )}
-            <p>
-              {tct(
-                'For other parts of your code, you can use [customInstrumentationLink:custom instrumentation], such as in the following example:',
-                {
-                  customInstrumentationLink: (
-                    <ExternalLink href="https://docs.sentry.io/platforms/dotnet/guides/maui/performance/instrumentation/custom-instrumentation/" />
-                  ),
-                }
-              )}
-            </p>
-          </Fragment>
-        ),
-        language: 'csharp',
-        code: `
+var httpClient = new HttpClient(httpHandler);`;
+
+const getPerformanceInstrumentationSnippet = () => `
 // Transaction can be started by providing, at minimum, the name and the operation
 // Transaction can be started by providing, at minimum, the name and the operation
 var transaction = SentrySdk.StartTransaction(
 var transaction = SentrySdk.StartTransaction(
   "test-transaction-name",
   "test-transaction-name",
@@ -173,36 +75,135 @@ var span = transaction.StartChild("test-child-operation");
 // ...
 // ...
 
 
 span.Finish(); // Mark the span as finished
 span.Finish(); // Mark the span as finished
-transaction.Finish(); // Mark the transaction as finished and send it to Sentry
-        `,
-      },
-    ],
-  },
-  {
-    title: t('Sample Application'),
-    description: (
-      <p>
-        {tct(
-          'See the [mauiSampleLink:MAUI Sample in the [code:sentry-dotnet] repository].',
-          {
-            mauiSampleLink: (
-              <ExternalLink href="https://github.com/getsentry/sentry-dotnet/tree/main/samples/Sentry.Samples.Maui" />
-            ),
-            code: <code />,
-          }
-        )}
-      </p>
-    ),
-  },
-];
-// Configuration End
-
-export function GettingStartedWithMaui({
-  dsn,
-  sourcePackageRegistries,
-  ...props
-}: ModuleProps) {
-  return <Layout steps={steps({dsn, sourcePackageRegistries})} {...props} />;
-}
-
-export default GettingStartedWithMaui;
+transaction.Finish(); // Mark the transaction as finished and send it to Sentry`;
+
+const onboarding: OnboardingConfig = {
+  install: params => [
+    {
+      type: StepType.INSTALL,
+      description: tct('Install the [strong:NuGet] package:', {
+        strong: <strong />,
+      }),
+      configurations: [
+        {
+          partialLoading: params.sourcePackageRegistries.isLoading,
+          code: [
+            {
+              language: 'shell',
+              label: 'Package Manager',
+              value: 'packageManager',
+              code: getInstallSnippetPackageManager(params),
+            },
+            {
+              language: 'shell',
+              label: '.NET Core CLI',
+              value: 'coreCli',
+              code: getInstallSnippetCoreCli(params),
+            },
+          ],
+        },
+      ],
+    },
+  ],
+  configure: params => [
+    {
+      type: StepType.CONFIGURE,
+      description: tct(
+        'Then add Sentry to [mauiProgram:MauiProgram.cs] through the [mauiAppBuilderCode:MauiAppBuilder]:',
+        {
+          mauiAppBuilderCode: <code />,
+          mauiProgram: <code />,
+        }
+      ),
+      configurations: [
+        {
+          language: 'csharp',
+          code: getConfigureSnippet(params),
+        },
+      ],
+    },
+  ],
+  verify: () => [
+    {
+      type: StepType.VERIFY,
+      description: t(
+        'To verify your set up, you can capture a message with the SDK, anywhere in your code after the application is built, such as in a page constructor or button click event handler:'
+      ),
+      configurations: [
+        {
+          language: 'csharp',
+          code: 'SentrySdk.CaptureMessage("Hello Sentry");',
+        },
+      ],
+    },
+    {
+      title: t('Performance Monitoring'),
+      description: (
+        <Fragment>
+          {t(
+            'We do not yet have automatic performance instrumentation for .NET MAUI. We will be adding that in a future release. However, if desired you can still manually instrument parts of your application.'
+          )}
+          <p>
+            {tct(
+              'For some parts of your code, [automaticInstrumentationLink:automatic instrumentation] is available across all of our .NET SDKs, and can be used with MAUI as well:',
+              {
+                automaticInstrumentationLink: (
+                  <ExternalLink href="https://docs.sentry.io/platforms/dotnet/guides/maui/performance/instrumentation/automatic-instrumentation/" />
+                ),
+              }
+            )}
+          </p>
+        </Fragment>
+      ),
+      configurations: [
+        {
+          description: tct(
+            'If your app uses [code:HttpClient], you can instrument your HTTP calls by passing our HTTP message handler:',
+            {code: <code />}
+          ),
+          language: 'csharp',
+          code: getPerformanceMessageHandlerSnippet(),
+        },
+        {
+          description: (
+            <Fragment>
+              {t(
+                'If your app uses Entity Framework Core or SQL Client, we will automatically instrument that for you without any additional code.'
+              )}
+              <p>
+                {tct(
+                  'For other parts of your code, you can use [customInstrumentationLink:custom instrumentation], such as in the following example:',
+                  {
+                    customInstrumentationLink: (
+                      <ExternalLink href="https://docs.sentry.io/platforms/dotnet/guides/maui/performance/instrumentation/custom-instrumentation/" />
+                    ),
+                  }
+                )}
+              </p>
+            </Fragment>
+          ),
+          language: 'csharp',
+          code: getPerformanceInstrumentationSnippet(),
+        },
+      ],
+    },
+    {
+      title: t('Sample Application'),
+      description: tct(
+        'See the [mauiSampleLink:MAUI Sample in the [code:sentry-dotnet] repository].',
+        {
+          mauiSampleLink: (
+            <ExternalLink href="https://github.com/getsentry/sentry-dotnet/tree/main/samples/Sentry.Samples.Maui" />
+          ),
+          code: <code />,
+        }
+      ),
+    },
+  ],
+};
+
+const docs: Docs = {
+  onboarding,
+};
+
+export default docs;

+ 28 - 12
static/app/gettingStartedDocs/dotnet/uwp.spec.tsx

@@ -1,18 +1,34 @@
-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 docs from './uwp';
 
 
-import {GettingStartedWithUwp, steps} from './uwp';
+describe('uwp onboarding docs', function () {
+  it('renders docs correctly', async function () {
+    renderWithOnboardingLayout(docs, {
+      releaseRegistry: {
+        'sentry.dotnet': {
+          version: '1.99.9',
+        },
+      },
+    });
 
 
-describe('GettingStartedWithUwp', function () {
-  it('renders doc correctly', function () {
-    render(<GettingStartedWithUwp dsn="test-dsn" projectSlug="test-project" />);
+    // Renders main headings
+    expect(screen.getByRole('heading', {name: 'Install'})).toBeInTheDocument();
+    expect(screen.getByRole('heading', {name: 'Configure SDK'})).toBeInTheDocument();
+    expect(screen.getByRole('heading', {name: 'Verify'})).toBeInTheDocument();
+    expect(
+      screen.getByRole('heading', {name: 'Performance Monitoring'})
+    ).toBeInTheDocument();
+    expect(screen.getByRole('heading', {name: 'Documentation'})).toBeInTheDocument();
+    expect(screen.getByRole('heading', {name: 'Samples'})).toBeInTheDocument();
 
 
-    // Steps
-    for (const step of steps()) {
-      expect(
-        screen.getByRole('heading', {name: step.title ?? StepTitle[step.type]})
-      ).toBeInTheDocument();
-    }
+    // Renders SDK version from registry
+    expect(
+      await screen.findByText(
+        textWithMarkupMatcher(/Install-Package Sentry -Version 1\.99\.9/)
+      )
+    ).toBeInTheDocument();
   });
   });
 });
 });

+ 162 - 175
static/app/gettingStartedDocs/dotnet/uwp.tsx

@@ -5,73 +5,24 @@ import {Alert} from 'sentry/components/alert';
 import ExternalLink from 'sentry/components/links/externalLink';
 import ExternalLink from 'sentry/components/links/externalLink';
 import List from 'sentry/components/list';
 import List from 'sentry/components/list';
 import ListItem from 'sentry/components/list/listItem';
 import ListItem from 'sentry/components/list/listItem';
-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 {StepType} from 'sentry/components/onboarding/gettingStartedDoc/step';
+import type {
+  Docs,
+  DocsParams,
+  OnboardingConfig,
+} from 'sentry/components/onboarding/gettingStartedDoc/types';
 import {t, tct} from 'sentry/locale';
 import {t, tct} from 'sentry/locale';
+import {getPackageVersion} from 'sentry/utils/gettingStartedDocs/getPackageVersion';
 
 
-// Configuration Start
-export const steps = ({
-  dsn,
-  sourcePackageRegistries,
-}: Partial<
-  Pick<ModuleProps, 'dsn' | 'sourcePackageRegistries'>
-> = {}): LayoutProps['steps'] => [
-  {
-    type: StepType.INSTALL,
-    description: (
-      <p>
-        {tct('Install the [strong:NuGet] package:', {
-          strong: <strong />,
-        })}
-      </p>
-    ),
-    configurations: [
-      {
-        language: 'shell',
-        partialLoading: sourcePackageRegistries?.isLoading,
-        code: `
-# Using Package Manager
-Install-Package Sentry -Version ${
-          sourcePackageRegistries?.isLoading
-            ? t('\u2026loading')
-            : sourcePackageRegistries?.data?.['sentry.dotnet']?.version ?? '3.34.0'
-        }
+type Params = DocsParams;
 
 
-# Or using .NET Core CLI
-dotnet add package Sentry -v ${
-          sourcePackageRegistries?.isLoading
-            ? t('\u2026loading')
-            : sourcePackageRegistries?.data?.['sentry.dotnet']?.version ?? '3.34.0'
-        }
-        `,
-      },
-    ],
-    additionalInfo: (
-      <AlertWithoutMarginBottom type="info">
-        {tct(
-          '[strong:Using .NET Framework prior to 4.6.1?] Our legacy SDK supports .NET Framework as early as 3.5.',
-          {strong: <strong />}
-        )}
-      </AlertWithoutMarginBottom>
-    ),
-  },
-  {
-    type: StepType.CONFIGURE,
-    description: (
-      <p>
-        {tct(
-          'Initialize the SDK as early as possible, like in the constructor of the [code:App]:',
-          {
-            code: <code />,
-          }
-        )}
-      </p>
-    ),
-    configurations: [
-      {
-        language: 'csharp',
-        code: `
+const getInstallSnippetPackageManager = (params: Params) => `
+Install-Package Sentry -Version ${getPackageVersion(params, 'sentry.dotnet', '3.34.0')}`;
+
+const getInstallSnippetCoreCli = (params: Params) => `
+dotnet add package Sentry -v ${getPackageVersion(params, 'sentry.dotnet', '3.34.0')}`;
+
+const getConfigureSnippet = (params: Params) => `
 using System.Windows;
 using System.Windows;
 using Sentry.Protocol;
 using Sentry.Protocol;
 using Sentry;
 using Sentry;
@@ -83,7 +34,7 @@ sealed partial class App : Application
         SentrySdk.Init(o =>
         SentrySdk.Init(o =>
         {
         {
             // Tells which project in Sentry to send events to:
             // Tells which project in Sentry to send events to:
-            o.Dsn = "${dsn}";
+            o.Dsn = "${params.dsn}";
             // When configuring for the first time, to see what the SDK is doing:
             // When configuring for the first time, to see what the SDK is doing:
             o.Debug = true;
             o.Debug = true;
             // Set TracesSampleRate to 1.0 to capture 100% of transactions for performance monitoring.
             // Set TracesSampleRate to 1.0 to capture 100% of transactions for performance monitoring.
@@ -108,43 +59,9 @@ sealed partial class App : Application
             SentrySdk.FlushAsync(TimeSpan.FromSeconds(3)).Wait();
             SentrySdk.FlushAsync(TimeSpan.FromSeconds(3)).Wait();
         }
         }
     }
     }
-}
-        `,
-      },
-    ],
-  },
-  {
-    type: StepType.VERIFY,
-    description: t('To verify your set up, you can capture a message with the SDK:'),
-    configurations: [
-      {
-        language: 'csharp',
-        code: 'SentrySdk.CaptureMessage("Hello Sentry");',
-      },
-    ],
-    additionalInfo: (
-      <p>
-        {tct(
-          "If you don't want to depend on the static class, the SDK registers a client in the DI container. In this case, you can [link:take [code:IHub] as a dependency].",
-          {
-            code: <code />,
-            link: (
-              <ExternalLink href="https://docs.sentry.io/platforms/dotnet/guides/aspnetcore/unit-testing/" />
-            ),
-          }
-        )}
-      </p>
-    ),
-  },
-  {
-    title: t('Performance Monitoring'),
-    description: t(
-      'You can measure the performance of your code by capturing transactions and spans.'
-    ),
-    configurations: [
-      {
-        language: 'csharp',
-        code: `
+}`;
+
+const getPerformanceInstrumentationSnippet = () => `
 // Transaction can be started by providing, at minimum, the name and the operation
 // Transaction can be started by providing, at minimum, the name and the operation
 var transaction = SentrySdk.StartTransaction(
 var transaction = SentrySdk.StartTransaction(
   "test-transaction-name",
   "test-transaction-name",
@@ -159,90 +76,160 @@ var span = transaction.StartChild("test-child-operation");
 // ...
 // ...
 
 
 span.Finish(); // Mark the span as finished
 span.Finish(); // Mark the span as finished
-transaction.Finish(); // Mark the transaction as finished and send it to Sentry
-        `,
-      },
-    ],
-    additionalInfo: (
-      <p>
-        {tct(
-          'Check out [link:the documentation] to learn more about the API and automatic instrumentations.',
-          {
-            link: (
-              <ExternalLink href="https://docs.sentry.io/platforms/dotnet/performance/instrumentation/" />
-            ),
-          }
-        )}
-      </p>
-    ),
-  },
-  {
-    title: t('Documentation'),
-    description: (
-      <p>
-        {tct(
-          "Once you've verified the package is initialized properly and sent a test event, consider visiting our [link:complete UWP docs].",
-          {
-            link: (
-              <ExternalLink href="https://docs.sentry.io/platforms/dotnet/guides/uwp/" />
-            ),
-          }
-        )}
-      </p>
-    ),
-  },
-  {
-    title: t('Samples'),
-    description: (
-      <Fragment>
-        <p>
-          {tct(
-            'You can find an example UWP app with Sentry integrated [link:on this GitHub repository].',
+transaction.Finish(); // Mark the transaction as finished and send it to Sentry`;
+
+const onboarding: OnboardingConfig = {
+  install: params => [
+    {
+      type: StepType.INSTALL,
+      description: tct('Install the [strong:NuGet] package:', {
+        strong: <strong />,
+      }),
+      configurations: [
+        {
+          partialLoading: params.sourcePackageRegistries.isLoading,
+          code: [
+            {
+              language: 'shell',
+              label: 'Package Manager',
+              value: 'packageManager',
+              code: getInstallSnippetPackageManager(params),
+            },
             {
             {
-              link: (
-                <ExternalLink href="https://github.com/getsentry/examples/tree/master/dotnet/UwpCSharp" />
-              ),
-            }
+              language: 'shell',
+              label: '.NET Core CLI',
+              value: 'coreCli',
+              code: getInstallSnippetCoreCli(params),
+            },
+          ],
+        },
+      ],
+      additionalInfo: (
+        <AlertWithoutMarginBottom type="info">
+          {tct(
+            '[strong:Using .NET Framework prior to 4.6.1?] Our legacy SDK supports .NET Framework as early as 3.5.',
+            {strong: <strong />}
           )}
           )}
-        </p>
-        {t(
-          'See the following examples that demonstrate how to integrate Sentry with various frameworks.'
-        )}
-        <List symbol="bullet">
-          <ListItem>
+        </AlertWithoutMarginBottom>
+      ),
+    },
+  ],
+  configure: params => [
+    {
+      type: StepType.CONFIGURE,
+      description: tct(
+        'Initialize the SDK as early as possible, like in the constructor of the [code:App]:',
+        {
+          code: <code />,
+        }
+      ),
+      configurations: [
+        {
+          language: 'csharp',
+          code: getConfigureSnippet(params),
+        },
+      ],
+    },
+  ],
+  verify: () => [
+    {
+      type: StepType.VERIFY,
+      description: t('To verify your set up, you can capture a message with the SDK:'),
+      configurations: [
+        {
+          language: 'csharp',
+          code: 'SentrySdk.CaptureMessage("Hello Sentry");',
+        },
+      ],
+      additionalInfo: tct(
+        "If you don't want to depend on the static class, the SDK registers a client in the DI container. In this case, you can [link:take [code:IHub] as a dependency].",
+        {
+          code: <code />,
+          link: (
+            <ExternalLink href="https://docs.sentry.io/platforms/dotnet/guides/aspnetcore/unit-testing/" />
+          ),
+        }
+      ),
+    },
+    {
+      title: t('Performance Monitoring'),
+      description: t(
+        'You can measure the performance of your code by capturing transactions and spans.'
+      ),
+      configurations: [
+        {
+          language: 'csharp',
+          code: getPerformanceInstrumentationSnippet(),
+        },
+      ],
+      additionalInfo: tct(
+        'Check out [link:the documentation] to learn more about the API and automatic instrumentations.',
+        {
+          link: (
+            <ExternalLink href="https://docs.sentry.io/platforms/dotnet/performance/instrumentation/" />
+          ),
+        }
+      ),
+    },
+    {
+      title: t('Documentation'),
+      description: tct(
+        "Once you've verified the package is initialized properly and sent a test event, consider visiting our [link:complete UWP docs].",
+        {
+          link: (
+            <ExternalLink href="https://docs.sentry.io/platforms/dotnet/guides/uwp/" />
+          ),
+        }
+      ),
+    },
+    {
+      title: t('Samples'),
+      description: (
+        <Fragment>
+          <p>
             {tct(
             {tct(
-              '[link:Multiple samples in the [code:dotnet] SDK repository] [strong:(C#)]',
+              'You can find an example UWP app with Sentry integrated [link:on this GitHub repository].',
               {
               {
                 link: (
                 link: (
-                  <ExternalLink href="https://github.com/getsentry/sentry-dotnet/tree/main/samples" />
+                  <ExternalLink href="https://github.com/getsentry/examples/tree/master/dotnet/UwpCSharp" />
                 ),
                 ),
-                code: <code />,
-                strong: <strong />,
               }
               }
             )}
             )}
-          </ListItem>
-          <ListItem>
-            {tct('[link:Basic F# sample] [strong:(F#)]', {
-              link: <ExternalLink href="https://github.com/sentry-demos/fsharp" />,
-              strong: <strong />,
-            })}
-          </ListItem>
-        </List>
-      </Fragment>
-    ),
-  },
-];
-// Configuration End
+          </p>
+          {t(
+            'See the following examples that demonstrate how to integrate Sentry with various frameworks.'
+          )}
+          <List symbol="bullet">
+            <ListItem>
+              {tct(
+                '[link:Multiple samples in the [code:dotnet] SDK repository] [strong:(C#)]',
+                {
+                  link: (
+                    <ExternalLink href="https://github.com/getsentry/sentry-dotnet/tree/main/samples" />
+                  ),
+                  code: <code />,
+                  strong: <strong />,
+                }
+              )}
+            </ListItem>
+            <ListItem>
+              {tct('[link:Basic F# sample] [strong:(F#)]', {
+                link: <ExternalLink href="https://github.com/sentry-demos/fsharp" />,
+                strong: <strong />,
+              })}
+            </ListItem>
+          </List>
+        </Fragment>
+      ),
+    },
+  ],
+};
 
 
-export function GettingStartedWithUwp({
-  dsn,
-  sourcePackageRegistries,
-  ...props
-}: ModuleProps) {
-  return <Layout steps={steps({dsn, sourcePackageRegistries})} {...props} />;
-}
+const docs: Docs = {
+  onboarding,
+};
 
 
-export default GettingStartedWithUwp;
+export default docs;
 
 
 const AlertWithoutMarginBottom = styled(Alert)`
 const AlertWithoutMarginBottom = styled(Alert)`
   margin-bottom: 0;
   margin-bottom: 0;

+ 28 - 12
static/app/gettingStartedDocs/dotnet/winforms.spec.tsx

@@ -1,18 +1,34 @@
-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 docs from './winforms';
 
 
-import {GettingStartedWithWinForms, steps} from './winforms';
+describe('winforms onboarding docs', function () {
+  it('renders docs correctly', async function () {
+    renderWithOnboardingLayout(docs, {
+      releaseRegistry: {
+        'sentry.dotnet': {
+          version: '1.99.9',
+        },
+      },
+    });
 
 
-describe('GettingStartedWithWinForms', function () {
-  it('renders doc correctly', function () {
-    render(<GettingStartedWithWinForms dsn="test-dsn" projectSlug="test-project" />);
+    // Renders main headings
+    expect(screen.getByRole('heading', {name: 'Install'})).toBeInTheDocument();
+    expect(screen.getByRole('heading', {name: 'Configure SDK'})).toBeInTheDocument();
+    expect(screen.getByRole('heading', {name: 'Verify'})).toBeInTheDocument();
+    expect(
+      screen.getByRole('heading', {name: 'Performance Monitoring'})
+    ).toBeInTheDocument();
+    expect(screen.getByRole('heading', {name: 'Documentation'})).toBeInTheDocument();
+    expect(screen.getByRole('heading', {name: 'Samples'})).toBeInTheDocument();
 
 
-    // Steps
-    for (const step of steps()) {
-      expect(
-        screen.getByRole('heading', {name: step.title ?? StepTitle[step.type]})
-      ).toBeInTheDocument();
-    }
+    // Renders SDK version from registry
+    expect(
+      await screen.findByText(
+        textWithMarkupMatcher(/Install-Package Sentry -Version 1\.99\.9/)
+      )
+    ).toBeInTheDocument();
   });
   });
 });
 });

+ 152 - 161
static/app/gettingStartedDocs/dotnet/winforms.tsx

@@ -5,73 +5,24 @@ import {Alert} from 'sentry/components/alert';
 import ExternalLink from 'sentry/components/links/externalLink';
 import ExternalLink from 'sentry/components/links/externalLink';
 import List from 'sentry/components/list';
 import List from 'sentry/components/list';
 import ListItem from 'sentry/components/list/listItem';
 import ListItem from 'sentry/components/list/listItem';
-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 {StepType} from 'sentry/components/onboarding/gettingStartedDoc/step';
+import type {
+  Docs,
+  DocsParams,
+  OnboardingConfig,
+} from 'sentry/components/onboarding/gettingStartedDoc/types';
 import {t, tct} from 'sentry/locale';
 import {t, tct} from 'sentry/locale';
+import {getPackageVersion} from 'sentry/utils/gettingStartedDocs/getPackageVersion';
 
 
-// Configuration Start
-export const steps = ({
-  dsn,
-  sourcePackageRegistries,
-}: Partial<
-  Pick<ModuleProps, 'dsn' | 'sourcePackageRegistries'>
-> = {}): LayoutProps['steps'] => [
-  {
-    type: StepType.INSTALL,
-    description: (
-      <p>
-        {tct('Install the [strong:NuGet] package:', {
-          strong: <strong />,
-        })}
-      </p>
-    ),
-    configurations: [
-      {
-        language: 'shell',
-        partialLoading: sourcePackageRegistries?.isLoading,
-        code: `
-# Using Package Manager
-Install-Package Sentry -Version ${
-          sourcePackageRegistries?.isLoading
-            ? t('\u2026loading')
-            : sourcePackageRegistries?.data?.['sentry.dotnet']?.version ?? '3.34.0'
-        }
+type Params = DocsParams;
 
 
-# Or using .NET Core CLI
-dotnet add package Sentry -v ${
-          sourcePackageRegistries?.isLoading
-            ? t('\u2026loading')
-            : sourcePackageRegistries?.data?.['sentry.dotnet']?.version ?? '3.34.0'
-        }
-        `,
-      },
-    ],
-    additionalInfo: (
-      <AlertWithoutMarginBottom type="info">
-        {tct(
-          '[strong:Using .NET Framework prior to 4.6.1?] Our legacy SDK supports .NET Framework as early as 3.5.',
-          {strong: <strong />}
-        )}
-      </AlertWithoutMarginBottom>
-    ),
-  },
-  {
-    type: StepType.CONFIGURE,
-    description: (
-      <p>
-        {tct(
-          'Initialize the SDK as early as possible, like in the constructor of the [code:App]:',
-          {
-            code: <code />,
-          }
-        )}
-      </p>
-    ),
-    configurations: [
-      {
-        language: 'csharp',
-        code: `
+const getInstallSnippetPackageManager = (params: Params) => `
+Install-Package Sentry -Version ${getPackageVersion(params, 'sentry.dotnet', '3.34.0')}`;
+
+const getInstallSnippetCoreCli = (params: Params) => `
+dotnet add package Sentry -v ${getPackageVersion(params, 'sentry.dotnet', '3.34.0')}`;
+
+const getConfigureSnippet = (params: Params) => `
 using System;
 using System;
 using System.Windows.Forms;
 using System.Windows.Forms;
 using Sentry;
 using Sentry;
@@ -85,7 +36,7 @@ static class Program
         SentrySdk.Init(o =>
         SentrySdk.Init(o =>
         {
         {
             // Tells which project in Sentry to send events to:
             // Tells which project in Sentry to send events to:
-            o.Dsn = "${dsn}";
+            o.Dsn = "${params.dsn}";
             // When configuring for the first time, to see what the SDK is doing:
             // When configuring for the first time, to see what the SDK is doing:
             o.Debug = true;
             o.Debug = true;
             // Set TracesSampleRate to 1.0 to capture 100% of transactions for performance monitoring.
             // Set TracesSampleRate to 1.0 to capture 100% of transactions for performance monitoring.
@@ -99,30 +50,9 @@ static class Program
 
 
         Application.Run(new Form1());
         Application.Run(new Form1());
     }
     }
-}
-        `,
-      },
-    ],
-  },
-  {
-    type: StepType.VERIFY,
-    description: t('To verify your set up, you can capture a message with the SDK:'),
-    configurations: [
-      {
-        language: 'csharp',
-        code: 'SentrySdk.CaptureMessage("Hello Sentry");',
-      },
-    ],
-  },
-  {
-    title: t('Performance Monitoring'),
-    description: t(
-      'You can measure the performance of your code by capturing transactions and spans.'
-    ),
-    configurations: [
-      {
-        language: 'csharp',
-        code: `
+}`;
+
+const getPerformanceInstrumentationSnippet = () => `
 // Transaction can be started by providing, at minimum, the name and the operation
 // Transaction can be started by providing, at minimum, the name and the operation
 var transaction = SentrySdk.StartTransaction(
 var transaction = SentrySdk.StartTransaction(
   "test-transaction-name",
   "test-transaction-name",
@@ -137,80 +67,141 @@ var span = transaction.StartChild("test-child-operation");
 // ...
 // ...
 
 
 span.Finish(); // Mark the span as finished
 span.Finish(); // Mark the span as finished
-transaction.Finish(); // Mark the transaction as finished and send it to Sentry
-        `,
-      },
-    ],
-    additionalInfo: (
-      <p>
-        {tct(
-          'Check out [link:the documentation] to learn more about the API and automatic instrumentations.',
-          {
-            link: (
-              <ExternalLink href="https://docs.sentry.io/platforms/dotnet/performance/instrumentation/" />
-            ),
-          }
-        )}
-      </p>
-    ),
-  },
-  {
-    title: t('Documentation'),
-    description: (
-      <p>
-        {tct(
-          "Once you've verified the package is initialized properly and sent a test event, consider visiting our [link:complete WinForms docs].",
-          {
-            link: (
-              <ExternalLink href="https://docs.sentry.io/platforms/dotnet/guides/winforms/" />
-            ),
-          }
-        )}
-      </p>
-    ),
-  },
-  {
-    title: t('Samples'),
-    description: (
-      <Fragment>
-        {t(
-          'See the following examples that demonstrate how to integrate Sentry with various frameworks.'
-        )}
-        <List symbol="bullet">
-          <ListItem>
-            {tct(
-              '[link:Multiple samples in the [code:dotnet] SDK repository] [strong:(C#)]',
-              {
-                link: (
-                  <ExternalLink href="https://github.com/getsentry/sentry-dotnet/tree/main/samples" />
-                ),
-                code: <code />,
+transaction.Finish(); // Mark the transaction as finished and send it to Sentry`;
+
+const onboarding: OnboardingConfig = {
+  install: params => [
+    {
+      type: StepType.INSTALL,
+      description: tct('Install the [strong:NuGet] package:', {
+        strong: <strong />,
+      }),
+      configurations: [
+        {
+          partialLoading: params.sourcePackageRegistries.isLoading,
+          code: [
+            {
+              language: 'shell',
+              label: 'Package Manager',
+              value: 'packageManager',
+              code: getInstallSnippetPackageManager(params),
+            },
+            {
+              language: 'shell',
+              label: '.NET Core CLI',
+              value: 'coreCli',
+              code: getInstallSnippetCoreCli(params),
+            },
+          ],
+        },
+      ],
+      additionalInfo: (
+        <AlertWithoutMarginBottom type="info">
+          {tct(
+            '[strong:Using .NET Framework prior to 4.6.1?] Our legacy SDK supports .NET Framework as early as 3.5.',
+            {strong: <strong />}
+          )}
+        </AlertWithoutMarginBottom>
+      ),
+    },
+  ],
+  configure: params => [
+    {
+      type: StepType.CONFIGURE,
+      description: tct(
+        'Initialize the SDK as early as possible, like in the constructor of the [code:App]:',
+        {
+          code: <code />,
+        }
+      ),
+      configurations: [
+        {
+          language: 'csharp',
+          code: getConfigureSnippet(params),
+        },
+      ],
+    },
+  ],
+  verify: () => [
+    {
+      type: StepType.VERIFY,
+      description: t('To verify your set up, you can capture a message with the SDK:'),
+      configurations: [
+        {
+          language: 'csharp',
+          code: 'SentrySdk.CaptureMessage("Hello Sentry");',
+        },
+      ],
+    },
+    {
+      title: t('Performance Monitoring'),
+      description: t(
+        'You can measure the performance of your code by capturing transactions and spans.'
+      ),
+      configurations: [
+        {
+          language: 'csharp',
+          code: getPerformanceInstrumentationSnippet(),
+        },
+      ],
+      additionalInfo: tct(
+        'Check out [link:the documentation] to learn more about the API and automatic instrumentations.',
+        {
+          link: (
+            <ExternalLink href="https://docs.sentry.io/platforms/dotnet/performance/instrumentation/" />
+          ),
+        }
+      ),
+    },
+    {
+      title: t('Documentation'),
+      description: tct(
+        "Once you've verified the package is initialized properly and sent a test event, consider visiting our [link:complete WinForms docs].",
+        {
+          link: (
+            <ExternalLink href="https://docs.sentry.io/platforms/dotnet/guides/winforms/" />
+          ),
+        }
+      ),
+    },
+    {
+      title: t('Samples'),
+      description: (
+        <Fragment>
+          {t(
+            'See the following examples that demonstrate how to integrate Sentry with various frameworks.'
+          )}
+          <List symbol="bullet">
+            <ListItem>
+              {tct(
+                '[link:Multiple samples in the [code:dotnet] SDK repository] [strong:(C#)]',
+                {
+                  link: (
+                    <ExternalLink href="https://github.com/getsentry/sentry-dotnet/tree/main/samples" />
+                  ),
+                  code: <code />,
+                  strong: <strong />,
+                }
+              )}
+            </ListItem>
+            <ListItem>
+              {tct('[link:Basic F# sample] [strong:(F#)]', {
+                link: <ExternalLink href="https://github.com/sentry-demos/fsharp" />,
                 strong: <strong />,
                 strong: <strong />,
-              }
-            )}
-          </ListItem>
-          <ListItem>
-            {tct('[link:Basic F# sample] [strong:(F#)]', {
-              link: <ExternalLink href="https://github.com/sentry-demos/fsharp" />,
-              strong: <strong />,
-            })}
-          </ListItem>
-        </List>
-      </Fragment>
-    ),
-  },
-];
-// Configuration End
-
-export function GettingStartedWithWinForms({
-  dsn,
-  sourcePackageRegistries,
-  ...props
-}: ModuleProps) {
-  return <Layout steps={steps({dsn, sourcePackageRegistries})} {...props} />;
-}
-
-export default GettingStartedWithWinForms;
+              })}
+            </ListItem>
+          </List>
+        </Fragment>
+      ),
+    },
+  ],
+};
+
+const docs: Docs = {
+  onboarding,
+};
+
+export default docs;
 
 
 const AlertWithoutMarginBottom = styled(Alert)`
 const AlertWithoutMarginBottom = styled(Alert)`
   margin-bottom: 0;
   margin-bottom: 0;

+ 28 - 12
static/app/gettingStartedDocs/dotnet/wpf.spec.tsx

@@ -1,18 +1,34 @@
-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 docs from './wpf';
 
 
-import {GettingStartedWithWpf, steps} from './wpf';
+describe('wpf onboarding docs', function () {
+  it('renders docs correctly', async function () {
+    renderWithOnboardingLayout(docs, {
+      releaseRegistry: {
+        'sentry.dotnet': {
+          version: '1.99.9',
+        },
+      },
+    });
 
 
-describe('GettingStartedWithWpf', function () {
-  it('renders doc correctly', function () {
-    render(<GettingStartedWithWpf dsn="test-dsn" projectSlug="test-project" />);
+    // Renders main headings
+    expect(screen.getByRole('heading', {name: 'Install'})).toBeInTheDocument();
+    expect(screen.getByRole('heading', {name: 'Configure SDK'})).toBeInTheDocument();
+    expect(screen.getByRole('heading', {name: 'Verify'})).toBeInTheDocument();
+    expect(
+      screen.getByRole('heading', {name: 'Performance Monitoring'})
+    ).toBeInTheDocument();
+    expect(screen.getByRole('heading', {name: 'Documentation'})).toBeInTheDocument();
+    expect(screen.getByRole('heading', {name: 'Samples'})).toBeInTheDocument();
 
 
-    // Steps
-    for (const step of steps()) {
-      expect(
-        screen.getByRole('heading', {name: step.title ?? StepTitle[step.type]})
-      ).toBeInTheDocument();
-    }
+    // Renders SDK version from registry
+    expect(
+      await screen.findByText(
+        textWithMarkupMatcher(/Install-Package Sentry -Version 1\.99\.9/)
+      )
+    ).toBeInTheDocument();
   });
   });
 });
 });

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