Skip to content

Commit ad2281f

Browse files
DariaBodlabkey-tchadcnathelabkey-nickalabkey-danield
authored
Tests for multi choice value (#2872)
Co-authored-by: Trey Chadick <tchad@labkey.com> Co-authored-by: Cory Nathe <cnathe@labkey.com> Co-authored-by: Nick Kerr <nickk@labkey.com> Co-authored-by: Dan Duffek <danield@labkey.com> Co-authored-by: Susan Hert <susanh@labkey.com> Co-authored-by: Josh Eckels <jeckels@labkey.com>
1 parent e128c2a commit ad2281f

13 files changed

Lines changed: 194 additions & 30 deletions

src/org/labkey/test/components/domain/DomainFieldRow.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,11 @@ public DomainFieldRow clickRemoveOntologyConcept()
767767
// behind the scenes. Because of that the validator aspect of the TextChoice field is hidden from the user (just like
768768
// it is in the product).
769769

770+
public void setAllowMultipleSelections(Boolean allowMultipleSelections)
771+
{
772+
elementCache().allowMultipleSelectionsCheckbox.set(allowMultipleSelections);
773+
}
774+
770775
/**
771776
* Set the list of allowed values for a TextChoice field.
772777
*
@@ -1702,6 +1707,10 @@ protected class ElementCache extends WebDriverComponent.ElementCache
17021707
public final WebElement domainWarningIcon = Locator.tagWithClass("span", "domain-warning-icon")
17031708
.findWhenNeeded(this);
17041709

1710+
// text choice field option
1711+
public final Checkbox allowMultipleSelectionsCheckbox = new Checkbox(Locator.tagWithClass("input", "domain-text-choice-multi")
1712+
.refindWhenNeeded(this).withTimeout(WAIT_FOR_JAVASCRIPT));
1713+
17051714
// lookup field options
17061715
public final Select lookupContainerSelect = SelectWrapper.Select(Locator.name("domainpropertiesrow-lookupContainer"))
17071716
.findWhenNeeded(this);

src/org/labkey/test/components/domain/DomainFormPanel.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,10 @@ else if (validator instanceof FieldDefinition.TextChoiceValidator textChoiceVali
236236
throw new IllegalArgumentException("TextChoice fields cannot have additional validators.");
237237
}
238238
fieldRow.setTextChoiceValues(textChoiceValidator.getValues());
239+
if(fieldDefinition.getType() == FieldDefinition.ColumnType.MultiValueTextChoice)
240+
{
241+
fieldRow.setAllowMultipleSelections(true);
242+
}
239243
}
240244
else
241245
{

src/org/labkey/test/components/ui/FilterStatusValue.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,10 @@ public void remove()
5050
{
5151
String originalText = getText();
5252
getWrapper().mouseOver(getComponentElement());
53-
getWrapper().mouseOver(elementCache().icon);
54-
WebDriverWrapper.waitFor(()-> isActive() && isClose(),
55-
"The filter status item with text ["+getText()+"] did not become active.", 500);
53+
if(elementCache().popover.isDisplayed())
54+
{
55+
getWrapper().mouseOut();
56+
}
5657
elementCache().icon.click();
5758

5859
// If the item you're dismissing is not the rightmost, it won't become stale; instead, its text will
@@ -94,6 +95,8 @@ protected class ElementCache extends Component<?>.ElementCache
9495
public final WebElement textSpan = Locator.tag("span").refindWhenNeeded(getComponentElement());
9596

9697
public final WebElement icon = Locator.tag("i").findWhenNeeded(getComponentElement());
98+
99+
public final WebElement popover = Locator.tag("div").withClass("lk-popover popover bottom").findWhenNeeded(_driver);
97100
}
98101

99102

src/org/labkey/test/components/ui/entities/EntityBulkUpdateDialog.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,19 @@ public EntityBulkUpdateDialog setSelectionField(CharSequence fieldIdentifier, Li
124124
return this;
125125
}
126126

127+
/**
128+
* Clear the field (fieldIdentifier).
129+
*
130+
* @param fieldIdentifier Identifier for the field; name ({@link String}) or fieldKey ({@link FieldKey})
131+
* @return this component
132+
*/
133+
public EntityBulkUpdateDialog clearSelection(CharSequence fieldIdentifier)
134+
{
135+
FilteringReactSelect reactSelect = enableSelectionField(fieldIdentifier);
136+
reactSelect.clearSelection();
137+
return this;
138+
}
139+
127140
/**
128141
* @param fieldIdentifier Identifier for the field; name ({@link String}) or fieldKey ({@link FieldKey})
129142
* @param selectValue value to select

src/org/labkey/test/components/ui/grids/EditableGrid.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,12 @@ public void setCellValue(CharSequence columnToSearch, String valueToSearch, Char
429429
setCellValue(getRowIndex(columnToSearch, valueToSearch), columnToSet, valueToSet);
430430
}
431431

432+
public void overwriteCellValue(CharSequence columnToSearch, String valueToSearch, CharSequence columnToSet, Object valueToSet)
433+
{
434+
clearCellValue(getRowIndex(columnToSearch, valueToSearch), columnToSet);
435+
setCellValue(getRowIndex(columnToSearch, valueToSearch), columnToSet, valueToSet);
436+
}
437+
432438
/**
433439
* <p>
434440
* For the identified row set the value in the identified column.
@@ -507,6 +513,7 @@ public WebElement setCellValue(int row, CharSequence columnIdentifier, Object va
507513

508514
if (value instanceof List)
509515
{
516+
510517
// If this is a list assume that it will need a lookup.
511518
List<String> values = (List) value;
512519

@@ -975,6 +982,7 @@ public String copyCurrentSelection() throws IOException, UnsupportedFlavorExcept
975982

976983
public void dragFill(WebElement startCell, WebElement endCell)
977984
{
985+
dismissPopover();
978986
Locator.XPathLocator selectionHandleLoc = Locator.byClass("cell-selection-handle");
979987
WebElement selectionHandle = selectionHandleLoc.findElement(startCell);
980988
dragToCell(selectionHandle, endCell);

src/org/labkey/test/components/ui/grids/ResponsiveGrid.java

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import org.labkey.test.components.react.ReactCheckBox;
1818
import org.labkey.test.components.ui.grids.FieldReferenceManager.FieldReference;
1919
import org.labkey.test.components.ui.search.FilterExpressionPanel;
20+
import org.labkey.test.components.ui.search.FilterFacetedPanel;
2021
import org.labkey.test.params.FieldKey;
2122
import org.labkey.test.util.selenium.WebElementUtils;
2223
import org.openqa.selenium.Keys;
@@ -40,6 +41,13 @@
4041
import static org.hamcrest.CoreMatchers.is;
4142
import static org.hamcrest.MatcherAssert.assertThat;
4243
import static org.junit.Assert.assertEquals;
44+
import static org.labkey.remoteapi.query.Filter.Operator.ARRAY_CONTAINS_ALL;
45+
import static org.labkey.remoteapi.query.Filter.Operator.ARRAY_CONTAINS_ANY;
46+
import static org.labkey.remoteapi.query.Filter.Operator.ARRAY_CONTAINS_EXACT;
47+
import static org.labkey.remoteapi.query.Filter.Operator.ARRAY_CONTAINS_NONE;
48+
import static org.labkey.remoteapi.query.Filter.Operator.ARRAY_CONTAINS_NOT_EXACT;
49+
import static org.labkey.remoteapi.query.Filter.Operator.ARRAY_ISEMPTY;
50+
import static org.labkey.remoteapi.query.Filter.Operator.ARRAY_ISNOTEMPTY;
4351
import static org.labkey.test.WebDriverWrapper.waitFor;
4452

4553
public class ResponsiveGrid<T extends ResponsiveGrid<?>> extends WebDriverComponent<ResponsiveGrid<T>.ElementCache> implements UpdatingComponent
@@ -232,20 +240,33 @@ public String filterColumnExpectingError(CharSequence columnIdentifier, Filter.O
232240
return errorMsg;
233241
}
234242

243+
private static final List<Filter.Operator> ARRAY_OPERATORS = List.of(ARRAY_CONTAINS_ALL, ARRAY_CONTAINS_ANY, ARRAY_CONTAINS_EXACT, ARRAY_CONTAINS_NONE,
244+
ARRAY_CONTAINS_NOT_EXACT, ARRAY_ISEMPTY, ARRAY_ISNOTEMPTY);
245+
235246
private GridFilterModal initFilterColumn(CharSequence columnIdentifier, Filter.Operator operator, Object value)
236247
{
237248
clickColumnMenuItem(columnIdentifier, "Filter...", false);
238249
GridFilterModal filterModal = new GridFilterModal(getDriver(), this);
239250
if (operator != null)
240251
{
241-
if (operator.equals(Filter.Operator.IN) && value instanceof List<?>)
252+
if (operator.equals(Filter.Operator.IN) && value instanceof List<?> || ARRAY_OPERATORS.contains(operator))
242253
{
243-
List<String> values = (List<String>) value;
244-
filterModal.selectFacetTab().selectValue(values.get(0));
245-
filterModal.selectFacetTab().checkValues(values.toArray(String[]::new));
254+
FilterFacetedPanel filterPanel = filterModal.selectFacetTab();
255+
if (ARRAY_OPERATORS.contains(operator))
256+
{
257+
filterPanel.selectArrayFilterOperator(operator);
258+
}
259+
if (value != null)
260+
{
261+
List<String> values = (List<String>) value;
262+
filterPanel.selectValue(values.get(0));
263+
filterPanel.checkValues(values.toArray(String[]::new));
264+
}
246265
}
247266
else
267+
{
248268
filterModal.selectExpressionTab().setFilter(new FilterExpressionPanel.Expression(operator, value));
269+
}
249270
}
250271
return filterModal;
251272
}
@@ -385,15 +406,16 @@ public T selectRow(int index, boolean checked)
385406

386407
/**
387408
* Finds the first row with the specified texts in the specified columns, and sets its checkbox
388-
* @param partialMap key-column (fieldKey, name, or label), value-text in that column
389-
* @param checked the desired checkbox state
409+
*
410+
* @param partialMap key-column (fieldKey, name, or label), value-text in that column
411+
* @param checked the desired checkbox state
390412
* @return this grid
391413
*/
392414
public T selectRow(Map<String, String> partialMap, boolean checked)
393415
{
394416
GridRow row = getRow(partialMap);
395417
selectRowAndVerifyCheckedCounts(row, checked);
396-
getWrapper().log("Row described by map ["+partialMap+"] selection state set to + ["+row.isSelected()+"]");
418+
getWrapper().log("Row described by map [" + partialMap + "] selection state set to + [" + row.isSelected() + "]");
397419

398420
return getThis();
399421
}

src/org/labkey/test/components/ui/search/FilterFacetedPanel.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package org.labkey.test.components.ui.search;
22

33
import org.apache.commons.lang3.StringUtils;
4+
import org.labkey.remoteapi.query.Filter;
45
import org.labkey.test.Locator;
56
import org.labkey.test.components.Component;
67
import org.labkey.test.components.WebDriverComponent;
78
import org.labkey.test.components.html.Checkbox;
89
import org.labkey.test.components.html.Input;
10+
import org.labkey.test.components.react.ReactSelect;
911
import org.labkey.test.components.ui.FilterStatusValue;
1012
import org.openqa.selenium.WebDriver;
1113
import org.openqa.selenium.WebElement;
@@ -48,6 +50,15 @@ public void selectValue(String value)
4850
elementCache().findCheckboxLabel(value).click();
4951
}
5052

