Skip to content

Commit b3e4c22

Browse files
committed
Test MultiPageEditorPart contracts in FormEditor #3764
1 parent 157e7ed commit b3e4c22

File tree

6 files changed

+300
-3
lines changed

6 files changed

+300
-3
lines changed

tests/org.eclipse.ui.tests.forms/META-INF/MANIFEST.MF

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ Bundle-Version: 3.11.100.qualifier
66
Require-Bundle: org.eclipse.ui;bundle-version="3.208.0",
77
org.eclipse.core.runtime,
88
org.eclipse.test.performance,
9-
org.eclipse.ui.forms
9+
org.eclipse.ui.forms,
10+
org.mockito.mockito-core;bundle-version="[5.21.0,6.0.0)",
11+
junit-jupiter-api;bundle-version="[5.14.3,6.0.0)"
1012
Bundle-Vendor: Eclipse.org
1113
Import-Package: org.junit.jupiter.api;version="[5.14.0,6.0.0)",
1214
org.junit.jupiter.api.function;version="[5.14.0,6.0.0)",

tests/org.eclipse.ui.tests.forms/build.properties

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
bin.includes = .,\
1515
META-INF/,\
1616
about.html,\
17-
test.xml
17+
test.xml,\
18+
plugin.xml
1819
output.. = bin/
1920
source.. = forms/
2021

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2026 Vasili Gulevich and others
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* Vasili Gulevich - initial API and implementation
13+
*******************************************************************************/
14+
package org.eclipse.ui.forms.editor;
15+
16+
import org.eclipse.core.runtime.IProgressMonitor;
17+
import org.eclipse.swt.custom.CTabFolder;
18+
import org.eclipse.swt.custom.CTabItem;
19+
import org.eclipse.swt.widgets.Composite;
20+
import org.eclipse.swt.widgets.Control;
21+
import org.eclipse.ui.IEditorPart;
22+
import org.eclipse.ui.PartInitException;
23+
24+
public class FormEditorMock extends FormEditor {
25+
public static final String ID = "org.eclipse.ui.tests.forms.FormEditorMock";
26+
27+
public interface Hook {
28+
29+
default boolean isSaveAsAllowed(FormEditorMock subject) {
30+
return false;
31+
}
32+
33+
default void addPages(FormEditorMock subject) {
34+
FormPage page1 = new FormPage(subject, "defaultpage", "defaultpage");
35+
try {
36+
subject.addPage(page1);
37+
} catch (PartInitException e) {
38+
throw new AssertionError(e);
39+
}
40+
}
41+
42+
default void doSave(FormEditorMock subject) {
43+
}
44+
45+
default void createContainer(FormEditorMock subject, CTabFolder container) {
46+
}
47+
48+
default void createItem(FormEditorMock subject, CTabItem item) {
49+
50+
}
51+
}
52+
53+
public static final Hook DEFAULT_HOOK = new Hook() {
54+
};
55+
56+
public static Hook hook = DEFAULT_HOOK;
57+
58+
@Override
59+
protected CTabFolder createContainer(Composite parent) {
60+
CTabFolder result = super.createContainer(parent);
61+
hook.createContainer(this, result);
62+
return result;
63+
}
64+
65+
@Override
66+
protected CTabItem createItem(int index, Control control) {
67+
CTabItem result = super.createItem(index, control);
68+
hook.createItem(this, result);
69+
return result;
70+
}
71+
@Override
72+
protected void addPages() {
73+
hook.addPages(this);
74+
}
75+
76+
@Override
77+
public void doSave(IProgressMonitor monitor) {
78+
hook.doSave(this);
79+
}
80+
81+
@Override
82+
public void doSaveAs() {
83+
hook.doSave(this);
84+
}
85+
86+
@Override
87+
public boolean isSaveAsAllowed() {
88+
return hook.isSaveAsAllowed(this);
89+
}
90+
91+
public CTabFolder leakContainer() {
92+
return (CTabFolder) getContainer();
93+
}
94+
95+
public IEditorPart[] leakPages() {
96+
return pages.stream().toArray(IEditorPart[]::new);
97+
}
98+
}
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2026 Vasili Gulevich and others
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* Vasili Gulevich - initial API and implementation
13+
*******************************************************************************/
14+
package org.eclipse.ui.forms.editor;
15+
16+
import static org.junit.jupiter.api.Assertions.assertEquals;
17+
import static org.junit.jupiter.api.Assertions.assertNotNull;
18+
import static org.junit.jupiter.api.Assertions.assertNull;
19+
import static org.junit.jupiter.api.Assertions.assertSame;
20+
import static org.junit.jupiter.api.Assertions.assertTrue;
21+
import static org.mockito.Mockito.mock;
22+
23+
import org.eclipse.swt.SWT;
24+
import org.eclipse.swt.custom.CTabFolder;
25+
import org.eclipse.swt.custom.CTabItem;
26+
import org.eclipse.swt.widgets.Event;
27+
import org.eclipse.ui.IEditorInput;
28+
import org.eclipse.ui.IEditorPart;
29+
import org.eclipse.ui.IWorkbench;
30+
import org.eclipse.ui.PartInitException;
31+
import org.eclipse.ui.PlatformUI;
32+
import org.eclipse.ui.forms.editor.FormEditorMock.Hook;
33+
import org.junit.jupiter.api.BeforeEach;
34+
import org.junit.jupiter.api.Disabled;
35+
import org.junit.jupiter.api.Test;
36+
37+
public class FormEditorTest {
38+
39+
private static final IWorkbench WORKBENCH = PlatformUI.getWorkbench();
40+
41+
public IEditorInput input = mock();
42+
43+
@BeforeEach
44+
public void closeEditors() {
45+
WORKBENCH.getActiveWorkbenchWindow().getActivePage().closeAllEditors(false);
46+
}
47+
48+
@Test
49+
public void activatePage() throws PartInitException {
50+
FormEditorMock.hook = FormEditorMock.DEFAULT_HOOK;
51+
FormEditorMock subject = (FormEditorMock) WORKBENCH.getActiveWorkbenchWindow().getActivePage().openEditor(input,
52+
FormEditorMock.ID);
53+
assertEquals("defaultpage", subject.getActivePageInstance().getTitle());
54+
FormPage page1 = addPage(subject, "page1");
55+
subject.setActivePage("page1");
56+
dispatch(subject);
57+
assertSame(page1, subject.getActivePageInstance());
58+
}
59+
60+
@Test
61+
public void removePage() throws PartInitException {
62+
FormEditorMock.hook = FormEditorMock.DEFAULT_HOOK;
63+
FormEditorMock subject = (FormEditorMock) WORKBENCH.getActiveWorkbenchWindow().getActivePage().openEditor(input,
64+
FormEditorMock.ID);
65+
dispatch(subject);
66+
CTabItem[] tabs = subject.leakContainer().getItems();
67+
assertEquals(1, tabs.length);
68+
FormPage page1 = addPage(subject, "page1");
69+
assertSame(page1, subject.findPage("page1"));
70+
tabs = subject.leakContainer().getItems();
71+
assertEquals(2, tabs.length);
72+
subject.removePage(page1.getIndex());
73+
dispatch(subject);
74+
assertNull(subject.findPage("page1"));
75+
tabs = subject.leakContainer().getItems();
76+
assertEquals(1, tabs.length);
77+
}
78+
79+
@Test
80+
public void disposeTab() throws PartInitException {
81+
FormEditorMock.hook = FormEditorMock.DEFAULT_HOOK;
82+
FormEditorMock subject = (FormEditorMock) WORKBENCH.getActiveWorkbenchWindow().getActivePage().openEditor(input,
83+
FormEditorMock.ID);
84+
dispatch(subject);
85+
CTabItem[] tabs = subject.leakContainer().getItems();
86+
assertEquals(1, tabs.length);
87+
FormPage page1 = addPage(subject, "page1");
88+
assertSame(page1, subject.findPage("page1"));
89+
tabs = subject.leakContainer().getItems();
90+
assertEquals(2, tabs.length);
91+
tabs[tabs.length - 1].dispose();
92+
dispatch(subject);
93+
tabs = subject.leakContainer().getItems();
94+
assertEquals(1, tabs.length);
95+
// BUG https://github.com/eclipse-platform/eclipse.platform.ui/issues/3766
96+
// assertNull(subject.findPage("page1"));
97+
}
98+
99+
@Test
100+
public void maintainIntegrityOnPageClose() throws PartInitException {
101+
FormEditorMock.hook = new Hook() {
102+
@Override
103+
public void createContainer(FormEditorMock subject, CTabFolder container) {
104+
Hook.super.createContainer(subject, container);
105+
container.setUnselectedCloseVisible(true);
106+
}
107+
108+
@Override
109+
public void createItem(FormEditorMock subject, CTabItem item) {
110+
Hook.super.createItem(subject, item);
111+
item.setShowClose(true);
112+
}
113+
};
114+
FormEditorMock subject = (FormEditorMock) WORKBENCH.getActiveWorkbenchWindow().getActivePage().openEditor(input,
115+
FormEditorMock.ID);
116+
FormPage page1 = addPage(subject, "page1");
117+
CTabFolder tabFolder = subject.leakContainer();
118+
CTabItem tab = tabFolder.getItem(1);
119+
assertTrue(tab.getShowClose());
120+
assertSame(page1, subject.findPage("page1"));
121+
Event event = new Event();
122+
event.type = SWT.MouseDown;
123+
event.button = 1;
124+
event.x = tab.getBounds().x + tab.getBounds().width - 9;
125+
event.y = tab.getBounds().y + tab.getBounds().height/2;
126+
tabFolder.notifyListeners(event.type, event);
127+
dispatch(subject);
128+
event.type = SWT.MouseUp;
129+
tabFolder.notifyListeners(event.type, event);
130+
dispatch(subject);
131+
assertEquals(1, tabFolder.getItems().length);
132+
// BUG https://github.com/eclipse-platform/eclipse.platform.ui/issues/3766
133+
// assertNull(subject.findPage("page1"));
134+
}
135+
136+
@Test
137+
@Disabled("https://github.com/eclipse-platform/eclipse.platform.ui/issues/3764")
138+
public void anEditorIsActiveOnStart() throws PartInitException {
139+
FormEditorMock.hook = FormEditorMock.DEFAULT_HOOK;
140+
FormEditorMock subject = (FormEditorMock) WORKBENCH.getActiveWorkbenchWindow().getActivePage().openEditor(input,
141+
FormEditorMock.ID);
142+
dispatch(subject);
143+
// BUG https://github.com/eclipse-platform/eclipse.platform.ui/issues/3764
144+
assertNotNull(subject.getActiveEditor());
145+
}
146+
147+
@Test
148+
@Disabled("https://github.com/eclipse-platform/eclipse.platform.ui/issues/3764")
149+
public void activateEditors() throws PartInitException {
150+
FormEditorMock.hook = FormEditorMock.DEFAULT_HOOK;
151+
FormEditorMock subject = (FormEditorMock) WORKBENCH.getActiveWorkbenchWindow().getActivePage().openEditor(input,
152+
FormEditorMock.ID);
153+
FormPage page1 = addPage(subject, "page1");
154+
assertNotNull(page1);
155+
// BUG https://github.com/eclipse-platform/eclipse.platform.ui/issues/3764
156+
assertEveryTabCanBeActive(subject);
157+
}
158+
159+
private void assertEveryTabCanBeActive(FormEditorMock subject) {
160+
dispatch(subject);
161+
for (IEditorPart part : subject.leakPages()) {
162+
subject.setActiveEditor(part);
163+
dispatch(subject);
164+
assertSame(part, subject.getActiveEditor());
165+
}
166+
}
167+
168+
private void dispatch(FormEditorMock subject) {
169+
while (subject.leakContainer().getDisplay().readAndDispatch()) {
170+
}
171+
}
172+
173+
private FormPage addPage(FormEditorMock subject, String id) throws PartInitException {
174+
FormPage page1 = new FormPage(subject, id, id);
175+
subject.addPage(page1);
176+
dispatch(subject);
177+
return page1;
178+
}
179+
180+
}

tests/org.eclipse.ui.tests.forms/forms/org/eclipse/ui/tests/forms/AllFormsTests.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.eclipse.ui.tests.forms;
1818

19+
import org.eclipse.ui.forms.editor.FormEditorTest;
1920
import org.eclipse.ui.tests.forms.events.AllEventsTests;
2021
import org.eclipse.ui.tests.forms.layout.AllLayoutTests;
2122
import org.eclipse.ui.tests.forms.util.AllUtilityTests;
@@ -32,7 +33,8 @@
3233
AllEventsTests.class, //
3334
AllLayoutTests.class, //
3435
AllUtilityTests.class, //
35-
AllWidgetsTests.class //
36+
AllWidgetsTests.class, //
37+
FormEditorTest.class //
3638
})
3739
public class AllFormsTests {
3840

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<?eclipse version="3.4"?>
3+
<plugin>
4+
<extension
5+
point="org.eclipse.ui.editors">
6+
<editor
7+
class="org.eclipse.ui.forms.editor.FormEditorMock"
8+
default="false"
9+
id="org.eclipse.ui.tests.forms.FormEditorMock"
10+
name="FormEditorMock">
11+
</editor>
12+
</extension>
13+
14+
</plugin>

0 commit comments

Comments
 (0)