Skip to content

Commit 504f0ef

Browse files
Issue 51524: Allowlist for acceptable types of file upload - automation test (#2428)
Co-authored-by: labkey-danield <[email protected]>
1 parent 37024cd commit 504f0ef

File tree

10 files changed

+1030
-8
lines changed

10 files changed

+1030
-8
lines changed

data/fileTypes/targz_sample.tar.gz

953 Bytes
Binary file not shown.

src/org/labkey/test/TestScrubber.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.labkey.remoteapi.Connection;
2121
import org.labkey.remoteapi.SimplePostCommand;
2222
import org.labkey.test.components.html.Checkbox;
23+
import org.labkey.test.pages.core.admin.AllowedFileExtensionAdminPage;
2324
import org.labkey.test.pages.core.admin.BaseSettingsPage;
2425
import org.labkey.test.pages.core.admin.ConfigureFileSystemAccessPage;
2526
import org.labkey.test.pages.core.admin.LimitActiveUserPage;
@@ -132,6 +133,15 @@ public void cleanSiteSettings()
132133
TestLogger.error("Failed to re-enable file Upload after test", e);
133134
}
134135

136+
try
137+
{
138+
AllowedFileExtensionAdminPage.deleteAllAllowedFileExtension(createDefaultConnection());
139+
}
140+
catch (Exception e)
141+
{
142+
TestLogger.error("Failed to remove list of allowed file extensions.", e);
143+
}
144+
135145
try
136146
{
137147
LimitActiveUserPage.resetUserLimits(connection);
@@ -213,4 +223,5 @@ private void disableFileUploadSetting() throws IOException, CommandException
213223
}
214224
}
215225
}
226+
216227
}

src/org/labkey/test/components/html/FileInput.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ public void set(File file)
3333
getWrapper().setFormElement(getComponentElement(), file);
3434
}
3535

36+
public void clear()
37+
{
38+
getComponentElement().clear();
39+
}
40+
3641
@Override
3742
protected void assertElementType(WebElement el)
3843
{

src/org/labkey/test/pages/announcements/BaseUpdatePage.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,22 @@ public PAGE setTitle(String title)
4242
return getThis();
4343
}
4444

45+
public String getTitle()
46+
{
47+
return elementCache().titleInput.get();
48+
}
49+
4550
public PAGE setBody(String body)
4651
{
4752
elementCache().bodyInput.set(body);
4853
return getThis();
4954
}
5055

