Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[bot] Fast-forward for 24.11.0 #2138

Merged
merged 11 commits into from
Nov 13, 2024
36 changes: 19 additions & 17 deletions src/org/labkey/test/BaseWebDriverTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import org.labkey.remoteapi.query.ContainerFilter;
import org.labkey.remoteapi.query.Filter;
import org.labkey.remoteapi.query.SelectRowsResponse;
import org.labkey.remoteapi.security.CreateUserResponse;
import org.labkey.serverapi.reader.TabLoader;
import org.labkey.serverapi.writer.PrintWriters;
import org.labkey.test.components.CustomizeView;
Expand Down Expand Up @@ -94,7 +95,6 @@
import org.labkey.test.util.search.SearchAdminAPIHelper;
import org.labkey.test.util.selenium.WebDriverUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.ElementClickInterceptedException;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.TimeoutException;
Expand Down Expand Up @@ -309,20 +309,9 @@ public void setUp()
doTearDown();
}

SingletonWebDriver.getInstance().setUp(this);
SingletonWebDriver.getInstance().setUpWebDriver(this);

getDriver().manage().timeouts().scriptTimeout(Duration.ofMillis(WAIT_FOR_PAGE));
getDriver().manage().timeouts().pageLoadTimeout(Duration.ofMillis(defaultWaitForPage));
try
{
getDriver().manage().window().setSize(new Dimension(TestProperties.getBrowserWidth(), TestProperties.getBrowserHeight()));
}
catch (WebDriverException ex)
{
// Ignore occasional error from attempting to resize maximized window
if (!ex.getMessage().contains("current state is maximized"))
throw ex;
}
initWebDriverTimeouts();
closeExtraWindows();

if (!TestProperties.isCspCheckSkipped() && cspFailFast())
Expand All @@ -331,6 +320,15 @@ public void setUp()
}
}

@LogMethod
private void initWebDriverTimeouts()
{
TestLogger.debug("set script timeout");
getDriver().manage().timeouts().scriptTimeout(Duration.ofMillis(WAIT_FOR_PAGE));
TestLogger.debug("page load timeout set");
getDriver().manage().timeouts().pageLoadTimeout(Duration.ofMillis(defaultWaitForPage));
}

/**
* Specifies whether the CSP log should be checked before each page load.
* Tests that only want the CSP log to be checked at the end should override this method.
Expand Down Expand Up @@ -365,6 +363,7 @@ public BrowserType getBrowserType()
return BROWSER_TYPE;
}

@LogMethod
private static void doTearDown()
{
boolean closeWindow = !_testFailed || isRunWebDriverHeadless() || Boolean.parseBoolean(System.getProperty("close.on.fail", "true"));
Expand Down Expand Up @@ -1948,15 +1947,17 @@ public void setPipelineRootToDefault()
/**
* Create a user with the specified permissions for the specified project
*/
public void createUserWithPermissions(String userName, String projectName, String permissions)
public CreateUserResponse createUserWithPermissions(String userName, String projectName, String permissions)
{
if (projectName == null)
{
projectName = getProjectName();
}
_userHelper.createUser(userName, true);
CreateUserResponse ret = _userHelper.createUser(userName, true);
new ApiPermissionsHelper(this)
.addMemberToRole(userName, permissions, PermissionsHelper.MemberType.user, projectName);

return ret;
}

public ApiPermissionsHelper createSiteDeveloper(String userEmail)
Expand Down Expand Up @@ -2766,7 +2767,8 @@ private File getDownloadDir()
return _downloadDir;
}

