Skip to content

Commit 07605c9

Browse files
vogellaclaude
andcommitted
Add CTabFolder test coverage for untested API and edge cases
Adds 13 focused tests covering behavior that was previously untested: error handling for invalid arguments, single-mode rendering, empty folder edge cases, selection boundary conditions, min/max mutual exclusion, tab compression under overflow, item disposal of the selected item, hit-testing, and SelectionListener contract. Contributes to #3219 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent fbe0d7a commit 07605c9

File tree

1 file changed

+211
-0
lines changed

1 file changed

+211
-0
lines changed

tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_custom_CTabFolder.java

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
import static org.junit.jupiter.api.Assertions.assertEquals;
1818
import static org.junit.jupiter.api.Assertions.assertFalse;
1919
import static org.junit.jupiter.api.Assertions.assertNotNull;
20+
import static org.junit.jupiter.api.Assertions.assertNull;
21+
import static org.junit.jupiter.api.Assertions.assertThrows;
22+
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
2023
import static org.junit.jupiter.api.Assertions.assertTrue;
2124
import static org.junit.jupiter.api.Assertions.fail;
2225

@@ -25,7 +28,9 @@
2528
import java.util.ArrayList;
2629
import java.util.Arrays;
2730
import java.util.List;
31+
import java.util.concurrent.atomic.AtomicBoolean;
2832
import java.util.concurrent.atomic.AtomicLong;
33+
import java.util.concurrent.atomic.AtomicReference;
2934
import java.util.function.BiConsumer;
3035
import java.util.function.Consumer;
3136

@@ -728,4 +733,210 @@ private Rectangle getBoundsInShell(Widget control) {
728733
return bounds;
729734
}
730735

