@@ -6,7 +6,7 @@ import { describe, it } from 'node:test';
66import assert from 'node:assert/strict' ;
77import {
88 ChartsWidget ,
9- computeHistogramLayout ,
9+ computeHistogramLayout , hitTestColumn ,
1010 kLeftMargin , kRightMargin , kTopMargin , kBottomMargin ,
1111} from '../../src/charts-widget.js' ;
1212
@@ -199,6 +199,60 @@ describe('computeHistogramLayout', () => {
199199 } ) ;
200200} ) ;
201201
202+ describe ( 'hitTestColumn' , ( ) => {
203+ // Build a two-bar layout: one tall bar, one very short bar.
204+ const layout = computeHistogramLayout ( {
205+ bins : [
206+ { lower : - 0.1 , upper : 0.0 , count : 100 , negative : true } ,
207+ { lower : 0.0 , upper : 0.1 , count : 2 , negative : false } ,
208+ ] ,
209+ time_unit : 'ns' ,
210+ } , 500 , 400 ) ;
211+ const { bars, chartArea } = layout ;
212+ // Sanity: the second bar is much shorter than the first.
213+ assert . ok ( bars [ 1 ] . height < bars [ 0 ] . height / 5 ) ;
214+
215+ it ( 'hits a bar by clicking within its rendered area' , ( ) => {
216+ const cx = bars [ 0 ] . x + bars [ 0 ] . width / 2 ;
217+ const cy = bars [ 0 ] . y + bars [ 0 ] . height / 2 ;
218+ assert . equal ( hitTestColumn ( bars , chartArea , cx , cy ) , bars [ 0 ] ) ;
219+ } ) ;
220+
221+ it ( 'hits a short bar by clicking above it in the same column' , ( ) => {
222+ // Click in the middle of the column, well above the tiny bar.
223+ const cx = bars [ 1 ] . x + bars [ 1 ] . width / 2 ;
224+ const cy = chartArea . top + 5 ; // near the top of the chart
225+ assert . equal ( hitTestColumn ( bars , chartArea , cx , cy ) , bars [ 1 ] ) ;
226+ } ) ;
227+
228+ it ( 'returns null when clicking outside the chart area vertically' , ( ) => {
229+ const cx = bars [ 0 ] . x + bars [ 0 ] . width / 2 ;
230+ assert . equal ( hitTestColumn ( bars , chartArea , cx , chartArea . top - 1 ) , null ) ;
231+ assert . equal ( hitTestColumn ( bars , chartArea , cx , chartArea . bottom + 1 ) , null ) ;
232+ } ) ;
233+
234+ it ( 'returns null when clicking between bars (gap region)' , ( ) => {
235+ // The gap is between bar 0's right edge and bar 1's left edge.
236+ const cx = bars [ 0 ] . x + bars [ 0 ] . width + 1 ; // in the gap
237+ const cy = ( chartArea . top + chartArea . bottom ) / 2 ;
238+ // Only null if the point is truly outside both bars' x ranges.
239+ const hit = hitTestColumn ( bars , chartArea , cx , cy ) ;
240+ if ( cx < bars [ 1 ] . x ) {
241+ assert . equal ( hit , null ) ;
242+ }
243+ } ) ;
244+
245+ it ( 'returns null for null bars or chartArea' , ( ) => {
246+ assert . equal ( hitTestColumn ( null , chartArea , 100 , 200 ) , null ) ;
247+ assert . equal ( hitTestColumn ( bars , null , 100 , 200 ) , null ) ;
248+ } ) ;
249+
250+ it ( 'returns null when clicking left of all bars' , ( ) => {
251+ const cy = ( chartArea . top + chartArea . bottom ) / 2 ;
252+ assert . equal ( hitTestColumn ( bars , chartArea , bars [ 0 ] . x - 5 , cy ) , null ) ;
253+ } ) ;
254+ } ) ;
255+
202256describe ( 'ChartsWidget debug charts' , ( ) => {
203257 it ( 'ignores histogram hover and click handlers while a debug chart is active' , async ( ) => {
204258 const { app, widget } = createWidget ( ) ;
0 commit comments