From ef9041eaa111fcbcb69e8f609d08ccdc929e9708 Mon Sep 17 00:00:00 2001 From: XingY Date: Fri, 8 Aug 2025 20:31:50 -0700 Subject: [PATCH 1/5] Selenium tests : Required Lineage Relationships --- .../ui/domainproperties/EntityTypeDesigner.java | 10 +++++----- .../samples/SampleTypeDesigner.java | 12 ++++++------ .../test/components/ui/grids/EditableGrid.java | 13 +++++++++++++ .../test/tests/SampleTypeParentColumnTest.java | 2 ++ src/org/labkey/test/util/EscapeUtil.java | 14 ++++++++++++++ 5 files changed, 40 insertions(+), 11 deletions(-) diff --git a/src/org/labkey/test/components/ui/domainproperties/EntityTypeDesigner.java b/src/org/labkey/test/components/ui/domainproperties/EntityTypeDesigner.java index 0a8678bda1..62d61fbb25 100644 --- a/src/org/labkey/test/components/ui/domainproperties/EntityTypeDesigner.java +++ b/src/org/labkey/test/components/ui/domainproperties/EntityTypeDesigner.java @@ -365,18 +365,18 @@ public List getParentAliasOptions(int index) return elementCache().parentAliasSelect(index).getOptions(); } - public T setParentAlias(int index, @Nullable String alias, @Nullable String optionDisplayText) + public T setParentAlias(int index, @Nullable String alias, @Nullable String dataType) { - return setParentAlias(index, alias, optionDisplayText, false); + return setParentAlias(index, alias, dataType, false); } - public T setParentAlias(int index, @Nullable String alias, @Nullable String optionDisplayText, boolean isRequired) + public T setParentAlias(int index, @Nullable String alias, @Nullable String dataType, boolean isRequired) { expandPropertiesPanel(); elementCache().parentAlias(index).setValue(alias); - if (optionDisplayText != null) + if (dataType != null) { - elementCache().parentAliasSelect(index).select(optionDisplayText); + elementCache().parentAliasSelect(index).select(dataType); } // The "Required" checkbox is not presented outside of the apps. Only a test running in the app could set diff --git a/src/org/labkey/test/components/ui/domainproperties/samples/SampleTypeDesigner.java b/src/org/labkey/test/components/ui/domainproperties/samples/SampleTypeDesigner.java index 522a4726f5..2b0ebfeb5c 100644 --- a/src/org/labkey/test/components/ui/domainproperties/samples/SampleTypeDesigner.java +++ b/src/org/labkey/test/components/ui/domainproperties/samples/SampleTypeDesigner.java @@ -41,12 +41,12 @@ public T addParentAlias(String alias) return addParentAlias(alias, null); } - public T addParentAlias(String alias, @Nullable String optionDisplayText) + public T addParentAlias(String alias, @Nullable String dataType) { - return addParentAlias(alias, optionDisplayText, false); + return addParentAlias(alias, dataType, false); } - public T addParentAlias(String alias, @Nullable String optionDisplayText, boolean isRequired) + public T addParentAlias(String alias, @Nullable String dataType, boolean isRequired) { expandPropertiesPanel(); @@ -55,11 +55,11 @@ public T addParentAlias(String alias, @Nullable String optionDisplayText, boolea elementCache().addParentAliasButton.click(); int initialCount = findEmptyAlias(); - if (optionDisplayText == null) + if (dataType == null) { - optionDisplayText = CURRENT_SAMPLE_TYPE; + dataType = CURRENT_SAMPLE_TYPE; } - setParentAlias(initialCount, alias, optionDisplayText, isRequired); + setParentAlias(initialCount, alias, dataType, isRequired); return getThis(); } diff --git a/src/org/labkey/test/components/ui/grids/EditableGrid.java b/src/org/labkey/test/components/ui/grids/EditableGrid.java index aa4c8633d8..2b12458c87 100644 --- a/src/org/labkey/test/components/ui/grids/EditableGrid.java +++ b/src/org/labkey/test/components/ui/grids/EditableGrid.java @@ -149,6 +149,19 @@ public EditableGrid removeColumn(CharSequence columnIdentifier) return this; } + public boolean canRemoveColumn(CharSequence columnIdentifier) + { + WebElement headerCell = elementCache().getColumnHeaderCell(columnIdentifier); + WebElement downBtn = Locator.byClass("fa-chevron-circle-down").findElementOrNull(headerCell); + if (downBtn == null) + return false; + downBtn.click(); + WebElement removeBtn = Locator.tagWithText("a", "Remove Column").findElementOrNull(headerCell); + boolean canRemove = removeBtn != null && removeBtn.isDisplayed() && removeBtn.isEnabled(); + downBtn.click(); // close dropdown + return canRemove; + } + private boolean hasSelectColumn() { return elementCache().selectColumn.isDisplayed(); diff --git a/src/org/labkey/test/tests/SampleTypeParentColumnTest.java b/src/org/labkey/test/tests/SampleTypeParentColumnTest.java index 01f87ea14f..7c4f18a5dd 100644 --- a/src/org/labkey/test/tests/SampleTypeParentColumnTest.java +++ b/src/org/labkey/test/tests/SampleTypeParentColumnTest.java @@ -670,6 +670,8 @@ public void testSampleTypeParentAliasOptions() checker().verifyTrue("Missing expected parent alias option", options.contains("Sample Type: " + PARENT_CONTAINER_SAMPLE_TYPE_NAME + " (" + PROJECT_NAME + ")")); checker().verifyTrue("Missing expected parent alias option", options.contains("Sample Type: " + SIBLING_SAMPLE_TYPE_NAME + " (" + SUB_FOLDER_NAME + ")")); + // + createPage.clickCancel(); } diff --git a/src/org/labkey/test/util/EscapeUtil.java b/src/org/labkey/test/util/EscapeUtil.java index b5ea40ad83..e97f09759b 100644 --- a/src/org/labkey/test/util/EscapeUtil.java +++ b/src/org/labkey/test/util/EscapeUtil.java @@ -23,6 +23,7 @@ import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.List; +import java.util.Map; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -53,6 +54,19 @@ static public String toJSONStr(String str) return escaped.toString(); } + static public String toJSONRow(Map row) + { + StringBuilder sb = new StringBuilder("{"); + for (Map.Entry entry : row.entrySet()) + { + Object value = entry.getValue(); + sb.append("\"").append(EscapeUtil.toJSONStr(entry.getKey())) + .append("\": \"").append(value instanceof String ? EscapeUtil.toJSONStr((String) entry.getValue()) : value).append("\","); + } + sb.append("}"); + return sb.toString(); + } + static public String jsString(String s) { if (s == null) From e87ed2977a672cd074a1278ea729595b3be3f967 Mon Sep 17 00:00:00 2001 From: XingY Date: Sun, 10 Aug 2025 13:03:08 -0700 Subject: [PATCH 2/5] fix json escape --- src/org/labkey/test/AssayAPITest.java | 4 ++-- src/org/labkey/test/util/EscapeUtil.java | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/org/labkey/test/AssayAPITest.java b/src/org/labkey/test/AssayAPITest.java index a3f1945a62..bb05a2ba72 100644 --- a/src/org/labkey/test/AssayAPITest.java +++ b/src/org/labkey/test/AssayAPITest.java @@ -424,8 +424,8 @@ private void verifyUpdateRunFileAPI(String assayName, String runFileField, int r "queryName: \"Runs\", " + "success: callback," + "failure: callback," + - "rows: [{ RowId: \""+ runRowId + "\"," + - "\"" + EscapeUtil.toJSONStr(runFileField) + "\": \"" + EscapeUtil.toJSONStr(filePath) + "\"," + + "rows: [{ \"RowId\": " + runRowId + "," + + EscapeUtil.toJSONStr(runFileField) + ": " + EscapeUtil.toJSONStr(filePath) + "}]" + "})"; executeAndVerifyScript(updateScript, errorMsg); diff --git a/src/org/labkey/test/util/EscapeUtil.java b/src/org/labkey/test/util/EscapeUtil.java index e97f09759b..2c9ad394ef 100644 --- a/src/org/labkey/test/util/EscapeUtil.java +++ b/src/org/labkey/test/util/EscapeUtil.java @@ -51,7 +51,7 @@ static public String toJSONStr(String str) } } } - return escaped.toString(); + return "\"" + escaped + "\""; } static public String toJSONRow(Map row) @@ -60,8 +60,8 @@ static public String toJSONRow(Map row) for (Map.Entry entry : row.entrySet()) { Object value = entry.getValue(); - sb.append("\"").append(EscapeUtil.toJSONStr(entry.getKey())) - .append("\": \"").append(value instanceof String ? EscapeUtil.toJSONStr((String) entry.getValue()) : value).append("\","); + sb.append(EscapeUtil.toJSONStr(entry.getKey())) + .append(": ").append(value instanceof String ? EscapeUtil.toJSONStr((String) entry.getValue()) : value).append(","); } sb.append("}"); return sb.toString(); From 7d282b778f566862ec711e03ab3834bfefc8d182 Mon Sep 17 00:00:00 2001 From: XingY Date: Sun, 10 Aug 2025 13:20:07 -0700 Subject: [PATCH 3/5] fix json escape --- src/org/labkey/test/util/EscapeUtil.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/org/labkey/test/util/EscapeUtil.java b/src/org/labkey/test/util/EscapeUtil.java index 2c9ad394ef..08ac4bbfc2 100644 --- a/src/org/labkey/test/util/EscapeUtil.java +++ b/src/org/labkey/test/util/EscapeUtil.java @@ -57,11 +57,14 @@ static public String toJSONStr(String str) static public String toJSONRow(Map row) { StringBuilder sb = new StringBuilder("{"); + String comma = ""; for (Map.Entry entry : row.entrySet()) { + sb.append(comma); Object value = entry.getValue(); sb.append(EscapeUtil.toJSONStr(entry.getKey())) - .append(": ").append(value instanceof String ? EscapeUtil.toJSONStr((String) entry.getValue()) : value).append(","); + .append(": ").append(value instanceof String ? EscapeUtil.toJSONStr((String) entry.getValue()) : value); + comma = ","; } sb.append("}"); return sb.toString(); From c15630d7cdfd7ff2c040083228f930ebe2ffc9a8 Mon Sep 17 00:00:00 2001 From: XingY Date: Sun, 10 Aug 2025 21:03:11 -0700 Subject: [PATCH 4/5] Test for update UI --- .../components/react/BaseReactSelect.java | 2 +- .../ui/entities/ParentEntityEditPanel.java | 25 ++++++++++++++++--- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/org/labkey/test/components/react/BaseReactSelect.java b/src/org/labkey/test/components/react/BaseReactSelect.java index 0761b6fbaf..cc35b0acc6 100644 --- a/src/org/labkey/test/components/react/BaseReactSelect.java +++ b/src/org/labkey/test/components/react/BaseReactSelect.java @@ -115,7 +115,7 @@ public boolean isClearable() public boolean isDisabled() { - return hasClass("select-input__control--is-disabled"); + return hasClass("select-input__control--is-disabled") || hasClass("select-input--is-disabled"); } public boolean isEnabled() diff --git a/src/org/labkey/test/components/ui/entities/ParentEntityEditPanel.java b/src/org/labkey/test/components/ui/entities/ParentEntityEditPanel.java index e71980e918..34efbee7fa 100644 --- a/src/org/labkey/test/components/ui/entities/ParentEntityEditPanel.java +++ b/src/org/labkey/test/components/ui/entities/ParentEntityEditPanel.java @@ -262,13 +262,20 @@ public ReactSelect getAddNewEntityTypeSelect() * * @return A select at this given ordinal position. */ - private ReactSelect getEntityTypeByPosition(int index) + public ReactSelect getEntityTypeByPosition(int index) { return ReactSelect.finder(getDriver()) .withNamedInput(String.format("entityType%d", index)) .waitFor(elementCache()); } + public ReactSelect getDisabledEntityTypeByLabel(String typeName) + { + return ReactSelect.finder(getDriver()) + .followingLabelWithSpan(typeName) + .waitFor(elementCache()); + } + public ReactSelect getEntityType(String entityName) { Locator input = Locator.tagWithAttribute("input", "value", entityName.toLowerCase()); @@ -344,6 +351,10 @@ public ParentEntityEditPanel addParent(String typeName, String parentId) return addParents(typeName, Arrays.asList(parentId)); } + public ParentEntityEditPanel addParents(String typeName, List parentIds) + { + return addParents(typeName, parentIds, false); + } /** * Add a specific parents (samples or sources) from the given type. If the type is not currently being used for * parent elements it will be added. @@ -353,9 +364,9 @@ public ParentEntityEditPanel addParent(String typeName, String parentId) * @param parentIds A list of the individuals samples or sources to add. * @return A reference to this panel. */ - public ParentEntityEditPanel addParents(String typeName, List parentIds) + public ParentEntityEditPanel addParents(String typeName, List parentIds, boolean skipAdd) { - if (getEntityType(typeName) == null) + if (!skipAdd && getEntityType(typeName) == null) getAddNewEntityTypeSelect().select(typeName); var selectParent = getParentFinder(typeName).waitFor(elementCache()); @@ -393,6 +404,9 @@ public ParentEntityEditPanel removeEntityType(String typeName) boolean found = false; for (ReactSelect reactSelect : selectControls) { + if (reactSelect.isDisabled()) + continue; + if (reactSelect.getSelections().contains(typeName)) { found = true; @@ -444,6 +458,11 @@ public void clearActionComment() elementCache().commentInput.clear(); } + public boolean hasParentInputError() + { + return Locator.tagWithClass("div", "edit-parent-danger").isDisplayed(this); + } + /** * Simple finder for this panel. From ea05d43be95ebe6e7ff59aca9e15641febc709e1 Mon Sep 17 00:00:00 2001 From: XingY Date: Mon, 11 Aug 2025 13:16:04 -0700 Subject: [PATCH 5/5] clean up --- src/org/labkey/test/tests/SampleTypeParentColumnTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/org/labkey/test/tests/SampleTypeParentColumnTest.java b/src/org/labkey/test/tests/SampleTypeParentColumnTest.java index 7c4f18a5dd..01f87ea14f 100644 --- a/src/org/labkey/test/tests/SampleTypeParentColumnTest.java +++ b/src/org/labkey/test/tests/SampleTypeParentColumnTest.java @@ -670,8 +670,6 @@ public void testSampleTypeParentAliasOptions() checker().verifyTrue("Missing expected parent alias option", options.contains("Sample Type: " + PARENT_CONTAINER_SAMPLE_TYPE_NAME + " (" + PROJECT_NAME + ")")); checker().verifyTrue("Missing expected parent alias option", options.contains("Sample Type: " + SIBLING_SAMPLE_TYPE_NAME + " (" + SUB_FOLDER_NAME + ")")); - // - createPage.clickCancel(); }