Skip to content

Commit 2ba16bb

Browse files
committed
Merge remote-tracking branch 'origin/develop' into fb_sourceDIB
2 parents b18c113 + a835fca commit 2ba16bb

4 files changed

Lines changed: 238 additions & 154 deletions

File tree

src/org/labkey/test/components/ui/domainproperties/EntityTypeDesigner.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ Optional<WebElement> optionalWarningAlert()
436436

437437
public final WebElement helpTarget(String divLabelText)
438438
{
439-
return Locator.xpath(String.format("//div[text()='%s']//span[@class='label-help-target']", divLabelText)).findWhenNeeded(this);
439+
return Locator.xpath(String.format("//span[text()='%s']//div[@class='overlay-trigger']", divLabelText)).findWhenNeeded(this);
440440
}
441441

442442
// Tool tips exist on the page, outside the scope of the domainDesigner, so scope the search accordingly.
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
package org.labkey.test.components.ui.entities;
2+
3+
import org.apache.commons.lang3.StringUtils;
4+
import org.labkey.api.util.Pair;
5+
import org.labkey.test.Locator;
6+
import org.labkey.test.components.bootstrap.ModalDialog;
7+
import org.labkey.test.components.html.Checkbox;
8+
import org.labkey.test.components.html.Input;
9+
import org.labkey.test.components.react.FilteringReactSelect;
10+
import org.labkey.test.components.react.ReactDateTimePicker;
11+
import org.labkey.test.components.react.ReactSelect;
12+
import org.labkey.test.components.react.ToggleButton;
13+
import org.labkey.test.components.ui.files.FileAttachmentContainer;
14+
import org.labkey.test.params.FieldKey;
15+
import org.openqa.selenium.WebElement;
16+
17+
import java.util.HashMap;
18+
import java.util.Map;
19+
20+
import static org.labkey.test.WebDriverWrapper.WAIT_FOR_JAVASCRIPT;
21+
22+
/**
23+
* Abstract base for {@link EntityBulkInsertDialog} and {@link EntityBulkUpdateDialog}.
24+
*/
25+
public abstract class EntityBulkDialog extends ModalDialog
26+
{
27+
protected int _changeCounter = 0;
28+
29+
protected EntityBulkDialog(ModalDialogFinder finder)
30+
{
31+
super(finder);
32+
}
33+
34+
/**
35+
* @param fieldIdentifier Identifier for the field; name ({@link String}) or fieldKey ({@link FieldKey})
36+
* @return current value of the specified field
37+
*/
38+
public String getTextArea(CharSequence fieldIdentifier)
39+
{
40+
return elementCache().textArea(fieldIdentifier).get();
41+
}
42+
43+
/**
44+
* @param fieldIdentifier Identifier for the field; name ({@link String}) or fieldKey ({@link FieldKey})
45+
* @return current value of the specified field
46+
*/
47+
public String getNumericField(CharSequence fieldIdentifier)
48+
{
49+
return elementCache().textInput(fieldIdentifier).get();
50+
}
51+
52+
/**
53+
* @param fieldIdentifier Identifier for the field; name ({@link String}) or fieldKey ({@link FieldKey})
54+
* @return current value of the specified field
55+
*/
56+
public boolean getBooleanField(CharSequence fieldIdentifier)
57+
{
58+
return elementCache().checkbox(fieldIdentifier).get();
59+
}
60+
61+
public String getFieldValue(WebElement input)
62+
{
63+
String value = input.getText();
64+
if (StringUtils.isEmpty(value))
65+
value = input.getAttribute("value");
66+
if (StringUtils.isEmpty(value))
67+
value = input.getAttribute("placeholder");
68+
if (StringUtils.isEmpty(value) && "checkbox".equals(input.getAttribute("type")))
69+
value = input.getAttribute("title");
70+
return value;
71+
}
72+
73+
protected String getValueForReactSelect(ReactSelect reactSelect)
74+
{
75+
if (!reactSelect.getSelections().isEmpty())
76+
{
77+
return reactSelect.getSelections().get(0);
78+
}
79+
else
80+
{
81+
return "";
82+
}
83+
}
84+
85+
private WebElement getAmountUnitsRow()
86+
{
87+
String fieldLabel = "Amount and Units";
88+
return elementCache().formRowByControlLabel(fieldLabel);
89+
}
90+
91+
public Pair<String, String> getAmountAndUnitsReadOnlyValues()
92+
{
93+
String amountVal = getFieldValue(getAmountInput());
94+
String unitVal = Locator.tagWithClass("div", "select-input__value-container").withoutAttribute("type", "hidden").findElement(getAmountUnitsRow()).getText();
95+
return new Pair<>(amountVal, unitVal);
96+
}
97+
98+
public Pair<String, String> getAmountAndUnitsInputValues()
99+
{
100+
enableAmountAndUnits();
101+
String amountVal = getWrapper().getFormElement(getAmountInput());
102+
String unitVal = getValueForReactSelect(getAmountUnitSelect());
103+
return new Pair<>(amountVal, unitVal);
104+
}
105+
106+
public void enableAmountAndUnits()
107+
{
108+
ToggleButton toggle = new ToggleButton.ToggleButtonFinder(getDriver()).findOrNull(getAmountUnitsRow());
109+
if (toggle != null && !toggle.isOn())
110+
{
111+
toggle.set(true);
112+
_changeCounter++;
113+
}
114+
}
115+
116+
public void disableAmountAndUnits()
117+
{
118+
ToggleButton toggle = new ToggleButton.ToggleButtonFinder(getDriver()).findOrNull(getAmountUnitsRow());
119+
if (toggle != null && toggle.isOn())
120+
{
121+
toggle.set(false);
122+
_changeCounter--;
123+
}
124+
}
125+
126+
private WebElement getAmountInput()
127+
{
128+
return elementCache().amountInputLoc.findElement(getAmountUnitsRow());
129+
}
130+
131+
public ReactSelect getAmountUnitSelect()
132+
{
133+
enableAmountAndUnits();
134+
return new ReactSelect(getAmountUnitsRow(), getDriver());
135+
}
136+
137+
public void setAmountUnit(String amount, String unit)
138+
{
139+
enableAmountAndUnits();
140+
141+
if (amount != null)
142+
getWrapper().setFormElement(getAmountInput(), amount);
143+
if (unit != null)
144+
{
145+
ReactSelect reactSelect = getAmountUnitSelect();
146+
if (!unit.isEmpty())
147+
reactSelect.select(unit);
148+
else
149+
reactSelect.clearSelection();
150+
}
151+
152+
if (amount != null && unit != null)
153+
_changeCounter++;
154+
}
155+
156+
@Override
157+
protected abstract ElementCache newElementCache();
158+
159+
@Override
160+
protected ElementCache elementCache()
161+
{
162+
return (ElementCache) super.elementCache();
163+
}
164+
165+
protected abstract class ElementCache extends ModalDialog.ElementCache
166+
{
167+
protected final Locator textInputLoc = Locator.tagWithAttribute("input", "type", "text");
168+
protected final Locator checkboxLoc = Locator.tagWithAttribute("input", "type", "checkbox");
169+
protected final Locator.XPathLocator amountInputLoc = Locator.tag("input").withAttribute("aria-label", "Amount");
170+
171+
protected final Map<String, WebElement> _rows = new HashMap<>();
172+
173+
/**
174+
* Returns the form row div that contains the controls for the given field.
175+
*/
176+
public abstract WebElement formRow(CharSequence fieldIdentifier);
177+
178+
// For composite fields (e.g. StoredAmount + Units) that render a <div> label instead of <label for="...">,
179+
private WebElement formRowByControlLabel(String fieldLabel)
180+
{
181+
return _rows.computeIfAbsent(fieldLabel, k ->
182+
Locator.tagWithClass("div", "row")
183+
.withChild(Locator.tagWithClass("div", "control-label").withText(fieldLabel))
184+
.waitForElement(this, WAIT_FOR_JAVASCRIPT));
185+
}
186+
187+
public FilteringReactSelect selectionField(CharSequence fieldIdentifier)
188+
{
189+
return new FilteringReactSelect(formRow(fieldIdentifier), getDriver());
190+
}
191+
192+
public Checkbox checkbox(CharSequence fieldIdentifier)
193+
{
194+
return new Checkbox(checkboxLoc.findElement(formRow(fieldIdentifier)));
195+
}
196+
197+
public Input textInput(CharSequence fieldIdentifier)
198+
{
199+
return new Input(textInputLoc.findElement(formRow(fieldIdentifier)), getDriver());
200+
}
201+
202+
public Input textArea(CharSequence fieldIdentifier)
203+
{
204+
return new Input(Locator.tag("textarea").findElement(formRow(fieldIdentifier)), getDriver());
205+
}
206+
207+
public ReactDateTimePicker dateInput(CharSequence fieldIdentifier)
208+
{
209+
return new ReactDateTimePicker.ReactDateTimeInputFinder(getDriver()).find(formRow(fieldIdentifier));
210+
}
211+
212+
public FileAttachmentContainer fileUploadField(CharSequence fieldIdentifier)
213+
{
214+
return new FileAttachmentContainer(formRow(fieldIdentifier), getDriver());
215+
}
216+
}
217+
}

0 commit comments

Comments
 (0)