diff --git a/src/org/labkey/test/components/domain/DomainFieldRow.java b/src/org/labkey/test/components/domain/DomainFieldRow.java
index 10f80dbe33..2dedc18a65 100644
--- a/src/org/labkey/test/components/domain/DomainFieldRow.java
+++ b/src/org/labkey/test/components/domain/DomainFieldRow.java
@@ -15,10 +15,11 @@
import org.labkey.test.components.html.SelectWrapper;
import org.labkey.test.components.react.FilteringReactSelect;
import org.labkey.test.components.ui.ontology.ConceptPickerDialog;
+import org.labkey.test.pages.core.admin.BaseSettingsPage.DATE_FORMAT;
+import org.labkey.test.pages.core.admin.BaseSettingsPage.TIME_FORMAT;
import org.labkey.test.params.FieldDefinition;
import org.labkey.test.util.LabKeyExpectedConditions;
import org.openqa.selenium.ElementNotInteractableException;
-import org.openqa.selenium.Keys;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.SearchContext;
import org.openqa.selenium.WebDriver;
@@ -146,12 +147,8 @@ public DomainFieldRow setType(FieldDefinition.ColumnType columnType, boolean con
public ModalDialog setTypeWithDialog(FieldDefinition.ColumnType columnType)
{
elementCache().fieldTypeSelectInput.selectByVisibleText(columnType.getLabel());
-
- ModalDialog confirmDialog = new ModalDialog.ModalDialogFinder(getDriver())
+ return new ModalDialog.ModalDialogFinder(getDriver())
.withTitle("Confirm Data Type Change").timeout(1000).waitFor();
-
- return confirmDialog;
-
}
public boolean getRequiredField()
@@ -412,29 +409,19 @@ public DomainFieldRow setFormat(String formatString, @Nullable String dataType)
{
expand();
- if (!StringUtils.isEmpty(dataType))
+
+ if (FieldDefinition.ColumnType.DateAndTime.getRangeURI().equals(dataType) ||
+ FieldDefinition.ColumnType.Date.getRangeURI().equals(dataType) ||
+ (FieldDefinition.ColumnType.Time.getRangeURI().equals(dataType)))
{
- if (FieldDefinition.ColumnType.DateAndTime.getRangeURI().equals(dataType))
- {
- setDateTimeFormat(formatString);
- return this;
- }
- if (FieldDefinition.ColumnType.Date.getRangeURI().equals(dataType))
- {
- setDateFormat(formatString);
- return this;
- }
- if (FieldDefinition.ColumnType.Time.getRangeURI().equals(dataType))
- {
- setTimeFormat(formatString);
- return this;
- }
+ throw new UnsupportedOperationException("Setting the format for Date, Time or DateTime fields not supported in this method.");
}
- if(elementCache().formatInput.getComponentElement().isDisplayed())
+
+ if (elementCache().formatInput.getComponentElement().isDisplayed())
{
elementCache().formatInput.setValue(formatString);
}
- else if(elementCache().charScaleInput.getComponentElement().isDisplayed())
+ else if (elementCache().charScaleInput.getComponentElement().isDisplayed())
{
// Formatting of Boolean types use the scale input.
elementCache().charScaleInput.setValue(formatString);
@@ -1303,67 +1290,93 @@ public boolean isDateTimeInherited()
return elementCache().dateTimeInheritedCheckbox.get();
}
- public String getDateTimeFormatDate()
+ public DomainFieldRow setDateTimeFormat(DATE_FORMAT date, TIME_FORMAT time)
{
- return getFormatWithoutExample(elementCache().dateTimeFormatDateSelect.getValue());
+ setDateTimeFormat(date);
+ setDateTimeFormat(time);
+ return this;
}
- public DomainFieldRow setDateTimeFormatDate(String dateFormat)
+ public DomainFieldRow setDateTimeFormat(DATE_FORMAT dateFormat)
{
expand();
if (isDateTimeInherited())
setDateTimeInherited(false);
- elementCache().dateTimeFormatDateSelect.typeAheadSelect(dateFormat + " (");
+
+ String txt;
+
+ if (dateFormat.equals(DATE_FORMAT.DATETIME))
+ {
+ txt = dateFormat.toString();
+ }
+ else
+ {
+ txt = dateFormat + " (";
+ }
+
+ elementCache().dateTimeFormatDateSelect.typeAheadSelect(txt);
return this;
}
- public DomainFieldRow setDateTimeFormatTime(String timeFormat)
+ public DomainFieldRow setDateTimeFormat(TIME_FORMAT timeFormat)
{
expand();
if (isDateTimeInherited())
setDateTimeInherited(false);
- elementCache().dateTimeFormatTimeSelect.typeAheadSelect(timeFormat + " (");
+ elementCache().dateTimeFormatTimeSelect.typeAheadSelect(TIME_FORMAT.none.equals(timeFormat) ? timeFormat.toString() : timeFormat + " (");
return this;
}
- public String getDateTimeFormatTime()
+ public String getDateTimeFormatDate()
{
- return getFormatWithoutExample(elementCache().dateTimeFormatTimeSelect.getValue());
+ String formatValue;
+
+ if(elementCache().dateTimeFormatDateSelect.isInteractive())
+ {
+ formatValue = getFormatWithoutExample(elementCache().dateTimeFormatDateSelect.getValue());
+ }
+ else
+ {
+ formatValue = getFormatWithoutExample(elementCache().disabledDateTimeDateFormat.getText());
+ }
+
+ return formatValue;
}
- public String getDateTimeFormat()
+ public boolean isDateTimeFormatDateEnabled()
{
- String date = getDateTimeFormatDate();
- String time = getDateTimeFormatTime();
- if ("".equals(time))
- time = null;
- if (StringUtils.isEmpty(time))
- return date;
-
- return date + " " + time;
+ return elementCache().dateTimeFormatDateSelect.isInteractive();
}
- public DomainFieldRow setDateTimeFormat(String dateTime)
+ public String getDateTimeFormatTime()
{
- expand();
- if (isDateTimeInherited())
- setDateTimeInherited(false);
+ String formatValue;
+
+ if(elementCache().dateTimeFormatTimeSelect.isInteractive())
+ {
+ formatValue = getFormatWithoutExample(elementCache().dateTimeFormatTimeSelect.getValue());
+ }
+ else
+ {
+ formatValue = getFormatWithoutExample(elementCache().disabledDateTimeTimeFormat.getText());
+ }
- String[] parts = dateTime.split("\\s+", 2);
- if (parts.length == 2)
- return setDateTimeFormat(parts[0], parts[1]);
- return setDateTimeFormat(parts[0], "");
+ return formatValue;
}
- public DomainFieldRow setDateTimeFormat(String date, String time)
+ public boolean isDateTimeFormatTimeEnabled()
{
- expand();
- if (isDateTimeInherited())
- setDateTimeInherited(false);
+ return elementCache().dateTimeFormatTimeSelect.isInteractive();
+ }
- elementCache().dateTimeFormatDateSelect.typeAheadSelect(date + " (");
- elementCache().dateTimeFormatTimeSelect.typeAheadSelect("".equals(time) ? time : time + " (");
- return this;
+ public String getDateTimeFormat()
+ {
+ String date = getDateTimeFormatDate();
+ String time = getDateTimeFormatTime();
+ if (TIME_FORMAT.none.toString().equals(time) || StringUtils.isEmpty(time))
+ return date;
+
+ return date + " " + time;
}
public DomainFieldRow setDateInherited(boolean check)
@@ -1380,15 +1393,42 @@ public boolean isDateInherited()
public String getDateFormat()
{
- return getFormatWithoutExample(elementCache().dateFormatSelect.getValue());
+ String formatValue;
+
+ if(elementCache().dateFormatSelect.isInteractive())
+ {
+ formatValue = getFormatWithoutExample(elementCache().dateFormatSelect.getValue());
+ }
+ else
+ {
+ formatValue = getFormatWithoutExample(elementCache().disabledDateFormat.getText());
+ }
+
+ return formatValue;
+ }
+
+ public boolean isDateFormatEnabled()
+ {
+ return elementCache().dateFormatSelect.isInteractive();
}
- public DomainFieldRow setDateFormat(String dateFormat)
+ public DomainFieldRow setDateFormat(DATE_FORMAT dateFormat)
{
expand();
if (isDateInherited())
setDateInherited(false);
- elementCache().dateFormatSelect.typeAheadSelect(dateFormat + " (");
+
+ String txt;
+ if (dateFormat.equals(DATE_FORMAT.DATE))
+ {
+ txt = dateFormat.toString();
+ }
+ else
+ {
+ txt = dateFormat + " (";
+ }
+ elementCache().dateFormatSelect.typeAheadSelect(txt);
+
return this;
}
@@ -1406,18 +1446,56 @@ public boolean isTimeInherited()
public String getTimeFormat()
{
- return getFormatWithoutExample(elementCache().timeFormatSelect.getValue());
+ String formatValue;
+
+ if(elementCache().timeFormatSelect.isInteractive())
+ {
+ formatValue = getFormatWithoutExample(elementCache().timeFormatSelect.getValue());
+ }
+ else
+ {
+ formatValue = getFormatWithoutExample(elementCache().disabledTimeFormat.getText());
+ }
+
+ return formatValue;
}
- public DomainFieldRow setTimeFormat(String timeFormat)
+ public boolean isTimeFormatEnabled()
+ {
+ return elementCache().timeFormatSelect.isInteractive();
+ }
+
+ public DomainFieldRow setTimeFormat(TIME_FORMAT timeFormat)
{
expand();
if (isTimeInherited())
setTimeInherited(false);
- elementCache().timeFormatSelect.typeAheadSelect(timeFormat + " (");
+
+ String txt;
+
+ if (timeFormat.equals(TIME_FORMAT.TIME))
+ {
+ txt = timeFormat.toString();
+ }
+ else
+ {
+ txt = timeFormat + " (";
+ }
+
+ elementCache().timeFormatSelect.typeAheadSelect(txt);
return this;
}
+ public boolean hasDomainWarningIcon()
+ {
+ return elementCache().domainWarningIcon.isDisplayed();
+ }
+
+ public WebElement getDomainWarningIcon()
+ {
+ return elementCache().domainWarningIcon;
+ }
+
public static class DomainFieldRowFinder extends WebDriverComponentFinder
{
private final Locator.XPathLocator _baseLocator = Locator.tagWithClassContaining("div", "domain-field-row").withoutClass("domain-floating-hdr");
@@ -1523,15 +1601,25 @@ protected class ElementCache extends WebDriverComponent.ElementCache
public final FilteringReactSelect dateTimeFormatDateSelect = FilteringReactSelect.finder(getDriver())
.withNamedInput("domainpropertiesrow-format_datedateTime")
.refindWhenNeeded(this);
+ public final WebElement disabledDateTimeDateFormat = Locator.tagWithAttributeContaining("div", "id", "domainpropertiesrow-format_datedateTime")
+ .descendant("div[contains(@class,'select-input__single-value--is-disabled')]").findWhenNeeded(this);
public final FilteringReactSelect dateTimeFormatTimeSelect = FilteringReactSelect.finder(getDriver())
.withNamedInput("domainpropertiesrow-format_timedateTime")
.refindWhenNeeded(this);
+ public final WebElement disabledDateTimeTimeFormat = Locator.tagWithAttributeContaining("div", "id", "domainpropertiesrow-format_timedateTime")
+ .descendant("div[contains(@class,'select-input__single-value--is-disabled')]").findWhenNeeded(this);
public final FilteringReactSelect dateFormatSelect = FilteringReactSelect.finder(getDriver())
.withNamedInput("domainpropertiesrow-format_datedate")
.refindWhenNeeded(this);
+ public final WebElement disabledDateFormat = Locator.tagWithAttributeContaining("div", "id", "domainpropertiesrow-format_datedate")
+ .descendant("div[contains(@class,'select-input__single-value--is-disabled')]").findWhenNeeded(this);
public final FilteringReactSelect timeFormatSelect = FilteringReactSelect.finder(getDriver())
.withNamedInput("domainpropertiesrow-format_timetime")
.refindWhenNeeded(this);
+ public final WebElement disabledTimeFormat = Locator.tagWithAttributeContaining("div", "id", "domainpropertiesrow-format_timetime")
+ .descendant("div[contains(@class,'select-input__single-value--is-disabled')]").findWhenNeeded(this);
+ public final WebElement domainWarningIcon = Locator.tagWithClass("span", "domain-warning-icon")
+ .findWhenNeeded(this);
// lookup field options
public final Select lookupContainerSelect = SelectWrapper.Select(Locator.name("domainpropertiesrow-lookupContainer"))
diff --git a/src/org/labkey/test/components/domain/DomainFormPanel.java b/src/org/labkey/test/components/domain/DomainFormPanel.java
index 49abcf1991..5510089b57 100644
--- a/src/org/labkey/test/components/domain/DomainFormPanel.java
+++ b/src/org/labkey/test/components/domain/DomainFormPanel.java
@@ -8,6 +8,8 @@
import org.labkey.test.components.html.Checkbox;
import org.labkey.test.components.react.ToggleButton;
import org.labkey.test.components.ui.grids.ResponsiveGrid;
+import org.labkey.test.pages.core.admin.BaseSettingsPage.DATE_FORMAT;
+import org.labkey.test.pages.core.admin.BaseSettingsPage.TIME_FORMAT;
import org.labkey.test.params.FieldDefinition;
import org.labkey.test.selenium.WebElementWrapper;
import org.openqa.selenium.NoSuchElementException;
@@ -125,7 +127,39 @@ private DomainFormPanel editField(DomainFieldRow fieldRow, FieldDefinition field
if (fieldDefinition.getLabel() != null)
fieldRow.setLabel(fieldDefinition.getLabel());
if (fieldDefinition.getFormat() != null)
- fieldRow.setFormat(fieldDefinition.getFormat(), fieldDefinition.getRangeURI());
+ {
+ if (fieldDefinition.getType().equals(FieldDefinition.ColumnType.Date))
+ {
+ fieldRow.setDateFormat(DATE_FORMAT.get(fieldDefinition.getFormat()));
+ }
+ else if (fieldDefinition.getType().equals(FieldDefinition.ColumnType.Time))
+ {
+ fieldRow.setTimeFormat(TIME_FORMAT.get(fieldDefinition.getFormat()));
+ }
+ else if (fieldDefinition.getType().equals(FieldDefinition.ColumnType.DateAndTime))
+ {
+
+ // Identify the part of the format that is the date and the part that is the time. Take into account
+ // a data format may include spaces (time does not).
+ String format = fieldDefinition.getFormat().trim();
+ int index = format.lastIndexOf(" ");
+
+ if (format.substring(index + 1).contains(":"))
+ {
+ fieldRow.setDateTimeFormat(
+ DATE_FORMAT.get(format.substring(0, index)),
+ TIME_FORMAT.get(format.substring(index + 1)));
+ }
+ else
+ {
+ fieldRow.setDateTimeFormat(DATE_FORMAT.get(format));
+ }
+ }
+ else
+ {
+ fieldRow.setFormat(fieldDefinition.getFormat(), fieldDefinition.getRangeURI());
+ }
+ }
if (fieldDefinition.getScale() != null)
fieldRow.setCharCount(fieldDefinition.getScale());
if (fieldDefinition.getURL() != null)
diff --git a/src/org/labkey/test/pages/admin/FolderFormatsPage.java b/src/org/labkey/test/pages/admin/FolderFormatsPage.java
new file mode 100644
index 0000000000..b312606638
--- /dev/null
+++ b/src/org/labkey/test/pages/admin/FolderFormatsPage.java
@@ -0,0 +1,299 @@
+package org.labkey.test.pages.admin;
+
+import org.labkey.test.Locator;
+import org.labkey.test.WebDriverWrapper;
+import org.labkey.test.WebTestHelper;
+import org.labkey.test.pages.core.admin.BaseSettingsPage;
+import org.labkey.test.pages.core.admin.BaseSettingsPage.DATE_FORMAT;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+
+public class FolderFormatsPage extends FolderManagementPage
+{
+
+ public FolderFormatsPage(WebDriver driver)
+ {
+ super(driver);
+ }
+
+ public static FolderFormatsPage beginAt(WebDriverWrapper wrapper)
+ {
+ return beginAt(wrapper, wrapper.getCurrentContainerPath());
+ }
+
+ public static FolderFormatsPage beginAt(WebDriverWrapper wrapper, String containerPath)
+ {
+ wrapper.beginAt(WebTestHelper.buildURL("admin", containerPath, "folderSettings"));
+ return new FolderFormatsPage(wrapper.getDriver());
+ }
+
+ private Boolean getInherited(String name)
+ {
+ return elementCache().inheritedChk(name).isSelected();
+ }
+
+ private void setInherited(String name, boolean enable)
+ {
+ if (enable)
+ checkCheckbox(elementCache().inheritedChk(name));
+ else
+ uncheckCheckbox(elementCache().inheritedChk(name));
+ }
+
+ public boolean getDefaultDateDisplayInherited()
+ {
+ return getInherited("defaultDateFormatInherited");
+ }
+
+ public void setDefaultDateDisplayInherited(boolean enable)
+ {
+ setInherited("defaultDateFormatInherited", enable);
+ }
+
+ public String getDefaultDateDisplay()
+ {
+ return getSelectedOptionValue(elementCache().defaultDateFormat);
+ }
+
+ public void setDefaultDateDisplay(DATE_FORMAT dateFormat)
+ {
+ selectOptionByValue(elementCache().defaultDateFormat, dateFormat.toString());
+ }
+
+ public boolean defaultDateDisplayWarning()
+ {
+ return elementCache().nonStandardWarning(elementCache().defaultDateFormat).isDisplayed();
+ }
+
+ public void setDefaultDateTimeDisplay(BaseSettingsPage.DATE_FORMAT dateFormat, BaseSettingsPage.TIME_FORMAT timeFormat)
+ {
+ setDefaultDateTimeDateDisplay(dateFormat);
+ setDefaultDateTimeTimeDisplay(timeFormat);
+ }
+
+ public String getDefaultDateTimeDateDisplay()
+ {
+ return getSelectedOptionValue(elementCache().defaultDateTimeDateFormat);
+ }
+
+ public void setDefaultDateTimeDateDisplay(BaseSettingsPage.DATE_FORMAT dateFormat)
+ {
+ selectOptionByValue(elementCache().defaultDateTimeDateFormat, dateFormat.toString());
+ }
+
+ public boolean defaultDateTimeDateDisplayWarning()
+ {
+ return elementCache().nonStandardWarning(elementCache().defaultDateTimeDateFormat).isDisplayed();
+ }
+
+ public boolean getDefaultTimeDisplayInherited()
+ {
+ return getInherited("defaultTimeFormatInherited");
+ }
+
+ public void setDefaultTimeDisplayInherited(boolean enable)
+ {
+ setInherited("defaultTimeFormatInherited", enable);
+ }
+
+ public String getDefaultDateTimeTimeDisplay()
+ {
+ return getSelectedOptionValue(elementCache().defaultDateTimeTimeFormat);
+ }
+
+ public void setDefaultDateTimeTimeDisplay(BaseSettingsPage.TIME_FORMAT timeFormat)
+ {
+ selectOptionByValue(elementCache().defaultDateTimeTimeFormat, timeFormat.toString());
+ }
+
+ public boolean defaultDateTimeTimeDisplayWarning()
+ {
+ return elementCache().nonStandardWarning(elementCache().defaultDateTimeTimeFormat).isDisplayed();
+ }
+
+ public boolean getDefaultDateTimeDisplayInherited()
+ {
+ return getInherited("defaultDateTimeFormatInherited");
+ }
+
+ public void setDefaultDateTimeDisplayInherited(boolean enable)
+ {
+ setInherited("defaultDateTimeFormatInherited", enable);
+ }
+
+ public String getDefaultTimeDisplay()
+ {
+ return getSelectedOptionValue(elementCache().defaultTimeFormat);
+ }
+
+ public void setDefaultTimeDisplay(BaseSettingsPage.TIME_FORMAT timeFormat)
+ {
+ selectOptionByValue(elementCache().defaultTimeFormat, timeFormat.toString());
+ }
+
+ public boolean defaultTimeDisplayWarning()
+ {
+ return elementCache().nonStandardWarning(elementCache().defaultTimeFormat).isDisplayed();
+ }
+
+ public boolean getDefaultNumberDisplayInherited()
+ {
+ return getInherited("defaultNumberFormatInherited");
+ }
+
+ public void setDefaultNumberDisplayInherited(boolean enable)
+ {
+ setInherited("defaultNumberFormatInherited", enable);
+ }
+
+ public String getDefaultNumberDisplay()
+ {
+ return getFormElement(elementCache().defaultNumberFormat);
+ }
+
+ public void setDefaultNumberDisplay(String numberFormat)
+ {
+ setFormElement(elementCache().defaultNumberFormat, numberFormat);
+ }
+
+ public boolean getAdditionalParsingPatternDatesInherited()
+ {
+ return getInherited("extraDateParsingPatternInherited");
+ }
+
+ public void setAdditionalParsingPatternDatesInherited(boolean enable)
+ {
+ setInherited("extraDateParsingPatternInherited", enable);
+ }
+
+ public String getAdditionalParsingPatternDates()
+ {
+ return getFormElement(elementCache().additionalParsingPatternDates);
+ }
+
+ public void setAdditionalParsingPatternDates(String pattern)
+ {
+ setFormElement(elementCache().additionalParsingPatternDates, pattern);
+ }
+
+ public boolean getAdditionalParsingPatternDateAndTimeInherited()
+ {
+ return getInherited("extraDateTimeParsingPatternInherited");
+ }
+
+ public void setAdditionalParsingPatternDateAndTimeInherited(boolean enable)
+ {
+ setInherited("extraDateTimeParsingPatternInherited", enable);
+ }
+
+ public String getAdditionalParsingPatternDateAndTime()
+ {
+ return getFormElement(elementCache().additionalParsingPatternDateAndTime);
+ }
+
+ public void setAdditionalParsingPatternDateAndTime(String pattern)
+ {
+ setFormElement(elementCache().additionalParsingPatternDateAndTime, pattern);
+ }
+
+ public boolean getAdditionalParsingPatternTimesInherited()
+ {
+ return getInherited("extraTimeParsingPatternInherited");
+ }
+
+ public void setAdditionalParsingPatternTimesInherited(boolean enable)
+ {
+ setInherited("extraTimeParsingPatternInherited", enable);
+ }
+
+ public String getAdditionalParsingPatternTimes()
+ {
+ return getFormElement(elementCache().additionalParsingPatternTimes);
+ }
+
+ public void setAdditionalParsingPatternTimes(String pattern)
+ {
+ setFormElement(elementCache().additionalParsingPatternTimes, pattern);
+ }
+
+ public boolean getRestrictChartingColsInherited()
+ {
+ return getInherited("restrictedColumnsEnabledInherited");
+ }
+
+ public void setRestrictChartingColsInherited(boolean enable)
+ {
+ setInherited("restrictedColumnsEnabledInherited", enable);
+ }
+
+ public void setRestrictChartingCols(boolean restrict)
+ {
+ if (restrict)
+ checkCheckbox(elementCache().restrictChartingColsChk);
+ else
+ uncheckCheckbox(elementCache().restrictChartingColsChk);
+ }
+
+ public boolean getRestrictChartingCols()
+ {
+ return elementCache().restrictChartingColsChk.isSelected();
+ }
+
+ public FolderFormatsPage clickSave()
+ {
+ clickAndWait(elementCache().saveButton);
+ clearCache();
+ return this;
+ }
+
+ public FolderFormatsPage clickInheritAll()
+ {
+ clickAndWait(elementCache().inheritAll);
+ clearCache();
+ return this;
+ }
+
+ @Override
+ protected ElementCache newElementCache()
+ {
+ return new ElementCache();
+ }
+
+ @Override
+ protected ElementCache elementCache()
+ {
+ return (ElementCache) super.elementCache();
+ }
+
+ protected class ElementCache extends FolderManagementPage.ElementCache
+ {
+ WebElement inheritedChk(String name)
+ {
+ return Locator.checkboxByName(name).findWhenNeeded(this);
+ }
+
+ WebElement defaultDateFormat = Locator.id("defaultDateFormat").findWhenNeeded(this);
+ WebElement defaultTimeFormat = Locator.id("defaultTimeFormat").findWhenNeeded(this);
+ WebElement defaultDateTimeDateFormat = Locator.id("dateSelect").findWhenNeeded(this);
+ WebElement defaultDateTimeTimeFormat = Locator.id("timeSelect").findWhenNeeded(this);
+ WebElement formatWarningBanner = Locator.tagWithId("div", "dateFormatWarning").findWhenNeeded(this);
+
+ WebElement nonStandardWarning(WebElement field)
+ {
+ String id = field.getAttribute("id");
+ String xpath = String.format("//select[@id='%s']/following-sibling::span[@class='has-warning']", id);
+ return Locator.xpath(xpath).findWhenNeeded(this);
+ }
+
+ WebElement defaultNumberFormat = Locator.inputByNameContaining("defaultNumberFormat").findWhenNeeded(this);
+ WebElement additionalParsingPatternDates = Locator.inputByNameContaining("extraDateParsingPattern").findElement(this);
+ WebElement additionalParsingPatternTimes = Locator.inputByNameContaining("extraTimeParsingPattern").findElement(this);
+ WebElement additionalParsingPatternDateAndTime = Locator.inputByNameContaining("extraDateTimeParsingPattern").findElement(this);
+ WebElement restrictChartingColsChk = Locator.checkboxByName("restrictedColumnsEnabled").findWhenNeeded(this);
+
+ WebElement saveButton = Locator.lkButton("Save").findWhenNeeded(this);
+ WebElement inheritAll = Locator.lkButton("Inherit All").findWhenNeeded(this);
+
+ }
+
+}
diff --git a/src/org/labkey/test/pages/admin/FolderManagementPage.java b/src/org/labkey/test/pages/admin/FolderManagementPage.java
index 2b6ee0ff77..3f588c36ba 100644
--- a/src/org/labkey/test/pages/admin/FolderManagementPage.java
+++ b/src/org/labkey/test/pages/admin/FolderManagementPage.java
@@ -57,6 +57,12 @@ public FileRootsManagementPage goToFilesTab()
return new FileRootsManagementPage(getDriver());
}
+ public FolderFormatsPage goToFormatsTab()
+ {
+ selectTab("settings");
+ return new FolderFormatsPage(getDriver());
+ }
+
public RConfigurationPage goToRConfigTab()
{
selectTab("rConfig");
diff --git a/src/org/labkey/test/pages/core/admin/BaseSettingsPage.java b/src/org/labkey/test/pages/core/admin/BaseSettingsPage.java
index 043d7c0d45..4ab90f8604 100644
--- a/src/org/labkey/test/pages/core/admin/BaseSettingsPage.java
+++ b/src/org/labkey/test/pages/core/admin/BaseSettingsPage.java
@@ -11,6 +11,8 @@
import org.openqa.selenium.WebElement;
import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
public class BaseSettingsPage extends LabKeyPage
{
@@ -181,7 +183,12 @@ public String getDefaultDateDisplay()
public void setDefaultDateDisplay(DATE_FORMAT dateFormat)
{
- selectOptionByValue(elementCache().defaultDateFormat, dateFormat.format);
+ selectOptionByValue(elementCache().defaultDateFormat, dateFormat.toString());
+ }
+
+ public boolean defaultDateDisplayWarning()
+ {
+ return elementCache().nonStandardWarning(elementCache().defaultDateFormat).isDisplayed();
}
public void setDefaultDateTimeDisplay(DATE_FORMAT dateFormat, TIME_FORMAT timeFormat)
@@ -197,7 +204,12 @@ public String getDefaultDateTimeDateDisplay()
public void setDefaultDateTimeDateDisplay(DATE_FORMAT dateFormat)
{
- selectOptionByValue(elementCache().defaultDateTimeDateFormat, dateFormat.format);
+ selectOptionByValue(elementCache().defaultDateTimeDateFormat, dateFormat.toString());
+ }
+
+ public boolean defaultDateTimeDateDisplayWarning()
+ {
+ return elementCache().nonStandardWarning(elementCache().defaultDateTimeDateFormat).isDisplayed();
}
public String getDefaultDateTimeTimeDisplay()
@@ -207,7 +219,12 @@ public String getDefaultDateTimeTimeDisplay()
public void setDefaultDateTimeTimeDisplay(TIME_FORMAT timeFormat)
{
- selectOptionByValue(elementCache().defaultDateTimeTimeFormat, timeFormat.format);
+ selectOptionByValue(elementCache().defaultDateTimeTimeFormat, timeFormat.toString());
+ }
+
+ public boolean defaultDateTimeTimeDisplayWarning()
+ {
+ return elementCache().nonStandardWarning(elementCache().defaultDateTimeTimeFormat).isDisplayed();
}
public String getDefaultTimeDisplay()
@@ -217,7 +234,12 @@ public String getDefaultTimeDisplay()
public void setDefaultTimeDisplay(TIME_FORMAT timeFormat)
{
- selectOptionByValue(elementCache().defaultTimeFormat, timeFormat.format);
+ selectOptionByValue(elementCache().defaultTimeFormat, timeFormat.toString());
+ }
+
+ public boolean defaultTimeDisplayWarning()
+ {
+ return elementCache().nonStandardWarning(elementCache().defaultTimeFormat).isDisplayed();
}
public String getDefaultNumberDisplay()
@@ -283,6 +305,23 @@ public void setAltLoginPage(String loginPage)
setFormElement(elementCache().altLoginPageTxt,loginPage);
}
+ /**
+ * If the warning banner is present return the text otherwise return an empty string.
+ *
+ * @return Text in warning banner, empty string if no banner is present.
+ */
+ public String getFormatWarningMessage()
+ {
+ if (elementCache().formatWarningBanner.isDisplayed())
+ {
+ return elementCache().formatWarningBanner.getText();
+ }
+ else
+ {
+ return "";
+ }
+ }
+
public void save()
{
clickAndWait(elementCache().saveBtn);
@@ -325,6 +364,14 @@ protected class ElementCache extends LabKeyPage>.ElementCache
WebElement defaultTimeFormat = Locator.id("defaultTimeFormat").findWhenNeeded(this);
WebElement defaultDateTimeDateFormat = Locator.id("dateSelect").findWhenNeeded(this);
WebElement defaultDateTimeTimeFormat = Locator.id("timeSelect").findWhenNeeded(this);
+ WebElement formatWarningBanner = Locator.tagWithId("div", "dateFormatWarning").findWhenNeeded(this);
+
+ WebElement nonStandardWarning(WebElement field)
+ {
+ String id = field.getAttribute("id");
+ String xpath = String.format("//select[@id='%s']/following-sibling::span[@class='has-warning']", id);
+ return Locator.xpath(xpath).findWhenNeeded(this);
+ }
WebElement defaultNumberFormat = Locator.inputByNameContaining("defaultNumberFormat").findWhenNeeded(this);
WebElement additionalParsingPatternDates = Locator.inputByNameContaining("extraDateParsingPattern").findWhenNeeded(this);
@@ -351,12 +398,19 @@ public enum DATE_FORMAT
{
yyyy_MM_dd("yyyy-MM-dd"),
yyyy_MMM_dd("yyyy-MMM-dd"),
+ yyyy_MM("yyyy-MM"),
dd_MMM_yyyy("dd-MMM-yyyy"),
dd_MMM_yy("dd-MMM-yy"),
+ dd_MM_yyyy("dd-MM-yyyy"),
ddMMMyyyy("ddMMMyyyy"),
ddMMMyy("ddMMMyy"),
+ MMddyyyy("MM/dd/yyyy"),
+ MM_dd_yyyy("MM-dd-yyyy"),
+ MMMM_dd_yyyy("MMMM dd yyyy"),
Default("yyyy-MM-dd"),
- DTDefault("yyyy-MM-dd");
+ DTDefault("yyyy-MM-dd"),
+ DATE("Date"), // Valid only in a domain designer.
+ DATETIME("DATETIME"); // Valid only in a domain designer and only for the date part of a DateTime field.
private final String format;
@@ -369,6 +423,19 @@ public enum DATE_FORMAT
public String toString() {
return this.format;
}
+
+ private static final Map lookup = new HashMap<>();
+
+ static {
+ for (DATE_FORMAT d : DATE_FORMAT.values()) {
+ lookup.put(d.toString(), d);
+ }
+ }
+
+ public static DATE_FORMAT get(String format) {
+ return lookup.get(format);
+ }
+
}
public enum TIME_FORMAT
@@ -377,8 +444,10 @@ public enum TIME_FORMAT
HH_mm("HH:mm"),
HH_mm_ss_SSS("HH:mm:ss.SSS"),
hh_mm_a("hh:mm a"),
+ none(""), // Valid only for a DateTime field.
Default("HH:mm:ss"),
- DTDefault("HH:mm");
+ DTDefault("HH:mm"),
+ TIME("Time"); // Valid only in domain designer.
private final String format;
@@ -391,6 +460,19 @@ public enum TIME_FORMAT
public String toString() {
return this.format;
}
+
+ private static final Map lookup = new HashMap<>();
+
+ static {
+ for (TIME_FORMAT t : TIME_FORMAT.values()) {
+ lookup.put(t.toString(), t);
+ }
+ }
+
+ public static TIME_FORMAT get(String format) {
+ return lookup.get(format);
+ }
+
}
}
diff --git a/src/org/labkey/test/tests/DataClassTest.java b/src/org/labkey/test/tests/DataClassTest.java
index fd2c085cc8..d8adeeddd1 100644
--- a/src/org/labkey/test/tests/DataClassTest.java
+++ b/src/org/labkey/test/tests/DataClassTest.java
@@ -26,6 +26,8 @@
import org.labkey.test.categories.Daily;
import org.labkey.test.components.domain.BaseDomainDesigner;
import org.labkey.test.components.domain.DomainFormPanel;
+import org.labkey.test.pages.core.admin.BaseSettingsPage.DATE_FORMAT;
+import org.labkey.test.pages.core.admin.BaseSettingsPage.TIME_FORMAT;
import org.labkey.test.pages.experiment.CreateDataClassPage;
import org.labkey.test.pages.query.UpdateQueryRowPage;
import org.labkey.test.params.FieldDefinition;
@@ -304,29 +306,26 @@ public void testDateAndTimeFields()
log("Add a date-time field.");
String dateTimeField = "DateTime";
- String dateTimeFormat = "ddMMMyyyy hh:mm a";
DomainFormPanel domainFormPanel = createPage.getDomainEditor();
domainFormPanel.manuallyDefineFields(dateTimeField)
.setType(FieldDefinition.ColumnType.DateAndTime)
- .setDateTimeFormat(dateTimeFormat);
+ .setDateTimeFormat(DATE_FORMAT.ddMMMyyyy, TIME_FORMAT.hh_mm_a);
log("Add a date-only field.");
String dateField = "Date";
- String dateFormat = "ddMMMyyyy";
domainFormPanel = createPage.getDomainEditor();
domainFormPanel.addField(dateField)
.setType(FieldDefinition.ColumnType.Date)
- .setDateFormat(dateFormat);
+ .setDateFormat(DATE_FORMAT.ddMMMyyyy);
log("Add a time-only field.");
String timeField = "Time";
- String timeFormat = "hh:mm a";
domainFormPanel = createPage.getDomainEditor();
domainFormPanel.addField(timeField)
.setType(FieldDefinition.ColumnType.Time)
- .setTimeFormat(timeFormat);
+ .setTimeFormat(TIME_FORMAT.hh_mm_a);
createPage.clickSave();
diff --git a/src/org/labkey/test/tests/DomainDesignerTest.java b/src/org/labkey/test/tests/DomainDesignerTest.java
index ff87f6c18d..291c858d6d 100644
--- a/src/org/labkey/test/tests/DomainDesignerTest.java
+++ b/src/org/labkey/test/tests/DomainDesignerTest.java
@@ -35,6 +35,8 @@
import org.labkey.test.components.domain.RangeValidatorDialog;
import org.labkey.test.components.domain.RegexValidatorDialog;
import org.labkey.test.components.domain.RegexValidatorPanel;
+import org.labkey.test.pages.core.admin.BaseSettingsPage.DATE_FORMAT;
+import org.labkey.test.pages.core.admin.BaseSettingsPage.TIME_FORMAT;
import org.labkey.test.pages.experiment.CreateSampleTypePage;
import org.labkey.test.pages.list.EditListDefinitionPage;
import org.labkey.test.params.FieldDefinition;
@@ -311,7 +313,7 @@ public void testAddDomainField() throws Exception
domainFormPanel.addField("addedField")
.setType(FieldDefinition.ColumnType.DateAndTime)
.expand()
- .setDateTimeFormat("yyyy-MM-dd HH:mm")
+ .setDateTimeFormat(DATE_FORMAT.yyyy_MM_dd, TIME_FORMAT.HH_mm)
.setExcludeFromDateShifting(false)
.setDescription("simplest date format of all")
.setLabel("DateTime");
diff --git a/src/org/labkey/test/tests/ExpTest.java b/src/org/labkey/test/tests/ExpTest.java
index e3f706b714..4e6dc9febe 100644
--- a/src/org/labkey/test/tests/ExpTest.java
+++ b/src/org/labkey/test/tests/ExpTest.java
@@ -27,7 +27,7 @@
import org.labkey.test.categories.FileBrowser;
import org.labkey.test.components.domain.DomainFieldRow;
import org.labkey.test.components.ui.lineage.LineageGraph;
-import org.labkey.test.pages.core.admin.BaseSettingsPage;
+import org.labkey.test.pages.core.admin.BaseSettingsPage.DATE_FORMAT;
import org.labkey.test.pages.query.QueryMetadataEditorPage;
import org.labkey.test.params.FieldDefinition;
import org.labkey.test.util.PortalHelper;
@@ -140,7 +140,7 @@ public void testSteps()
DomainFieldRow domainRow = designerPage.fieldsPanel().getField("Created");
domainRow.setLabel("editedCreated");
domainRow.setDateTimeInherited(false);
- domainRow.setDateTimeFormatDate(BaseSettingsPage.DATE_FORMAT.ddMMMyyyy.toString());
+ domainRow.setDateTimeFormat(DATE_FORMAT.ddMMMyyyy);
designerPage.clickSave();
// Verify that it ended up in the XML version of the metadata
diff --git a/src/org/labkey/test/tests/NonStandardDateAndTimeFormatTest.java b/src/org/labkey/test/tests/NonStandardDateAndTimeFormatTest.java
new file mode 100644
index 0000000000..1167fb8078
--- /dev/null
+++ b/src/org/labkey/test/tests/NonStandardDateAndTimeFormatTest.java
@@ -0,0 +1,1343 @@
+package org.labkey.test.tests;
+
+import org.jetbrains.annotations.Nullable;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.labkey.remoteapi.CommandException;
+import org.labkey.remoteapi.Connection;
+import org.labkey.test.BaseWebDriverTest;
+import org.labkey.test.Locator;
+import org.labkey.test.TestTimeoutException;
+import org.labkey.test.categories.Daily;
+import org.labkey.test.components.domain.DomainFieldRow;
+import org.labkey.test.components.domain.DomainFormPanel;
+import org.labkey.test.pages.admin.FolderFormatsPage;
+import org.labkey.test.pages.admin.FolderManagementPage;
+import org.labkey.test.pages.core.admin.BaseSettingsPage;
+import org.labkey.test.pages.core.admin.BaseSettingsPage.TIME_FORMAT;
+import org.labkey.test.pages.core.admin.BaseSettingsPage.DATE_FORMAT;
+import org.labkey.test.pages.core.admin.LookAndFeelSettingsPage;
+import org.labkey.test.pages.core.admin.ProjectSettingsPage;
+import org.labkey.test.pages.experiment.CreateDataClassPage;
+import org.labkey.test.pages.list.EditListDefinitionPage;
+import org.labkey.test.params.FieldDefinition;
+import org.labkey.test.params.experiment.DataClassDefinition;
+import org.labkey.test.params.list.IntListDefinition;
+import org.labkey.test.params.list.ListDefinition;
+import org.labkey.test.util.APIContainerHelper;
+import org.labkey.test.util.DataRegionTable;
+import org.labkey.test.util.PortalHelper;
+import org.labkey.test.util.URLBuilder;
+import org.openqa.selenium.WebElement;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+@Category({Daily.class})
+public class NonStandardDateAndTimeFormatTest extends BaseWebDriverTest
+{
+
+ private static final String PROJECT_NAME = "Non-Standard Date And Time Formats Test";
+
+ // No standard Date, Time and DateTime formats set at the project level.
+ private static final String PROJECT_DATE_FORMAT = "dd/MM/yy";
+ private static final String PROJECT_TIME_FORMAT = "K:m:s a Z";
+ private static final String PROJECT_DATETIME_FORMAT = "EEEE MMMM dd D yyyy k:mm:s X";
+
+ // Warning shown on the Validation page for project settings.
+ private static final List PROJECT_WARNINGS = List.of(String.format("Project default display format for Dates: %s", PROJECT_DATE_FORMAT),
+ String.format("Project default display format for DateTimes: %s", PROJECT_DATETIME_FORMAT),
+ String.format("Project default display format for Times: %s", PROJECT_TIME_FORMAT));
+
+ // Tooltips shown on the various designer pages for non-standard formats.
+ private static final String TT_NS_DATE = "Non-standard date format.";
+ private static final String TT_NS_TIME = "Non-standard time format.";
+ private static final String TT_NS_DATETIME = "Non-standard date-time format.";
+
+ private final PortalHelper _portalHelper = new PortalHelper(this);
+
+ @Override
+ public List getAssociatedModules()
+ {
+ return Arrays.asList("list");
+ }
+
+ @Override
+ protected String getProjectName()
+ {
+ return PROJECT_NAME;
+ }
+
+ @BeforeClass
+ public static void setupProject() throws IOException, CommandException
+ {
+ NonStandardDateAndTimeFormatTest init = (NonStandardDateAndTimeFormatTest)getCurrentTest();
+ init.doSetup();
+ }
+
+ private void doSetup() throws IOException, CommandException
+ {
+ resetSiteSettings();
+ _containerHelper.createProject(PROJECT_NAME, null);
+ goToProjectHome();
+
+ // Use the API to set non-standard formats for the project.
+ new APIContainerHelper(this)
+ .setDateAndTimeFormats(createDefaultConnection(), PROJECT_NAME,
+ PROJECT_DATE_FORMAT, PROJECT_TIME_FORMAT, PROJECT_DATETIME_FORMAT);
+
+ _portalHelper.addWebPart("Lists");
+ _portalHelper.addWebPart("Data Classes");
+
+ }
+
+ @AfterClass
+ public static void afterClass() throws IOException, CommandException
+ {
+ ((NonStandardDateAndTimeFormatTest) getCurrentTest()).resetSiteSettings();
+ }
+
+ @Override
+ public void doCleanup(boolean afterTest) throws TestTimeoutException
+ {
+
+ super.doCleanup(afterTest);
+
+ try
+ {
+ ((NonStandardDateAndTimeFormatTest) getCurrentTest()).resetSiteSettings();
+ }
+ catch (IOException | CommandException rethrow)
+ {
+ throw new RuntimeException(rethrow);
+ }
+ }
+
+ private void resetSiteSettings() throws IOException, CommandException
+ {
+ log("Reset site settings.");
+ BaseSettingsPage.resetSettings(createDefaultConnection(), "/");
+ }
+
+ @Before
+ public void preTest()
+ {
+ goToProjectHome();
+ }
+
+ @Override
+ protected BrowserType bestBrowser()
+ {
+ return BrowserType.CHROME;
+ }
+
+ /**
+ *
+ * Test non-standard Date, Time and DateTime format settings at the project level. The non-standard formats are
+ * set during project creation.
+ *
+ *
+ * This test will:
+ *
+ * - Validate that the Date, Time and DateTime fields are not inherited.
+ * - Validate the formats are as expected (non-standard)
+ * - Validate the tooltip message.
+ * - Validate the Site Validate report show the project settings.
+ *
+ *
+ */
+ @Test
+ public void testProjectSettingsPage()
+ {
+
+ log("Check that the Date, Time and DateTime format fields in the Project Settings page.");
+
+ goToProjectHome();
+ ProjectSettingsPage.beginAt(this);
+ validateSettingsPage(false, PROJECT_DATE_FORMAT, true,
+ false, PROJECT_TIME_FORMAT, true,
+ false, PROJECT_DATETIME_FORMAT, "",
+ true, false);
+
+ log("Check that Site Validation includes warnings from the project settings.");
+ String scope = String.format("Project: %s", getProjectName());
+ validateSiteValidationReport(scope, PROJECT_WARNINGS, true);
+
+ }
+
+ /**
+ *
+ * Test non-standard Date, Time and DateTime formats with lists.
+ *
+ *
+ * This test will:
+ *
+ * - Create a list that has non-standard formats set for the fields.
+ * - Create a second list that has fields that inherit from the project settings.
+ * - Import data into the list to validate non-standard formats are used when display the data.
+ * - Validate the designer for fields that do not inherit from the project.
+ * - Validate the designer for fields that are inherited from the project (should see no warnings)
+ * - Check Site Validation report calls out the fields not inherited, but not the inherited fields.
+ *
+ *
+ *
+ * @throws IOException Can be thrown by the API creation calls.
+ * @throws CommandException Can be thrown by the API creation calls.
+ */
+ @Test
+ public void testLists() throws IOException, CommandException
+ {
+
+ String listFormat = "List Non-Standard Formats";
+ String listInherit = "List Inherit Project Formats";
+ String dateCol01 = "Date01";
+ String dateCol02 = "Date02";
+ String timeCol01 = "Time01";
+ String timeCol02 = "Time02";
+ String dateTimeCol01 = "DateTime01";
+ String dateTimeCol02 = "DateTime02";
+
+ log(String.format("Create a list named '%s' with various Date, Time and DateTime columns.", listFormat));
+
+ String nsDateFormat01 = "MMMM dd, yyyy"; // Similar to a standard format, except this has a comma after the dd.
+ String nsDateFormat02 = "yyyy-w G";
+ String nsTimeFormat01 = "hh:mm:ss.ss a";
+ String nsTimeFormat02 = "K:mm a z";
+
+ List listFields = List.of(
+ new FieldDefinition(dateCol01, FieldDefinition.ColumnType.Date).setFormat(nsDateFormat01),
+ new FieldDefinition(dateCol02, FieldDefinition.ColumnType.Date).setFormat(nsDateFormat02),
+ new FieldDefinition(timeCol01, FieldDefinition.ColumnType.Time).setFormat(nsTimeFormat01),
+ new FieldDefinition(timeCol02, FieldDefinition.ColumnType.Time).setFormat(nsTimeFormat02),
+ new FieldDefinition(dateTimeCol01, FieldDefinition.ColumnType.DateAndTime).setFormat(String.format("%s %s", nsDateFormat01, nsTimeFormat01)),
+ new FieldDefinition(dateTimeCol02, FieldDefinition.ColumnType.DateAndTime).setFormat(String.format("%s %s", nsTimeFormat02, nsDateFormat02))
+ );
+
+ createListByAPI(getProjectName(), listFormat, listFields);
+
+ log(String.format("Create a second list named '%s' that inherits formats from the project.", listInherit));
+
+ listFields = List.of(
+ new FieldDefinition(dateCol01, FieldDefinition.ColumnType.Date),
+ new FieldDefinition(timeCol01, FieldDefinition.ColumnType.Time),
+ new FieldDefinition(dateTimeCol01, FieldDefinition.ColumnType.DateAndTime)
+ );
+
+ createListByAPI(getProjectName(), listInherit, listFields);
+
+ log(String.format("Validate the design and data of list '%s' (does not inherit formats).", listFormat));
+ goToProjectHome();
+ _listHelper.goToList(listFormat);
+ _listHelper.insertNewRow(Map.of(dateCol01, "4/1/21",
+ dateCol02, "12/25/19",
+ timeCol01, "12:32 am",
+ timeCol02, "14:42",
+ dateTimeCol01, "May 1, 2005 6:32 pm",
+ dateTimeCol02, "6/1/24 10:00"), false);
+
+ Map expectedRowValues = Map.of(dateCol01, "April 01, 2021",
+ dateCol02, "2019-52 AD",
+ timeCol01, "12:32:00.00 AM",
+ timeCol02, "2:42 PM PST",
+ dateTimeCol01, "May 01, 2005 06:32:00.00 PM",
+ dateTimeCol02, "10:00 AM PDT 2024-22 AD");
+
+ EditListDefinitionPage listDefinitionPage = _listHelper.goToEditDesign(listFormat);
+ DomainFormPanel domainEditor = listDefinitionPage.getFieldsPanel();
+
+ validateFieldsInDesigner(domainEditor, dateCol01, false, FieldDefinition.ColumnType.Date,
+ nsDateFormat01, TT_NS_DATE);
+ validateFieldsInDesigner(domainEditor, dateCol02, false, FieldDefinition.ColumnType.Date,
+ nsDateFormat02, TT_NS_DATE);
+ validateFieldsInDesigner(domainEditor, timeCol01, false, FieldDefinition.ColumnType.Time,
+ nsTimeFormat01, TT_NS_TIME);
+ validateFieldsInDesigner(domainEditor, timeCol02, false, FieldDefinition.ColumnType.Time,
+ nsTimeFormat02, TT_NS_TIME);
+ validateFieldsInDesigner(domainEditor, dateTimeCol01, false, FieldDefinition.ColumnType.DateAndTime,
+ String.format("%s %s", nsDateFormat01, nsTimeFormat01), TT_NS_DATETIME);
+ validateFieldsInDesigner(domainEditor, dateTimeCol02, false, FieldDefinition.ColumnType.DateAndTime,
+ String.format("%s %s", nsTimeFormat02, nsDateFormat02), TT_NS_DATETIME);
+
+ validateDataIsFormatted(getProjectName(), listFormat, expectedRowValues);
+
+ log(String.format("Validate the design and data of list '%s' (does inherit formats).", listInherit));
+ goToProjectHome();
+ _listHelper.goToList(listInherit);
+ _listHelper.insertNewRow(Map.of(dateCol01, "4/1/21",
+ timeCol01, "12:32 am",
+ dateTimeCol01, "May 1, 2005 6:32 pm"), false);
+
+ expectedRowValues = Map.of(dateCol01, "01/04/21",
+ timeCol01, "0:32:0 AM -0800",
+ dateTimeCol01, "Sunday May 01 121 2005 18:32:0 -07");
+
+ listDefinitionPage = _listHelper.goToEditDesign(listInherit);
+ domainEditor = listDefinitionPage.getFieldsPanel();
+
+ validateFieldsInDesigner(domainEditor, dateCol01, true, FieldDefinition.ColumnType.Date,
+ PROJECT_DATE_FORMAT, TT_NS_DATE);
+ validateFieldsInDesigner(domainEditor, timeCol01, true, FieldDefinition.ColumnType.Time,
+ PROJECT_TIME_FORMAT, TT_NS_TIME);
+ validateFieldsInDesigner(domainEditor, dateTimeCol01, true, FieldDefinition.ColumnType.DateAndTime,
+ PROJECT_DATETIME_FORMAT, TT_NS_DATETIME);
+
+ listDefinitionPage.clickCancel();
+
+ validateDataIsFormatted(getProjectName(), listInherit, expectedRowValues);
+
+ log("Validate that the Site Validation contains the expected warnings.");
+
+ List expectedWarnings = List.of(String.format("Date property \"lists.%s.%s\": %s",
+ listFormat, dateCol01, nsDateFormat01),
+ String.format("Date property \"lists.%s.%s\": %s",
+ listFormat, dateCol02, nsDateFormat02),
+ String.format("Time property \"lists.%s.%s\": %s",
+ listFormat, timeCol01, nsTimeFormat01),
+ String.format("Time property \"lists.%s.%s\": %s",
+ listFormat, timeCol02, nsTimeFormat02),
+ String.format("DateTime property \"lists.%s.%s\": %s %s",
+ listFormat, dateTimeCol01, nsDateFormat01, nsTimeFormat01),
+ String.format("DateTime property \"lists.%s.%s\": %s %s",
+ listFormat, dateTimeCol02, nsTimeFormat02, nsDateFormat02)
+ );
+
+ String scope = String.format("Project: %s", getProjectName());
+ validateSiteValidationReport(scope, expectedWarnings, true);
+
+ log("Validate that Site Validation does not contain warnings about inherited fields.");
+
+ expectedWarnings = List.of(String.format("Date property \"lists.%s.%s\": %s",
+ listInherit, dateCol01, nsDateFormat01),
+ String.format("Time property \"lists.%s.%s\": %s",
+ listInherit, timeCol01, nsTimeFormat01),
+ String.format("DateTime property \"lists.%s.%s\": %s %s",
+ listInherit, dateTimeCol01, nsDateFormat01, nsTimeFormat01)
+ );
+
+ validateSiteValidationReport(scope, expectedWarnings, false);
+
+ }
+
+ /**
+ *
+ * Validate editing Date-Time fields with non-standard formats to standard formats.
+ *
+ *
+ * This test will:
+ *
+ * - Create a list with a non-standard format.
+ * - Validate the list and fields are called out in the site validation.
+ * - Edit the various fields and change the formats to a standard format.
+ * - Cancel the edit and validate the at the non-standard format is retained.
+ * - Edit again and change the fields to a standard format.
+ * - Validate the list and fields are no longer called out in the Site Validation report.
+ *
+ *
+ *
+ * @throws IOException Can be thrown by the API creation calls.
+ * @throws CommandException Can be thrown by the API creation calls.
+ */
+ @Test
+ public void testEditDomain() throws IOException, CommandException
+ {
+ String listEdit = "List Edit Non-Standard Formats";
+ String dateCol = "Date";
+ String timeCol = "Time";
+ String dateTimeCol = "DateTime";
+
+ log(String.format("Create a list named '%s' with various Date, Time and DateTime columns.", listEdit));
+
+ String nsDateFormat = "MMMM dd, yyyy";
+ String nsTimeFormat = "hh:mm:ss.ss a";
+
+ List listFields = List.of(
+ new FieldDefinition(dateCol, FieldDefinition.ColumnType.Date).setFormat(nsDateFormat),
+ new FieldDefinition(timeCol, FieldDefinition.ColumnType.Time).setFormat(nsTimeFormat),
+ new FieldDefinition(dateTimeCol, FieldDefinition.ColumnType.DateAndTime).setFormat(String.format("%s %s", nsDateFormat, nsTimeFormat))
+ );
+
+ createListByAPI(getProjectName(), listEdit, listFields);
+
+ log("Check that Site Validation tags the fields in the list.");
+
+ List expectedWarnings = List.of(String.format("Date property \"lists.%s.%s\": %s",
+ listEdit, dateCol, nsDateFormat),
+ String.format("Time property \"lists.%s.%s\": %s",
+ listEdit, timeCol, nsTimeFormat),
+ String.format("DateTime property \"lists.%s.%s\": %s %s",
+ listEdit, dateTimeCol, nsDateFormat, nsTimeFormat));
+
+ String scope = String.format("Project: %s", getProjectName());
+ validateSiteValidationReport(scope, expectedWarnings, true);
+
+ goToProjectHome();
+ _listHelper.goToList(listEdit);
+ EditListDefinitionPage listDefinitionPage = _listHelper.goToEditDesign(listEdit);
+
+ log("Edit the Date, Time and DateTime fields but then cancel out of the edit.");
+
+ DomainFormPanel domainEditor = listDefinitionPage.getFieldsPanel();
+ DomainFieldRow fieldRow = domainEditor.getField(dateCol);
+ fieldRow.expand();
+ fieldRow.setDateFormat(DATE_FORMAT.yyyy_MM_dd);
+ checker().withScreenshot()
+ .verifyFalse(String.format("Changing '%s' to a standard format should remove the warning icon.", dateCol),
+ fieldRow.hasDomainWarningIcon());
+
+ fieldRow = domainEditor.getField(timeCol);
+ fieldRow.expand();
+ fieldRow.setTimeFormat(TIME_FORMAT.HH_mm_ss);
+ checker().withScreenshot()
+ .verifyFalse(String.format("Changing '%s' to a standard format should remove the warning icon.", timeCol),
+ fieldRow.hasDomainWarningIcon());
+
+ fieldRow = domainEditor.getField(dateTimeCol);
+ fieldRow.expand();
+ fieldRow.setDateTimeFormat(DATE_FORMAT.yyyy_MM_dd, TIME_FORMAT.hh_mm_a);
+ checker().withScreenshot()
+ .verifyFalse(String.format("Changing '%s' to a standard format should remove the warning icon.", dateTimeCol),
+ fieldRow.hasDomainWarningIcon());
+
+ log("Cancel out of the edit.");
+ listDefinitionPage.clickCancel();
+
+ log("Go back to the design page and validate that the non-standard formats are still there.");
+ listDefinitionPage = _listHelper.goToEditDesign(listEdit);
+ domainEditor = listDefinitionPage.getFieldsPanel();
+
+ validateFieldsInDesigner(domainEditor, dateCol, false, FieldDefinition.ColumnType.Date,
+ nsDateFormat, TT_NS_DATE);
+ validateFieldsInDesigner(domainEditor, timeCol, false, FieldDefinition.ColumnType.Time,
+ nsTimeFormat, TT_NS_TIME);
+ validateFieldsInDesigner(domainEditor, dateTimeCol, false, FieldDefinition.ColumnType.DateAndTime,
+ String.format("%s %s", nsDateFormat, nsTimeFormat), TT_NS_DATETIME);
+
+ listDefinitionPage.clickCancel();
+
+ log("Now edit the field to a standard format.");
+ listDefinitionPage = _listHelper.goToEditDesign(listEdit);
+
+ domainEditor = listDefinitionPage.getFieldsPanel();
+ fieldRow = domainEditor.getField(dateCol);
+ fieldRow.expand();
+ fieldRow.setDateFormat(DATE_FORMAT.yyyy_MM_dd);
+ fieldRow = domainEditor.getField(timeCol);
+ fieldRow.expand();
+ fieldRow.setTimeFormat(TIME_FORMAT.HH_mm_ss);
+ fieldRow = domainEditor.getField(dateTimeCol);
+ fieldRow.expand();
+ fieldRow.setDateTimeFormat(DATE_FORMAT.yyyy_MM_dd, TIME_FORMAT.hh_mm_a);
+
+ listDefinitionPage.clickSave();
+
+ listDefinitionPage = _listHelper.goToEditDesign(listEdit);
+ domainEditor = listDefinitionPage.getFieldsPanel();
+
+ validateFieldsInDesigner(domainEditor, dateCol, false, FieldDefinition.ColumnType.Date,
+ DATE_FORMAT.yyyy_MM_dd.toString(), null);
+ validateFieldsInDesigner(domainEditor, timeCol, false, FieldDefinition.ColumnType.Time,
+ TIME_FORMAT.HH_mm_ss.toString(), null);
+ validateFieldsInDesigner(domainEditor, dateTimeCol, false, FieldDefinition.ColumnType.DateAndTime,
+ String.format("%s %s", DATE_FORMAT.yyyy_MM_dd, TIME_FORMAT.hh_mm_a), null);
+
+ log("Check that Site Validation Does not tag the fields in the list after they have been edited.");
+
+ validateSiteValidationReport(scope, expectedWarnings, false);
+
+ }
+
+ /**
+ *
+ * Validate non-standard Date, Time and DateTime formats in a DataClass
+ *
+ *
+ * This test will:
+ *
+ * - Create a DataClass with non-standard formats.
+ * - Create a DataClass that inherits non-standard formats from the project settings.
+ * - Add some data to both as a sanity validation that non-standard formats are used.
+ * - Validate the designer scenarios for both DataClasses.
+ *
+ *
+ *
+ * @throws IOException Can be thrown by the API creation calls.
+ * @throws CommandException Can be thrown by the API creation calls.
+ */
+ @Test
+ public void testDataClass() throws IOException, CommandException
+ {
+ String dcFormat = "DC Non-Standard Formats";
+ String dcInherit = "DC Inherit Project Formats";
+ String dateCol = "Date";
+ String timeCol = "Time";
+ String dateTimeCol = "DateTime";
+
+ String nsDateFormat = "MMMM dd, yyyy";
+ String nsTimeFormat = "hh:mm:ss.ss a";
+
+ List fields = List.of(
+ new FieldDefinition(dateCol, FieldDefinition.ColumnType.Date).setFormat(nsDateFormat),
+ new FieldDefinition(timeCol, FieldDefinition.ColumnType.Time).setFormat(nsTimeFormat),
+ new FieldDefinition(dateTimeCol, FieldDefinition.ColumnType.DateAndTime).setFormat(String.format("%s %s", nsDateFormat, nsTimeFormat))
+ );
+
+ log(String.format("Create a Data Class named '%s' with non-standard format fields.", dcFormat));
+
+ createDataClass(getProjectName(), dcFormat, fields);
+
+ fields = List.of(
+ new FieldDefinition(dateCol, FieldDefinition.ColumnType.Date),
+ new FieldDefinition(timeCol, FieldDefinition.ColumnType.Time),
+ new FieldDefinition(dateTimeCol, FieldDefinition.ColumnType.DateAndTime)
+ );
+
+ log(String.format("Create a Data Class named '%s' that inherits non-standard format fields from the project.", dcFormat));
+
+ createDataClass(getProjectName(), dcInherit, fields);
+
+ log("Add some data to both data classes as a sanity validation of the formats.");
+
+ String bulkData = String.format("%s\t%s\t%s\t%s\n", "Name", dateTimeCol, dateCol, timeCol)
+ + "A\t12/23/24 14:45\t12/23/24\t14:45\n";
+
+ Map expectedFormatData = Map.of("Name", "A",
+ dateTimeCol, "December 23, 2024 02:45:00.00 PM",
+ dateCol, "December 23, 2024",
+ timeCol, "02:45:00.00 PM", "Flag", "");
+
+ Map expectedInheritedData = Map.of("Name", "A",
+ dateTimeCol, "Monday December 23 358 2024 14:45:0 -08",
+ dateCol, "23/12/24",
+ timeCol, "2:45:0 PM -0800", "Flag", "");
+
+ populateDataClass(getProjectName(), dcFormat, bulkData);
+ populateDataClass(getProjectName(), dcInherit, bulkData);
+
+ log(String.format("Validate domain designer feedback for '%s'.", dcFormat));
+
+ goToProjectHome();
+ clickAndWait(Locator.linkWithText(dcFormat));
+ clickAndWait(Locator.lkButton("Edit Data Class"));
+ CreateDataClassPage editPage = new CreateDataClassPage(getDriver());
+ DomainFormPanel domainEditor = editPage.getDomainEditor();
+
+ validateFieldsInDesigner(domainEditor, dateCol,
+ false, FieldDefinition.ColumnType.Date,
+ nsDateFormat, TT_NS_DATE);
+
+ validateFieldsInDesigner(domainEditor, timeCol,
+ false, FieldDefinition.ColumnType.Time,
+ nsTimeFormat, TT_NS_TIME);
+
+ validateFieldsInDesigner(domainEditor, dateTimeCol,
+ false, FieldDefinition.ColumnType.DateAndTime,
+ String.format("%s %s", nsDateFormat, nsTimeFormat), TT_NS_DATETIME);
+
+ editPage.clickCancel();
+
+ log("Validate the data (make sure we still respect non-standard formats).");
+ validateDataIsFormatted(getProjectName(), dcFormat, expectedFormatData);
+
+ log("Validate that data sets are reported in Site Validation.");
+ List expectedWarnings = List.of(String.format("Date property \"exp.data.%s.%s\": %s",
+ dcFormat, dateCol, nsDateFormat),
+ String.format("Time property \"exp.data.%s.%s\": %s",
+ dcFormat, timeCol, nsTimeFormat),
+ String.format("DateTime property \"exp.data.%s.%s\": %s %s",
+ dcFormat, dateTimeCol, nsDateFormat, nsTimeFormat));
+
+ String scope = String.format("Project: %s", getProjectName());
+ validateSiteValidationReport(scope, expectedWarnings, true);
+
+ log(String.format("Validate domain designer feedback for '%s'.", dcInherit));
+
+ goToProjectHome();
+ clickAndWait(Locator.linkWithText(dcInherit));
+ clickAndWait(Locator.lkButton("Edit Data Class"));
+ editPage = new CreateDataClassPage(getDriver());
+ domainEditor = editPage.getDomainEditor();
+
+ validateFieldsInDesigner(domainEditor, dateCol,
+ false, FieldDefinition.ColumnType.Date,
+ PROJECT_DATE_FORMAT, TT_NS_DATE);
+
+ validateFieldsInDesigner(domainEditor, timeCol,
+ false, FieldDefinition.ColumnType.Time,
+ PROJECT_TIME_FORMAT, TT_NS_TIME);
+
+ validateFieldsInDesigner(domainEditor, dateTimeCol,
+ false, FieldDefinition.ColumnType.DateAndTime,
+ PROJECT_DATETIME_FORMAT, TT_NS_DATETIME);
+
+ editPage.clickCancel();
+
+ log("Validate the data (make sure we still respect non-standard formats).");
+ validateDataIsFormatted(getProjectName(), dcInherit, expectedInheritedData);
+
+ }
+
+ /**
+ *
+ * This test will check the scoping of non-standard formats when set at the site and subfolder levels. This test
+ * creates a separate project to avoid the project settings from changed for the default test project from
+ * interfering. This test also uses data classes for validation because a data class is visible in subfolders.
+ *
+ *
+ * This test will:
+ *
+ * - Create a separate project with a subfolder. Project has standard formats.
+ * - Create and populate a data class in the project.
+ * - Create and populate a data class in the subfolder.
+ * - From the subfolder add a record to the data class in the parent folder.
+ * - Change the Date-Time settings at the site level to be non-standard.
+ * - Validate the 'Look and Feel' page for the site.
+ * - Validate the Site Validation report calls out the site settings.
+ * - Change the Date-Time format at the subfolder.
+ * - Validate the 'Formats' page for the subfolder.
+ * - Validate the Site Validation report.
+ * - Validate the data in both data classes is formatted as expected in the subfolder.
+ * - Reset the site settings.
+ * - Validate the Site Validation does not call out the site settings but still calls out the subfolder.
+ * - Validate the 'Look and Feel' page is reset with the default formats.
+ * - Validate the subfolder formats are unchanged.
+ *
+ * Note: there are periodic checks that the data is formatted as expected at the various levels.
+ *
+ *
+ * @throws IOException Can be thrown by the test APIs.
+ * @throws CommandException Can be thrown by the test APIs.
+ */
+ @Test
+ public void testScopeFromSiteToSubFolder() throws IOException, CommandException
+ {
+
+ String folderProject = "Non-Standard Sub-Folder Test";
+ String subFolder = "SubFolder_01";
+ String subFolderPath = folderProject + "/" + subFolder;
+
+ String dcInProj = "DC In Project Folder";
+ String dcInSub = "DC In Sub-Folder";
+ String dateCol = "Date";
+ String timeCol = "Time";
+ String dateTimeCol = "DateTime";
+
+ log(String.format("Create a project '%s' with standard formatting.", folderProject));
+
+ _containerHelper.deleteProject(folderProject, false);
+ _containerHelper.createProject(folderProject, null);
+
+ log(String.format("Create a sub-folder '%s'.", folderProject));
+ _containerHelper.createSubfolder(folderProject, subFolder);
+
+ log(String.format("In the parent folder create a DataClass named '%s' with various Date, Time and DateTime columns.", dcInProj));
+
+ goToProjectHome(folderProject);
+ _portalHelper.addWebPart("Data Classes");
+
+ List fields = List.of(
+ new FieldDefinition(dateCol, FieldDefinition.ColumnType.Date),
+ new FieldDefinition(timeCol, FieldDefinition.ColumnType.Time),
+ new FieldDefinition(dateTimeCol, FieldDefinition.ColumnType.DateAndTime)
+ );
+
+ createDataClass(folderProject, dcInProj, fields);
+
+ log("Add data to use for format validation.");
+ String bulkData = String.format("%s\t%s\t%s\t%s\n", "Name", dateTimeCol, dateCol, timeCol)
+ + "P1\t12/23/24 14:45\t12/23/24\t14:45\n";
+
+ populateDataClass(folderProject, dcInProj, bulkData);
+
+ log(String.format("In the sub-folder '%s' create a DataClass named '%s' with Date & Time columns.", subFolder, dcInSub));
+
+ navigateToFolder(folderProject, subFolder);
+ _portalHelper.addWebPart("Data Classes");
+
+ fields = List.of(
+ new FieldDefinition(dateCol, FieldDefinition.ColumnType.Date),
+ new FieldDefinition(timeCol, FieldDefinition.ColumnType.Time),
+ new FieldDefinition(dateTimeCol, FieldDefinition.ColumnType.DateAndTime)
+ );
+
+ createDataClass(subFolderPath, dcInSub, fields);
+
+ log("Add data to DataClass created in the subfolder as validation.");
+
+ bulkData = String.format("%s\t%s\t%s\t%s\n", "Name", dateTimeCol, dateCol, timeCol)
+ + "C1\t11/28/24 11:11\t11/28/24\t11:11\n";
+
+ populateDataClass(subFolderPath, dcInSub, bulkData);
+
+ log("In the subfolder add data to DataClass from the parent folder as validation.");
+
+ populateDataClass(subFolderPath, dcInProj, bulkData);
+
+ log("Change the site setting to be non-standard.");
+
+ String nsSiteDateFormat = "MMMM dd, yyyy";
+ String nsSiteTimeFormat = "kk:mm z";
+
+ changeSiteDateAndTimeFormats(nsSiteDateFormat, nsSiteTimeFormat);
+
+ goToProjectHome(folderProject);
+
+ log("Validate the site 'Look and Feel' page has the correct values, feedback, etc...");
+ LookAndFeelSettingsPage lookAndFeelSettingsPage = goToAdminConsole().clickLookAndFeelSettings();
+ validateSettingsPage(null, nsSiteDateFormat, true,
+ null, nsSiteTimeFormat, true,
+ null, String.format("%s %s", nsSiteDateFormat, nsSiteTimeFormat), "",
+ true, false);
+
+ if (checker().withScreenshot()
+ .verifyTrue("The warning banner at the top of the Site Setting page does not contain the expected comment.",
+ lookAndFeelSettingsPage.getFormatWarningMessage()
+ .startsWith("Warning: One or more date, time, or date-time display formats are using non-standard patterns.")))
+ {
+ WebElement link = Locator.linkWithText("Click here").findWhenNeeded(getDriver());
+ if (checker().withScreenshot()
+ .verifyTrue("'Click here' link is not visible.", link.isDisplayed()))
+ {
+ link.click();
+ switchToWindow(1);
+ WebElement banner = Locator.tagWithText("h3", "Date & Number Display Formats").refindWhenNeeded(getDriver());
+ checker().withScreenshot()
+ .verifyTrue("'Click here' link did not navigate as expected.",
+ waitFor(banner::isDisplayed, 1_000));
+ closeExtraWindows();
+ }
+ }
+
+ log("Check that the Site Validation report calls out the site settings.");
+
+ List siteWarnings = List.of(String.format("Site default display format for Dates: %s", nsSiteDateFormat),
+ String.format("Site default display format for Times: %s", nsSiteTimeFormat),
+ String.format("Site default display format for DateTimes: %s %s", nsSiteDateFormat, nsSiteTimeFormat));
+
+ String scope = "Root: /";
+ validateSiteValidationReport(scope, siteWarnings, true);
+
+ log(String.format("Validate project settings for '%s' inherit the site settings.", folderProject));
+ ProjectSettingsPage.beginAt(this, folderProject);
+ validateSettingsPage(true, nsSiteDateFormat, false,
+ true, nsSiteTimeFormat, false,
+ true, String.format("%s %s", nsSiteDateFormat, nsSiteTimeFormat), "",
+ false, false);
+
+ log(String.format("Validate subfolder settings for '%s' inherit the site settings.", subFolderPath));
+ FolderFormatsPage.beginAt(this, subFolderPath);
+ validateSettingsPage(true, nsSiteDateFormat, false,
+ true, nsSiteTimeFormat, false,
+ true, String.format("%s %s", nsSiteDateFormat, nsSiteTimeFormat), "",
+ false, false);
+
+ log("Sanity check that the DataClass data is formatted in the project and subfolder.");
+ Map expectedFormatData = Map.of("Name", "P1",
+ dateTimeCol, "December 23, 2024 14:45 PST",
+ dateCol, "December 23, 2024",
+ timeCol, "14:45 PST",
+ "Flag", "");
+
+ validateDataIsFormatted(folderProject, dcInProj, expectedFormatData);
+
+ expectedFormatData = Map.of("Name", "C1",
+ dateTimeCol, "November 28, 2024 11:11 PST",
+ dateCol, "November 28, 2024",
+ timeCol, "11:11 PST",
+ "Flag", "");
+ validateDataIsFormatted(subFolderPath, dcInSub, expectedFormatData);
+ validateDataIsFormatted(subFolderPath, dcInProj, expectedFormatData);
+
+ log("Change the formats in the subFolder.");
+ String nsSubDateFormat = "EEEE MMMM dd, yyyy";
+ String nsSubTimeFormat = "kk:mm (z)";
+
+ new APIContainerHelper(this)
+ .setDateAndTimeFormats(createDefaultConnection(), subFolderPath,
+ nsSubDateFormat, nsSubTimeFormat, String.format("%s %s", nsSubDateFormat, nsSubTimeFormat));
+
+ log(String.format("Validate folder settings for '%s' no longer inherit the site settings.", subFolderPath));
+ FolderFormatsPage.beginAt(this, subFolderPath);
+ validateSettingsPage(false, nsSubDateFormat, true,
+ false, nsSubTimeFormat, true,
+ false, String.format("%s %s", nsSubDateFormat, nsSubTimeFormat), "",
+ true, false);
+
+ log("Check the format in the DataClasses");
+ expectedFormatData = Map.of("Name", "C1",
+ dateTimeCol, "Thursday November 28, 2024 11:11 (PST)",
+ dateCol, "Thursday November 28, 2024",
+ timeCol, "11:11 (PST)",
+ "Flag", "");
+ validateDataIsFormatted(subFolderPath, dcInSub, expectedFormatData);
+ validateDataIsFormatted(subFolderPath, dcInProj, expectedFormatData);
+
+ log("Check that the 'Site Validation' report now includes the subfolder.");
+ List folderWarnings = List.of(String.format("Folder default display format for Dates: %s", nsSubDateFormat),
+ String.format("Folder default display format for Times: %s", nsSubTimeFormat),
+ String.format("Folder default display format for DateTimes: %s %s", nsSubDateFormat, nsSubTimeFormat));
+
+ scope = String.format("Folder: %s", subFolderPath);
+ validateSiteValidationReport(scope, folderWarnings, true);
+
+ log("Reset the site settings.");
+ resetSiteSettings();
+
+ log("Validate 'Look and Feel' page after reset.");
+ goToAdminConsole().clickLookAndFeelSettings();
+ validateSettingsPage(null, DATE_FORMAT.Default.toString(), false,
+ null, TIME_FORMAT.Default.toString(), false,
+ null, DATE_FORMAT.DTDefault.toString(), TIME_FORMAT.DTDefault.toString(),
+ false, false);
+
+ log("Validate site is no longer listed in Site Validation report.");
+ scope = "Root: /";
+ validateSiteValidationReport(scope, siteWarnings, false);
+
+ log(String.format("Validate subfolder settings for '%s' still do not inherit the site settings.", subFolderPath));
+ FolderFormatsPage.beginAt(this, subFolderPath);
+ validateSettingsPage(false, nsSubDateFormat, true,
+ false, nsSubTimeFormat, true,
+ false, String.format("%s %s", nsSubDateFormat, nsSubTimeFormat), "",
+ true, false);
+
+ log("Validate the subfolder still appears in the Site Validation report.");
+ scope = String.format("Folder: %s", subFolderPath);
+ validateSiteValidationReport(scope, folderWarnings, true);
+
+ }
+
+ /**
+ *
+ * Use the text values 'Date', 'Time' and 'DateTime' as the format values in a domain designer. This will use a
+ * DataClass because its design will be visible in the sub-folder.
+ *
+ *
+ * This test will:
+ *
+ * - Create a new project and set the Date-Time formats to some standard format.
+ * - Create a sub-folder and set the Date-Time formats to some other standard format.
+ * - Create a DataClass in parent folder.
+ * - Set the date field format to 'Date'.
+ * - Set the time field format to 'Time'.
+ * - Set the DateTime field format to 'DateTime' and 'none'.
+ * - Validate data is formatted as expected in the project.
+ * - In the sub-folder validate the data is formatted by the sub-folder settings.
+ * - Validate that setting the date part of a DateTime field only allows 'none' for the time format part.
+ *
+ *
+ *
+ * @throws IOException Can be thrown by helpers that create the folders, etc...
+ * @throws CommandException Can be thrown by helpers that create the folders, etc...
+ */
+ @Test
+ public void testTextFormatValueOfDate() throws IOException, CommandException
+ {
+
+ String folderProject = "Text_Format_Test";
+ String subFolder = "SubFolder_01";
+ String subFolderPath = folderProject + "/" + subFolder;
+
+ log(String.format("Create a project '%s' with standard formatting.", folderProject));
+
+ _containerHelper.deleteProject(folderProject, false);
+ _containerHelper.createProject(folderProject, null);
+
+ log(String.format("Create a sub-folder '%s'.", folderProject));
+ _containerHelper.createSubfolder(folderProject, subFolder);
+
+ goToProjectHome(folderProject);
+ _portalHelper.addWebPart("Data Classes");
+
+ goToProjectHome(subFolderPath);
+ _portalHelper.addWebPart("Data Classes");
+
+ String dcSetFormats = "DC Use Text Format";
+ String dcCheckWarnings = "DC Check Warnings";
+
+ String dateCol = "Date01";
+ String timeCol = "Time01";
+ String dateTimeCol = "DateTime01";
+
+ log(String.format("Create a DataClass named '%s' with Date, Time and DateTime columns.", dcSetFormats));
+
+ List fields = List.of(
+ new FieldDefinition(dateCol, FieldDefinition.ColumnType.Date),
+ new FieldDefinition(timeCol, FieldDefinition.ColumnType.Time),
+ new FieldDefinition(dateTimeCol, FieldDefinition.ColumnType.DateAndTime)
+ );
+
+ createDataClass(folderProject, dcSetFormats, fields);
+ createDataClass(folderProject, dcCheckWarnings, fields);
+
+ log("Add data in the parent folder.");
+ String bulkData = String.format("%s\t%s\t%s\t%s\n", "Name", dateTimeCol, dateCol, timeCol)
+ + "P1\t11/11/11 23:11\t11/11/11\t23:11\n";
+
+ populateDataClass(folderProject, dcSetFormats, bulkData);
+
+ log("Add data to the DataClasses in the subfolder.");
+
+ bulkData = String.format("%s\t%s\t%s\t%s\n", "Name", dateTimeCol, dateCol, timeCol)
+ + "C1\t11/11/11 23:11\t11/11/11\t23:11\n";
+
+ populateDataClass(subFolderPath, dcSetFormats, bulkData);
+
+ log("At the project level set the formats to something other than the default values.");
+ ProjectSettingsPage projectSettingsPage = ProjectSettingsPage.beginAt(this, folderProject);
+ projectSettingsPage.setDefaultDateDisplayInherited(false);
+ projectSettingsPage.setDefaultDateDisplay(DATE_FORMAT.dd_MMM_yyyy);
+ projectSettingsPage.setDefaultTimeDisplayInherited(false);
+ projectSettingsPage.setDefaultTimeDisplay(TIME_FORMAT.hh_mm_a);
+ projectSettingsPage.setDefaultDateTimeDisplayInherited(false);
+ projectSettingsPage.setDefaultDateTimeDisplay(DATE_FORMAT.dd_MMM_yyyy, TIME_FORMAT.hh_mm_a);
+ projectSettingsPage.save();
+
+ log("At the sub-folder level set the formats to something different as well.");
+ FolderFormatsPage folderFormatsPage = FolderManagementPage.beginAt(this, subFolderPath).goToFormatsTab();
+ folderFormatsPage.setDefaultDateDisplayInherited(false);
+ folderFormatsPage.setDefaultDateDisplay(DATE_FORMAT.ddMMMyy);
+ folderFormatsPage.setDefaultTimeDisplayInherited(false);
+ folderFormatsPage.setDefaultTimeDisplay(TIME_FORMAT.HH_mm_ss_SSS);
+ folderFormatsPage.setDefaultDateTimeDisplayInherited(false);
+ folderFormatsPage.setDefaultDateTimeDisplay(DATE_FORMAT.ddMMMyy, TIME_FORMAT.HH_mm_ss_SSS);
+ folderFormatsPage.clickSave();
+
+ log("Go to the project and change the formats in the DataClass.");
+ goToProjectHome(folderProject);
+
+ log(String.format("For DataClass '%s' in the parent folder, change the formats to use 'Date', 'Time' and 'DateTime'.", dcSetFormats));
+ clickAndWait(Locator.linkWithText(dcSetFormats));
+ clickAndWait(Locator.lkButton("Edit Data Class"));
+ CreateDataClassPage editPage = new CreateDataClassPage(getDriver());
+ DomainFormPanel domainEditor = editPage.getDomainEditor();
+ DomainFieldRow fieldRow = domainEditor.getField(dateCol);
+ fieldRow.setDateInherited(false);
+ fieldRow.setDateFormat(DATE_FORMAT.DATE);
+ fieldRow = domainEditor.getField(timeCol);
+ fieldRow.setTimeInherited(false);
+ fieldRow.setTimeFormat(TIME_FORMAT.TIME);
+ fieldRow = domainEditor.getField(dateTimeCol);
+ fieldRow.setDateTimeInherited(false);
+ fieldRow.setDateTimeFormat(DATE_FORMAT.DATETIME, TIME_FORMAT.none);
+ editPage.clickSave();
+
+ log("Validate that the values are formatted with the settings in the parent folder.");
+
+ Map expectedFormatData = Map.of("Name", "P1",
+ dateTimeCol, "11-Nov-2011 11:11 PM",
+ dateCol, "11-Nov-2011",
+ timeCol, "11:11 PM", "Flag", "");
+
+ validateDataIsFormatted(folderProject, dcSetFormats, expectedFormatData);
+
+ log("Check that using the values DATE, TIME and DATETIME do not show up in the validation report.");
+ // Issue 51491
+ List siteWarnings = List.of(String.format("Site default display format for Dates: %s", DATE_FORMAT.DATE),
+ String.format("Site default display format for Times: %s", TIME_FORMAT.TIME),
+ String.format("Site default display format for DateTimes: %s %s", DATE_FORMAT.DATETIME, TIME_FORMAT.none));
+
+ String scope = "Root: /";
+ validateSiteValidationReport(scope, siteWarnings, false);
+
+ log(String.format("Go to sub-folder '%s' and validate the data here is formatted according to sub-folder settings.", subFolder));
+
+ expectedFormatData = Map.of("Name", "C1",
+ dateTimeCol, "11Nov11 23:11:00.000",
+ dateCol, "11Nov11",
+ timeCol, "23:11:00.000", "Flag", "");
+
+ validateDataIsFormatted(subFolderPath, dcSetFormats, expectedFormatData);
+
+ log("Go back to parent folder and validate warnings for DateTime fields.");
+
+ goToProjectHome(folderProject);
+
+ clickAndWait(Locator.linkWithText(dcCheckWarnings));
+ clickAndWait(Locator.lkButton("Edit Data Class"));
+ editPage = new CreateDataClassPage(getDriver());
+ domainEditor = editPage.getDomainEditor();
+ fieldRow = domainEditor.getField(dateTimeCol);
+ fieldRow.setDateTimeInherited(false);
+ fieldRow.setDateTimeFormat(DATE_FORMAT.DATETIME, TIME_FORMAT.hh_mm_a);
+
+ checker().verifyTrue(String.format("When setting the date part of a DateTime to '%s', '%s' to should be the only allowed value for the time part.",
+ DATE_FORMAT.DATETIME, TIME_FORMAT.none),
+ fieldRow.hasDomainWarningIcon());
+
+ List actualValues = editPage.clickSaveExpectingErrors();
+
+ List expectedValues = List.of(
+ String.format("Property %s: %s %s is an illegal format for type DateTime",
+ dateTimeCol, DATE_FORMAT.DATETIME, TIME_FORMAT.hh_mm_a),
+ String.format("Please correct errors in %s before saving.",
+ dcCheckWarnings));
+
+ checker().verifyEquals("Error messages are not as expected.",
+ expectedValues, actualValues);
+
+ checker().screenShotIfNewError("Warning_Errors");
+
+ log("Cancel out of the editor.");
+ editPage.clickCancel();
+
+ }
+
+ // Private helper that will create a list through the APIs. This allows the list to have non-standard formats.
+ private void createListByAPI(String path, String listName, List fields) throws IOException, CommandException
+ {
+ Connection connection = createDefaultConnection();
+ ListDefinition listDef = new IntListDefinition(listName, "Key");
+ for(FieldDefinition field : fields)
+ {
+ listDef.addField(field);
+ }
+
+ listDef.create(connection, path);
+ }
+
+ private void createDataClass(String path, String dcName, List fields) throws IOException, CommandException
+ {
+ log(String.format("Create a Data Class named '%s' in '%s'.", dcName, path));
+
+ DataClassDefinition dataClass = new DataClassDefinition(dcName);
+ for(FieldDefinition field : fields)
+ {
+ dataClass.addField(field);
+ }
+
+ dataClass.create(createDefaultConnection(), path);
+
+ }
+
+ private void populateDataClass(String path, String dcName, String importData)
+ {
+ goToProjectHome(path);
+ clickAndWait(Locator.linkWithText(dcName));
+
+ DataRegionTable dataTable = new DataRegionTable("query", getDriver());
+ dataTable.clickImportBulkData()
+ .setText(importData);
+
+ clickButton("Submit");
+
+ }
+
+ // Private helper to validate the data in the list or data class is formatted as expected.
+ private void validateDataIsFormatted(String projectPath, String domainName, Map expectedFormatData)
+ {
+ goToProjectHome(projectPath);
+ clickAndWait(Locator.linkWithText(domainName));
+ DataRegionTable dataTable = new DataRegionTable("query", getDriver());
+ Map actualData = dataTable.getRowDataAsMap(0);
+ checker().withScreenshot()
+ .verifyEquals(String.format("Data in '%s' is not formatted as expected.", domainName),
+ expectedFormatData, actualData);
+
+ }
+
+ // Private helper to change the Date-Time formats at the site level to non-standard formats.
+ // This modifies the html of the page to make an option in each field to be of a non-standard format.
+ private void changeSiteDateAndTimeFormats(String dateFormat, String timeFormat)
+ {
+ LookAndFeelSettingsPage lookAndFeelSettingsPage = goToAdminConsole().clickLookAndFeelSettings();
+
+ log(String.format("Chang date format '%s' to have a value of '%s'.", DATE_FORMAT.ddMMMyy, dateFormat));
+ WebElement defaultDate = Locator.id("defaultDateFormat").findElement(getDriver());
+ WebElement optionEl = Locator.tagWithAttribute("option", "value", DATE_FORMAT.ddMMMyy.toString()).findElement(defaultDate);
+ executeScript("arguments[0].value = arguments[1]", optionEl, dateFormat);
+ selectOptionByValue(defaultDate, dateFormat);
+
+ log(String.format("Chang time format '%s' to have a value of '%s'.", TIME_FORMAT.hh_mm_a, timeFormat));
+ WebElement defaultTime = Locator.id("defaultTimeFormat").findElement(getDriver());
+ optionEl = Locator.tagWithAttribute("option", "value", TIME_FORMAT.hh_mm_a.toString()).findElement(defaultTime);
+ executeScript("arguments[0].value = arguments[1]", optionEl, timeFormat);
+ selectOptionByValue(defaultTime, timeFormat);
+
+ log(String.format("Chang DateTime date format '%s' to have a value of '%s'.", DATE_FORMAT.ddMMMyy, dateFormat));
+ WebElement defaultDTDate = Locator.id("dateSelect").findElement(getDriver());
+ optionEl = Locator.tagWithAttribute("option", "value", DATE_FORMAT.ddMMMyy.toString()).findElement(defaultDTDate);
+ executeScript("arguments[0].value = arguments[1]", optionEl, dateFormat);
+ selectOptionByValue(defaultDTDate, dateFormat);
+
+ log(String.format("Chang DateTime time format '%s' to have a value of '%s'.", TIME_FORMAT.hh_mm_a, timeFormat));
+ WebElement defaultDTTime = Locator.id("timeSelect").findElement(getDriver());
+ optionEl = Locator.tagWithAttribute("option", "value", TIME_FORMAT.hh_mm_a.toString()).findElement(defaultDTTime);
+ executeScript("arguments[0].value = arguments[1]", optionEl, timeFormat);
+ selectOptionByValue(defaultDTTime, timeFormat);
+
+ lookAndFeelSettingsPage.save();
+ }
+
+ // Private helper that validates Date, Time and DateTime fields in a domain designer.
+ // isInherited: Used to check the enabled / editable state of the field.
+ // columnType: Used to identify the expected field options and messages.
+ // expectedToolTipText: Used as a check for the warning icon. If null no warning icon is expected.
+ private void validateFieldsInDesigner(DomainFormPanel domainEditor, String fieldName,
+ boolean isInherited, FieldDefinition.ColumnType columnType,
+ String expectedFormat, @Nullable String expectedToolTipText)
+ {
+ DomainFieldRow fieldRow = domainEditor.getField(fieldName);
+ fieldRow.expand();
+
+ if (FieldDefinition.ColumnType.Date.equals(columnType))
+ {
+ if(isInherited)
+ {
+ checker().verifyTrue(String.format("Field '%s' should show as inherited, it does not.", fieldName),
+ fieldRow.isDateInherited());
+
+ checker().verifyFalse(String.format("Field '%s' should not be enabled.", fieldName),
+ fieldRow.isDateFormatEnabled());
+ }
+
+ checker().verifyEquals(String.format("Date format for field '%s' not as expected.", fieldName),
+ expectedFormat, fieldRow.getDateFormat());
+ }
+ else if (FieldDefinition.ColumnType.Time.equals(columnType))
+ {
+
+ if(isInherited)
+ {
+ checker().verifyTrue(String.format("Field '%s' should show as inherited, it does not.", fieldName),
+ fieldRow.isTimeInherited());
+
+ checker().verifyFalse(String.format("Field '%s' should not be enabled.", fieldName),
+ fieldRow.isTimeFormatEnabled());
+ }
+
+ checker().verifyEquals(String.format("Time format for field '%s' not as expected.", fieldName),
+ expectedFormat, fieldRow.getTimeFormat());
+ }
+ else
+ {
+
+ if(isInherited)
+ {
+ checker().verifyTrue(String.format("Field '%s' should show as inherited, it does not.", fieldName),
+ fieldRow.isDateTimeInherited());
+
+ checker().verifyFalse(String.format("Date part of DateTime field '%s' should not be enabled.", fieldName),
+ fieldRow.isDateTimeFormatDateEnabled());
+
+ checker().verifyFalse(String.format("Time part of DateTime field '%s' should not be enabled.", fieldName),
+ fieldRow.isDateTimeFormatTimeEnabled());
+ }
+
+ String expectedDateFormat;
+ String expectedTimeFormat;
+
+ // If expected tooltip text is not null treat the field as a non-standard format field.
+ if (null != expectedToolTipText)
+ {
+ expectedDateFormat = expectedFormat;
+ expectedTimeFormat = TIME_FORMAT.none.toString();
+ }
+ else
+ {
+ // None of the standard dates have a space. The first space will be between the date format and the time format.
+ int index = expectedFormat.indexOf(" ");
+
+ expectedDateFormat = expectedFormat.substring(0, index);
+ expectedTimeFormat = expectedFormat.substring(index+1);
+ }
+
+ checker().verifyEquals(String.format("DateTime Date format for field '%s' not as expected.", fieldName),
+ expectedDateFormat, fieldRow.getDateTimeFormatDate());
+
+ checker().verifyEquals(String.format("DateTime Time format for field '%s' not as expected.", fieldName),
+ expectedTimeFormat, fieldRow.getDateTimeFormatTime());
+ }
+
+ // If expected tooltip text is not null treat the field as a non-standard format field.
+ if (null != expectedToolTipText)
+ {
+ if (checker().verifyTrue("No warning icon present for field with non-standard date-time format.",
+ fieldRow.hasDomainWarningIcon()))
+ {
+ WebElement icon = fieldRow.getDomainWarningIcon();
+ mouseOver(icon);
+ WebElement toolTip = Locator.tagWithClass("div", "tooltip-inner")
+ .withText(expectedToolTipText)
+ .findWhenNeeded(getDriver());
+
+ checker().verifyTrue("Tooltip not present or text not as expected.",
+ waitFor(toolTip::isDisplayed, 1_000));
+ }
+ }
+ else
+ {
+ checker().verifyFalse(String.format("Field '%s' should not have a warning icon present, but one is there.", fieldName),
+ fieldRow.hasDomainWarningIcon());
+ }
+
+ checker().screenShotIfNewError(String.format("Non_Standard_Field_%s_Error", fieldName));
+
+ }
+
+ // These controls are shared across multiple setting pages. It is easier to find them here in the test than to use
+ // the page objects.
+ private String getFormatFromControl(String fieldId)
+ {
+ return getSelectedOptionValue(Locator.id(fieldId).findElement(getDriver()));
+ }
+
+ private boolean getFieldInherited(String fieldName)
+ {
+ return Locator.checkboxByName(fieldName).findElement(getDriver()).isSelected();
+ }
+
+ private boolean getNonStandardWarning(String fieldId)
+ {
+ String xpath = String.format("//select[@id='%s']/following-sibling::span[@class='has-warning']", fieldId);
+ return Locator.xpath(xpath).findWhenNeeded(getDriver()).isDisplayed();
+ }
+
+ // Private helper to check the format settings at the site, project or folder.
+ // Site settings do not inherit, if the inherited parameter is null that check is skipped.
+ private void validateSettingsPage(@Nullable Boolean dateInherited, String dateFormat, boolean dateWarning,
+ @Nullable Boolean timeInherited, String timeFormat, boolean timeWarning,
+ @Nullable Boolean dateTimeInherited, String dtDateFormat, String dtTimeFormat,
+ boolean dtDateWarning, boolean dtTimeWarning)
+ {
+
+ log("Check Date field settings.");
+
+ checker().verifyEquals("Format of Default Date is not as expected.",
+ dateFormat, getFormatFromControl("defaultDateFormat"));
+
+ if (null != dateInherited)
+ {
+ checker().verifyEquals("Inherited value for Date format not as expected.",
+ dateInherited, getFieldInherited("defaultDateFormatInherited"));
+ }
+
+ checker().verifyEquals("Non-standard warning for Date field not as expected.",
+ dateWarning, getNonStandardWarning("defaultDateFormat"));
+
+
+ log("Check Time field settings.");
+
+ checker().verifyEquals("Format of Default Time is not as expected.",
+ timeFormat, getFormatFromControl("defaultTimeFormat"));
+
+ if (null != timeInherited)
+ {
+ checker().verifyEquals("Inherited value for Time format not as expected.",
+ timeInherited, getFieldInherited("defaultTimeFormatInherited"));
+ }
+
+ checker().verifyEquals("Non-standard warning for Time field not as expected.",
+ timeWarning, getNonStandardWarning("defaultTimeFormat"));
+
+
+ log("Check DateTime field settings.");
+
+ checker().verifyEquals("Format of Default DateTime (Date) is not as expected.",
+ dtDateFormat, getFormatFromControl("dateSelect"));
+
+ checker().verifyEquals("Format of Default DateTime (Time) is not as expected.",
+ dtTimeFormat, getFormatFromControl("timeSelect"));
+
+ if (null != dateTimeInherited)
+ {
+ checker().verifyEquals("Inherited value for DateTime format not as expected.",
+ dateTimeInherited, getFieldInherited("defaultDateTimeFormatInherited"));
+ }
+
+ checker().verifyEquals("Non-standard warning for DateTime (Date) not as expected.",
+ dtDateWarning, getNonStandardWarning("dateSelect"));
+
+ checker().verifyEquals("Non-standard warning for DateTime (Time) not as expected.",
+ dtTimeWarning, getNonStandardWarning("timeSelect"));
+
+ checker().screenShotIfNewError("Settings_Page_Error");
+ }
+
+ // Private helper to check the Site Validation report. Checks to see if the report should, or should not, contain
+ // the list of warnings.
+ private void validateSiteValidationReport(String scope, List expectedWarnings, boolean shouldContain)
+ {
+ List actualWarnings = getProjectValidationWarnings(scope);
+
+ log("Found Warnings: " + actualWarnings);
+
+ if (shouldContain)
+ {
+ log("Should Contain Warnings: " + expectedWarnings);
+
+ if (checker().withScreenshot()
+ .verifyFalse(String.format("Found no Site Validation warnings under '%s'.", scope),
+ actualWarnings.isEmpty()))
+ {
+ checker().verifyTrue("Did not find the expected warnings in the 'Site Validation' report.",
+ actualWarnings.containsAll(expectedWarnings));
+
+ }
+ }
+ else
+ {
+ log("Should Not Contain Warnings: " + expectedWarnings);
+
+ boolean shouldBeFalse = actualWarnings.stream()
+ .anyMatch(expectedWarnings::contains);
+
+ checker().withScreenshot()
+ .verifyFalse("Found Site Validation warning(s) that should not be there.",
+ shouldBeFalse);
+ }
+
+ checker().screenShotIfNewError("Site_Validation_Error");
+ }
+
+ // Private helper that gets the data from the Site Validation page, narrowed to the scope provided, and cleans it up a bit.
+ private List getProjectValidationWarnings(String scope)
+ {
+
+ URLBuilder urlBuilder = new URLBuilder("admin", "configureSiteValidation");
+ String url = urlBuilder.buildRelativeURL();
+ beginAt(url);
+
+ waitForElementToBeVisible(Locator.lkButton("Validate"));
+
+ // Disable all validators.
+ Locator.tagWithAttribute("input", "type", "checkbox")
+ .findElements(getDriver()).forEach(this::uncheckCheckbox);
+
+ // Enable Display Format validator.
+ WebElement formatValidation = Locator.checkboxByNameAndValue("providers", "Display Format Validator").findWhenNeeded(getDriver());
+ checkCheckbox(formatValidation);
+
+ // Validate projects and sub-folders.
+ checkRadioButton(Locator.radioButtonByNameAndValue("includeSubfolders", "true"));
+
+ // Don't run in the background.
+ uncheckCheckbox(Locator.id("background"));
+
+ clickAndWait(Locator.lkButton("Validate"));
+
+ waitForText("Folder Validation Results");
+
+ String xpath = String.format("//li[contains(text(),'%s')]//li[contains(text(),'Warnings:')]//ul", scope);
+ WebElement ul = Locator.xpath(xpath).findWhenNeeded(getDriver());
+
+ List warnings = new ArrayList<>();
+ int linkTextLength = " more info".length();
+
+ if (ul.isDisplayed())
+ {
+ // Get the text of the warnings and trim off the 'More Info' link.
+ warnings = ul.findElements(Locator.tag("li"))
+ .stream()
+ .map(el->el.getText().trim().substring(0, el.getText().length() - linkTextLength)).toList();
+ }
+
+ return warnings;
+ }
+
+}
diff --git a/src/org/labkey/test/tests/ProjectSettingsTest.java b/src/org/labkey/test/tests/ProjectSettingsTest.java
index 63b27805cf..1de201af03 100644
--- a/src/org/labkey/test/tests/ProjectSettingsTest.java
+++ b/src/org/labkey/test/tests/ProjectSettingsTest.java
@@ -17,7 +17,6 @@
import org.junit.AfterClass;
import org.junit.BeforeClass;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.labkey.remoteapi.CommandException;
@@ -28,12 +27,15 @@
import org.labkey.test.components.html.BootstrapMenu;
import org.labkey.test.components.html.SiteNavBar;
import org.labkey.test.pages.core.admin.BaseSettingsPage;
+import org.labkey.test.pages.core.admin.BaseSettingsPage.DATE_FORMAT;
+import org.labkey.test.pages.core.admin.BaseSettingsPage.TIME_FORMAT;
import org.labkey.test.pages.core.admin.LookAndFeelSettingsPage;
import org.labkey.test.pages.core.admin.ProjectSettingsPage;
import org.labkey.test.params.FieldDefinition;
import org.labkey.test.params.FieldDefinition.ColumnType;
import org.labkey.test.params.list.IntListDefinition;
import org.labkey.test.params.list.ListDefinition;
+import org.labkey.test.util.APIContainerHelper;
import org.labkey.test.util.DataRegionTable;
import org.labkey.test.util.PortalHelper;
import org.labkey.test.util.TestDataGenerator;
@@ -55,8 +57,8 @@
public class ProjectSettingsTest extends BaseWebDriverTest
{
- private static final BaseSettingsPage.DATE_FORMAT DEFAULT_DATE_FORMAT = BaseSettingsPage.DATE_FORMAT.Default;
- private static final BaseSettingsPage.TIME_FORMAT DEFAULT_TIME_FORMAT = BaseSettingsPage.TIME_FORMAT.Default;
+ private static final DATE_FORMAT DEFAULT_DATE_FORMAT = DATE_FORMAT.Default;
+ private static final TIME_FORMAT DEFAULT_TIME_FORMAT = TIME_FORMAT.Default;
private static final String INJECT_CHARS = "";
@@ -125,8 +127,8 @@ private boolean checkDataInList(String projectName, String listName, List