@@ -46,36 +46,48 @@ public String getName()
4646 return elementCache ().nameInput .get ();
4747 }
4848
49- public QueryChartDialog setTitle (String value ) {
50- elementCache ().titleInput .set (value );
51- elementCache ().title .click (); // blur the element
49+ public QueryChartDialog setTitle (String value )
50+ {
51+ doAndWaitForPreview (() -> {
52+ elementCache ().titleInput .set (value );
53+ elementCache ().title .click (); // blur the element
54+ });
5255 return this ;
5356 }
5457
5558 public QueryChartDialog setSubtitle (String value )
5659 {
57- elementCache ().subtitleInput .set (value );
58- elementCache ().title .click (); // blur the element
60+ doAndWaitForPreview (() -> {
61+ elementCache ().subtitleInput .set (value );
62+ elementCache ().title .click (); // blur the element
63+ });
5964 return this ;
6065 }
6166
6267 public QueryChartDialog setHeight (String value )
6368 {
64- elementCache ().heightInput .set (value );
65- elementCache ().title .click (); // blur the element
69+ doAndWaitForPreview (() -> {
70+ elementCache ().heightInput .set (value );
71+ elementCache ().title .click (); // blur the element
72+ });
6673 return this ;
6774 }
6875
6976 public QueryChartDialog setWidth (String value )
7077 {
71- elementCache ().widthInput .set (value );
72- elementCache ().title .click (); // blur the element
78+ doAndWaitForPreview (() -> {
79+ elementCache ().widthInput .set (value );
80+ elementCache ().title .click (); // blur the element
81+ });
7382 return this ;
7483 }
7584
7685 public QueryChartDialog setUseFullWidth (boolean checked )
7786 {
78- elementCache ().fullWidthCheckbox .set (checked );
87+ if (checked )
88+ doAndWaitForPreview (() -> elementCache ().fullWidthCheckbox .check ()); // always refreshes the svg
89+ else
90+ elementCache ().fullWidthCheckbox .uncheck ();
7991 return this ;
8092 }
8193
@@ -110,7 +122,7 @@ public boolean getInheritable()
110122
111123 public QueryChartDialog clearFieldValue (String fieldLabel )
112124 {
113- elementCache ().reactSelectByLabel (fieldLabel ).clearSelection ();
125+ doAndWaitForPreview (() -> elementCache ().reactSelectByLabel (fieldLabel ).clearSelection () );
114126 return this ;
115127 }
116128
@@ -119,7 +131,7 @@ public QueryChartDialog clearFieldValue(String fieldLabel)
119131 */
120132 public QueryChartDialog selectXAxis (String field )
121133 {
122- elementCache ().reactSelectByLabel ("X Axis" ).select (field );
134+ doAndWaitForPreview (() -> elementCache ().reactSelectByLabel ("X Axis" ).select (field ) );
123135 return this ;
124136 }
125137
@@ -145,14 +157,16 @@ private void clickFieldOptions(String label)
145157
146158 public QueryChartDialog setLegendPos (String legendPos )
147159 {
148-
160+ RadioButton radio ;
149161 if ("bottom" .equals (legendPos ))
150- elementCache ().legendBottomRadio . check () ;
162+ radio = elementCache ().legendBottomRadio ;
151163 else if ("right" .equals (legendPos ))
152- elementCache ().legendRightRadio . check () ;
164+ radio = elementCache ().legendRightRadio ;
153165 else
154166 throw new IllegalArgumentException ("Invalid legend value: " + legendPos );
155167
168+ if (!radio .isChecked ())
169+ doAndWaitForPreview (radio ::check );
156170 return this ;
157171 }
158172
@@ -173,10 +187,7 @@ public boolean isLegendPosVisible()
173187
174188 public QueryChartDialog setPointsHidden (boolean hidden )
175189 {
176- if (hidden )
177- elementCache ().pointsHideRadio .check ();
178- else
179- elementCache ().pointsShowRadio .check ();
190+ doAndWaitForPreview (() -> elementCache ().pointsHideRadio .set (hidden ));
180191 return this ;
181192 }
182193
@@ -194,12 +205,15 @@ public boolean hasPointsHiddenOption()
194205 public QueryChartDialog setAxisScaleType (String label , String value )
195206 {
196207 clickFieldOptions (label ); // open the popover
208+ RadioButton radio ;
197209 if ("linear" .equalsIgnoreCase (value ))
198- elementCache ().scaleLinearRadio . check () ;
210+ radio = elementCache ().scaleLinearRadio ;
199211 else if ("log" .equalsIgnoreCase (value ))
200- elementCache ().scaleLogRadio . check () ;
212+ radio = elementCache ().scaleLogRadio ;
201213 else
202214 throw new IllegalArgumentException ("Invalid scale value: " + value );
215+ if (!radio .isChecked ())
216+ doAndWaitForPreview (radio ::check );
203217 clickFieldOptions (label ); // close the popover
204218 return this ;
205219 }
@@ -228,12 +242,15 @@ public boolean isAxisScaleTypeAvailable(String label)
228242 public QueryChartDialog setAxisRangeType (String label , String value )
229243 {
230244 clickFieldOptions (label ); // open the popover
245+ RadioButton radio ;
231246 if ("automatic" .equalsIgnoreCase (value ))
232- elementCache ().scaleAutomaticRadio . check () ;
247+ radio = elementCache ().scaleAutomaticRadio ;
233248 else if ("manual" .equalsIgnoreCase (value ))
234- elementCache ().scaleManualRadio . check () ;
249+ radio = elementCache ().scaleManualRadio ;
235250 else
236251 throw new IllegalArgumentException ("Invalid range value: " + value );
252+ if (!radio .isChecked ())
253+ doAndWaitForPreview (radio ::check );
237254 clickFieldOptions (label ); // close the popover
238255 return this ;
239256 }
@@ -252,8 +269,8 @@ public QueryChartDialog setAxisRange(String label, String min, String max)
252269 clickFieldOptions (label ); // open the popover
253270 if (elementCache ().scaleManualRadio .isChecked ())
254271 {
255- elementCache ().scaleRangeMinInput .set (min );
256- elementCache ().scaleRangeMaxInput .set (max );
272+ doAndWaitForPreview (() -> elementCache ().scaleRangeMinInput .set (min ) );
273+ doAndWaitForPreview (() -> elementCache ().scaleRangeMaxInput .set (max ) );
257274 }
258275 clickFieldOptions (label ); // close the popover
259276 return this ;
@@ -280,7 +297,7 @@ public String getAxisRangeMax(String label)
280297 */
281298 public QueryChartDialog selectYAxis (String field )
282299 {
283- elementCache ().reactSelectByLabel ("Y Axis" ).select (field );
300+ doAndWaitForPreview (() -> elementCache ().reactSelectByLabel ("Y Axis" ).select (field ) );
284301 return this ;
285302 }
286303
@@ -294,10 +311,20 @@ public List<String> getYAxisSelectionOptions()
294311 return elementCache ().reactSelectByLabel ("Y Axis" ).getOptions ();
295312 }
296313
314+ private void doAndWaitForPreview (Runnable action )
315+ {
316+ WebElement svg = isPreviewPresent () ? elementCache ().svg () : null ;
317+ action .run ();
318+
319+ // preview might not appear after action, but it will definitely go stale.
320+ if (svg != null )
321+ getWrapper ().shortWait ().until (ExpectedConditions .stalenessOf (svg ));
322+ }
323+
297324 public QueryChartDialog selectYAxisAggregateMethod (String option )
298325 {
299326 clickFieldOptions ("Y Axis" ); // open the popover
300- getAggregateMethodSelect ().select (option );
327+ doAndWaitForPreview (() -> getAggregateMethodSelect ().select (option ) );
301328 Locator .tagWithText ("label" , "Name *" ).findElement (this ).click (); // close the popover
302329 return this ;
303330 }
@@ -334,7 +361,9 @@ private RadioButton getErrorBarsRadio(String value)
334361 public QueryChartDialog selectYAxisErrorBar (String value )
335362 {
336363 clickFieldOptions ("Y Axis" ); // open the popover
337- getErrorBarsRadio (value ).check ();
364+ RadioButton errorBarsRadio = getErrorBarsRadio (value );
365+ if (!errorBarsRadio .isChecked ())
366+ doAndWaitForPreview (errorBarsRadio ::check );
338367 Locator .tagWithText ("label" , "Name *" ).findElement (this ).click (); // close the popover
339368 return this ;
340369 }
@@ -350,15 +379,15 @@ public boolean isYAxisErrorBarOptionEnabled(String value)
350379 public QueryChartDialog setXAxisLabel (String value )
351380 {
352381 clickFieldOptions ("X Axis" );
353- elementCache ().xLabelInput .set (value );
382+ doAndWaitForPreview (() -> elementCache ().xLabelInput .set (value ) );
354383 Locator .tagWithText ("label" , "Name *" ).findElement (this ).click (); // close the popover
355384 return this ;
356385 }
357386
358387 public QueryChartDialog setYAxisLabel (String value )
359388 {
360389 clickFieldOptions ("Y Axis" );
361- elementCache ().yLabelInput .set (value );
390+ doAndWaitForPreview (() -> elementCache ().yLabelInput .set (value ) );
362391 Locator .tagWithText ("label" , "Name *" ).findElement (this ).click (); // close the popover
363392 return this ;
364393 }
@@ -368,7 +397,7 @@ public QueryChartDialog setYAxisLabel(String value)
368397 */
369398 public QueryChartDialog selectGroupBy (String field )
370399 {
371- elementCache ().reactSelectByLabel ("Group By" ).select (field );
400+ doAndWaitForPreview (() -> elementCache ().reactSelectByLabel ("Group By" ).select (field ) );
372401 return this ;
373402 }
374403
@@ -387,7 +416,7 @@ public List<String> getGroupBySelectionOptions()
387416 */
388417 public QueryChartDialog selectColor (String field )
389418 {
390- elementCache ().reactSelectByLabel ("Color" ).select (field );
419+ doAndWaitForPreview (() -> elementCache ().reactSelectByLabel ("Color" ).select (field ) );
391420 return this ;
392421 }
393422
@@ -401,7 +430,7 @@ public String getSelectedColor()
401430 */
402431 public QueryChartDialog selectShape (String field )
403432 {
404- elementCache ().reactSelectByLabel ("Shape" ).select (field );
433+ doAndWaitForPreview (() -> elementCache ().reactSelectByLabel ("Shape" ).select (field ) );
405434 return this ;
406435 }
407436
@@ -415,7 +444,7 @@ public String getSelectedShape()
415444 */
416445 public QueryChartDialog selectSeries (String field )
417446 {
418- elementCache ().reactSelectByLabel ("Series" ).select (field );
447+ doAndWaitForPreview (() -> elementCache ().reactSelectByLabel ("Series" ).select (field ) );
419448 return this ;
420449 }
421450
@@ -440,17 +469,19 @@ public List<String> getTrendlineOptions()
440469 */
441470 public QueryChartDialog selectTrendline (String field )
442471 {
443- elementCache ().reactSelectByLabel ("Trendline" ).select (field );
472+ doAndWaitForPreview (() -> elementCache ().reactSelectByLabel ("Trendline" ).select (field ) );
444473 return this ;
445474 }
446475
447476 public QueryChartDialog setTrendlineProvidedParameters (String field )
448477 {
449478 clickFieldOptions ("Trendline" ); // open the popover
450- if (field != null )
451- getTrendlineProvidedParametersSelect ().select (field );
452- else
453- getTrendlineProvidedParametersSelect ().clearSelection ();
479+ doAndWaitForPreview (() -> {
480+ if (field != null )
481+ getTrendlineProvidedParametersSelect ().select (field );
482+ else
483+ getTrendlineProvidedParametersSelect ().clearSelection ();
484+ });
454485 elementCache ().title .click (); // close the popover
455486 return this ;
456487 }
@@ -480,7 +511,7 @@ public String getSelectedSeries()
480511 */
481512 public QueryChartDialog selectCategories (String field )
482513 {
483- elementCache ().reactSelectByLabel ("Categories" ).select (field );
514+ doAndWaitForPreview (() -> elementCache ().reactSelectByLabel ("Categories" ).select (field ) );
484515 return this ;
485516 }
486517
@@ -508,7 +539,7 @@ public QueryChartDialog setChartType(CHART_TYPE chartType)
508539 var chartTypeDropdown = elementCache ().reactSelectByLabel ("Chart Type" );
509540 // ChartTypeDropdown component uses a custom option renderer
510541 chartTypeDropdown .setOptionLocator ((String type ) -> Locator .byClass ("chart-builder-type-option" ).withAttribute ("data-chart-type" , type ));
511- chartTypeDropdown .select (chartType .getChartType ());
542+ doAndWaitForPreview (() -> chartTypeDropdown .select (chartType .getChartType () ));
512543 WebDriverWrapper .waitFor (()-> getSelectedChartType ().equals (chartType ),
513544 "The requested chart type did not become selected" , 2000 );
514545
@@ -538,7 +569,7 @@ public List<String> getPreviewErrors()
538569
539570 public WebElement getSvgChart ()
540571 {
541- WebDriverWrapper .waitFor (()-> isPreviewPresent () ,
572+ WebDriverWrapper .waitFor (this :: isPreviewPresent ,
542573 "the preview was not present in time" , 2000 );
543574 return elementCache ().svg ();
544575 }
@@ -654,7 +685,7 @@ private QueryChartDialog setColor(WebElement colorPickerContainer, String hexCol
654685 {
655686 Locator .tagWithClassContaining ("button" , "color-picker__button" ).findElement (colorPickerContainer ).click ();
656687 ColorPickerInput colorInput = new ColorPickerInput .ColorPickerInputFinder (getDriver ()).findWhenNeeded ();
657- colorInput .setHexValue (hexColor );
688+ doAndWaitForPreview (() -> colorInput .setHexValue (hexColor ) );
658689 colorPickerContainer .click (); // need to click outside the color picker to close it
659690 return this ;
660691 }
@@ -666,7 +697,7 @@ public boolean hasColorPaletteOption()
666697
667698 public QueryChartDialog selectColorPalette (String option )
668699 {
669- elementCache ().reactSelectByLabel ("Color Palette" ).select (option );
700+ doAndWaitForPreview (() -> elementCache ().reactSelectByLabel ("Color Palette" ).select (option ) );
670701 return this ;
671702 }
672703
@@ -680,7 +711,7 @@ public QueryChartDialog selectLineColorAndStyleOption(String option, String hexC
680711 var seriesDropdown = elementCache ().reactSelectByLabel ("Line Color and Style" );
681712 // series select component uses a custom option renderer
682713 seriesDropdown .setOptionLocator ((String type ) -> Locator .byClass ("chart-builder-type-option" ).withAttribute ("data-series-option" , type ));
683- seriesDropdown .select (option );
714+ doAndWaitForPreview (() -> seriesDropdown .select (option ) );
684715
685716 if (hexColor != null )
686717 setColor (elementCache ().seriesColorPicker , hexColor );
@@ -690,7 +721,7 @@ public QueryChartDialog selectLineColorAndStyleOption(String option, String hexC
690721 {
691722 var lineTypeDropdown = elementCache ().reactSelectByLabel ("Line Type" );
692723 lineTypeDropdown .setOptionLocator ((String type ) -> Locator .byClass ("chart-builder-type-option" ).withAttribute ("data-series-linetype" , type ));
693- lineTypeDropdown .select (lineType );
724+ doAndWaitForPreview (() -> lineTypeDropdown .select (lineType ) );
694725 }
695726
696727 return this ;
0 commit comments