From f74c5b90d3b7ba0a174f97204f789476eb9b4a82 Mon Sep 17 00:00:00 2001
From: Robert Scott <code@humanleg.org.uk>
Date: Sat, 20 Oct 2018 21:21:17 +0100
Subject: [PATCH v1] UploadDialogTest: fix for non-headless mode

---
 .../openstreetmap/josm/gui/io/UploadDialog.java    |   4 -
 .../josm/gui/io/UploadDialogTest.java              | 211 +++++++++++++++------
 .../josm/testutils/mockers/BaseDialogMockUp.java   |   7 +
 3 files changed, 164 insertions(+), 58 deletions(-)

diff --git a/src/org/openstreetmap/josm/gui/io/UploadDialog.java b/src/org/openstreetmap/josm/gui/io/UploadDialog.java
index 8221f605e..6eff116f0 100644
--- a/src/org/openstreetmap/josm/gui/io/UploadDialog.java
+++ b/src/org/openstreetmap/josm/gui/io/UploadDialog.java
@@ -477,10 +477,6 @@ public class UploadDialog extends AbstractUploadDialog implements PropertyChange
                     tr("Cancel and return to the previous dialog"),
                     tr("Ignore this hint and upload anyway")};
 
-            if (GraphicsEnvironment.isHeadless()) {
-                return false;
-            }
-
             ExtendedDialog dlg = new ExtendedDialog((Component) dialog, title, buttonTexts) {
                 @Override
                 public void setupDialog() {
diff --git a/test/unit/org/openstreetmap/josm/gui/io/UploadDialogTest.java b/test/unit/org/openstreetmap/josm/gui/io/UploadDialogTest.java
index a1ae2869a..352e28b1f 100644
--- a/test/unit/org/openstreetmap/josm/gui/io/UploadDialogTest.java
+++ b/test/unit/org/openstreetmap/josm/gui/io/UploadDialogTest.java
@@ -1,16 +1,30 @@
 // License: GPL. For details, see LICENSE file.
 package org.openstreetmap.josm.gui.io;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
+import java.awt.GraphicsEnvironment;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
+import javax.swing.JButton;
+import javax.swing.JOptionPane;
 
 import org.junit.Rule;
 import org.junit.Test;
+import org.openstreetmap.josm.gui.ExtendedDialog;
+import org.openstreetmap.josm.TestUtils;
 import org.openstreetmap.josm.io.UploadStrategySpecification;
 import org.openstreetmap.josm.testutils.JOSMTestRules;
+import org.openstreetmap.josm.testutils.mockers.ExtendedDialogMocker;
+import org.openstreetmap.josm.testutils.mockers.WindowMocker;
+
+import mockit.Invocation;
+import mockit.Mock;
+
+import com.google.common.collect.ImmutableMap;
 
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 
@@ -26,62 +40,75 @@ public class UploadDialogTest {
     @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
     public JOSMTestRules test = new JOSMTestRules().preferences();
 
-    private static IUploadDialog newUploadDialog(final String comment, final String source) {
-        return new IUploadDialog() {
-
-            @Override
-            public void rememberUserInput() {
-                // Do nothing
-            }
-
-            @Override
-            public boolean isCanceled() {
-                return false;
-            }
-
-            @Override
-            public void handleMissingSource() {
-                // Do nothing
-            }
-
-            @Override
-            public void handleMissingComment() {
-                // Do nothing
-            }
-
-            @Override
-            public void handleIllegalChunkSize() {
-                // Do nothing
-            }
-
-            @Override
-            public UploadStrategySpecification getUploadStrategySpecification() {
-                return new UploadStrategySpecification();
-            }
-
-            @Override
-            public String getUploadSource() {
-                return source;
-            }
-
-            @Override
-            public String getUploadComment() {
-                return comment;
-            }
-
-            @Override
-            public Map<String, String> getTags(boolean keepEmpty) {
-                return new ConcurrentHashMap<>();
-            }
-        };
-    }
+    private static class MockUploadDialog extends JOptionPane implements IUploadDialog {
+        private final String source;
+        private final String comment;
+
+        public int handleMissingCommentCalls = 0;
+        public int handleMissingSourceCalls = 0;
+
+        public MockUploadDialog(final String comment, final String source) {
+            this.source = source;
+            this.comment = comment;
+        }
+
+        @Override
+        public void rememberUserInput() {
+            // Do nothing
+        }
+
+        @Override
+        public boolean isCanceled() {
+            return false;
+        }
+
+        @Override
+        public void handleMissingSource() {
+            this.handleMissingSourceCalls += 1;
+        }
+
+        @Override
+        public void handleMissingComment() {
+            this.handleMissingCommentCalls += 1;
+        }
+
+        @Override
+        public void handleIllegalChunkSize() {
+            // Do nothing
+        }
+
+        @Override
+        public UploadStrategySpecification getUploadStrategySpecification() {
+            return new UploadStrategySpecification();
+        }
+
+        @Override
+        public String getUploadSource() {
+            return source;
+        }
+
+        @Override
+        public String getUploadComment() {
+            return comment;
+        }
+
+        @Override
+        public Map<String, String> getTags(boolean keepEmpty) {
+            return new ConcurrentHashMap<>();
+        }
+    };
 
     /**
      * Test of {@link UploadDialog.CancelAction} class.
      */
     @Test
     public void testCancelAction() {
-        new UploadDialog.CancelAction(newUploadDialog(null, null)).actionPerformed(null);
+        if (GraphicsEnvironment.isHeadless()) {
+            TestUtils.assumeWorkingJMockit();
+            new WindowMocker();
+        }
+        MockUploadDialog uploadDialog = new MockUploadDialog(null, null);
+        new UploadDialog.CancelAction(uploadDialog).actionPerformed(null);
     }
 
     /**
@@ -89,10 +116,86 @@ public class UploadDialogTest {
      */
     @Test
     public void testUploadAction() {
-        new UploadDialog.UploadAction(newUploadDialog("comment", "source")).actionPerformed(null);
-        new UploadDialog.UploadAction(newUploadDialog("", "source")).actionPerformed(null);
-        new UploadDialog.UploadAction(newUploadDialog("comment", "")).actionPerformed(null);
-        new UploadDialog.UploadAction(newUploadDialog("a comment long enough", "a source long enough")).actionPerformed(null);
+        TestUtils.assumeWorkingJMockit();
+        ExtendedDialogMocker edMocker = new ExtendedDialogMocker(
+            ImmutableMap.<String, Object>of(
+                "<html>Your upload comment is <i>empty</i>, or <i>very short</i>.<br /><br />This is "
+                + "technically allowed, but please consider that many users who are<br />watching changes "
+                + "in their area depend on meaningful changeset comments<br />to understand what is going "
+                + "on!<br /><br />If you spend a minute now to explain your change, you will make life<br />"
+                + "easier for many other mappers.</html>", "Revise",
+                "<html>You did not specify a source for your changes.<br />It is technically allowed, "
+                + "but this information helps<br />other users to understand the origins of the data."
+                + "<br /><br />If you spend a minute now to explain your change, you will make life"
+                + "<br />easier for many other mappers.</html>", "Revise"
+            )
+        ) {
+            @Mock
+            void setupDialog(Invocation invocation) throws Exception {
+                if (GraphicsEnvironment.isHeadless()) {
+                    final int nButtons = ((String[]) TestUtils.getPrivateField(ExtendedDialog.class, invocation.getInvokedInstance(), "bTexts")).length;
+                    @SuppressWarnings("unchecked")
+                    final List<JButton> buttons = (List<JButton>) TestUtils.getPrivateField(ExtendedDialog.class, invocation.getInvokedInstance(), "buttons");
+
+                    for (int i = 0; i < nButtons; i++) {
+                        buttons.add(new JButton());
+                    }
+                } else {
+                    invocation.proceed();
+                }
+            }
+        };
+
+        MockUploadDialog uploadDialog = new MockUploadDialog("comment", "source");
+        new UploadDialog.UploadAction(uploadDialog).actionPerformed(null);
+
+        assertEquals(1, uploadDialog.handleMissingCommentCalls);
+        assertEquals(0, uploadDialog.handleMissingSourceCalls);
+        assertEquals(1, edMocker.getInvocationLog().size());
+        Object[] invocationLogEntry = edMocker.getInvocationLog().get(0);
+        assertEquals(1, (int) invocationLogEntry[0]);
+        assertEquals("Please revise upload comment", invocationLogEntry[2]);
+        edMocker.resetInvocationLog();
+
+        uploadDialog = new MockUploadDialog("", "source");
+        new UploadDialog.UploadAction(uploadDialog).actionPerformed(null);
+
+        assertEquals(1, uploadDialog.handleMissingCommentCalls);
+        assertEquals(0, uploadDialog.handleMissingSourceCalls);
+        assertEquals(1, edMocker.getInvocationLog().size());
+        invocationLogEntry = edMocker.getInvocationLog().get(0);
+        assertEquals(1, (int) invocationLogEntry[0]);
+        assertEquals("Please revise upload comment", invocationLogEntry[2]);
+        edMocker.resetInvocationLog();
+
+        uploadDialog = new MockUploadDialog("comment", "");
+        new UploadDialog.UploadAction(uploadDialog).actionPerformed(null);
+
+        assertEquals(1, uploadDialog.handleMissingCommentCalls);
+        assertEquals(0, uploadDialog.handleMissingSourceCalls);
+        assertEquals(1, edMocker.getInvocationLog().size());
+        invocationLogEntry = edMocker.getInvocationLog().get(0);
+        assertEquals(1, (int) invocationLogEntry[0]);
+        assertEquals("Please revise upload comment", invocationLogEntry[2]);
+        edMocker.resetInvocationLog();
+
+        uploadDialog = new MockUploadDialog("a comment long enough", "");
+        new UploadDialog.UploadAction(uploadDialog).actionPerformed(null);
+
+        assertEquals(0, uploadDialog.handleMissingCommentCalls);
+        assertEquals(1, uploadDialog.handleMissingSourceCalls);
+        assertEquals(1, edMocker.getInvocationLog().size());
+        invocationLogEntry = edMocker.getInvocationLog().get(0);
+        assertEquals(1, (int) invocationLogEntry[0]);
+        assertEquals("Please specify a changeset source", invocationLogEntry[2]);
+        edMocker.resetInvocationLog();
+
+        uploadDialog = new MockUploadDialog("a comment long enough", "a source long enough");
+        new UploadDialog.UploadAction(uploadDialog).actionPerformed(null);
+
+        assertEquals(0, uploadDialog.handleMissingCommentCalls);
+        assertEquals(0, uploadDialog.handleMissingSourceCalls);
+        assertEquals(0, edMocker.getInvocationLog().size());
     }
 
     /**
diff --git a/test/unit/org/openstreetmap/josm/testutils/mockers/BaseDialogMockUp.java b/test/unit/org/openstreetmap/josm/testutils/mockers/BaseDialogMockUp.java
index 4cae11948..a20d3c329 100644
--- a/test/unit/org/openstreetmap/josm/testutils/mockers/BaseDialogMockUp.java
+++ b/test/unit/org/openstreetmap/josm/testutils/mockers/BaseDialogMockUp.java
@@ -25,6 +25,13 @@ abstract class BaseDialogMockUp<T> extends MockUp<T> {
         return this.invocationLog;
     }
 
+    /**
+     * Empties the invocation log.
+     */
+    public void resetInvocationLog() {
+        this.invocationLogInternal.clear();
+    }
+
     private final List<Object[]> invocationLogInternal = new ArrayList<>(4);
 
     /**
-- 
2.11.0

