|
56 | 56 | import org.eclipse.swtbot.swt.finder.widgets.SWTBotToolbarPushButton; |
57 | 57 | import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree; |
58 | 58 | import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem; |
| 59 | +import org.eclipse.ui.IViewPart; |
59 | 60 | import org.eclipse.ui.IWorkbench; |
60 | 61 | import org.eclipse.ui.IWorkbenchWindow; |
61 | 62 | import org.eclipse.ui.PlatformUI; |
@@ -968,24 +969,54 @@ public static void checkRunCleanProjectCheckBox(Shell shell, String runDebugConf |
968 | 969 |
|
969 | 970 | public static Object getAppInPackageExplorerTree(String appName) { |
970 | 971 | openJavaPerspectiveViaMenu(); |
971 | | - // Open Package Explorer view using Eclipse API instead of menu navigation |
972 | | - // This is more reliable in headless CI environments |
| 972 | + // Open Package Explorer view using Eclipse API instead of menu navigation. |
| 973 | + // This is more reliable in headless CI environments. |
973 | 974 | showPackageExplorerView(); |
974 | | - Object peView = MagicWidgetFinder.findGlobal("Package Explorer"); |
| 975 | + |
| 976 | + // Obtain the Package Explorer IViewPart directly from the Eclipse API rather |
| 977 | + // than using findGlobal(), which scans all visible shells and could match a |
| 978 | + // widget in an unrelated view. MagicWidgetFinder already knows how to traverse |
| 979 | + // a CommonNavigator (the PE's base class) to reach its TreeItems, so passing |
| 980 | + // the IViewPart as the neighbour is both correct and race-condition-free. |
| 981 | + IViewPart peView = getPackageExplorerView(); |
975 | 982 |
|
976 | 983 | Object project = MagicWidgetFinder.find(appName, peView, Option.factory().useContains(true).widgetClass(TreeItem.class).build()); |
977 | | - go(project); |
978 | 984 |
|
979 | | - // Wait until the tree item is enabled before returning. |
| 985 | + // Select and focus the item so the Package Explorer's selection provider is |
| 986 | + // active before the caller opens a context menu. Calling go() here is omitted |
| 987 | + // intentionally: the intermediate click it triggers can fire selection-listener |
| 988 | + // events that steal focus away before the caller reaches context(). |
980 | 989 | SWTBotTreeItem botItem = new SWTBotTreeItem((TreeItem) project); |
981 | 990 | SWTBotTestCondition.waitFor(botItem::isEnabled, SWTBotTestCondition.SHORT_WAIT_MS); |
982 | 991 | botItem.select(); |
983 | 992 | botItem.setFocus(); |
984 | | - System.out.println("Explorer item selected: " + botItem.contextMenu().menuItems()); |
985 | 993 |
|
| 994 | + System.out.println("Project in context explorer context menu: " + botItem.contextMenu().menuItems()); |
986 | 995 | return project; |
987 | 996 | } |
988 | 997 |
|
| 998 | + /** |
| 999 | + * Returns the Package Explorer IViewPart obtained directly from the Eclipse API. |
| 1000 | + * Must be called after showPackageExplorerView() has confirmed the view is present. |
| 1001 | + * |
| 1002 | + * @return The Package Explorer IViewPart, or {@code null} if unavailable. |
| 1003 | + */ |
| 1004 | + private static IViewPart getPackageExplorerView() { |
| 1005 | + final IViewPart[] result = { null }; |
| 1006 | + Display.getDefault().syncExec(() -> { |
| 1007 | + try { |
| 1008 | + IWorkbench wb = PlatformUI.getWorkbench(); |
| 1009 | + IWorkbenchWindow window = wb.getActiveWorkbenchWindow(); |
| 1010 | + if (window != null && window.getActivePage() != null) { |
| 1011 | + result[0] = window.getActivePage().findView("org.eclipse.jdt.ui.PackageExplorer"); |
| 1012 | + } |
| 1013 | + } catch (Exception e) { |
| 1014 | + System.err.println("Failed to retrieve Package Explorer view: " + e.getMessage()); |
| 1015 | + } |
| 1016 | + }); |
| 1017 | + return result[0]; |
| 1018 | + } |
| 1019 | + |
989 | 1020 | /** |
990 | 1021 | * Launches the start action using the debug as configuration shortcut. |
991 | 1022 | * |
@@ -1332,6 +1363,26 @@ public static void openSourceTab(Shell shell) { |
1332 | 1363 | SWTBot shellBot = botShell.bot(); |
1333 | 1364 | SWTBotCTabItem tabItem = shellBot.cTabItem("Source"); |
1334 | 1365 | tabItem.activate().setFocus(); |
| 1366 | + |
| 1367 | + // Wait until the Source tab's "Default" source-lookup tree item exists and has been |
| 1368 | + // populated with at least one child entry. |
| 1369 | + SWTBotTestCondition.waitFor(() -> { |
| 1370 | + try { |
| 1371 | + Object defaultItem = find("Default", shell); |
| 1372 | + if (defaultItem == null) { |
| 1373 | + return false; |
| 1374 | + } |
| 1375 | + SWTBotTreeItem item = new SWTBotTreeItem((TreeItem) defaultItem); |
| 1376 | + if (!item.isEnabled()) { |
| 1377 | + return false; |
| 1378 | + } |
| 1379 | + |
| 1380 | + item.expand(); |
| 1381 | + return item.getItems().length != 0; |
| 1382 | + } catch (Exception e) { |
| 1383 | + return false; |
| 1384 | + } |
| 1385 | + }, SWTBotTestCondition.SHORT_WAIT_MS); |
1335 | 1386 | } |
1336 | 1387 |
|
1337 | 1388 | /** |
|
0 commit comments