736+
@Test
737+
public void test_setTabPosition_invalidArgument() {
738+
makeCleanEnvironment();
739+
assertThrows(IllegalArgumentException.class, () -> ctabFolder.setTabPosition(SWT.LEFT));
740+
}
741+
742+
@Test
743+
public void test_setTabHeight_invalidArgument() {
744+
makeCleanEnvironment();
745+
assertThrows(IllegalArgumentException.class, () -> ctabFolder.setTabHeight(-2));
746+
}
747+
748+
@Test
749+
public void test_setSingle_onlySelectedTabShowing() {
750+
createTabFolder(null, 5);
751+
shell.setSize(800, 400);
752+
SwtTestUtil.openShell(shell);
753+
processEvents();
754+
755+
ctabFolder.setSingle(true);
756+
processEvents();
757+
758+
// in single mode, only the selected tab should be showing
759+
int selectedIdx = ctabFolder.getSelectionIndex();
760+
for (int i = 0; i < ctabFolder.getItemCount(); i++) {
761+
if (i == selectedIdx) {
762+
assertTrue(ctabFolder.getItem(i).isShowing(),
763+
"Selected tab at index " + i + " should be showing in single mode");
764+
}
765+
}
766+
}
767+
768+
@Test
769+
public void test_getSelection_empty() {
770+
makeCleanEnvironment();
771+
assertNull(ctabFolder.getSelection());
772+
assertEquals(-1, ctabFolder.getSelectionIndex());
773+
}
774+
775+
@Test
776+
public void test_setSelection_outOfRange() {
777+
createTabFolder(null, 3);
778+
ctabFolder.setSelection(0);
779+
assertEquals(0, ctabFolder.getSelectionIndex());
780+
781+
// out of range should not change selection
782+
ctabFolder.setSelection(-1);
783+
assertEquals(0, ctabFolder.getSelectionIndex());
784+
785+
ctabFolder.setSelection(99);
786+
assertEquals(0, ctabFolder.getSelectionIndex());
787+
}
788+
789+
@Test
790+
public void test_minimized_maximized_mutualExclusion() {
791+
makeCleanEnvironment();
792+
793+
assertFalse(ctabFolder.getMinimized());
794+
assertFalse(ctabFolder.getMaximized());
795+
796+
ctabFolder.setMinimized(true);
797+
assertTrue(ctabFolder.getMinimized());
798+
assertFalse(ctabFolder.getMaximized());
799+
800+
// setting maximized should clear minimized
801+
ctabFolder.setMaximized(true);
802+
assertTrue(ctabFolder.getMaximized());
803+
assertFalse(ctabFolder.getMinimized());
804+
805+
ctabFolder.setMaximized(false);
806+
assertFalse(ctabFolder.getMaximized());
807+
assertFalse(ctabFolder.getMinimized());
808+
}
809+
810+
@Test
811+
public void test_emptyFolder_operationsDontThrow() {
812+
makeCleanEnvironment();
813+
814+
assertEquals(0, ctabFolder.getItemCount());
815+
assertNull(ctabFolder.getSelection());
816+
assertEquals(-1, ctabFolder.getSelectionIndex());
817+
818+
assertDoesNotThrow(() -> {
819+
ctabFolder.showSelection();
820+
ctabFolder.setBorderVisible(true);
821+
ctabFolder.setMinimizeVisible(true);
822+
ctabFolder.setMaximizeVisible(true);
823+
ctabFolder.setSingle(true);
824+
ctabFolder.setTabPosition(SWT.BOTTOM);
825+
});
826+
}
827+
828+
@Test
829+
public void test_emptyFolder_afterDisposingAllItems() {
830+
createTabFolder(null, 3);
831+
assertEquals(3, ctabFolder.getItemCount());
832+
ctabFolder.setSelection(1);
833+
834+
while (ctabFolder.getItemCount() > 0) {
835+
ctabFolder.getItem(0).dispose();
836+
}
837+
838+
assertEquals(0, ctabFolder.getItemCount());
839+
assertNull(ctabFolder.getSelection());
840+
assertEquals(-1, ctabFolder.getSelectionIndex());
841+
}
842+
843+
@Test
844+
public void test_tabOverflow_tabCompression() {
845+
createTabFolder(null, 15);
846+
shell.setSize(800, 200);
847+
SwtTestUtil.openShell(shell);
848+
processEvents();
849+
850+
int[] fullWidths = new int[ctabFolder.getItemCount()];
851+
for (int i = 0; i < ctabFolder.getItemCount(); i++) {
852+
fullWidths[i] = ctabFolder.getItem(i).getBounds().width;
853+
}
854+
855+
// shrink to force compression
856+
shell.setSize(200, 200);
857+
processEvents();
858+
859+
boolean anyCompressed = false;
860+
for (int i = 0; i < ctabFolder.getItemCount(); i++) {
861+
int w = ctabFolder.getItem(i).getBounds().width;
862+
if (w < fullWidths[i] || w == 0) {
863+
anyCompressed = true;
864+
break;
865+
}
866+
}
867+
assertTrue(anyCompressed, "Some tabs should be compressed when space is tight");
868+
}
869+
870+
@Test
871+
public void test_SelectionListener_notFiredProgrammatically() {
872+
createTabFolder(null, 3);
873+
874+
AtomicBoolean selectionFired = new AtomicBoolean(false);
875+
AtomicReference<Widget> selectedItem = new AtomicReference<>();
876+
877+
ctabFolder.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() {
878+
@Override
879+
public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {
880+
selectionFired.set(true);
881+
selectedItem.set(e.item);
882+
}
883+
});
884+
885+
// programmatic setSelection must NOT fire SelectionListener
886+
ctabFolder.setSelection(1);
887+
assertFalse(selectionFired.get(), "Programmatic setSelection should not fire SelectionListener");
888+
889+
// user-initiated selection (via notifyListeners) must fire
890+
Event event = new Event();
891+
event.item = ctabFolder.getItem(2);
892+
ctabFolder.notifyListeners(SWT.Selection, event);
893+
894+
assertTrue(selectionFired.get(), "SelectionListener should fire on SWT.Selection event");
895+
assertEquals(ctabFolder.getItem(2), selectedItem.get());
896+
}
897+
898+
@Test
899+
public void test_itemDisposal_selectedItem() {
900+
createTabFolder(null, 3);
901+
ctabFolder.setSelection(1);
902+
assertEquals(1, ctabFolder.getSelectionIndex());
903+
904+
// disposing the currently selected item must not crash
905+
ctabFolder.getItem(1).dispose();
906+
assertEquals(2, ctabFolder.getItemCount());
907+
}
908+
909+
@Test
910+
public void test_showSelection_makesSelectedVisible() {
911+
createTabFolder(null, 20);
912+
SwtTestUtil.openShell(shell);
913+
914+
ctabFolder.setSelection(ctabFolder.getItemCount() - 1);
915+
ctabFolder.showSelection();
916+
processEvents();
917+
918+
assertTrue(ctabFolder.getItem(ctabFolder.getSelectionIndex()).isShowing(),
919+
"Selected item should be visible after showSelection()");
920+
}
921+
922+
@Test
923+
public void test_getItem_byPoint() {
924+
createTabFolder(null, 3);
925+
shell.setSize(800, 400);
926+
SwtTestUtil.openShell(shell);
927+
processEvents();
928+
929+
CTabItem firstItem = ctabFolder.getItem(0);
930+
Rectangle bounds = firstItem.getBounds();
931+
// point inside the first tab should find it
932+
CTabItem found = ctabFolder.getItem(
933+
ctabFolder.toControl(ctabFolder.toDisplay(bounds.x + bounds.width / 2, bounds.y + bounds.height / 2)));
934+
assertEquals(firstItem, found);
935+
936+
// point outside any tab should return null
937+
CTabItem notFound = ctabFolder.getItem(
938+
ctabFolder.toControl(ctabFolder.toDisplay(bounds.x, ctabFolder.getBounds().height + 100)));
939+
assertNull(notFound);
940+
}
941+
731942
}

0 commit comments

Comments
 (0)