diff --git a/src/org/labkey/test/pages/core/admin/OptionalFeaturesPage.java b/src/org/labkey/test/pages/core/admin/OptionalFeaturesPage.java new file mode 100644 index 0000000000..49948af620 --- /dev/null +++ b/src/org/labkey/test/pages/core/admin/OptionalFeaturesPage.java @@ -0,0 +1,80 @@ +package org.labkey.test.pages.core.admin; + +import org.labkey.test.Locator; +import org.labkey.test.WebDriverWrapper; +import org.labkey.test.WebTestHelper; +import org.labkey.test.components.html.Checkbox; +import org.labkey.test.pages.LabKeyPage; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/* + Wraps Optional Features, Experimental Features, Deprecated Features pages linked + from Admin Console + */ +public class OptionalFeaturesPage extends LabKeyPage +{ + public OptionalFeaturesPage(WebDriver driver) + { + super(driver); + } + + public static OptionalFeaturesPage beginAt(WebDriverWrapper webDriverWrapper, OptionalFeatureType featureType) + { + webDriverWrapper.beginAt(WebTestHelper.buildURL("admin", "/", "optionalFeatures", Map.of("Type", featureType.toString()))); + return new OptionalFeaturesPage(webDriverWrapper.getDriver()); + } + + @Override + protected void waitForPage() + { + waitFor(()-> elementCache().listGroupLoc.findWhenNeeded(getDriver()).isDisplayed(), + "The page did not render in time", WAIT_FOR_JAVASCRIPT); + } + + public ShowAdminPage goToAdminConsole() + { + clickAndWait(Locator.linkWithText("Admin Console")); + return new ShowAdminPage(getDriver()); + } + + public boolean getFeatureStatus(String id) + { + return elementCache().getCheckboxById(id).get(); + } + + public OptionalFeaturesPage setFeatureStatus(String id, boolean status) + { + elementCache().getCheckboxById(id).set(status); + return this; + } + + @Override + protected ElementCache newElementCache() + { + return new ElementCache(); + } + + protected class ElementCache extends LabKeyPage.ElementCache + { + public final Locator.XPathLocator listGroupLoc = Locator.tagWithClass("div", "list-group"); + public final WebElement listGroupElement = listGroupLoc.waitForElement(getDriver(), 1500); + public final Locator listItemLabelLoc = Locator.tagWithClass("div", "list-group-item") + .child(Locator.tag("Label")); + + public Checkbox getCheckboxById(String id) + { + return Checkbox.Checkbox(Locator.id(id)).waitFor(listGroupElement); + } + } + + public enum OptionalFeatureType{ + Experimental, + Optional, + Deprecated + } +} diff --git a/src/org/labkey/test/tests/AdminConsoleTest.java b/src/org/labkey/test/tests/AdminConsoleTest.java index 756af7106d..d692fce1bb 100644 --- a/src/org/labkey/test/tests/AdminConsoleTest.java +++ b/src/org/labkey/test/tests/AdminConsoleTest.java @@ -15,6 +15,7 @@ */ package org.labkey.test.tests; +import org.assertj.core.api.Assertions; import org.junit.Test; import org.junit.experimental.categories.Category; import org.labkey.remoteapi.CommandException; @@ -25,13 +26,16 @@ import org.labkey.test.Locator; import org.labkey.test.WebDriverWrapper; import org.labkey.test.WebTestHelper; +import org.labkey.test.util.OptionalFeatureHelper; import org.labkey.test.categories.Daily; import org.labkey.test.pages.core.admin.CustomizeSitePage; +import org.labkey.test.pages.core.admin.OptionalFeaturesPage; import org.labkey.test.pages.core.login.LoginConfigRow; import org.labkey.test.pages.core.login.LoginConfigurePage; import org.labkey.test.util.LogMethod; import java.io.IOException; +import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -226,6 +230,26 @@ public void testSiteBannerAPIConfiguration() throws Exception .verifyFalse("expect banner not to be shown", bannerLoc.isDisplayed(getDriver())); } + @Test + public void testUIOptionalFeatures() + { + goToAdminConsole(); + + var featureIds = List.of("extendedMetrics", "StageFileUploads"); + + verifyOptionalFeatures("optional features", featureIds, OptionalFeaturesPage.OptionalFeatureType.Optional); + } + + @Test + public void testUIExperimentalFeatures() + { + goToAdminConsole(); + + var featureIds = List.of("queryBasedDatasets", "LinkedDatasetCheck", "blockMaliciousClients"); + + verifyOptionalFeatures("experimental features", featureIds, OptionalFeaturesPage.OptionalFeatureType.Experimental); + } + @Test public void testAppAdminRole() { @@ -357,4 +381,41 @@ public void testAdminConsoleCredits() log("Verifying the page is properly loaded"); assertTextPresent("JAR Files Distributed with the API Module"); } + + private void verifyOptionalFeatures(String linkText, List featureIds, OptionalFeaturesPage.OptionalFeatureType optionalFeatureType) + { + waitAndClickAndWait(Locator.linkWithText(linkText)); + var optionalFeaturesPage = new OptionalFeaturesPage(getDriver()); + var cn = createDefaultConnection(); + + for (String testId : featureIds) { + // capture initial state + boolean initialState = OptionalFeatureHelper.isOptionalFeatureEnabled(cn, testId); + + // ensure the UI reflects the same state + boolean initialUIState = optionalFeaturesPage.getFeatureStatus(testId); + checker().withScreenshot("initial state not as expected") + .wrapAssertion(()-> Assertions.assertThat(initialUIState) + .as("expect ui to align with API initial state") + .isEqualTo(initialState)); + + // toggle it the other way + optionalFeaturesPage.setFeatureStatus(testId, !initialState); + checker().withScreenshot("toggled state not as expected") + .awaiting(Duration.ofMillis(500), ()-> Assertions.assertThat(OptionalFeatureHelper.isOptionalFeatureEnabled(cn, testId)) + .as("expect toggling the UI to update the server status for the feature") + .isEqualTo(!initialState)); + + // use the API to restore the initial state + OptionalFeatureHelper.setOptionalFeature(cn, testId, initialState); + optionalFeaturesPage.goToAdminConsole(); + + optionalFeaturesPage = OptionalFeaturesPage.beginAt(this, optionalFeatureType); + + // verify the page state reflects the API change after a reload + checker().withScreenshot("state not as expected after api set and refresh") + .verifyEquals("expect page to reflect state after api config", + initialState, optionalFeaturesPage.getFeatureStatus(testId)); + } + } }