Ver código fonte

Pull out the act of batch-adding children into an object as ReplaceChildrenController.
Add test code for ReplaceChildrenController and SummaryPanel.

Sam Jaffe 5 anos atrás
pai
commit
422e542517

+ 28 - 0
src/main/lombok/org/leumasjaffe/recipe/controller/ReplaceChildrenController.java

@@ -0,0 +1,28 @@
+package org.leumasjaffe.recipe.controller;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.util.Collection;
+import java.util.function.BiConsumer;
+import java.util.function.Function;
+
+import lombok.AccessLevel;
+import lombok.RequiredArgsConstructor;
+import lombok.experimental.FieldDefaults;
+
+@RequiredArgsConstructor
+@FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
+public class ReplaceChildrenController<T, V> implements BiConsumer<Container, T> {
+	Function<T, ? extends Collection<V>> getChildren;
+	Function<? super V, ? extends Component> makeView;
+	
+	@Override
+	public void accept(final Container parent, final T model) {
+		final Collection<V> children = getChildren.apply(model);
+		if (parent.getComponents().length == children.size()) {
+			return;
+		}
+		parent.removeAll();
+		children.stream().map(makeView).forEach(parent::add);
+	}
+}

+ 21 - 13
src/main/lombok/org/leumasjaffe/recipe/view/summary/SummaryPanel.java

@@ -11,6 +11,8 @@ import javax.swing.JTextField;
 
 import org.jdesktop.swingx.VerticalLayout;
 import org.leumasjaffe.observer.ObservableListener;
+import org.leumasjaffe.observer.ObserverDispatch;
+import org.leumasjaffe.recipe.controller.ReplaceChildrenController;
 import org.leumasjaffe.recipe.model.CollatedDuration;
 import org.leumasjaffe.recipe.model.Element;
 import org.leumasjaffe.recipe.model.RecipeCard;
@@ -22,12 +24,20 @@ import lombok.experimental.FieldDefaults;
 import java.awt.Font;
 
 @SuppressWarnings("serial")
-@FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
+@FieldDefaults(level=AccessLevel.PRIVATE)
 public class SummaryPanel extends JPanel {
+	ReplaceChildrenController<RecipeCard, Element> controller;
 	ObservableListener<CollatedDurationPanel, RecipeCard> durationListener;
 	ObservableListener<JPanel, RecipeCard> childListener;
 	
 	public SummaryPanel(final RecipeCard card) {
+		controller = new ReplaceChildrenController<>(RecipeCard::getElements, element -> {
+			JPanel wrapper = new JPanel(new VerticalLayout());
+			wrapper.add(new ElementPanel(element));
+			wrapper.add(new JSeparator());
+			return wrapper;
+		});
+		
 		GridBagLayout gridBagLayout = new GridBagLayout();
 		gridBagLayout.columnWidths = new int[]{0, 0, 0};
 		gridBagLayout.rowHeights = new int[]{0, 0, 0, 0};
@@ -111,21 +121,19 @@ public class SummaryPanel extends JPanel {
 		durationListener = new ObservableListener<>(panelDuration,
 				(c, v) -> c.setModel(v.getCollatedDuration()));
 		
-		childListener = new ObservableListener<>(panelIngredients, (c, v) -> {
-			if (c.getComponents().length == v.getElements().size()) {
-				return;
-			}
-			c.removeAll();
-			for (final Element element : v.getElements()) {
-				JPanel wrapper = new JPanel(new VerticalLayout());
-				wrapper.add(new ElementPanel(element));
-				wrapper.add(new JSeparator());
-				c.add(wrapper);
-			}
-		});
+		// This indirection allows for testing of controller
+		childListener = new ObservableListener<>(panelIngredients,
+				(c, v) -> controller.accept(c, v));
 		
 		durationListener.setObserved(card);
 		childListener.setObserved(card);
 	}
 	
+	@Override
+	public void removeNotify() {
+		super.removeNotify();
+		ObserverDispatch.unsubscribeAll(durationListener);
+		ObserverDispatch.unsubscribeAll(childListener);
+	}
+	
 }

+ 52 - 0
src/test/java/org/leumasjaffe/recipe/controller/ReplaceChildrenControllerTest.java

@@ -0,0 +1,52 @@
+package org.leumasjaffe.recipe.controller;
+
+import static org.mockito.Mockito.*;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.function.Function;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.platform.runner.JUnitPlatform;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+@ExtendWith(MockitoExtension.class)
+@RunWith(JUnitPlatform.class)
+class ReplaceChildrenControllerTest {
+	
+	@Mock Container parent;
+	Function<Void, Collection<Void>> getChildren = (v) -> Arrays.asList(null, null);
+	Function<Void, Component> makeView = (v) -> null;
+	ReplaceChildrenController<Void, Void> controller;
+	
+	@BeforeEach
+	void setUp() {
+		controller = new ReplaceChildrenController<>(getChildren, makeView);
+	}
+
+	@Test
+	void testDoesNotReplaceComponentsWhenNoSizeChange() {
+		doReturn(new Component[2]).when(parent).getComponents();
+		
+		controller.accept(parent, null);
+		
+		verify(parent, never()).removeAll();
+		verify(parent, never()).add((Component) any());
+	}
+
+	@Test
+	void testReplacesComponents() {
+		doReturn(new Component[1]).when(parent).getComponents();
+		
+		controller.accept(parent, null);
+		
+		verify(parent).removeAll();
+		verify(parent, times(2)).add((Component) any());
+	}
+}

+ 31 - 0
src/test/java/org/leumasjaffe/recipe/view/summary/SummaryPanelTest.java

@@ -0,0 +1,31 @@
+package org.leumasjaffe.recipe.view.summary;
+
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.platform.runner.JUnitPlatform;
+import org.junit.runner.RunWith;
+import org.leumasjaffe.observer.ObserverDispatch;
+import org.leumasjaffe.recipe.controller.ReplaceChildrenController;
+import org.leumasjaffe.recipe.model.Element;
+import org.leumasjaffe.recipe.model.RecipeCard;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+@ExtendWith(MockitoExtension.class)
+@RunWith(JUnitPlatform.class)
+class SummaryPanelTest {
+	
+	RecipeCard card = new RecipeCard();
+	@Mock ReplaceChildrenController<RecipeCard, Element> controller;
+	@InjectMocks SummaryPanel panel = new SummaryPanel(card);
+
+	@Test
+	void testUpdateToCardInvokesController() {
+		ObserverDispatch.notifySubscribers(card);
+		verify(controller).accept(any(), same(card));
+	}
+
+}