53+
/**
54+
* Select a filer by clicking its label. Right now this method relevant only for multi-value text choice.
55+
* @param operator desired filter value
56+
*/
57+
public void selectArrayFilterOperator(Filter.Operator operator)
58+
{
59+
elementCache().arrayFilterOperatorSelect.select(operator.getDisplayValue());
60+
}
61+
5162
/**
5263
* Check single facet value by label to see if it is checked or not.
5364
* @param value desired value
@@ -123,6 +134,8 @@ protected class ElementCache extends Component<?>.ElementCache
123134
{
124135
protected final Input filterInput =
125136
Input(Locator.id("filter-faceted__typeahead-input"), getDriver()).findWhenNeeded(this);
137+
protected final ReactSelect arrayFilterOperatorSelect =
138+
new ReactSelect.ReactSelectFinder(getDriver()).index(0).findWhenNeeded(this);
126139
protected final WebElement checkboxSection =
127140
Locator.byClass("labkey-wizard-pills").index(0).refindWhenNeeded(this);
128141
protected final Locator.XPathLocator checkboxLabelLoc

src/org/labkey/test/pages/DatasetInsertPage.java

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.openqa.selenium.WebDriver;
2323
import org.openqa.selenium.WebElement;
2424

25+
import java.util.List;
2526
import java.util.Map;
2627

2728
import static org.labkey.test.util.EscapeUtil.FORM_FIELD_PREFIX;
@@ -45,26 +46,26 @@ protected void waitForReady()
4546
waitForElement(Locator.tag("*").attributeStartsWith("name", FORM_FIELD_PREFIX));
4647
}
4748

48-
public void insert(Map<String, String> values)
49+
public void insert(Map<String, ?> values)
4950
{
5051
tryInsert(values);
5152

5253
assertElementNotPresent(Locators.labkeyError);
5354
}
5455

55-
public void insert(Map<String, String> values, boolean b, String s)
56+
public void insert(Map<String, ?> values, boolean b, String s)
5657
{
5758
tryInsert(values);
5859

5960
assertElementNotPresent(Locators.labkeyError);
6061
}
6162

62-
public void insertExpectingError(Map<String, String> values)
63+
public void insertExpectingError(Map<String, ?> values)
6364
{
6465
insertExpectingError(values, null);
6566
}
6667

67-
public void insertExpectingError(Map<String, String> values, String errorMsg)
68+
public void insertExpectingError(Map<String, ?> values, String errorMsg)
6869
{
6970
tryInsert(values);
7071

@@ -78,20 +79,20 @@ public void insertExpectingError(Map<String, String> values, String errorMsg)
7879
}
7980
}
8081

81-
private void tryInsert(Map<String, String> values)
82+
private void tryInsert(Map<String, ?> values)
8283
{
83-
for (Map.Entry<String, String> entry : values.entrySet())
84+
for (Map.Entry<String, ?> entry : values.entrySet())
8485
{
85-
WebElement fieldInput = Locator.name(EscapeUtil.getFormFieldName(entry.getKey())).findElement(getDriver());
86+
WebElement fieldInput = Locator.tag("*").attributeEndsWith("name", EscapeUtil.getFormFieldName(entry.getKey())).findElement(getDriver());
8687
String type = fieldInput.getAttribute("type");
8788
switch (type)
8889
{
8990
case "text":
9091
case "file":
91-
setFormElement(fieldInput, entry.getValue());
92+
setFormElement(fieldInput, entry.getValue().toString());
9293
break;
9394
case "checkbox":
94-
if (Boolean.valueOf(entry.getValue()))
95+
if (Boolean.valueOf(entry.getValue().toString()))
9596
checkCheckbox(fieldInput);
9697
else
9798
uncheckCheckbox(fieldInput);
@@ -101,10 +102,19 @@ private void tryInsert(Map<String, String> values)
101102
switch (tag)
102103
{
103104
case "textarea":
104-
setFormElementJS(fieldInput, entry.getValue());
105+
setFormElementJS(fieldInput, entry.getValue().toString());
105106
break;
106107
case "select":
107-
selectOptionByText(fieldInput, entry.getValue());
108+
if (entry.getValue() instanceof List)
109+
{
110+
List<String> options = (List<String>) entry.getValue();
111+
for (String option : options)
112+
{
113+
selectOptionByText(fieldInput, option);
114+
}
115+
break;
116+
}
117+
selectOptionByText(fieldInput, entry.getValue().toString());
108118
break;
109119
default:
110120
throw new IllegalArgumentException("Update " + getClass().getSimpleName() + "#insert() to support field: " + entry.getKey() + ", tag = " + tag + ", type = " + type);

src/org/labkey/test/pages/query/UpdateQueryRowPage.java

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,16 @@
1111
import org.labkey.test.components.html.Checkbox;
1212
import org.labkey.test.components.html.Input;
1313
import org.labkey.test.components.html.OptionSelect;
14+
import org.labkey.test.components.html.SelectWrapper;
1415
import org.labkey.test.pages.LabKeyPage;
1516
import org.labkey.test.util.EscapeUtil;
1617
import org.openqa.selenium.WebDriver;
1718
import org.openqa.selenium.WebElement;
19+
import org.openqa.selenium.support.ui.Select;
1820

1921
import java.io.File;
2022
import java.util.HashMap;
23+
import java.util.List;
2124
import java.util.Map;
2225

2326
public class UpdateQueryRowPage extends LabKeyPage<UpdateQueryRowPage.ElementCache>
@@ -52,7 +55,7 @@ public static UpdateQueryRowPage beginAt(WebDriverWrapper webDriverWrapper, Stri
5255
public static UpdateQueryRowPage beginAtInsertRowPage(WebDriverWrapper webDriverWrapper, String containerPath, String schemaName, String queryName)
5356
{
5457
webDriverWrapper.beginAt(WebTestHelper.buildURL("query", containerPath, "insertQueryRow",
55-
Map.of("schemaName", schemaName, "query.queryName", queryName)));
58+
Map.of("schemaName", schemaName, "query.queryName", queryName)));
5659
return new UpdateQueryRowPage(webDriverWrapper.getDriver());
5760
}
5861

@@ -87,6 +90,10 @@ else if (value instanceof File f)
8790
{
8891
setField(entry.getKey(), f);
8992
}
93+
else if (value instanceof List l)
94+
{
95+
setField(entry.getKey(), l);
96+
}
9097
else
9198
{
9299
throw new IllegalArgumentException("Unsupported value type for '" + entry.getKey() + "': " + value.getClass().getName());
@@ -99,7 +106,7 @@ public UpdateQueryRowPage setField(String fieldName, String value)
99106
WebElement field = elementCache().findField(fieldName);
100107
if (field.getTagName().equals("select"))
101108
{
102-
setField(fieldName, OptionSelect.SelectOption.textOption(value));
109+
selectOptionByText(field, value);
103110
}
104111
else
105112
{
@@ -108,6 +115,14 @@ public UpdateQueryRowPage setField(String fieldName, String value)
108115
return this;
109116
}
110117

118+
public UpdateQueryRowPage setField(String fieldName, List<String> values)
119+
{
120+
Select field = elementCache().getMultiChoiceSelect(fieldName);
121+
field.deselectAll();
122+
values.forEach(field::selectByVisibleText);
123+
return this;
124+
}
125+
111126
public UpdateQueryRowPage setField(String fieldName, Boolean value)
112127
{
113128
new Checkbox(elementCache().findField(fieldName)).set(value);
@@ -136,12 +151,6 @@ public UpdateQueryRowPage setField(String fieldName, OptionSelect.SelectOption o
136151
return this;
137152
}
138153

139-
public UpdateQueryRowPage setMultiValueField(String fieldName, OptionSelect.SelectOption option)
140-
{
141-
new OptionSelect<>(elementCache().findField(fieldName, true)).selectOption(option);
142-
return this;
143-
}
144-
145154
public String getTextInputValue(String fieldName)
146155
{
147156
var input = new Input(elementCache().findField(fieldName), getDriver());
@@ -203,5 +212,11 @@ WebElement findField(String name)
203212
}
204213

205214
final WebElement submitButton = Locator.lkButton("Submit").findWhenNeeded(this);
215+
216+
Select getMultiChoiceSelect(String name)
217+
{
218+
return SelectWrapper.Select(Locator.name(EscapeUtil.getFormFieldName(name, true)))
219+
.find(getDriver());
220+
}
206221
}
207222
}

0 commit comments

Comments
 (0)