summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--client/src/main/java/com/vaadin/client/ui/VUpload.java1
-rw-r--r--uitest/src/main/java/com/vaadin/tests/components/upload/InterruptUpload.java208
-rw-r--r--uitest/src/test/java/com/vaadin/tests/components/upload/InterruptUploadTest.java112
3 files changed, 321 insertions, 0 deletions
diff --git a/client/src/main/java/com/vaadin/client/ui/VUpload.java b/client/src/main/java/com/vaadin/client/ui/VUpload.java
index 16d62ccf42..5f191162c2 100644
--- a/client/src/main/java/com/vaadin/client/ui/VUpload.java
+++ b/client/src/main/java/com/vaadin/client/ui/VUpload.java
@@ -222,6 +222,7 @@ public class VUpload extends SimplePanel {
* file. A new target frame is created later."
*/
cleanTargetFrame();
+ rebuildPanel();
submitted = false;
}
}
diff --git a/uitest/src/main/java/com/vaadin/tests/components/upload/InterruptUpload.java b/uitest/src/main/java/com/vaadin/tests/components/upload/InterruptUpload.java
new file mode 100644
index 0000000000..8d95b35373
--- /dev/null
+++ b/uitest/src/main/java/com/vaadin/tests/components/upload/InterruptUpload.java
@@ -0,0 +1,208 @@
+package com.vaadin.tests.components.upload;
+
+import java.io.OutputStream;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.FormLayout;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.ProgressBar;
+import com.vaadin.ui.UI;
+import com.vaadin.ui.Upload;
+import com.vaadin.ui.Upload.FailedEvent;
+import com.vaadin.ui.Upload.FinishedEvent;
+import com.vaadin.ui.Upload.Receiver;
+import com.vaadin.ui.Upload.StartedEvent;
+import com.vaadin.ui.Upload.SucceededEvent;
+import com.vaadin.ui.Window;
+
+public class InterruptUpload extends AbstractTestUI {
+
+ private Upload sample;
+ private UploadInfoWindow uploadInfoWindow;
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ LineBreakCounter lineBreakCounter = new LineBreakCounter();
+ lineBreakCounter.setSlow(true);
+
+ sample = new Upload(null, lineBreakCounter);
+ sample.setImmediateMode(true);
+ sample.setButtonCaption("Upload File");
+
+ uploadInfoWindow = new UploadInfoWindow(sample, lineBreakCounter);
+
+ sample.addStartedListener(event -> {
+ if (uploadInfoWindow.getParent() == null) {
+ UI.getCurrent().addWindow(uploadInfoWindow);
+ }
+ uploadInfoWindow.setClosable(false);
+ });
+ sample.addFinishedListener(event -> uploadInfoWindow.setClosable(true));
+
+ addComponent(sample);
+ }
+
+ private static class UploadInfoWindow extends Window
+ implements Upload.StartedListener, Upload.ProgressListener,
+ Upload.FailedListener, Upload.SucceededListener,
+ Upload.FinishedListener {
+ private final Label state = new Label();
+ private final Label result = new Label();
+ private final Label fileName = new Label();
+ private final Label textualProgress = new Label();
+
+ private final ProgressBar progressBar = new ProgressBar();
+ private final Button cancelButton;
+ private final LineBreakCounter counter;
+
+ private UploadInfoWindow(final Upload upload,
+ final LineBreakCounter lineBreakCounter) {
+ super("Status");
+ counter = lineBreakCounter;
+
+ addStyleName("upload-info");
+
+ setResizable(false);
+ setDraggable(false);
+
+ final FormLayout uploadInfoLayout = new FormLayout();
+ setContent(uploadInfoLayout);
+ uploadInfoLayout.setMargin(true);
+
+ final HorizontalLayout stateLayout = new HorizontalLayout();
+ stateLayout.setSpacing(true);
+ stateLayout.addComponent(state);
+
+ cancelButton = new Button("Cancel");
+ cancelButton.addClickListener(event -> upload.interruptUpload());
+ cancelButton.setVisible(false);
+ cancelButton.setStyleName("small");
+ stateLayout.addComponent(cancelButton);
+
+ stateLayout.setCaption("Current state");
+ state.setValue("Idle");
+ uploadInfoLayout.addComponent(stateLayout);
+
+ fileName.setCaption("File name");
+ uploadInfoLayout.addComponent(fileName);
+
+ result.setCaption("Line breaks counted");
+ uploadInfoLayout.addComponent(result);
+
+ progressBar.setCaption("Progress");
+ progressBar.setVisible(false);
+ uploadInfoLayout.addComponent(progressBar);
+
+ textualProgress.setVisible(false);
+ uploadInfoLayout.addComponent(textualProgress);
+
+ upload.addStartedListener(this);
+ upload.addProgressListener(this);
+ upload.addFailedListener(this);
+ upload.addSucceededListener(this);
+ upload.addFinishedListener(this);
+
+ }
+
+ @Override
+ public void uploadFinished(final FinishedEvent event) {
+ state.setValue("Idle");
+ progressBar.setVisible(false);
+ textualProgress.setVisible(false);
+ cancelButton.setVisible(false);
+ UI.getCurrent().setPollInterval(-1);
+ }
+
+ @Override
+ public void uploadStarted(final StartedEvent event) {
+ // this method gets called immediately after upload is started
+ progressBar.setValue(0f);
+ progressBar.setVisible(true);
+ UI.getCurrent().setPollInterval(500);
+ textualProgress.setVisible(true);
+ // updates to client
+ state.setValue("Uploading");
+ fileName.setValue(event.getFilename());
+
+ cancelButton.setVisible(true);
+ }
+
+ @Override
+ public void updateProgress(final long readBytes,
+ final long contentLength) {
+ // this method gets called several times during the update
+ progressBar.setValue(readBytes / (float) contentLength);
+ textualProgress.setValue(
+ "Processed " + readBytes + " bytes of " + contentLength);
+ result.setValue(counter.getLineBreakCount() + " (counting...)");
+ }
+
+ @Override
+ public void uploadSucceeded(final SucceededEvent event) {
+ result.setValue(counter.getLineBreakCount() + " (total)");
+ }
+
+ @Override
+ public void uploadFailed(final FailedEvent event) {
+ result.setValue(
+ counter.getLineBreakCount() + " (counting interrupted at "
+ + Math.round(100 * progressBar.getValue()) + "%)");
+ }
+ }
+
+ private static class LineBreakCounter implements Receiver {
+ private int counter;
+ private int total;
+ private boolean sleep;
+
+ /**
+ * return an OutputStream that simply counts lineends
+ */
+ @Override
+ public OutputStream receiveUpload(final String filename,
+ final String MIMEType) {
+ counter = 0;
+ total = 0;
+ return new OutputStream() {
+ private static final int searchedByte = '\n';
+
+ @Override
+ public void write(final int b) {
+ total++;
+ if (b == searchedByte) {
+ counter++;
+ }
+ if (sleep && total % 1000 == 0) {
+ try {
+ Thread.sleep(100);
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ };
+ }
+
+ private int getLineBreakCount() {
+ return counter;
+ }
+
+ private void setSlow(boolean value) {
+ sleep = value;
+ }
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 9635;
+ }
+
+ @Override
+ public String getDescription() {
+ return "Interrupting an upload shouldn't prevent uploading that same file immediately afterwards.";
+ }
+
+}
diff --git a/uitest/src/test/java/com/vaadin/tests/components/upload/InterruptUploadTest.java b/uitest/src/test/java/com/vaadin/tests/components/upload/InterruptUploadTest.java
new file mode 100644
index 0000000000..1df188202d
--- /dev/null
+++ b/uitest/src/test/java/com/vaadin/tests/components/upload/InterruptUploadTest.java
@@ -0,0 +1,112 @@
+package com.vaadin.tests.components.upload;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.List;
+
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.internal.WrapsElement;
+import org.openqa.selenium.remote.DesiredCapabilities;
+import org.openqa.selenium.remote.LocalFileDetector;
+import org.openqa.selenium.remote.RemoteWebElement;
+
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.LabelElement;
+import com.vaadin.testbench.elements.WindowElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+import com.vaadin.tests.util.LoremIpsum;
+
+public class InterruptUploadTest extends MultiBrowserTest {
+
+ @Override
+ public List<DesiredCapabilities> getBrowsersToTest() {
+ // PhantomJS fails to upload files for unknown reasons
+ return getBrowsersExcludingPhantomJS();
+ }
+
+ @Test
+ public void testInterruptUpload() throws Exception {
+ openTestURL();
+
+ File tempFile = createTempFile();
+ fillPathToUploadInput(tempFile.getPath());
+
+ waitForElementPresent(By.className("v-window"));
+
+ $(ButtonElement.class).caption("Cancel").first().click();
+
+ String expected = " (counting interrupted at ";
+ String actual = $(LabelElement.class).caption("Line breaks counted")
+ .first().getText();
+ assertTrue("Line break count note does not match expected (was: "
+ + actual + ")", actual.contains(expected));
+
+ $(WindowElement.class).first().close();
+ waitForElementNotPresent(By.className("v-window"));
+
+ tempFile = createTempFile();
+ fillPathToUploadInput(tempFile.getPath());
+
+ waitForElementPresent(By.className("v-window"));
+ $(ButtonElement.class).caption("Cancel").first().click();
+ }
+
+ /**
+ * @return The generated temp file handle
+ * @throws IOException
+ */
+ private File createTempFile() throws IOException {
+ File tempFile = File.createTempFile("TestFileUpload", ".txt");
+ BufferedWriter writer = new BufferedWriter(new FileWriter(tempFile));
+ writer.write(getTempFileContents());
+ writer.close();
+ tempFile.deleteOnExit();
+ return tempFile;
+ }
+
+ private String getTempFileContents() {
+ StringBuilder sb = new StringBuilder("This is a big test file!");
+ for (int i = 0; i < 70; ++i) {
+ sb.append("\n");
+ sb.append(LoremIpsum.get());
+ }
+ return sb.toString();
+ }
+
+ private void fillPathToUploadInput(String tempFileName) throws Exception {
+ // create a valid path in upload input element. Instead of selecting a
+ // file by some file browsing dialog, we use the local path directly.
+ WebElement input = getInput();
+ setLocalFileDetector(input);
+ input.sendKeys(tempFileName);
+ }
+
+ private WebElement getInput() {
+ return getDriver().findElement(By.className("gwt-FileUpload"));
+ }
+
+ private void setLocalFileDetector(WebElement element) throws Exception {
+ if (getRunLocallyBrowser() != null) {
+ return;
+ }
+
+ if (element instanceof WrapsElement) {
+ element = ((WrapsElement) element).getWrappedElement();
+ }
+ if (element instanceof RemoteWebElement) {
+ ((RemoteWebElement) element)
+ .setFileDetector(new LocalFileDetector());
+ } else {
+ throw new IllegalArgumentException(
+ "Expected argument of type RemoteWebElement, received "
+ + element.getClass().getName());
+ }
+ }
+
+}