Skip to content

Commit

Permalink
Merge 25.1 to develop
Browse files Browse the repository at this point in the history
  • Loading branch information
labkey-teamcity committed Jan 29, 2025
2 parents 121ea6b + 418d6c9 commit 33730ce
Show file tree
Hide file tree
Showing 9 changed files with 400 additions and 106 deletions.
5 changes: 5 additions & 0 deletions src/org/labkey/test/BaseWebDriverTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,11 @@ public abstract class BaseWebDriverTest extends LabKeySiteWrapper implements Cle

public static final double DELTA = 10E-10;

// See QueryKey.ILLEGAL TODO make that array public so it can be used here
public static final String[] ILLEGAL_QUERY_KEY_CHARACTERS = {"$", "/", "&", "}", "~", ",", "."};
// See TSVWriter.shouldQuote. Generally we are not able to use the tab and new line characters when creating field names in the UI, but including here for completeness
public static final String[] TRICKY_IMPORT_FIELD_CHARACTERS = {"\\", "\"", "\\t", ",", "\\n", "\\r"};

public static final String TRICKY_CHARACTERS = "><&/%\\' \"1\u00E4\u00F6\u00FC\u00C5";
public static final String TRICKY_CHARACTERS_NO_QUOTES = "></% 1\u00E4\u00F6\u00FC\u00C5";
public static final String TRICKY_CHARACTERS_FOR_PROJECT_NAMES = "\u2603~!@$&()_+{}-=[],.#\u00E4\u00F6\u00FC\u00C5"; // No slash or space
Expand Down
50 changes: 50 additions & 0 deletions src/org/labkey/test/TestFileUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ public abstract class TestFileUtils
{
private static final Logger LOG = LogManager.getLogger(TestFileUtils.class);

private static final char _chQuote = '"';
// here we quote for both tab and comma, even though
private static final String _escapedCharsString = "\r\n\\" + _chQuote;

private static File _labkeyRoot = null;
private static File _buildDir = null;
private static File _testRoot = null;
Expand Down Expand Up @@ -689,4 +693,50 @@ public static File convertTabularToXlsx(File tabularFile, String delimiter, Stri

return excelFile;
}

// TODO should be able to use the methods in TSVWriter itself but currently has problems with NoClassDefFound
// TODO Consider using TestDataUtils.TsvQuoter instead
public static boolean shouldQuote(String value, String delimiter)
{
String escapeChars = _escapedCharsString + delimiter;

int len = value.length();
if (len == 0)
return false;
char firstCh = value.charAt(0);
char lastCh = value.charAt(len-1);
if (Character.isSpaceChar(firstCh) || Character.isSpaceChar(lastCh))
return true;
return StringUtils.containsAny(value,escapeChars);
}

public static String quoteValue(String value, String delimiter)
{
if (value == null)
return "";

String escaped = value;
if (shouldQuote(value, delimiter))
{
StringBuilder sb = new StringBuilder(value.length() + 10);
sb.append(_chQuote);
int i;
int lastMatch = 0;

while (-1 != (i = value.indexOf(_chQuote, lastMatch)))
{
sb.append(value, lastMatch, i);
sb.append(_chQuote).append(_chQuote);
lastMatch = i+1;
}

if (lastMatch < value.length())
sb.append(value.substring(lastMatch));

sb.append(_chQuote);
escaped = sb.toString();
}

return escaped;
}
}
18 changes: 9 additions & 9 deletions src/org/labkey/test/components/ui/grids/DetailTableEdit.java
Original file line number Diff line number Diff line change
Expand Up @@ -174,16 +174,16 @@ public DetailTableEdit setTextareaByFieldName(String fieldName, String value)
/**
* Get the value of a boolean field.
*
* @param fieldCaption The caption/label of the field to get.
* @param inputName The caption/label of the field to get.
* @return The value of the field.
**/
public boolean getBooleanField(String fieldCaption)
public boolean getBooleanField(String inputName)
{
// The text used in the field caption and the value of the name attribute in the checkbox don't always have the same case.
WebElement editableElement = Locator.tagWithAttributeIgnoreCase("input", "name", fieldCaption).findElement(getComponentElement());
WebElement editableElement = Locator.tagWithAttributeIgnoreCase("input", "name", inputName).findElement(getComponentElement());
String elementType = editableElement.getAttribute("type").toLowerCase().trim();

Assert.assertEquals(String.format("Field '%s' is not a checkbox. Cannot be get true/false value.", fieldCaption), "checkbox", elementType);
Assert.assertEquals(String.format("Field '%s' is not a checkbox. Cannot be get true/false value.", inputName), "checkbox", elementType);

return new Checkbox(editableElement).isChecked();
}
Expand All @@ -200,9 +200,9 @@ public DetailTableEdit setBooleanField(String fieldCaption, boolean value)

