Skip to content

Commit 063e82c

Browse files
committed
Add synchronization to QueryChartDialog
1 parent 80112df commit 063e82c

1 file changed

Lines changed: 77 additions & 46 deletions

File tree

src/org/labkey/test/components/react/QueryChartDialog.java

Lines changed: 77 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)