Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
69c0be8
Issue 51524: Allowlist for acceptable types of file upload - automate…
labkey-sweta Apr 24, 2025
88070ee
Merge branch 'develop' into fb_allowFileExtensionAutoTest
labkey-danield May 1, 2025
e17dfa3
Reworking some of the allowed file extension tests.
labkey-danield May 2, 2025
ec58d43
Merge branch 'develop' into fb_allowFileExtensionAutoTest
labkey-danield May 2, 2025
f5455a0
Merge branch 'develop' into fb_allowFileExtensionAutoTest
labkey-danield May 5, 2025
159dead
Merge branch 'develop' into fb_allowFileExtensionAutoTest
labkey-danield May 6, 2025
f6aaa24
Merge branch 'develop' into fb_allowFileExtensionAutoTest
labkey-danield May 7, 2025
fafd0f7
Finish tests for SampleTypes and Lists.
labkey-danield May 7, 2025
6951263
Add tests for Messages.
labkey-danield May 8, 2025
1a454d4
Merge branch 'develop' into fb_allowFileExtensionAutoTest
labkey-danield May 8, 2025
e8514f5
Change test workflow to accommodate resolution of issue 53026 (not go…
labkey-danield May 12, 2025
795eb4e
Merge branch 'develop' into fb_allowFileExtensionAutoTest
labkey-danield May 14, 2025
204f26f
Move deleteAllAllowedFileExtensions out of AllowedFileExtensionAdminT…
labkey-danield May 15, 2025
c920717
Add check for dirty bit behavior to AllowedFileExtensionAdminTest
labkey-danield May 16, 2025
544e48b
Merge branch 'develop' into fb_allowFileExtensionAutoTest
labkey-danield May 19, 2025
9b8040a
Merge branch 'develop' into fb_allowFileExtensionAutoTest
labkey-danield May 22, 2025
b820591
Merge branch 'develop' into fb_allowFileExtensionAutoTest
labkey-danield May 29, 2025
5ec98ae
Add a tar.gz file to the mix.
labkey-danield May 31, 2025
e8eb091
Add a tar.gz file to the mix.
labkey-danield May 31, 2025
046b264
Merge branch 'develop' into fb_allowFileExtensionAutoTest
labkey-danield Jun 4, 2025
9bf8303
Move most of the Admin Page specific test cases into a separate class…
labkey-danield Jun 5, 2025
d3dd6e6
Change test names.
labkey-danield Jun 5, 2025
421dec5
Merge branch 'develop' into fb_allowFileExtensionAutoTest
labkey-danield Jun 5, 2025
755177d
Merge branch 'develop' into fb_allowFileExtensionAutoTest
labkey-danield Jun 6, 2025
1b4d6b0
Commented out the parts of the test that check for dirty bit.
labkey-danield Jun 7, 2025
a209aa0
Merge branch 'develop' into fb_allowFileExtensionAutoTest
labkey-danield Jun 9, 2025
067c2a3
Update tests to validate the complete error message.
labkey-danield Jun 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added data/fileTypes/targz_sample.tar.gz
Binary file not shown.
11 changes: 11 additions & 0 deletions src/org/labkey/test/TestScrubber.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -132,6 +133,15 @@ public void cleanSiteSettings()
TestLogger.error("Failed to re-enable file Upload after test", e);
}

try
{
AllowedFileExtensionAdminPage.deleteAllAllowedFileExtension(createDefaultConnection());
}
catch (Exception e)
{
TestLogger.error("Failed to remove list of allowed file extensions.", e);
}

try
{
LimitActiveUserPage.resetUserLimits(connection);
Expand Down Expand Up @@ -213,4 +223,5 @@ private void disableFileUploadSetting() throws IOException, CommandException
}
}
}

}
5 changes: 5 additions & 0 deletions src/org/labkey/test/components/html/FileInput.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ public void set(File file)
getWrapper().setFormElement(getComponentElement(), file);
}

public void clear()
{
getComponentElement().clear();
}

