Skip to content

Commit

Permalink
fix(onboarding): Fix integration issues (#76539)
Browse files Browse the repository at this point in the history
  • Loading branch information
priscilawebdev committed Aug 27, 2024
1 parent f56a98f commit 853b937
Show file tree
Hide file tree
Showing 8 changed files with 243 additions and 180 deletions.
10 changes: 3 additions & 7 deletions static/app/views/onboarding/integrationSetup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {motion} from 'framer-motion';

import {openInviteMembersModal} from 'sentry/actionCreators/modal';
import {Alert} from 'sentry/components/alert';
import {Button, LinkButton} from 'sentry/components/button';
import {Button} from 'sentry/components/button';
import ButtonBar from 'sentry/components/buttonBar';
import ExternalLink from 'sentry/components/links/externalLink';
import LoadingError from 'sentry/components/loadingError';
Expand Down Expand Up @@ -141,12 +141,8 @@ function IntegrationSetup(props: Props) {
analyticsParams={{view: 'onboarding', already_installed: false}}
modalParams={{projectId: project.id}}
/>
<LinkButton
<Button
size="sm"
to={{
pathname: window.location.pathname,
query: {manual: '1'},
}}
onClick={() => {
props.onClickManualSetup?.();
trackIntegrationAnalytics('integrations.switch_manual_sdk_setup', {
Expand All @@ -158,7 +154,7 @@ function IntegrationSetup(props: Props) {
}}
>
{t('Manual Setup')}
</LinkButton>
</Button>
</StyledButtonBar>
</DocsWrapper>
</Fragment>
Expand Down
4 changes: 2 additions & 2 deletions static/app/views/onboarding/setupDocs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ function SetupDocs({location, recentCreatedProject: project}: StepProps) {
return null;
}

const platformName = currentPlatform?.name ?? '';
const integrationSlug = project?.platform && platformToIntegrationMap[project.platform];
const platformName = currentPlatform.name;
const integrationSlug = project.platform && platformToIntegrationMap[project.platform];
const showIntegrationOnboarding = integrationSlug && !integrationUseManualSetup;

return (
Expand Down
138 changes: 65 additions & 73 deletions static/app/views/projectInstall/platform.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import {render, screen} from 'sentry-test/reactTestingLibrary';

import ConfigStore from 'sentry/stores/configStore';
import ProjectsStore from 'sentry/stores/projectsStore';
import type {Project} from 'sentry/types/project';
import type {PlatformIntegration, PlatformKey, Project} from 'sentry/types/project';
import {ProjectInstallPlatform} from 'sentry/views/projectInstall/platform';

type ProjectWithBadPlatform = Omit<Project, 'platform'> & {
platform: string;
};

function mockProjectApiResponses(projects: Array<Project | ProjectWithBadPlatform>) {
function mockProjectApiResponses(projects: (Project | ProjectWithBadPlatform)[]) {
MockApiClient.addMockResponse({
method: 'GET',
url: '/organizations/org-slug/projects/',
Expand Down Expand Up @@ -58,106 +58,81 @@ describe('ProjectInstallPlatform', function () {
});

it('should render NotFound if no matching integration/platform', async function () {
const routeParams = {
projectId: ProjectFixture().slug,
};
const {organization, routerProps, project, router} = initializeOrg({
router: {
location: {
query: {},
params: {
projectId: ProjectFixture().slug,
},
params: routeParams,
},
});

mockProjectApiResponses([{...project, platform: 'lua'}]);

render(<ProjectInstallPlatform {...routerProps} />, {
organization,
router,
});
render(
<ProjectInstallPlatform
{...routerProps}
loading={false}
platform={undefined}
currentPlatformKey={'lua' as PlatformKey}
project={project}
/>,
{
organization,
router,
}
);

expect(await screen.findByText('Page Not Found')).toBeInTheDocument();
});

it('should display info for a non-supported platform', async function () {
const routeParams = {
projectId: ProjectFixture().slug,
};

const {organization, routerProps, project} = initializeOrg({
router: {
location: {
query: {},
params: {
projectId: ProjectFixture().slug,
},
params: routeParams,
},
});

// this is needed because we don't handle a loading state in the UI
ProjectsStore.loadInitialData([{...project, platform: 'other'}]);

mockProjectApiResponses([{...project, platform: 'other'}]);

render(<ProjectInstallPlatform {...routerProps} />, {
organization,
});

expect(
await screen.findByText(/We cannot provide instructions for 'Other' projects/)
).toBeInTheDocument();
});

it('should render getting started docs for correct platform', async function () {
const project = ProjectFixture({platform: 'javascript'});

const routeParams = {
projectId: project.slug,
platform: 'python',
const platform: PlatformIntegration = {
id: 'other',
name: 'Other',
link: 'https://docs.sentry.io/platforms/',
type: 'language',
language: 'other',
};

const {routerProps, router} = initializeOrg({
router: {
location: {
query: {},
},
params: routeParams,
},
});

ProjectsStore.loadInitialData([project]);

mockProjectApiResponses([project]);

render(<ProjectInstallPlatform {...routerProps} />, {
router,
});
// this is needed because we don't handle a loading state in the UI
ProjectsStore.loadInitialData([{...project, platform: platform.id}]);

mockProjectApiResponses([{...project, platform: platform.id}]);

render(
<ProjectInstallPlatform
{...routerProps}
loading={false}
platform={platform}
project={project}
currentPlatformKey={platform.id}
/>,
{
organization,
}
);

expect(
await screen.findByRole('heading', {
name: 'Configure Browser JavaScript SDK',
})
await screen.findByText(/We cannot provide instructions for 'Other' projects/)
).toBeInTheDocument();

expect(await screen.getByText('Take me to Issues')).toBeInTheDocument();
expect(await screen.getByText('Take me to Performance')).toBeInTheDocument();
expect(await screen.getByText('Take me to Session Replay')).toBeInTheDocument();
});

it('should not render performance/session replay buttons for errors only self-hosted', async function () {
const project = ProjectFixture({platform: 'javascript'});

const routeParams = {
projectId: project.slug,
platform: 'python',
};

const {routerProps, router} = initializeOrg({
router: {
location: {
query: {},
params: {
projectId: project.slug,
},
params: routeParams,
},
});

Expand All @@ -166,9 +141,26 @@ describe('ProjectInstallPlatform', function () {
mockProjectApiResponses([project]);
ConfigStore.set('isSelfHostedErrorsOnly', true);

render(<ProjectInstallPlatform {...routerProps} />, {
router,
});
const platform: PlatformIntegration = {
id: 'javascript',
name: 'Browser JavaScript',
type: 'language',
language: 'javascript',
link: 'https://docs.sentry.io/platforms/javascript/',
};

render(
<ProjectInstallPlatform
{...routerProps}
project={project}
loading={false}
platform={platform}
currentPlatformKey={platform.id}
/>,
{
router,
}
);

expect(
await screen.findByRole('heading', {
Expand Down
50 changes: 18 additions & 32 deletions static/app/views/projectInstall/platform.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {Fragment, useCallback, useContext, useEffect, useMemo, useState} from 'react';
import type {RouteComponentProps} from 'react-router';
import styled from '@emotion/styled';
import omit from 'lodash/omit';

Expand All @@ -23,55 +22,42 @@ import ConfigStore from 'sentry/stores/configStore';
import {space} from 'sentry/styles/space';
import type {IssueAlertRule} from 'sentry/types/alerts';
import type {OnboardingSelectedSDK} from 'sentry/types/onboarding';
import type {PlatformIntegration, PlatformKey} from 'sentry/types/project';
import type {PlatformIntegration, PlatformKey, Project} from 'sentry/types/project';
import {trackAnalytics} from 'sentry/utils/analytics';
import {useApiQuery} from 'sentry/utils/queryClient';
import {decodeList} from 'sentry/utils/queryString';
import {useLocation} from 'sentry/utils/useLocation';
import useOrganization from 'sentry/utils/useOrganization';
import useProjects from 'sentry/utils/useProjects';
import {SetupDocsLoader} from 'sentry/views/onboarding/setupDocsLoader';
import {GettingStartedWithProjectContext} from 'sentry/views/projects/gettingStartedWithProjectContext';

import {OtherPlatformsInfo} from './otherPlatformsInfo';
import {PlatformDocHeader} from './platformDocHeader';

const allPlatforms: PlatformIntegration[] = [
...platforms,
{
id: 'other',
name: t('Other'),
link: 'https://docs.sentry.io/platforms/',
type: 'language',
language: 'other',
},
];

const ProductUnavailableCTAHook = HookOrDefault({
hookName: 'component:product-unavailable-cta',
});

type Props = RouteComponentProps<{projectId: string}, {}>;
type Props = {
currentPlatformKey: PlatformKey;
loading: boolean;
platform: PlatformIntegration | undefined;
project: Project | undefined;
};

export function ProjectInstallPlatform({location, params}: Props) {
export function ProjectInstallPlatform({
loading,
project,
currentPlatformKey,
platform: currentPlatform,
}: Props) {
const organization = useOrganization();
const location = useLocation();
const gettingStartedWithProjectContext = useContext(GettingStartedWithProjectContext);

const isSelfHosted = ConfigStore.get('isSelfHosted');
const isSelfHostedErrorsOnly = ConfigStore.get('isSelfHostedErrorsOnly');

const {projects, initiallyLoaded} = useProjects({
slugs: [params.projectId],
orgId: organization.slug,
});

const loadingProjects = !initiallyLoaded;
const project = !loadingProjects
? projects.find(proj => proj.slug === params.projectId)
: undefined;

const currentPlatformKey = project?.platform ?? 'other';
const currentPlatform = allPlatforms.find(p => p.id === currentPlatformKey);

const [showLoaderOnboarding, setShowLoaderOnboarding] = useState(
currentPlatform?.id === 'javascript'
);
Expand Down Expand Up @@ -227,7 +213,7 @@ export function ProjectInstallPlatform({location, params}: Props) {
<StyledButtonBar gap={1}>
<LinkButton
priority="primary"
busy={loadingProjects}
busy={loading}
to={{
pathname: issueStreamLink,
query: {
Expand All @@ -240,7 +226,7 @@ export function ProjectInstallPlatform({location, params}: Props) {
</LinkButton>
{!isSelfHostedErrorsOnly && (
<LinkButton
busy={loadingProjects}
busy={loading}
to={{
pathname: performanceOverviewLink,
query: {
Expand All @@ -253,7 +239,7 @@ export function ProjectInstallPlatform({location, params}: Props) {
)}
{!isSelfHostedErrorsOnly && showReplayButton && (
<LinkButton
busy={loadingProjects}
busy={loading}
to={{
pathname: replayLink,
query: {
Expand Down
7 changes: 5 additions & 2 deletions static/app/views/projectInstall/platformDocHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ import useRouter from 'sentry/utils/useRouter';
type Props = {
platform: Platform;
projectSlug: Project['slug'];
title?: string;
};

export function PlatformDocHeader({platform, projectSlug}: Props) {
export function PlatformDocHeader({platform, projectSlug, title}: Props) {
const organization = useOrganization();
const api = useApi();
const router = useRouter();
Expand Down Expand Up @@ -91,7 +92,9 @@ export function PlatformDocHeader({platform, projectSlug}: Props) {

return (
<StyledPageHeader>
<h2>{t('Configure %(platform)s SDK', {platform: platform.name ?? 'other'})}</h2>
<h2>
{title ?? t('Configure %(platform)s SDK', {platform: platform.name ?? 'other'})}
</h2>
<ButtonBar gap={1}>
<Confirm
bypass={!shallProjectBeDeleted}
Expand Down
Loading

0 comments on commit 853b937

Please sign in to comment.