Skip to content

Commit 2ef260e

Browse files
authored
Merge pull request #395 from BentoBoxWorld/worktree-junit5-panel-tests
Worktree junit5 panel tests
2 parents 48b503a + c12c15c commit 2ef260e

8 files changed

Lines changed: 1578 additions & 0 deletions

File tree

Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
package world.bentobox.challenges.panel;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertFalse;
5+
import static org.junit.jupiter.api.Assertions.assertNotNull;
6+
import static org.junit.jupiter.api.Assertions.assertTrue;
7+
import static org.mockito.ArgumentMatchers.any;
8+
import static org.mockito.ArgumentMatchers.anyInt;
9+
import static org.mockito.ArgumentMatchers.eq;
10+
import static org.mockito.Mockito.mock;
11+
import static org.mockito.Mockito.never;
12+
import static org.mockito.Mockito.times;
13+
import static org.mockito.Mockito.verify;
14+
import static org.mockito.Mockito.when;
15+
16+
import java.util.ArrayList;
17+
import java.util.List;
18+
import java.util.stream.IntStream;
19+
20+
import org.bukkit.Bukkit;
21+
import org.bukkit.World;
22+
import org.junit.jupiter.api.AfterEach;
23+
import org.junit.jupiter.api.BeforeEach;
24+
import org.junit.jupiter.api.Test;
25+
import org.mockbukkit.mockbukkit.MockBukkit;
26+
import org.mockbukkit.mockbukkit.ServerMock;
27+
import org.mockito.ArgumentCaptor;
28+
import org.mockito.Mock;
29+
import org.mockito.MockedStatic;
30+
import org.mockito.Mockito;
31+
import org.mockito.MockitoAnnotations;
32+
33+
import world.bentobox.bentobox.api.panels.PanelItem;
34+
import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
35+
import world.bentobox.bentobox.api.user.User;
36+
import world.bentobox.challenges.ChallengesAddon;
37+
import world.bentobox.challenges.managers.ChallengesManager;
38+
39+
/**
40+
* Tests for {@link CommonPagedPanel} pagination and button creation logic.
41+
*/
42+
public class CommonPagedPanelTest {
43+
44+
@Mock
45+
private ChallengesAddon addon;
46+
@Mock
47+
private User user;
48+
@Mock
49+
private World world;
50+
@Mock
51+
private ChallengesManager manager;
52+
@Mock
53+
private PanelBuilder panelBuilder;
54+
55+
private TestablePagedPanel panel;
56+
private AutoCloseable closeable;
57+
private ServerMock mbServer;
58+
private MockedStatic<Bukkit> mockedBukkit;
59+
60+
private static class TestablePagedPanel extends CommonPagedPanel<String> {
61+
private boolean filterUpdated = false;
62+
private final List<PanelItem> createdButtons = new ArrayList<>();
63+
64+
protected TestablePagedPanel(ChallengesAddon addon, User user, World world,
65+
String topLabel, String permissionPrefix) {
66+
super(addon, user, world, topLabel, permissionPrefix);
67+
}
68+
69+
@Override
70+
protected void build() { }
71+
72+
@Override
73+
protected void updateFilters() {
74+
this.filterUpdated = true;
75+
}
76+
77+
@Override
78+
protected PanelItem createElementButton(String object) {
79+
PanelItem item = mock(PanelItem.class);
80+
createdButtons.add(item);
81+
return item;
82+
}
83+
84+
public void callPopulateElements(PanelBuilder builder, List<String> objects) {
85+
this.populateElements(builder, objects);
86+
}
87+
88+
@SuppressWarnings("unchecked")
89+
public PanelItem callGetButton(String buttonName) throws Exception {
90+
Class<?> enumClass = Class.forName(
91+
"world.bentobox.challenges.panel.CommonPagedPanel$CommonButtons");
92+
Object enumValue = null;
93+
for (Object c : enumClass.getEnumConstants()) {
94+
if (c.toString().equals(buttonName)) {
95+
enumValue = c;
96+
break;
97+
}
98+
}
99+
var method = CommonPagedPanel.class.getDeclaredMethod("getButton", enumClass);
100+
method.setAccessible(true);
101+
return (PanelItem) method.invoke(this, enumValue);
102+
}
103+
104+
public void setPageIndex(int index) throws Exception {
105+
var field = CommonPagedPanel.class.getDeclaredField("pageIndex");
106+
field.setAccessible(true);
107+
field.setInt(this, index);
108+
}
109+
110+
public int getPageIndex() throws Exception {
111+
var field = CommonPagedPanel.class.getDeclaredField("pageIndex");
112+
field.setAccessible(true);
113+
return field.getInt(this);
114+
}
115+
}
116+
117+
@BeforeEach
118+
public void setUp() throws Exception {
119+
closeable = MockitoAnnotations.openMocks(this);
120+
mbServer = MockBukkit.mock();
121+
122+
when(addon.getChallengesManager()).thenReturn(manager);
123+
PanelTestHelper.setupUserTranslations(user);
124+
when(panelBuilder.slotOccupied(anyInt())).thenReturn(false);
125+
126+
mockedBukkit = Mockito.mockStatic(Bukkit.class, Mockito.RETURNS_DEEP_STUBS);
127+
mockedBukkit.when(Bukkit::getServer).thenReturn(mbServer);
128+
mockedBukkit.when(Bukkit::getItemFactory).thenReturn(mbServer.getItemFactory());
129+
mockedBukkit.when(Bukkit::getUnsafe).thenReturn(mbServer.getUnsafe());
130+
131+
panel = new TestablePagedPanel(addon, user, world, "island", "bskyblock.");
132+
}
133+
134+
@AfterEach
135+
public void tearDown() throws Exception {
136+
if (mockedBukkit != null) mockedBukkit.closeOnDemand();
137+
if (closeable != null) closeable.close();
138+
MockBukkit.unmock();
139+
Mockito.framework().clearInlineMocks();
140+
}
141+
142+
@Test
143+
public void testPopulateEmptyList() {
144+
panel.callPopulateElements(panelBuilder, List.of());
145+
verify(panelBuilder, never()).item(anyInt(), any(PanelItem.class));
146+
}
147+
148+
@Test
149+
public void testPopulateSingleElement() {
150+
panel.callPopulateElements(panelBuilder, List.of("one"));
151+
verify(panelBuilder).item(eq(10), any(PanelItem.class));
152+
assertEquals(1, panel.createdButtons.size());
153+
}
154+
155+
@Test
156+
public void testPopulateExactlyMaxElements() {
157+
List<String> elements = IntStream.range(0, 21).mapToObj(i -> "item" + i).toList();
158+
panel.callPopulateElements(panelBuilder, elements);
159+
assertEquals(21, panel.createdButtons.size());
160+
}
161+
162+
@Test
163+
public void testPopulateMoreThanMaxShowsNextButton() {
164+
List<String> elements = IntStream.range(0, 22).mapToObj(i -> "item" + i).toList();
165+
panel.callPopulateElements(panelBuilder, elements);
166+
ArgumentCaptor<Integer> slotCaptor = ArgumentCaptor.forClass(Integer.class);
167+
verify(panelBuilder, times(23)).item(slotCaptor.capture(), any(PanelItem.class));
168+
assertTrue(slotCaptor.getAllValues().contains(26));
169+
}
170+
171+
@Test
172+
public void testPopulateSecondPageShowsPreviousButton() throws Exception {
173+
panel.setPageIndex(1);
174+
List<String> elements = IntStream.range(0, 42).mapToObj(i -> "item" + i).toList();
175+
panel.callPopulateElements(panelBuilder, elements);
176+
ArgumentCaptor<Integer> slotCaptor = ArgumentCaptor.forClass(Integer.class);
177+
// 21 items + previous button + search button = 23
178+
verify(panelBuilder, times(23)).item(slotCaptor.capture(), any(PanelItem.class));
179+
assertTrue(slotCaptor.getAllValues().contains(18));
180+
}
181+
182+
@Test
183+
public void testPopulateSkipsOccupiedSlots() {
184+
when(panelBuilder.slotOccupied(10)).thenReturn(true);
185+
panel.callPopulateElements(panelBuilder, List.of("one", "two", "three"));
186+
verify(panelBuilder, never()).item(eq(10), any(PanelItem.class));
187+
assertEquals(3, panel.createdButtons.size());
188+
}
189+
190+
@Test
191+
public void testNegativePageIndexWrapsToLastPage() throws Exception {
192+
panel.setPageIndex(-1);
193+
List<String> elements = IntStream.range(0, 42).mapToObj(i -> "item" + i).toList();
194+
panel.callPopulateElements(panelBuilder, elements);
195+
assertEquals(2, panel.getPageIndex());
196+
}
197+
198+
@Test
199+
public void testPageIndexBeyondMaxWrapsToZero() throws Exception {
200+
panel.setPageIndex(5);
201+
List<String> elements = IntStream.range(0, 21).mapToObj(i -> "item" + i).toList();
202+
panel.callPopulateElements(panelBuilder, elements);
203+
assertEquals(0, panel.getPageIndex());
204+
}
205+
206+
@Test
207+
public void testSearchButtonAppearsWhenMoreThanMaxElements() {
208+
List<String> elements = IntStream.range(0, 22).mapToObj(i -> "item" + i).toList();
209+
panel.callPopulateElements(panelBuilder, elements);
210+
ArgumentCaptor<Integer> slotCaptor = ArgumentCaptor.forClass(Integer.class);
211+
verify(panelBuilder, times(23)).item(slotCaptor.capture(), any(PanelItem.class));
212+
assertTrue(slotCaptor.getAllValues().contains(40));
213+
}
214+
215+
@Test
216+
public void testSearchButtonAppearsWhenSearchStringSet() {
217+
panel.searchString = "test";
218+
panel.callPopulateElements(panelBuilder, List.of("one"));
219+
ArgumentCaptor<Integer> slotCaptor = ArgumentCaptor.forClass(Integer.class);
220+
verify(panelBuilder, times(2)).item(slotCaptor.capture(), any(PanelItem.class));
221+
assertTrue(slotCaptor.getAllValues().contains(40));
222+
}
223+
224+
@Test
225+
public void testNoSearchButtonWhenFewElementsAndNoSearch() {
226+
panel.callPopulateElements(panelBuilder, List.of("one", "two"));
227+
ArgumentCaptor<Integer> slotCaptor = ArgumentCaptor.forClass(Integer.class);
228+
verify(panelBuilder, times(2)).item(slotCaptor.capture(), any(PanelItem.class));
229+
assertFalse(slotCaptor.getAllValues().contains(40));
230+
}
231+
232+
@Test
233+
public void testGetNextButton() throws Exception {
234+
PanelItem nextButton = panel.callGetButton("NEXT");
235+
assertNotNull(nextButton);
236+
}
237+
238+
@Test
239+
public void testGetPreviousButton() throws Exception {
240+
PanelItem prevButton = panel.callGetButton("PREVIOUS");
241+
assertNotNull(prevButton);
242+
}
243+
244+
@Test
245+
public void testGetSearchButton() throws Exception {
246+
PanelItem searchButton = panel.callGetButton("SEARCH");
247+
assertNotNull(searchButton);
248+
}
249+
250+
@Test
251+
public void testGetSearchButtonWithExistingSearchString() throws Exception {
252+
panel.searchString = "diamond";
253+
PanelItem searchButton = panel.callGetButton("SEARCH");
254+
assertNotNull(searchButton);
255+
}
256+
257+
@Test
258+
public void testPopulateLastPageNoNextButton() throws Exception {
259+
panel.setPageIndex(1);
260+
List<String> elements = IntStream.range(0, 42).mapToObj(i -> "item" + i).toList();
261+
panel.callPopulateElements(panelBuilder, elements);
262+
ArgumentCaptor<Integer> slotCaptor = ArgumentCaptor.forClass(Integer.class);
263+
// 21 items + previous button + search button = 23
264+
verify(panelBuilder, times(23)).item(slotCaptor.capture(), any(PanelItem.class));
265+
assertTrue(slotCaptor.getAllValues().contains(18));
266+
assertEquals(1, panel.getPageIndex());
267+
}
268+
269+
@Test
270+
public void testPopulateFirstPageNoPreviousButton() throws Exception {
271+
List<String> elements = IntStream.range(0, 42).mapToObj(i -> "item" + i).toList();
272+
panel.callPopulateElements(panelBuilder, elements);
273+
// First page: 21 items + next button + search button = 23
274+
ArgumentCaptor<Integer> slotCaptor = ArgumentCaptor.forClass(Integer.class);
275+
verify(panelBuilder, times(23)).item(slotCaptor.capture(), any(PanelItem.class));
276+
assertTrue(slotCaptor.getAllValues().contains(26));
277+
assertEquals(0, panel.getPageIndex());
278+
}
279+
}

0 commit comments

Comments
 (0)