1- import { mapMetricUnitToFieldType } from 'sentry/views/explore/metrics/utils' ;
1+ import qs from 'query-string' ;
2+ import { OrganizationFixture } from 'sentry-fixture/organization' ;
3+
4+ import { SavedQuery } from 'sentry/views/explore/hooks/useGetSavedQueries' ;
5+ import { decodeMetricsQueryParams } from 'sentry/views/explore/metrics/metricQuery' ;
6+ import {
7+ getMetricsUrlFromSavedQueryUrl ,
8+ mapMetricUnitToFieldType ,
9+ } from 'sentry/views/explore/metrics/utils' ;
10+ import { Mode } from 'sentry/views/explore/queryParams/mode' ;
211
312describe ( 'mapMetricUnitToFieldType' , ( ) => {
413 it . each ( [
@@ -18,3 +27,144 @@ describe('mapMetricUnitToFieldType', () => {
1827 expect ( mapMetricUnitToFieldType ( unit ) ) . toEqual ( expected ) ;
1928 } ) ;
2029} ) ;
30+
31+ describe ( 'getMetricsUrlFromSavedQueryUrl' , ( ) => {
32+ const organization = OrganizationFixture ( ) ;
33+
34+ function decodeMetricFromUrl ( url : string ) {
35+ const query = qs . parseUrl ( url ) . query ;
36+ const metricParam = Array . isArray ( query . metric ) ? query . metric [ 0 ] : query . metric ;
37+ return decodeMetricsQueryParams ( metricParam ! ) ;
38+ }
39+
40+ it ( 'decodes orderby into sortBys' , ( ) => {
41+ const url = getMetricsUrlFromSavedQueryUrl ( {
42+ organization,
43+ savedQuery : new SavedQuery ( {
44+ id : 1 ,
45+ interval : '5m' ,
46+ name : 'test query' ,
47+ projects : [ ] ,
48+ dataset : 'metrics' ,
49+ dateAdded : '2025-01-01T00:00:00.000000Z' ,
50+ dateUpdated : '2025-01-01T00:00:00.000000Z' ,
51+ lastVisited : '2025-01-01T00:00:00.000000Z' ,
52+ starred : false ,
53+ position : null ,
54+ query : [
55+ {
56+ mode : Mode . SAMPLES ,
57+ query : '' ,
58+ fields : [ 'id' , 'timestamp' ] ,
59+ orderby : '-value' ,
60+ aggregateField : [ { yAxes : [ 'sum(value,test_metric,counter,-)' ] } ] ,
61+ metric : { name : 'test_metric' , type : 'counter' } ,
62+ } ,
63+ ] ,
64+ } ) ,
65+ } ) ;
66+
67+ const decoded = decodeMetricFromUrl ( url ) ;
68+ expect ( decoded ?. queryParams . sortBys ) . toEqual ( [ { field : 'value' , kind : 'desc' } ] ) ;
69+ } ) ;
70+
71+ it ( 'decodes aggregateOrderby into aggregateSortBys' , ( ) => {
72+ const url = getMetricsUrlFromSavedQueryUrl ( {
73+ organization,
74+ savedQuery : new SavedQuery ( {
75+ id : 1 ,
76+ interval : '5m' ,
77+ name : 'test query' ,
78+ projects : [ ] ,
79+ dataset : 'metrics' ,
80+ dateAdded : '2025-01-01T00:00:00.000000Z' ,
81+ dateUpdated : '2025-01-01T00:00:00.000000Z' ,
82+ lastVisited : '2025-01-01T00:00:00.000000Z' ,
83+ starred : false ,
84+ position : null ,
85+ query : [
86+ {
87+ mode : Mode . SAMPLES ,
88+ query : '' ,
89+ fields : [ 'id' , 'timestamp' ] ,
90+ orderby : '-timestamp' ,
91+ aggregateOrderby : '-sum(value,test_metric,counter,-)' ,
92+ aggregateField : [ { yAxes : [ 'sum(value,test_metric,counter,-)' ] } ] ,
93+ metric : { name : 'test_metric' , type : 'counter' } ,
94+ } ,
95+ ] ,
96+ } ) ,
97+ } ) ;
98+
99+ const decoded = decodeMetricFromUrl ( url ) ;
100+ expect ( decoded ?. queryParams . sortBys ) . toEqual ( [ { field : 'timestamp' , kind : 'desc' } ] ) ;
101+ expect ( decoded ?. queryParams . aggregateSortBys ) . toEqual ( [
102+ { field : 'sum(value,test_metric,counter,-)' , kind : 'desc' } ,
103+ ] ) ;
104+ } ) ;
105+
106+ it ( 'falls back to defaults when aggregateOrderby is missing (backwards compat)' , ( ) => {
107+ const url = getMetricsUrlFromSavedQueryUrl ( {
108+ organization,
109+ savedQuery : new SavedQuery ( {
110+ id : 1 ,
111+ interval : '5m' ,
112+ name : 'test query' ,
113+ projects : [ ] ,
114+ dataset : 'metrics' ,
115+ dateAdded : '2025-01-01T00:00:00.000000Z' ,
116+ dateUpdated : '2025-01-01T00:00:00.000000Z' ,
117+ lastVisited : '2025-01-01T00:00:00.000000Z' ,
118+ starred : false ,
119+ position : null ,
120+ query : [
121+ {
122+ mode : Mode . SAMPLES ,
123+ query : '' ,
124+ fields : [ 'id' , 'timestamp' ] ,
125+ orderby : '-timestamp' ,
126+ aggregateField : [ { yAxes : [ 'sum(value,test_metric,counter,-)' ] } ] ,
127+ metric : { name : 'test_metric' , type : 'counter' } ,
128+ } ,
129+ ] ,
130+ } ) ,
131+ } ) ;
132+
133+ const decoded = decodeMetricFromUrl ( url ) ;
134+ expect ( decoded ?. queryParams . sortBys ) . toEqual ( [ { field : 'timestamp' , kind : 'desc' } ] ) ;
135+ expect ( decoded ?. queryParams . aggregateSortBys ) . toEqual ( [
136+ { field : 'sum(value,test_metric,counter,-)' , kind : 'desc' } ,
137+ ] ) ;
138+ } ) ;
139+
140+ it ( 'falls back to defaults when orderby is missing' , ( ) => {
141+ const url = getMetricsUrlFromSavedQueryUrl ( {
142+ organization,
143+ savedQuery : new SavedQuery ( {
144+ id : 1 ,
145+ interval : '5m' ,
146+ name : 'test query' ,
147+ projects : [ ] ,
148+ dataset : 'metrics' ,
149+ dateAdded : '2025-01-01T00:00:00.000000Z' ,
150+ dateUpdated : '2025-01-01T00:00:00.000000Z' ,
151+ lastVisited : '2025-01-01T00:00:00.000000Z' ,
152+ starred : false ,
153+ position : null ,
154+ query : [
155+ {
156+ mode : Mode . SAMPLES ,
157+ query : '' ,
158+ fields : [ 'id' , 'timestamp' ] ,
159+ orderby : '' ,
160+ aggregateField : [ { yAxes : [ 'sum(value,test_metric,counter,-)' ] } ] ,
161+ metric : { name : 'test_metric' , type : 'counter' } ,
162+ } ,
163+ ] ,
164+ } ) ,
165+ } ) ;
166+
167+ const decoded = decodeMetricFromUrl ( url ) ;
168+ expect ( decoded ?. queryParams . sortBys ) . toEqual ( [ { field : 'timestamp' , kind : 'desc' } ] ) ;
169+ } ) ;
170+ } ) ;
0 commit comments