diff --git a/src/org/labkey/test/pages/LabkeyErrorPage.java b/src/org/labkey/test/pages/LabkeyErrorPage.java
index 49937d6cb4..b9b415419d 100644
--- a/src/org/labkey/test/pages/LabkeyErrorPage.java
+++ b/src/org/labkey/test/pages/LabkeyErrorPage.java
@@ -51,6 +51,12 @@ public String getErrorImage()
{
return elementCache().errorImage.getAttribute("src");
}
+
+ public boolean isShowDetailsPresent()
+ {
+ return !Locator.button("View Details").findElements(getDriver()).isEmpty();
+ }
+
@Override
protected ElementCache newElementCache()
{
diff --git a/src/org/labkey/test/pages/compliance/ComplianceLoginSettingsPage.java b/src/org/labkey/test/pages/compliance/ComplianceLoginSettingsPage.java
index a7a08d90aa..2892a3e32e 100644
--- a/src/org/labkey/test/pages/compliance/ComplianceLoginSettingsPage.java
+++ b/src/org/labkey/test/pages/compliance/ComplianceLoginSettingsPage.java
@@ -35,6 +35,11 @@ public void disableLoginControls()
shortWait().until(wd -> !elementCache().loginAttemptCountCombo.isEnabled());
}
+ public boolean isLoginLimitEnabled()
+ {
+ return elementCache().enableLoginChk.isSelected();
+ }
+
public void setLoginAttemptCount(String count)
{
setFormElement(elementCache().loginAttemptCountInput, count);
@@ -45,6 +50,21 @@ public void selectLoginAttemptCount(String count)
elementCache().loginAttemptCountCombo.selectComboBoxItem(count);
}
+ public String getLoginAttemptCount()
+ {
+ return getFormElement(elementCache().loginAttemptCountInput);
+ }
+
+ public String getLoginAttemptPeriod()
+ {
+ return getFormElement(elementCache().loginAttemptPeriodInput);
+ }
+
+ public String getLoginAttemptRecoveryTime()
+ {
+ return getFormElement(elementCache().loginAttemptRecoveryTimeInput);
+ }
+
public void selectLoginAttemptPeriod(String period)
{
elementCache().loginAttemptPeriodCombo.selectComboBoxItem(period);
diff --git a/src/org/labkey/test/tests/LabkeyErrorPageTest.java b/src/org/labkey/test/tests/LabkeyErrorPageTest.java
index 4f05da9bb2..0cbfddf7fe 100644
--- a/src/org/labkey/test/tests/LabkeyErrorPageTest.java
+++ b/src/org/labkey/test/tests/LabkeyErrorPageTest.java
@@ -45,6 +45,8 @@ public void testGeneralErrors()
checker().verifyEquals("Incorrect error heading message", "404: page not found",
errorPage.getErrorHeading());
checker().verifyThat("Incorrect error image", errorPage.getErrorImage(), CoreMatchers.containsString(imageTitle));
+ checker().verifyTrue("'Show Details' button should appear on not found error page",
+ errorPage.isShowDetailsPresent());
beginAt(WebTestHelper.buildRelativeUrl("project", getCurrentContainerPath(), "beginning"));
errorPage = new LabkeyErrorPage(getDriver());
@@ -88,6 +90,8 @@ public void testServerConfigurationErrors()
checker().verifyEquals("Incorrect error sub-heading message", "The requested page cannot be found. You have a configuration problem.",
errorPage.getSubErrorHeading());
checker().verifyThat("Incorrect error image", errorPage.getErrorImage(), CoreMatchers.containsString(imageTitle));
+ checker().verifyTrue("'Show Details' button should appear on configuration error page",
+ errorPage.isShowDetailsPresent());
checkExpectedErrors(1);
}
@@ -103,9 +107,11 @@ public void testExecutionErrors()
checker().verifyEquals("Incorrect error heading message", "Oops! An error has occurred.",
errorPage.getErrorHeading());
checker().verifyEquals("Incorrect error instructions", "You can find help resources here and may " +
- "find troubleshooting hints by reading the full stack trace in the View Details section below.",
+ "find troubleshooting hints by reading the full stack trace in the server logs.",
errorPage.getErrorInstruction());
checker().verifyThat("Incorrect error image", errorPage.getErrorImage(), CoreMatchers.containsString(imageTitle));
+ checker().verifyFalse("'Show Details' button should not appear on execution error page",
+ errorPage.isShowDetailsPresent());
checkExpectedErrors(2);
}
diff --git a/src/org/labkey/test/tests/upgrade/BaseUpgradeTest.java b/src/org/labkey/test/tests/upgrade/BaseUpgradeTest.java
index a7e3b20568..12e1e2bc29 100644
--- a/src/org/labkey/test/tests/upgrade/BaseUpgradeTest.java
+++ b/src/org/labkey/test/tests/upgrade/BaseUpgradeTest.java
@@ -50,13 +50,23 @@ public static void setupProject() throws Exception
{
BaseUpgradeTest currentTest = BaseWebDriverTest.getCurrentTest();
+ Class> testClass = currentTest.getClass();
+ String earliestVersion = Optional.ofNullable(testClass.getAnnotation(EarliestVersion.class))
+ .map(EarliestVersion::value).orElse(null);
+ String latestVersion = Optional.ofNullable(testClass.getAnnotation(LatestVersion.class))
+ .map(LatestVersion::value).orElse(null);
+
+ Assume.assumeTrue("Test class not valid when upgrading from version: " + setupVersion,
+ VersionRange.versionRange(earliestVersion, latestVersion).contains(setupVersion)
+ );
+
if (isUpgradeSetupPhase)
{
currentTest.doSetup();
}
else
{
- TestLogger.info("Skipping setup for %s. Verifying upgrade.". formatted(currentTest.getClass().getSimpleName()));
+ TestLogger.info("Skipping setup for %s. Verifying upgrade.". formatted(testClass.getSimpleName()));
}
}
@@ -100,19 +110,19 @@ protected boolean wasSetupWithin(String earliestVersion, String latestVersion)
* Specifies the earliest version of the test class that performed the required setup for the annotated method.
*/
@Retention(RetentionPolicy.RUNTIME)
- @Target({ElementType.METHOD})
+ @Target({ElementType.METHOD, ElementType.TYPE})
protected @interface EarliestVersion
{
String value();
}
/**
- * Annotates test methods that should only run when upgrading from particular LabKey versions, as specified in
- * {@code webtest.upgradePreviousVersion}.
- * Specifies the latest version of the test class that performed the required setup for the annotated method.
+ * Annotates test methods or classes that should only run when upgrading from particular LabKey versions, as
+ * specified in {@code webtest.upgradePreviousVersion}.
+ * Specifies the latest version of the test class that performed the required setup for the annotated method or class.
*/
@Retention(RetentionPolicy.RUNTIME)
- @Target({ElementType.METHOD})
+ @Target({ElementType.METHOD, ElementType.TYPE})
protected @interface LatestVersion {
String value();
}
diff --git a/src/org/labkey/test/util/VersionRange.java b/src/org/labkey/test/util/VersionRange.java
index 865974783e..083c425336 100644
--- a/src/org/labkey/test/util/VersionRange.java
+++ b/src/org/labkey/test/util/VersionRange.java
@@ -14,15 +14,13 @@ public class VersionRange
*
* @param earliestVersion The earliest version in the range (inclusive). If null, there is no lower bound.
* @param latestVersion The latest version in the range (inclusive). If null, there is no upper bound.
- * @throws IllegalArgumentException if both versions are null, or if earliestVersion is after latestVersion.
+ * @throws IllegalArgumentException if earliestVersion is after latestVersion.
*/
public VersionRange(Version earliestVersion, Version latestVersion)
{
this.earliestVersion = earliestVersion;
this.latestVersion = latestVersion;
- if (earliestVersion == null && latestVersion == null)
- throw new IllegalArgumentException("Version range requires at least one version");
if (earliestVersion != null && latestVersion != null && earliestVersion.compareTo(latestVersion) > 0)
throw new IllegalArgumentException("%s is after %s".formatted(earliestVersion, latestVersion));