@Override
protected void assertElementType(WebElement el)
{
Expand Down
10 changes: 10 additions & 0 deletions src/org/labkey/test/pages/announcements/BaseUpdatePage.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
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;
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.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.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<AllowedFileExtensionAdminPage.ElementCache>
{
public AllowedFileExtensionAdminPage(WebDriver driver)
{
super(driver);
}

public static AllowedFileExtensionAdminPage beginAt(WebDriverWrapper webDriverWrapper)
{
webDriverWrapper.beginAt(WebTestHelper.buildURL("admin", "allowList",
Map.of("type", "FileExtension")));
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);

}

/**
* 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<String, Object> params = new HashMap<>();
params.put("type", "FileExtension");
command.setParameters(params);
command.execute(connection, "/");
}


public AllowedFileExtensionAdminPage setExtension(String extension)
{
elementCache().extension.set(extension);
return this;
}

public String clickSaveExpectingError()
{
return clickButtonExpectingError(elementCache().saveExtension);
}

public AllowedFileExtensionAdminPage clickSaveExtension()
{
return clickButtonNoError(elementCache().saveExtension);
}

public AllowedFileExtensionAdminPage updateExtension(String oldExtension, String newExtension)
{
getAllowedExtension(getAllowedExtensionIndex(oldExtension)).set(newExtension);
clearCache();
return this;
}

public AllowedFileExtensionAdminPage clickSaveUpdateExtension()
{
return clickButtonNoError(elementCache().saveUpdateExtension);
}

public String clickUpdateExtensionExpectingError()
{
return clickButtonExpectingError(elementCache().saveUpdateExtension);
}

private AllowedFileExtensionAdminPage clickButtonNoError(WebElement button)
{
clickAndWait(button);
clearCache();
assertNoLabKeyErrors();
return this;
}

private String clickButtonExpectingError(WebElement button)
{
clickAndWait(button);
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 AllowedFileExtensionAdminPage deleteExtension(String extension)
{
return deleteExtension(getAllowedExtensionIndex(extension));
}

public AllowedFileExtensionAdminPage deleteAllExtensions(boolean acceptAlert)
{
if (acceptAlert)
{
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());
}
return this;
}

public List<Input> getAllowedExtensions()
{
List<WebElement> 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<Input> allowedExtensions = getAllowedExtensions();

for(Input element : allowedExtensions)
{
if (element.getValue().equalsIgnoreCase(extension))
return index;

index++;
}

return -1;
}

@Override
protected ElementCache newElementCache()
{
return new ElementCache();
}

protected class ElementCache extends LabKeyPage<ElementCache>.ElementCache
{
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 Input extension = new Input(Locator.id("newValueTextField").findWhenNeeded(registerNewPanel), getDriver());
final WebElement saveExtension = Locator.lkButton("Save").findWhenNeeded(registerNewPanel);

final WebElement saveUpdateExtension = Locator.lkButton("Save").findWhenNeeded(existingPanel);

List<Input> allowedExtensions()
{
return Locator.inputByIdContaining("existingValue")
.findElements(elementCache().existingPanel)
.stream().map(el -> new Input(el, getDriver())).collect(Collectors.toList());
}

final List<WebElement> deleteExtensions = Locator.linkWithText("Delete").findElements(existingPanel);

final WebElement deleteAll = Locator.linkWithText("Delete All").findWhenNeeded(existingPanel);

}
}
8 changes: 8 additions & 0 deletions src/org/labkey/test/pages/core/admin/ShowAdminPage.java
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -280,6 +287,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);
Expand Down
Original file line number Diff line number Diff line change
@@ -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<String, File> 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<String> allowedTypes, List<String> expectedTypes)
{
AllowedFileExtensionAdminPage allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();

for (String extension : allowedTypes)
{
allowedFileExtensionAdminPage.setExtension(extension);
allowedFileExtensionAdminPage.clickSaveExtension();
}

List<Input> extensions = allowedFileExtensionAdminPage.getAllowedExtensions();

checker().withScreenshot()
.verifyEqualsSorted("List of 'Allowed extensions' is not as expected.",
expectedTypes, extensions.stream().map(Input::getValue).toList());

return allowedFileExtensionAdminPage;
}

}
Loading