private void setUp(BaseWebDriverTest test)
@LogMethod
private void setUpWebDriver(BaseWebDriverTest test)
{
WebDriver oldWebDriver = getWebDriver();
File newDownloadDir = new File(ArtifactCollector.ensureDumpDir(test.getClass().getSimpleName()), "downloads");
Expand Down
24 changes: 16 additions & 8 deletions src/org/labkey/test/LabKeySiteWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -412,19 +412,25 @@ public void signInShouldFail(String email, String password, String... expectedMe
assertTrue(String.format("Wrong errors.\nExpected: ['%s']\nActual: '%s'", String.join("',\n'", expectedMessages), errorText), missingErrors.isEmpty());
}

protected String setInitialPassword(String user)
@Deprecated // TODO: Call the variant that takes a userId instead
protected String setInitialPassword(String email)
{
return setInitialPassword(_userHelper.getUserId(email));
}

protected String setInitialPassword(int userId)
{
String password = PasswordUtil.getPassword();
SetPasswordForm.goToInitialPasswordForUser(this, user)
.setNewPassword(password)
.clickSubmit();
SetPasswordForm.goToInitialPasswordForUser(this, userId)
.setNewPassword(password)
.clickSubmit();

return password;
}

protected String getPasswordResetUrl(String username)
protected String getPasswordResetUrl(int userId)
{
beginAt(buildURL("security", "showResetEmail", Map.of("email", username)));
beginAt(buildURL("security", "showResetEmail", Map.of("userId", userId)));

WebElement resetLink = Locator.xpath("//a[contains(@href, 'setPassword.view')]").findElement(getDriver());
shortWait().until(ExpectedConditions.elementToBeClickable(resetLink));
Expand Down Expand Up @@ -608,8 +614,10 @@ private void checkForUpgrade()
refresh(); // Clear form

log("Testing bad email addresses");
verifyInitialUserError(null, null, null, "Invalid email address");
verifyInitialUserError("bogus@bogus@bogus", null, null, "Invalid email address: bogus@bogus@bogus");
verifyInitialUserError(null, null, null, "email: '' is not a valid email address. Please enter an email address in this form: [email protected]");
verifyInitialUserError("bogus@bogus@bogus", null, null, "email: 'bogus@bogus@bogus' is not a valid email address. Please enter an email address in this form: [email protected]");
// In the past, email address was getting double encoded
verifyInitialUserError("<>\"&%", null, null, "email: '<>\"&%' is not a valid email address. Please enter an email address in this form: [email protected]");

log("Testing bad passwords");
verifyInitialUserError(email, null, null, "You must enter a password.");
Expand Down
22 changes: 15 additions & 7 deletions src/org/labkey/test/TestProperties.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.apache.commons.lang3.StringUtils;
import org.labkey.serverapi.reader.Readers;
import org.labkey.test.util.TestLogger;
import org.openqa.selenium.Dimension;

import java.io.File;
import java.io.IOException;
Expand All @@ -30,6 +31,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.stream.Collectors;
import java.util.stream.Stream;
Expand Down Expand Up @@ -180,14 +182,20 @@ public static String getCloudPipelineBucketName()
return System.getProperty("cloud.pipeline.bucket");
}

public static int getBrowserWidth()
public static Optional<Dimension> getWindowSize()
{
return getIntegerProperty("webtest.browser.width", 1280);
}

public static int getBrowserHeight()
{
return getIntegerProperty("webtest.browser.height", 1024);
String dimensionStr = System.getProperty("webtest.window.size", "1280x1024");
if (!dimensionStr.isEmpty())
{
String[] dimensionParts = dimensionStr.split("x", 2);
int browserWidth = Integer.parseInt(dimensionParts[0]);
int browserHeight = Integer.parseInt(dimensionParts[1]);
return Optional.of(new Dimension(browserWidth, browserHeight));
}
else
{
return Optional.empty();
}
}

public static boolean isWebDriverLoggingEnabled()
Expand Down
9 changes: 9 additions & 0 deletions src/org/labkey/test/WebDriverWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,14 @@ protected Pair<WebDriver, DriverService> createNewWebDriver(@NotNull Pair<WebDri

if (newWebDriver != null)
{

Optional<Dimension> windowSize = TestProperties.getWindowSize();
if (windowSize.isPresent())
{
TestLogger.info("Set window size: " + windowSize.get());
newWebDriver.manage().window().setSize(windowSize.get());
}

Capabilities caps = ((HasCapabilities) newWebDriver).getCapabilities();
String browserName = caps.getBrowserName();
String browserVersion = caps.getBrowserVersion();
Expand Down Expand Up @@ -1008,6 +1016,7 @@ public void switchToWindow(int index)
}
}

@LogMethod
protected void closeExtraWindows()
{
List<String> windows = new ArrayList<>(getDriver().getWindowHandles());
Expand Down
46 changes: 44 additions & 2 deletions src/org/labkey/test/components/core/ApiKeyDialog.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@

import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.util.Arrays;

public class ApiKeyDialog extends ModalDialog
{
Expand Down Expand Up @@ -42,8 +44,48 @@ public ApiKeyDialog copyKey()

public String getClipboardContent() throws IOException, UnsupportedFlavorException
{
return (String) Toolkit.getDefaultToolkit().getSystemClipboard()
.getData(DataFlavor.stringFlavor);
DataFlavor[] flavors = Toolkit.getDefaultToolkit().getSystemClipboard().getAvailableDataFlavors();
Transferable t = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);

// Adding debug info for TeamCity run.
// Windows is not giving DataFlavor (MIME Type) for the data on the clipboard.
getWrapper().log("Available flavors: " + Arrays.stream(flavors).toList());
getWrapper().log("Best flavor: " + DataFlavor.selectBestTextFlavor(flavors));

if (t != null)
{

// Adding debug info for TeamCity run.
getWrapper().log("Is DataFlavor.imageFlavor supported? " + t.isDataFlavorSupported(DataFlavor.imageFlavor));
getWrapper().log("Is DataFlavor.allHtmlFlavor supported? " + t.isDataFlavorSupported(DataFlavor.allHtmlFlavor));
getWrapper().log("Is DataFlavor.fragmentHtmlFlavor supported? " + t.isDataFlavorSupported(DataFlavor.fragmentHtmlFlavor));
getWrapper().log("Is DataFlavor.selectionHtmlFlavor supported? " + t.isDataFlavorSupported(DataFlavor.selectionHtmlFlavor));
getWrapper().log("Is DataFlavor.javaFileListFlavor supported? " + t.isDataFlavorSupported(DataFlavor.javaFileListFlavor));
getWrapper().log("Is DataFlavor.stringFlavor supported? " + t.isDataFlavorSupported(DataFlavor.stringFlavor));

DataFlavor[] transferFlavors = t.getTransferDataFlavors();
getWrapper().log("Transferable supported data flavors: " + Arrays.stream(transferFlavors).toList());

if (flavors.length > 0)
{
getWrapper().log("Best Text Flavor: " + DataFlavor.selectBestTextFlavor(flavors));
return (String) Toolkit.getDefaultToolkit().getSystemClipboard()
.getData(DataFlavor.selectBestTextFlavor(flavors));
}
else
{
getWrapper().log("There are no DataFlavors to use.");
// Return a value to indicate something is on the clipboard but no DataFlavor was provided.
return "There are no DataFlavors to use.";
}

}
else
{
getWrapper().log("The clipboard is empty.");
return "";
}

}

public boolean isCopyButtonDisplayed()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ public SetPasswordForm(WebDriver driver)
}

// Don't use this unless you're actually testing authentication functionality
public static SetPasswordForm goToInitialPasswordForUser(WebDriverWrapper wrapper, String email)
public static SetPasswordForm goToInitialPasswordForUser(WebDriverWrapper wrapper, int userId)
{
wrapper.beginAt(WebTestHelper.buildURL("security", "showRegistrationEmail", Map.of("email", email)));
wrapper.beginAt(WebTestHelper.buildURL("security", "showRegistrationEmail", Map.of("userId", userId)));
// Get setPassword URL from notification email.
WebElement resetLink = Locator.linkWithHref("setPassword.view").findElement(wrapper.getDriver());

Expand Down
39 changes: 24 additions & 15 deletions src/org/labkey/test/components/domain/DomainFormPanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@
import org.labkey.test.components.ui.grids.ResponsiveGrid;
import org.labkey.test.params.FieldDefinition;
import org.labkey.test.selenium.WebElementWrapper;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
Expand Down Expand Up @@ -519,18 +520,22 @@ public WebElement getPanelErrorWebElement()
*/
public String getPanelAlertText()
{
WebElement alertEl = getPanelAlertWebElement();
if (alertEl != null)
return alertEl.getText();

return "";
return getPanelAlertText(0);
}

public String getPanelAlertText(int index)
{
return getPanelAlertWebElement(index).getText();
WebElement panelAlertWebElement = getPanelAlertWebElement(index);
if (panelAlertWebElement != null)
return panelAlertWebElement.getText();
else
return "";
}

public List<String> getPanelAlertTexts()
{
return getWrapper().getTexts(getPanelAlertElements());
}
/**
* There may be an element in the alert that a test will need to interact with so return the alert element and let
* the test find the control it needs.
Expand All @@ -542,20 +547,24 @@ public WebElement getPanelAlertWebElement()
}

public WebElement getPanelAlertWebElement(int index)
{
List<WebElement> panelAlertElements = getPanelAlertElements();
if (panelAlertElements.size() > index)
return panelAlertElements.get(index);
else
return null;
}

public List<WebElement> getPanelAlertElements()
{
try
{
getWrapper().waitFor(() -> BootstrapLocators.infoBanner.existsIn(getDriver()),
"the info alert did not appear as expected", 1000);
return BootstrapLocators.infoBanner.waitForElements(this, 1000);
}
catch (TimeoutException e)
catch (NoSuchElementException nothing)
{
return null;
return Collections.emptyList();
}

// It would be better to not return a raw WebElement but who knows what the future holds, different alerts
// may show different controls.
return BootstrapLocators.infoBanner.index(index).findElement(this);
}

@Override
Expand Down
16 changes: 6 additions & 10 deletions src/org/labkey/test/components/ui/entities/EntityInsertPanel.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.labkey.test.components.ui.entities;

import org.junit.Assert;
import org.labkey.test.Locator;
import org.labkey.test.WebDriverWrapper;
import org.labkey.test.components.Component;
Expand Down Expand Up @@ -140,18 +141,14 @@ public EntityInsertPanel addRecords(List<Map<String, Object>> records)
showGrid();
elementCache().grid.addRows(records.size());

List<Integer> rowIndices = elementCache().grid.getEditableRowIndices();

if(rowIndices.size() < records.size())
{
throw new IllegalStateException("Trying to add more records than there are rows. Number of records to create: " + records.size() + " number of available rows: " + rowIndices.size());
}
Assert.assertFalse(String.format("Trying to add more records than there are rows. Number of records to create: %d number of available rows: %d",
records.size(), elementCache().grid.getRowCount()),
elementCache().grid.getRowCount() < records.size());

int index = 0;

for(Map<String, Object> record : records)
{
setRecordValues(record, rowIndices.get(index));
setRecordValues(record, index);
index++;
}

Expand All @@ -160,8 +157,7 @@ public EntityInsertPanel addRecords(List<Map<String, Object>> records)

public EntityInsertPanel setRecordValues(Map<String, Object> columnValues)
{
int insertRowIndex = getEditableGrid().getEditableRowIndices().get(0);
return setRecordValues(columnValues, insertRowIndex);
return setRecordValues(columnValues, 0);
}

public EntityInsertPanel setRecordValues(Map<String, Object> columnValues, int row)
Expand Down
Loading
Loading