WebElement fieldValueElement = elementCache().fieldValue(fieldCaption);
Assert.assertTrue(String.format("Field '%s' is not editable and cannot be set.", fieldCaption), isEditableField(fieldValueElement));
getWrapper().scrollIntoView(fieldValueElement);

// The text used in the field caption and the value of the name attribute in the checkbox don't always have the same case.
WebElement editableElement = fieldValueElement.findElement(Locator.tagWithAttributeIgnoreCase("input", "name", fieldCaption));
WebElement editableElement = fieldValueElement.findElement(By.xpath("./div/div/input"));
String elementType = editableElement.getAttribute("type").toLowerCase().trim();

Assert.assertEquals(String.format("Field '%s' is not a checkbox. Cannot be set to true/false.", fieldCaption), "checkbox", elementType);
Expand Down Expand Up @@ -357,17 +357,17 @@ public DetailTableEdit clearSelectValue(String fieldCaption, boolean waitForSele

/**
* Set a DateTime, Date or Time field.
* @param fieldCaption The caption of the field to set.
* @param fieldKey The encoded fieldKey of the field to set.
* @param dateTime Will be used to determine what kind of field is being set and how to set it. If the parameter
* is a LocalDateTime object then it is assumed that field is a DateTime field. If the parameter is
* a LocalDate object then it is assumed to be a date-only field. And I think you can guess what
* happens with a LocalTime object type. If the type is a string it is used as a literal value that
* is typed into the field (no picker is used).
* @return A reference to this DetailTableEdit object.
*/
public DetailTableEdit setDateTimeField(String fieldCaption, Object dateTime)
public DetailTableEdit setDateTimeField(String fieldKey, Object dateTime)
{
ReactDateTimePicker dateTimePicker = getDateTimePicker(fieldCaption);
ReactDateTimePicker dateTimePicker = getDateTimePicker(fieldKey);
if(dateTime instanceof LocalDateTime localDateTime)
{
dateTimePicker.select(localDateTime);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ public enum XFrameOption
public enum KeyExpirationOptions implements OptionSelect.SelectOption
{
UNLIMITED(-1),
TEN_SECONDS(10),
ONE_WEEK(7*SECONDS_PER_DAY),
ONE_MONTH(30*SECONDS_PER_DAY),
THREE_MONTHS(90*SECONDS_PER_DAY),
Expand Down
12 changes: 12 additions & 0 deletions src/org/labkey/test/pages/user/UserDetailsPage.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import org.labkey.test.Locator;
import org.labkey.test.WebDriverWrapper;
import org.labkey.test.WebTestHelper;
import org.labkey.test.components.core.login.SetPasswordForm;
import org.labkey.test.pages.LabKeyPage;
import org.labkey.test.util.PasswordUtil;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

Expand Down Expand Up @@ -34,6 +36,15 @@ public ClonePermissionsPage clickClonePermission()
return new ClonePermissionsPage(getDriver());
}

public SetPasswordForm clickChangePassword()
{
if (PasswordUtil.getUsername().equals(getCurrentUser()))
throw new IllegalArgumentException("Don't change the primary site admin user's password");

clickAndWait(elementCache().changePwdButton);
return new SetPasswordForm(getDriver());
}

@Override
protected ElementCache newElementCache()
{
Expand All @@ -44,5 +55,6 @@ protected class ElementCache extends LabKeyPage<?>.ElementCache
{
WebElement editButton = Locator.lkButton("Edit").findWhenNeeded(this);
WebElement cloneButton = Locator.lkButton("Clone Permissions").findWhenNeeded(this);
WebElement changePwdButton = Locator.lkButton("Change Password").findWhenNeeded(this);
}
}
Loading

0 comments on commit 33730ce

Please sign in to comment.