@@ -112,115 +112,168 @@ describe("CartesianChart: tooltip", () => {
112112 } ) ;
113113 } ) ;
114114
115- test ( "customizes series rendering" , async ( ) => {
115+ describe ( "Custom tooltip content" , ( ) => {
116+ const series : CartesianChartProps . SeriesOptions [ ] = [
117+ { type : "line" , id : "l" , name : "Line" , data : [ { x : 1 , y : 2 } ] } ,
118+ { type : "errorbar" , linkedTo : "l" , name : "Error" , data : [ { x : 1 , low : 1 , high : 4 } ] } ,
119+ { type : "x-threshold" , name : "Threshold" , value : 1 } ,
120+ ] ;
121+
116122 const onClickValue = vi . fn ( ) ;
117- renderCartesianChart ( {
118- highcharts,
119- series : [
120- { type : "line" , id : "l" , name : "Line" , data : [ { x : 1 , y : 2 } ] } ,
121- { type : "errorbar" , linkedTo : "l" , name : "Error" , data : [ { x : 1 , low : 1 , high : 4 } ] } ,
122- { type : "x-threshold" , name : "Threshold" , value : 1 } ,
123- ] ,
124- tooltip : {
125- point ( { item } ) {
126- return {
127- key : < span > { item . series . name } </ span > ,
128- value : < button onClick = { ( ) => onClickValue ( "root" ) } > { item . y ?? "T" } </ button > ,
129- expandable : item . series . name === "Line" ,
130- subItems :
131- item . series . name === "Line"
132- ? [
133- {
134- key : < span > sub-1 key</ span > ,
135- value : < button onClick = { ( ) => onClickValue ( "sub-1" ) } > sub-1 value</ button > ,
136- } ,
137- {
138- key : < span > sub-2 key</ span > ,
139- value : < button onClick = { ( ) => onClickValue ( "sub-2" ) } > sub-2 value</ button > ,
140- } ,
141- ]
142- : [ ] ,
143- description : item . errorRanges ?. length ? `${ item . errorRanges [ 0 ] . low } - ${ item . errorRanges [ 0 ] . high } ` : null ,
144- } ;
145- } ,
146- } ,
147- } ) ;
123+ const customKey = ( item : CartesianChartProps . TooltipPointItem ) => (
124+ < span > { `Custom name for ${ item . series . name } ` } </ span >
125+ ) ;
126+ const customValue = ( item : CartesianChartProps . TooltipPointItem ) => (
127+ < button onClick = { ( ) => onClickValue ( "root" ) } > { item . y ?? "T" } </ button >
128+ ) ;
129+ const customSubItems = ( item : CartesianChartProps . TooltipPointItem ) =>
130+ item . series . name === "Line"
131+ ? [
132+ {
133+ key : < span > sub-1 key</ span > ,
134+ value : < button onClick = { ( ) => onClickValue ( "sub-1" ) } > sub-1 value</ button > ,
135+ } ,
136+ {
137+ key : < span > sub-2 key</ span > ,
138+ value : < button onClick = { ( ) => onClickValue ( "sub-2" ) } > sub-2 value</ button > ,
139+ } ,
140+ ]
141+ : [ ] ;
142+ const customDescription = ( item : CartesianChartProps . TooltipPointItem ) =>
143+ item . errorRanges ?. length ? `${ item . errorRanges [ 0 ] . low } - ${ item . errorRanges [ 0 ] . high } ` : null ;
148144
149- act ( ( ) => hc . highlightChartPoint ( 0 , 0 ) ) ;
145+ const openTooltip = async ( ) => {
146+ act ( ( ) => hc . highlightChartPoint ( 0 , 0 ) ) ;
150147
151- await waitFor ( ( ) => {
152- expect ( getTooltip ( ) ) . not . toBe ( null ) ;
148+ await waitFor ( ( ) => {
149+ expect ( getTooltip ( ) ) . not . toBe ( null ) ;
150+ } ) ;
151+
152+ expect ( getTooltipHeader ( ) . getElement ( ) . textContent ) . toBe ( "1" ) ;
153+ expect ( getAllTooltipSeries ( ) ) . toHaveLength ( 2 ) ;
154+ } ;
155+
156+ const expectCustomSubItems = ( ) => {
157+ expect ( getTooltipSeries ( 0 ) . find ( '[aria-expanded="false"]' ) ) . not . toBe ( null ) ;
158+ getTooltipSeries ( 0 ) . find ( '[aria-expanded="false"]' ) ! . click ( { bubbles : false } ) ;
159+ expect ( getTooltipSeries ( 0 ) . findSubItems ( ) ) . toHaveLength ( 2 ) ;
160+ expect ( getTooltipSeries ( 0 ) . findSubItems ( ) [ 1 ] . findKey ( ) . getElement ( ) . textContent ) . toBe ( "sub-2 key" ) ;
161+ expect ( getTooltipSeries ( 0 ) . findSubItems ( ) [ 1 ] . findValue ( ) . getElement ( ) . textContent ) . toBe ( "sub-2 value" ) ;
162+ getTooltipSeries ( 0 ) . findSubItems ( ) [ 1 ] . findValue ( ) . find ( "button" ) ! . click ( ) ;
163+ expect ( onClickValue ) . toHaveBeenCalledWith ( "sub-2" ) ;
164+ expect ( getTooltipSeries ( 1 ) . find ( '[aria-expanded="false"]' ) ) . toBe ( null ) ;
165+ } ;
166+
167+ afterEach ( ( ) => {
168+ onClickValue . mockReset ( ) ;
153169 } ) ;
154170
155- expect ( getTooltipHeader ( ) . getElement ( ) . textContent ) . toBe ( "1" ) ;
156- expect ( getAllTooltipSeries ( ) ) . toHaveLength ( 2 ) ;
171+ test ( "customizes key, value, sub-items and description" , async ( ) => {
172+ renderCartesianChart ( {
173+ highcharts,
174+ series,
175+ tooltip : {
176+ point ( { item } ) {
177+ return {
178+ key : customKey ( item ) ,
179+ value : customValue ( item ) ,
180+ expandable : item . series . name === "Line" ,
181+ subItems : customSubItems ( item ) ,
182+ description : customDescription ( item ) ,
183+ } ;
184+ } ,
185+ } ,
186+ } ) ;
157187
158- expect ( getTooltipSeries ( 0 ) . findKey ( ) . getElement ( ) . textContent ) . toBe ( "Line" ) ;
159- expect ( getTooltipSeries ( 0 ) . findValue ( ) . getElement ( ) . textContent ) . toBe ( "2" ) ;
160- expect ( getTooltipSeries ( 0 ) . find ( '[aria-expanded="false"]' ) ) . not . toBe ( null ) ;
188+ await openTooltip ( ) ;
161189
162- getTooltipSeries ( 0 ) . find ( '[aria-expanded="false"]' ) ! . click ( { bubbles : false } ) ;
163- expect ( getTooltipSeries ( 0 ) . findSubItems ( ) ) . toHaveLength ( 2 ) ;
164- expect ( getTooltipSeries ( 0 ) . findSubItems ( ) [ 1 ] . findKey ( ) . getElement ( ) . textContent ) . toBe ( "sub-2 key" ) ;
165- expect ( getTooltipSeries ( 0 ) . findSubItems ( ) [ 1 ] . findValue ( ) . getElement ( ) . textContent ) . toBe ( "sub-2 value" ) ;
190+ expect ( getTooltipSeries ( 0 ) . findKey ( ) . getElement ( ) . textContent ) . toBe ( "Custom name for Line" ) ;
191+ expect ( getTooltipSeries ( 0 ) . findValue ( ) . getElement ( ) . textContent ) . toBe ( "2" ) ;
166192
167- getTooltipSeries ( 0 ) . findValue ( ) . find ( "button" ) ! . click ( ) ;
168- expect ( onClickValue ) . toHaveBeenCalledWith ( "root" ) ;
193+ expectCustomSubItems ( ) ;
169194
170- getTooltipSeries ( 0 ) . findSubItems ( ) [ 1 ] . findValue ( ) . find ( "button" ) ! . click ( ) ;
171- expect ( onClickValue ) . toHaveBeenCalledWith ( "sub-2 " ) ;
195+ getTooltipSeries ( 0 ) . findValue ( ) . find ( "button" ) ! . click ( ) ;
196+ expect ( onClickValue ) . toHaveBeenCalledWith ( "root " ) ;
172197
173- expect ( getTooltipSeries ( 0 ) . findDescription ( ) . getElement ( ) . textContent ) . toBe ( "1 - 4" ) ;
198+ expect ( getTooltipSeries ( 0 ) . findDescription ( ) . getElement ( ) . textContent ) . toBe ( "1 - 4" ) ;
174199
175- expect ( getTooltipSeries ( 1 ) . findKey ( ) . getElement ( ) . textContent ) . toBe ( "Threshold" ) ;
176- expect ( getTooltipSeries ( 1 ) . findValue ( ) . getElement ( ) . textContent ) . toBe ( "T" ) ;
177- expect ( getTooltipSeries ( 1 ) . find ( '[aria-expanded="false"]' ) ) . toBe ( null ) ;
178- } ) ;
200+ expect ( getTooltipSeries ( 1 ) . findKey ( ) . getElement ( ) . textContent ) . toBe ( "Custom name for Threshold" ) ;
201+ expect ( getTooltipSeries ( 1 ) . findValue ( ) . getElement ( ) . textContent ) . toBe ( "T" ) ;
202+ } ) ;
179203
180- test ( "customizes tooltip slots" , async ( ) => {
181- renderCartesianChart ( {
182- highcharts,
183- series : [
184- { type : "line" , id : "l" , name : "Line" , data : [ { x : 1 , y : 2 } ] } ,
185- { type : "x-threshold" , name : "Threshold" , value : 1 } ,
186- { type : "errorbar" , name : "Error" , data : [ { x : 1 , low : 3 , high : 4 } ] , linkedTo : "l" } ,
187- ] ,
188- tooltip : {
189- header ( { x, items } ) {
190- return (
191- < span >
192- header { x } { items . length } { items [ 0 ] . series . name } { items [ 0 ] . errorRanges ! [ 0 ] . low } { " " }
193- { items [ 0 ] . errorRanges ! [ 0 ] . high } { items [ 1 ] . series . name }
194- </ span >
195- ) ;
196- } ,
197- body ( { x, items } ) {
198- return (
199- < span >
200- body { x } { items . length } { items [ 0 ] . series . name } { items [ 0 ] . errorRanges ! [ 0 ] . low } { " " }
201- { items [ 0 ] . errorRanges ! [ 0 ] . high } { items [ 1 ] . series . name }
202- </ span >
203- ) ;
204- } ,
205- footer ( { x, items } ) {
206- return (
207- < span >
208- footer { x } { items . length } { items [ 0 ] . series . name } { items [ 0 ] . errorRanges ! [ 0 ] . low } { " " }
209- { items [ 0 ] . errorRanges ! [ 0 ] . high } { items [ 1 ] . series . name }
210- </ span >
211- ) ;
204+ test ( "renders default key and value if not defined" , async ( ) => {
205+ renderCartesianChart ( {
206+ highcharts,
207+ series,
208+ tooltip : {
209+ point ( { item } ) {
210+ return {
211+ expandable : item . series . name === "Line" ,
212+ subItems : customSubItems ( item ) ,
213+ description : customDescription ( item ) ,
214+ } ;
215+ } ,
212216 } ,
213- } ,
214- } ) ;
217+ } ) ;
215218
216- act ( ( ) => hc . highlightChartPoint ( 0 , 0 ) ) ;
219+ await openTooltip ( ) ;
217220
218- await waitFor ( ( ) => {
219- expect ( getTooltip ( ) ) . not . toBe ( null ) ;
221+ expect ( getTooltipSeries ( 0 ) . findKey ( ) . getElement ( ) . textContent ) . toBe ( "Line" ) ;
222+ expect ( getTooltipSeries ( 0 ) . findValue ( ) . getElement ( ) . textContent ) . toBe ( "2" ) ;
223+
224+ expectCustomSubItems ( ) ;
225+
226+ expect ( getTooltipSeries ( 0 ) . findDescription ( ) . getElement ( ) . textContent ) . toBe ( "1 - 4" ) ;
227+
228+ expect ( getTooltipSeries ( 1 ) . findKey ( ) . getElement ( ) . textContent ) . toBe ( "Threshold" ) ;
229+ expect ( getTooltipSeries ( 1 ) . findValue ( ) . getElement ( ) . textContent ) . toBe ( "" ) ; // X threshold has no y value
220230 } ) ;
221231
222- expect ( getTooltipHeader ( ) . getElement ( ) . textContent ) . toBe ( "header 1 2 Line 3 4 Threshold" ) ;
223- expect ( getTooltipBody ( ) . getElement ( ) . textContent ) . toBe ( "body 1 2 Line 3 4 Threshold" ) ;
224- expect ( getTooltipFooter ( ) . getElement ( ) . textContent ) . toBe ( "footer 1 2 Line 3 4 Threshold" ) ;
232+ test ( "customizes tooltip slots" , async ( ) => {
233+ renderCartesianChart ( {
234+ highcharts,
235+ series : [
236+ { type : "line" , id : "l" , name : "Line" , data : [ { x : 1 , y : 2 } ] } ,
237+ { type : "x-threshold" , name : "Threshold" , value : 1 } ,
238+ { type : "errorbar" , name : "Error" , data : [ { x : 1 , low : 3 , high : 4 } ] , linkedTo : "l" } ,
239+ ] ,
240+ tooltip : {
241+ header ( { x, items } ) {
242+ return (
243+ < span >
244+ header { x } { items . length } { items [ 0 ] . series . name } { items [ 0 ] . errorRanges ! [ 0 ] . low } { " " }
245+ { items [ 0 ] . errorRanges ! [ 0 ] . high } { items [ 1 ] . series . name }
246+ </ span >
247+ ) ;
248+ } ,
249+ body ( { x, items } ) {
250+ return (
251+ < span >
252+ body { x } { items . length } { items [ 0 ] . series . name } { items [ 0 ] . errorRanges ! [ 0 ] . low } { " " }
253+ { items [ 0 ] . errorRanges ! [ 0 ] . high } { items [ 1 ] . series . name }
254+ </ span >
255+ ) ;
256+ } ,
257+ footer ( { x, items } ) {
258+ return (
259+ < span >
260+ footer { x } { items . length } { items [ 0 ] . series . name } { items [ 0 ] . errorRanges ! [ 0 ] . low } { " " }
261+ { items [ 0 ] . errorRanges ! [ 0 ] . high } { items [ 1 ] . series . name }
262+ </ span >
263+ ) ;
264+ } ,
265+ } ,
266+ } ) ;
267+
268+ act ( ( ) => hc . highlightChartPoint ( 0 , 0 ) ) ;
269+
270+ await waitFor ( ( ) => {
271+ expect ( getTooltip ( ) ) . not . toBe ( null ) ;
272+ } ) ;
273+
274+ expect ( getTooltipHeader ( ) . getElement ( ) . textContent ) . toBe ( "header 1 2 Line 3 4 Threshold" ) ;
275+ expect ( getTooltipBody ( ) . getElement ( ) . textContent ) . toBe ( "body 1 2 Line 3 4 Threshold" ) ;
276+ expect ( getTooltipFooter ( ) . getElement ( ) . textContent ) . toBe ( "footer 1 2 Line 3 4 Threshold" ) ;
277+ } ) ;
225278 } ) ;
226279} ) ;
0 commit comments