Skip to content

Commit 5ced1d4

Browse files
authored
Refactor DataRegionTable to handle tricky characters better (#2513)
- Update `DataRegionTable` to use `FieldReferenceManager.java` to organize and identify columns - Clean up numerous IntelliJ warnings - Remove usages of some deprecated `DataRegionTable` methods
1 parent 58fb876 commit 5ced1d4

25 files changed

Lines changed: 481 additions & 378 deletions
Lines changed: 66 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,45 @@
11
package org.labkey.test.components.ui.grids;
22

3-
import org.apache.commons.lang3.mutable.Mutable;
4-
import org.apache.commons.lang3.mutable.MutableObject;
3+
import org.jetbrains.annotations.NotNull;
4+
import org.jetbrains.annotations.Nullable;
55
import org.labkey.test.params.FieldKey;
66
import org.labkey.test.params.WrapsFieldKey;
7+
import org.labkey.test.util.CachingSupplier;
78
import org.labkey.test.util.selenium.WebElementUtils;
89
import org.openqa.selenium.NoSuchElementException;
910
import org.openqa.selenium.WebElement;
1011

11-
import java.util.Collections;
1212
import java.util.LinkedHashMap;
1313
import java.util.List;
1414
import java.util.Map;
1515
import java.util.Objects;
16+
import java.util.function.Function;
1617
import java.util.function.Supplier;
18+
import java.util.stream.Collectors;
1719

1820
public class FieldReferenceManager
1921
{
2022
private final List<FieldReference> _fieldReferences;
21-
private final Map<FieldKey, FieldReference> fieldKeys = new LinkedHashMap<>();
22-
private final Map<String, FieldReference> fieldLabels = new LinkedHashMap<>();
23+
private final Map<Integer, FieldReference> _fieldsByIndex;
24+
private final Map<FieldKey, FieldReference> _fieldKeys = new LinkedHashMap<>();
25+
private final Map<String, FieldReference> _fieldLabels = new LinkedHashMap<>();
2326

2427
public <T extends FieldReference> FieldReferenceManager(List<T> columnHeaders)
2528
{
26-
this._fieldReferences = Collections.unmodifiableList(columnHeaders);
29+
_fieldReferences = List.copyOf(columnHeaders);
30+
_fieldsByIndex = columnHeaders.stream().collect(Collectors.toMap(FieldReference::getDomIndex, Function.identity()));
2731
}
2832

2933
public List<FieldReference> getColumnHeaders()
3034
{
3135
return _fieldReferences;
3236
}
3337

38+
public FieldReference getColumnHeader(int index)
39+
{
40+
return _fieldsByIndex.get(index);
41+
}
42+
3443
/**
3544
* Find field by uncertain field identifier in order of precedence:
3645
* <ol>
@@ -40,7 +49,7 @@ public List<FieldReference> getColumnHeaders()
4049
* <li>Field Label</li>
4150
* </ol>
4251
*/
43-
public final FieldReference findFieldReference(CharSequence fieldIdentifier)
52+
public final @NotNull FieldReference findFieldReference(CharSequence fieldIdentifier)
4453
{
4554
List<Supplier<FieldReference>> options;
4655

@@ -64,20 +73,32 @@ public final FieldReference findFieldReference(CharSequence fieldIdentifier)
6473
.orElseThrow(() -> new NoSuchElementException("Unable to locate field: " + fieldIdentifier));
6574
}
6675

76+
public final @Nullable FieldReference findFieldReferenceOrNull(CharSequence fieldIdentifier)
77+
{
78+
try
79+
{
80+
return findFieldReference(fieldIdentifier);
81+
}
82+
catch (NoSuchElementException e)
83+
{
84+
return null;
85+
}
86+
}
87+
6788
private FieldReference findColumnHeaderByFieldKey(FieldKey fieldIdentifier)
6889
{
69-
if (fieldKeys.containsKey(fieldIdentifier))
90+
if (_fieldKeys.containsKey(fieldIdentifier))
7091
{
71-
return fieldKeys.get(fieldIdentifier);
92+
return _fieldKeys.get(fieldIdentifier);
7293
}
73-
else if (fieldKeys.size() < _fieldReferences.size())
94+
else if (_fieldKeys.size() < _fieldReferences.size())
7495
{
7596
for (FieldReference header : _fieldReferences)
7697
{
77-
if (!fieldKeys.containsValue(header))
98+
if (!_fieldKeys.containsValue(header))
7899
{
79100
FieldKey fieldKey = header.getFieldKey();
80-
fieldKeys.put(fieldKey, header);
101+
_fieldKeys.put(fieldKey, header);
81102
if (fieldKey.equals(fieldIdentifier))
82103
{
83104
return header;
@@ -91,18 +112,18 @@ else if (fieldKeys.size() < _fieldReferences.size())
91112

92113
private FieldReference findColumnHeaderByLabel(String label)
93114
{
94-
if (fieldLabels.containsKey(label))
115+
if (_fieldLabels.containsKey(label))
95116
{
96-
return fieldLabels.get(label);
117+
return _fieldLabels.get(label);
97118
}
98-
else if (fieldLabels.size() < _fieldReferences.size())
119+
else if (_fieldLabels.size() < _fieldReferences.size())
99120
{
100121
for (FieldReference header : _fieldReferences)
101122
{
102-
if (!fieldLabels.containsValue(header))
123+
if (!_fieldLabels.containsValue(header))
103124
{
104125
String columnLabel = header.getLabel();
105-
fieldLabels.put(columnLabel, header);
126+
_fieldLabels.put(columnLabel, header);
106127
if (columnLabel.equals(label))
107128
{
108129
return header;
@@ -118,8 +139,8 @@ public static class FieldReference
118139
{
119140
private final WebElement _element;
120141
private final int _domIndex;
121-
private final Mutable<String> _fieldLabel = new MutableObject<>();
122-
private final Mutable<FieldKey> _fieldKey = new MutableObject<>();
142+
private final CachingSupplier<String> _fieldLabel = new CachingSupplier<>(this::labelSupplier);
143+
private final CachingSupplier<FieldKey> _fieldKey = new CachingSupplier<>(this::fieldKeySupplier);
123144

124145
public FieldReference(WebElement element, int domIndex)
125146
{
@@ -134,34 +155,12 @@ public WebElement getElement()
134155

135156
public FieldKey getFieldKey()
136157
{
137-
if (_fieldKey.getValue() == null)
138-
{
139-
String path = _element.getDomAttribute("data-fieldkey");
140-
if (path == null)
141-
{
142-
// Some grids don't have a field key, but have a similar value in the ID attribute
143-
path = _element.getDomAttribute("id");
144-
}
145-
146-
if (path != null)
147-
{
148-
_fieldKey.setValue(FieldKey.fromFieldKey(path));
149-
}
150-
else
151-
{
152-
_fieldKey.setValue(FieldKey.EMPTY);
153-
}
154-
}
155-
return _fieldKey.getValue();
158+
return _fieldKey.get();
156159
}
157160

158161
public String getLabel()
159162
{
160-
if (_fieldLabel.getValue() == null)
161-
{
162-
_fieldLabel.setValue(WebElementUtils.getTextContent(getElement()).trim());
163-
}
164-
return _fieldLabel.getValue();
163+
return _fieldLabel.get();
165164
}
166165

167166
public String getName()
@@ -173,5 +172,29 @@ public int getDomIndex()
173172
{
174173
return _domIndex;
175174
}
175+
176+
protected String labelSupplier()
177+
{
178+
return WebElementUtils.getTextContent(getElement()).trim();
179+
}
180+
181+
protected FieldKey fieldKeySupplier()
182+
{
183+
String path = getElement().getDomAttribute("data-fieldkey");
184+
if (path == null)
185+
{
186+
// Some grids don't have a field key, but have a similar value in the ID attribute
187+
path = getElement().getDomAttribute("id");
188+
}
189+
190+
if (path != null)
191+
{
192+
return FieldKey.fromFieldKey(path);
193+
}
194+
else
195+
{
196+
return FieldKey.EMPTY;
197+
}
198+
}
176199
}
177200
}

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

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,21 +59,21 @@ public void setFields(Map<String, ?> fields)
5959
for (Map.Entry<String, ?> entry : fields.entrySet())
6060
{
6161
Object value = entry.getValue();
62-
if (value instanceof String)
62+
if (value instanceof String s)
6363
{
64-
setField(entry.getKey(), (String) value);
64+
setField(entry.getKey(), s);
6565
}
66-
else if (value instanceof Boolean)
66+
else if (value instanceof Boolean b)
6767
{
68-
setField(entry.getKey(), (Boolean) value);
68+
setField(entry.getKey(), b);
6969
}
70-
else if (value instanceof Integer)
70+
else if (value instanceof Integer i)
7171
{
72-
setField(entry.getKey(), (Integer) value);
72+
setField(entry.getKey(), i);
7373
}
74-
else if (value instanceof File)
74+
else if (value instanceof File f)
7575
{
76-
setField(entry.getKey(), (File) value);
76+
setField(entry.getKey(), f);
7777
}
7878
else
7979
{

src/org/labkey/test/pages/study/OverviewPage.java

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,11 @@
1616
package org.labkey.test.pages.study;
1717

1818
import org.jetbrains.annotations.Nullable;
19-
import org.labkey.test.CachingLocator;
2019
import org.labkey.test.Locator;
2120
import org.labkey.test.WebDriverWrapper;
2221
import org.labkey.test.WebTestHelper;
2322
import org.labkey.test.pages.LabKeyPage;
24-
import org.labkey.test.selenium.LazyWebElement;
23+
import org.labkey.test.util.CachingSupplier;
2524
import org.openqa.selenium.WebDriver;
2625
import org.openqa.selenium.WebElement;
2726

@@ -133,7 +132,7 @@ public Map<String, List<CountPair>> getDatasetRowData()
133132
public Map<String, List<CountPair>> getDatasetRowData(@Nullable Integer leftVisitIndex, @Nullable Integer endVisitIndex)
134133
{
135134
Map<String, List<CountPair>> datasetRowData = new HashMap<>();
136-
List<WebElement> overviewRows = elementCache().getStudyOverviewRows();
135+
List<WebElement> overviewRows = elementCache().studyOverviewRows.get();
137136
overviewRows = overviewRows.subList(1, overviewRows.size());
138137

139138
for (WebElement row : overviewRows)
@@ -178,7 +177,7 @@ else if (!countStr.isEmpty())
178177

179178
public List<String> getVisits()
180179
{
181-
WebElement headerRow = elementCache().getStudyOverviewRows().get(0);
180+
WebElement headerRow = elementCache().studyOverviewRows.get().get(0);
182181
List<WebElement> visitCells = Locator.css("td").findElements(headerRow);
183182
visitCells = visitCells.subList(1, visitCells.size() - 1);
184183

@@ -193,16 +192,13 @@ protected Elements newElementCache()
193192

194193
protected class Elements extends LabKeyPage<?>.ElementCache
195194
{
196-
public final WebElement participantCountCheckbox = new LazyWebElement(Locator.checkboxByNameAndValue("visitStatistic", "ParticipantCount"), this);
197-
public final WebElement rowCountCheckbox = new LazyWebElement(Locator.checkboxByNameAndValue("visitStatistic", "RowCount"), this);
198-
public final WebElement studyOverview = new LazyWebElement(Locator.tagWithId("table", "studyOverview"), this);
195+
public final WebElement participantCountCheckbox = Locator.checkboxByNameAndValue("visitStatistic", "ParticipantCount").findWhenNeeded(this);
196+
public final WebElement rowCountCheckbox = Locator.checkboxByNameAndValue("visitStatistic", "RowCount").findWhenNeeded(this);
197+
public final WebElement studyOverview = Locator.tagWithId("table", "studyOverview").findWhenNeeded(this);
199198

200-
private final Locator studyOverviewRow = new CachingLocator(Locator.CssLocator.union(Locator.css(".labkey-row"), Locator.css(".labkey-alternate-row")));
199+
private final Locator studyOverviewRow = Locator.CssLocator.union(Locator.css(".labkey-row"), Locator.css(".labkey-alternate-row"));
201200

202-
public List<WebElement> getStudyOverviewRows()
203-
{
204-
return studyOverviewRow.findElements(studyOverview);
205-
}
201+
public CachingSupplier<List<WebElement>> studyOverviewRows = new CachingSupplier<>(() -> studyOverviewRow.findElements(studyOverview));
206202
}
207203

208204
public static class CountPair

src/org/labkey/test/params/FieldKey.java

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import org.apache.commons.lang3.StringUtils;
44
import org.jetbrains.annotations.NotNull;
5-
import org.jetbrains.annotations.Nullable;
65

76
import java.util.ArrayList;
87
import java.util.Arrays;
@@ -66,22 +65,15 @@ public static FieldKey fromParts(String... parts)
6665
* @param fieldKey String or FieldKey
6766
* @return FieldKey representation of the String, or the identity if a FieldKey was provided
6867
*/
69-
public static @Nullable FieldKey fromFieldKey(CharSequence fieldKey)
68+
public static FieldKey fromFieldKey(CharSequence fieldKey)
7069
{
7170
if (fieldKey instanceof WrapsFieldKey fk)
7271
{
7372
return fk.getFieldKey();
7473
}
7574
else
7675
{
77-
try
78-
{
79-
return fromParts(Arrays.stream(fieldKey.toString().split(SEPARATOR)).map(FieldKey::decodePart).toList());
80-
}
81-
catch (IllegalArgumentException iae)
82-
{
83-
return null;
84-
}
76+
return fromParts(Arrays.stream(fieldKey.toString().split(SEPARATOR)).map(FieldKey::decodePart).toList());
8577
}
8678
}
8779

@@ -149,6 +141,10 @@ public String getName()
149141
return _name;
150142
}
151143

144+
/**
145+
* Inverse of {@link #fromParts(String...)}
146+
* @return decoded parts of the field key
147+
*/
152148
public String[] getNameArray()
153149
{
154150
return Arrays.stream(_fieldKey.split(SEPARATOR)).map(FieldKey::decodePart).toArray(String[]::new);

src/org/labkey/test/tests/AbstractExportTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@
3535
import java.util.HashSet;
3636
import java.util.List;
3737

38+
import static org.hamcrest.MatcherAssert.assertThat;
3839
import static org.junit.Assert.assertEquals;
39-
import static org.junit.Assert.assertThat;
4040
import static org.junit.Assert.assertTrue;
4141

4242
/**
@@ -103,7 +103,7 @@ public void preTest()
103103
exportHelper = new DataRegionExportHelper(dataRegion);
104104

105105
if (hasSelectors())
106-
dataRegion.uncheckAll();
106+
dataRegion.uncheckAllOnPage();
107107
}
108108

109109
@Test

src/org/labkey/test/tests/ButtonCustomizationTest.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,13 @@
2525
import org.labkey.test.params.FieldDefinition;
2626
import org.labkey.test.params.FieldDefinition.ColumnType;
2727
import org.labkey.test.util.DataRegionTable;
28+
import org.labkey.test.util.DataRegionTable.DataRegionFinder;
2829
import org.labkey.test.util.PortalHelper;
2930
import org.labkey.test.util.WikiHelper;
3031

3132
import java.util.Arrays;
3233
import java.util.List;
34+
import java.util.Map;
3335

3436
import static org.junit.Assert.assertTrue;
3537

@@ -101,12 +103,10 @@ public void testSteps()
101103
goToManageLists();
102104
clickAndWait(Locator.linkWithText(LIST_NAME));
103105
assertButtonNotPresent(METADATA_OVERRIDE_BUTTON);
104-
DataRegionTable.findDataRegion(this).clickInsertNewRow();
105-
setFormElement(Locator.name("quf_name"), "Seattle");
106-
clickButton("Submit");
107-
DataRegionTable.findDataRegion(this).clickInsertNewRow();
108-
setFormElement(Locator.name("quf_name"), "Portland");
109-
clickButton("Submit");
106+
new DataRegionFinder(getDriver()).find().clickInsertNewRow()
107+
.update(Map.of("name", "Seattle"));
108+
new DataRegionFinder(getDriver()).find().clickInsertNewRow()
109+
.update(Map.of("name", "Portland"));
110110

111111
// assert custom buttons can be added to the standard set:
112112
beginAt("/query/" + PROJECT_NAME + "/schema.view?schemaName=lists");
@@ -188,7 +188,7 @@ public void testSteps()
188188
Locator.lkButton(METADATA_LINK_BUTTON).waitForElement(getDriver(), WAIT_FOR_JAVASCRIPT)
189189
.getAttribute("class").contains("labkey-disabled-button"));
190190

191-
buttonRegion.checkCheckbox(buttonRegion.getIndexWhereDataAppears("Portland", "Name"));
191+
buttonRegion.checkCheckbox(buttonRegion.getRowIndex("Portland", "Name"));
192192
// wait for the button to enable:
193193
waitForElement(Locator.lkButton(METADATA_LINK_BUTTON), 10000);
194194

src/org/labkey/test/tests/DataRegionTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ private void dataRegionTest(URL url, String dataRegionName) throws MalformedURLE
277277
clickAndWait(selectionPart.append(Locator.tagWithClass("span", "show-selected")));
278278
assertEquals(5, table.getDataRowCount());
279279

280-
table.showAll();
280+
table.rowSelector().showAll();
281281
assertEquals(15, table.getDataRowCount());
282282
}
283283

0 commit comments

Comments
 (0)