Browse Source

feat(opsgenie): plugin migration frontend (#55355)

Add functionality to the button that begins the Opsgenie plugin
migration.

Fixes ER-1684
Michelle Fu 1 year ago
parent
commit
b437ae068f

+ 30 - 0
fixtures/js-stubs/opsgenieIntegration.tsx

@@ -0,0 +1,30 @@
+import {OrganizationIntegration} from 'sentry/types';
+
+export function OpsgenieIntegration(
+  params: Partial<OrganizationIntegration> = {}
+): OrganizationIntegration {
+  return {
+    id: '1',
+    name: 'hello-world',
+    icon: null,
+    domainName: 'hello-world.app.opsgenie.com',
+    accountType: null,
+    status: 'active',
+    provider: {
+      key: 'opsgenie',
+      slug: 'opsgenie',
+      name: 'Opsgenie',
+      canAdd: true,
+      canDisable: false,
+      features: ['enterprise-alert-rule', 'enterprise-incident-management'],
+      aspects: {},
+    },
+    configOrganization: [],
+    configData: {},
+    externalId: 'hello-world',
+    organizationId: '',
+    organizationIntegrationStatus: 'active',
+    gracePeriodEnd: '',
+    ...params,
+  };
+}

+ 33 - 0
fixtures/js-stubs/opsgenieIntegrationProvider.tsx

@@ -0,0 +1,33 @@
+import {IntegrationProvider} from 'sentry/types';
+
+export function OpsgenieIntegrationProvider(
+  params: Partial<IntegrationProvider> = {}
+): IntegrationProvider {
+  return {
+    key: 'opsgenie',
+    slug: 'opsgenie',
+    name: 'Opsgenie (Integration)',
+    metadata: {
+      description: 'hi',
+      features: [
+        {description: '*markdown* feature description', featureGate: '', featureId: 3},
+      ],
+      author: 'The Sentry Team',
+      noun: 'Installation',
+      issue_url:
+        'https://github.com/getsentry/sentry/issues/new?assignees=&labels=Component:%20Integrations&template=bug.yml&title=Integration%20Problem',
+      source_url:
+        'https://github.com/getsentry/sentry/tree/master/src/sentry/integrations/opsgenie',
+      aspects: {},
+    },
+    canAdd: true,
+    canDisable: false,
+    features: ['alert-rule', 'incident-management'],
+    setupDialog: {
+      url: '/organizations/sentry/integrations/opsgenie/setup/',
+      width: 600,
+      height: 600,
+    },
+    ...params,
+  };
+}

+ 2 - 0
fixtures/js-stubs/types.tsx

@@ -98,6 +98,8 @@ type TestStubFixtures = {
   MetricsTotalCountByReleaseIn24h: SimpleStub;
   MissingMembers: OverridableStubList;
   NotificationDefaults: SimpleStub;
+  OpsgenieIntegration: OverridableStub;
+  OpsgenieIntegrationProvider: OverridableStub;
   OrgOwnedApps: SimpleStub;
   OrgRoleList: OverridableStub;
   Organization: OverridableStub;

+ 74 - 0
static/app/views/settings/organizationIntegrations/configureIntegration.spec.tsx

@@ -0,0 +1,74 @@
+import {
+  render,
+  renderGlobalModal,
+  screen,
+  userEvent,
+} from 'sentry-test/reactTestingLibrary';
+
+import ConfigureIntegration from 'sentry/views/settings/organizationIntegrations/configureIntegration';
+
+describe('OpsgenieMigrationButton', function () {
+  const org = TestStubs.Organization({
+    access: ['org:integrations', 'org:write'],
+  });
+  const integrationId = '1';
+  it('Migrate Plugin button hits migration endpoint', async function () {
+    org.features.push('integrations-opsgenie-migration');
+    MockApiClient.addMockResponse({
+      url: `/organizations/${org.slug}/config/integrations/`,
+      body: {
+        providers: [TestStubs.OpsgenieIntegrationProvider()],
+      },
+    });
+
+    MockApiClient.addMockResponse({
+      url: `/organizations/${org.slug}/integrations/${integrationId}/`,
+      body: TestStubs.OpsgenieIntegration(),
+    });
+
+    MockApiClient.addMockResponse({
+      url: `/organizations/${org.slug}/plugins/configs/`,
+      body: [
+        {
+          id: 'opsgenie',
+          name: 'Opsgenie',
+          slug: 'opsgenie',
+          projectList: [
+            {
+              projectId: 2,
+              projectSlug: 'python',
+              projectName: 'python',
+              enabled: true,
+              configured: true,
+              projectPlatform: 'python',
+            },
+          ],
+        },
+      ],
+    });
+
+    const onConfirmCall = MockApiClient.addMockResponse({
+      url: `/organizations/${org.slug}/integrations/${integrationId}/migrate-opsgenie/`,
+      method: 'PUT',
+    });
+
+    render(
+      <ConfigureIntegration
+        {...TestStubs.routeComponentProps()}
+        params={{integrationId, providerKey: 'opsgenie'}}
+        organization={org}
+        location={TestStubs.location({query: {}})}
+      />
+    );
+    renderGlobalModal();
+    expect(screen.getByRole('button', {name: 'Migrate Plugin'})).toBeEnabled();
+
+    await userEvent.click(screen.getByRole('button', {name: 'Migrate Plugin'}));
+
+    expect(screen.queryByRole('button', {name: 'Confirm'})).toBeInTheDocument();
+
+    await userEvent.click(screen.getByRole('button', {name: 'Confirm'}));
+
+    expect(onConfirmCall).toHaveBeenCalled();
+  });
+});

+ 21 - 7
static/app/views/settings/organizationIntegrations/configureIntegration.tsx

@@ -166,13 +166,27 @@ class ConfigureIntegration extends DeprecatedAsyncView<Props, State> {
     }
   };
 
-  handleOpsgenieMigration = () => {
-    this.setState(
-      {
-        plugins: (this.state.plugins || []).filter(({id}) => id === 'opsgenie'),
-      },
-      () => addSuccessMessage(t("This doesn't do anything yet!"))
-    );
+  handleOpsgenieMigration = async () => {
+    const {
+      organization,
+      params: {integrationId},
+    } = this.props;
+    try {
+      await this.api.requestPromise(
+        `/organizations/${organization.slug}/integrations/${integrationId}/migrate-opsgenie/`,
+        {
+          method: 'PUT',
+        }
+      );
+      this.setState(
+        {
+          plugins: (this.state.plugins || []).filter(({id}) => id === 'opsgenie'),
+        },
+        () => addSuccessMessage(t('Migration in progress.'))
+      );
+    } catch (error) {
+      addErrorMessage(t('Something went wrong! Please try again.'));
+    }
   };
 
   isInstalledOpsgeniePlugin = (plugin: PluginWithProjectList) => {