56+
public String getBody()
57+
{
58+
return elementCache().bodyInput.get();
59+
}
60+
5161
public PAGE setRenderAs(WikiRendererType renderAs)
5262
{
5363
elementCache().rendererSelect.set(renderAs);
Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
package org.labkey.test.pages.core.admin;
2+
3+
import org.labkey.remoteapi.CommandException;
4+
import org.labkey.remoteapi.Connection;
5+
import org.labkey.remoteapi.SimplePostCommand;
6+
import org.labkey.test.BootstrapLocators;
7+
import org.labkey.test.Locator;
8+
import org.labkey.test.Locators;
9+
import org.labkey.test.WebDriverWrapper;
10+
import org.labkey.test.WebTestHelper;
11+
import org.labkey.test.components.html.Input;
12+
import org.labkey.test.pages.LabKeyPage;
13+
import org.labkey.test.util.PortalHelper;
14+
import org.openqa.selenium.NoSuchElementException;
15+
import org.openqa.selenium.StaleElementReferenceException;
16+
import org.openqa.selenium.TimeoutException;
17+
import org.openqa.selenium.WebDriver;
18+
import org.openqa.selenium.WebElement;
19+
import org.openqa.selenium.support.ui.ExpectedConditions;
20+
21+
import java.io.IOException;
22+
import java.util.HashMap;
23+
import java.util.List;
24+
import java.util.Map;
25+
import java.util.stream.Collectors;
26+
27+
import static org.junit.Assert.assertFalse;
28+
import static org.junit.Assert.assertTrue;
29+
30+
public class AllowedFileExtensionAdminPage extends LabKeyPage<AllowedFileExtensionAdminPage.ElementCache>
31+
{
32+
public AllowedFileExtensionAdminPage(WebDriver driver)
33+
{
34+
super(driver);
35+
}
36+
37+
public static AllowedFileExtensionAdminPage beginAt(WebDriverWrapper webDriverWrapper)
38+
{
39+
webDriverWrapper.beginAt(WebTestHelper.buildURL("admin", "allowList",
40+
Map.of("type", "FileExtension")));
41+
return new AllowedFileExtensionAdminPage(webDriverWrapper.getDriver());
42+
}
43+
44+
@Override
45+
protected void waitForPage()
46+
{
47+
waitFor(()-> {
48+
try
49+
{
50+
return !BootstrapLocators.loadingSpinner.areAnyVisible(getDriver()) &&
51+
elementCache().extension.getComponentElement().isDisplayed();
52+
}
53+
catch (NoSuchElementException | StaleElementReferenceException | TimeoutException retry)
54+
{
55+
return false;
56+
}
57+
}, "Allowed File Extensions page did not load in time.", 3_000);
58+
59+
}
60+
61+
/**
62+
* Clears any file extensions that are set as the only allowable names, letting users upload any filename they like.
63+
*
64+
* @param connection A connection object to use in the command.execute call.
65+
*/
66+
public static void deleteAllAllowedFileExtension(Connection connection) throws IOException, CommandException
67+
{
68+
SimplePostCommand command = new SimplePostCommand("admin", "deleteAllValues");
69+
Map<String, Object> params = new HashMap<>();
70+
params.put("type", "FileExtension");
71+
command.setParameters(params);
72+
command.execute(connection, "/");
73+
}
74+
75+
76+
public AllowedFileExtensionAdminPage setExtension(String extension)
77+
{
78+
elementCache().extension.set(extension);
79+
return this;
80+
}
81+
82+
public String clickSaveExpectingError()
83+
{
84+
return clickButtonExpectingError(elementCache().saveExtension);
85+
}
86+
87+
public AllowedFileExtensionAdminPage clickSaveExtension()
88+
{
89+
return clickButtonNoError(elementCache().saveExtension);
90+
}
91+
92+
public AllowedFileExtensionAdminPage updateExtension(String oldExtension, String newExtension)
93+
{
94+
getAllowedExtension(getAllowedExtensionIndex(oldExtension)).set(newExtension);
95+
clearCache();
96+
return this;
97+
}
98+
99+
public AllowedFileExtensionAdminPage clickSaveUpdateExtension()
100+
{
101+
return clickButtonNoError(elementCache().saveUpdateExtension);
102+
}
103+
104+
public String clickUpdateExtensionExpectingError()
105+
{
106+
return clickButtonExpectingError(elementCache().saveUpdateExtension);
107+
}
108+
109+
private AllowedFileExtensionAdminPage clickButtonNoError(WebElement button)
110+
{
111+
clickAndWait(button);
112+
clearCache();
113+
assertNoLabKeyErrors();
114+
return this;
115+
}
116+
117+
private String clickButtonExpectingError(WebElement button)
118+
{
119+
clickAndWait(button);
120+
clearCache();
121+
return waitForElement(Locators.labkeyError).getText();
122+
}
123+
124+
public AllowedFileExtensionAdminPage deleteExtension(int index)
125+
{
126+
WebElement deleteButton = elementCache().deleteExtensions.get(index);
127+
deleteButton.click();
128+
129+
shortWait().withMessage("Existing extenstion was not deleted.")
130+
.until(ExpectedConditions.stalenessOf(deleteButton));
131+
132+
clearCache();
133+
return this;
134+
}
135+
136+
public AllowedFileExtensionAdminPage deleteExtension(String extension)
137+
{
138+
return deleteExtension(getAllowedExtensionIndex(extension));
139+
}
140+
141+
public AllowedFileExtensionAdminPage deleteAllExtensions(boolean acceptAlert)
142+
{
143+
if (acceptAlert)
144+
{
145+
doAndWaitForPageToLoad(() -> {
146+
elementCache().deleteAll.click();
147+
acceptAlert();
148+
});
149+
clearCache();
150+
assertFalse("Delete All button should not be present after deleting all extensions", elementCache().deleteAll.isDisplayed());
151+
}
152+
else
153+
{
154+
elementCache().deleteAll.click();
155+
cancelAlert();
156+
assertTrue("Delete All button should be present", elementCache().deleteAll.isDisplayed());
157+
}
158+
return this;
159+
}
160+
161+
public List<Input> getAllowedExtensions()
162+
{
163+
List<WebElement> collection = Locator.inputByIdContaining("existingValue")
164+
.findElements(elementCache().existingPanel);
165+
166+
return collection.stream().map(el -> new Input(el, getDriver())).collect(Collectors.toList());
167+
168+
}
169+
170+
public Input getAllowedExtension(int index)
171+
{
172+
return getAllowedExtensions().get(index);
173+
}
174+
175+
public Integer getAllowedExtensionIndex(String extension)
176+
{
177+
int index = 0;
178+
List<Input> allowedExtensions = getAllowedExtensions();
179+
180+
for(Input element : allowedExtensions)
181+
{
182+
if (element.getValue().equalsIgnoreCase(extension))
183+
return index;
184+
185+
index++;
186+
}
187+
188+
return -1;
189+
}
190+
191+
@Override
192+
protected ElementCache newElementCache()
193+
{
194+
return new ElementCache();
195+
}
196+
197+
protected class ElementCache extends LabKeyPage<ElementCache>.ElementCache
198+
{
199+
final WebElement registerNewPanel = PortalHelper.Locators.webPart("Register New Allowed File Extension").findWhenNeeded(this);
200+
final WebElement existingPanel = PortalHelper.Locators.webPart("Existing Allowed File Extensions").findWhenNeeded(this);
201+
202+
final Input extension = new Input(Locator.id("newValueTextField").findWhenNeeded(registerNewPanel), getDriver());
203+
final WebElement saveExtension = Locator.lkButton("Save").findWhenNeeded(registerNewPanel);
204+
205+
final WebElement saveUpdateExtension = Locator.lkButton("Save").findWhenNeeded(existingPanel);
206+
207+
List<Input> allowedExtensions()
208+
{
209+
return Locator.inputByIdContaining("existingValue")
210+
.findElements(elementCache().existingPanel)
211+
.stream().map(el -> new Input(el, getDriver())).collect(Collectors.toList());
212+
}
213+
214+
final List<WebElement> deleteExtensions = Locator.linkWithText("Delete").findElements(existingPanel);
215+
216+
final WebElement deleteAll = Locator.linkWithText("Delete All").findWhenNeeded(existingPanel);
217+
218+
}
219+
}

src/org/labkey/test/pages/core/admin/ShowAdminPage.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,13 @@ public ShowAuditLogPage clickAuditLog()
9999
return new ShowAuditLogPage(getDriver());
100100
}
101101

