From 7615619c4fadbd0ec2e5cccb976c0407132ec681 Mon Sep 17 00:00:00 2001 From: Trey Chadick Date: Wed, 2 Jul 2025 13:59:01 -0700 Subject: [PATCH 1/8] Fix data region column name references (#2526) Remove unnecessary logging parameters from CustomizeView Update CustomizeView to use FieldKey Fix data region column name references --- .../labkey/test/components/CustomizeView.java | 228 ++++++------------ src/org/labkey/test/params/FieldKey.java | 59 +++-- .../test/tests/ButtonCustomizationTest.java | 2 +- .../test/tests/ContainerContextTest.java | 3 +- .../labkey/test/tests/CustomizeViewTest.java | 6 +- .../labkey/test/tests/DataReportsTest.java | 6 +- src/org/labkey/test/tests/FlagColumnTest.java | 7 +- .../test/tests/InlineImagesAssayTest.java | 5 +- .../test/tests/SampleTypeLineageTest.java | 31 +-- .../labkey/test/tests/TimeChartAPITest.java | 16 +- .../test/tests/UserDetailsPermissionTest.java | 14 +- .../tests/assay/AssayMissingValuesTest.java | 4 +- .../tests/elispotassay/ElispotAssayTest.java | 11 +- .../tests/flow/FlowDuplicateSamplesTest.java | 10 +- .../test/tests/flow/FlowJoQueryTest.java | 12 +- src/org/labkey/test/tests/flow/FlowTest.java | 11 +- src/org/labkey/test/tests/list/ListTest.java | 30 +-- .../test/tests/nab/NAbResultCalcTest.java | 8 +- .../labkey/test/tests/nab/NabAssayTest.java | 38 +-- .../test/tests/viability/ViabilityTest.java | 2 +- src/org/labkey/test/util/DataRegionTable.java | 4 +- 21 files changed, 218 insertions(+), 289 deletions(-) diff --git a/src/org/labkey/test/components/CustomizeView.java b/src/org/labkey/test/components/CustomizeView.java index e2e801c044..4e688abdc5 100644 --- a/src/org/labkey/test/components/CustomizeView.java +++ b/src/org/labkey/test/components/CustomizeView.java @@ -28,7 +28,7 @@ import org.labkey.test.components.ext4.ComboBox; import org.labkey.test.components.ext4.RadioButton; import org.labkey.test.components.ext4.Window; -import org.labkey.test.selenium.LazyWebElement; +import org.labkey.test.params.FieldKey; import org.labkey.test.selenium.RefindingWebElement; import org.labkey.test.util.DataRegionTable; import org.labkey.test.util.Ext4Helper; @@ -44,9 +44,9 @@ import org.openqa.selenium.interactions.Actions; import org.openqa.selenium.support.ui.ExpectedConditions; -import java.util.ArrayList; -import java.util.Arrays; +import java.util.Iterator; import java.util.List; +import java.util.Objects; import static org.labkey.test.components.ext4.Checkbox.Ext4Checkbox; import static org.labkey.test.components.ext4.RadioButton.RadioButton; @@ -233,14 +233,14 @@ public void saveCustomView(String name, @Nullable Boolean shared, @Nullable Bool saveWindow.save(); } - public static class SaveWindow extends Window + public static class SaveWindow extends Window.ElementCache> { public final Checkbox shareCheckbox = Ext4Checkbox().withLabel("Make this grid view available to all users").findWhenNeeded(this); public final Checkbox inheritCheckbox = Ext4Checkbox().withLabel("Make this grid view available in child folders").findWhenNeeded(this); public final RadioButton defaultViewRadio = RadioButton().withLabelContaining("Default").findWhenNeeded(this); public final RadioButton namedViewRadio = RadioButton().withLabelContaining("Named").findWhenNeeded(this); - private final WebElement viewNameInput = new LazyWebElement(Locator.xpath("//input[@name='saveCustomView_name']"), this); - private final WebElement targetContainerInput = new LazyWebElement(Locator.xpath("//input[@name='saveCustomView_targetContainer']"), this); + private final WebElement viewNameInput = Locator.input("saveCustomView_name").findWhenNeeded(this); + private final WebElement targetContainerInput = Locator.input("saveCustomView_targetContainer").findWhenNeeded(this); protected SaveWindow(WebDriver driver) { @@ -258,10 +258,10 @@ public void setTargetContainer(String container) getWrapper().setFormElement(targetContainerInput, container); } - public Window saveError() + public Window saveError() { clickButton("Save", 0); - return new Window("Error saving grid view", getWrapper().getDriver()); + return new Window<>("Error saving grid view", getWrapper().getDriver()); } public void save() @@ -279,7 +279,7 @@ public void cancel() public void deleteView() { elements().deleteButton.click(); - Window confirm = Window(getDriver()).withTitleContaining("Delete").find(); + Window confirm = Window(getDriver()).withTitleContaining("Delete").find(); confirm.clickButton("Yes"); } @@ -308,19 +308,11 @@ public void revertUnsavedView() /** * add a column to an already open customize view grid * - * @param column_name Name of the column. If your column is nested, should be of the form - * "nodename/nodename/lastnodename", where nodename is not the displayed text of a node - * but the name included in the span containing the checkbox. It will often be the same name, - * but with less whitespace + * @param fieldKey fieldKey of the column */ - public void addColumn(String column_name) + public void addColumn(CharSequence fieldKey) { - addColumn(column_name, column_name); - } - - public void addColumn(String[] fieldKeyParts) - { - addColumn(fieldKeyParts, StringUtils.join(fieldKeyParts, "/")); + addItem(fieldKey, ViewItemType.Columns); } public void changeTab(ViewItemType tab) @@ -344,87 +336,69 @@ public enum ViewItemType } /** - * expand customize view menu to all but the last of fieldKeyParts - * @return The data-recordid property of the <tr> element for the specified field in the "Available Fields" column tree. + * expand customize view fields tree to expose the specified column + * @return The row element for the specified column */ - private WebElement expandPivots(String[] fieldKeyParts) + private WebElement expandPivots(CharSequence fieldKey) { - String nodePath = ""; - String fieldKey = StringUtils.join(fieldKeyParts, "/").toUpperCase(); + Iterator fieldKeyIterator = Objects.requireNonNull(FieldKey.fromFieldKey(fieldKey), "Invalid fieldKey: " + fieldKey).getIterator(); + FieldKey currentFieldKey = fieldKeyIterator.next(); + String dataRecordId = currentFieldKey.toString().toUpperCase(); - for (int i = 0; i < fieldKeyParts.length - 1; i ++ ) + while (fieldKeyIterator.hasNext()) { - nodePath += fieldKeyParts[i].toUpperCase(); - WebElement fieldRow = Locator.tag("tr").withClass("x4-grid-data-row").withAttribute("data-recordid", nodePath).waitForElement(getComponentElement(), 10000); + WebElement fieldRow = Locator.tag("tr").withClass("x4-grid-data-row").withAttribute("data-recordid", dataRecordId).waitForElement(getComponentElement(), 10000); _driver.scrollIntoView(fieldRow, false); - if (!fieldRow.getAttribute("class").contains("expanded")) + if (!StringUtils.trimToEmpty(fieldRow.getAttribute("class")).contains("expanded")) { Locator.css(".x4-tree-expander").findElement(fieldRow).click(); } - Locator.tag("tr").withClass("x4-grid-tree-node-expanded").withAttribute("data-recordid", nodePath).waitForElement(getComponentElement(), 10000); + Locator.tag("tr").withClass("x4-grid-tree-node-expanded").withAttribute("data-recordid", dataRecordId).waitForElement(getComponentElement(), 10000); WebDriverWrapper.waitFor(() -> Locator.css("tr[data-recordid] + tr:not(.x4-grid-row)").findElements(getComponentElement()).isEmpty(), 2000); // Spacer row appears during expansion animation - nodePath += "/"; + + currentFieldKey = fieldKeyIterator.next(); + dataRecordId = currentFieldKey.toString().toUpperCase(); } - return Locator.tag("tr").withClass("x4-grid-data-row").withAttribute("data-recordid", fieldKey).findElement(getComponentElement()); + return Locator.tag("tr").withClass("x4-grid-data-row").withAttribute("data-recordid", dataRecordId).findElement(getComponentElement()); } - private void addItem(String[] fieldKeyParts, String columnName, ViewItemType type) + private void addItem(CharSequence fieldKey, ViewItemType type) { // fieldKey is the value contained in @fieldkey - _driver.log("Adding " + columnName + " " + type.toString()); + _driver.log("Adding " + fieldKey + " " + type); changeTab(type); // Expand all nodes necessary to reveal the desired node. - WebElement fieldRow = expandPivots(fieldKeyParts); + WebElement fieldRow = expandPivots(fieldKey); WebElement checkbox = Locator.css("input[type=button]").findElement(fieldRow); WebElement rowLabel = Locator.byClass("x4-tree-node-text").findElement(fieldRow); rowLabel.click(); new Checkbox(checkbox).check(); - itemXPath(type, fieldKeyParts).waitForElement(this, 2_000); + itemXPath(type, fieldKey).waitForElement(this, 2_000); } - public void addColumn(String[] fieldKeyParts, String label) + public void addFilter(CharSequence fieldKey, String filter_type) { - addItem(fieldKeyParts, label, ViewItemType.Columns); + addFilter(fieldKey, filter_type, ""); } - public void addColumn(String fieldKey, String column_name) - { - addItem(fieldKey.split("/"), column_name, ViewItemType.Columns); - } - - public void addFilter(String fieldKey, String filter_type) - { - addFilter(fieldKey, fieldKey, filter_type, ""); - } - - public void addFilter(String fieldKey, String filter_type, String filter) - { - addFilter(fieldKey, fieldKey, filter_type, filter); - } - - public void addFilter(String fieldKey, String column_name, String filter_type, String filter) - { - addFilter(fieldKey.split("/"), column_name, filter_type, filter); - } - - public void addFilter(String[] fieldKeyParts, String column_name, String filter_type, String filter) + public void addFilter(CharSequence fieldKey, String filter_type, String filter) { if (filter.isEmpty()) - _driver.log("Adding " + column_name + " filter of " + filter_type); + _driver.log("Adding " + fieldKey + " filter of " + filter_type); else - _driver.log("Adding " + column_name + " filter of " + filter_type + " " + filter); + _driver.log("Adding " + fieldKey + " filter of " + filter_type + " " + filter); changeTab(ViewItemType.Filter); - Locator.XPathLocator itemXPath = itemXPath(ViewItemType.Filter, fieldKeyParts); + Locator.XPathLocator itemXPath = itemXPath(ViewItemType.Filter, fieldKey); if (!_driver.isElementPresent(itemXPath)) { // Add filter if it doesn't exist - addItem(fieldKeyParts, column_name, ViewItemType.Filter); + addItem(fieldKey, ViewItemType.Filter); _driver.assertElementPresent(itemXPath); } else @@ -459,15 +433,9 @@ private Locator.XPathLocator tabContentXPath(ViewItemType type) return Locator.tagWithClass("div", "test-" + type.toString().toLowerCase() + "-tab"); } - private Locator.XPathLocator itemXPath(ViewItemType type, String[] fieldKeyParts) + private Locator.XPathLocator itemXPath(ViewItemType type, CharSequence fieldKey) { - return itemXPath(type, StringUtils.join(fieldKeyParts, "/")); - } - - private Locator.XPathLocator itemXPath(ViewItemType type, String fieldKey) - { - FieldKey parsedFieldKey = new FieldKey(fieldKey); - return itemXPath(type).withPredicate("@fieldkey=" + Locator.xq(fieldKey) + " or @fieldkey=" + Locator.xq(parsedFieldKey.toString())); + return itemXPath(type).withAttribute("fieldkey", fieldKey.toString()); } private Locator.XPathLocator itemXPath(ViewItemType type, int item_index) @@ -480,7 +448,7 @@ private Locator.XPathLocator itemXPath(ViewItemType type) return Locator.tagWithClass("table", "labkey-customview-" + type.toString().toLowerCase() + "-item"); } - private void removeItem(String fieldKey, ViewItemType type) + private void removeItem(CharSequence fieldKey, ViewItemType type) { changeTab(type); @@ -510,43 +478,6 @@ private void removeItem(String fieldKey, ViewItemType type) } } - public static class FieldKey - { - public static final String SEPARATOR = "/"; - private final String fieldName; - private final String fieldKey; - private final List lookupParts; - - public FieldKey(String fieldKey) - { - List allParts = Arrays.asList(fieldKey.split(SEPARATOR)); - lookupParts = allParts.subList(0, allParts.size() - 1); - for (int i = 0; i < lookupParts.size(); i++) - { - lookupParts.set(i, lookupParts.get(i));//.toUpperCase()); - } - fieldName = allParts.get(allParts.size() - 1); - allParts = new ArrayList<>(lookupParts); - allParts.add(fieldName); - this.fieldKey = String.join(SEPARATOR, allParts); - } - - public String getFieldName() - { - return fieldName; - } - - public List getLookupParts() - { - return lookupParts; - } - - public String toString() - { - return fieldKey; - } - } - //enable customize view grid to show hidden fields public void showHiddenItems() { @@ -558,40 +489,30 @@ public void showHiddenItems() BaseWebDriverTest.sleep(250); // wait for columns to display } - public void addSort(String column_name, SortDirection order) - { - addSort(column_name, column_name, order); - } - - public void addSort(String fieldKey, String column_name, SortDirection order) - { - addSort(fieldKey.split("/"), column_name, order); - } - - public void addSort(String[] fieldKeyParts, String column_name, SortDirection order) + public void addSort(CharSequence fieldKey, SortDirection order) { - Locator.XPathLocator itemXPath = itemXPath(ViewItemType.Sort, fieldKeyParts); + Locator.XPathLocator itemXPath = itemXPath(ViewItemType.Sort, fieldKey); _driver.assertElementNotPresent(itemXPath); - addItem(fieldKeyParts, column_name, ViewItemType.Sort); + addItem(fieldKey, ViewItemType.Sort); _driver._ext4Helper.selectComboBoxItem(itemXPath, order.toString()); itemXPath.append("//tr").findElement(this).click(); // Sort direction doesn't stick without this } - public void removeColumn(String fieldKey) + public void removeColumn(CharSequence fieldKey) { _driver.log("Removing " + fieldKey + " column"); removeItem(fieldKey, ViewItemType.Columns); } - public void removeFilter(String fieldKey) + public void removeFilter(CharSequence fieldKey) { _driver.log("Removing " + fieldKey + " filter"); removeItem(fieldKey, ViewItemType.Filter); } - public void removeSort(String fieldKey) + public void removeSort(CharSequence fieldKey) { _driver.log("Removing " + fieldKey + " sort"); removeItem(fieldKey, ViewItemType.Sort); @@ -643,25 +564,25 @@ public void setFolderFilter(@LoggedParam String folderFilter) _driver._ext4Helper.selectComboBoxItem("Folder Filter:", folderFilter); } - public void moveColumn(String fieldKey, boolean moveUp) + public void moveColumn(CharSequence fieldKey, boolean moveUp) { _driver.log("Moving filter, " + fieldKey + " " + (moveUp ? "up." : "down.")); moveItem(fieldKey, moveUp, ViewItemType.Columns); } - public void moveFilter(String fieldKey, boolean moveUp) + public void moveFilter(CharSequence fieldKey, boolean moveUp) { _driver.log("Moving filter, " + fieldKey + " " + (moveUp ? "up." : "down.")); moveItem(fieldKey, moveUp, ViewItemType.Filter); } - public void moveSort(String fieldKey, boolean moveUp) + public void moveSort(CharSequence fieldKey, boolean moveUp) { _driver.log("Moving sort, " + fieldKey + " " + (moveUp ? "up." : "down.")); moveItem(fieldKey, moveUp, ViewItemType.Sort); } - private void moveItem(String fieldKey, boolean moveUp, ViewItemType type) + private void moveItem(CharSequence fieldKey, boolean moveUp, ViewItemType type) { changeTab(type); final int itemIndex = _driver.getElementIndex(itemXPath(type, fieldKey).findElement(this)); @@ -683,7 +604,7 @@ private void moveItem(int field_index, boolean moveUp, ViewItemType type) builder.dragAndDrop(fromItem, toItem).build().perform(); } - public void removeColumnTitle(String fieldKey) + public void removeColumnTitle(CharSequence fieldKey) { setColumnTitle(fieldKey, null); } @@ -693,7 +614,7 @@ public void removeColumnTitle(String fieldKey) * @param fieldKey The field key of the column to change. Note that the column should already be in the selected column list. * @param caption The caption value or null to unset the column caption. */ - public void setColumnTitle(String fieldKey, String caption) + public void setColumnTitle(CharSequence fieldKey, String caption) { String msg = "Setting column " + fieldKey; if (caption != null) @@ -702,23 +623,22 @@ public void setColumnTitle(String fieldKey, String caption) changeTab(ViewItemType.Columns); - Window window = new SelectedColumnRow(fieldKey).clickEdit(); + Window window = new SelectedColumnRow(fieldKey).clickEdit(); if (caption == null) caption = ""; _driver.setFormElement(Locator.name("title").findElement(window), caption); Locator.xpath("//label").findElement(window).click(); - window.clickButton("OK", 0); - window.waitForClose(); + window.clickButton("OK", true); } /** Check that a column is present. */ - public boolean isColumnPresent(String fieldKey) + public boolean isColumnPresent(CharSequence fieldKey) { try { - expandPivots(fieldKey.split("/")); + expandPivots(fieldKey); return true; } catch (NoSuchElementException no) @@ -728,23 +648,23 @@ public boolean isColumnPresent(String fieldKey) } /** Check that a column is present and is not selectable. */ - public boolean isColumnUnselectable(String fieldKey) + public boolean isColumnUnselectable(CharSequence fieldKey) { - WebElement fieldRow = expandPivots(fieldKey.split("/")); + WebElement fieldRow = expandPivots(fieldKey); return "on".equals(fieldRow.getAttribute("unselectable")); } - public WebElement getColumn(String fieldKey) + public WebElement getColumn(CharSequence fieldKey) { - return expandPivots(fieldKey.split("/")); + return expandPivots(fieldKey); } /** Check that a column is present and not hidden. Assumes that the 'show hidden columns' is unchecked. */ - public boolean isColumnVisible(String fieldKey) + public boolean isColumnVisible(CharSequence fieldKey) { try { - WebElement fieldRow = expandPivots(fieldKey.split("/")); + WebElement fieldRow = expandPivots(fieldKey); return fieldRow.isDisplayed(); } catch (NoSuchElementException no) @@ -754,9 +674,9 @@ public boolean isColumnVisible(String fieldKey) } /** Check that a column is present and is a lookup column. */ - public boolean isLookupColumn(String fieldKey) + public boolean isLookupColumn(CharSequence fieldKey) { - WebElement fieldRow = expandPivots(fieldKey.split("/")); + WebElement fieldRow = expandPivots(fieldKey); return !Locator.css("img.x4-tree-expander").findElements(fieldRow).isEmpty(); } @@ -766,7 +686,7 @@ protected Elements newElementCache() return new Elements(); } - protected class Elements extends Component.ElementCache + protected class Elements extends Component.ElementCache { protected final WebElement deleteButton = new RefindingWebElement(Ext4Helper.Locators.ext4Button("Delete"), this); protected final WebElement revertButton = new RefindingWebElement(Ext4Helper.Locators.ext4Button("Revert"), this); @@ -774,14 +694,14 @@ protected class Elements extends Component.ElementCache protected final WebElement saveButton = new RefindingWebElement(Ext4Helper.Locators.ext4Button("Save"), this); } - private class SelectedItemRow extends Component + private class SelectedItemRow extends Component.ElementCache> { private final WebElement _element; - private final String _fieldKey; + private final FieldKey _fieldKey; - protected SelectedItemRow(ViewItemType itemType, String fieldkey) + protected SelectedItemRow(ViewItemType itemType, CharSequence fieldkey) { - _fieldKey = fieldkey; + _fieldKey = FieldKey.fromFieldKey(fieldkey); _element = itemXPath(itemType, fieldkey).findElement(CustomizeView.this); } @@ -791,7 +711,7 @@ public WebElement getComponentElement() return _element; } - protected String getFieldKey() + protected FieldKey getFieldKey() { return _fieldKey; } @@ -805,12 +725,12 @@ public void clickDelete() private class SelectedColumnRow extends SelectedItemRow { - public SelectedColumnRow(String fieldkey) + public SelectedColumnRow(CharSequence fieldkey) { super(ViewItemType.Columns, fieldkey); } - public Window clickEdit() + public Window clickEdit() { WebElement gear = Locator.css("div.labkey-tool-gear").findElement(getComponentElement()); _driver.scrollIntoView(gear, true); @@ -821,7 +741,7 @@ public Window clickEdit() private class SelectedFilterRow extends SelectedItemRow { - public SelectedFilterRow(String fieldkey) + public SelectedFilterRow(CharSequence fieldkey) { super(ViewItemType.Filter, fieldkey); } @@ -834,7 +754,7 @@ public void setFilter(Filter filter) private class SelectedSortRow extends SelectedItemRow { - public SelectedSortRow(String fieldkey) + public SelectedSortRow(CharSequence fieldkey) { super(ViewItemType.Sort, fieldkey); } diff --git a/src/org/labkey/test/params/FieldKey.java b/src/org/labkey/test/params/FieldKey.java index eb3100a331..6ccc37387d 100644 --- a/src/org/labkey/test/params/FieldKey.java +++ b/src/org/labkey/test/params/FieldKey.java @@ -15,9 +15,9 @@ public final class FieldKey implements CharSequence, WrapsFieldKey private static final String[] ILLEGAL = {"$", "/", "&", "}", "~", ",", "."}; private static final String[] REPLACEMENT = {"$D", "$S", "$A", "$B", "$T", "$C", "$P"}; - public static final FieldKey EMPTY = new FieldKey(""); // Useful as a sort of FieldKey builder starting point - public static final FieldKey SOURCES_FK = new FieldKey("DataInputs"); - public static final FieldKey PARENTS_FK = new FieldKey("MaterialInputs"); + public static final FieldKey EMPTY = new FieldKey(null, ""); // Useful as a sort of FieldKey builder starting point + public static final FieldKey SOURCES_FK = FieldKey.fromParts("DataInputs"); + public static final FieldKey PARENTS_FK = FieldKey.fromParts("MaterialInputs"); private static final String SEPARATOR = "/"; @@ -25,18 +25,20 @@ public final class FieldKey implements CharSequence, WrapsFieldKey private final String _name; private final String _fieldKey; - private FieldKey(String name) - { - _parent = null; - _name = name; - _fieldKey = encodePart(name); - } - private FieldKey(FieldKey parent, String child) { - _parent = parent; - _name = parent.getName() + SEPARATOR + child; - _fieldKey = parent + SEPARATOR + encodePart(child); + if (parent != null && !parent.isEmpty()) + { + _parent = parent; + _name = parent.getName() + SEPARATOR + child; + _fieldKey = parent + SEPARATOR + encodePart(child); + } + else + { + _parent = null; + _name = child; + _fieldKey = encodePart(child); + } } public static List getIllegalChars() @@ -46,14 +48,7 @@ public static List getIllegalChars() public static FieldKey fromParts(List parts) { - FieldKey fieldKey = EMPTY; - - for (String part : parts) - { - fieldKey = fieldKey.child(part); - } - - return fieldKey; + return EMPTY.child(parts); } public static FieldKey fromParts(String... parts) @@ -113,19 +108,23 @@ public FieldKey getParent() return _parent; } - public FieldKey child(String part) + public FieldKey child(String... parts) { - if (StringUtils.isBlank(part)) - throw new IllegalArgumentException("FieldKey can't have blank part(s): " + this); + return child(Arrays.asList(parts)); + } - if (StringUtils.isBlank(getName())) - { - return new FieldKey(part); - } - else + public FieldKey child(List parts) + { + FieldKey child = this; + + for (String part : parts) { - return new FieldKey(this, part); + if (StringUtils.isBlank(part)) + throw new IllegalArgumentException("FieldKey can't have blank part(s): " + parts); + + child = new FieldKey(child, part); } + return child; } public Iterator getIterator() diff --git a/src/org/labkey/test/tests/ButtonCustomizationTest.java b/src/org/labkey/test/tests/ButtonCustomizationTest.java index 49eca0c4c5..25c4b09a75 100644 --- a/src/org/labkey/test/tests/ButtonCustomizationTest.java +++ b/src/org/labkey/test/tests/ButtonCustomizationTest.java @@ -188,7 +188,7 @@ public void testSteps() Locator.lkButton(METADATA_LINK_BUTTON).waitForElement(getDriver(), WAIT_FOR_JAVASCRIPT) .getAttribute("class").contains("labkey-disabled-button")); - buttonRegion.checkCheckbox(buttonRegion.getRowIndex("Portland", "Name")); + buttonRegion.checkCheckbox(buttonRegion.getRowIndex("Name", "Portland")); // wait for the button to enable: waitForElement(Locator.lkButton(METADATA_LINK_BUTTON), 10000); diff --git a/src/org/labkey/test/tests/ContainerContextTest.java b/src/org/labkey/test/tests/ContainerContextTest.java index f5d6a05cbb..1ff9b6eed6 100644 --- a/src/org/labkey/test/tests/ContainerContextTest.java +++ b/src/org/labkey/test/tests/ContainerContextTest.java @@ -35,6 +35,7 @@ import org.labkey.test.categories.Data; import org.labkey.test.pages.reports.ScriptReportPage; import org.labkey.test.params.FieldDefinition; +import org.labkey.test.params.FieldKey; import org.labkey.test.params.list.IntListDefinition; import org.labkey.test.util.DataRegionTable; import org.labkey.test.util.Ext4Helper; @@ -177,7 +178,7 @@ public void testListLookupURL() throws Exception log("** Adding in lookup list columns to grid"); _customizeViewsHelper.openCustomizeViewPanel(); - _customizeViewsHelper.addColumn(new String[] { "ListLookup", "LookupAge" }); + _customizeViewsHelper.addColumn(FieldKey.fromParts("ListLookup", "LookupAge")); _customizeViewsHelper.saveCustomView(); log("** Checking URLs go to correct container..."); diff --git a/src/org/labkey/test/tests/CustomizeViewTest.java b/src/org/labkey/test/tests/CustomizeViewTest.java index d5acccbffb..fb4384de1d 100644 --- a/src/org/labkey/test/tests/CustomizeViewTest.java +++ b/src/org/labkey/test/tests/CustomizeViewTest.java @@ -300,7 +300,7 @@ private void saveAfterApplyingView(String name, String newColumnLabel, String ne @Test public void saveFilterTest() { - String fieldKey = FieldKey.fromParts(LAST_NAME_COLUMN).toString(); + FieldKey fieldKey = FieldKey.fromParts(LAST_NAME_COLUMN); String op = "Starts With"; String value = "J"; String[] viewNames = {TRICKY_CHARACTERS + "view", "AAC", "aaa", "aad", "zzz"}; @@ -309,7 +309,7 @@ public void saveFilterTest() for(String name : viewNames) { _customizeViewsHelper.openCustomizeViewPanel(); - _customizeViewsHelper.addFilter(new String[]{fieldKey}, fieldKey, op, value); + _customizeViewsHelper.addFilter(fieldKey, op, value); _customizeViewsHelper.saveCustomView(name); } @@ -350,7 +350,7 @@ private void setColumns(String... columnNames) private void addFilter(String columnName, String op, String value) { _customizeViewsHelper.openCustomizeViewPanel(); - _customizeViewsHelper.addFilter(FieldKey.fromParts(columnName).toString(), columnName, op, value); + _customizeViewsHelper.addFilter(FieldKey.fromParts(columnName).toString(), op, value); _customizeViewsHelper.applyCustomView(); } diff --git a/src/org/labkey/test/tests/DataReportsTest.java b/src/org/labkey/test/tests/DataReportsTest.java index 574b87865b..a49bd1bed7 100644 --- a/src/org/labkey/test/tests/DataReportsTest.java +++ b/src/org/labkey/test/tests/DataReportsTest.java @@ -191,7 +191,7 @@ public void doQueryReportTests() clickAndWait(Locator.linkWithText("AE-1:(VTN) AE Log")); DataRegionTable dataSetTable = new DataRegionTable("Dataset", getDriver()); dataSetTable.openCustomizeGrid(); - _customizeViewsHelper.addFilter("MouseId", "Mouse Id", "Equals One Of", String.join(";", PTIDS_FOR_CUSTOM_VIEW)); + _customizeViewsHelper.addFilter("MouseId", "Equals One Of", String.join(";", PTIDS_FOR_CUSTOM_VIEW)); _customizeViewsHelper.saveCustomView(QUERY_REPORT_VIEW_NAME_2); goToManageViews().clickAddReport("Query Report"); @@ -337,8 +337,8 @@ public void doRReportsTest() DataRegionTable dataSetTable = new DataRegionTable("Dataset", getDriver()); dataSetTable.openCustomizeGrid(); _customizeViewsHelper.removeColumn(R_REMCOL); - _customizeViewsHelper.addFilter("DEMhisp", "3.Latino\\a or Hispanic?", "Does Not Equal", "Yes"); - _customizeViewsHelper.addSort(R_SORT, "2.What is your sex?", SortDirection.DESC); + _customizeViewsHelper.addFilter("DEMhisp", "Does Not Equal", "Yes"); + _customizeViewsHelper.addSort(R_SORT, SortDirection.DESC); _customizeViewsHelper.saveCustomView("Custom Query View"); log("Check that customize view worked"); diff --git a/src/org/labkey/test/tests/FlagColumnTest.java b/src/org/labkey/test/tests/FlagColumnTest.java index 70a0e274e8..3739e9c71c 100644 --- a/src/org/labkey/test/tests/FlagColumnTest.java +++ b/src/org/labkey/test/tests/FlagColumnTest.java @@ -12,6 +12,7 @@ import org.labkey.test.categories.Assays; import org.labkey.test.categories.Daily; import org.labkey.test.params.FieldDefinition; +import org.labkey.test.params.FieldKey; import org.labkey.test.util.DataRegionTable; import org.labkey.test.util.RelativeUrl; @@ -116,9 +117,9 @@ private void doInit() clickAndWait(Locator.linkWithText("view results")); var customizeView = _customizeViewsHelper.openCustomizeViewPanel(); customizeView.showHiddenItems(); - customizeView.addColumn(new String[] { "Run" }); - customizeView.addColumn(new String[] { "Run", RUN_FLAG}); - customizeView.addColumn(new String[] { "Run", "AnotherRunFlag" }); + customizeView.addColumn(FieldKey.fromParts("Run")); + customizeView.addColumn(FieldKey.fromParts("Run", RUN_FLAG)); + customizeView.addColumn(FieldKey.fromParts("Run", "AnotherRunFlag")); customizeView.addSort("RowId", SortDirection.ASC); customizeView.saveCustomView(); diff --git a/src/org/labkey/test/tests/InlineImagesAssayTest.java b/src/org/labkey/test/tests/InlineImagesAssayTest.java index bb3458c5a1..34b9809a85 100644 --- a/src/org/labkey/test/tests/InlineImagesAssayTest.java +++ b/src/org/labkey/test/tests/InlineImagesAssayTest.java @@ -30,6 +30,7 @@ import org.labkey.test.components.CustomizeView; import org.labkey.test.pages.ReactAssayDesignerPage; import org.labkey.test.params.FieldDefinition; +import org.labkey.test.params.FieldKey; import org.labkey.test.util.DataRegionExportHelper; import org.labkey.test.util.DataRegionTable; import org.labkey.test.util.ExcelHelper; @@ -177,8 +178,8 @@ public final void testAssayInlineImages() throws Exception DataRegionTable list = new DataRegionTable("Data", getDriver()); CustomizeView customizeView = list.openCustomizeGrid(); customizeView.showHiddenItems(); - customizeView.addColumn(new String[]{"Run", "RowId"}); - customizeView.addColumn(new String[]{"Run", "Protocol", "RowId"}); + customizeView.addColumn(FieldKey.fromParts("Run", "RowId")); + customizeView.addColumn(FieldKey.fromParts("Run", "Protocol", "RowId")); customizeView.applyCustomView(); var protocolId = list.getDataAsText(0, "Run/Protocol/RowId"); var runId = list.getDataAsText(0, "Run/RowId"); diff --git a/src/org/labkey/test/tests/SampleTypeLineageTest.java b/src/org/labkey/test/tests/SampleTypeLineageTest.java index 11ccc0725c..9be0d9d8d2 100644 --- a/src/org/labkey/test/tests/SampleTypeLineageTest.java +++ b/src/org/labkey/test/tests/SampleTypeLineageTest.java @@ -17,6 +17,7 @@ import org.labkey.test.categories.Daily; import org.labkey.test.components.ext4.Window; import org.labkey.test.params.FieldDefinition; +import org.labkey.test.params.FieldKey; import org.labkey.test.params.experiment.DataClassDefinition; import org.labkey.test.params.experiment.SampleTypeDefinition; import org.labkey.test.util.DataRegionTable; @@ -383,7 +384,7 @@ public void testUpdateLineageUsingFileImport() log("Check that the imported data is as expected."); DataRegionTable dataRegionTable = new DataRegionTable("Material", this); - int row = dataRegionTable.getRowIndex(testSample, "Name"); + int row = dataRegionTable.getRowIndex("Name", testSample); String data = dataRegionTable.getDataAsText(row, columnName); checker().verifyEquals("Something doesn't look right. Value for column not as expected.", testData, data); @@ -406,7 +407,7 @@ public void testUpdateLineageUsingFileImport() log("Check that the updated data is shown."); dataRegionTable = new DataRegionTable("Material", this); - row = dataRegionTable.getRowIndex(testSample, "Name"); + row = dataRegionTable.getRowIndex("Name", testSample); data = dataRegionTable.getDataAsText(row, columnName); checker().verifyEquals("Value for column not updated as expected.", updatedTestData, data); @@ -459,7 +460,7 @@ public void testLineageWithThreeGenerations() DataRegionTable table = sampleHelper.getSamplesDataRegionTable(); table.openCustomizeGrid(); _customizeViewsHelper.showHiddenItems(); - _customizeViewsHelper.addColumn(new String[]{"Inputs", "Materials", parentSampleType}); + _customizeViewsHelper.addColumn(FieldKey.fromParts("Inputs", "Materials", parentSampleType)); _customizeViewsHelper.applyCustomView(); waitAndClickAndWait(Locator.linkWithText("SampleSetBVT4")); @@ -652,7 +653,7 @@ public void testDeriveSampleByUI() throws CommandException, IOException for(String parent : parents) { - int index = drt.getRowIndex(parent, "Name"); + int index = drt.getRowIndex("Name", parent); drt.checkCheckbox(index); } @@ -1129,7 +1130,7 @@ public void testDeleteSamplesSomeWithDerivedSamples() sampleHelper.createSampleType(new SampleTypeDefinition(SAMPLE_TYPE_NAME), sampleData); DataRegionTable drtSamples = sampleHelper.getSamplesDataRegionTable(); log("Derive one sample from another"); - drtSamples.checkCheckbox(drtSamples.getRowIndex(parentSampleNames.get(0), "Name")); + drtSamples.checkCheckbox(drtSamples.getRowIndex("Name", parentSampleNames.get(0))); clickButton("Derive Samples"); waitAndClickAndWait(Locator.lkButton("Next")); String childName = parentSampleNames.get(0) + ".1"; @@ -1145,8 +1146,8 @@ public void testDeleteSamplesSomeWithDerivedSamples() log("Derive a sample with two parents"); clickAndWait(Locator.linkContainingText(SAMPLE_TYPE_NAME)); - drtSamples.checkCheckbox(drtSamples.getRowIndex(parentSampleNames.get(1), "Name")); - drtSamples.checkCheckbox(drtSamples.getRowIndex(childName, "Name")); + drtSamples.checkCheckbox(drtSamples.getRowIndex("Name", parentSampleNames.get(1))); + drtSamples.checkCheckbox(drtSamples.getRowIndex("Name", childName)); clickButton("Derive Samples"); waitAndClickAndWait(Locator.lkButton("Next")); String twoParentChildName = parentSampleNames.get(1) + "+" + childName + ".1"; @@ -1156,14 +1157,14 @@ public void testDeleteSamplesSomeWithDerivedSamples() clickAndWait(Locator.linkContainingText(SAMPLE_TYPE_NAME)); log("Try to delete parent sample"); - drtSamples.checkCheckbox(drtSamples.getRowIndex(parentSampleNames.get(0), "Name")); + drtSamples.checkCheckbox(drtSamples.getRowIndex("Name", parentSampleNames.get(0))); drtSamples.clickHeaderButton("Delete"); Window.Window(getDriver()).withTitle("No samples can be deleted").waitFor() .clickButton("Dismiss", true); log("Try to delete multiple parent samples"); - drtSamples.checkCheckbox(drtSamples.getRowIndex(parentSampleNames.get(1), "Name")); - drtSamples.checkCheckbox(drtSamples.getRowIndex(childName, "Name")); + drtSamples.checkCheckbox(drtSamples.getRowIndex("Name", parentSampleNames.get(1))); + drtSamples.checkCheckbox(drtSamples.getRowIndex("Name", childName)); drtSamples.clickHeaderButton("Delete"); Window.Window(getDriver()).withTitle("No samples can be deleted").waitFor() .clickButton("Dismiss", true); @@ -1172,21 +1173,21 @@ public void testDeleteSamplesSomeWithDerivedSamples() assertEquals("No selection should remain", 0, drtSamples.getSelectedCount()); log("Try to delete parent and child"); - drtSamples.checkCheckbox(drtSamples.getRowIndex(parentSampleNames.get(1), "Name")); - drtSamples.checkCheckbox(drtSamples.getRowIndex(twoParentChildName, "Name")); + drtSamples.checkCheckbox(drtSamples.getRowIndex("Name", parentSampleNames.get(1))); + drtSamples.checkCheckbox(drtSamples.getRowIndex("Name", twoParentChildName)); assertEquals("Parent and child should be checked", 2, drtSamples.getCheckedCount()); assertEquals("Parent and child should be checked", 2, drtSamples.getSelectedCount()); sampleHelper.deleteSamples(drtSamples, "Permanently delete 1 sample"); - assertEquals("Deleted sample " + twoParentChildName + " still appears in grid", -1, drtSamples.getRowIndex(twoParentChildName, "Name")); - assertTrue("Parent sample " + parentSampleNames.get(1) + " does not appears in grid", drtSamples.getRowIndex(parentSampleNames.get(1), "Name") > -1); + assertEquals("Deleted sample " + twoParentChildName + " still appears in grid", -1, drtSamples.getRowIndex("Name", twoParentChildName)); + assertTrue("Parent sample " + parentSampleNames.get(1) + " does not appears in grid", drtSamples.getRowIndex("Name", parentSampleNames.get(1)) > -1); assertEquals("Only parent sample should be checked", 1, drtSamples.getCheckedCount()); assertEquals("Only parent sample should be checked", 1, drtSamples.getSelectedCount()); log("Now that the child is gone, try to delete the parent"); sampleHelper.deleteSamples(drtSamples, "Permanently delete 1 sample"); - assertEquals("Deleted sample " + parentSampleNames.get(1) + " still appears in grid", -1, drtSamples.getRowIndex(parentSampleNames.get(1), "Name")); + assertEquals("Deleted sample " + parentSampleNames.get(1) + " still appears in grid", -1, drtSamples.getRowIndex("Name", parentSampleNames.get(1))); assertEquals("No selection should remain", 0, drtSamples.getCheckedCount()); log("Now try to delete what's left, in several hitches"); diff --git a/src/org/labkey/test/tests/TimeChartAPITest.java b/src/org/labkey/test/tests/TimeChartAPITest.java index 08a3bf01d0..1f33efd2bd 100644 --- a/src/org/labkey/test/tests/TimeChartAPITest.java +++ b/src/org/labkey/test/tests/TimeChartAPITest.java @@ -82,7 +82,7 @@ public class TimeChartAPITest extends TimeChartTest add(Pair.of("study_LuminexAssay_ObsConc", Arrays.asList(35.87, 40.07, 52.74, 13.68, 28.35, 42.38, 2.82, 5.19, 7.99, 5.12, 6.69, 32.33, 3.09, 5.76, 12.49))); add(Pair.of("IL-10 (23)::study_LuminexAssay_ObsConc_MAX", Arrays.asList(40.07, 42.38, 7.99, 32.33, 12.49))); add(Pair.of("IL-10 (23)::study_LuminexAssay_ObsConc_MAX", Arrays.asList(40.07, 42.38, 7.99, 32.33, 12.49))); - add(Pair.of("M1", Arrays.asList(520.0, 543.0))); + add(Pair.of("study_GenericAssay_M1", Arrays.asList(520.0, 543.0))); add(Pair.of("IL-10 (23)::study_LuminexAssay_ObsConc_MAX", Arrays.asList(40.07, 42.38, 7.99, 32.33, 12.49))); }}; @@ -152,16 +152,16 @@ protected void doCreateSteps() final List>> GETDATA_API_TEST_VISITLABEL = new ArrayList<>() {{ - add(Pair.of("VisitLabel", Arrays.asList("Month 2", "Month 3", "Month 4", "Month 7", "Month 9", "Month 10", "Month 10", "Month 11", "Month 12", "Month 13"))); - add(Pair.of("VisitLabel", Arrays.asList("Month 2", "Month 3", "Month 4", "Month 7", "Month 9", "Month 10", "Month 10", "Month 11", "Month 12", "Month 13"))); add(Pair.of("study_Lab Results_ParticipantVisit_Visit_Label", Arrays.asList("Month 2", "Month 3", "Month 4", "Month 7", "Month 9", "Month 10", "Month 10", "Month 11", "Month 12", "Month 13"))); add(Pair.of("study_Lab Results_ParticipantVisit_Visit_Label", Arrays.asList("Month 2", "Month 3", "Month 4", "Month 7", "Month 9", "Month 10", "Month 10", "Month 11", "Month 12", "Month 13"))); - add(Pair.of("VisitLabel", Arrays.asList("Month 2", "Month 2", "Month 2", "Month 3", "Month 3", "Month 3", "Month 4", "Month 4", "Month 4", "Month 7", "Month 7", "Month 7", "Month 9", "Month 9", "Month 9"))); + add(Pair.of("study_Lab Results_ParticipantVisit_Visit_Label", Arrays.asList("Month 2", "Month 3", "Month 4", "Month 7", "Month 9", "Month 10", "Month 10", "Month 11", "Month 12", "Month 13"))); + add(Pair.of("study_Lab Results_ParticipantVisit_Visit_Label", Arrays.asList("Month 2", "Month 3", "Month 4", "Month 7", "Month 9", "Month 10", "Month 10", "Month 11", "Month 12", "Month 13"))); + add(Pair.of("study_Lab Results_ParticipantVisit_Visit_Label", Arrays.asList("Month 2", "Month 2", "Month 2", "Month 3", "Month 3", "Month 3", "Month 4", "Month 4", "Month 4", "Month 7", "Month 7", "Month 7", "Month 9", "Month 9", "Month 9"))); add(Pair.of("study_Lab Results_ParticipantVisit_Visit_Label", Arrays.asList("Month 2", "Month 2", "Month 2", "Month 3", "Month 3", "Month 3", "Month 4", "Month 4", "Month 4", "Month 7", "Month 7", "Month 7", "Month 9", "Month 9", "Month 9", "Month 10", "Month 10", "Month 11", "Month 12", "Month 13"))); - add(Pair.of("VisitLabel", Arrays.asList("Month 2", "Month 3", "Month 4", "Month 7", "Month 9"))); + add(Pair.of("study_Lab Results_ParticipantVisit_Visit_Label", Arrays.asList("Month 2", "Month 3", "Month 4", "Month 7", "Month 9"))); + add(Pair.of("study_Lab Results_ParticipantVisit_Visit_Label", Arrays.asList("Month 2", "Month 3", "Month 4", "Month 7", "Month 9", "Month 10", "Month 10", "Month 11", "Month 12", "Month 13"))); + add(Pair.of("study_Lab Results_ParticipantVisit_Visit_Label", Arrays.asList("Month 2", "Month 2", "Month 2", "Month 3", "Month 4", "Month 7", "Month 9", "Month 10", "Month 10", "Month 11", "Month 12", "Month 13"))); add(Pair.of("study_Lab Results_ParticipantVisit_Visit_Label", Arrays.asList("Month 2", "Month 3", "Month 4", "Month 7", "Month 9", "Month 10", "Month 10", "Month 11", "Month 12", "Month 13"))); - add(Pair.of("VisitLabel", Arrays.asList("Month 2", "Month 2", "Month 2", "Month 3", "Month 4", "Month 7", "Month 9", "Month 10", "Month 10", "Month 11", "Month 12", "Month 13"))); - add(Pair.of("VisitLabel", Arrays.asList("Month 2", "Month 3", "Month 4", "Month 7", "Month 9", "Month 10", "Month 10", "Month 11", "Month 12", "Month 13"))); }}; testVisApi(TestFileUtils.getSampleData("api/getDataVisitTest.html"), GETDATA_API_TEST_TITLES, GETDATA_API_TEST_NUMROWS, GETDATA_API_VISITTEST_COLNAMES, null, GETDATA_API_TEST_VISITLABEL, @@ -333,7 +333,7 @@ private void testVisApi(File htmlPage, String[] testTitles, @Nullable int[] test { Pair> expectedColumn = expectedColForAllTests.get(testIndex); String columnName = expectedColumn.getKey(); - int columnIndex = table.getColumnIndex(columnName); + int columnIndex = table.getColumnIndexStrict(columnName); List expectedValues = expectedColumn.getValue(); List actualValues = new ArrayList<>(); boolean isNumberCol = expectedValues.get(0) instanceof Number; diff --git a/src/org/labkey/test/tests/UserDetailsPermissionTest.java b/src/org/labkey/test/tests/UserDetailsPermissionTest.java index 01d33a4121..dab8e7f848 100644 --- a/src/org/labkey/test/tests/UserDetailsPermissionTest.java +++ b/src/org/labkey/test/tests/UserDetailsPermissionTest.java @@ -256,12 +256,12 @@ private void createHiddenEmailList() selectOptionByText(Locator.name("quf_user"), _userHelper.getDisplayNameForEmail(ADMIN_USER)); clickButton("Submit"); _customizeViewsHelper.openCustomizeViewPanel(); - _customizeViewsHelper.addColumn("user/Phone", "Phone"); - _customizeViewsHelper.addColumn("user/" + CUSTOM_USER_COLUMN, CUSTOM_USER_COLUMN); - _customizeViewsHelper.addColumn("user/Email", "Email"); - _customizeViewsHelper.addColumn("user/ModifiedBy/Email", "Email"); - _customizeViewsHelper.addColumn("user/ModifiedBy/ModifiedBy/Email", "Email"); - _customizeViewsHelper.addColumn("ModifiedBy/Email", "Email"); + _customizeViewsHelper.addColumn("user/Phone"); + _customizeViewsHelper.addColumn("user/" + CUSTOM_USER_COLUMN); + _customizeViewsHelper.addColumn("user/Email"); + _customizeViewsHelper.addColumn("user/ModifiedBy/Email"); + _customizeViewsHelper.addColumn("user/ModifiedBy/ModifiedBy/Email"); + _customizeViewsHelper.addColumn("ModifiedBy/Email"); _customizeViewsHelper.saveCustomView(HIDDEN_COL_VIEW, true); assertTextPresent(CHECKED_USER, ADMIN_USER, HIDDEN_STRING); // Ensure subsequent check is valid @@ -273,7 +273,7 @@ private void createUsersTableView() { ExecuteQueryPage.beginAt(this, "core", "Users"); _customizeViewsHelper.openCustomizeViewPanel(); - _customizeViewsHelper.addColumn("ModifiedBy/Email", "Email"); + _customizeViewsHelper.addColumn("ModifiedBy/Email"); _customizeViewsHelper.saveCustomView(HIDDEN_COL_VIEW, true); assertTextPresent(CHECKED_USER, ADMIN_USER, HIDDEN_STRING); // Ensure subsequent check is valid diff --git a/src/org/labkey/test/tests/assay/AssayMissingValuesTest.java b/src/org/labkey/test/tests/assay/AssayMissingValuesTest.java index bb14a71a7e..87cdbb1c46 100644 --- a/src/org/labkey/test/tests/assay/AssayMissingValuesTest.java +++ b/src/org/labkey/test/tests/assay/AssayMissingValuesTest.java @@ -272,8 +272,8 @@ public void testSaveBatchAPIMissingValues() throws Exception // expect 3 rows in this assay, p2 and p3 should get mv indicators in the count column Map> expectedData = new HashMap<>(); - expectedData.put("Participant ID", List.of("p1", "p2", "p3")); - expectedData.put("Visit ID", List.of("1", "1", "1")); + expectedData.put("ParticipantID", List.of("p1", "p2", "p3")); + expectedData.put("VisitId", List.of("1", "1", "1")); expectedData.put("Count", List.of("4", "N", "Q")); checkDataregionData(dataRegion, expectedData); diff --git a/src/org/labkey/test/tests/elispotassay/ElispotAssayTest.java b/src/org/labkey/test/tests/elispotassay/ElispotAssayTest.java index 7e4a65938b..0cda0ff4fd 100644 --- a/src/org/labkey/test/tests/elispotassay/ElispotAssayTest.java +++ b/src/org/labkey/test/tests/elispotassay/ElispotAssayTest.java @@ -17,6 +17,7 @@ package org.labkey.test.tests.elispotassay; import org.apache.commons.lang3.math.NumberUtils; +import org.assertj.core.api.Assertions; import org.junit.BeforeClass; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -210,8 +211,8 @@ public void fluorospotTests() clickAndWait(Locator.linkWithText("view runs")); waitAndClick(Locator.linkWithText("view results")); DataRegionTable results = new DataRegionTable("Data", this); - results.ensureColumnsPresent("Wellgroup Name", "Antigen Wellgroup Name", "Antigen Name", "Cells per Well", "Wellgroup Location", "Spot Count", "Normalized Spot Count", "Spot Size", "Analyte", "Cytokine", "Activity", "Intensity", "Specimen ID", "Participant ID", "Visit ID", "Date", "Sample Description", "ProtocolName", "Plate Reader"); - assertEquals(Arrays.asList("Specimen 4", "Antigen 6", "atg_6F2", "150", "(7, 8)", "0.0", "0.0", " ", "FITC+Cy5", " ", " ", " ", " ", "ptid 4 F2", "4.0", " ", "blood", " ", "AID", " "), results.getRowDataAsText(0)); + Assertions.assertThat(results.getColumnLabels()).as("Wrong columns").containsExactly("Wellgroup Name", "Antigen Wellgroup Name", "Antigen Name", "Cells per Well", "Wellgroup Location", "Spot Count", "Normalized Spot Count", "Spot Size", "Analyte", "Cytokine", "Activity", "Intensity", "Specimen ID", "Participant ID", "Visit ID", "Date", "Sample Description", "ProtocolName", "Plate Reader", "Target Study"); + Assertions.assertThat(results.getRowDataAsText(0)).as("row data").containsExactly("Specimen 4", "Antigen 6", "atg_6F2", "150", "(7, 8)", "0.0", "0.0", " ", "FITC+Cy5", " ", " ", " ", " ", "ptid 4 F2", "4.0", " ", "blood", " ", "AID", " "); } private void verifyDataRegion(DataRegionTable table, SortDirection sortDir, List expectedSpotCount, List expectedActivity, List expectedIntensity, List expectedCytokine) @@ -226,9 +227,9 @@ private void verifyDataRegion(DataRegionTable table, SortDirection sortDir, List cvHelper.removeSort("Analyte"); cvHelper.removeSort("WellgroupLocation"); - cvHelper.addSort("AntigenLsid/AntigenName", "AntigenName", sortDir); - cvHelper.addSort("Analyte", "Analyte", sortDir); - cvHelper.addSort("WellgroupLocation", "WellgroupLocation", sortDir); + cvHelper.addSort("AntigenLsid/AntigenName", sortDir); + cvHelper.addSort("Analyte", sortDir); + cvHelper.addSort("WellgroupLocation", sortDir); cvHelper.applyCustomView(); pushLocation(); diff --git a/src/org/labkey/test/tests/flow/FlowDuplicateSamplesTest.java b/src/org/labkey/test/tests/flow/FlowDuplicateSamplesTest.java index 1d3f9a2c23..658bfdff97 100644 --- a/src/org/labkey/test/tests/flow/FlowDuplicateSamplesTest.java +++ b/src/org/labkey/test/tests/flow/FlowDuplicateSamplesTest.java @@ -10,6 +10,7 @@ import org.labkey.test.categories.Daily; import org.labkey.test.categories.FileBrowser; import org.labkey.test.categories.Flow; +import org.labkey.test.params.FieldKey; import org.labkey.test.util.DataRegionTable; import org.labkey.test.util.PipelineStatusTable; @@ -53,16 +54,19 @@ public void duplicateSamples() importAnalysis(getContainerPath(), "/flowjoquery/Workspaces/duplicate-samples.xml", SelectFCSFileOption.Previous, null, "dupes", false, true); + FieldKey fcsFileFk = FieldKey.fromParts("FCSFile"); + FieldKey DTOTfk = fcsFileFk.child("Keyword", "$TOT"); + FieldKey filePathFk = fcsFileFk.child("FilePath"); // verify both samples "118795.fcs" were imported and associated with the correct FCS file _customizeViewsHelper.openCustomizeViewPanel(); _customizeViewsHelper.showHiddenItems(); - _customizeViewsHelper.addColumn(new String[] { "FCSFile", "Keyword", "$DTOT"}); - _customizeViewsHelper.addColumn(new String[] { "FCSFile", "FilePath"}); + _customizeViewsHelper.addColumn(DTOTfk.toString()); + _customizeViewsHelper.addColumn(filePathFk.toString()); _customizeViewsHelper.addSort("Statistic/Count", SortDirection.ASC); _customizeViewsHelper.applyCustomView(); var dr = new DataRegionTable("query", getDriver()); - var rows = dr.getRows("Name", "Count", "$TOT", "FilePath"); + var rows = dr.getRows("Name", "Count", DTOTfk, filePathFk); Assert.assertEquals(2, rows.size()); var row0 = rows.get(0); diff --git a/src/org/labkey/test/tests/flow/FlowJoQueryTest.java b/src/org/labkey/test/tests/flow/FlowJoQueryTest.java index 9d3f526db8..154bbdfbcb 100644 --- a/src/org/labkey/test/tests/flow/FlowJoQueryTest.java +++ b/src/org/labkey/test/tests/flow/FlowJoQueryTest.java @@ -71,12 +71,12 @@ protected void verifyQueryTest() _customizeViewsHelper.openCustomizeViewPanel(); _customizeViewsHelper.clearColumns(); _customizeViewsHelper.addColumn("Name"); - _customizeViewsHelper.addColumn("AnalysisScript", "Analysis Script"); - _customizeViewsHelper.addColumn("FCSFile/Keyword/Comp", "Comp"); - _customizeViewsHelper.addColumn("FCSFile/Keyword/Stim", "Stim"); - _customizeViewsHelper.addColumn("FCSFile/Keyword/Sample Order", "Sample Order"); - _customizeViewsHelper.addColumn("Statistic/S$SLv$SL$S3+$S4+:Count", "4+:Count"); - _customizeViewsHelper.addColumn("Statistic/S$SLv$SL$S3+$S8+:Count", "8+:Count"); + _customizeViewsHelper.addColumn("AnalysisScript"); + _customizeViewsHelper.addColumn("FCSFile/Keyword/Comp"); + _customizeViewsHelper.addColumn("FCSFile/Keyword/Stim"); + _customizeViewsHelper.addColumn("FCSFile/Keyword/Sample Order"); + _customizeViewsHelper.addColumn("Statistic/S$SLv$SL$S3+$S4+:Count"); + _customizeViewsHelper.addColumn("Statistic/S$SLv$SL$S3+$S8+:Count"); _customizeViewsHelper.applyCustomView(); clickProject(getProjectName()); diff --git a/src/org/labkey/test/tests/flow/FlowTest.java b/src/org/labkey/test/tests/flow/FlowTest.java index 3987aad49a..464dd0fa0d 100644 --- a/src/org/labkey/test/tests/flow/FlowTest.java +++ b/src/org/labkey/test/tests/flow/FlowTest.java @@ -34,6 +34,7 @@ import org.labkey.test.pages.flow.reports.ReportEditorPage; import org.labkey.test.pages.pipeline.PipelineStatusDetailsPage; import org.labkey.test.params.FieldDefinition; +import org.labkey.test.params.FieldKey; import org.labkey.test.tests.AuditLogTest; import org.labkey.test.util.DataRegion; import org.labkey.test.util.DataRegionTable; @@ -787,13 +788,13 @@ private void verifyReport(@LoggedParam String reportName) { beginAt("/flow" + getContainerPath() + "/query.view?schemaName=flow&query.queryName=FCSAnalyses"); - String reportNameEscaped = EscapeUtil.fieldKeyEncodePart(reportName); + FieldKey reportNameFk = FieldKey.fromParts(reportName); _customizeViewsHelper.openCustomizeViewPanel(); - _customizeViewsHelper.addColumn(new String[] { reportNameEscaped, "Raw P" }); - _customizeViewsHelper.addColumn(new String[] { reportNameEscaped, "Adjusted P"}); - _customizeViewsHelper.addColumn(new String[] { reportNameEscaped, "Response"}); - _customizeViewsHelper.addFilter(new String[] { reportNameEscaped, "Response"}, "Response", "Equals", "1"); + _customizeViewsHelper.addColumn(reportNameFk.child("Raw P")); + _customizeViewsHelper.addColumn(reportNameFk.child("Adjusted P")); + _customizeViewsHelper.addColumn(reportNameFk.child("Response")); + _customizeViewsHelper.addFilter(reportNameFk.child("Response"), "Equals", "1"); _customizeViewsHelper.addSort("Name", SortDirection.ASC); _customizeViewsHelper.saveCustomView(); diff --git a/src/org/labkey/test/tests/list/ListTest.java b/src/org/labkey/test/tests/list/ListTest.java index a7293f6727..9c5404850b 100644 --- a/src/org/labkey/test/tests/list/ListTest.java +++ b/src/org/labkey/test/tests/list/ListTest.java @@ -52,7 +52,7 @@ import org.labkey.test.pages.query.UpdateQueryRowPage; import org.labkey.test.params.FieldDefinition; import org.labkey.test.params.FieldDefinition.StringLookup; -import org.labkey.test.params.FieldInfo; +import org.labkey.test.params.FieldKey; import org.labkey.test.params.list.VarListDefinition; import org.labkey.test.tests.AuditLogTest; import org.labkey.test.util.AbstractDataRegionExportOrSignHelper.ColumnHeaderType; @@ -598,8 +598,8 @@ public void testCustomViews() clickAndWait(Locator.linkWithText(LIST_NAME_COLORS)); _customizeViewsHelper.openCustomizeViewPanel(); _customizeViewsHelper.removeColumn(_listColGood.getName()); - _customizeViewsHelper.addFilter(_listColGood.getName(), _listColGood.getLabel(), "Is Less Than", "10"); - _customizeViewsHelper.addSort(_listColMonth.getName(), _listColMonth.getLabel(), SortDirection.ASC); + _customizeViewsHelper.addFilter(_listColGood.getName(), "Is Less Than", "10"); + _customizeViewsHelper.addSort(_listColMonth.getName(), SortDirection.ASC); _customizeViewsHelper.saveCustomView(TEST_VIEW); log("Check Customize View worked"); @@ -718,13 +718,13 @@ public void testCustomViews() log("Check that reference worked"); _customizeViewsHelper.openCustomizeViewPanel(); - _customizeViewsHelper.addColumn(EscapeUtil.fieldKeyEncodePart(_list2Col1.getName()) + "/" + _listColDesc.getName(), _list2Col1.getLabel() + " " + _listColDesc.getLabel()); - _customizeViewsHelper.addColumn(EscapeUtil.fieldKeyEncodePart(_list2Col1.getName()) + "/" + _listColMonth.getName(), _list2Col1.getLabel() + " " + _listColMonth.getLabel()); - _customizeViewsHelper.addColumn(EscapeUtil.fieldKeyEncodePart(_list2Col1.getName()) + "/" + _listColGood.getName(), _list2Col1.getLabel() + " " + _listColGood.getLabel()); - _customizeViewsHelper.addFilter(EscapeUtil.fieldKeyEncodePart(_list2Col1.getName()) + "/" + _listColGood.getName(), _listColGood.getLabel(), "Is Less Than", "10"); - _customizeViewsHelper.addSort(EscapeUtil.fieldKeyEncodePart(_list2Col1.getName()) + "/" + _listColGood.getName(), _listColGood.getLabel(), SortDirection.ASC); - _customizeViewsHelper.addColumn(_list3Col1.getName() + "/" + _list3Col1.getName(), _list3Col1.getLabel() + " " + _list3Col1.getLabel()); - _customizeViewsHelper.addColumn(_list3Col1.getName() + "/" + _list3Col2.getName(), _list3Col1.getLabel() + " " + _list3Col2.getLabel()); + _customizeViewsHelper.addColumn(FieldKey.fromParts(_list2Col1.getName(), _listColDesc.getName())); + _customizeViewsHelper.addColumn(FieldKey.fromParts(_list2Col1.getName(), _listColMonth.getName())); + _customizeViewsHelper.addColumn(FieldKey.fromParts(_list2Col1.getName(), _listColGood.getName())); + _customizeViewsHelper.addFilter(FieldKey.fromParts(_list2Col1.getName(), _listColGood.getName()), "Is Less Than", "10"); + _customizeViewsHelper.addSort(FieldKey.fromParts(_list2Col1.getName(), _listColGood.getName()), SortDirection.ASC); + _customizeViewsHelper.addColumn(_list3Col1.getName() + "/" + _list3Col1.getName()); + _customizeViewsHelper.addColumn(_list3Col1.getName() + "/" + _list3Col2.getName()); _customizeViewsHelper.saveCustomView(TEST_VIEW); log("Check adding referenced fields worked"); @@ -2079,11 +2079,11 @@ public void customizeURLTest() // show all columns _customizeViewsHelper.openCustomizeViewPanel(); - _customizeViewsHelper.addColumn("Bfk/B", "Bfk B"); - _customizeViewsHelper.addColumn("Bfk/title", "Bfk Title"); - _customizeViewsHelper.addColumn("Bfk/Cfk", "Bfk Cfk"); - _customizeViewsHelper.addColumn("Bfk/Cfk/C", "Bfk Cfk C"); - _customizeViewsHelper.addColumn("Bfk/Cfk/title", "Bfk Cfk Title"); + _customizeViewsHelper.addColumn("Bfk/B"); + _customizeViewsHelper.addColumn("Bfk/title"); + _customizeViewsHelper.addColumn("Bfk/Cfk"); + _customizeViewsHelper.addColumn("Bfk/Cfk/C"); + _customizeViewsHelper.addColumn("Bfk/Cfk/title"); _customizeViewsHelper.saveCustomView("allColumns"); clickAndWait(Locator.linkWithText("one C").index(1)); diff --git a/src/org/labkey/test/tests/nab/NAbResultCalcTest.java b/src/org/labkey/test/tests/nab/NAbResultCalcTest.java index 02f48dc295..589d68b13b 100644 --- a/src/org/labkey/test/tests/nab/NAbResultCalcTest.java +++ b/src/org/labkey/test/tests/nab/NAbResultCalcTest.java @@ -72,8 +72,8 @@ public void testPercentNeutralizationCalcsForDilution() waitAndClickAndWait(Locator.linkWithText("View Results")); _customizeViewsHelper.openCustomizeViewPanel(); - _customizeViewsHelper.addColumn("PercentNeutralizationInitialDilution", "Percent Neutralization Initial Dilution"); - _customizeViewsHelper.addColumn("PercentNeutralizationMax", "Percent Neutralization Max"); + _customizeViewsHelper.addColumn("PercentNeutralizationInitialDilution"); + _customizeViewsHelper.addColumn("PercentNeutralizationMax"); _customizeViewsHelper.applyCustomView(); DataRegionTable region = new DataRegionTable("Data", this); @@ -103,8 +103,8 @@ public void testPercentNeutralizationCalcsForConcentration() waitAndClickAndWait(Locator.linkWithText("View Results")); _customizeViewsHelper.openCustomizeViewPanel(); - _customizeViewsHelper.addColumn("PercentNeutralizationInitialDilution", "Percent Neutralization Initial Dilution"); - _customizeViewsHelper.addColumn("PercentNeutralizationMax", "Percent Neutralization Max"); + _customizeViewsHelper.addColumn("PercentNeutralizationInitialDilution"); + _customizeViewsHelper.addColumn("PercentNeutralizationMax"); _customizeViewsHelper.applyCustomView(); DataRegionTable region = new DataRegionTable("Data", this); diff --git a/src/org/labkey/test/tests/nab/NabAssayTest.java b/src/org/labkey/test/tests/nab/NabAssayTest.java index 5d013a74bc..1585551864 100644 --- a/src/org/labkey/test/tests/nab/NabAssayTest.java +++ b/src/org/labkey/test/tests/nab/NabAssayTest.java @@ -621,18 +621,18 @@ private void addAUCColumns() log("Adding AUC columns to custom view"); // add AUC columns. ORDER MATTERS! _customizeViewsHelper.openCustomizeViewPanel(); - _customizeViewsHelper.addColumn("AUC_4pl", "AUC 4pl"); - _customizeViewsHelper.addColumn("AUC_5pl", "AUC 5pl"); - _customizeViewsHelper.addColumn("AUC_Poly", "AUC Poly"); - _customizeViewsHelper.addColumn("Cutoff50/IC_4pl", "Curve IC50 4pl"); - _customizeViewsHelper.addColumn("Cutoff50/IC_5pl", "Curve IC50 5pl"); - _customizeViewsHelper.addColumn("Cutoff50/IC_Poly", "Curve IC50 Poly"); - _customizeViewsHelper.addColumn("Cutoff70/IC_4pl", "Curve IC70 4pl"); - _customizeViewsHelper.addColumn("Cutoff70/IC_5pl", "Curve IC70 5pl"); - _customizeViewsHelper.addColumn("Cutoff70/IC_Poly", "Curve IC70 Poly"); - _customizeViewsHelper.addColumn("Cutoff80/IC_4pl", "Curve IC80 4pl"); - _customizeViewsHelper.addColumn("Cutoff80/IC_5pl", "Curve IC80 5pl"); - _customizeViewsHelper.addColumn("Cutoff80/IC_Poly", "Curve IC80 Poly"); + _customizeViewsHelper.addColumn("AUC_4pl"); + _customizeViewsHelper.addColumn("AUC_5pl"); + _customizeViewsHelper.addColumn("AUC_Poly"); + _customizeViewsHelper.addColumn("Cutoff50/IC_4pl"); + _customizeViewsHelper.addColumn("Cutoff50/IC_5pl"); + _customizeViewsHelper.addColumn("Cutoff50/IC_Poly"); + _customizeViewsHelper.addColumn("Cutoff70/IC_4pl"); + _customizeViewsHelper.addColumn("Cutoff70/IC_5pl"); + _customizeViewsHelper.addColumn("Cutoff70/IC_Poly"); + _customizeViewsHelper.addColumn("Cutoff80/IC_4pl"); + _customizeViewsHelper.addColumn("Cutoff80/IC_5pl"); + _customizeViewsHelper.addColumn("Cutoff80/IC_Poly"); _customizeViewsHelper.applyCustomView(); } @@ -672,13 +672,13 @@ private void assertAliasedAUCStudyData() DataRegionTable table = new DataRegionTable("Dataset", this); table.setSort("ParticipantId", SortDirection.ASC); _customizeViewsHelper.openCustomizeViewPanel(); - _customizeViewsHelper.addColumn("AUC_Poly", AUC_POLY_COL_TITLE); - _customizeViewsHelper.addColumn("AUC_4pl", AUC_4PL_COL_TITLE); - _customizeViewsHelper.addColumn("AUC_5pl", AUC_5PL_COL_TITLE); - _customizeViewsHelper.addColumn("Cutoff50/IC_Poly", CURVE_IC50_POLY_COL_TITLE); - _customizeViewsHelper.addColumn("Cutoff50/IC_4pl", CURVE_IC50_4PL_COL_TITLE); - _customizeViewsHelper.addColumn("Cutoff70/IC_Poly", CURVE_IC70_POLY_COL_TITLE); - _customizeViewsHelper.addColumn("Cutoff80/IC_4pl", CURVE_IC80_4PL_COL_TITLE); + _customizeViewsHelper.addColumn("AUC_Poly"); + _customizeViewsHelper.addColumn("AUC_4pl"); + _customizeViewsHelper.addColumn("AUC_5pl"); + _customizeViewsHelper.addColumn("Cutoff50/IC_Poly"); + _customizeViewsHelper.addColumn("Cutoff50/IC_4pl"); + _customizeViewsHelper.addColumn("Cutoff70/IC_Poly"); + _customizeViewsHelper.addColumn("Cutoff80/IC_4pl"); _customizeViewsHelper.saveCustomView(); table = new DataRegionTable("Dataset", this); diff --git a/src/org/labkey/test/tests/viability/ViabilityTest.java b/src/org/labkey/test/tests/viability/ViabilityTest.java index 3593bf685d..ed38972cbe 100644 --- a/src/org/labkey/test/tests/viability/ViabilityTest.java +++ b/src/org/labkey/test/tests/viability/ViabilityTest.java @@ -348,7 +348,7 @@ protected void runTargetStudyTest() clickAndWait(Locator.linkWithText(runName)); _customizeViewsHelper.openCustomizeViewPanel(); - _customizeViewsHelper.addColumn("TargetStudy", "Target Study"); + _customizeViewsHelper.addColumn("TargetStudy"); _customizeViewsHelper.saveDefaultView(); DataRegionTable table = new DataRegionTable("Data", this); diff --git a/src/org/labkey/test/util/DataRegionTable.java b/src/org/labkey/test/util/DataRegionTable.java index d0f00e599f..aacbb3d46d 100644 --- a/src/org/labkey/test/util/DataRegionTable.java +++ b/src/org/labkey/test/util/DataRegionTable.java @@ -416,7 +416,7 @@ public WebElement link(int row, CharSequence columnIdentifier) return link(row, getColumnIndexStrict(columnIdentifier)); } - protected int getColumnIndexStrict(CharSequence columnIdentifier) + public int getColumnIndexStrict(CharSequence columnIdentifier) { return elementCache().getColumnIndex(columnIdentifier).getDomIndex(); } @@ -1536,7 +1536,7 @@ protected FieldReferenceManager getColumnHeaderManager() String noSpaces = columnIdentifier.toString().replace(" ", ""); if (!noSpaces.equals(columnIdentifier.toString())) { - fieldReference = elementCache().getColumnHeaderManager().findFieldReferenceOrNull(columnIdentifier); + fieldReference = elementCache().getColumnHeaderManager().findFieldReferenceOrNull(noSpaces); if (fieldReference != null) { TestLogger.warn("Unnecessary space in requested column name. " + From 38b3bed151657545feaba7e7eebb2a30cc3cb222 Mon Sep 17 00:00:00 2001 From: Nick Kerr Date: Thu, 3 Jul 2025 09:39:41 -0700 Subject: [PATCH 2/8] Add EntityBulkUpdateDialog.getSelectionFieldHelpBlockText() (#2531) --- .../components/ui/entities/EntityBulkUpdateDialog.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/org/labkey/test/components/ui/entities/EntityBulkUpdateDialog.java b/src/org/labkey/test/components/ui/entities/EntityBulkUpdateDialog.java index a5300dca78..066410a787 100644 --- a/src/org/labkey/test/components/ui/entities/EntityBulkUpdateDialog.java +++ b/src/org/labkey/test/components/ui/entities/EntityBulkUpdateDialog.java @@ -1,6 +1,7 @@ package org.labkey.test.components.ui.entities; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.labkey.remoteapi.CommandException; import org.labkey.test.BootstrapLocators; import org.labkey.test.Locator; @@ -132,6 +133,15 @@ public EntityBulkUpdateDialog setSelectionField(CharSequence fieldIdentifier, St return setSelectionField(fieldIdentifier, List.of(selectValue)); } + /** + * @param fieldIdentifier Identifier for the field; name ({@link String}) or fieldKey ({@link FieldKey}) + * @return text displayed in the help block, if any, for the selection field + */ + public @Nullable String getSelectionFieldHelpBlockText(CharSequence fieldIdentifier) + { + return elementCache().getSelect(fieldIdentifier).getHelpBlockText(); + } + /** * @param fieldIdentifier Identifier for the field; name ({@link String}) or fieldKey ({@link FieldKey}) * @return available options for the specified field From 98c705cb9d55afe3f7ea8625c7dbd2ae50dd9736 Mon Sep 17 00:00:00 2001 From: Alan Vezina Date: Thu, 3 Jul 2025 14:25:56 -0500 Subject: [PATCH 3/8] Alan's 25.7 Issues (#2535) Add clickEditAssayDesign to AssayRunsPage --- src/org/labkey/test/pages/assay/AssayRunsPage.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/org/labkey/test/pages/assay/AssayRunsPage.java b/src/org/labkey/test/pages/assay/AssayRunsPage.java index 79fd09df05..8da9a93c4a 100644 --- a/src/org/labkey/test/pages/assay/AssayRunsPage.java +++ b/src/org/labkey/test/pages/assay/AssayRunsPage.java @@ -21,6 +21,7 @@ import org.labkey.test.WebTestHelper; import org.labkey.test.components.bootstrap.ModalDialog; import org.labkey.test.components.labkey.LabKeyAlert; +import org.labkey.test.components.react.MultiMenu; import org.labkey.test.pages.LabKeyPage; import org.labkey.test.util.DataRegionTable; import org.labkey.test.util.ExperimentRunTable; @@ -107,6 +108,11 @@ public AssayRunsPage setRowQcStatus(String state, String comment, boolean expect return updatePage.clickUpdate(); } + public void clickEditAssayDesign() + { + elementCache().manageMenu.doMenuAction("Edit Assay Design"); + } + @Override protected ElementCache newElementCache() { @@ -115,6 +121,6 @@ protected ElementCache newElementCache() protected class ElementCache extends LabKeyPage.ElementCache { - + MultiMenu manageMenu = new MultiMenu.MultiMenuFinder(getDriver()).withText("Manage").findWhenNeeded(getDriver()); } } From 39f09ec1eb034996edddca91efae6cffb01df7bc Mon Sep 17 00:00:00 2001 From: Trey Chadick Date: Thu, 3 Jul 2025 14:29:56 -0700 Subject: [PATCH 4/8] Use OS-specific file separator for expected file paths (#2536) --- .../labkey/test/tests/core/admin/AllowedFileExtensionTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionTest.java b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionTest.java index 70b95debb2..e20c43fb95 100644 --- a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionTest.java +++ b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionTest.java @@ -381,7 +381,7 @@ public void testAllowedFileExtensionsInSampleType() { fieldMap = Map.of("Name", String.format("S-%d", i), stFileField, fileMap.get(allowedType).getAbsolutePath()); sampleTypeHelper.insertRow(fieldMap); - expectedValues.add(String.format(" sampletype/%s", fileMap.get(allowedType).getName())); + expectedValues.add(String.format(" sampletype%s%s", File.separator, fileMap.get(allowedType).getName())); i++; } From 645e4343eb760d797ad18c792f9f6c563edb5d25 Mon Sep 17 00:00:00 2001 From: Adam Rauch Date: Sat, 5 Jul 2025 10:28:03 -0700 Subject: [PATCH 5/8] Add test for "Reset" email notifications settings (#2534) --- .../pages/announcements/EmailPrefsPage.java | 70 +++++++++++++++++-- .../labkey/test/tests/MessagesLongTest.java | 47 ++++++++++--- 2 files changed, 101 insertions(+), 16 deletions(-) diff --git a/src/org/labkey/test/pages/announcements/EmailPrefsPage.java b/src/org/labkey/test/pages/announcements/EmailPrefsPage.java index 4b6f70746d..02b74c319d 100644 --- a/src/org/labkey/test/pages/announcements/EmailPrefsPage.java +++ b/src/org/labkey/test/pages/announcements/EmailPrefsPage.java @@ -43,36 +43,92 @@ public static EmailPrefsPage beginAt(WebDriverWrapper driver, String containerPa return new EmailPrefsPage(driver.getDriver()); } + @Deprecated // Inconsistent name, but leave for backward compatibility public EmailPrefsPage setNoNotify() + { + return setNotifyNone(); + } + + public EmailPrefsPage setNotifyNone() { elementCache().notifyNone.click(); return new EmailPrefsPage(getDriver()); } + public boolean isNotifyNoneSelected() + { + return elementCache().notifyNone.isSelected(); + } + + public boolean isNotifyNoneDisabled() + { + return !elementCache().notifyNone.isEnabled(); + } + public EmailPrefsPage setNotifyOnMine() { elementCache().notifyMine.click(); return new EmailPrefsPage(getDriver()); } + public boolean isNotifyOnMineSelected() + { + return elementCache().notifyMine.isSelected(); + } + + public boolean isNotifyOnMineDisabled() + { + return !elementCache().notifyMine.isEnabled(); + } + public EmailPrefsPage setNotifyOnAll() { elementCache().notifyAll.click(); return new EmailPrefsPage(getDriver()); } + public boolean isNotifyOnAllSelected() + { + return elementCache().notifyAll.isSelected(); + } + + public boolean isNotifyOnAllDisabled() + { + return !elementCache().notifyAll.isEnabled(); + } + public EmailPrefsPage setTypeIndividual() { - elementCache().notifyAll.click(); + elementCache().typeIndividual.click(); return new EmailPrefsPage(getDriver()); } + public boolean isTypeIndividualSelected() + { + return elementCache().typeIndividual.isSelected(); + } + + public boolean isTypeIndividualDisabled() + { + return !elementCache().typeIndividual.isEnabled(); + } + public EmailPrefsPage setTypeDigest() { - elementCache().notifyAll.click(); + elementCache().typeDigest.click(); return new EmailPrefsPage(getDriver()); } + public boolean isTypeDigestSelected() + { + return elementCache().typeDigest.isSelected(); + } + + public boolean isTypeDigestDisabled() + { + return !elementCache().typeDigest.isEnabled(); + } + public EmailPrefsPage reset(boolean reset) { if (reset) @@ -108,16 +164,16 @@ protected ElementCache newElementCache() protected class ElementCache extends LabKeyPage.ElementCache { - private Locator.XPathLocator notify = Locator.radioButtonByName("emailPreference"); + private final Locator.XPathLocator notify = Locator.radioButtonByName("emailPreference"); protected WebElement notifyNone = notify.withAttribute("value", "0").findWhenNeeded(this); protected WebElement notifyMine = notify.withAttribute("value", "2").findWhenNeeded(this); protected WebElement notifyAll = notify.withAttribute("value", "1").findWhenNeeded(this); - private Locator.XPathLocator type = Locator.radioButtonByName("notificationType"); - protected WebElement typeIndividual = notify.withAttribute("value", "3").findWhenNeeded(this); - protected WebElement typeDigest = notify.withAttribute("value", "4").findWhenNeeded(this); + private final Locator.XPathLocator type = Locator.radioButtonByName("notificationType"); + protected WebElement typeIndividual = type.withAttribute("value", "3").findWhenNeeded(this); + protected WebElement typeDigest = type.withAttribute("value", "4").findWhenNeeded(this); - Checkbox resetCheckbox = Checkbox(Locator.tagWithName("input", "emailPreference").withAttribute("value", "1")).findWhenNeeded(this); + Checkbox resetCheckbox = Checkbox(Locator.tagWithId("input", "resetFolderDefault")).findWhenNeeded(this); WebElement updateButton = Locator.lkButton("Update").findWhenNeeded(this); WebElement cancelButton = Locator.lkButton("Cancel").findWhenNeeded(this); diff --git a/src/org/labkey/test/tests/MessagesLongTest.java b/src/org/labkey/test/tests/MessagesLongTest.java index 5974d1b803..136dcc2431 100644 --- a/src/org/labkey/test/tests/MessagesLongTest.java +++ b/src/org/labkey/test/tests/MessagesLongTest.java @@ -33,6 +33,7 @@ import org.labkey.test.components.html.SiteNavBar; import org.labkey.test.pages.admin.PermissionsPage; import org.labkey.test.pages.announcements.AdminPage; +import org.labkey.test.pages.announcements.EmailPrefsPage; import org.labkey.test.pages.announcements.InsertPage; import org.labkey.test.pages.announcements.RespondPage; import org.labkey.test.util.ApiPermissionsHelper; @@ -170,8 +171,6 @@ private void doSetup() .assertPermissionSetting("testers1", "No Permissions") .clickSaveAndFinish(); _containerHelper.enableModule(PROJECT_NAME, "Dumbster"); - - } @Test @@ -190,10 +189,37 @@ public void testSteps() clickProject(PROJECT_NAME); log("Check email preferences"); + // Unlike EmailPrefsPage.beginAt(), this ensures returnUrl is passed to the action _portalHelper.clickWebpartMenuItem("Messages", true, "Email Preferences"); - checkCheckbox(Locator.radioButtonByName("emailPreference").index(2)); - clickButton("Update"); - clickButton("Done"); + EmailPrefsPage prefsPage = new EmailPrefsPage(getDriver()); + // Verify prefs are "Mine" (doTestEmailPrefsMine() sets this) and "Individual" (folder default) + assertTrue(prefsPage.isNotifyOnMineSelected()); + assertTrue(prefsPage.isTypeIndividualSelected()); + + // Update to settings that differ from the folder default values to test "Reset to folder default setting", Issue 53387 + prefsPage = prefsPage + .setNotifyOnAll() + .setTypeDigest() + .update(); + assertTrue(prefsPage.isNotifyOnAllSelected()); + assertTrue(prefsPage.isTypeDigestSelected()); + + // After clicking "Reset", all options should be disabled + prefsPage = prefsPage.reset(true); + assertTrue(prefsPage.isNotifyNoneDisabled()); + assertTrue(prefsPage.isNotifyOnMineDisabled()); + assertTrue(prefsPage.isNotifyOnAllDisabled()); + assertTrue(prefsPage.isTypeIndividualDisabled()); + assertTrue(prefsPage.isTypeDigestDisabled()); + + // Submit reset to folder default and verify + prefsPage = prefsPage.update(); + assertTrue(prefsPage.isNotifyOnMineSelected()); + assertTrue(prefsPage.isTypeIndividualSelected()); + + prefsPage = prefsPage.setNotifyOnAll().update(); + assertTrue(prefsPage.isNotifyOnAllSelected()); + prefsPage.done(); SiteNavBar siteNavBar = new SiteNavBar(getDriver()); siteNavBar.enterPageAdminMode(); @@ -225,7 +251,7 @@ public void testSteps() log("Create message using markdown"); clickButton( "New"); InsertPage markdownPage = new InsertPage(getDriver()); - assertEquals("default selection should be 'Markdown'",markdownPage.getRenderAs(), WikiHelper.WikiRendererType.MARKDOWN); + assertEquals("default selection should be 'Markdown'", WikiHelper.WikiRendererType.MARKDOWN, markdownPage.getRenderAs()); markdownPage.setTitle("Markdown is a thing now") .setBody(""" # Holy Header, Batman! @@ -644,10 +670,13 @@ private void doTestEmailPrefsMine() createUserWithPermissions(RESPONDER, PROJECT_NAME, "Editor"); goToProjectHome(PROJECT_NAME); + // Unlike EmailPrefsPage.beginAt(), this ensures returnUrl is passed to the action _portalHelper.clickWebpartMenuItem("Messages", true, "Email Preferences"); - checkCheckbox(Locator.radioButtonByName("emailPreference").index(1)); - clickButton("Update"); - clickButton("Done"); + EmailPrefsPage prefsPage = new EmailPrefsPage(getDriver()) + .setNotifyOnMine() + .update(); + assertTrue(prefsPage.isNotifyOnMineSelected()); + prefsPage.done(); createNewMessage(_messageTitle, _messageBody); From f46ec8a460cf0c7b8ea3bd02ee84bedd6ebb9cc1 Mon Sep 17 00:00:00 2001 From: Cory Nathe Date: Mon, 7 Jul 2025 08:52:18 -0500 Subject: [PATCH 6/8] Issue 53394: FileInput revert removal of the "-fileUpload" suffix from inputId (#2532) - Test identifier updates for -fileUpload suffix revert --- .../components/ui/entities/EntityBulkUpdateDialog.java | 10 ++++++---- .../components/ui/files/FileAttachmentContainer.java | 10 ++++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/org/labkey/test/components/ui/entities/EntityBulkUpdateDialog.java b/src/org/labkey/test/components/ui/entities/EntityBulkUpdateDialog.java index 066410a787..09aee4dcc9 100644 --- a/src/org/labkey/test/components/ui/entities/EntityBulkUpdateDialog.java +++ b/src/org/labkey/test/components/ui/entities/EntityBulkUpdateDialog.java @@ -253,9 +253,10 @@ public String getDateField(CharSequence fieldIdentifier) * @param fieldIdentifier Identifier for the field; name ({@link String}) or fieldKey ({@link FieldKey}) * @return file attachment component */ - public FileAttachmentContainer getFileField(CharSequence fieldIdentifier) + private FileAttachmentContainer getFileField(CharSequence fieldIdentifier) { - return enableAndWait(fieldIdentifier, elementCache().fileUploadField(fieldIdentifier)); + FieldKey identifier = FileAttachmentContainer.fileUploadFieldKey(fieldIdentifier); + return enableAndWait(identifier, elementCache().fileUploadField(identifier)); } /** @@ -279,9 +280,10 @@ public EntityBulkUpdateDialog removeFile(CharSequence fieldIdentifier) return this; } - public FileUploadField getExistingFileField(String fieldIdentifier) + public FileUploadField getExistingFileCard(CharSequence fieldIdentifier) { - return enableAndWait(fieldIdentifier, elementCache().fileField(fieldIdentifier)); + FieldKey identifier = FileAttachmentContainer.fileUploadFieldKey(fieldIdentifier); + return enableAndWait(identifier, elementCache().fileField(identifier)); } /** diff --git a/src/org/labkey/test/components/ui/files/FileAttachmentContainer.java b/src/org/labkey/test/components/ui/files/FileAttachmentContainer.java index bb6acebe86..01cbeb7946 100644 --- a/src/org/labkey/test/components/ui/files/FileAttachmentContainer.java +++ b/src/org/labkey/test/components/ui/files/FileAttachmentContainer.java @@ -6,6 +6,7 @@ import org.labkey.test.components.WebDriverComponent; import org.labkey.test.components.html.FileInput; import org.labkey.test.components.html.Input; +import org.labkey.test.params.FieldKey; import org.openqa.selenium.ElementNotInteractableException; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; @@ -195,6 +196,15 @@ protected class ElementCache extends Component.ElementCache public Locator fileUploadScrollFooterLoc = Locator.tagWithClass("div", "file-upload__scroll-footer"); } + /** + * File upload fields append "-fileUpload" to the field's fieldKey + * @param fieldIdentifier Identifier for the field; name ({@link String}) or fieldKey ({@link FieldKey}) + * @return FieldKey with expected suffix + */ + public static FieldKey fileUploadFieldKey(CharSequence fieldIdentifier) + { + return FieldKey.fromFieldKey(FieldKey.fromName(fieldIdentifier) + "-fileUpload"); // Issue 53394 + } public static class FileAttachmentContainerFinder extends WebDriverComponentFinder { From 77aea551ae876f3ada90e5330cf717931ad714cb Mon Sep 17 00:00:00 2001 From: Trey Chadick Date: Tue, 8 Jul 2025 10:04:22 -0700 Subject: [PATCH 7/8] A couple more CSP enhancements (#2530) - Configure object-src for Knitr tests and remove exclusion from `CspLogUtil` - Add regression test for script nonce in report webpart (`AbstractKnitrReportTest`) - Remove redundant methods from `PortalHelper` - Move some methods from `WikiHelper` to `wiki.EditPage` --- data/reports/knitr_no_scriptpad.rhtml | 6 ++ data/reports/knitr_no_scriptpad.rmd | 6 ++ data/reports/nonce_check.rhtml | 15 ++++ .../reports/schemas/script_rhtml.rhtml | 6 ++ .../resources/reports/schemas/script_rmd.rmd | 6 ++ src/org/labkey/test/TestFileUtils.java | 6 +- .../test/pages/admin/ExternalSourcesPage.java | 1 + .../test/pages/reports/ScriptReportPage.java | 20 +++++ src/org/labkey/test/pages/wiki/EditPage.java | 38 +++++++++ .../test/tests/AbstractKnitrReportTest.java | 79 ++++++++++++++++++- src/org/labkey/test/tests/TabTest.java | 2 +- src/org/labkey/test/util/CspLogUtil.java | 4 +- src/org/labkey/test/util/PortalHelper.java | 18 +---- src/org/labkey/test/util/RReportHelper.java | 2 - src/org/labkey/test/util/WikiHelper.java | 28 +------ 15 files changed, 187 insertions(+), 50 deletions(-) create mode 100644 data/reports/nonce_check.rhtml diff --git a/data/reports/knitr_no_scriptpad.rhtml b/data/reports/knitr_no_scriptpad.rhtml index 1442cd2065..1b3d5c69a1 100644 --- a/data/reports/knitr_no_scriptpad.rhtml +++ b/data/reports/knitr_no_scriptpad.rhtml @@ -93,5 +93,11 @@ end.rcode-->

Well, everything seems to be working. Let's ask R what is the value of π? Of course it is .

+Nonce check: FAIL + + + \ No newline at end of file diff --git a/data/reports/knitr_no_scriptpad.rmd b/data/reports/knitr_no_scriptpad.rmd index 691a947b9c..78ba8eb048 100644 --- a/data/reports/knitr_no_scriptpad.rmd +++ b/data/reports/knitr_no_scriptpad.rmd @@ -113,6 +113,12 @@ library(knitr) knit('knitr-minimal.Rmd') ``` +Nonce check: FAIL + + + ## Conclusion Markdown is super easy to write. Go to **knitr** [homepage](http://yihui.name/knitr) for details. \ No newline at end of file diff --git a/data/reports/nonce_check.rhtml b/data/reports/nonce_check.rhtml new file mode 100644 index 0000000000..7efb90bd76 --- /dev/null +++ b/data/reports/nonce_check.rhtml @@ -0,0 +1,15 @@ + + + + Test script nonce in Knitr HTML + + + +Nonce check: FAIL + + + + + \ No newline at end of file diff --git a/modules/scriptpad/resources/reports/schemas/script_rhtml.rhtml b/modules/scriptpad/resources/reports/schemas/script_rhtml.rhtml index 77e8cfec5d..f9bc5fc814 100644 --- a/modules/scriptpad/resources/reports/schemas/script_rhtml.rhtml +++ b/modules/scriptpad/resources/reports/schemas/script_rhtml.rhtml @@ -87,5 +87,11 @@ end.rcode-->

Well, everything seems to be working. Let's ask R what is the value of π? Of course it is .

+Nonce check: FAIL + + + \ No newline at end of file diff --git a/modules/scriptpad/resources/reports/schemas/script_rmd.rmd b/modules/scriptpad/resources/reports/schemas/script_rmd.rmd index 5729f20b1c..f136b7616b 100644 --- a/modules/scriptpad/resources/reports/schemas/script_rmd.rmd +++ b/modules/scriptpad/resources/reports/schemas/script_rmd.rmd @@ -108,6 +108,12 @@ library(knitr) knit('knitr-minimal.Rmd') ``` +Nonce check: FAIL + + + ## Conclusion Markdown is super easy to write. Go to **knitr** [homepage](http://yihui.name/knitr) for details. \ No newline at end of file diff --git a/src/org/labkey/test/TestFileUtils.java b/src/org/labkey/test/TestFileUtils.java index 6a4a3ae4eb..b9a1228ceb 100644 --- a/src/org/labkey/test/TestFileUtils.java +++ b/src/org/labkey/test/TestFileUtils.java @@ -109,7 +109,7 @@ public static String getFileContents(Path path) { try { - return new String(Files.readAllBytes(path), StandardCharsets.UTF_8); + return Files.readString(path); } catch (IOException fail) { @@ -306,7 +306,7 @@ public static Set getSampleDataDirs() if (sampledataDirsFile.exists()) { String path = getFileContents(sampledataDirsFile); - _sampledataDirs.addAll(Arrays.stream(path.split(";")).map(File::new).collect(Collectors.toList())); + _sampledataDirs.addAll(Arrays.stream(path.split(";")).map(File::new).toList()); } else { @@ -317,7 +317,7 @@ public static Set getSampleDataDirs() // We know where the modules live; no reason to insist that sampledata.dirs exists. Files.walkFileTree(modulesDir, Collections.emptySet(), 2, new SimpleFileVisitor<>(){ @Override - public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException + public @NotNull FileVisitResult preVisitDirectory(@NotNull Path dir, @NotNull BasicFileAttributes attrs) { if (dir.equals(modulesDir)) { diff --git a/src/org/labkey/test/pages/admin/ExternalSourcesPage.java b/src/org/labkey/test/pages/admin/ExternalSourcesPage.java index 25d1da4db3..25d3c41075 100644 --- a/src/org/labkey/test/pages/admin/ExternalSourcesPage.java +++ b/src/org/labkey/test/pages/admin/ExternalSourcesPage.java @@ -207,6 +207,7 @@ public enum Directive implements OptionSelect.SelectOption Frame("frame-src"), Image("image-src"), Style("style-src"), + Object("object-src"), ; private final String directiveId; diff --git a/src/org/labkey/test/pages/reports/ScriptReportPage.java b/src/org/labkey/test/pages/reports/ScriptReportPage.java index 2d57bc293d..31b0db491e 100644 --- a/src/org/labkey/test/pages/reports/ScriptReportPage.java +++ b/src/org/labkey/test/pages/reports/ScriptReportPage.java @@ -11,12 +11,14 @@ import org.labkey.test.pages.LabKeyPage; import org.labkey.test.util.CodeMirrorHelper; import org.labkey.test.util.Ext4Helper; +import org.labkey.test.util.PipelineStatusTable; import org.labkey.test.util.TestLogger; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.ExpectedConditions; import java.util.Map; +import java.util.Objects; import java.util.Optional; import static org.labkey.test.components.ext4.Checkbox.Ext4Checkbox; @@ -79,6 +81,7 @@ public CodeMirrorHelper getEditor() public String saveReport(String name, boolean isSaveAs, int wait) { + String reportIdBeforeSave = getReportId(); WebElement saveButton = Ext4Helper.Locators.ext4Button(isSaveAs ? "Save As" : "Save").findElement(getDriver()); scrollIntoView(saveButton, true); clickAndWait(saveButton, wait); @@ -86,6 +89,11 @@ public String saveReport(String name, boolean isSaveAs, int wait) { saveReportWithName(name, isSaveAs); } + return Objects.requireNonNullElse(getReportId(), reportIdBeforeSave); + } + + public String getReportId() + { return getUrlParam("reportId", true); } @@ -141,6 +149,7 @@ public void clearOption(ReportOption option) private void _selectOption(ReportOption option, boolean checked) { + clickSourceTab(); ensureFieldSetExpanded(option.getSection()); Checkbox checkbox; if (option.isCheckbox()) @@ -202,6 +211,17 @@ public WebElement findReportElement() return Locator.byClass("reportView").findElement(getDriver()); } + public void startPipelineJobAndWait() + { + clickReportTab(); + + waitAndClick(Locator.lkButton("Start Job")); + waitAndClickAndWait(Locator.linkWithText("click here")); + new PipelineStatusTable(this) + .clickStatusLink(0) + .waitForComplete(); + } + @Override protected ElementCache newElementCache() { diff --git a/src/org/labkey/test/pages/wiki/EditPage.java b/src/org/labkey/test/pages/wiki/EditPage.java index 032f0c2734..9e4d76a535 100644 --- a/src/org/labkey/test/pages/wiki/EditPage.java +++ b/src/org/labkey/test/pages/wiki/EditPage.java @@ -100,10 +100,48 @@ public EditPage setTitle(String title) public EditPage setBody(String body) { + switchWikiToSourceView(); elementCache().bodyTextArea.set(body); return this; } + /** + * Switches the wiki edit page to source view when the format type is HTML. + */ + public void switchWikiToSourceView() + { + String curFormat = executeScript("return LABKEY._wiki.getProps().rendererType;", String.class); + if (curFormat.equalsIgnoreCase("HTML")) + { + if (isElementPresent(Locator.css("#wiki-tab-source.labkey-tab-inactive"))) + { + Locator tab = Locator.css("#wiki-tab-source > a"); + waitForElementToBeVisible(tab); + click(tab); + waitForElement(Locator.css("#wiki-tab-source.labkey-tab-active")); + } + } + } + + public void switchWikiToVisualView() + { + String curFormat = (String) executeScript("return LABKEY._wiki.getProps().rendererType;"); + if (curFormat.equalsIgnoreCase("HTML")) + { + if (isElementPresent(Locator.css("#wiki-tab-visual.labkey-tab-inactive"))) + { + Locator tab = Locator.css("#wiki-tab-visual > a"); + waitForElementToBeVisible(tab); + click(tab); + + Locator yesButton = Locator.tagWithText("span","Yes"); + waitForElementToBeVisible(yesButton); + waitAndClick(yesButton); + waitForElement(Locator.css("#wiki-tab-visual.labkey-tab-active")); + } + } + } + public EditPage setShouldIndex(boolean shouldIndex) { elementCache().shouldIndexCheckbox.set(shouldIndex); diff --git a/src/org/labkey/test/tests/AbstractKnitrReportTest.java b/src/org/labkey/test/tests/AbstractKnitrReportTest.java index d40ece66e7..562b775d94 100644 --- a/src/org/labkey/test/tests/AbstractKnitrReportTest.java +++ b/src/org/labkey/test/tests/AbstractKnitrReportTest.java @@ -17,6 +17,7 @@ import org.junit.Assume; import org.junit.BeforeClass; +import org.junit.Test; import org.labkey.remoteapi.CommandException; import org.labkey.test.BaseWebDriverTest; import org.labkey.test.Locator; @@ -25,12 +26,16 @@ import org.labkey.test.pages.admin.ExternalSourcesPage; import org.labkey.test.pages.core.admin.logger.ManagerPage; import org.labkey.test.pages.reports.ManageViewsPage; +import org.labkey.test.pages.reports.ScriptReportPage; +import org.labkey.test.pages.reports.ScriptReportPage.StandardReportOption; import org.labkey.test.util.CodeMirrorHelper; +import org.labkey.test.util.CspLogUtil; import org.labkey.test.util.Log4jUtils; import org.labkey.test.util.LogMethod; import org.labkey.test.util.LoggedParam; import org.labkey.test.util.PortalHelper; import org.labkey.test.util.RReportHelper; +import org.labkey.test.util.WikiHelper; import org.labkey.test.util.core.admin.CspConfigHelper; import org.openqa.selenium.WebElement; @@ -54,6 +59,10 @@ public abstract class AbstractKnitrReportTest extends BaseWebDriverTest protected static final Path rmdReport_no_scriptpad = TestFileUtils.getSampleData("reports/knitr_no_scriptpad.rmd").toPath(); private static final Path rhtmlReport = scriptpadReports.resolve("script_rhtml.rhtml"); private static final Path rhtmlReport_no_scriptpad = TestFileUtils.getSampleData("reports/knitr_no_scriptpad.rhtml").toPath(); + private static final Path rhtmlNonceCheck = TestFileUtils.getSampleData("reports/nonce_check.rhtml").toPath(); + private static final Locator.XPathLocator nonceCheckLoc = Locator.id("nonce-check-result"); + private static final Locator.XPathLocator nonceCheckSuccessLoc = nonceCheckLoc.withText("SUCCESS"); + protected final RReportHelper _rReportHelper = new RReportHelper(this); private static String readReport(final Path reportFile) @@ -81,6 +90,7 @@ protected void setupProject() try { new CspConfigHelper(this).setAllowedHosts(Map.of( + ExternalSourcesPage.Directive.Object, List.of("'self'"), // Issue 53226: reports-streamFile is blocked by object-src CSP directive ExternalSourcesPage.Directive.Style, List.of("https://cdn.datatables.net"), ExternalSourcesPage.Directive.Font, List.of("https://mathjax.rstudio.com"))); } @@ -166,7 +176,9 @@ protected void htmlFormat() Locator.tag("pre").containing("## \"1\",249318596,\"2008-05-17\",86,36,129,76,64"), Locator.tag("pre").withText("## knitr says hello to HTML!"), Locator.tag("pre").startsWith("## Error").containing(": non-numeric argument to binary operator"), - Locator.tag("p").startsWith("Well, everything seems to be working. Let's ask R what is the value of \u03C0? Of course it is 3.141")}; + Locator.tag("p").startsWith("Well, everything seems to be working. Let's ask R what is the value of \u03C0? Of course it is 3.141"), + nonceCheckSuccessLoc // Inline script should run + }; String[] reportNotContains = {"", // Uninterpreted html "