Issue
I know that there is some kind of bug in selenium that causes uploading multiple files at once a trouble (I'm using v4.4.0). When I try to do it, I can upload 1st file, but 2nd file from the list will be uploaded along with 1st and 3rd along with 1st and 2nd, resulting in 3x1st file, 2x2nd file, 1x3rd file.
Wherever I need to upload multiple files, I visit upload place, upload 1st file, save, return, then visit again and upload 2nd file, and so on. But it's technically invoking method with a single upload few times.
Now I am in place, where such a tactic can't be chosen. I read that using \n
as delimiter of String of files can help, but it just doesn't seem to work for me.
If only one file were to be sent (filepaths
is list of only one element) it works fine.
public ApplyFilesPO uploadFile(@NotNull List<String> filepaths) {
String filepath = String.join("\n", filepaths);
uploadFilePO.uploadFile(filepath, fileInput, progressBar);
return this; // doesn't work if list contains more than 1 element
}
This is UploadFilePO#uploadFile(String, By, By)
method:
public void uploadFile(String filename, By input, By progressBar) {
File file = new File(Objects
.requireNonNull(getClass().getClassLoader().getResource(filename))
.getFile());
getExistingElement(input).sendKeys(file.toString());
waitForElementToDisappear(progressBar);
}
The input is 2px x 0px element, real user opens select file window by clicking on some button.
getExistingElement
:
protected final WebElement getExistingElement(By locator) {
return wait.until(ExpectedConditions.presenceOfElementLocated(locator));
}
waitForElementToDisappear
(Progress bar shows immediately after uploading file, and disappears after it is uploaded, so I added this method to be sure that uploading is done:
protected final <T> void waitForElementToDisappear(T locator) {
wait.until(isBy(locator)
? ExpectedConditions.invisibilityOfElementLocated((By) locator)
: ExpectedConditions.invisibilityOf((WebElement) locator));
}
Solution
I found the answer to my problem. An input element has to be provided with a string containing absolute paths to the files one wants to upload joined with " \n ".
So this is the piece of code I am using now:
public void uploadFiles(@NotNull List<String> filenames, By input, By progressBar) {
String upload = String.join(" \n ", filenames
.stream()
.map(filename -> new File(Objects.requireNonNull(
getClass().getClassLoader().getResource(filename)).getFile()).getAbsolutePath())
.toList());
getExistingElement(input).sendKeys(upload);
wait.until(ExpectedConditions.invisibilityOfAllElements(driver.findElements(progressBar)));
}
Answered By - hetacz
Answer Checked By - Clifford M. (JavaFixing Volunteer)