@@ -212,20 +212,27 @@ test('Scatter buildQuery should handle js_columns', () => {
212212 expect ( query . columns ) . toContain ( 'custom_col2' ) ;
213213} ) ;
214214
215- test ( 'Scatter buildQuery should convert numeric metric value to string' , ( ) => {
215+ test ( 'Scatter buildQuery should handle adhoc SQL metric for point_radius_fixed' , ( ) => {
216+ const adhocMetric = {
217+ label : 'count(*) * 1.1' ,
218+ expressionType : 'SQL' as const ,
219+ sqlExpression : 'count(*) * 1.1' ,
220+ } ;
216221 const formData : DeckScatterFormData = {
217222 ...baseFormData ,
218223 point_radius_fixed : {
219224 type : 'metric' ,
220- value : 123 , // numeric metric (edge case)
225+ value : adhocMetric ,
221226 } ,
222227 } ;
223228
224229 const queryContext = buildQuery ( formData ) ;
225230 const [ query ] = queryContext . queries ;
226231
227- expect ( query . metrics ) . toContain ( '123' ) ;
228- expect ( query . orderby ) . toEqual ( [ [ '123' , false ] ] ) ;
232+ // Should preserve full adhoc metric object (not just the label string)
233+ expect ( query . metrics ) . toContainEqual ( adhocMetric ) ;
234+ // orderby should use the label string
235+ expect ( query . orderby ) . toEqual ( [ [ 'count(*) * 1.1' , false ] ] ) ;
229236} ) ;
230237
231238test ( 'Scatter buildQuery should set is_timeseries to false' , ( ) => {
@@ -310,3 +317,107 @@ test('Scatter buildQuery should deduplicate metrics when radius metric already e
310317 expect ( query . metrics ) . toEqual ( [ 'COUNT(*)' , 'AVG(price)' ] ) ;
311318 expect ( query . metrics ) . toHaveLength ( 2 ) ;
312319} ) ;
320+
321+ // Comprehensive point_radius_fixed tests to prevent regressions
322+ test ( 'Scatter buildQuery should handle adhoc SIMPLE metric for point_radius_fixed' , ( ) => {
323+ const adhocMetric = {
324+ label : 'AVG(population)' ,
325+ expressionType : 'SIMPLE' as const ,
326+ column : { column_name : 'population' } ,
327+ aggregate : 'AVG' as const ,
328+ } ;
329+ const formData : DeckScatterFormData = {
330+ ...baseFormData ,
331+ point_radius_fixed : {
332+ type : 'metric' ,
333+ value : adhocMetric ,
334+ } ,
335+ } ;
336+
337+ const queryContext = buildQuery ( formData ) ;
338+ const [ query ] = queryContext . queries ;
339+
340+ // Should preserve full adhoc metric object
341+ expect ( query . metrics ) . toContainEqual ( adhocMetric ) ;
342+ expect ( query . orderby ) . toEqual ( [ [ 'AVG(population)' , false ] ] ) ;
343+ } ) ;
344+
345+ test ( 'Scatter buildQuery should deduplicate adhoc metrics with same label' , ( ) => {
346+ const adhocMetric = {
347+ label : 'custom_count' ,
348+ expressionType : 'SQL' as const ,
349+ sqlExpression : 'count(*) * 2' ,
350+ } ;
351+ const formData : DeckScatterFormData = {
352+ ...baseFormData ,
353+ metrics : [ adhocMetric ] , // Already has this metric
354+ point_radius_fixed : {
355+ type : 'metric' ,
356+ value : adhocMetric , // Same metric for radius
357+ } ,
358+ } ;
359+
360+ const queryContext = buildQuery ( formData ) ;
361+ const [ query ] = queryContext . queries ;
362+
363+ // Should not duplicate the metric
364+ expect ( query . metrics ) . toHaveLength ( 1 ) ;
365+ expect ( query . metrics ) . toContainEqual ( adhocMetric ) ;
366+ } ) ;
367+
368+ test ( 'Scatter buildQuery should handle fixed type with string value correctly' , ( ) => {
369+ const formData : DeckScatterFormData = {
370+ ...baseFormData ,
371+ point_radius_fixed : {
372+ type : 'fix' ,
373+ value : '2500' ,
374+ } ,
375+ } ;
376+
377+ const queryContext = buildQuery ( formData ) ;
378+ const [ query ] = queryContext . queries ;
379+
380+ // Fixed values should NOT be added to metrics
381+ expect ( query . metrics ) . toEqual ( [ ] ) ;
382+ expect ( query . orderby ) . toEqual ( [ ] ) ;
383+ } ) ;
384+
385+ test ( 'Scatter buildQuery should handle undefined value in metric type gracefully' , ( ) => {
386+ const formData : DeckScatterFormData = {
387+ ...baseFormData ,
388+ point_radius_fixed : {
389+ type : 'metric' ,
390+ value : undefined ,
391+ } ,
392+ } ;
393+
394+ const queryContext = buildQuery ( formData ) ;
395+ const [ query ] = queryContext . queries ;
396+
397+ // Should not add anything when value is undefined
398+ expect ( query . metrics ) . toEqual ( [ ] ) ;
399+ expect ( query . orderby ) . toEqual ( [ ] ) ;
400+ } ) ;
401+
402+ test ( 'Scatter buildQuery should preserve adhoc metric with custom label' , ( ) => {
403+ const adhocMetric = {
404+ label : 'My Custom Metric' ,
405+ expressionType : 'SQL' as const ,
406+ sqlExpression : 'SUM(revenue) / COUNT(*)' ,
407+ hasCustomLabel : true ,
408+ } ;
409+ const formData : DeckScatterFormData = {
410+ ...baseFormData ,
411+ point_radius_fixed : {
412+ type : 'metric' ,
413+ value : adhocMetric ,
414+ } ,
415+ } ;
416+
417+ const queryContext = buildQuery ( formData ) ;
418+ const [ query ] = queryContext . queries ;
419+
420+ // Should preserve full metric including hasCustomLabel
421+ expect ( query . metrics ) . toContainEqual ( adhocMetric ) ;
422+ expect ( query . orderby ) . toEqual ( [ [ 'My Custom Metric' , false ] ] ) ;
423+ } ) ;
0 commit comments