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
2 changes: 1 addition & 1 deletion static/app/views/explore/metrics/metricPanel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export function MetricPanel({traceMetric, queryIndex}: MetricPanelProps) {
});

return (
<Panel>
<Panel data-test-id="metric-panel">
<PanelBody>
{orientation === 'right' ? (
<SideBySideOrientation
Expand Down
1 change: 1 addition & 0 deletions static/app/views/explore/metrics/metricToolbar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export function MetricToolbar({traceMetric, queryIndex}: MetricToolbarProps) {
align="center"
gap="md"
columns={`24px auto auto auto 1fr ${metricQueries.length > 1 ? '40px' : '0'}`}
data-test-id="metric-toolbar"
>
<VisualizeLabel
index={queryIndex}
Expand Down
220 changes: 220 additions & 0 deletions static/app/views/explore/metrics/metricsTab.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
import {OrganizationFixture} from 'sentry-fixture/organization';
import {ProjectFixture} from 'sentry-fixture/project';

import {
render,
screen,
userEvent,
waitFor,
within,
} from 'sentry-test/reactTestingLibrary';

import {MetricsTabContent} from 'sentry/views/explore/metrics/metricsTab';
import {MultiMetricsQueryParamsProvider} from 'sentry/views/explore/metrics/multiMetricsQueryParams';
import type {PickableDays} from 'sentry/views/explore/utils';

const datePageFilterProps: PickableDays = {
defaultPeriod: '7d' as const,
maxPickableDays: 7,
relativeOptions: ({arbitraryOptions}) => ({
...arbitraryOptions,
'1h': 'Last hour',
'24h': 'Last 24 hours',
'7d': 'Last 7 days',
}),
};

describe('MetricsTabContent', () => {
const organization = OrganizationFixture({
features: ['tracemetrics-enabled'],
});
const project = ProjectFixture({id: '1'});

function ProviderWrapper({children}: {children: React.ReactNode}) {
return <MultiMetricsQueryParamsProvider>{children}</MultiMetricsQueryParamsProvider>;
}

const initialRouterConfig = {
location: {
pathname: `/organizations/${organization.slug}/explore/metrics/`,
query: {
start: '2025-04-10T14%3A37%3A55',
end: '2025-04-10T20%3A04%3A51',
project: project.id,
},
},
route: '/organizations/:orgId/explore/metrics/',
};

beforeEach(() => {
MockApiClient.clearMockResponses();

MockApiClient.addMockResponse({
url: `/organizations/${organization.slug}/events/`,
method: 'GET',
body: {
data: [
{'metric.name': 'foo', 'metric.type': 'counter', 'count(metric.name)': 1},
{'metric.name': 'bar', 'metric.type': 'distribution', 'count(metric.name)': 2},
{'metric.name': 'baz', 'metric.type': 'gauge', 'count(metric.name)': 3},
],
meta: {
fields: {},
units: {},
isMetricsData: false,
isMetricsExtractedData: false,
tips: {},
datasetReason: 'unchanged',
dataset: 'tracemetrics',
dataScanned: 'full',
accuracy: {
confidence: [],
},
},
confidence: [],
},
match: [
MockApiClient.matchQuery({
dataset: 'tracemetrics',
referrer: 'api.explore.metric-options',
}),
],
});

MockApiClient.addMockResponse({
url: `/organizations/${organization.slug}/events/`,
method: 'GET',
body: {
data: [],
meta: {
fields: {},
units: {},
isMetricsData: false,
isMetricsExtractedData: false,
tips: {},
datasetReason: 'unchanged',
dataset: 'tracemetrics',
dataScanned: 'full',
accuracy: {
confidence: [],
},
},
confidence: [],
},
match: [
MockApiClient.matchQuery({
dataset: 'tracemetrics',
referrer: 'api.explore.metric-aggregates-table',
}),
],
});

MockApiClient.addMockResponse({
url: `/organizations/${organization.slug}/events/`,
method: 'GET',
body: {
data: [],
meta: {
fields: {},
units: {},
isMetricsData: false,
isMetricsExtractedData: false,
tips: {},
datasetReason: 'unchanged',
dataset: 'tracemetrics',
dataScanned: 'full',
accuracy: {
confidence: [],
},
},
confidence: [],
},
match: [
MockApiClient.matchQuery({
dataset: 'tracemetrics',
referrer: 'api.explore.metric-samples-table',
}),
],
});

MockApiClient.addMockResponse({
url: `/organizations/${organization.slug}/events-stats/`,
method: 'GET',
body: {},
});

MockApiClient.addMockResponse({
url: `/organizations/${organization.slug}/recent-searches/`,
method: 'GET',
body: [],
});

MockApiClient.addMockResponse({
url: `/subscriptions/${organization.slug}/`,
method: 'GET',
body: {},
});

MockApiClient.addMockResponse({
url: `/organizations/${organization.slug}/trace-items/attributes/`,
method: 'GET',
body: [],
});

MockApiClient.addMockResponse({
url: `/organizations/${organization.slug}/stats_v2/`,
method: 'GET',
body: {},
});
});

it('should add a metric when Add Metric button is clicked', async () => {
render(
<ProviderWrapper>
<MetricsTabContent {...datePageFilterProps} />
</ProviderWrapper>,
{
initialRouterConfig,
organization,
}
);

let toolbars = screen.getAllByTestId('metric-toolbar');
expect(toolbars).toHaveLength(1);
// have to wait for the response to load
await waitFor(() => {
// selects the first metric available - sorted alphanumerically
expect(within(toolbars[0]!).getByRole('button', {name: 'bar'})).toBeInTheDocument();
});
expect(screen.getAllByTestId('metric-panel')).toHaveLength(1);

let addButton = screen.getByRole('button', {name: 'Add Metric'});
expect(addButton).toBeInTheDocument();
expect(addButton).toBeEnabled();

await userEvent.click(addButton);

toolbars = screen.getAllByTestId('metric-toolbar');
expect(toolbars).toHaveLength(2);
// selects the first metric available - sorted alphanumerically
expect(within(toolbars[1]!).getByRole('button', {name: 'bar'})).toBeInTheDocument();
expect(screen.getAllByTestId('metric-panel')).toHaveLength(2);

// change the second metric from bar to foo
await userEvent.click(within(toolbars[1]!).getByRole('button', {name: 'bar'}));
await userEvent.click(within(toolbars[1]!).getByRole('option', {name: 'foo'}));
expect(within(toolbars[1]!).getByRole('button', {name: 'foo'})).toBeInTheDocument();

addButton = screen.getByRole('button', {name: 'Add Metric'});
expect(addButton).toBeInTheDocument();
expect(addButton).toBeEnabled();

await userEvent.click(addButton);

toolbars = screen.getAllByTestId('metric-toolbar');
expect(toolbars).toHaveLength(3);
// selects the first metric available - sorted alphanumerically
expect(within(toolbars[2]!).getByRole('button', {name: 'bar'})).toBeInTheDocument();
expect(screen.getAllByTestId('metric-panel')).toHaveLength(3);
});
});
Loading