Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion static/app/router/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1469,7 +1469,6 @@ function buildRoutes(): RouteObject[] {
'sentry/views/alerts/workflowEngineRedirectWrappers/metricAlertRuleDetails'
)
),
deprecatedRouteProps: true,
},
{
path: ':projectId/',
Expand Down
129 changes: 51 additions & 78 deletions static/app/views/alerts/rules/metric/details/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,33 @@ import {initializeOrg} from 'sentry-test/initializeOrg';
import {act, render, screen, userEvent} from 'sentry-test/reactTestingLibrary';

import ProjectsStore from 'sentry/stores/projectsStore';
import type {Organization} from 'sentry/types/organization';
import {trackAnalytics} from 'sentry/utils/analytics';
import MetricAlertDetails from 'sentry/views/alerts/rules/metric/details';
import {
Dataset,
EventTypes,
ExtrapolationMode,
type MetricRule,
} from 'sentry/views/alerts/rules/metric/types';
import {SAMPLING_MODE} from 'sentry/views/explore/hooks/useProgressiveQuery';

jest.mock('sentry/utils/analytics');

function getRouteConfig(
organization: Organization,
rule: MetricRule,
query?: Record<string, string>
) {
return {
location: {
pathname: `/organizations/${organization.slug}/alerts/rules/details/${rule.id}/`,
query,
},
route: '/organizations/:orgId/alerts/rules/details/:ruleId/',
};
}

describe('MetricAlertDetails', () => {
const project = ProjectFixture({slug: 'earth', platform: 'javascript'});
beforeEach(() => {
Expand Down Expand Up @@ -48,7 +64,7 @@ describe('MetricAlertDetails', () => {
});

it('renders', async () => {
const {organization, routerProps} = initializeOrg();
const {organization} = initializeOrg();
const incident = IncidentFixture();
const rule = MetricRuleFixture({
projects: [project.slug],
Expand All @@ -71,16 +87,10 @@ describe('MetricAlertDetails', () => {
body: [incident],
});

render(
<MetricAlertDetails
organization={organization}
{...routerProps}
params={{ruleId: rule.id}}
/>,
{
organization,
}
);
render(<MetricAlertDetails />, {
organization,
initialRouterConfig: getRouteConfig(organization, rule),
});

expect(await screen.findByText(rule.name)).toBeInTheDocument();
expect(screen.getByText('Change alert status to Resolved')).toBeInTheDocument();
Expand All @@ -98,7 +108,7 @@ describe('MetricAlertDetails', () => {
});

it('renders selected incident', async () => {
const {organization, router, routerProps} = initializeOrg();
const {organization} = initializeOrg();
const rule = MetricRuleFixture({projects: [project.slug]});
const incident = IncidentFixture();
const promptResponse = {
Expand Down Expand Up @@ -127,17 +137,10 @@ describe('MetricAlertDetails', () => {
body: [GroupFixture()],
});

render(
<MetricAlertDetails
organization={organization}
{...routerProps}
location={{...router.location, query: {alert: incident.id}}}
params={{ruleId: rule.id}}
/>,
{
organization,
}
);
render(<MetricAlertDetails />, {
organization,
initialRouterConfig: getRouteConfig(organization, rule, {alert: incident.id}),
});

expect(await screen.findByText(rule.name)).toBeInTheDocument();
// Related issues
Expand All @@ -154,7 +157,7 @@ describe('MetricAlertDetails', () => {
});

it('renders mute button for metric alert', async () => {
const {organization, routerProps} = initializeOrg();
const {organization} = initializeOrg();
const incident = IncidentFixture();
const rule = MetricRuleFixture({
projects: [project.slug],
Expand Down Expand Up @@ -185,16 +188,10 @@ describe('MetricAlertDetails', () => {
method: 'DELETE',
});

render(
<MetricAlertDetails
{...routerProps}
organization={organization}
params={{ruleId: rule.id}}
/>,
{
organization,
}
);
render(<MetricAlertDetails />, {
organization,
initialRouterConfig: getRouteConfig(organization, rule),
});

expect(await screen.findByText('Mute for everyone')).toBeInTheDocument();

Expand All @@ -208,7 +205,7 @@ describe('MetricAlertDetails', () => {
});

it('renders open in discover button with dataset=errors for is:unresolved query', async () => {
const {organization, routerProps} = initializeOrg({
const {organization} = initializeOrg({
organization: {features: ['discover-basic']},
});
const rule = MetricRuleFixture({
Expand All @@ -230,16 +227,10 @@ describe('MetricAlertDetails', () => {
body: [],
});

render(
<MetricAlertDetails
organization={organization}
{...routerProps}
params={{ruleId: rule.id}}
/>,
{
organization,
}
);
render(<MetricAlertDetails />, {
organization,
initialRouterConfig: getRouteConfig(organization, rule),
});

expect(await screen.findByText(rule.name)).toBeInTheDocument();

Expand All @@ -250,7 +241,7 @@ describe('MetricAlertDetails', () => {
});

it('disables duplicate button if deprecation flag is on', async () => {
const {organization, routerProps} = initializeOrg({
const {organization} = initializeOrg({
organization: {
features: ['discover-basic', 'discover-saved-queries-deprecation'],
},
Expand All @@ -277,16 +268,10 @@ describe('MetricAlertDetails', () => {
body: [],
});

render(
<MetricAlertDetails
organization={organization}
{...routerProps}
params={{ruleId: rule.id}}
/>,
{
organization,
}
);
render(<MetricAlertDetails />, {
organization,
initialRouterConfig: getRouteConfig(organization, rule),
});

expect(await screen.findByText(rule.name)).toBeInTheDocument();

Expand All @@ -297,7 +282,7 @@ describe('MetricAlertDetails', () => {
});

it('uses SERVER_WEIGHTED extrapolation mode when alert has it configured', async () => {
const {organization, routerProps} = initializeOrg();
const {organization} = initializeOrg();
const ruleWithExtrapolation = MetricRuleFixture({
projects: [project.slug],
dataset: Dataset.EVENTS_ANALYTICS_PLATFORM,
Expand All @@ -322,16 +307,10 @@ describe('MetricAlertDetails', () => {
body: EventsStatsFixture(),
});

render(
<MetricAlertDetails
organization={organization}
{...routerProps}
params={{ruleId: ruleWithExtrapolation.id}}
/>,
{
organization,
}
);
render(<MetricAlertDetails />, {
organization,
initialRouterConfig: getRouteConfig(organization, ruleWithExtrapolation),
});

expect(await screen.findByText(ruleWithExtrapolation.name)).toBeInTheDocument();

Expand All @@ -348,7 +327,7 @@ describe('MetricAlertDetails', () => {
});

it('uses NONE extrapolation mode when alert has it configured', async () => {
const {organization, routerProps} = initializeOrg();
const {organization} = initializeOrg();
const ruleWithNoExtrapolation = MetricRuleFixture({
projects: [project.slug],
dataset: Dataset.EVENTS_ANALYTICS_PLATFORM,
Expand All @@ -373,16 +352,10 @@ describe('MetricAlertDetails', () => {
body: EventsStatsFixture(),
});

render(
<MetricAlertDetails
organization={organization}
{...routerProps}
params={{ruleId: ruleWithNoExtrapolation.id}}
/>,
{
organization,
}
);
render(<MetricAlertDetails />, {
organization,
initialRouterConfig: getRouteConfig(organization, ruleWithNoExtrapolation),
});

expect(await screen.findByText(ruleWithNoExtrapolation.name)).toBeInTheDocument();

Expand Down
44 changes: 29 additions & 15 deletions static/app/views/alerts/rules/metric/details/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,16 @@ import * as Layout from 'sentry/components/layouts/thirds';
import PageFiltersContainer from 'sentry/components/organizations/pageFilters/container';
import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
import {t} from 'sentry/locale';
import type {RouteComponentProps} from 'sentry/types/legacyReactRouter';
import type {Organization} from 'sentry/types/organization';
import type {Project} from 'sentry/types/project';
import {trackAnalytics} from 'sentry/utils/analytics';
import {getUtcDateString} from 'sentry/utils/dates';
import type RequestError from 'sentry/utils/requestError/requestError';
import withApi from 'sentry/utils/withApi';
import withOrganization from 'sentry/utils/withOrganization';
import withProjects from 'sentry/utils/withProjects';
import useApi from 'sentry/utils/useApi';
import {useLocation} from 'sentry/utils/useLocation';
import useOrganization from 'sentry/utils/useOrganization';
import {useParams} from 'sentry/utils/useParams';
import useProjects from 'sentry/utils/useProjects';
import type {MetricRule} from 'sentry/views/alerts/rules/metric/types';
import {
AlertRuleComparisonType,
Expand All @@ -39,11 +40,12 @@ import {ALERT_RULE_STATUS, TIME_OPTIONS, TIME_WINDOWS} from './constants';
import DetailsHeader from './header';
import {buildMetricGraphDateRange} from './utils';

interface Props extends RouteComponentProps<{ruleId: string}> {
interface Props {
api: Client;
location: Location;
organization: Organization;
projects: Project[];
ruleId: string;
loadingProjects?: boolean;
}

Expand Down Expand Up @@ -84,19 +86,19 @@ class MetricAlertDetails extends Component<Props, State> {
if (
!isEqual(prevQuery, nextQuery) ||
prevProps.organization.slug !== this.props.organization.slug ||
prevProps.params.ruleId !== this.props.params.ruleId
prevProps.ruleId !== this.props.ruleId
) {
this.fetchData();
this.trackView();
}
}

trackView() {
const {params, organization, location} = this.props;
const {ruleId, organization, location} = this.props;

trackAnalytics('alert_rule_details.viewed', {
organization,
rule_id: parseInt(params.ruleId, 10),
rule_id: parseInt(ruleId, 10),
alert: (location.query.alert as string) ?? '',
has_chartcuterie: organization.features
.includes('metric-alert-chartcuterie')
Expand Down Expand Up @@ -190,12 +192,7 @@ class MetricAlertDetails extends Component<Props, State> {
};

fetchData = async () => {
const {
api,
organization,
params: {ruleId},
location,
} = this.props;
const {api, organization, ruleId, location} = this.props;

this.setState({isLoading: true, hasError: false});

Expand Down Expand Up @@ -310,4 +307,21 @@ class MetricAlertDetails extends Component<Props, State> {
}
}

export default withApi(withOrganization(withProjects(MetricAlertDetails)));
export default function MetricAlertDetailsWrapper() {
const api = useApi();
const location = useLocation();
const {ruleId} = useParams<{ruleId: string}>();
const organization = useOrganization();
const {projects, initiallyLoaded} = useProjects();

return (
<MetricAlertDetails
api={api}
location={location}
organization={organization}
ruleId={ruleId}
projects={projects}
loadingProjects={!initiallyLoaded}
/>
);
}
Loading