Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ function doTest()

if (contextPath.length > 0) {
var baseUrl = LABKEY.ActionURL.getBaseURL();
if (!baseUrl.endsWith(contextPath + "/"))
var suffix = contextPath + "/";
var idx = baseUrl.indexOf(suffix);
if (idx === -1 || idx !== baseUrl.length - suffix.length)
errors[errors.length] = new Error("ActionURL.getBaseURL() = " + baseUrl);
}

Expand Down
13 changes: 8 additions & 5 deletions src/org/labkey/test/LabKeySiteWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -405,11 +405,14 @@ public void attemptSignIn(String email, String password)
setFormElement(Locator.id("email"), email);
setFormElement(Locator.id("password"), password);
WebElement signInButton = Locator.lkButton("Sign In").findElement(getDriver());
signInButton.click();
shortWait().until(ExpectedConditions.invisibilityOfElementLocated(Locator.byClass("signing-in-msg")));
shortWait().until(ExpectedConditions.or(
ExpectedConditions.stalenessOf(signInButton), // Successful login
ExpectedConditions.presenceOfElementLocated(Locators.labkeyError.withText()))); // Error during sign-in
doAndMaybeWaitForPageToLoad(10_000, () -> {
signInButton.click();
shortWait().until(ExpectedConditions.invisibilityOfElementLocated(Locator.byClass("signing-in-msg")));
shortWait().until(ExpectedConditions.or(
ExpectedConditions.stalenessOf(signInButton), // Successful login
ExpectedConditions.presenceOfElementLocated(Locators.labkeyError.withText()))); // Error during sign-in
return ExpectedConditions.stalenessOf(signInButton).apply(null);
});
}

public void signInShouldFail(String email, String password, String... expectedMessages)
Expand Down
1 change: 1 addition & 0 deletions src/org/labkey/test/Locators.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ private Locators() { }
public static final Locator.XPathLocator folderTab = Locator.tagWithClass("div", "lk-nav-tabs-ct").append(Locator.tagWithClass("ul", "lk-nav-tabs")).childTag("li");
public static final Locator.XPathLocator panelWebpartTitle = Locator.byClass("labkey-wp-title-text");
public static final Locator.XPathLocator folderTitle = Locator.tagWithClass("a", "lk-body-title-folder");
public static final Locator.XPathLocator loadingSpinner = Locator.byClass("fa-spinner");

public static Locator.XPathLocator headerContainer()
{
Expand Down
11 changes: 11 additions & 0 deletions src/org/labkey/test/TestScrubber.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.labkey.remoteapi.Connection;
import org.labkey.remoteapi.SimplePostCommand;
import org.labkey.test.components.html.Checkbox;
import org.labkey.test.components.pipeline.PipelineTriggerWizard;
import org.labkey.test.pages.core.admin.AllowedFileExtensionAdminPage;
import org.labkey.test.pages.core.admin.BaseSettingsPage;
import org.labkey.test.pages.core.admin.ConfigureFileSystemAccessPage;
Expand Down Expand Up @@ -160,6 +161,16 @@ public void cleanSiteSettings()
TestLogger.error("Failed to reset site look and feel properties after test.", e);
}

try
{
// Disable all pipeline triggers so that they don't show up as memory leaks in subsequent tests.
PipelineTriggerWizard.disableAllPipelineTriggers(createDefaultConnection());
}
catch (Exception e)
{
TestLogger.error("Failed to disable pipeline triggers after test", e);
}

}

@LogMethod(quiet = true)
Expand Down
9 changes: 6 additions & 3 deletions src/org/labkey/test/WebDriverWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -3000,14 +3000,17 @@ public void selectFolderTreeItem(String folderName)

