Issue 51524: Allowlist for acceptable types of file upload - automation test#2428
Issue 51524: Allowlist for acceptable types of file upload - automation test#2428labkey-danield merged 27 commits intodevelopfrom
Conversation
Add test to check for adding invalid extensions.
Update BaseUpdatePage to have a getter for the title and body.
…ing to check if fields remain populated).
…est and into BaseWebDriverTest. Add AllowedFileExtensionsTest in lims/biologics, add testAllowedFilesInSampleTypes. Add TestScrubber.clearListOfAllowedFileExtensions.
Add AllowedFileExtensionsTest.testAllowedFilesInWorkflow
| waitForPipelineJobsToComplete(pipelineJobs, "Study Reload", expectError); | ||
| } | ||
|
|
||
| protected void deleteAllAllowedFileExtension() throws IOException, CommandException |
There was a problem hiding this comment.
| protected void deleteAllAllowedFileExtension() throws IOException, CommandException | |
| /** Clears any file extensions that are set as the only allowable names, letting users upload any filename they like */ | |
| protected void deleteAllAllowedFileExtension() throws IOException, CommandException |
| } | ||
| } | ||
|
|
||
| private void clearListOfAllowedFileExtensions() throws IOException, CommandException |
There was a problem hiding this comment.
Can we consolidate this with the copy in BaseWebDriverTest?
There was a problem hiding this comment.
I've removed this method. The only place this code should now appear is in AllowedFileExtensionAdminPage.deleteAllAllowedFileExtension.
| // Not sure why we record two exceptions. | ||
| checkExpectedErrors(2); |
There was a problem hiding this comment.
Should no longer be needed
| // Not sure why we record two exceptions. | ||
| checkExpectedErrors(2); |
There was a problem hiding this comment.
Should no longer be needed
labkey-tchad
left a comment
There was a problem hiding this comment.
The instructions on the admin page say that ".gz" won't allow ".tar.gz" files; should we verify that is true?
| protected void deleteAllAllowedFileExtension() throws IOException, CommandException | ||
| { | ||
| SimplePostCommand command = new SimplePostCommand("admin", "deleteAllValues"); | ||
| Map<String, Object> params = new HashMap<>(); | ||
| params.put("type", "FileExtension"); | ||
| command.setParameters(params); | ||
| command.execute(createDefaultConnection(), "/"); | ||
| } |
There was a problem hiding this comment.
This method should go in LabKeySiteWrapper. That would allow TestScrubber to access it.
Alternatively, you could make it a static method in AllowedFileExtensionAdminPage (with a Connection parameter).
There was a problem hiding this comment.
I've moved it AllowedFileExtensionsAdminPage and made it static. I think it might be more discoverable there.
|
|
||
| public static AllowedFileExtensionAdminPage beginAt(WebDriverWrapper webDriverWrapper) | ||
| { | ||
| webDriverWrapper.beginAt(WebTestHelper.buildURL("admin", "allowList")); |
There was a problem hiding this comment.
The allowList page has several flavors, need to specify the FileExtension version.
| webDriverWrapper.beginAt(WebTestHelper.buildURL("admin", "allowList")); | |
| webDriverWrapper.beginAt(WebTestHelper.buildURL("admin", "allowList", Map.of("type", "FileExtension"))); |
| public String clickSaveExpectingError() | ||
| { | ||
| String errorText; | ||
| elementCache().saveExtension.click(); | ||
| errorText = waitForElement(Locators.labkeyError).getText(); | ||
| clearCache(); | ||
| return errorText; | ||
| } | ||
|
|
||
| public AllowedFileExtensionAdminPage clickSaveExtension() | ||
| { | ||
| elementCache().saveExtension.click(); | ||
| clearCache(); | ||
| return this; | ||
| } |
There was a problem hiding this comment.
All of the buttons (delete, save, and update) trigger a page load, regardless of whether there is an error. These should all wait for a page load and error-free versions should verify that there is no error.
| public String clickSaveExpectingError() | |
| { | |
| String errorText; | |
| elementCache().saveExtension.click(); | |
| errorText = waitForElement(Locators.labkeyError).getText(); | |
| clearCache(); | |
| return errorText; | |
| } | |
| public AllowedFileExtensionAdminPage clickSaveExtension() | |
| { | |
| elementCache().saveExtension.click(); | |
| clearCache(); | |
| return this; | |
| } | |
| 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 String clickSaveExpectingError() | |
| { | |
| return clickButtonExpectingError(elementCache().saveExtension); | |
| } | |
| public AllowedFileExtensionAdminPage clickSaveExtension() | |
| { | |
| return clickButtonNoError(elementCache().saveExtension); | |
| } |
And so on for update and delete.
| elementCache().deleteAll.click(); | ||
|
|
||
| if (acceptAlert) | ||
| { | ||
| acceptAlert(); | ||
| shortWait().withMessage("'Delete All' button should have gone away.") | ||
| .until(ExpectedConditions.stalenessOf(elementCache().deleteAll)); | ||
| } | ||
| else | ||
| { | ||
| cancelAlert(); | ||
| } | ||
|
|
||
| clearCache(); | ||
| return this; |
There was a problem hiding this comment.
This staleness check will always pass because there is a page load. Need to clear the cache and check the button's visibility.
| elementCache().deleteAll.click(); | |
| if (acceptAlert) | |
| { | |
| acceptAlert(); | |
| shortWait().withMessage("'Delete All' button should have gone away.") | |
| .until(ExpectedConditions.stalenessOf(elementCache().deleteAll)); | |
| } | |
| else | |
| { | |
| cancelAlert(); | |
| } | |
| clearCache(); | |
| return this; | |
| if (acceptAlert) | |
| { | |
| doAndWaitForPageLoad(() -> { | |
| 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; |
| new PortalHelper(getDriver()).addWebPart("Files"); | ||
| new PortalHelper(getDriver()).addWebPart("Sample Types"); | ||
| new PortalHelper(getDriver()).addWebPart("Lists"); | ||
| new PortalHelper(getDriver()).addWebPart("Messages List"); |
There was a problem hiding this comment.
Each addWebPart enters and exits page admin mode. Wrap in doInAdminMode to avoid all the extra navigations.
| new PortalHelper(getDriver()).addWebPart("Files"); | |
| new PortalHelper(getDriver()).addWebPart("Sample Types"); | |
| new PortalHelper(getDriver()).addWebPart("Lists"); | |
| new PortalHelper(getDriver()).addWebPart("Messages List"); | |
| new PortalHelper(driver).doInAdminMode(ph -> { | |
| ph.addWebPart("Files"); | |
| ph.addWebPart("Sample Types"); | |
| ph.addWebPart("Lists"); | |
| ph.addWebPart("Messages List"); | |
| }); |
| 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); |
There was a problem hiding this comment.
Consider moving the admin page validation to a separate test case (duplicate extensions, updating extensions, invalid extensions, delete all cancelling, etc.)
There was a problem hiding this comment.
I have moved most of the tests cases that check the admin page functionality into a separate class:
- Check that allowed file extensions are listed in alphabetical order.
- Canceling out of 'Delete All'.
- Validate extension value must start with a '.'
- Validate duplicate extensions are not allowed.
- Validate blank extension type is not allowed.
I did leave in test cases that validate actions on the admin page behave as expected in the project:
- Remove an allowed file type and validate files of that type cannot be uploaded.
- 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.
As a side note it is not possible to test for dirty bit in LKS with selenium. See issue 38785.
| _listHelper.createList(getProjectName(), listName, keyField, | ||
| new FieldDefinition(attachmentField, FieldDefinition.ColumnType.Attachment)); |
There was a problem hiding this comment.
Create list via API.
| _listHelper.createList(getProjectName(), listName, keyField, | |
| new FieldDefinition(attachmentField, FieldDefinition.ColumnType.Attachment)); | |
| new IntListDefinition(listName, keyField) | |
| .addField(new FieldDefinition(attachmentField, FieldDefinition.ColumnType.Attachment)) | |
| .create(getProjectName(), createDefaultConnection()); |
| FileInput el = FileInput.FileInput(Locator.name("quf_" + attachmentField), getDriver()).findWhenNeeded(); | ||
| executeScript("arguments[0].value = '';", el.getComponentElement()); |
There was a problem hiding this comment.
Does WebElement.clear work for this?
| FileInput el = FileInput.FileInput(Locator.name("quf_" + attachmentField), getDriver()).findWhenNeeded(); | |
| executeScript("arguments[0].value = '';", el.getComponentElement()); | |
| FileInput el = FileInput.FileInput(Locator.name("quf_" + attachmentField), getDriver()).findWhenNeeded(); | |
| el.getComponentElement().clear(); |
If it does, consider adding a clear method to FileInput.
There was a problem hiding this comment.
It appears to. I've added FileInput.clear.
This is a good idea - we should cover a "double extension" like this. |
labkey-chrisj
left a comment
There was a problem hiding this comment.
I don't have anything pressing to add, looks good to me tho
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.
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.
I've added a tar.gz file to the mix. |
… (AllowedFileExtensionsPageTest). Add a base class that has some shared code.
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.
Fixed some typos in comments.
Rationale
Add automated tests for the Allowed Files list.
These tests will cover:
Has coverage for:
Issue 53039: Updating an allowed file extension should set a dirty bit on the page.
Issue 53027: Cannot insert a row into a sample type if Allowed File Extensions are set and no file is provided.
TeamCity runs are here.
Related Pull Requests
Changes