source: josm/trunk/test/unit/org/openstreetmap/josm/gui/io/SaveLayersDialogTest.java@ 18706

Last change on this file since 18706 was 18706, checked in by taylor.smock, 14 months ago

Fix #22817: Don't delete layer with changes and a non-normal upload policy (patch by gaben, modified)

Patch modifications are as follows:

  • A non-regression test
  • Account for UploadPolicy.BLOCKED causing requiresUploadToServer to return false.
  • Property svn:eol-style set to native
File size: 7.6 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.io;
3
4import static org.junit.jupiter.api.Assertions.assertEquals;
5import static org.junit.jupiter.api.Assertions.assertFalse;
6import static org.junit.jupiter.api.Assertions.assertTrue;
7
8import java.awt.Component;
9import java.awt.GraphicsEnvironment;
10import java.io.File;
11import java.util.Collections;
12import java.util.List;
13
14import javax.swing.JComponent;
15import javax.swing.JLabel;
16import javax.swing.JList;
17import javax.swing.JOptionPane;
18
19import mockit.Invocation;
20import mockit.Mock;
21import mockit.MockUp;
22import org.junit.jupiter.api.Test;
23import org.junit.jupiter.params.ParameterizedTest;
24import org.junit.jupiter.params.provider.EnumSource;
25import org.openstreetmap.josm.command.AddPrimitivesCommand;
26import org.openstreetmap.josm.data.coor.LatLon;
27import org.openstreetmap.josm.data.osm.DataSet;
28import org.openstreetmap.josm.data.osm.Node;
29import org.openstreetmap.josm.data.osm.UploadPolicy;
30import org.openstreetmap.josm.gui.layer.OsmDataLayer;
31import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
32import org.openstreetmap.josm.testutils.mockers.JOptionPaneSimpleMocker;
33import org.openstreetmap.josm.testutils.mockers.WindowMocker;
34
35/**
36 * Unit tests of {@link SaveLayersDialog} class.
37 */
38@BasicPreferences
39class SaveLayersDialogTest {
40 /**
41 * Test of {@link SaveLayersDialog#confirmSaveLayerInfosOK}.
42 */
43 @Test
44 void testConfirmSaveLayerInfosOK() {
45 final List<SaveLayerInfo> list = Collections.singletonList(new SaveLayerInfo(new OsmDataLayer(new DataSet(), null, null)));
46
47 final JOptionPaneSimpleMocker jopsMocker = new JOptionPaneSimpleMocker() {
48 @Override
49 protected void act(final Object message) {
50 // use this opportunity to assert that our SaveLayerInfo is the single option in the JList
51 @SuppressWarnings("unchecked")
52 final JList<SaveLayerInfo> jList = (JList<SaveLayerInfo>) ((JComponent) message).getComponent(1);
53 assertEquals(1, jList.getModel().getSize());
54 assertEquals(list.get(0), jList.getModel().getElementAt(0));
55 }
56
57 @Override
58 protected String getStringFromMessage(final Object message) {
59 return ((JLabel) ((JComponent) message).getComponent(0)).getText();
60 }
61 };
62
63 jopsMocker.getMockResultMap().put(
64 "<html>1 layer has unresolved conflicts.<br>Either resolve them first or discard the "
65 + "modifications.<br>Layer with conflicts:</html>", JOptionPane.OK_OPTION
66 );
67
68 assertFalse(SaveLayersDialog.confirmSaveLayerInfosOK(new SaveLayersModel() {
69 @Override
70 public List<SaveLayerInfo> getLayersWithConflictsAndUploadRequest() {
71 return list;
72 }
73 }));
74
75 assertEquals(1, jopsMocker.getInvocationLog().size());
76 Object[] invocationLogEntry = jopsMocker.getInvocationLog().get(0);
77 assertEquals(JOptionPane.OK_OPTION, (int) invocationLogEntry[0]);
78 assertEquals("Unsaved data and conflicts", invocationLogEntry[2]);
79
80 jopsMocker.resetInvocationLog();
81 jopsMocker.getMockResultMap().clear();
82 jopsMocker.getMockResultMap().put(
83 "<html>1 layer needs saving but has no associated file.<br>Either select a file for this "
84 + "layer or discard the changes.<br>Layer without a file:</html>", JOptionPane.OK_OPTION
85 );
86
87 assertFalse(SaveLayersDialog.confirmSaveLayerInfosOK(new SaveLayersModel() {
88 @Override
89 public List<SaveLayerInfo> getLayersWithoutFilesAndSaveRequest() {
90 return list;
91 }
92 }));
93
94 assertEquals(1, jopsMocker.getInvocationLog().size());
95 invocationLogEntry = jopsMocker.getInvocationLog().get(0);
96 assertEquals(JOptionPane.OK_OPTION, (int) invocationLogEntry[0]);
97 assertEquals("Unsaved data and missing associated file", invocationLogEntry[2]);
98
99 jopsMocker.resetInvocationLog();
100 jopsMocker.getMockResultMap().clear();
101 jopsMocker.getMockResultMap().put(
102 "<html>1 layer needs saving but has an associated file<br>which cannot be written.<br>Either "
103 + "select another file for this layer or discard the changes.<br>Layer with a non-writable "
104 + "file:</html>", JOptionPane.OK_OPTION
105 );
106
107 assertFalse(SaveLayersDialog.confirmSaveLayerInfosOK(new SaveLayersModel() {
108 @Override
109 public List<SaveLayerInfo> getLayersWithIllegalFilesAndSaveRequest() {
110 return list;
111 }
112 }));
113
114 assertEquals(1, jopsMocker.getInvocationLog().size());
115 invocationLogEntry = jopsMocker.getInvocationLog().get(0);
116 assertEquals(JOptionPane.OK_OPTION, (int) invocationLogEntry[0]);
117 assertEquals("Unsaved data non-writable files", invocationLogEntry[2]);
118
119 jopsMocker.resetInvocationLog();
120 jopsMocker.getMockResultMap().clear();
121
122 assertTrue(SaveLayersDialog.confirmSaveLayerInfosOK(new SaveLayersModel()));
123 }
124
125 /**
126 * Non-regression test for #22817: No warning when deleting a layer with changes and discourages upload
127 * @param policy The upload policy to test
128 */
129 @ParameterizedTest
130 @EnumSource(value = UploadPolicy.class)
131 void testNonRegression22817(UploadPolicy policy) {
132 final OsmDataLayer osmDataLayer = new OsmDataLayer(new DataSet(), null, null);
133 osmDataLayer.getDataSet().setUploadPolicy(policy);
134 // BLOCKED files don't have a way to become blocked via the UI, so they must be loaded from disk.
135 if (policy == UploadPolicy.BLOCKED) {
136 osmDataLayer.setAssociatedFile(new File("/dev/null"));
137 }
138 new AddPrimitivesCommand(Collections.singletonList(new Node(LatLon.ZERO).save()), Collections.emptyList(), osmDataLayer.getDataSet())
139 .executeCommand();
140 assertTrue(osmDataLayer.getDataSet().isModified());
141 new WindowMocker();
142 // Needed since the *first call* is to check whether we are in a headless environment
143 new GraphicsEnvironmentMock();
144 // Needed since we need to mock out the UI
145 SaveLayersDialogMock saveLayersDialogMock = new SaveLayersDialogMock();
146
147 assertTrue(SaveLayersDialog.saveUnsavedModifications(Collections.singleton(osmDataLayer), SaveLayersDialog.Reason.DELETE));
148 assertEquals(1, saveLayersDialogMock.getUserActionCalled, "The user should have been asked for an action on the layer");
149 }
150
151 private static class GraphicsEnvironmentMock extends MockUp<GraphicsEnvironment> {
152 @Mock
153 public static boolean isHeadless(Invocation invocation) {
154 return false;
155 }
156 }
157
158 private static class SaveLayersDialogMock extends MockUp<SaveLayersDialog> {
159 private final SaveLayersModel model = new SaveLayersModel();
160 private int getUserActionCalled = 0;
161 @Mock
162 public void $init(Component parent) {
163 // Do nothing
164 }
165
166 @Mock
167 public void prepareForSavingAndUpdatingLayers(final SaveLayersDialog.Reason reason) {
168 // Do nothing
169 }
170
171 @Mock
172 public SaveLayersModel getModel() {
173 return this.model;
174 }
175
176 @Mock
177 public void setVisible(boolean b) {
178 // Do nothing
179 }
180
181 @Mock
182 public SaveLayersDialog.UserAction getUserAction() {
183 this.getUserActionCalled++;
184 return SaveLayersDialog.UserAction.PROCEED;
185 }
186
187 @Mock
188 public void closeDialog() {
189 // Do nothing
190 }
191 }
192}
Note: See TracBrowser for help on using the repository browser.