From 7e466741bd48ff77940f30d6e775fb1f8bd3d803 Mon Sep 17 00:00:00 2001 From: labkey-tchad Date: Wed, 6 Aug 2025 12:53:27 -0700 Subject: [PATCH 1/2] Handle double spaces in grid warning messages --- src/org/labkey/test/params/FieldInfo.java | 38 +++++++++++-------- .../tests/component/EditableGridTest.java | 7 ++-- src/org/labkey/test/util/TextUtils.java | 5 ++- 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/src/org/labkey/test/params/FieldInfo.java b/src/org/labkey/test/params/FieldInfo.java index f962aa8241..802ceab6a8 100644 --- a/src/org/labkey/test/params/FieldInfo.java +++ b/src/org/labkey/test/params/FieldInfo.java @@ -3,8 +3,10 @@ import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.labkey.test.params.FieldDefinition.ColumnType; +import org.labkey.test.util.CachingSupplier; import org.labkey.test.util.EscapeUtil; import org.labkey.test.util.TestDataGenerator; +import org.labkey.test.util.TextUtils; import java.util.Objects; import java.util.function.Consumer; @@ -17,22 +19,25 @@ public class FieldInfo implements CharSequence, WrapsFieldKey { private final FieldKey _fieldKey; - private final String _label; + private final String _rawLabel; private final ColumnType _columnType; private final Consumer _fieldDefinitionMutator; - private String _namePart; // used for random field generation to track the name part used + private final String _namePart; // used for random field generation to track the name part used + private final CachingSupplier _label = new CachingSupplier<>(() -> Objects.requireNonNullElseGet(getRawLabel(), () -> FieldDefinition.labelFromName(getName()))); + private final CachingSupplier _uiLabel = new CachingSupplier<>(() -> TextUtils.normalizeSpace(getLabel())); - private FieldInfo(FieldKey fieldKey, String label, ColumnType columnType, Consumer fieldDefinitionMutator) + private FieldInfo(FieldKey fieldKey, String label, ColumnType columnType, Consumer fieldDefinitionMutator, String namePart) { _fieldKey = fieldKey; - _label = label; + _rawLabel = label; _columnType = Objects.requireNonNullElse(columnType, ColumnType.String); _fieldDefinitionMutator = fieldDefinitionMutator; + _namePart = namePart; } public FieldInfo(String name, String label, ColumnType columnType) { - this(FieldKey.fromParts(name.trim()), label, columnType, null); + this(FieldKey.fromParts(name.trim()), label, columnType, null, null); } public FieldInfo(String name, String label) @@ -55,8 +60,7 @@ public FieldInfo(String name) */ public static FieldInfo random(String namePart, ColumnType columnType) { - FieldInfo field = new FieldInfo(TestDataGenerator.randomFieldName(namePart), columnType); - field.setNamePart(namePart); + FieldInfo field = new FieldInfo(FieldKey.fromParts(TestDataGenerator.randomFieldName(namePart)), null, columnType, null, namePart); return field; } @@ -82,19 +86,28 @@ public FieldInfo customizeFieldDefinition(Consumer fieldDefinit { throw new IllegalArgumentException("FieldDefinition customizer should not modify field label"); } - return new FieldInfo(_fieldKey, _label, _columnType, fieldDefinitionMutator); + return new FieldInfo(_fieldKey, _rawLabel, _columnType, fieldDefinitionMutator, _namePart); } @Contract(pure = true) protected String getRawLabel() { - return _label; + return _rawLabel; } @Contract(pure = true) public String getLabel() { - return Objects.requireNonNullElseGet(getRawLabel(), () -> FieldDefinition.labelFromName(_fieldKey.getName())); + return _label.get(); + } + + /** + * Get field label as it appears when rendered in browser + */ + @Contract(pure = true) + public String getUiLabel() + { + return _uiLabel.get(); } @Override @@ -175,11 +188,6 @@ private FieldDefinition getFieldDefinition(ColumnType columnType) return fieldDefinition; } - private void setNamePart(String namePart) - { - _namePart = namePart; - } - @Override public int length() { diff --git a/src/org/labkey/test/tests/component/EditableGridTest.java b/src/org/labkey/test/tests/component/EditableGridTest.java index 92a7cc60fb..d5cd5b240e 100644 --- a/src/org/labkey/test/tests/component/EditableGridTest.java +++ b/src/org/labkey/test/tests/component/EditableGridTest.java @@ -21,6 +21,7 @@ import org.labkey.test.params.experiment.SampleTypeDefinition; import org.labkey.test.params.list.IntListDefinition; import org.labkey.test.params.list.ListDefinition; +import org.labkey.test.util.TextUtils; import org.openqa.selenium.Dimension; import org.openqa.selenium.Keys; import org.openqa.selenium.WebElement; @@ -1341,11 +1342,11 @@ public void testInputCellValidation() log("Input empty string for required field should trigger cell warning."); testGrid.setCellValue(1, REQ_STR_FIELD, " "); checker().verifyEquals("Cell warning status not as expected at row " + 1 + " for col " + REQ_STR_FIELD.getLabel(), true, testGrid.hasCellError(1, REQ_STR_FIELD)); - checker().verifyEquals("Cell warning msg not as expected at row " + 1 + " for col " + REQ_STR_FIELD.getLabel(), REQ_STR_FIELD.getLabel() + " is required.", testGrid.getCellPopoverText(1, REQ_STR_FIELD)); + checker().verifyEquals("Cell warning msg not as expected at row " + 1 + " for col " + REQ_STR_FIELD.getLabel(), REQ_STR_FIELD.getUiLabel() + " is required.", testGrid.getCellPopoverText(1, REQ_STR_FIELD)); mouseOver(testGrid.getCell(0, "Row")); // dismiss warning popup testGrid.setCellValue(1, REQ_INT_FIELD, " "); checker().verifyEquals("Cell warning status not as expected at row " + 1 + " for col " + REQ_INT_FIELD.getLabel(), true, testGrid.hasCellError(1, REQ_INT_FIELD)); - checker().verifyEquals("Cell warning msg not as expected at row " + 1 + " for col " + REQ_INT_FIELD.getLabel(), REQ_INT_FIELD.getLabel() + " is required.", testGrid.getCellPopoverText(1, REQ_INT_FIELD)); + checker().verifyEquals("Cell warning msg not as expected at row " + 1 + " for col " + REQ_INT_FIELD.getLabel(), REQ_INT_FIELD.getUiLabel() + " is required.", testGrid.getCellPopoverText(1, REQ_INT_FIELD)); log("Correct values should remove cell warning, keep entering wrong values should update warning"); mouseOver(testGrid.getCell(0, "Row")); // dismiss warning popup @@ -1496,7 +1497,7 @@ private void verifyCellWarning(EditableGrid testGrid, List expectedWarni checker().verifyEquals("Cell warning status not as expected at row " + rowId + " for col " + field.getLabel(), !StringUtils.isEmpty(expectedWarning), testGrid.hasCellError(rowId, field)); if (!StringUtils.isEmpty(expectedWarning)) - checker().verifyEquals("Cell warning msg not as expected at row " + rowId + " for col " + field.getLabel(), expectedWarning, testGrid.getCellPopoverText(rowId, field)); + checker().verifyEquals("Cell warning msg not as expected at row " + rowId + " for col " + field.getLabel(), TextUtils.normalizeSpace(expectedWarning), testGrid.getCellPopoverText(rowId, field)); } } diff --git a/src/org/labkey/test/util/TextUtils.java b/src/org/labkey/test/util/TextUtils.java index 5b8a585cfd..97ec58700e 100644 --- a/src/org/labkey/test/util/TextUtils.java +++ b/src/org/labkey/test/util/TextUtils.java @@ -16,7 +16,10 @@ private TextUtils() {} */ public static String normalizeSpace(String value) { - return NS_PATTERN.matcher(value).replaceAll(" ").trim(); + if (value == null) + return value; + else + return NS_PATTERN.matcher(value).replaceAll(" ").trim(); } public static List normalizeSpace(List values) From 5b934ff6097487da8799fa6713bac140a08666f2 Mon Sep 17 00:00:00 2001 From: labkey-tchad Date: Wed, 6 Aug 2025 13:53:06 -0700 Subject: [PATCH 2/2] Handle double spaces in ListLookupTest --- src/org/labkey/test/params/FieldInfo.java | 5 ++--- .../test/tests/list/ListLookupTest.java | 22 ++++++++++++++----- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/org/labkey/test/params/FieldInfo.java b/src/org/labkey/test/params/FieldInfo.java index 802ceab6a8..073eaa5ca4 100644 --- a/src/org/labkey/test/params/FieldInfo.java +++ b/src/org/labkey/test/params/FieldInfo.java @@ -37,7 +37,7 @@ private FieldInfo(FieldKey fieldKey, String label, ColumnType columnType, Consum public FieldInfo(String name, String label, ColumnType columnType) { - this(FieldKey.fromParts(name.trim()), label, columnType, null, null); + this(FieldKey.fromParts(name.trim()), label, columnType, null, name); } public FieldInfo(String name, String label) @@ -60,8 +60,7 @@ public FieldInfo(String name) */ public static FieldInfo random(String namePart, ColumnType columnType) { - FieldInfo field = new FieldInfo(FieldKey.fromParts(TestDataGenerator.randomFieldName(namePart)), null, columnType, null, namePart); - return field; + return new FieldInfo(FieldKey.fromParts(TestDataGenerator.randomFieldName(namePart)), null, columnType, null, namePart); } /** diff --git a/src/org/labkey/test/tests/list/ListLookupTest.java b/src/org/labkey/test/tests/list/ListLookupTest.java index 056a1a0115..1e36e7b33e 100644 --- a/src/org/labkey/test/tests/list/ListLookupTest.java +++ b/src/org/labkey/test/tests/list/ListLookupTest.java @@ -26,6 +26,8 @@ import java.util.Map; import static org.junit.Assert.assertEquals; +import static org.labkey.test.params.FieldDefinition.labelFromName; +import static org.labkey.test.util.TextUtils.normalizeSpace; // Issue 52098, Issue 49422 @Category({Daily.class, Data.class, Hosting.class}) @@ -122,7 +124,8 @@ public void testWithoutValidatorOrAlternateKeys() throws IOException, CommandExc String error = importDataPage .setText(bulkData) .submitExpectingError(); - checker().withScreenshot().verifyEquals("Error message for invalid primary key not as expected", "Could not convert value 'noneSuch' (String) for Integer field '" + lookFromLookupFieldName + "'", error); + checker().withScreenshot().verifyEquals("Error message for invalid primary key not as expected", + "Could not convert value 'noneSuch' (String) for Integer field '" + normalizeSpace(lookFromLookupFieldName) + "'", error); } @Test @@ -168,7 +171,8 @@ public void testWithoutValidatorWithAlternateKeys() throws IOException, CommandE .setText(bulkData) .setImportLookupByAlternateKey(true) .submitExpectingError(); - checker().withScreenshot().verifyEquals("Error message after supplying invalid alternate key not as expected", "Value 'NotAValue' not found for field " + lookFromLookupFieldName + " in the current context.", error); + checker().withScreenshot().verifyEquals("Error message after supplying invalid alternate key not as expected", + "Value 'NotAValue' not found for field " + normalizeSpace(lookFromLookupFieldName) + " in the current context.", error); } @Test @@ -196,13 +200,16 @@ public void testWithLookupValidatorWithoutAlternateKeys() throws IOException, Co String error = importDataPage .setText(tsvFromColumn(List.of(lookFromLookupFieldName, "1000"))) .submitExpectingError(); - checker().withScreenshot().verifyEquals("Error message for invalid primary key value not as expected", "Value '1000' was not present in lookup target 'lists." + lookToListName + "' for field '" + FieldDefinition.labelFromName(lookFromLookupFieldName) + "'", error); + checker().withScreenshot().verifyEquals("Error message for invalid primary key value not as expected", + "Value '1000' was not present in lookup target 'lists." + normalizeSpace(lookToListName) + + "' for field '" + normalizeSpace(labelFromName(lookFromLookupFieldName)) + "'", error); log("With lookup validation on, import data and provide an invalid primary key of type string."); error = importDataPage .setText(tsvFromColumn(List.of(lookFromLookupFieldName, "Look"))) .submitExpectingError(); - checker().withScreenshot().verifyEquals("Error message for invalid primary key type not as expected", "Could not convert value 'Look' (String) for Integer field '" + lookFromLookupFieldName + "'", error); + checker().withScreenshot().verifyEquals("Error message for invalid primary key type not as expected", + "Could not convert value 'Look' (String) for Integer field '" + normalizeSpace(lookFromLookupFieldName) + "'", error); } @Test @@ -246,14 +253,17 @@ public void testWithLookupValidatorAndAlternateKeys() throws IOException, Comman .setText(bulkData) .setImportLookupByAlternateKey(true) .submitExpectingError(); - checker().withScreenshot().verifyEquals("Error message for invalid string alternate key not as expected", "Value 'Invalid' not found for field " + lookFromLookupFieldName + " in the current context.", error); + checker().withScreenshot().verifyEquals("Error message for invalid string alternate key not as expected", + "Value 'Invalid' not found for field " + normalizeSpace(lookFromLookupFieldName) + " in the current context.", error); bulkData = tsvFromColumn(List.of(lookFromLookupFieldName, "1234")); error = importDataPage .setText(bulkData) .setImportLookupByAlternateKey(true) .submitExpectingError(); - checker().withScreenshot().verifyEquals("Error message for invalid number-like alternate key not as expected", "Value '1234' was not present in lookup target 'lists." + lookToListName + "' for field '" + FieldDefinition.labelFromName(lookFromLookupFieldName) + "'", error); + checker().withScreenshot().verifyEquals("Error message for invalid number-like alternate key not as expected", + "Value '1234' was not present in lookup target 'lists." + normalizeSpace(lookToListName) + + "' for field '" + normalizeSpace(labelFromName(lookFromLookupFieldName)) + "'", error); }