102+
public AllowedFileExtensionAdminPage clickAllowedFileExtensions()
103+
{
104+
goToSettingsSection();
105+
clickAndWait(elementCache().allowedFileExtensionLink);
106+
return new AllowedFileExtensionAdminPage(getDriver());
107+
}
108+
102109
public void clickAuditLogMaintenance()
103110
{
104111
goToSettingsSection();
@@ -280,6 +287,7 @@ protected class ElementCache extends LabKeyPage.ElementCache
280287

281288
protected WebElement analyticsSettingsLink = Locator.linkWithText("analytics settings").findWhenNeeded(this);
282289
protected WebElement externalRedirectHostLink = Locator.linkWithText("allowed external redirect hosts").findElement(this);
290+
protected WebElement allowedFileExtensionLink = Locator.linkWithText("allowed file extensions").findElement(this);
283291
protected WebElement auditLogLink = Locator.linkWithText("audit log").findWhenNeeded(this);
284292
protected WebElement auditLogMaintenanceLink = Locator.linkWithText("Audit Log Maintenance").findWhenNeeded(this);
285293
protected WebElement authenticationLink = Locator.linkWithText("authentication").findWhenNeeded(this);
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package org.labkey.test.tests.core.admin;
2+
3+
import org.labkey.remoteapi.CommandException;
4+
import org.labkey.test.BaseWebDriverTest;
5+
import org.labkey.test.TestFileUtils;
6+
import org.labkey.test.components.html.Input;
7+
import org.labkey.test.pages.core.admin.AllowedFileExtensionAdminPage;
8+
9+
import java.io.File;
10+
import java.io.IOException;
11+
import java.util.List;
12+
import java.util.Map;
13+
14+
public abstract class AllowedFileExtensionBaseTest extends BaseWebDriverTest
15+
{
16+
17+
protected final File TAR_FILE = TestFileUtils.getSampleData("fileTypes/targz_sample.tar.gz");
18+
protected final File CSV_FILE = TestFileUtils.getSampleData("fileTypes/csv_sample.csv");
19+
protected final File TSV_FILE = TestFileUtils.getSampleData("fileTypes/tsv_sample.tsv");
20+
protected final File TXT_FILE = TestFileUtils.getSampleData("fileTypes/sample.txt");
21+
protected final File XLS_FILE = TestFileUtils.getSampleData("fileTypes/xls_sample.xls");
22+
protected final File XLSX_FILE = TestFileUtils.getSampleData("fileTypes/xlsx_sample.xlsx");
23+
24+
protected final Map<String, File> fileMap = Map.of(
25+
".tar.gz", TAR_FILE,
26+
".xls", XLS_FILE,
27+
".tsv", TSV_FILE,
28+
".csv", CSV_FILE,
29+
".txt", TXT_FILE,
30+
".xlsx", XLSX_FILE
31+
);
32+
33+
@Override
34+
protected void doCleanup(boolean afterTest)
35+
{
36+
_containerHelper.deleteProject(getProjectName(), afterTest);
37+
try
38+
{
39+
AllowedFileExtensionAdminPage.deleteAllAllowedFileExtension(createDefaultConnection());
40+
}
41+
catch (IOException | CommandException e)
42+
{
43+
throw new RuntimeException(e);
44+
}
45+
}
46+
47+
protected AllowedFileExtensionAdminPage setAllowedExtensions(List<String> allowedTypes, List<String> expectedTypes)
48+
{
49+
AllowedFileExtensionAdminPage allowedFileExtensionAdminPage = goToAdminConsole().clickAllowedFileExtensions();
50+
51+
for (String extension : allowedTypes)
52+
{
53+
allowedFileExtensionAdminPage.setExtension(extension);
54+
allowedFileExtensionAdminPage.clickSaveExtension();
55+
}
56+
57+
List<Input> extensions = allowedFileExtensionAdminPage.getAllowedExtensions();
58+
59+
checker().withScreenshot()
60+
.verifyEqualsSorted("List of 'Allowed extensions' is not as expected.",
61+
expectedTypes, extensions.stream().map(Input::getValue).toList());
62+
63+
return allowedFileExtensionAdminPage;
64+
}
65+
66+
}

0 commit comments

Comments
 (0)