/**
* Move mouse to the upper left corner of the document to dismiss tooltips and the like
* Will scroll page if necessary
*/
public void mouseOut()
{
try
{
scrollToTop();
new Actions(getDriver()).moveToLocation(0, 0).perform();
new Actions(getDriver())
.moveToLocation(0, 0)
// Add a little wiggle to make sure tooltips notice
.moveByOffset(4, 4)
.moveByOffset(-2, -2)
.perform();
}
catch (WebDriverException ignore) { }
}
Expand Down
2 changes: 1 addition & 1 deletion src/org/labkey/test/components/domain/DomainDesigner.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public class ElementCache extends BaseDomainDesigner<?>.ElementCache
protected final DomainPanel<?, ?> propertiesPanel = new DomainPanel.DomainPanelFinder(getDriver()).index(0)
.timeout(WAIT_FOR_JAVASCRIPT).findWhenNeeded(this);
protected final DomainFormPanel fieldsPanel = new DomainFormPanel.DomainFormPanelFinder(getDriver())
.index(getFieldPanelIndex()).timeout(1000).findWhenNeeded();
.index(getFieldPanelIndex()).timeout(2_000).findWhenNeeded();

protected int getFieldPanelIndex()
{
Expand Down
19 changes: 19 additions & 0 deletions src/org/labkey/test/components/pipeline/PipelineTriggerWizard.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
package org.labkey.test.components.pipeline;

import org.jetbrains.annotations.NotNull;
import org.labkey.remoteapi.CommandException;
import org.labkey.remoteapi.Connection;
import org.labkey.remoteapi.query.ContainerFilter;
import org.labkey.remoteapi.query.Filter;
import org.labkey.test.Locator;
import org.labkey.test.WebDriverWrapper;
import org.labkey.test.WebTestHelper;
Expand All @@ -24,11 +28,14 @@
import org.labkey.test.components.html.Checkbox;
import org.labkey.test.components.html.Input;
import org.labkey.test.components.html.OptionSelect;
import org.labkey.test.util.query.QueryApiHelper;
import org.openqa.selenium.Alert;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import static org.junit.Assert.assertTrue;
Expand Down Expand Up @@ -61,6 +68,18 @@ public static PipelineTriggerWizard beginAt(WebDriverWrapper driver, String cont
return new PipelineTriggerWizard(driver.getDriver());
}

public static void disableAllPipelineTriggers(Connection connection) throws IOException, CommandException
{
QueryApiHelper queryApiHelper = new QueryApiHelper(connection, "/", "pipeline", "TriggerConfigurations");
List<Map<String, Object>> triggers = queryApiHelper.selectRows(List.of("rowId", "enabled"),
List.of(new Filter("enabled", true)), List.of(), ContainerFilter.AllFolders).getRows();
if (!triggers.isEmpty())
{
triggers.forEach(trigger -> trigger.put("enabled", false));
queryApiHelper.updateRows(triggers);
}
}

@Override
public WebElement getComponentElement()
{
Expand Down
4 changes: 4 additions & 0 deletions src/org/labkey/test/components/ui/grids/EditableGrid.java
Original file line number Diff line number Diff line change
Expand Up @@ -1160,6 +1160,8 @@ public String getErrorPopoverText(int row, CharSequence columnIdentifier)
*/
public String getCellPopoverText(int row, CharSequence columnIdentifier)
{
dismissPopover(); // Other popovers can block the target cell
getWrapper().mouseOver(Locator.tag("td").findElement(getRow(row))); // Avoid passing over any header cells on the way to the target cell
WebElement cellDiv = Locator.tagWithClass("div", "cellular-display").findElement(getCell(row, columnIdentifier));
getWrapper().mouseOver(cellDiv); // cause the tooltip to be present
return Optional.ofNullable(WebDriverWrapper.waitFor(()-> Locators.popover.findElementOrNull(getDriver()), 1000))
Expand All @@ -1170,7 +1172,9 @@ public String getCellPopoverText(int row, CharSequence columnIdentifier)
public void dismissPopover()
{
Locators.popover.findOptionalElement(getDriver()).ifPresent(popover -> {
getWrapper().mouseOver(popover);
getWrapper().mouseOut();
getWrapper().mouseOver(elementCache().getGridHeaderManager().getColumnHeader(0).getElement());
getWrapper().shortWait().until(ExpectedConditions.invisibilityOf(popover));
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,7 @@ public FieldSelectionDialog removeAllSelectedFields()
continue;
}

getWrapper().mouseOver(removeIcon);
removeIcon.click();
}

Expand Down
35 changes: 20 additions & 15 deletions src/org/labkey/test/components/ui/grids/QueryGrid.java
Original file line number Diff line number Diff line change
Expand Up @@ -221,18 +221,18 @@ public QueryGrid waitForRecordCount(int expectedCount, int milliseconds)
@Override
public void doAndWaitForUpdate(Runnable func)
{
waitForLoaded();
Optional<WebElement> optionalStatus = elementCache().selectionStatusContainerLoc.findOptionalElement(elementCache());
super.doAndWaitForUpdate(() ->
{
WebElement status = hasSelectColumn() ? Locators.selectionStatusContainerLoc.waitForElement(this, 5_000) : null;

func.run();
func.run();

optionalStatus.ifPresent(el -> {
getWrapper().shortWait().until(ExpectedConditions.stalenessOf(el));
elementCache().selectionStatusContainerLoc.waitForElement(this, 5_000);
if (status != null)
{
getWrapper().shortWait().until(ExpectedConditions.stalenessOf(status));
Locators.selectionStatusContainerLoc.waitForElement(this, 5_000);
}
});

waitForLoaded();
clearElementCache();
}


Expand Down Expand Up @@ -789,19 +789,24 @@ protected ElementCache elementCache()
return (ElementCache) super.elementCache();
}

protected static class Locators
{
static final Locator.XPathLocator selectionStatusContainerLoc = Locator.byClass("selection-status");
}

protected class ElementCache extends ResponsiveGrid<QueryGrid>.ElementCache
{

final GridBar gridBar = new GridBar.GridBarFinder().findWhenNeeded(QueryGrid.this);

WebElement saveViewButton = Locator.button("Save").findWhenNeeded(getDriver());
final WebElement saveViewButton = Locator.button("Save").findWhenNeeded(getDriver());

final BootstrapMenu viewMenu = new MultiMenu.MultiMenuFinder(getDriver()).withText("Views").findWhenNeeded(this);

final Locator.XPathLocator selectionStatusContainerLoc = Locator.tagWithClass("div", "selection-status");
final Locator selectAllBtnLoc = selectionStatusContainerLoc.append(Locator.tagWithClass("span", "selection-status__select-all")
.child(Locator.buttonContainingText("Select")));
final Locator clearBtnLoc = selectionStatusContainerLoc.append(Locator.byClass("selection-status__clear-all")
.child(Locator.tag("button")));
final Locator selectAllBtnLoc = Locators.selectionStatusContainerLoc.append(Locator.byClass("selection-status__select-all")
.childTag("button"));
final Locator clearBtnLoc = Locators.selectionStatusContainerLoc.append(Locator.byClass("selection-status__clear-all")
.childTag("button"));

final WebElement filterStatusPanel = Locator.css("div.grid-panel__filter-status").findWhenNeeded(this);

Expand Down
8 changes: 5 additions & 3 deletions src/org/labkey/test/components/ui/grids/ResponsiveGrid.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ public Boolean isLoaded()
return getComponentElement().isDisplayed() &&
!Locators.loadingGrid.existsIn(this) &&
!Locators.spinner.existsIn(this) &&
(Locator.tag("td").existsIn(this) ||
getGridEmptyMessage().isPresent());
(Locator.tag("td").existsIn(this) ||
getGridEmptyMessage().isPresent());
}

protected void waitForLoaded()
Expand All @@ -82,6 +82,8 @@ protected void waitForLoaded()
@Override
public void doAndWaitForUpdate(Runnable func)
{
waitForLoaded();

// Look at WebDriverWrapper.doAndWaitForElementToRefresh for an example.
func.run();

Expand Down Expand Up @@ -838,7 +840,7 @@ protected boolean hasSelectColumn()
return hasSelectColumn;
}

ReactCheckBox selectAllCheckbox = new ReactCheckBox(Locator.xpath("//th/input[@type='checkbox']").findWhenNeeded(this))
final ReactCheckBox selectAllCheckbox = new ReactCheckBox(Locator.xpath("//th/input[@type='checkbox']").findWhenNeeded(this))
{
@Override
public void toggle()
Expand Down
28 changes: 20 additions & 8 deletions src/org/labkey/test/components/ui/lineage/LineageGraph.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.labkey.test.components.ui.lineage;

import org.labkey.test.Locator;
import org.labkey.test.Locators;
import org.labkey.test.WebDriverWrapper;
import org.labkey.test.components.Component;
import org.labkey.test.components.WebDriverComponent;
import org.labkey.test.components.react.Tabs;
Expand Down Expand Up @@ -48,6 +50,16 @@ public static LineageGraph showLineageGraph(WebDriver driver)
return lineageGraph;
}

@Override
protected void waitForReady()
{
WebDriverWrapper.waitFor(()->
elementCache().visGraphContainer.isDisplayed() &&
elementCache().nodeDetailContainer.isDisplayed() &&
!Locators.loadingSpinner.existsIn(this),
"lineage graph did not load in time", 5_000);
}

public Map<String, String> getCurrentNodeData()
{
return elementCache().detailTable().getTableDataByLabel();
Expand Down Expand Up @@ -178,16 +190,16 @@ final WebElement lineageItem(String name, WebElement tabPanel)
// container for the details of the currently-selected node
final WebElement nodeDetailContainer = Locator.tagWithClass("div", "lineage-node-detail-container")
.findWhenNeeded(this).withTimeout(4000);
WebElement componentDetailImage = Locator.tagWithClass("i", "component-detail--child--img")
final WebElement componentDetailImage = Locator.tagWithClass("i", "component-detail--child--img")
.child(Locator.tag("img")).findWhenNeeded(nodeDetailContainer);
WebElement nodeDetailName = Locator.tagWithClass("h4", "lineage-name-data")
final WebElement nodeDetailName = Locator.tagWithClass("h4", "lineage-name-data")
.findWhenNeeded(nodeDetailContainer);
WebElement nodeDetailLinksContainer = Locator.tagWithClass("div", "lineage-node-detail")
final WebElement nodeDetailLinksContainer = Locator.tagWithClass("div", "lineage-node-detail")
.findWhenNeeded(nodeDetailContainer);
WebElement nodeOverviewLink = Locator.linkWithSpan("Overview").withClass("lineage-data-link--text")
final WebElement nodeOverviewLink = Locator.linkWithSpan("Overview").withClass("lineage-data-link--text")
.findWhenNeeded(nodeDetailLinksContainer);
Locator lineageLinkLoc = Locator.linkWithSpan("Lineage").withClass("lineage-data-link--text");
WebElement nodeLineageLink = lineageLinkLoc.findWhenNeeded(nodeDetailLinksContainer);
final Locator lineageLinkLoc = Locator.linkWithSpan("Lineage").withClass("lineage-data-link--text");
final WebElement nodeLineageLink = lineageLinkLoc.findWhenNeeded(nodeDetailLinksContainer);
Tabs nodeDetailsTabs()
{
return new Tabs.TabsFinder(getDriver()).findWhenNeeded(nodeDetailContainer);
Expand All @@ -198,9 +210,9 @@ DetailTable detailTable()
return new DetailTable.DetailTableFinder(getDriver()).waitFor(nodeDetailContainer);
}

WebElement nodeDetails = Locator.tagWithClass("div", "lineage-node-detail")
final WebElement nodeDetails = Locator.tagWithClass("div", "lineage-node-detail")
.findWhenNeeded(nodeDetailContainer).withTimeout(3000);
WebElement nodeDetailsName = Locator.tagWithClass("div", "lineage-name-data")
final WebElement nodeDetailsName = Locator.tagWithClass("div", "lineage-name-data")
.findWhenNeeded(nodeDetails);

NodeDetailGroup summaryList(String nodeLabel)
Expand Down
7 changes: 3 additions & 4 deletions src/org/labkey/test/params/property/DomainProps.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,9 @@ public DomainResponse execute(Connection connection, String folderPath) throws I

DomainResponse response = super.execute(connection, folderPath);

TestLogger.log("Successfully created domain, '%s':\n%s"
.formatted(
response.getDomain().getName(),
response.getDomain().toJSONObject().toString(2)));
TestLogger.log().debug("Successfully created domain, '{}':\n{}",
() -> response.getDomain().getName(),
() -> response.getDomain().toJSONObject().toString(2));

return response;
}
Expand Down
4 changes: 2 additions & 2 deletions src/org/labkey/test/tests/ExpTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,12 @@ public void testSteps()
});
clickButton("Setup");
// Don't upload file. Uploading file creates 'exp.Data' entries that we don't want.
setPipelineRoot(TestFileUtils.getSampleData("xarfiles/expVerify").getAbsolutePath());
setPipelineRoot(TestFileUtils.getSampleData("xarfiles/expVerify").getParentFile().getAbsolutePath());
clickFolder(FOLDER_NAME);

clickButton("Process and Import Data");

_fileBrowserHelper.importFile("experiment.xar.xml", "Import Experiment");
_fileBrowserHelper.importFile("/expVerify/experiment.xar.xml", "Import Experiment");
Date importDate = new Date(); // Import timestamp will have various formats applied to it
clickAndWait(Locator.linkWithText("Data Pipeline"));
waitForPipelineJobsToComplete(1, false);
Expand Down
11 changes: 6 additions & 5 deletions src/org/labkey/test/util/DataRegion.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
import java.util.regex.Pattern;

Expand Down Expand Up @@ -190,7 +191,7 @@ protected String getTableId()
{
if (_tableId == null)
{
String id = _el.getAttribute("id");
String id = Objects.requireNonNull(_el.getAttribute("id"), "Table has no ID");
if (id.endsWith("-form"))
_tableId = id.replace("-form", "");
else
Expand Down Expand Up @@ -328,7 +329,7 @@ public static Locator.XPathLocator form(String regionName)
}
}

public class ElementCache extends Component.ElementCache
public class ElementCache extends Component<DataRegion.ElementCache>.ElementCache
{
protected ElementCache()
{
Expand Down Expand Up @@ -412,7 +413,7 @@ protected BootstrapMenu getHeaderMenu(String text)

private abstract class BaseDataRegionApi
{
final String regionJS = "LABKEY.DataRegions['" + getDataRegionName().replaceAll("'", "\\\\'") + "']";
final CachingSupplier<String> regionJS = new CachingSupplier<>(() -> "LABKEY.DataRegions['" + getDataRegionName().replaceAll("'", "\\\\'") + "']");

public void executeScript(String methodWithArgs, Object... args)
{
Expand All @@ -421,7 +422,7 @@ public void executeScript(String methodWithArgs, Object... args)

public <T> T executeScript(String methodWithArgs, Class<T> expectedResultType, Object... args)
{
return getWrapper().executeScript((expectedResultType != null ? "return " : "") + regionJS + "." + methodWithArgs, expectedResultType, args);
return getWrapper().executeScript((expectedResultType != null ? "return " : "") + regionJS.get() + "." + methodWithArgs, expectedResultType, args);
}

public void callMethod(String apiMethodName, Object... args)
Expand Down Expand Up @@ -459,7 +460,7 @@ public <T> T executeScript(String methodWithArgs, Class<T> expectedResultType, O
{
MutableObject<T> result = new MutableObject<>();
doAndWaitForUpdate(() -> result.setValue(super.executeScript(methodWithArgs, expectedResultType, args)));
return result.getValue();
return result.get();
}
}
}
Loading