From 69c0be803c65fad07ce00635669993e45e859c5b Mon Sep 17 00:00:00 2001
From: labkey-sweta
Date: Thu, 24 Apr 2025 11:57:12 -0700
Subject: [PATCH 01/13] Issue 51524: Allowlist for acceptable types of file
upload - automated tests
---
.../admin/AllowedFileExtensionAdminPage.java | 102 +++++++++++
.../test/pages/core/admin/ShowAdminPage.java | 8 +
.../admin/AllowedFileExtensionAdminTest.java | 163 ++++++++++++++++++
.../labkey/test/util/FileBrowserHelper.java | 28 ++-
4 files changed, 293 insertions(+), 8 deletions(-)
create mode 100644 src/org/labkey/test/pages/core/admin/AllowedFileExtensionAdminPage.java
create mode 100644 src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java
diff --git a/src/org/labkey/test/pages/core/admin/AllowedFileExtensionAdminPage.java b/src/org/labkey/test/pages/core/admin/AllowedFileExtensionAdminPage.java
new file mode 100644
index 0000000000..4d573e3595
--- /dev/null
+++ b/src/org/labkey/test/pages/core/admin/AllowedFileExtensionAdminPage.java
@@ -0,0 +1,102 @@
+package org.labkey.test.pages.core.admin;
+
+import org.labkey.test.Locator;
+import org.labkey.test.Locators;
+import org.labkey.test.WebDriverWrapper;
+import org.labkey.test.WebTestHelper;
+import org.labkey.test.components.html.Input;
+import org.labkey.test.pages.LabKeyPage;
+import org.labkey.test.util.PortalHelper;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+
+public class AllowedFileExtensionAdminPage extends LabKeyPage
+{
+ public AllowedFileExtensionAdminPage(WebDriver driver)
+ {
+ super(driver);
+ }
+
+ public static AllowedFileExtensionAdminPage beginAt(WebDriverWrapper webDriverWrapper)
+ {
+ webDriverWrapper.beginAt(WebTestHelper.buildURL("admin", "allowList"));
+ return new AllowedFileExtensionAdminPage(webDriverWrapper.getDriver());
+ }
+
+ public AllowedFileExtensionAdminPage setExtension(String extension)
+ {
+ elementCache().extension.set(extension);
+ return this;
+ }
+
+ public String clickSaveExpectingError()
+ {
+ elementCache().saveExtension.click();
+ clearCache();
+ return waitForElement(Locators.labkeyError).getText();
+ }
+
+ public AllowedFileExtensionAdminPage clickSaveExtension()
+ {
+ elementCache().saveExtension.click();
+ clearCache();
+ return this;
+ }
+
+ public AllowedFileExtensionAdminPage updateExtension(String oldExtension, String newExtension)
+ {
+ elementCache().allowedExtension(oldExtension).set(newExtension);
+ clearCache();
+ return this;
+ }
+
+ public AllowedFileExtensionAdminPage deleteExtension(int index)
+ {
+ elementCache().deleteExtension(index);
+ clearCache();
+ return this;
+ }
+
+ public AllowedFileExtensionAdminPage clickUpdateExtension()
+ {
+ elementCache().updateExtension.click();
+ clearCache();
+ return this;
+ }
+
+ public String clickUpdateExtensionExpectingError()
+ {
+ elementCache().updateExtension.click();
+ clearCache();
+ return waitForElement(Locators.labkeyError).getText();
+ }
+
+ @Override
+ protected ElementCache newElementCache()
+ {
+ return new ElementCache();
+ }
+
+ protected class ElementCache extends LabKeyPage.ElementCache
+ {
+ final WebElement registerNewAllowedFileExtension = PortalHelper.Locators.webPart("Register New Allowed File Extension")
+ .findWhenNeeded(this);
+ final Input extension = new Input(Locator.name("newValue").findWhenNeeded(registerNewAllowedFileExtension), getDriver());
+ final WebElement saveExtension = Locator.lkButton("Save").findWhenNeeded(registerNewAllowedFileExtension);
+
+ final WebElement existingAllowedFileExtensions = PortalHelper.Locators.webPart("Existing Allowed File Extensions")
+ .findWhenNeeded(this);
+ final WebElement updateExtension = Locator.lkButton("Save").findWhenNeeded(existingAllowedFileExtensions);
+
+ final Input allowedExtension(String value)
+ {
+ return new Input(Locator.inputByIdContaining("existingValue").withAttribute("value", value)
+ .findWhenNeeded(existingAllowedFileExtensions), getDriver());
+ }
+
+ final WebElement deleteExtension(int index)
+ {
+ return Locator.linkWithText("Delete").index(index).findWhenNeeded(existingAllowedFileExtensions);
+ }
+ }
+}
diff --git a/src/org/labkey/test/pages/core/admin/ShowAdminPage.java b/src/org/labkey/test/pages/core/admin/ShowAdminPage.java
index a23ee09e45..31e36ab2e1 100644
--- a/src/org/labkey/test/pages/core/admin/ShowAdminPage.java
+++ b/src/org/labkey/test/pages/core/admin/ShowAdminPage.java
@@ -99,6 +99,13 @@ public ShowAuditLogPage clickAuditLog()
return new ShowAuditLogPage(getDriver());
}
+ public AllowedFileExtensionAdminPage clickAllowedFileExtensions()
+ {
+ goToSettingsSection();
+ clickAndWait(elementCache().allowedFileExtensionLink);
+ return new AllowedFileExtensionAdminPage(getDriver());
+ }
+
public void clickAuditLogMaintenance()
{
goToSettingsSection();
@@ -274,6 +281,7 @@ protected class ElementCache extends LabKeyPage.ElementCache
protected WebElement analyticsSettingsLink = Locator.linkWithText("analytics settings").findWhenNeeded(this);
protected WebElement externalRedirectHostLink = Locator.linkWithText("allowed external redirect hosts").findElement(this);
+ protected WebElement allowedFileExtensionLink = Locator.linkWithText("allowed file extensions").findElement(this);
protected WebElement auditLogLink = Locator.linkWithText("audit log").findWhenNeeded(this);
protected WebElement auditLogMaintenanceLink = Locator.linkWithText("Audit Log Maintenance").findWhenNeeded(this);
protected WebElement authenticationLink = Locator.linkWithText("authentication").findWhenNeeded(this);
diff --git a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java
new file mode 100644
index 0000000000..cedee08547
--- /dev/null
+++ b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java
@@ -0,0 +1,163 @@
+package org.labkey.test.tests.core.admin;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.labkey.remoteapi.CommandException;
+import org.labkey.remoteapi.SimplePostCommand;
+import org.labkey.test.BaseWebDriverTest;
+import org.labkey.test.Locator;
+import org.labkey.test.TestFileUtils;
+import org.labkey.test.categories.Git;
+import org.labkey.test.components.ext4.Window;
+import org.labkey.test.pages.core.admin.AllowedFileExtensionAdminPage;
+import org.labkey.test.params.FieldDefinition;
+import org.labkey.test.params.list.IntListDefinition;
+import org.labkey.test.util.Ext4Helper;
+import org.labkey.test.util.PortalHelper;
+import org.labkey.test.util.TestDataGenerator;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.labkey.test.util.exp.SampleTypeAPIHelper.SAMPLE_TYPE_DOMAIN_KIND;
+
+@Category({Git.class})
+public class AllowedFileExtensionAdminTest extends BaseWebDriverTest
+{
+ private final File EXCEL_DATA_FILE = TestFileUtils.getSampleData("dataLoading/excel/fruits.xls");
+ private final File TSV_DATA_FILE = TestFileUtils.getSampleData("dataLoading/excel/fruits.tsv");
+ private final File TXT_DATA_FILE = TestFileUtils.getSampleData("survey/TestAttachment.txt");
+
+ @BeforeClass
+ public static void setupProject()
+ {
+ AllowedFileExtensionAdminTest init = getCurrentTest();
+ init.doSetup();
+ }
+
+ @Override
+ protected void doCleanup(boolean afterTest)
+ {
+ _containerHelper.deleteProject(getProjectName(), afterTest);
+ deleteAllAllowedFileExtension();
+ }
+
+ private void doSetup()
+ {
+ _containerHelper.createProject(getProjectName(), null);
+
+ goToProjectHome();
+ new PortalHelper(getDriver()).addWebPart("Files");
+ new PortalHelper(getDriver()).addWebPart("Sample Types");
+ }
+
+ @Test
+ public void testAllowedFileExtensionsInLists() throws IOException, CommandException
+ {
+ log("Verify and set allowed file extensions in admin console");
+ AllowedFileExtensionAdminPage allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
+ Assert.assertEquals("Incorrect error message for invalid extension", "File extension must start with a '.'",
+ allowedFileExtensionAdminPage.setExtension("jpg").clickSaveExpectingError());
+ allowedFileExtensionAdminPage.setExtension(".xls").clickSaveExtension().clickUpdateExtension();
+ Assert.assertEquals("Incorrect error message for duplicate extension", "'.xls' already exists. Duplicate values not allowed.",
+ allowedFileExtensionAdminPage.setExtension(".xls").clickSaveExpectingError());
+
+ log("Create a list with attachment field");
+ goToProjectHome();
+ String listName = "ListWithAttachments";
+ new IntListDefinition(listName, "List_key")
+ .setFields(List.of(new FieldDefinition("File_Upload_1", FieldDefinition.ColumnType.Attachment)))
+ .create(createDefaultConnection(), getProjectName());
+
+ goToManageLists();
+ waitAndClickAndWait(Locator.linkWithText(listName));
+ _listHelper.insertNewRow(Map.of("File_Upload_1", EXCEL_DATA_FILE.getAbsolutePath()), false);
+
+
+ //import from file.
+
+ }
+
+ @Test
+ public void testAllowedFileExtensionsInSampleType() throws IOException, CommandException
+ {
+ log("Set allowed file extensions in admin console");
+ AllowedFileExtensionAdminPage allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
+ allowedFileExtensionAdminPage.setExtension("tsv").clickSaveExtension().clickUpdateExtension();
+
+ FieldDefinition.LookupInfo lookupInfo = new FieldDefinition.LookupInfo(getProjectName(), "exp.materials", "Sample type Testing");
+ TestDataGenerator dgen = new TestDataGenerator(lookupInfo)
+ .withColumns(List.of(
+ new FieldDefinition("name", FieldDefinition.ColumnType.String),
+ new FieldDefinition("File_Upload_1", FieldDefinition.ColumnType.File)
+ ));
+ dgen.createDomain(createDefaultConnection(), SAMPLE_TYPE_DOMAIN_KIND);
+ }
+
+ @Test
+ public void testAllowedFileExtensionsInFileBrowser()
+ {
+ log("Set allowed file extensions in admin console");
+ deleteAllAllowedFileExtension();
+ AllowedFileExtensionAdminPage allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
+ allowedFileExtensionAdminPage.setExtension(".txt").clickSaveExtension().clickUpdateExtension();
+
+ log("Verify upload of .txt is successful");
+ goToProjectHome();
+ _fileBrowserHelper.uploadFile(TXT_DATA_FILE);
+ Assert.assertTrue(_fileBrowserHelper.fileIsPresent(TXT_DATA_FILE.getName()));
+
+ log("Verify upload of .tsv fails");
+ Window errorWindow = _fileBrowserHelper.uploadFileExpectingError(TSV_DATA_FILE);
+ Assert.assertEquals(".tsv is not a valid extension", "This file type [tsv] is not allowed.", errorWindow.getBody());
+ click(Ext4Helper.Locators.ext4Button("OK"));
+
+ log("Update the allowed file extension from .txt to .tsv");
+ allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
+ allowedFileExtensionAdminPage.updateExtension(".txt", ".tsv").clickUpdateExtension();
+ sleep(500);
+
+ log("Verify upload of .tsv is successful");
+ goToProjectHome();
+ _fileBrowserHelper.uploadFile(TSV_DATA_FILE);
+ Assert.assertTrue(_fileBrowserHelper.fileIsPresent(TSV_DATA_FILE.getName()));
+ }
+
+ private void deleteAllAllowedFileExtension()
+ {
+ SimplePostCommand command = new SimplePostCommand("admin", "deleteAllValues");
+ Map params = new HashMap<>();
+ params.put("type", "FileExtension");
+ command.setParameters(params);
+ try
+ {
+ command.execute(createDefaultConnection(), "/");
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ catch (CommandException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected String getProjectName()
+ {
+ return "AllowedFileExtensionAdminTest Project " + TRICKY_CHARACTERS_FOR_PROJECT_NAMES;
+ }
+
+ @Override
+ public List getAssociatedModules()
+ {
+ return Arrays.asList();
+ }
+}
diff --git a/src/org/labkey/test/util/FileBrowserHelper.java b/src/org/labkey/test/util/FileBrowserHelper.java
index 98837af563..c01e1746b8 100644
--- a/src/org/labkey/test/util/FileBrowserHelper.java
+++ b/src/org/labkey/test/util/FileBrowserHelper.java
@@ -550,14 +550,7 @@ public void uploadFile(@LoggedParam final File file, @Nullable String descriptio
{
int initialCount = waitForFileGridReady();
- openUploadPanel();
-
- waitFor(() -> getFormElement(Locator.xpath("//label[text() = 'Choose a File:']/../..//input[contains(@class, 'x4-form-field')]")).isEmpty(),
- "Upload field did not clear after upload.", WAIT_FOR_JAVASCRIPT);
-
- setFormElement(Locator.css(".single-upload-panel input:last-of-type[type=file]"), file);
- waitFor(() -> getFormElement(Locator.xpath("//label[text() = 'Choose a File:']/../..//input[contains(@class, 'x4-form-field')]")).contains(file.getName()),
- "Upload field was not set to '" + file.getName() + "'.", WAIT_FOR_JAVASCRIPT);
+ setChooseAFile(file);
if (description != null)
setFormElement(Locator.name("description"), description);
@@ -602,6 +595,25 @@ public void uploadFile(@LoggedParam final File file, @Nullable String descriptio
assertEquals("Description didn't clear after upload", "", getFormElement(Locator.name("description")));
}
+ @LogMethod
+ public Window uploadFileExpectingError(File file)
+ {
+ waitForFileGridReady();
+ setChooseAFile(file);
+ clickButton("Upload", WAIT_FOR_EXT_MASK_TO_DISSAPEAR);
+ return new Window.WindowFinder(getDriver()).withTitle("Error").waitFor();
+ }
+
+ private void setChooseAFile(File file)
+ {
+ openUploadPanel();
+ waitFor(() -> getFormElement(Locator.xpath("//label[text() = 'Choose a File:']/../..//input[contains(@class, 'x4-form-field')]")).isEmpty(),
+ "Upload field did not clear after upload.", WAIT_FOR_JAVASCRIPT);
+ setFormElement(Locator.css(".single-upload-panel input:last-of-type[type=file]"), file);
+ waitFor(() -> getFormElement(Locator.xpath("//label[text() = 'Choose a File:']/../..//input[contains(@class, 'x4-form-field')]")).contains(file.getName()),
+ "Upload field was not set to '" + file.getName() + "'.", WAIT_FOR_JAVASCRIPT);
+ }
+
private void dragAndDropFileInDropZone(File file)
{
//Offsets for the drop zone
From e17dfa3498d4f391d287107aa481522dcb5bd55b Mon Sep 17 00:00:00 2001
From: labkey-danield
Date: Thu, 1 May 2025 19:09:21 -0700
Subject: [PATCH 02/13] Reworking some of the allowed file extension tests.
---
.../admin/AllowedFileExtensionAdminPage.java | 133 ++++++--
.../admin/AllowedFileExtensionAdminTest.java | 293 ++++++++++++++----
2 files changed, 347 insertions(+), 79 deletions(-)
diff --git a/src/org/labkey/test/pages/core/admin/AllowedFileExtensionAdminPage.java b/src/org/labkey/test/pages/core/admin/AllowedFileExtensionAdminPage.java
index 4d573e3595..20404a41df 100644
--- a/src/org/labkey/test/pages/core/admin/AllowedFileExtensionAdminPage.java
+++ b/src/org/labkey/test/pages/core/admin/AllowedFileExtensionAdminPage.java
@@ -1,5 +1,6 @@
package org.labkey.test.pages.core.admin;
+import org.labkey.test.BootstrapLocators;
import org.labkey.test.Locator;
import org.labkey.test.Locators;
import org.labkey.test.WebDriverWrapper;
@@ -7,8 +8,15 @@
import org.labkey.test.components.html.Input;
import org.labkey.test.pages.LabKeyPage;
import org.labkey.test.util.PortalHelper;
+import org.openqa.selenium.NoSuchElementException;
+import org.openqa.selenium.StaleElementReferenceException;
+import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
+import org.openqa.selenium.support.ui.ExpectedConditions;
+
+import java.util.List;
+import java.util.stream.Collectors;
public class AllowedFileExtensionAdminPage extends LabKeyPage
{
@@ -23,6 +31,23 @@ public static AllowedFileExtensionAdminPage beginAt(WebDriverWrapper webDriverWr
return new AllowedFileExtensionAdminPage(webDriverWrapper.getDriver());
}
+ @Override
+ protected void waitForPage()
+ {
+ waitFor(()-> {
+ try
+ {
+ return !BootstrapLocators.loadingSpinner.areAnyVisible(getDriver()) &&
+ elementCache().extension.getComponentElement().isDisplayed();
+ }
+ catch (NoSuchElementException | StaleElementReferenceException | TimeoutException retry)
+ {
+ return false;
+ }
+ }, "Allowed File Extensions page did not load in time.", 3_000);
+
+ }
+
public AllowedFileExtensionAdminPage setExtension(String extension)
{
elementCache().extension.set(extension);
@@ -31,9 +56,11 @@ public AllowedFileExtensionAdminPage setExtension(String extension)
public String clickSaveExpectingError()
{
+ String errorText;
elementCache().saveExtension.click();
+ errorText = waitForElement(Locators.labkeyError).getText();
clearCache();
- return waitForElement(Locators.labkeyError).getText();
+ return errorText;
}
public AllowedFileExtensionAdminPage clickSaveExtension()
@@ -45,30 +72,90 @@ public AllowedFileExtensionAdminPage clickSaveExtension()
public AllowedFileExtensionAdminPage updateExtension(String oldExtension, String newExtension)
{
- elementCache().allowedExtension(oldExtension).set(newExtension);
+ getAllowedExtension(getAllowedExtensionIndex(oldExtension)).set(newExtension);
clearCache();
return this;
}
- public AllowedFileExtensionAdminPage deleteExtension(int index)
+ public AllowedFileExtensionAdminPage clickSaveUpdateExtension()
{
- elementCache().deleteExtension(index);
+ elementCache().saveUpdateExtension.click();
+ sleep(750);
clearCache();
return this;
}
- public AllowedFileExtensionAdminPage clickUpdateExtension()
+ public String clickUpdateExtensionExpectingError()
{
- elementCache().updateExtension.click();
+ elementCache().saveUpdateExtension.click();
+ clearCache();
+ return waitForElement(Locators.labkeyError).getText();
+ }
+
+ public AllowedFileExtensionAdminPage deleteExtension(int index)
+ {
+ WebElement deleteButton = elementCache().deleteExtensions.get(index);
+ deleteButton.click();
+
+ shortWait().withMessage("Existing extenstion was not deleted.")
+ .until(ExpectedConditions.stalenessOf(deleteButton));
+
clearCache();
return this;
}
- public String clickUpdateExtensionExpectingError()
+ public AllowedFileExtensionAdminPage deleteExtension(String extension)
+ {
+ return deleteExtension(getAllowedExtensionIndex(extension));
+ }
+
+ public AllowedFileExtensionAdminPage deleteAllExtensions(boolean acceptAlert)
{
- elementCache().updateExtension.click();
+ elementCache().deleteAll.click();
+
+ if (acceptAlert)
+ {
+ acceptAlert();
+ shortWait().withMessage("'Delete All' button should have gone away.")
+ .until(ExpectedConditions.stalenessOf(elementCache().deleteAll));
+ }
+ else
+ {
+ cancelAlert();
+ }
+
clearCache();
- return waitForElement(Locators.labkeyError).getText();
+ return this;
+ }
+
+ public List getAllowedExtensions()
+ {
+ List collection = Locator.inputByIdContaining("existingValue")
+ .findElements(elementCache().existingPanel);
+
+ return collection.stream().map(el -> new Input(el, getDriver())).collect(Collectors.toList());
+
+ }
+
+ public Input getAllowedExtension(int index)
+ {
+ return getAllowedExtensions().get(index);
+ }
+
+ public Integer getAllowedExtensionIndex(String extension)
+ {
+ int index = 0;
+ List allowedExtensions = getAllowedExtensions();
+
+ for(Input element : allowedExtensions)
+ {
+ if (element.getValue().equalsIgnoreCase(extension))
+ return index;
+
+ index++;
+ }
+
+ return -1;
}
@Override
@@ -79,24 +166,24 @@ protected ElementCache newElementCache()
protected class ElementCache extends LabKeyPage.ElementCache
{
- final WebElement registerNewAllowedFileExtension = PortalHelper.Locators.webPart("Register New Allowed File Extension")
- .findWhenNeeded(this);
- final Input extension = new Input(Locator.name("newValue").findWhenNeeded(registerNewAllowedFileExtension), getDriver());
- final WebElement saveExtension = Locator.lkButton("Save").findWhenNeeded(registerNewAllowedFileExtension);
+ final WebElement registerNewPanel = PortalHelper.Locators.webPart("Register New Allowed File Extension").findWhenNeeded(this);
+ final WebElement existingPanel = PortalHelper.Locators.webPart("Existing Allowed File Extensions").findWhenNeeded(this);
- final WebElement existingAllowedFileExtensions = PortalHelper.Locators.webPart("Existing Allowed File Extensions")
- .findWhenNeeded(this);
- final WebElement updateExtension = Locator.lkButton("Save").findWhenNeeded(existingAllowedFileExtensions);
+ final Input extension = new Input(Locator.id("newValueTextField").findWhenNeeded(registerNewPanel), getDriver());
+ final WebElement saveExtension = Locator.lkButton("Save").findWhenNeeded(registerNewPanel);
- final Input allowedExtension(String value)
- {
- return new Input(Locator.inputByIdContaining("existingValue").withAttribute("value", value)
- .findWhenNeeded(existingAllowedFileExtensions), getDriver());
- }
+ final WebElement saveUpdateExtension = Locator.lkButton("Save").findWhenNeeded(existingPanel);
- final WebElement deleteExtension(int index)
+ List allowedExtensions()
{
- return Locator.linkWithText("Delete").index(index).findWhenNeeded(existingAllowedFileExtensions);
+ return Locator.inputByIdContaining("existingValue")
+ .findElements(elementCache().existingPanel)
+ .stream().map(el -> new Input(el, getDriver())).collect(Collectors.toList());
}
+
+ final List deleteExtensions = Locator.linkWithText("Delete").findElements(existingPanel);
+
+ final WebElement deleteAll = Locator.linkWithText("Delete All").findWhenNeeded(existingPanel);
+
}
}
diff --git a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java
index cedee08547..1cee2e490f 100644
--- a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java
+++ b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java
@@ -1,6 +1,6 @@
package org.labkey.test.tests.core.admin;
-import org.junit.Assert;
+import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;
@@ -11,6 +11,7 @@
import org.labkey.test.TestFileUtils;
import org.labkey.test.categories.Git;
import org.labkey.test.components.ext4.Window;
+import org.labkey.test.components.html.Input;
import org.labkey.test.pages.core.admin.AllowedFileExtensionAdminPage;
import org.labkey.test.params.FieldDefinition;
import org.labkey.test.params.list.IntListDefinition;
@@ -20,6 +21,7 @@
import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@@ -30,9 +32,19 @@
@Category({Git.class})
public class AllowedFileExtensionAdminTest extends BaseWebDriverTest
{
- private final File EXCEL_DATA_FILE = TestFileUtils.getSampleData("dataLoading/excel/fruits.xls");
- private final File TSV_DATA_FILE = TestFileUtils.getSampleData("dataLoading/excel/fruits.tsv");
- private final File TXT_DATA_FILE = TestFileUtils.getSampleData("survey/TestAttachment.txt");
+ private final File CSV_FILE = TestFileUtils.getSampleData("fileTypes/csv_sample.csv");
+ private final File TSV_FILE = TestFileUtils.getSampleData("fileTypes/tsv_sample.tsv");
+ private final File TXT_FILE = TestFileUtils.getSampleData("fileTypes/sample.txt");
+ private final File XLS_FILE = TestFileUtils.getSampleData("fileTypes/xls_sample.xls");
+ private final File XLSX_FILE = TestFileUtils.getSampleData("fileTypes/xlsx_sample.xlsx");
+
+ private final Map fileMap = Map.of(
+ ".csv", CSV_FILE,
+ ".tsv", TSV_FILE,
+ ".txt", TXT_FILE,
+ ".xls", XLS_FILE,
+ ".xlsx", XLSX_FILE
+ );
@BeforeClass
public static void setupProject()
@@ -45,7 +57,14 @@ public static void setupProject()
protected void doCleanup(boolean afterTest)
{
_containerHelper.deleteProject(getProjectName(), afterTest);
- deleteAllAllowedFileExtension();
+ try
+ {
+ deleteAllAllowedFileExtension();
+ }
+ catch (IOException | CommandException e)
+ {
+ throw new RuntimeException(e);
+ }
}
private void doSetup()
@@ -55,6 +74,206 @@ private void doSetup()
goToProjectHome();
new PortalHelper(getDriver()).addWebPart("Files");
new PortalHelper(getDriver()).addWebPart("Sample Types");
+ new PortalHelper(getDriver()).addWebPart("Messages List");
+ }
+
+ @Before
+ public void beforeTest() throws IOException, CommandException
+ {
+ log("Use API to delete any existing allowed extensions.");
+ deleteAllAllowedFileExtension();
+
+ log("Delete any files that have already been uploaded.");
+ goToProjectHome();
+ _fileBrowserHelper.deleteAll();
+ }
+
+ @Test
+ public void testAddUpdateAndDelete()
+ {
+
+ List allowedTypes = new ArrayList<>();
+ List excludedTypes = new ArrayList<>();
+ String excludedType = ".xlsx";
+ excludedTypes.add(excludedType);
+
+ for (String extension : fileMap.keySet())
+ {
+ if (!excludedTypes.contains(extension))
+ allowedTypes.add(extension);
+ }
+
+ log(String.format("Add the following as extensions: %s", allowedTypes));
+
+ AllowedFileExtensionAdminPage allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
+
+ for (String extension : allowedTypes)
+ {
+ allowedFileExtensionAdminPage.setExtension(extension);
+ allowedFileExtensionAdminPage.clickSaveExtension();
+ }
+
+ List extensions = allowedFileExtensionAdminPage.getAllowedExtensions();
+
+ checker().withScreenshot()
+ .verifyEqualsSorted("List of 'Allowed extensions' is not as expected.",
+ allowedTypes, extensions.stream().map(Input::getValue).toList());
+
+ log("Verify upload of allowed file types is successful.");
+ goToProjectHome();
+
+ List expectedFiles = new ArrayList<>();
+ for (Map.Entry entry : fileMap.entrySet())
+ {
+ if (!excludedTypes.contains(entry.getKey()))
+ {
+ _fileBrowserHelper.uploadFile(entry.getValue());
+ expectedFiles.add(entry.getValue().getName());
+ }
+ }
+
+ List actualFiles = _fileBrowserHelper.getFileList();
+
+ checker().withScreenshot()
+ .verifyEqualsSorted("Uploaded files not as expected.",
+ expectedFiles, actualFiles);
+
+ log(String.format("Verify upload of '%s' fails", excludedType));
+ Window> errorWindow = _fileBrowserHelper.uploadFileExpectingError(fileMap.get(excludedType));
+
+ checker().withScreenshot()
+ .verifyEquals(String.format("Error message for excluded file type '%s' not as expected.", excludedType),
+ String.format("This file type [%s] is not allowed.", excludedType.replace(".", "")), errorWindow.getBody());
+
+ click(Ext4Helper.Locators.ext4Button("OK"));
+
+ allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
+
+ allowedFileExtensionAdminPage.deleteExtension(allowedTypes.get(0));
+ excludedType = allowedTypes.remove(0);
+ excludedTypes.add(excludedType);
+
+ log(String.format("Remove '%s' as an allowed extension.", excludedType));
+
+ extensions = allowedFileExtensionAdminPage.getAllowedExtensions();
+
+ checker().withScreenshot()
+ .verifyEqualsSorted(String.format("List of 'Allowed extensions' is not as expected after removing '%s'.", excludedType),
+ allowedTypes, extensions.stream().map(Input::getValue).toList());
+
+ goToProjectHome();
+ log(String.format("Remove the '%s' file from the upload.", excludedType));
+ _fileBrowserHelper.deleteFile(fileMap.get(excludedType).getName());
+
+ log(String.format("Verify upload of '%s' fails.", excludedType));
+ errorWindow = _fileBrowserHelper.uploadFileExpectingError(fileMap.get(excludedType));
+
+ checker().withScreenshot()
+ .verifyEquals(String.format("Error message is not as expected after removing type '%s'.", excludedType),
+ String.format("This file type [%s] is not allowed.", excludedType.replace(".", "")), errorWindow.getBody());
+
+ click(Ext4Helper.Locators.ext4Button("OK"));
+
+ allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
+
+ log("Click 'Delete All' but cancel out of the confirmation dialog.");
+
+ allowedFileExtensionAdminPage.deleteAllExtensions(false);
+
+ extensions = allowedFileExtensionAdminPage.getAllowedExtensions();
+
+ checker().withScreenshot()
+ .verifyEqualsSorted("List of 'Allowed extensions' is not as expected after canceling 'Delete All'.",
+ allowedTypes, extensions.stream().map(Input::getValue).toList());
+
+ log("Now, click 'Delete All' and accept the confirmation dialog.");
+
+ allowedFileExtensionAdminPage.deleteAllExtensions(true);
+
+ extensions = allowedFileExtensionAdminPage.getAllowedExtensions();
+
+ checker().withScreenshot()
+ .verifyTrue("List of 'Allowed extensions' is not as expected after 'Delete All'.",
+ extensions.isEmpty());
+
+ excludedTypes = new ArrayList<>();
+
+ log("Validate 'all' file types can be uploaded.");
+ goToProjectHome();
+ _fileBrowserHelper.deleteAll();
+
+ expectedFiles = new ArrayList<>();
+ for (Map.Entry entry : fileMap.entrySet())
+ {
+ _fileBrowserHelper.uploadFile(entry.getValue());
+ expectedFiles.add(entry.getValue().getName());
+ }
+
+ actualFiles = _fileBrowserHelper.getFileList();
+
+ checker().withScreenshot()
+ .verifyEqualsSorted("Uploaded files not as expected.",
+ expectedFiles, actualFiles);
+
+ _fileBrowserHelper.deleteAll();
+
+ allowedTypes = new ArrayList<>();
+ excludedTypes = new ArrayList<>();
+ excludedType = ".xlsx";
+ excludedTypes.add(excludedType);
+
+ for (String extension : fileMap.keySet())
+ {
+ if (!excludedTypes.contains(extension))
+ allowedTypes.add(extension);
+ }
+
+ log(String.format("Add these extensions back: %s", allowedTypes));
+
+ allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
+
+ for (String extension : allowedTypes)
+ {
+ allowedFileExtensionAdminPage.setExtension(extension);
+ allowedFileExtensionAdminPage.clickSaveExtension();
+ }
+
+ String oldExtension = ".xls";
+ String newExtension = excludedType;
+
+ log(String.format("Edit the extension '%s' and change it to '%s'.", oldExtension, newExtension));
+
+ Input editExtension = allowedFileExtensionAdminPage.getAllowedExtension(allowedFileExtensionAdminPage.getAllowedExtensionIndex(oldExtension));
+
+ editExtension.setValue(newExtension);
+ allowedFileExtensionAdminPage.clickSaveUpdateExtension();
+
+ allowedTypes.remove(oldExtension);
+ allowedTypes.add(newExtension);
+
+ extensions = allowedFileExtensionAdminPage.getAllowedExtensions();
+
+ checker().withScreenshot()
+ .verifyEqualsSorted("List of 'Allowed extensions' is not as expected.",
+ allowedTypes, extensions.stream().map(Input::getValue).toList());
+
+ goToProjectHome();
+ _fileBrowserHelper.uploadFile(fileMap.get(newExtension));
+
+ actualFiles = _fileBrowserHelper.getFileList();
+
+ checker().withScreenshot()
+ .verifyTrue(String.format("File '%s' should have been uploaded.", fileMap.get(newExtension).getName()),
+ actualFiles.contains(fileMap.get(newExtension).getName()));
+
+ log(String.format("Verify file with the old extension '%s' is excluded.", oldExtension));
+
+ errorWindow = _fileBrowserHelper.uploadFileExpectingError(fileMap.get(oldExtension));
+
+ checker().withScreenshot()
+ .verifyEquals(String.format("Error message is not as expected after removing type '%s'.", oldExtension),
+ String.format("This file type [%s] is not allowed.", oldExtension.replace(".", "")), errorWindow.getBody());
+
}
@Test
@@ -62,11 +281,13 @@ public void testAllowedFileExtensionsInLists() throws IOException, CommandExcept
{
log("Verify and set allowed file extensions in admin console");
AllowedFileExtensionAdminPage allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
- Assert.assertEquals("Incorrect error message for invalid extension", "File extension must start with a '.'",
- allowedFileExtensionAdminPage.setExtension("jpg").clickSaveExpectingError());
- allowedFileExtensionAdminPage.setExtension(".xls").clickSaveExtension().clickUpdateExtension();
- Assert.assertEquals("Incorrect error message for duplicate extension", "'.xls' already exists. Duplicate values not allowed.",
- allowedFileExtensionAdminPage.setExtension(".xls").clickSaveExpectingError());
+ checker().withScreenshot()
+ .verifyEquals("Incorrect error message for invalid extension",
+ "File extension must start with a '.'", allowedFileExtensionAdminPage.setExtension("jpg").clickSaveExpectingError());
+ allowedFileExtensionAdminPage.setExtension(".xls").clickSaveExtension();
+ checker().withScreenshot()
+ .verifyEquals("Incorrect error message for duplicate extension",
+ "'.xls' already exists. Duplicate values not allowed.", allowedFileExtensionAdminPage.setExtension(".xls").clickSaveExpectingError());
log("Create a list with attachment field");
goToProjectHome();
@@ -77,8 +298,7 @@ public void testAllowedFileExtensionsInLists() throws IOException, CommandExcept
goToManageLists();
waitAndClickAndWait(Locator.linkWithText(listName));
- _listHelper.insertNewRow(Map.of("File_Upload_1", EXCEL_DATA_FILE.getAbsolutePath()), false);
-
+ _listHelper.insertNewRow(Map.of("File_Upload_1", XLS_FILE.getAbsolutePath()), false);
//import from file.
@@ -87,9 +307,10 @@ public void testAllowedFileExtensionsInLists() throws IOException, CommandExcept
@Test
public void testAllowedFileExtensionsInSampleType() throws IOException, CommandException
{
+ String allowedExtension = ".tsv";
log("Set allowed file extensions in admin console");
AllowedFileExtensionAdminPage allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
- allowedFileExtensionAdminPage.setExtension("tsv").clickSaveExtension().clickUpdateExtension();
+ allowedFileExtensionAdminPage.setExtension(allowedExtension).clickSaveExtension();
FieldDefinition.LookupInfo lookupInfo = new FieldDefinition.LookupInfo(getProjectName(), "exp.materials", "Sample type Testing");
TestDataGenerator dgen = new TestDataGenerator(lookupInfo)
@@ -100,59 +321,19 @@ public void testAllowedFileExtensionsInSampleType() throws IOException, CommandE
dgen.createDomain(createDefaultConnection(), SAMPLE_TYPE_DOMAIN_KIND);
}
- @Test
- public void testAllowedFileExtensionsInFileBrowser()
- {
- log("Set allowed file extensions in admin console");
- deleteAllAllowedFileExtension();
- AllowedFileExtensionAdminPage allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
- allowedFileExtensionAdminPage.setExtension(".txt").clickSaveExtension().clickUpdateExtension();
-
- log("Verify upload of .txt is successful");
- goToProjectHome();
- _fileBrowserHelper.uploadFile(TXT_DATA_FILE);
- Assert.assertTrue(_fileBrowserHelper.fileIsPresent(TXT_DATA_FILE.getName()));
-
- log("Verify upload of .tsv fails");
- Window errorWindow = _fileBrowserHelper.uploadFileExpectingError(TSV_DATA_FILE);
- Assert.assertEquals(".tsv is not a valid extension", "This file type [tsv] is not allowed.", errorWindow.getBody());
- click(Ext4Helper.Locators.ext4Button("OK"));
-
- log("Update the allowed file extension from .txt to .tsv");
- allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
- allowedFileExtensionAdminPage.updateExtension(".txt", ".tsv").clickUpdateExtension();
- sleep(500);
-
- log("Verify upload of .tsv is successful");
- goToProjectHome();
- _fileBrowserHelper.uploadFile(TSV_DATA_FILE);
- Assert.assertTrue(_fileBrowserHelper.fileIsPresent(TSV_DATA_FILE.getName()));
- }
-
- private void deleteAllAllowedFileExtension()
+ private void deleteAllAllowedFileExtension() throws IOException, CommandException
{
SimplePostCommand command = new SimplePostCommand("admin", "deleteAllValues");
Map params = new HashMap<>();
params.put("type", "FileExtension");
command.setParameters(params);
- try
- {
- command.execute(createDefaultConnection(), "/");
- }
- catch (IOException e)
- {
- throw new RuntimeException(e);
- }
- catch (CommandException e)
- {
- throw new RuntimeException(e);
- }
+ command.execute(createDefaultConnection(), "/");
}
@Override
protected String getProjectName()
{
- return "AllowedFileExtensionAdminTest Project " + TRICKY_CHARACTERS_FOR_PROJECT_NAMES;
+ return "Allowed File Extension Admin Test Project " + TRICKY_CHARACTERS_FOR_PROJECT_NAMES;
}
@Override
From fafd0f744b0fc7594697429ed50aafcd67930a3a Mon Sep 17 00:00:00 2001
From: labkey-danield
Date: Tue, 6 May 2025 19:37:12 -0700
Subject: [PATCH 03/13] Finish tests for SampleTypes and Lists. Add test to
check for adding invalid extensions.
---
.../admin/AllowedFileExtensionAdminTest.java | 403 +++++++++++++-----
1 file changed, 286 insertions(+), 117 deletions(-)
diff --git a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java
index 1cee2e490f..86b6be5cf9 100644
--- a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java
+++ b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java
@@ -11,18 +11,23 @@
import org.labkey.test.TestFileUtils;
import org.labkey.test.categories.Git;
import org.labkey.test.components.ext4.Window;
+import org.labkey.test.components.html.FileInput;
import org.labkey.test.components.html.Input;
import org.labkey.test.pages.core.admin.AllowedFileExtensionAdminPage;
import org.labkey.test.params.FieldDefinition;
+import org.labkey.test.params.experiment.SampleTypeDefinition;
import org.labkey.test.params.list.IntListDefinition;
import org.labkey.test.util.Ext4Helper;
import org.labkey.test.util.PortalHelper;
+import org.labkey.test.util.SampleTypeHelper;
import org.labkey.test.util.TestDataGenerator;
+import org.labkey.test.util.exp.SampleTypeAPIHelper;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -74,6 +79,7 @@ private void doSetup()
goToProjectHome();
new PortalHelper(getDriver()).addWebPart("Files");
new PortalHelper(getDriver()).addWebPart("Sample Types");
+ new PortalHelper(getDriver()).addWebPart("Lists");
new PortalHelper(getDriver()).addWebPart("Messages List");
}
@@ -88,6 +94,25 @@ public void beforeTest() throws IOException, CommandException
_fileBrowserHelper.deleteAll();
}
+ /**
+ *
+ * Test the 'Allowed File Extension Admin' page and use the files web part as part of the validation process.
+ *
+ *
+ * This test will:
+ *
+ *
Add several file extensions as allowed extensions, then upload files of that type.
+ *
Upload a file that is not allowed and validate it is rejected.
+ *
Remove an allowed file type and validate files of that type can not be uploaded.
+ *
Click 'Delete All' and cancel out of confirmation, validate no change.
+ *
Click 'Delete All' and validate any file type can be uploaded.
+ *
Edit an allowed extension, .xls to .xlsx, and validate .xlsx files can be uploaded but .xls can not.
+ *
Validate extension value must start with a '.'
+ *
Validate duplicate extensions are not allowed.
+ *
Validate blank extension type is not allowed.
+ *
+ *
+ */
@Test
public void testAddUpdateAndDelete()
{
@@ -103,51 +128,16 @@ public void testAddUpdateAndDelete()
allowedTypes.add(extension);
}
- log(String.format("Add the following as extensions: %s", allowedTypes));
-
- AllowedFileExtensionAdminPage allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
-
- for (String extension : allowedTypes)
- {
- allowedFileExtensionAdminPage.setExtension(extension);
- allowedFileExtensionAdminPage.clickSaveExtension();
- }
-
- List extensions = allowedFileExtensionAdminPage.getAllowedExtensions();
-
- checker().withScreenshot()
- .verifyEqualsSorted("List of 'Allowed extensions' is not as expected.",
- allowedTypes, extensions.stream().map(Input::getValue).toList());
+ log(String.format("Add the following as allowed extensions: %s", allowedTypes));
+ setAllowedExtensions(allowedTypes, allowedTypes);
log("Verify upload of allowed file types is successful.");
- goToProjectHome();
-
- List expectedFiles = new ArrayList<>();
- for (Map.Entry entry : fileMap.entrySet())
- {
- if (!excludedTypes.contains(entry.getKey()))
- {
- _fileBrowserHelper.uploadFile(entry.getValue());
- expectedFiles.add(entry.getValue().getName());
- }
- }
-
- List actualFiles = _fileBrowserHelper.getFileList();
-
- checker().withScreenshot()
- .verifyEqualsSorted("Uploaded files not as expected.",
- expectedFiles, actualFiles);
+ uploadToFileWebPartAllowed(excludedTypes);
log(String.format("Verify upload of '%s' fails", excludedType));
- Window> errorWindow = _fileBrowserHelper.uploadFileExpectingError(fileMap.get(excludedType));
-
- checker().withScreenshot()
- .verifyEquals(String.format("Error message for excluded file type '%s' not as expected.", excludedType),
- String.format("This file type [%s] is not allowed.", excludedType.replace(".", "")), errorWindow.getBody());
-
- click(Ext4Helper.Locators.ext4Button("OK"));
+ uploadToFileWebPartExcluded(excludedTypes);
- allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
+ AllowedFileExtensionAdminPage allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
allowedFileExtensionAdminPage.deleteExtension(allowedTypes.get(0));
excludedType = allowedTypes.remove(0);
@@ -155,24 +145,14 @@ public void testAddUpdateAndDelete()
log(String.format("Remove '%s' as an allowed extension.", excludedType));
- extensions = allowedFileExtensionAdminPage.getAllowedExtensions();
+ List extensions = allowedFileExtensionAdminPage.getAllowedExtensions();
checker().withScreenshot()
.verifyEqualsSorted(String.format("List of 'Allowed extensions' is not as expected after removing '%s'.", excludedType),
allowedTypes, extensions.stream().map(Input::getValue).toList());
- goToProjectHome();
- log(String.format("Remove the '%s' file from the upload.", excludedType));
- _fileBrowserHelper.deleteFile(fileMap.get(excludedType).getName());
-
log(String.format("Verify upload of '%s' fails.", excludedType));
- errorWindow = _fileBrowserHelper.uploadFileExpectingError(fileMap.get(excludedType));
-
- checker().withScreenshot()
- .verifyEquals(String.format("Error message is not as expected after removing type '%s'.", excludedType),
- String.format("This file type [%s] is not allowed.", excludedType.replace(".", "")), errorWindow.getBody());
-
- click(Ext4Helper.Locators.ext4Button("OK"));
+ uploadToFileWebPartExcluded(excludedTypes);
allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
@@ -196,26 +176,8 @@ public void testAddUpdateAndDelete()
.verifyTrue("List of 'Allowed extensions' is not as expected after 'Delete All'.",
extensions.isEmpty());
- excludedTypes = new ArrayList<>();
-
log("Validate 'all' file types can be uploaded.");
- goToProjectHome();
- _fileBrowserHelper.deleteAll();
-
- expectedFiles = new ArrayList<>();
- for (Map.Entry entry : fileMap.entrySet())
- {
- _fileBrowserHelper.uploadFile(entry.getValue());
- expectedFiles.add(entry.getValue().getName());
- }
-
- actualFiles = _fileBrowserHelper.getFileList();
-
- checker().withScreenshot()
- .verifyEqualsSorted("Uploaded files not as expected.",
- expectedFiles, actualFiles);
-
- _fileBrowserHelper.deleteAll();
+ uploadToFileWebPartAllowed(new ArrayList<>());
allowedTypes = new ArrayList<>();
excludedTypes = new ArrayList<>();
@@ -229,14 +191,7 @@ public void testAddUpdateAndDelete()
}
log(String.format("Add these extensions back: %s", allowedTypes));
-
- allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
-
- for (String extension : allowedTypes)
- {
- allowedFileExtensionAdminPage.setExtension(extension);
- allowedFileExtensionAdminPage.clickSaveExtension();
- }
+ allowedFileExtensionAdminPage = setAllowedExtensions(allowedTypes, allowedTypes);
String oldExtension = ".xls";
String newExtension = excludedType;
@@ -246,79 +201,293 @@ public void testAddUpdateAndDelete()
Input editExtension = allowedFileExtensionAdminPage.getAllowedExtension(allowedFileExtensionAdminPage.getAllowedExtensionIndex(oldExtension));
editExtension.setValue(newExtension);
+
+ // Issue 53039 If that issue is fixed code should be added here to validate dirty bit warning.
+
allowedFileExtensionAdminPage.clickSaveUpdateExtension();
allowedTypes.remove(oldExtension);
allowedTypes.add(newExtension);
+ excludedTypes = List.of(oldExtension);
extensions = allowedFileExtensionAdminPage.getAllowedExtensions();
checker().withScreenshot()
.verifyEqualsSorted("List of 'Allowed extensions' is not as expected.",
allowedTypes, extensions.stream().map(Input::getValue).toList());
- goToProjectHome();
- _fileBrowserHelper.uploadFile(fileMap.get(newExtension));
+ uploadToFileWebPartAllowed(excludedTypes);
- actualFiles = _fileBrowserHelper.getFileList();
+ log(String.format("Verify file with the old extension '%s' is excluded.", oldExtension));
+ uploadToFileWebPartExcluded(excludedTypes);
+ allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
+ allowedFileExtensionAdminPage.setExtension("not .an extension");
+ String expectedValue = "File extension must start with a '.'";
+ String actualValue = allowedFileExtensionAdminPage.clickSaveExpectingError();
checker().withScreenshot()
- .verifyTrue(String.format("File '%s' should have been uploaded.", fileMap.get(newExtension).getName()),
- actualFiles.contains(fileMap.get(newExtension).getName()));
+ .verifyEquals("Incorrect error message for invalid extension.",
+ expectedValue, actualValue);
- log(String.format("Verify file with the old extension '%s' is excluded.", oldExtension));
+ allowedFileExtensionAdminPage.setExtension(allowedTypes.get(0));
+ expectedValue = String.format("'%s' already exists. Duplicate values not allowed.", allowedTypes.get(0));
+ actualValue = allowedFileExtensionAdminPage.clickSaveExpectingError();
+ checker().withScreenshot()
+ .verifyEquals("Incorrect error message for duplicate extension.",
+ expectedValue, actualValue);
- errorWindow = _fileBrowserHelper.uploadFileExpectingError(fileMap.get(oldExtension));
+ allowedFileExtensionAdminPage.setExtension(allowedTypes.get(1).toUpperCase());
+ expectedValue = String.format("'%s' already exists. Duplicate values not allowed.", allowedTypes.get(1).toUpperCase());
+ actualValue = allowedFileExtensionAdminPage.clickSaveExpectingError();
+ checker().withScreenshot()
+ .verifyEquals("Incorrect error message for duplicate extension but different case.",
+ expectedValue, actualValue);
+ allowedFileExtensionAdminPage.setExtension("");
+ expectedValue = "File extension must not be blank.";
+ actualValue = allowedFileExtensionAdminPage.clickSaveExpectingError();
checker().withScreenshot()
- .verifyEquals(String.format("Error message is not as expected after removing type '%s'.", oldExtension),
- String.format("This file type [%s] is not allowed.", oldExtension.replace(".", "")), errorWindow.getBody());
+ .verifyEquals("Incorrect error message for blank extension value.",
+ expectedValue, actualValue);
+
+ }
+
+ private void uploadToFileWebPartAllowed(List excludedTypes)
+ {
+ goToProjectHome();
+ _fileBrowserHelper.deleteAll();
+
+ List expectedFiles = new ArrayList<>();
+ for (Map.Entry entry : fileMap.entrySet())
+ {
+ if (!excludedTypes.contains(entry.getKey()))
+ {
+ _fileBrowserHelper.uploadFile(entry.getValue());
+ expectedFiles.add(entry.getValue().getName());
+ }
+ }
+
+ List actualFiles = _fileBrowserHelper.getFileList();
+
+ checker().withScreenshot()
+ .verifyEqualsSorted("Uploaded files not as expected.",
+ expectedFiles, actualFiles);
+
+ }
+
+ private void uploadToFileWebPartExcluded(List excludedTypes)
+ {
+
+ goToProjectHome();
+
+ for (String excludedType : excludedTypes)
+ {
+
+ if (_fileBrowserHelper.fileIsPresent(fileMap.get(excludedType).getName()))
+ {
+ log(String.format("Remove the '%s' file from the upload.", excludedType));
+ _fileBrowserHelper.deleteFile(fileMap.get(excludedType).getName());
+ refresh();
+ }
+
+ Window> errorWindow = _fileBrowserHelper.uploadFileExpectingError(fileMap.get(excludedType));
+
+ checker().withScreenshot()
+ .verifyEquals(String.format("Error message for excluded file type '%s' not as expected.", excludedType),
+ String.format("This file type [%s] is not allowed.", excludedType.replace(".", "")), errorWindow.getBody());
+
+ click(Ext4Helper.Locators.ext4Button("OK"));
+ }
}
@Test
public void testAllowedFileExtensionsInLists() throws IOException, CommandException
{
- log("Verify and set allowed file extensions in admin console");
- AllowedFileExtensionAdminPage allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
- checker().withScreenshot()
- .verifyEquals("Incorrect error message for invalid extension",
- "File extension must start with a '.'", allowedFileExtensionAdminPage.setExtension("jpg").clickSaveExpectingError());
- allowedFileExtensionAdminPage.setExtension(".xls").clickSaveExtension();
- checker().withScreenshot()
- .verifyEquals("Incorrect error message for duplicate extension",
- "'.xls' already exists. Duplicate values not allowed.", allowedFileExtensionAdminPage.setExtension(".xls").clickSaveExpectingError());
- log("Create a list with attachment field");
+ List allowedTypes = new ArrayList<>();
+ String excludedType = ".csv";
+
+ for (String extension : fileMap.keySet())
+ {
+ if (!extension.equals(excludedType))
+ allowedTypes.add(extension);
+ }
+
+ log(String.format("Add the following as allowed extensions: %s", allowedTypes));
+ setAllowedExtensions(allowedTypes, allowedTypes);
+
goToProjectHome();
- String listName = "ListWithAttachments";
- new IntListDefinition(listName, "List_key")
- .setFields(List.of(new FieldDefinition("File_Upload_1", FieldDefinition.ColumnType.Attachment)))
- .create(createDefaultConnection(), getProjectName());
+ String listName = "Test Allowed Attachments";
+ String keyField = "Key";
+ String attachmentField = "Attachment Field";
+
+ log(String.format("Create a list '%s' with attachment field and auto-increment key.", listName));
+ _listHelper.createList(getProjectName(), listName, keyField,
+ new FieldDefinition(attachmentField, FieldDefinition.ColumnType.Attachment));
goToManageLists();
- waitAndClickAndWait(Locator.linkWithText(listName));
- _listHelper.insertNewRow(Map.of("File_Upload_1", XLS_FILE.getAbsolutePath()), false);
+ _listHelper.goToList(listName);
+
+ String [][] expectedData = new String [allowedTypes.size()][1];
+ int index = 0;
+ for (String allowedType : allowedTypes)
+ {
+ _listHelper.insertNewRow(Map.of(attachmentField, fileMap.get(allowedType).getAbsolutePath()), false);
+ // Add a space before the name to allow for the icon.
+ expectedData [index++][0] = String.format(" %s", fileMap.get(allowedType).getName());
+ }
- //import from file.
+ goToManageLists();
+ _listHelper.goToList(listName);
+ _listHelper.verifyListData(List.of(new FieldDefinition(attachmentField, FieldDefinition.ColumnType.Attachment)), expectedData, checker());
+
+ _listHelper.goToList(listName);
+ _listHelper.insertNewRow(Map.of(attachmentField, fileMap.get(excludedType).getAbsolutePath()), false);
+
+ // Not sure why we record two exceptions.
+ checkExpectedErrors(2);
}
+ /**
+ *
+ * Validate sample types work well with the allowed extension list.
+ *
+ *
+ * This test will set several extension as allowed type, create a sample type with a file field, and then:
+ *
+ *
Validate a row(s) can be inserted with the allowed file types.
+ *
Validate a row cannot be inserted with a disallowed file type.
+ *
Validate that removing the disallowed type from the file field allows for the row to be inserted.
+ *
+ * Note: This test does not exercise bulk or import by file. In those scenarios the file would have had
+ * to already been uploaded to the server for it to be referenced in the input or bulk file / data. Uploading to
+ * the server is covered in the testAddUpdateAndDelete test.
+ *
+ */
@Test
- public void testAllowedFileExtensionsInSampleType() throws IOException, CommandException
+ public void testAllowedFileExtensionsInSampleType()
+ {
+ List allowedTypes = new ArrayList<>();
+ List excludedTypes = new ArrayList<>();
+ String excludedType = ".xlsx";
+ excludedTypes.add(excludedType);
+
+ for (String extension : fileMap.keySet())
+ {
+ if (!excludedTypes.contains(extension))
+ allowedTypes.add(extension);
+ }
+
+ log(String.format("Add the following as allowed extensions: %s", allowedTypes));
+ setAllowedExtensions(allowedTypes, allowedTypes);
+
+ goToProjectHome();
+
+ String stName = "Allowed File Extension Testing";
+ SampleTypeDefinition stDefinition = new SampleTypeDefinition(stName);
+
+ String stFileField = "File Upload Test";
+ stDefinition.addField(new FieldDefinition("File Upload Test", FieldDefinition.ColumnType.File));
+ SampleTypeAPIHelper.createEmptySampleType(getProjectName(), stDefinition);
+
+ refresh();
+ waitForElement(Locator.linkWithText(stName));
+
+ SampleTypeHelper sampleTypeHelper = new SampleTypeHelper(this);
+ sampleTypeHelper.goToSampleType(stName);
+
+ log("Add rows in the sample type with the allowed file types.");
+ int i = 1;
+ Map fieldMap;
+ List expectedValues = new ArrayList<>();
+ for (String allowedType : allowedTypes)
+ {
+ fieldMap = Map.of("Name", String.format("S-%d", i), stFileField, fileMap.get(allowedType).getAbsolutePath());
+ sampleTypeHelper.insertRow(fieldMap);
+ expectedValues.add(String.format(" sampletype/%s", fileMap.get(allowedType).getName()));
+ i++;
+ }
+
+ // The order of the grid is last one added is at the top, which is opposite of how they were added to the list.
+ Collections.reverse(expectedValues);
+
+ List actualValues = sampleTypeHelper.getSamplesDataRegionTable().getColumnDataAsText(stFileField);
+ checker().verifyEquals(String.format("Values in the '%s' column not as expected.", stFileField),
+ expectedValues, actualValues);
+
+ log("Create a sample that tries to upload a disallowed file type.");
+ String sampleId = String.format("S-%d", i);
+ String description= "Some text for the description.";
+ String amount = "5.00";
+
+ fieldMap = Map.of("Name", sampleId,
+ "Description", description,
+ stFileField, fileMap.get(excludedType).getAbsolutePath(),
+ "StoredAmount", amount);
+ sampleTypeHelper.insertRow(fieldMap);
+
+ // Not sure why we record two exceptions.
+ checkExpectedErrors(2);
+
+ // Issue 53026 (or at least part of it)
+ log("Click 'Back' button and validate that the fields still have all the expected values.");
+ waitForElement(Locator.button("Back"));
+ clickButton("Back");
+
+ waitForElement(Locator.name("quf_" + stFileField));
+
+ checker().verifyEquals("'Name' field does not have expected value.",
+ sampleId, getFormElement(Locator.name("quf_Name")));
+
+ checker().verifyEquals("'Description' field does not have expected value.",
+ description, getFormElement(Locator.name("quf_Description")));
+
+ checker().verifyEquals("'StoredAmount' field does not have expected value.",
+ amount, getFormElement(Locator.name("quf_StoredAmount")));
+
+ checker().screenShotIfNewError("Field_Values_Error");
+
+ // Issue 53027
+ log("Clear the file field and resubmit.");
+ FileInput el = FileInput.FileInput(Locator.name("quf_" + stFileField), getDriver()).findWhenNeeded();
+ executeScript("arguments[0].value = '';", el.getComponentElement());
+
+ clickButton("Submit");
+
+ Map rowMap = sampleTypeHelper.getSamplesDataRegionTable().getRowDataAsMap(0);
+
+ checker().verifyEquals("'Name' field in grid does not have expected value.",
+ sampleId, rowMap.get("Name"));
+
+ checker().verifyEquals("'Amount' field in grid does not have expected value.",
+ amount, rowMap.get("Amount"));
+
+ checker().verifyEquals(String.format("'%s' field in grid does not have expected value.", stFileField),
+ "", rowMap.get(stFileField));
+
+ checker().screenShotIfNewError("Field_Values_Error");
+
+ }
+
+ private AllowedFileExtensionAdminPage setAllowedExtensions(List allowedTypes, List expectedTypes)
{
- String allowedExtension = ".tsv";
- log("Set allowed file extensions in admin console");
AllowedFileExtensionAdminPage allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
- allowedFileExtensionAdminPage.setExtension(allowedExtension).clickSaveExtension();
-
- FieldDefinition.LookupInfo lookupInfo = new FieldDefinition.LookupInfo(getProjectName(), "exp.materials", "Sample type Testing");
- TestDataGenerator dgen = new TestDataGenerator(lookupInfo)
- .withColumns(List.of(
- new FieldDefinition("name", FieldDefinition.ColumnType.String),
- new FieldDefinition("File_Upload_1", FieldDefinition.ColumnType.File)
- ));
- dgen.createDomain(createDefaultConnection(), SAMPLE_TYPE_DOMAIN_KIND);
+
+ for (String extension : allowedTypes)
+ {
+ allowedFileExtensionAdminPage.setExtension(extension);
+ allowedFileExtensionAdminPage.clickSaveExtension();
+ }
+
+ List extensions = allowedFileExtensionAdminPage.getAllowedExtensions();
+
+ checker().withScreenshot()
+ .verifyEqualsSorted("List of 'Allowed extensions' is not as expected.",
+ expectedTypes, extensions.stream().map(Input::getValue).toList());
+
+ return allowedFileExtensionAdminPage;
}
private void deleteAllAllowedFileExtension() throws IOException, CommandException
From 6951263002989fb23ab69d8d12fd90b083d7d879 Mon Sep 17 00:00:00 2001
From: labkey-danield
Date: Wed, 7 May 2025 18:17:20 -0700
Subject: [PATCH 04/13] Add tests for Messages. Update BaseUpdatePage to have a
getter for the title and body.
---
.../pages/announcements/BaseUpdatePage.java | 10 +
.../admin/AllowedFileExtensionAdminTest.java | 173 +++++++++++++++++-
2 files changed, 178 insertions(+), 5 deletions(-)
diff --git a/src/org/labkey/test/pages/announcements/BaseUpdatePage.java b/src/org/labkey/test/pages/announcements/BaseUpdatePage.java
index a73585b9e1..5331d2e075 100644
--- a/src/org/labkey/test/pages/announcements/BaseUpdatePage.java
+++ b/src/org/labkey/test/pages/announcements/BaseUpdatePage.java
@@ -42,12 +42,22 @@ public PAGE setTitle(String title)
return getThis();
}
+ public String getTitle()
+ {
+ return elementCache().titleInput.get();
+ }
+
public PAGE setBody(String body)
{
elementCache().bodyInput.set(body);
return getThis();
}
+ public String getBody()
+ {
+ return elementCache().bodyInput.get();
+ }
+
public PAGE setRenderAs(WikiRendererType renderAs)
{
elementCache().rendererSelect.set(renderAs);
diff --git a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java
index 86b6be5cf9..713a56bb52 100644
--- a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java
+++ b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java
@@ -16,12 +16,14 @@
import org.labkey.test.pages.core.admin.AllowedFileExtensionAdminPage;
import org.labkey.test.params.FieldDefinition;
import org.labkey.test.params.experiment.SampleTypeDefinition;
-import org.labkey.test.params.list.IntListDefinition;
+import org.labkey.test.util.DataRegionTable;
import org.labkey.test.util.Ext4Helper;
import org.labkey.test.util.PortalHelper;
import org.labkey.test.util.SampleTypeHelper;
-import org.labkey.test.util.TestDataGenerator;
import org.labkey.test.util.exp.SampleTypeAPIHelper;
+import org.labkey.test.pages.announcements.InsertPage;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.support.ui.ExpectedConditions;
import java.io.File;
import java.io.IOException;
@@ -32,7 +34,7 @@
import java.util.List;
import java.util.Map;
-import static org.labkey.test.util.exp.SampleTypeAPIHelper.SAMPLE_TYPE_DOMAIN_KIND;
+import static org.labkey.test.util.DataRegionTable.DataRegion;
@Category({Git.class})
public class AllowedFileExtensionAdminTest extends BaseWebDriverTest
@@ -301,8 +303,22 @@ private void uploadToFileWebPartExcluded(List excludedTypes)
}
+ /**
+ *
+ * Using a list validate that attachments work correctly with the allowed files list.
+ *
+ *
+ * After creating a list that has an auto-index and a attachment field as the only field this test will:
+ *
+ *
Can insert an element into the list with the allowed file type.
+ *
Validate that a file of the type not allowed is not allowed.
+ *
Remove the bad file and resubmit with a valid file type.
+ *
+ *
+ *
+ */
@Test
- public void testAllowedFileExtensionsInLists() throws IOException, CommandException
+ public void testAllowedFileExtensionsInLists()
{
List allowedTypes = new ArrayList<>();
@@ -335,7 +351,7 @@ public void testAllowedFileExtensionsInLists() throws IOException, CommandExcept
{
_listHelper.insertNewRow(Map.of(attachmentField, fileMap.get(allowedType).getAbsolutePath()), false);
// Add a space before the name to allow for the icon.
- expectedData [index++][0] = String.format(" %s", fileMap.get(allowedType).getName());
+ expectedData[index++][0] = String.format(" %s", fileMap.get(allowedType).getName());
}
goToManageLists();
@@ -348,6 +364,31 @@ public void testAllowedFileExtensionsInLists() throws IOException, CommandExcept
// Not sure why we record two exceptions.
checkExpectedErrors(2);
+ log("Click 'Back' button and select a file type that is allowed.");
+ waitForElement(Locator.button("Back"));
+ clickButton("Back");
+
+ waitForElement(Locator.name("quf_" + attachmentField));
+
+ // Same as Issue 53026, the fields are cleared after hitting back button. Covewrage for that issue is in
+ // testAllowedFileExtensionsInSampleType test.
+ log("Clear the file field.");
+ FileInput el = FileInput.FileInput(Locator.name("quf_" + attachmentField), getDriver()).findWhenNeeded();
+ executeScript("arguments[0].value = '';", el.getComponentElement());
+
+ File fileAgain = fileMap.get(".txt");
+ log(String.format("Add the '%s' file to the list again (it is an allowed file).", fileAgain.getName()));
+ el.set(fileAgain.getAbsolutePath());
+
+ clickButton("Submit");
+
+ DataRegionTable dataRegion = DataRegion(getDriver()).withName("query").find();
+ List actualData = dataRegion.getColumnDataAsText(attachmentField);
+
+ checker().withScreenshot()
+ .verifyEquals(String.format("The file '%s' should be in the list twice.", fileAgain.getName()),
+ 2, Collections.frequency(actualData, String.format(" %s", fileAgain.getName())));
+
}
/**
@@ -471,6 +512,128 @@ public void testAllowedFileExtensionsInSampleType()
}
+ /**
+ *
+ * Validate that message attachments work correctly with the allowed files list.
+ *
+ *
+ * This test will:
+ *
+ *
Create a message with several allowed files as attachments.
+ *
Verify a message created with a disallowed file type is not allowed.
+ *
Remove the disallowed file from the list of attachments and resubmit.
+ *
+ *
+ */
+ @Test
+ public void testAllowedFilesInMessages()
+ {
+
+ List allowedTypes = new ArrayList<>();
+ String excludedType = ".tsv";
+
+ for (String extension : fileMap.keySet())
+ {
+ if (!extension.equals(excludedType))
+ allowedTypes.add(extension);
+ }
+
+ log(String.format("Add the following as allowed extensions: %s", allowedTypes));
+ setAllowedExtensions(allowedTypes, allowedTypes);
+
+ goToProjectHome();
+
+ String allowedTitle = "Allowed Files Attachment";
+
+ InsertPage page = InsertPage.beginAt(this)
+ .setTitle(allowedTitle)
+ .setBody("These attachments should be allowed.");
+
+ for (String allowedType : allowedTypes)
+ {
+ page.addAttachments(fileMap.get(allowedType));
+ }
+
+ log(String.format("Create a message with title of '%s' and several allowed files as attachments.", allowedTitle));
+
+ page.submit();
+
+ String notAllowedTitle = "Not Allowed Files Attachment";
+ String notAllowedBody = "At least one of these attachments should not be allowed.";
+
+ page = InsertPage.beginAt(this)
+ .setTitle(notAllowedTitle)
+ .setBody(notAllowedBody);
+
+ for (Map.Entry entry : fileMap.entrySet())
+ {
+ page.addAttachments(entry.getValue());
+ }
+
+ List notAllowedAttachments = Locator.tagWithAttributeContaining("span", "id","filename")
+ .findElements(getDriver())
+ .stream().map(WebElement::getText).toList();
+
+ log(String.format("Try to create a message with title of '%s' with several allowed files as attachments, and one disallowed file type.", allowedTitle));
+
+ page.submit();
+
+ // Not sure why we record two exceptions.
+ checkExpectedErrors(2);
+
+ // Issue 53026 Fields cleared after clicking 'Back' button.
+ log("Click 'Back' button and validate that the fields still have all the expected values.");
+ waitForElement(Locator.button("Back"));
+ clickButton("Back");
+
+ waitForElement(Locator.tagWithId("textarea", "body"));
+
+ page = new InsertPage(getDriver());
+
+ checker().verifyEquals("Message title was not persisted.",
+ notAllowedTitle, page.getTitle());
+
+ checker().verifyEquals("Message body was not persisted.",
+ notAllowedBody, page.getBody());
+
+ List attachmentElements = Locator.tagWithAttributeContaining("span", "id","filename")
+ .findElements(getDriver());
+
+ checker().verifyEqualsSorted("None of the previous attachments are still present.",
+ notAllowedAttachments, attachmentElements
+ .stream().map(WebElement::getText).toList());
+
+ checker().screenShotIfNewError("Field_Values_After_Disallowed_Error");
+
+ log("Remove the offending file and resubmit the message.");
+
+ // This did not work for me. The index is correct but fails saying could not find link with text "remove".
+// page.removeAttachment(attachmentElements
+// .stream().map(WebElement::getText).toList()
+// .indexOf(fileMap.get(excludedType).getName()));
+
+ List removeLinks = Locator.linkContainingText("remove").findElements(getDriver());
+
+ WebElement removeLink = removeLinks.get(attachmentElements
+ .stream().map(WebElement::getText).toList()
+ .indexOf(fileMap.get(excludedType).getName()));
+
+ removeLink.click();
+
+ shortWait().until(ExpectedConditions.stalenessOf(removeLink));
+
+ page.submit();
+
+ goToProjectHome();
+
+ DataRegionTable dataRegion = DataRegion(getDriver()).withName("Announcements").find();
+
+ checker().withScreenshot()
+ .verifyEqualsSorted("Not all messages are there.",
+ List.of(allowedTitle, notAllowedTitle), dataRegion.getColumnDataAsText("Title"));
+
+ }
+
private AllowedFileExtensionAdminPage setAllowedExtensions(List allowedTypes, List expectedTypes)
{
AllowedFileExtensionAdminPage allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
From e8514f59dbb0c45a982f6ea95938fad43c787948 Mon Sep 17 00:00:00 2001
From: labkey-danield
Date: Mon, 12 May 2025 10:28:40 -0700
Subject: [PATCH 05/13] Change test workflow to accommodate resolution of issue
53026 (not going to check if fields remain populated).
---
.../admin/AllowedFileExtensionAdminTest.java | 81 ++-----------------
1 file changed, 7 insertions(+), 74 deletions(-)
diff --git a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java
index 713a56bb52..6778811375 100644
--- a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java
+++ b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java
@@ -472,30 +472,14 @@ public void testAllowedFileExtensionsInSampleType()
// Not sure why we record two exceptions.
checkExpectedErrors(2);
- // Issue 53026 (or at least part of it)
- log("Click 'Back' button and validate that the fields still have all the expected values.");
- waitForElement(Locator.button("Back"));
- clickButton("Back");
-
- waitForElement(Locator.name("quf_" + stFileField));
-
- checker().verifyEquals("'Name' field does not have expected value.",
- sampleId, getFormElement(Locator.name("quf_Name")));
-
- checker().verifyEquals("'Description' field does not have expected value.",
- description, getFormElement(Locator.name("quf_Description")));
-
- checker().verifyEquals("'StoredAmount' field does not have expected value.",
- amount, getFormElement(Locator.name("quf_StoredAmount")));
-
- checker().screenShotIfNewError("Field_Values_Error");
-
// Issue 53027
- log("Clear the file field and resubmit.");
- FileInput el = FileInput.FileInput(Locator.name("quf_" + stFileField), getDriver()).findWhenNeeded();
- executeScript("arguments[0].value = '';", el.getComponentElement());
-
- clickButton("Submit");
+ goToProjectHome();
+ sampleTypeHelper = new SampleTypeHelper(this);
+ sampleTypeHelper.goToSampleType(stName);
+ fieldMap = Map.of("Name", sampleId,
+ "Description", description,
+ "StoredAmount", amount);
+ sampleTypeHelper.insertRow(fieldMap);
Map rowMap = sampleTypeHelper.getSamplesDataRegionTable().getRowDataAsMap(0);
@@ -581,57 +565,6 @@ public void testAllowedFilesInMessages()
// Not sure why we record two exceptions.
checkExpectedErrors(2);
- // Issue 53026 Fields cleared after clicking 'Back' button.
- log("Click 'Back' button and validate that the fields still have all the expected values.");
- waitForElement(Locator.button("Back"));
- clickButton("Back");
-
- waitForElement(Locator.tagWithId("textarea", "body"));
-
- page = new InsertPage(getDriver());
-
- checker().verifyEquals("Message title was not persisted.",
- notAllowedTitle, page.getTitle());
-
- checker().verifyEquals("Message body was not persisted.",
- notAllowedBody, page.getBody());
-
- List attachmentElements = Locator.tagWithAttributeContaining("span", "id","filename")
- .findElements(getDriver());
-
- checker().verifyEqualsSorted("None of the previous attachments are still present.",
- notAllowedAttachments, attachmentElements
- .stream().map(WebElement::getText).toList());
-
- checker().screenShotIfNewError("Field_Values_After_Disallowed_Error");
-
- log("Remove the offending file and resubmit the message.");
-
- // This did not work for me. The index is correct but fails saying could not find link with text "remove".
-// page.removeAttachment(attachmentElements
-// .stream().map(WebElement::getText).toList()
-// .indexOf(fileMap.get(excludedType).getName()));
-
- List removeLinks = Locator.linkContainingText("remove").findElements(getDriver());
-
- WebElement removeLink = removeLinks.get(attachmentElements
- .stream().map(WebElement::getText).toList()
- .indexOf(fileMap.get(excludedType).getName()));
-
- removeLink.click();
-
- shortWait().until(ExpectedConditions.stalenessOf(removeLink));
-
- page.submit();
-
- goToProjectHome();
-
- DataRegionTable dataRegion = DataRegion(getDriver()).withName("Announcements").find();
-
- checker().withScreenshot()
- .verifyEqualsSorted("Not all messages are there.",
- List.of(allowedTitle, notAllowedTitle), dataRegion.getColumnDataAsText("Title"));
-
}
private AllowedFileExtensionAdminPage setAllowedExtensions(List allowedTypes, List expectedTypes)
From 204f26fa269e6035b6463d42d17f7eb2d764a575 Mon Sep 17 00:00:00 2001
From: labkey-danield
Date: Wed, 14 May 2025 18:41:26 -0700
Subject: [PATCH 06/13] Move deleteAllAllowedFileExtensions out of
AllowedFileExtensionAdminTest and into BaseWebDriverTest. Add
AllowedFileExtensionsTest in lims/biologics, add
testAllowedFilesInSampleTypes. Add
TestScrubber.clearListOfAllowedFileExtensions.
---
src/org/labkey/test/BaseWebDriverTest.java | 9 +++++++++
src/org/labkey/test/TestScrubber.java | 18 ++++++++++++++++++
.../admin/AllowedFileExtensionAdminTest.java | 15 ++-------------
3 files changed, 29 insertions(+), 13 deletions(-)
diff --git a/src/org/labkey/test/BaseWebDriverTest.java b/src/org/labkey/test/BaseWebDriverTest.java
index cc9345dbd9..85a4240aa6 100644
--- a/src/org/labkey/test/BaseWebDriverTest.java
+++ b/src/org/labkey/test/BaseWebDriverTest.java
@@ -2507,6 +2507,15 @@ protected void reloadStudyFromZip(File folderArchive, boolean validateQueries, i
waitForPipelineJobsToComplete(pipelineJobs, "Study Reload", expectError);
}
+ protected void deleteAllAllowedFileExtension() throws IOException, CommandException
+ {
+ SimplePostCommand command = new SimplePostCommand("admin", "deleteAllValues");
+ Map params = new HashMap<>();
+ params.put("type", "FileExtension");
+ command.setParameters(params);
+ command.execute(createDefaultConnection(), "/");
+ }
+
public AbstractContainerHelper getContainerHelper()
{
return _containerHelper;
diff --git a/src/org/labkey/test/TestScrubber.java b/src/org/labkey/test/TestScrubber.java
index ad2f2bf112..cd90a11dd9 100644
--- a/src/org/labkey/test/TestScrubber.java
+++ b/src/org/labkey/test/TestScrubber.java
@@ -132,6 +132,15 @@ public void cleanSiteSettings()
TestLogger.error("Failed to re-enable file Upload after test", e);
}
+ try
+ {
+ clearListOfAllowedFileExtensions();
+ }
+ catch (Exception e)
+ {
+ TestLogger.error("Failed to remove list of allowed file extensions.", e);
+ }
+
try
{
LimitActiveUserPage.resetUserLimits(connection);
@@ -213,4 +222,13 @@ private void disableFileUploadSetting() throws IOException, CommandException
}
}
}
+
+ private void clearListOfAllowedFileExtensions() throws IOException, CommandException
+ {
+ SimplePostCommand command = new SimplePostCommand("admin", "deleteAllValues");
+ Map params = new HashMap<>();
+ params.put("type", "FileExtension");
+ command.setParameters(params);
+ command.execute(createDefaultConnection(), "/");
+ }
}
diff --git a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java
index 6778811375..4f7b25b303 100644
--- a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java
+++ b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java
@@ -5,7 +5,7 @@
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.labkey.remoteapi.CommandException;
-import org.labkey.remoteapi.SimplePostCommand;
+
import org.labkey.test.BaseWebDriverTest;
import org.labkey.test.Locator;
import org.labkey.test.TestFileUtils;
@@ -23,14 +23,12 @@
import org.labkey.test.util.exp.SampleTypeAPIHelper;
import org.labkey.test.pages.announcements.InsertPage;
import org.openqa.selenium.WebElement;
-import org.openqa.selenium.support.ui.ExpectedConditions;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -430,7 +428,7 @@ public void testAllowedFileExtensionsInSampleType()
SampleTypeDefinition stDefinition = new SampleTypeDefinition(stName);
String stFileField = "File Upload Test";
- stDefinition.addField(new FieldDefinition("File Upload Test", FieldDefinition.ColumnType.File));
+ stDefinition.addField(new FieldDefinition(stFileField, FieldDefinition.ColumnType.File));
SampleTypeAPIHelper.createEmptySampleType(getProjectName(), stDefinition);
refresh();
@@ -586,15 +584,6 @@ private AllowedFileExtensionAdminPage setAllowedExtensions(List allowedT
return allowedFileExtensionAdminPage;
}
- private void deleteAllAllowedFileExtension() throws IOException, CommandException
- {
- SimplePostCommand command = new SimplePostCommand("admin", "deleteAllValues");
- Map params = new HashMap<>();
- params.put("type", "FileExtension");
- command.setParameters(params);
- command.execute(createDefaultConnection(), "/");
- }
-
@Override
protected String getProjectName()
{
From c92071740396a60860c45b989bb1d6fbfa49146f Mon Sep 17 00:00:00 2001
From: labkey-danield
Date: Fri, 16 May 2025 14:56:34 -0700
Subject: [PATCH 07/13] Add check for dirty bit behavior to
AllowedFileExtensionAdminTest Add
AllowedFileExtensionsTest.testAllowedFilesInWorkflow
---
.../admin/AllowedFileExtensionAdminTest.java | 22 ++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java
index 4f7b25b303..cdae9ed41a 100644
--- a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java
+++ b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java
@@ -22,6 +22,7 @@
import org.labkey.test.util.SampleTypeHelper;
import org.labkey.test.util.exp.SampleTypeAPIHelper;
import org.labkey.test.pages.announcements.InsertPage;
+import org.openqa.selenium.Alert;
import org.openqa.selenium.WebElement;
import java.io.File;
@@ -166,8 +167,16 @@ public void testAddUpdateAndDelete()
.verifyEqualsSorted("List of 'Allowed extensions' is not as expected after canceling 'Delete All'.",
allowedTypes, extensions.stream().map(Input::getValue).toList());
+ // Issue 53039.
+ log("Validate that canceling the 'Delete All' dialog does not set the dirty bit.");
+ // Using goToProjectHome will validate navigaiton happened.
+ goToProjectHome();
+
log("Now, click 'Delete All' and accept the confirmation dialog.");
+ // Have to navigate back.
+ allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
+
allowedFileExtensionAdminPage.deleteAllExtensions(true);
extensions = allowedFileExtensionAdminPage.getAllowedExtensions();
@@ -202,8 +211,19 @@ public void testAddUpdateAndDelete()
editExtension.setValue(newExtension);
- // Issue 53039 If that issue is fixed code should be added here to validate dirty bit warning.
+ // Issue 53039 validate dirty bit warning.
+ log("Validate that an alert is shown is the change is not saved.");
+ Locator.tagWithClass("a", "brand-logo").findElement(getDriver()).click();
+ Alert alert = waitForAlert();
+
+ checker().withScreenshot()
+ .verifyTrue("Alert text doesn't have expected text.",
+ alert.getText().contains("Changes you made may not be saved."));
+
+ log("Dismiss the alert.");
+ alert.dismiss();
+ log("Save the change.");
allowedFileExtensionAdminPage.clickSaveUpdateExtension();
allowedTypes.remove(oldExtension);
From 5ec98aefce7444b814fe6e5fb41bd6fa63c2ab63 Mon Sep 17 00:00:00 2001
From: labkey-danield
Date: Fri, 30 May 2025 18:12:52 -0700
Subject: [PATCH 08/13] Add a tar.gz file to the mix. Move
deleteAllAllowedFileExtensions to the AllowedFileExtensionAdminPage
Consolidate button code in AllowedFileExtensionAdminPage Remove calls to
checkExpectedErrors. Adding FileInput.clear method. Many other code review
feedback as well.
---
src/org/labkey/test/BaseWebDriverTest.java | 9 --
src/org/labkey/test/TestScrubber.java | 11 +-
.../admin/AllowedFileExtensionAdminPage.java | 70 +++++++----
.../admin/AllowedFileExtensionAdminTest.java | 110 ++++++++++--------
4 files changed, 115 insertions(+), 85 deletions(-)
diff --git a/src/org/labkey/test/BaseWebDriverTest.java b/src/org/labkey/test/BaseWebDriverTest.java
index 5b1021507c..7c8fb20608 100644
--- a/src/org/labkey/test/BaseWebDriverTest.java
+++ b/src/org/labkey/test/BaseWebDriverTest.java
@@ -2506,15 +2506,6 @@ protected void reloadStudyFromZip(File folderArchive, boolean validateQueries, i
waitForPipelineJobsToComplete(pipelineJobs, "Study Reload", expectError);
}
- protected void deleteAllAllowedFileExtension() throws IOException, CommandException
- {
- SimplePostCommand command = new SimplePostCommand("admin", "deleteAllValues");
- Map params = new HashMap<>();
- params.put("type", "FileExtension");
- command.setParameters(params);
- command.execute(createDefaultConnection(), "/");
- }
-
public AbstractContainerHelper getContainerHelper()
{
return _containerHelper;
diff --git a/src/org/labkey/test/TestScrubber.java b/src/org/labkey/test/TestScrubber.java
index cd90a11dd9..82f19b110a 100644
--- a/src/org/labkey/test/TestScrubber.java
+++ b/src/org/labkey/test/TestScrubber.java
@@ -20,6 +20,7 @@
import org.labkey.remoteapi.Connection;
import org.labkey.remoteapi.SimplePostCommand;
import org.labkey.test.components.html.Checkbox;
+import org.labkey.test.pages.core.admin.AllowedFileExtensionAdminPage;
import org.labkey.test.pages.core.admin.BaseSettingsPage;
import org.labkey.test.pages.core.admin.ConfigureFileSystemAccessPage;
import org.labkey.test.pages.core.admin.LimitActiveUserPage;
@@ -134,7 +135,7 @@ public void cleanSiteSettings()
try
{
- clearListOfAllowedFileExtensions();
+ AllowedFileExtensionAdminPage.deleteAllAllowedFileExtension(createDefaultConnection());
}
catch (Exception e)
{
@@ -223,12 +224,4 @@ private void disableFileUploadSetting() throws IOException, CommandException
}
}
- private void clearListOfAllowedFileExtensions() throws IOException, CommandException
- {
- SimplePostCommand command = new SimplePostCommand("admin", "deleteAllValues");
- Map params = new HashMap<>();
- params.put("type", "FileExtension");
- command.setParameters(params);
- command.execute(createDefaultConnection(), "/");
- }
}
diff --git a/src/org/labkey/test/pages/core/admin/AllowedFileExtensionAdminPage.java b/src/org/labkey/test/pages/core/admin/AllowedFileExtensionAdminPage.java
index 20404a41df..7c86feec6b 100644
--- a/src/org/labkey/test/pages/core/admin/AllowedFileExtensionAdminPage.java
+++ b/src/org/labkey/test/pages/core/admin/AllowedFileExtensionAdminPage.java
@@ -1,5 +1,8 @@
package org.labkey.test.pages.core.admin;
+import org.labkey.remoteapi.CommandException;
+import org.labkey.remoteapi.Connection;
+import org.labkey.remoteapi.SimplePostCommand;
import org.labkey.test.BootstrapLocators;
import org.labkey.test.Locator;
import org.labkey.test.Locators;
@@ -15,9 +18,15 @@
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
+import java.io.IOException;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.stream.Collectors;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
public class AllowedFileExtensionAdminPage extends LabKeyPage
{
public AllowedFileExtensionAdminPage(WebDriver driver)
@@ -27,7 +36,8 @@ public AllowedFileExtensionAdminPage(WebDriver driver)
public static AllowedFileExtensionAdminPage beginAt(WebDriverWrapper webDriverWrapper)
{
- webDriverWrapper.beginAt(WebTestHelper.buildURL("admin", "allowList"));
+ webDriverWrapper.beginAt(WebTestHelper.buildURL("admin", "allowList",
+ Map.of("type", "FileExtension")));
return new AllowedFileExtensionAdminPage(webDriverWrapper.getDriver());
}
@@ -48,6 +58,21 @@ protected void waitForPage()
}
+ /**
+ * Clears any file extensions that are set as the only allowable names, letting users upload any filename they like.
+ *
+ * @param connection A connection object to use in the command.execute call.
+ */
+ public static void deleteAllAllowedFileExtension(Connection connection) throws IOException, CommandException
+ {
+ SimplePostCommand command = new SimplePostCommand("admin", "deleteAllValues");
+ Map params = new HashMap<>();
+ params.put("type", "FileExtension");
+ command.setParameters(params);
+ command.execute(connection, "/");
+ }
+
+
public AllowedFileExtensionAdminPage setExtension(String extension)
{
elementCache().extension.set(extension);
@@ -56,18 +81,12 @@ public AllowedFileExtensionAdminPage setExtension(String extension)
public String clickSaveExpectingError()
{
- String errorText;
- elementCache().saveExtension.click();
- errorText = waitForElement(Locators.labkeyError).getText();
- clearCache();
- return errorText;
+ return clickButtonExpectingError(elementCache().saveExtension);
}
public AllowedFileExtensionAdminPage clickSaveExtension()
{
- elementCache().saveExtension.click();
- clearCache();
- return this;
+ return clickButtonNoError(elementCache().saveExtension);
}
public AllowedFileExtensionAdminPage updateExtension(String oldExtension, String newExtension)
@@ -79,15 +98,25 @@ public AllowedFileExtensionAdminPage updateExtension(String oldExtension, String
public AllowedFileExtensionAdminPage clickSaveUpdateExtension()
{
- elementCache().saveUpdateExtension.click();
- sleep(750);
+ return clickButtonNoError(elementCache().saveUpdateExtension);
+ }
+
+ public String clickUpdateExtensionExpectingError()
+ {
+ return clickButtonExpectingError(elementCache().saveUpdateExtension);
+ }
+
+ private AllowedFileExtensionAdminPage clickButtonNoError(WebElement button)
+ {
+ clickAndWait(button);
clearCache();
+ assertNoLabKeyErrors();
return this;
}
- public String clickUpdateExtensionExpectingError()
+ private String clickButtonExpectingError(WebElement button)
{
- elementCache().saveUpdateExtension.click();
+ clickAndWait(button);
clearCache();
return waitForElement(Locators.labkeyError).getText();
}
@@ -111,20 +140,21 @@ public AllowedFileExtensionAdminPage deleteExtension(String extension)
public AllowedFileExtensionAdminPage deleteAllExtensions(boolean acceptAlert)
{
- elementCache().deleteAll.click();
-
if (acceptAlert)
{
- acceptAlert();
- shortWait().withMessage("'Delete All' button should have gone away.")
- .until(ExpectedConditions.stalenessOf(elementCache().deleteAll));
+ doAndWaitForPageToLoad(() -> {
+ elementCache().deleteAll.click();
+ acceptAlert();
+ });
+ clearCache();
+ assertFalse("Delete All button should not be present after deleting all extensions", elementCache().deleteAll.isDisplayed());
}
else
{
+ elementCache().deleteAll.click();
cancelAlert();
+ assertTrue("Delete All button should be present", elementCache().deleteAll.isDisplayed());
}
-
- clearCache();
return this;
}
diff --git a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java
index cdae9ed41a..f307021d04 100644
--- a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java
+++ b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java
@@ -6,6 +6,8 @@
import org.junit.experimental.categories.Category;
import org.labkey.remoteapi.CommandException;
+import org.labkey.remoteapi.Connection;
+import org.labkey.remoteapi.domain.PropertyDescriptor;
import org.labkey.test.BaseWebDriverTest;
import org.labkey.test.Locator;
import org.labkey.test.TestFileUtils;
@@ -16,14 +18,15 @@
import org.labkey.test.pages.core.admin.AllowedFileExtensionAdminPage;
import org.labkey.test.params.FieldDefinition;
import org.labkey.test.params.experiment.SampleTypeDefinition;
+import org.labkey.test.params.list.IntListDefinition;
+import org.labkey.test.params.list.ListDefinition;
import org.labkey.test.util.DataRegionTable;
import org.labkey.test.util.Ext4Helper;
import org.labkey.test.util.PortalHelper;
import org.labkey.test.util.SampleTypeHelper;
+import org.labkey.test.util.TestDataGenerator;
import org.labkey.test.util.exp.SampleTypeAPIHelper;
import org.labkey.test.pages.announcements.InsertPage;
-import org.openqa.selenium.Alert;
-import org.openqa.selenium.WebElement;
import java.io.File;
import java.io.IOException;
@@ -38,6 +41,7 @@
@Category({Git.class})
public class AllowedFileExtensionAdminTest extends BaseWebDriverTest
{
+ private final File TAR_FILE = TestFileUtils.getSampleData("fileTypes/targz_sample.tar.gz");
private final File CSV_FILE = TestFileUtils.getSampleData("fileTypes/csv_sample.csv");
private final File TSV_FILE = TestFileUtils.getSampleData("fileTypes/tsv_sample.tsv");
private final File TXT_FILE = TestFileUtils.getSampleData("fileTypes/sample.txt");
@@ -45,10 +49,11 @@ public class AllowedFileExtensionAdminTest extends BaseWebDriverTest
private final File XLSX_FILE = TestFileUtils.getSampleData("fileTypes/xlsx_sample.xlsx");
private final Map fileMap = Map.of(
- ".csv", CSV_FILE,
+ ".tar.gz", TAR_FILE,
+ ".xls", XLS_FILE,
".tsv", TSV_FILE,
+ ".csv", CSV_FILE,
".txt", TXT_FILE,
- ".xls", XLS_FILE,
".xlsx", XLSX_FILE
);
@@ -65,7 +70,7 @@ protected void doCleanup(boolean afterTest)
_containerHelper.deleteProject(getProjectName(), afterTest);
try
{
- deleteAllAllowedFileExtension();
+ AllowedFileExtensionAdminPage.deleteAllAllowedFileExtension(createDefaultConnection());
}
catch (IOException | CommandException e)
{
@@ -78,17 +83,20 @@ private void doSetup()
_containerHelper.createProject(getProjectName(), null);
goToProjectHome();
- new PortalHelper(getDriver()).addWebPart("Files");
- new PortalHelper(getDriver()).addWebPart("Sample Types");
- new PortalHelper(getDriver()).addWebPart("Lists");
- new PortalHelper(getDriver()).addWebPart("Messages List");
+ new PortalHelper(getDriver()).doInAdminMode(ph -> {
+ ph.addWebPart("Files");
+ ph.addWebPart("Sample Types");
+ ph.addWebPart("Lists");
+ ph.addWebPart("Messages List");
+ });
+
}
@Before
public void beforeTest() throws IOException, CommandException
{
log("Use API to delete any existing allowed extensions.");
- deleteAllAllowedFileExtension();
+ AllowedFileExtensionAdminPage.deleteAllAllowedFileExtension(createDefaultConnection());
log("Delete any files that have already been uploaded.");
goToProjectHome();
@@ -104,10 +112,10 @@ public void beforeTest() throws IOException, CommandException
*
*
Add several file extensions as allowed extensions, then upload files of that type.
*
Upload a file that is not allowed and validate it is rejected.
- *
Remove an allowed file type and validate files of that type can not be uploaded.
+ *
Remove an allowed file type and validate files of that type cannot be uploaded.
*
Click 'Delete All' and cancel out of confirmation, validate no change.
*
Click 'Delete All' and validate any file type can be uploaded.
- *
Edit an allowed extension, .xls to .xlsx, and validate .xlsx files can be uploaded but .xls can not.
+ *
Edit an allowed extension, .xls to .xlsx, and validate .xlsx files can be uploaded, but .xls cannot.
*
Validate extension value must start with a '.'
*
Validate duplicate extensions are not allowed.
*
Validate blank extension type is not allowed.
@@ -115,7 +123,7 @@ public void beforeTest() throws IOException, CommandException
*
*/
@Test
- public void testAddUpdateAndDelete()
+ public void testAddUpdateAndDeleteFileExtensions()
{
List allowedTypes = new ArrayList<>();
@@ -211,17 +219,17 @@ public void testAddUpdateAndDelete()
editExtension.setValue(newExtension);
- // Issue 53039 validate dirty bit warning.
- log("Validate that an alert is shown is the change is not saved.");
- Locator.tagWithClass("a", "brand-logo").findElement(getDriver()).click();
- Alert alert = waitForAlert();
-
- checker().withScreenshot()
- .verifyTrue("Alert text doesn't have expected text.",
- alert.getText().contains("Changes you made may not be saved."));
-
- log("Dismiss the alert.");
- alert.dismiss();
+// // Issue 53039 validate dirty bit warning.
+// log("Validate that an alert is shown if the change is not saved.");
+// Locator.tagWithClass("a", "brand-logo").findElement(getDriver()).click();
+// Alert alert = waitForAlert();
+//
+// checker().withScreenshot()
+// .verifyTrue("Alert text doesn't have expected text.",
+// alert.getText().contains("Changes you made may not be saved."));
+//
+// log("Dismiss the alert.");
+// alert.dismiss();
log("Save the change.");
allowedFileExtensionAdminPage.clickSaveUpdateExtension();
@@ -313,8 +321,8 @@ private void uploadToFileWebPartExcluded(List excludedTypes)
Window> errorWindow = _fileBrowserHelper.uploadFileExpectingError(fileMap.get(excludedType));
checker().withScreenshot()
- .verifyEquals(String.format("Error message for excluded file type '%s' not as expected.", excludedType),
- String.format("This file type [%s] is not allowed.", excludedType.replace(".", "")), errorWindow.getBody());
+ .verifyTrue(String.format("Error message for excluded file type '%s' not as expected.", excludedType),
+ errorWindow.getBody().contains(String.format("This file type [%s] is not allowed.", excludedType.replace(".", ""))));
click(Ext4Helper.Locators.ext4Button("OK"));
}
@@ -323,7 +331,7 @@ private void uploadToFileWebPartExcluded(List excludedTypes)
/**
*
- * Using a list validate that attachments work correctly with the allowed files list.
+ * Using a list, validate that attachments work correctly with the allowed files list.
*
*
* After creating a list that has an auto-index and a attachment field as the only field this test will:
@@ -336,7 +344,7 @@ private void uploadToFileWebPartExcluded(List excludedTypes)
*
*/
@Test
- public void testAllowedFileExtensionsInLists()
+ public void testAllowedFileExtensionsInLists() throws IOException, CommandException
{
List allowedTypes = new ArrayList<>();
@@ -353,12 +361,13 @@ public void testAllowedFileExtensionsInLists()
goToProjectHome();
String listName = "Test Allowed Attachments";
- String keyField = "Key";
String attachmentField = "Attachment Field";
log(String.format("Create a list '%s' with attachment field and auto-increment key.", listName));
- _listHelper.createList(getProjectName(), listName, keyField,
- new FieldDefinition(attachmentField, FieldDefinition.ColumnType.Attachment));
+ Connection connection = createDefaultConnection();
+ ListDefinition listDef = new IntListDefinition(listName, "Key");
+ listDef.addField(new FieldDefinition(attachmentField, FieldDefinition.ColumnType.Attachment));
+ listDef.create(connection, getProjectName());
goToManageLists();
_listHelper.goToList(listName);
@@ -379,8 +388,7 @@ public void testAllowedFileExtensionsInLists()
_listHelper.goToList(listName);
_listHelper.insertNewRow(Map.of(attachmentField, fileMap.get(excludedType).getAbsolutePath()), false);
- // Not sure why we record two exceptions.
- checkExpectedErrors(2);
+ validateErrorPage(fileMap.get(excludedType).getName());
log("Click 'Back' button and select a file type that is allowed.");
waitForElement(Locator.button("Back"));
@@ -388,11 +396,11 @@ public void testAllowedFileExtensionsInLists()
waitForElement(Locator.name("quf_" + attachmentField));
- // Same as Issue 53026, the fields are cleared after hitting back button. Covewrage for that issue is in
+ // Same as Issue 53026, the fields are cleared after hitting back button. Coverage for that issue is in
// testAllowedFileExtensionsInSampleType test.
log("Clear the file field.");
FileInput el = FileInput.FileInput(Locator.name("quf_" + attachmentField), getDriver()).findWhenNeeded();
- executeScript("arguments[0].value = '';", el.getComponentElement());
+ el.clear();
File fileAgain = fileMap.get(".txt");
log(String.format("Add the '%s' file to the list again (it is an allowed file).", fileAgain.getName()));
@@ -469,7 +477,7 @@ public void testAllowedFileExtensionsInSampleType()
i++;
}
- // The order of the grid is last one added is at the top, which is opposite of how they were added to the list.
+ // The order of the grid is the last one added is at the top, which is opposite of how they were added to the list.
Collections.reverse(expectedValues);
List actualValues = sampleTypeHelper.getSamplesDataRegionTable().getColumnDataAsText(stFileField);
@@ -479,7 +487,7 @@ public void testAllowedFileExtensionsInSampleType()
log("Create a sample that tries to upload a disallowed file type.");
String sampleId = String.format("S-%d", i);
String description= "Some text for the description.";
- String amount = "5.00";
+ String amount = "5.0";
fieldMap = Map.of("Name", sampleId,
"Description", description,
@@ -487,8 +495,7 @@ public void testAllowedFileExtensionsInSampleType()
"StoredAmount", amount);
sampleTypeHelper.insertRow(fieldMap);
- // Not sure why we record two exceptions.
- checkExpectedErrors(2);
+ validateErrorPage(fileMap.get(excludedType).getName());
// Issue 53027
goToProjectHome();
@@ -505,10 +512,10 @@ public void testAllowedFileExtensionsInSampleType()
sampleId, rowMap.get("Name"));
checker().verifyEquals("'Amount' field in grid does not have expected value.",
- amount, rowMap.get("Amount"));
+ amount, rowMap.get("StoredAmount"));
checker().verifyEquals(String.format("'%s' field in grid does not have expected value.", stFileField),
- "", rowMap.get(stFileField));
+ " ", rowMap.get(stFileField));
checker().screenShotIfNewError("Field_Values_Error");
@@ -572,17 +579,26 @@ public void testAllowedFilesInMessages()
page.addAttachments(entry.getValue());
}
- List notAllowedAttachments = Locator.tagWithAttributeContaining("span", "id","filename")
- .findElements(getDriver())
- .stream().map(WebElement::getText).toList();
-
log(String.format("Try to create a message with title of '%s' with several allowed files as attachments, and one disallowed file type.", allowedTitle));
page.submit();
- // Not sure why we record two exceptions.
- checkExpectedErrors(2);
+ validateErrorPage(fileMap.get(excludedType).getName());
+
+ }
+
+ private void validateErrorPage(String notAllowedFile)
+ {
+
+ String notAllowedFileExtension = notAllowedFile.substring(notAllowedFile.lastIndexOf(".") + 1);
+ String expectedErrorMsg = String.format("%s: This file type [%s] is not allowed.",
+ notAllowedFile, notAllowedFileExtension);
+
+ checker().withScreenshot()
+ .verifyTrue(String.format("Error message '%s' not found on the error page.", expectedErrorMsg),
+ waitForElement(Locator.tagContainingText("div", expectedErrorMsg).withClass("labkey-error-heading"),
+ 1_500, false));
}
private AllowedFileExtensionAdminPage setAllowedExtensions(List allowedTypes, List expectedTypes)
From e8eb0913a627ad360dc586be3c39872ef7f9fdb4 Mon Sep 17 00:00:00 2001
From: labkey-danield
Date: Fri, 30 May 2025 18:13:19 -0700
Subject: [PATCH 09/13] Add a tar.gz file to the mix. Move
deleteAllAllowedFileExtensions to the AllowedFileExtensionAdminPage
Consolidate button code in AllowedFileExtensionAdminPage Remove calls to
checkExpectedErrors. Adding FileInput.clear method. Many other code review
feedback as well.
---
data/fileTypes/targz_sample.tar.gz | Bin 0 -> 953 bytes
.../labkey/test/components/html/FileInput.java | 5 +++++
2 files changed, 5 insertions(+)
create mode 100644 data/fileTypes/targz_sample.tar.gz
diff --git a/data/fileTypes/targz_sample.tar.gz b/data/fileTypes/targz_sample.tar.gz
new file mode 100644
index 0000000000000000000000000000000000000000..2a66d934641e02dbd125510e8e83d5d9843a1a21
GIT binary patch
literal 953
zcmV;q14jHGiwFR$N;+r&1MOB{Xd^`!pIZOjKBy>oA_^<|WHCFt*+1DH5jJhwv?fh1
zyJ@n8qfT}=n>4%0W_MCIeUXYUCn~6@2vrZn2e}sopDg$wcX&_tbT0>j6vP)nxf4YN
z@7(;Uy~ImfwCy36AMAXy!*AyMX1@8p`7m6vm79~L$aq2O%EeCFhxf-y;&+5)gioqRx0hXPH!K7%l`@Rjs6cU
zmkrCRhp>+iQb%wefoq5RUl5o9|MNna1tdI3BZlEN_dmGn;d{Ux0Hlycre(4~_Rt;!
z$AXUmVC+I5ga5HV_P3;@DA{hWJ!32qbiNv(+}RtyAAsXp-3}oqxPKwV@NvAR)%8lv
z?9QJJng;-QbcbUh4>vtS*AX_J%*Z`G`Jj0kfTwnNwt-Q=L6ghX)bt!S?3`z~3NpP8
ze?4eg00=kX2lON=8rE{L)N)pfxL#eUIpwCi;@8V|RbOj`8^PozEKuSx8e)MKAs
zzVd8We_#A(ke@J+Zn)He=7BxppXQlxfBZ8rcmM$DAB6I~aGS?J!;?0y*hZ8V*a*)-
zPT)d}7@=u`35#TME+%EC5_603kdH8SL;o&bq7geeVXf8DNS<}AyhgK28DGG*zQii-
zVjKzum5<3OMXRW@S*qArz;jM^DP1h9^TKKzqA78yCEIz?q39V$=Aps@OifRjQ_?o#F=?kS-30T5
z$nAM#|4_F7%t-LNUciBeAgaJRk2;3MIQltB?ixvO;xHQr7Z}Xp1i$Nf-uPHW^+MK8
zDyEQ9QZTg=52qCq65P<^>6<(7ln_T1`W^J;|3j(%_OAbedVjF~
Date: Wed, 4 Jun 2025 17:51:48 -0700
Subject: [PATCH 10/13] Move most of the Admin Page specific test cases into a
separate class (AllowedFileExtensionsPageTest). Add a base class that has
some shared code.
---
.../admin/AllowedFileExtensionBaseTest.java | 66 +++++++
...est.java => AllowedFileExtensionTest.java} | 127 +-------------
.../admin/AllowedFileExtensionsPageTest.java | 161 ++++++++++++++++++
3 files changed, 234 insertions(+), 120 deletions(-)
create mode 100644 src/org/labkey/test/tests/core/admin/AllowedFileExtensionBaseTest.java
rename src/org/labkey/test/tests/core/admin/{AllowedFileExtensionAdminTest.java => AllowedFileExtensionTest.java} (76%)
create mode 100644 src/org/labkey/test/tests/core/admin/AllowedFileExtensionsPageTest.java
diff --git a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionBaseTest.java b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionBaseTest.java
new file mode 100644
index 0000000000..671b573e57
--- /dev/null
+++ b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionBaseTest.java
@@ -0,0 +1,66 @@
+package org.labkey.test.tests.core.admin;
+
+import org.labkey.remoteapi.CommandException;
+import org.labkey.test.BaseWebDriverTest;
+import org.labkey.test.TestFileUtils;
+import org.labkey.test.components.html.Input;
+import org.labkey.test.pages.core.admin.AllowedFileExtensionAdminPage;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+public abstract class AllowedFileExtensionBaseTest extends BaseWebDriverTest
+{
+
+ protected final File TAR_FILE = TestFileUtils.getSampleData("fileTypes/targz_sample.tar.gz");
+ protected final File CSV_FILE = TestFileUtils.getSampleData("fileTypes/csv_sample.csv");
+ protected final File TSV_FILE = TestFileUtils.getSampleData("fileTypes/tsv_sample.tsv");
+ protected final File TXT_FILE = TestFileUtils.getSampleData("fileTypes/sample.txt");
+ protected final File XLS_FILE = TestFileUtils.getSampleData("fileTypes/xls_sample.xls");
+ protected final File XLSX_FILE = TestFileUtils.getSampleData("fileTypes/xlsx_sample.xlsx");
+
+ protected final Map fileMap = Map.of(
+ ".tar.gz", TAR_FILE,
+ ".xls", XLS_FILE,
+ ".tsv", TSV_FILE,
+ ".csv", CSV_FILE,
+ ".txt", TXT_FILE,
+ ".xlsx", XLSX_FILE
+ );
+
+ @Override
+ protected void doCleanup(boolean afterTest)
+ {
+ _containerHelper.deleteProject(getProjectName(), afterTest);
+ try
+ {
+ AllowedFileExtensionAdminPage.deleteAllAllowedFileExtension(createDefaultConnection());
+ }
+ catch (IOException | CommandException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected AllowedFileExtensionAdminPage setAllowedExtensions(List allowedTypes, List expectedTypes)
+ {
+ AllowedFileExtensionAdminPage allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
+
+ for (String extension : allowedTypes)
+ {
+ allowedFileExtensionAdminPage.setExtension(extension);
+ allowedFileExtensionAdminPage.clickSaveExtension();
+ }
+
+ List extensions = allowedFileExtensionAdminPage.getAllowedExtensions();
+
+ checker().withScreenshot()
+ .verifyEqualsSorted("List of 'Allowed extensions' is not as expected.",
+ expectedTypes, extensions.stream().map(Input::getValue).toList());
+
+ return allowedFileExtensionAdminPage;
+ }
+
+}
diff --git a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionTest.java
similarity index 76%
rename from src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java
rename to src/org/labkey/test/tests/core/admin/AllowedFileExtensionTest.java
index f307021d04..971024ffdc 100644
--- a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionAdminTest.java
+++ b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionTest.java
@@ -7,10 +7,7 @@
import org.labkey.remoteapi.CommandException;
import org.labkey.remoteapi.Connection;
-import org.labkey.remoteapi.domain.PropertyDescriptor;
-import org.labkey.test.BaseWebDriverTest;
import org.labkey.test.Locator;
-import org.labkey.test.TestFileUtils;
import org.labkey.test.categories.Git;
import org.labkey.test.components.ext4.Window;
import org.labkey.test.components.html.FileInput;
@@ -24,7 +21,6 @@
import org.labkey.test.util.Ext4Helper;
import org.labkey.test.util.PortalHelper;
import org.labkey.test.util.SampleTypeHelper;
-import org.labkey.test.util.TestDataGenerator;
import org.labkey.test.util.exp.SampleTypeAPIHelper;
import org.labkey.test.pages.announcements.InsertPage;
@@ -39,45 +35,16 @@
import static org.labkey.test.util.DataRegionTable.DataRegion;
@Category({Git.class})
-public class AllowedFileExtensionAdminTest extends BaseWebDriverTest
+public class AllowedFileExtensionTest extends AllowedFileExtensionBaseTest
{
- private final File TAR_FILE = TestFileUtils.getSampleData("fileTypes/targz_sample.tar.gz");
- private final File CSV_FILE = TestFileUtils.getSampleData("fileTypes/csv_sample.csv");
- private final File TSV_FILE = TestFileUtils.getSampleData("fileTypes/tsv_sample.tsv");
- private final File TXT_FILE = TestFileUtils.getSampleData("fileTypes/sample.txt");
- private final File XLS_FILE = TestFileUtils.getSampleData("fileTypes/xls_sample.xls");
- private final File XLSX_FILE = TestFileUtils.getSampleData("fileTypes/xlsx_sample.xlsx");
-
- private final Map fileMap = Map.of(
- ".tar.gz", TAR_FILE,
- ".xls", XLS_FILE,
- ".tsv", TSV_FILE,
- ".csv", CSV_FILE,
- ".txt", TXT_FILE,
- ".xlsx", XLSX_FILE
- );
@BeforeClass
public static void setupProject()
{
- AllowedFileExtensionAdminTest init = getCurrentTest();
+ AllowedFileExtensionTest init = getCurrentTest();
init.doSetup();
}
- @Override
- protected void doCleanup(boolean afterTest)
- {
- _containerHelper.deleteProject(getProjectName(), afterTest);
- try
- {
- AllowedFileExtensionAdminPage.deleteAllAllowedFileExtension(createDefaultConnection());
- }
- catch (IOException | CommandException e)
- {
- throw new RuntimeException(e);
- }
- }
-
private void doSetup()
{
_containerHelper.createProject(getProjectName(), null);
@@ -105,7 +72,8 @@ public void beforeTest() throws IOException, CommandException
/**
*
- * Test the 'Allowed File Extension Admin' page and use the files web part as part of the validation process.
+ * Test the 'Allowed File Extension' using the files web part as part of the validation process. This also
+ * validates some changes made on the admin page behave as expected.
*
*
* This test will:
@@ -113,12 +81,8 @@ public void beforeTest() throws IOException, CommandException
*
Add several file extensions as allowed extensions, then upload files of that type.
*
Upload a file that is not allowed and validate it is rejected.
*
Remove an allowed file type and validate files of that type cannot be uploaded.
- *
Click 'Delete All' and cancel out of confirmation, validate no change.
*
Click 'Delete All' and validate any file type can be uploaded.
*
Edit an allowed extension, .xls to .xlsx, and validate .xlsx files can be uploaded, but .xls cannot.
- *
Validate extension value must start with a '.'
- *
Validate duplicate extensions are not allowed.
- *
Validate blank extension type is not allowed.
*
*
*/
@@ -163,26 +127,8 @@ public void testAddUpdateAndDeleteFileExtensions()
log(String.format("Verify upload of '%s' fails.", excludedType));
uploadToFileWebPartExcluded(excludedTypes);
- allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
-
- log("Click 'Delete All' but cancel out of the confirmation dialog.");
-
- allowedFileExtensionAdminPage.deleteAllExtensions(false);
+ log("Click 'Delete All' and accept the confirmation dialog.");
- extensions = allowedFileExtensionAdminPage.getAllowedExtensions();
-
- checker().withScreenshot()
- .verifyEqualsSorted("List of 'Allowed extensions' is not as expected after canceling 'Delete All'.",
- allowedTypes, extensions.stream().map(Input::getValue).toList());
-
- // Issue 53039.
- log("Validate that canceling the 'Delete All' dialog does not set the dirty bit.");
- // Using goToProjectHome will validate navigaiton happened.
- goToProjectHome();
-
- log("Now, click 'Delete All' and accept the confirmation dialog.");
-
- // Have to navigate back.
allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
allowedFileExtensionAdminPage.deleteAllExtensions(true);
@@ -219,18 +165,6 @@ public void testAddUpdateAndDeleteFileExtensions()
editExtension.setValue(newExtension);
-// // Issue 53039 validate dirty bit warning.
-// log("Validate that an alert is shown if the change is not saved.");
-// Locator.tagWithClass("a", "brand-logo").findElement(getDriver()).click();
-// Alert alert = waitForAlert();
-//
-// checker().withScreenshot()
-// .verifyTrue("Alert text doesn't have expected text.",
-// alert.getText().contains("Changes you made may not be saved."));
-//
-// log("Dismiss the alert.");
-// alert.dismiss();
-
log("Save the change.");
allowedFileExtensionAdminPage.clickSaveUpdateExtension();
@@ -249,35 +183,6 @@ public void testAddUpdateAndDeleteFileExtensions()
log(String.format("Verify file with the old extension '%s' is excluded.", oldExtension));
uploadToFileWebPartExcluded(excludedTypes);
- allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
- allowedFileExtensionAdminPage.setExtension("not .an extension");
- String expectedValue = "File extension must start with a '.'";
- String actualValue = allowedFileExtensionAdminPage.clickSaveExpectingError();
- checker().withScreenshot()
- .verifyEquals("Incorrect error message for invalid extension.",
- expectedValue, actualValue);
-
- allowedFileExtensionAdminPage.setExtension(allowedTypes.get(0));
- expectedValue = String.format("'%s' already exists. Duplicate values not allowed.", allowedTypes.get(0));
- actualValue = allowedFileExtensionAdminPage.clickSaveExpectingError();
- checker().withScreenshot()
- .verifyEquals("Incorrect error message for duplicate extension.",
- expectedValue, actualValue);
-
- allowedFileExtensionAdminPage.setExtension(allowedTypes.get(1).toUpperCase());
- expectedValue = String.format("'%s' already exists. Duplicate values not allowed.", allowedTypes.get(1).toUpperCase());
- actualValue = allowedFileExtensionAdminPage.clickSaveExpectingError();
- checker().withScreenshot()
- .verifyEquals("Incorrect error message for duplicate extension but different case.",
- expectedValue, actualValue);
-
- allowedFileExtensionAdminPage.setExtension("");
- expectedValue = "File extension must not be blank.";
- actualValue = allowedFileExtensionAdminPage.clickSaveExpectingError();
- checker().withScreenshot()
- .verifyEquals("Incorrect error message for blank extension value.",
- expectedValue, actualValue);
-
}
private void uploadToFileWebPartAllowed(List excludedTypes)
@@ -601,29 +506,10 @@ private void validateErrorPage(String notAllowedFile)
1_500, false));
}
- private AllowedFileExtensionAdminPage setAllowedExtensions(List allowedTypes, List expectedTypes)
- {
- AllowedFileExtensionAdminPage allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
-
- for (String extension : allowedTypes)
- {
- allowedFileExtensionAdminPage.setExtension(extension);
- allowedFileExtensionAdminPage.clickSaveExtension();
- }
-
- List extensions = allowedFileExtensionAdminPage.getAllowedExtensions();
-
- checker().withScreenshot()
- .verifyEqualsSorted("List of 'Allowed extensions' is not as expected.",
- expectedTypes, extensions.stream().map(Input::getValue).toList());
-
- return allowedFileExtensionAdminPage;
- }
-
@Override
protected String getProjectName()
{
- return "Allowed File Extension Admin Test Project " + TRICKY_CHARACTERS_FOR_PROJECT_NAMES;
+ return "Allowed File Extension Test Project " + TRICKY_CHARACTERS_FOR_PROJECT_NAMES;
}
@Override
@@ -631,4 +517,5 @@ public List getAssociatedModules()
{
return Arrays.asList();
}
+
}
diff --git a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionsPageTest.java b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionsPageTest.java
new file mode 100644
index 0000000000..5e1454a094
--- /dev/null
+++ b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionsPageTest.java
@@ -0,0 +1,161 @@
+package org.labkey.test.tests.core.admin;
+
+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.test.Locator;
+import org.labkey.test.categories.Git;
+import org.labkey.test.components.html.Input;
+import org.labkey.test.pages.core.admin.AllowedFileExtensionAdminPage;
+import org.openqa.selenium.Alert;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+@Category({Git.class})
+public class AllowedFileExtensionsPageTest extends AllowedFileExtensionBaseTest
+{
+ @BeforeClass
+ public static void setupProject()
+ {
+ AllowedFileExtensionsPageTest init = getCurrentTest();
+ init.doSetup();
+ }
+
+ private void doSetup()
+ {
+ _containerHelper.createProject(getProjectName(), null);
+ goToProjectHome();
+ }
+
+ @Before
+ public void beforeTest() throws IOException, CommandException
+ {
+ log("Use API to delete any existing allowed extensions.");
+ AllowedFileExtensionAdminPage.deleteAllAllowedFileExtension(createDefaultConnection());
+ }
+
+ /**
+ *
+ * Test the 'Allowed File Extension Admin'.
+ *
+ *
+ * This test will:
+ *
+ *
Add several file extensions as allowed extensions, and validate they are listed in alphabetical order.
+ *
Click 'Delete All' and cancel out of confirmation, validate no change.
+ *
Validate no dirty bit after canceling out of 'Delete All'.
+ *
Edit an allowed extension, .txt to .pdf, don't save and validate the dirty bit.
+ *
Validate extension value must start with a '.'
+ *
Validate duplicate extensions are not allowed.
+ *
Validate blank extension type is not allowed.
+ *
+ *
+ */
+ @Test
+ public void testAddUpdateAndDeleteFileExtensions()
+ {
+
+ List allowedTypes = new ArrayList<>(fileMap.keySet());
+
+ log(String.format("Add the following as allowed extensions: %s", allowedTypes));
+ AllowedFileExtensionAdminPage allowedFileExtensionAdminPage = setAllowedExtensions(allowedTypes, allowedTypes);
+
+ log("Validate that the allowed file extensions are listed in alphabetical order.");
+ List actualValues = allowedFileExtensionAdminPage.getAllowedExtensions().stream().map(Input::getValue).toList();
+ Collections.sort(allowedTypes);
+
+ checker().withScreenshot()
+ .verifyEquals("List of 'Allowed extensions' is not in the expected order.",
+ allowedTypes, actualValues);
+
+ log("Click 'Delete All' but cancel out of the confirmation dialog.");
+
+ allowedFileExtensionAdminPage.deleteAllExtensions(false);
+
+ List extensions = allowedFileExtensionAdminPage.getAllowedExtensions();
+
+ checker().withScreenshot()
+ .verifyEqualsSorted("List of 'Allowed extensions' is not as expected after canceling 'Delete All'.",
+ allowedTypes, extensions.stream().map(Input::getValue).toList());
+
+ // Issue 53039.
+ log("Validate that canceling the 'Delete All' dialog does not set the dirty bit.");
+
+ // Using goToProjectHome will validate no dirty bit is set and navigation can happen.
+ goToProjectHome();
+
+ allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
+
+ String oldExtension = ".txt";
+ String newExtension = ".pdf";
+
+ log(String.format("Edit the extension '%s' and change it to '%s'.", oldExtension, newExtension));
+
+ Input editExtension = allowedFileExtensionAdminPage.getAllowedExtension(allowedFileExtensionAdminPage.getAllowedExtensionIndex(oldExtension));
+
+ editExtension.setValue(newExtension);
+
+ // Issue 53039 validate dirty bit warning.
+ log("Validate that an alert is shown if the change is not saved.");
+ Locator.tagWithClass("a", "brand-logo").findElement(getDriver()).click();
+ Alert alert = waitForAlert();
+
+ checker().withScreenshot()
+ .verifyTrue("Alert text doesn't have expected text.",
+ alert.getText().contains("Changes you made may not be saved."));
+
+ log("Dismiss the alert.");
+ alert.dismiss();
+
+ log("Save the change.");
+ allowedFileExtensionAdminPage.clickSaveUpdateExtension();
+
+ allowedFileExtensionAdminPage.setExtension("not .an extension");
+ String expectedValue = "File extension must start with a '.'";
+ String actualValue = allowedFileExtensionAdminPage.clickSaveExpectingError();
+ checker().withScreenshot()
+ .verifyEquals("Incorrect error message for invalid extension.",
+ expectedValue, actualValue);
+
+ allowedFileExtensionAdminPage.setExtension(allowedTypes.get(0));
+ expectedValue = String.format("'%s' already exists. Duplicate values not allowed.", allowedTypes.get(0));
+ actualValue = allowedFileExtensionAdminPage.clickSaveExpectingError();
+ checker().withScreenshot()
+ .verifyEquals("Incorrect error message for duplicate extension.",
+ expectedValue, actualValue);
+
+ allowedFileExtensionAdminPage.setExtension(allowedTypes.get(1).toUpperCase());
+ expectedValue = String.format("'%s' already exists. Duplicate values not allowed.", allowedTypes.get(1).toUpperCase());
+ actualValue = allowedFileExtensionAdminPage.clickSaveExpectingError();
+ checker().withScreenshot()
+ .verifyEquals("Incorrect error message for duplicate extension but different case.",
+ expectedValue, actualValue);
+
+ allowedFileExtensionAdminPage.setExtension("");
+ expectedValue = "File extension must not be blank.";
+ actualValue = allowedFileExtensionAdminPage.clickSaveExpectingError();
+ checker().withScreenshot()
+ .verifyEquals("Incorrect error message for blank extension value.",
+ expectedValue, actualValue);
+
+ }
+
+ @Override
+ protected String getProjectName()
+ {
+ return "Allowed File Extension Page Test Project " + TRICKY_CHARACTERS_FOR_PROJECT_NAMES;
+ }
+
+ @Override
+ public List getAssociatedModules()
+ {
+ return Arrays.asList();
+ }
+
+}
From d3dd6e664e327c41aa47f153c449667f6b36fbd8 Mon Sep 17 00:00:00 2001
From: labkey-danield
Date: Wed, 4 Jun 2025 21:30:03 -0700
Subject: [PATCH 11/13] Change test names.
---
.../labkey/test/tests/core/admin/AllowedFileExtensionTest.java | 2 +-
.../test/tests/core/admin/AllowedFileExtensionsPageTest.java | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionTest.java b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionTest.java
index 971024ffdc..b5cdb6f7aa 100644
--- a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionTest.java
+++ b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionTest.java
@@ -87,7 +87,7 @@ public void beforeTest() throws IOException, CommandException
*
*/
@Test
- public void testAddUpdateAndDeleteFileExtensions()
+ public void testAllowedFileExtensionsInFileWebPart()
{
List allowedTypes = new ArrayList<>();
diff --git a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionsPageTest.java b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionsPageTest.java
index 5e1454a094..fc8af78c98 100644
--- a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionsPageTest.java
+++ b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionsPageTest.java
@@ -58,7 +58,7 @@ public void beforeTest() throws IOException, CommandException
*
*/
@Test
- public void testAddUpdateAndDeleteFileExtensions()
+ public void testAllowFileExtensionsAdminPage()
{
List allowedTypes = new ArrayList<>(fileMap.keySet());
From 1b4d6b05e30959c1ae2a20387361132f2c7e6eed Mon Sep 17 00:00:00 2001
From: labkey-danield
Date: Fri, 6 Jun 2025 17:26:19 -0700
Subject: [PATCH 12/13] Commented out the parts of the test that check for
dirty bit. Cleaned up the biologics AllowedFileExtensionsTest (removed reset
errors, used existing methods, updated expected error message). Added
AppRegisterCellLinePage.setColumnValue that takes a file parameter. Added
AppRegisterCellLinePage.clickSubmitExpectingError. Updated
ThreadAttachment.clickRemove to return a confirmation dialog. Added
ThreadEditor.clickCreateBtnExpectingError.
---
.../admin/AllowedFileExtensionsPageTest.java | 70 ++++++++++---------
1 file changed, 37 insertions(+), 33 deletions(-)
diff --git a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionsPageTest.java b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionsPageTest.java
index fc8af78c98..e82b68ad3c 100644
--- a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionsPageTest.java
+++ b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionsPageTest.java
@@ -48,9 +48,7 @@ public void beforeTest() throws IOException, CommandException
* This test will:
*
*
Add several file extensions as allowed extensions, and validate they are listed in alphabetical order.
- *
Click 'Delete All' and cancel out of confirmation, validate no change.
- *
Validate no dirty bit after canceling out of 'Delete All'.
- *
Edit an allowed extension, .txt to .pdf, don't save and validate the dirty bit.
+ *
Click 'Delete All' and cancel out of confirmation.
*
Validate extension value must start with a '.'
*
Validate duplicate extensions are not allowed.
*
Validate blank extension type is not allowed.
@@ -84,37 +82,43 @@ public void testAllowFileExtensionsAdminPage()
.verifyEqualsSorted("List of 'Allowed extensions' is not as expected after canceling 'Delete All'.",
allowedTypes, extensions.stream().map(Input::getValue).toList());
+ // Issue 38785
+ // Selenium launches the firefox browser with a prefernce set that (basically) disabled the dirty bit.
+ // As a result, checking for the dirty bit dialog prompt, or a missing dialog, is doable until 38785 is addressed.
// Issue 53039.
- log("Validate that canceling the 'Delete All' dialog does not set the dirty bit.");
-
- // Using goToProjectHome will validate no dirty bit is set and navigation can happen.
- goToProjectHome();
-
- allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
-
- String oldExtension = ".txt";
- String newExtension = ".pdf";
-
- log(String.format("Edit the extension '%s' and change it to '%s'.", oldExtension, newExtension));
-
- Input editExtension = allowedFileExtensionAdminPage.getAllowedExtension(allowedFileExtensionAdminPage.getAllowedExtensionIndex(oldExtension));
-
- editExtension.setValue(newExtension);
-
- // Issue 53039 validate dirty bit warning.
- log("Validate that an alert is shown if the change is not saved.");
- Locator.tagWithClass("a", "brand-logo").findElement(getDriver()).click();
- Alert alert = waitForAlert();
-
- checker().withScreenshot()
- .verifyTrue("Alert text doesn't have expected text.",
- alert.getText().contains("Changes you made may not be saved."));
-
- log("Dismiss the alert.");
- alert.dismiss();
-
- log("Save the change.");
- allowedFileExtensionAdminPage.clickSaveUpdateExtension();
+// log("Validate that canceling the 'Delete All' dialog does not set the dirty bit.");
+//
+// // Using goToProjectHome will validate no dirty bit is set and navigation can happen.
+// goToProjectHome();
+//
+// allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
+
+ // Issue 38785
+ // Selenium launches the firefox browser with a prefernce set that (basically) disabled the dirty bit.
+ // As a result, checking for the dirty bit dialog prompt, or a missing dialog, is doable until 38785 is addressed.
+// String oldExtension = ".txt";
+// String newExtension = ".pdf";
+//
+// log(String.format("Edit the extension '%s' and change it to '%s'.", oldExtension, newExtension));
+//
+// Input editExtension = allowedFileExtensionAdminPage.getAllowedExtension(allowedFileExtensionAdminPage.getAllowedExtensionIndex(oldExtension));
+//
+// editExtension.setValue(newExtension);
+//
+// // Issue 53039 validate dirty bit warning.
+// log("Validate that an alert is shown if the change is not saved.");
+// Locator.tagWithClass("a", "brand-logo").findElement(getDriver()).click();
+// Alert alert = waitForAlert();
+//
+// checker().withScreenshot()
+// .verifyTrue("Alert text doesn't have expected text.",
+// alert.getText().contains("Changes you made may not be saved."));
+//
+// log("Dismiss the alert.");
+// alert.dismiss();
+//
+// log("Save the change.");
+// allowedFileExtensionAdminPage.clickSaveUpdateExtension();
allowedFileExtensionAdminPage.setExtension("not .an extension");
String expectedValue = "File extension must start with a '.'";
From 067c2a36858552a070f7b2d87200aa353ba716b0 Mon Sep 17 00:00:00 2001
From: labkey-danield
Date: Mon, 9 Jun 2025 17:55:19 -0700
Subject: [PATCH 13/13] Update tests to validate the complete error message.
Fixed some typos in comments.
---
.../core/admin/AllowedFileExtensionTest.java | 32 +++++++++++--------
.../admin/AllowedFileExtensionsPageTest.java | 5 +--
2 files changed, 21 insertions(+), 16 deletions(-)
diff --git a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionTest.java b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionTest.java
index b5cdb6f7aa..70b95debb2 100644
--- a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionTest.java
+++ b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionTest.java
@@ -108,7 +108,7 @@ public void testAllowedFileExtensionsInFileWebPart()
uploadToFileWebPartAllowed(excludedTypes);
log(String.format("Verify upload of '%s' fails", excludedType));
- uploadToFileWebPartExcluded(excludedTypes);
+ uploadToFileWebPartExcluded(excludedTypes, allowedTypes);
AllowedFileExtensionAdminPage allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
@@ -125,7 +125,7 @@ public void testAllowedFileExtensionsInFileWebPart()
allowedTypes, extensions.stream().map(Input::getValue).toList());
log(String.format("Verify upload of '%s' fails.", excludedType));
- uploadToFileWebPartExcluded(excludedTypes);
+ uploadToFileWebPartExcluded(excludedTypes, allowedTypes);
log("Click 'Delete All' and accept the confirmation dialog.");
@@ -181,7 +181,7 @@ public void testAllowedFileExtensionsInFileWebPart()
uploadToFileWebPartAllowed(excludedTypes);
log(String.format("Verify file with the old extension '%s' is excluded.", oldExtension));
- uploadToFileWebPartExcluded(excludedTypes);
+ uploadToFileWebPartExcluded(excludedTypes, allowedTypes);
}
@@ -208,11 +208,13 @@ private void uploadToFileWebPartAllowed(List excludedTypes)
}
- private void uploadToFileWebPartExcluded(List excludedTypes)
+ private void uploadToFileWebPartExcluded(List excludedTypes, List allowedTypes)
{
goToProjectHome();
+ Collections.sort(allowedTypes);
+
for (String excludedType : excludedTypes)
{
@@ -226,8 +228,10 @@ private void uploadToFileWebPartExcluded(List excludedTypes)
Window> errorWindow = _fileBrowserHelper.uploadFileExpectingError(fileMap.get(excludedType));
checker().withScreenshot()
- .verifyTrue(String.format("Error message for excluded file type '%s' not as expected.", excludedType),
- errorWindow.getBody().contains(String.format("This file type [%s] is not allowed.", excludedType.replace(".", ""))));
+ .verifyEquals(String.format("Error message for excluded file type '%s' not as expected.", excludedType),
+ String.format("This file type [%s] is not allowed. Accepted file extensions: %s",
+ excludedType.replace(".", ""), allowedTypes),
+ errorWindow.getBody());
click(Ext4Helper.Locators.ext4Button("OK"));
}
@@ -293,7 +297,7 @@ public void testAllowedFileExtensionsInLists() throws IOException, CommandExcept
_listHelper.goToList(listName);
_listHelper.insertNewRow(Map.of(attachmentField, fileMap.get(excludedType).getAbsolutePath()), false);
- validateErrorPage(fileMap.get(excludedType).getName());
+ validateErrorPage(fileMap.get(excludedType).getName(), allowedTypes);
log("Click 'Back' button and select a file type that is allowed.");
waitForElement(Locator.button("Back"));
@@ -301,8 +305,7 @@ public void testAllowedFileExtensionsInLists() throws IOException, CommandExcept
waitForElement(Locator.name("quf_" + attachmentField));
- // Same as Issue 53026, the fields are cleared after hitting back button. Coverage for that issue is in
- // testAllowedFileExtensionsInSampleType test.
+ // Issue 53026, the fields are cleared after hitting the back button. Unlikely the issue will be fixed.
log("Clear the file field.");
FileInput el = FileInput.FileInput(Locator.name("quf_" + attachmentField), getDriver()).findWhenNeeded();
el.clear();
@@ -400,7 +403,7 @@ public void testAllowedFileExtensionsInSampleType()
"StoredAmount", amount);
sampleTypeHelper.insertRow(fieldMap);
- validateErrorPage(fileMap.get(excludedType).getName());
+ validateErrorPage(fileMap.get(excludedType).getName(), allowedTypes);
// Issue 53027
goToProjectHome();
@@ -488,17 +491,18 @@ public void testAllowedFilesInMessages()
page.submit();
- validateErrorPage(fileMap.get(excludedType).getName());
+ validateErrorPage(fileMap.get(excludedType).getName(), allowedTypes);
}
- private void validateErrorPage(String notAllowedFile)
+ private void validateErrorPage(String notAllowedFile, List allowedTypes)
{
+ Collections.sort(allowedTypes);
String notAllowedFileExtension = notAllowedFile.substring(notAllowedFile.lastIndexOf(".") + 1);
- String expectedErrorMsg = String.format("%s: This file type [%s] is not allowed.",
- notAllowedFile, notAllowedFileExtension);
+ String expectedErrorMsg = String.format("%s: This file type [%s] is not allowed. Accepted file extensions: %s",
+ notAllowedFile, notAllowedFileExtension, allowedTypes);
checker().withScreenshot()
.verifyTrue(String.format("Error message '%s' not found on the error page.", expectedErrorMsg),
diff --git a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionsPageTest.java b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionsPageTest.java
index e82b68ad3c..b98d1537aa 100644
--- a/src/org/labkey/test/tests/core/admin/AllowedFileExtensionsPageTest.java
+++ b/src/org/labkey/test/tests/core/admin/AllowedFileExtensionsPageTest.java
@@ -83,8 +83,9 @@ public void testAllowFileExtensionsAdminPage()
allowedTypes, extensions.stream().map(Input::getValue).toList());
// Issue 38785
- // Selenium launches the firefox browser with a prefernce set that (basically) disabled the dirty bit.
- // As a result, checking for the dirty bit dialog prompt, or a missing dialog, is doable until 38785 is addressed.
+ // Selenium launches the firefox browser with a preference set that (basically) disabled the dirty bit.
+ // As a result, checking for the dirty bit dialog prompt, or a missing dialog, is not doable until issue 38785
+ // is addressed.
// Issue 53039.
// log("Validate that canceling the 'Delete All' dialog does not set the dirty bit.");
//