Skip to content

Commit 62402e8

Browse files
committed
Test MultiPageEditorPart contracts in FormEditor #3764
1 parent b819cf9 commit 62402e8

File tree

6 files changed

+295
-3
lines changed

6 files changed

+295
-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: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
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.assertNull;
18+
import static org.junit.jupiter.api.Assertions.assertSame;
19+
import static org.junit.jupiter.api.Assertions.assertTrue;
20+
import static org.mockito.Mockito.mock;
21+
22+
import org.eclipse.swt.SWT;
23+
import org.eclipse.swt.custom.CTabFolder;
24+
import org.eclipse.swt.custom.CTabItem;
25+
import org.eclipse.swt.widgets.Event;
26+
import org.eclipse.ui.IEditorInput;
27+
import org.eclipse.ui.IEditorPart;
28+
import org.eclipse.ui.IWorkbench;
29+
import org.eclipse.ui.PartInitException;
30+
import org.eclipse.ui.PlatformUI;
31+
import org.eclipse.ui.forms.editor.FormEditorMock.Hook;
32+
import org.junit.jupiter.api.BeforeEach;
33+
import org.junit.jupiter.api.Test;
34+
35+
public class FormEditorTest {
36+
37+
private static final IWorkbench WORKBENCH = PlatformUI.getWorkbench();
38+
39+
public IEditorInput input = mock();
40+
41+
@BeforeEach
42+
public void closeEditors() {
43+
WORKBENCH.getActiveWorkbenchWindow().getActivePage().closeAllEditors(false);
44+
}
45+
46+
@Test
47+
public void activatePage() throws PartInitException {
48+
FormEditorMock.hook = FormEditorMock.DEFAULT_HOOK;
49+
FormEditorMock subject = (FormEditorMock) WORKBENCH.getActiveWorkbenchWindow().getActivePage().openEditor(input,
50+
FormEditorMock.ID);
51+
assertEquals("defaultpage", subject.getActivePageInstance().getTitle());
52+
FormPage page1 = addPage(subject, "page1");
53+
subject.setActivePage("page1");
54+
dispatch(subject);
55+
assertSame(page1, subject.getActivePageInstance());
56+
}
57+
58+
@Test
59+
public void removePage() throws PartInitException {
60+
FormEditorMock.hook = FormEditorMock.DEFAULT_HOOK;
61+
FormEditorMock subject = (FormEditorMock) WORKBENCH.getActiveWorkbenchWindow().getActivePage().openEditor(input,
62+
FormEditorMock.ID);
63+
dispatch(subject);
64+
CTabItem[] tabs = subject.leakContainer().getItems();
65+
assertEquals(1, tabs.length);
66+
FormPage page1 = addPage(subject, "page1");
67+
assertSame(page1, subject.findPage("page1"));
68+
tabs = subject.leakContainer().getItems();
69+
assertEquals(2, tabs.length);
70+
subject.removePage(page1.getIndex());
71+
dispatch(subject);
72+
assertNull(subject.findPage("page1"));
73+
tabs = subject.leakContainer().getItems();
74+
assertEquals(1, tabs.length);
75+
}
76+
77+
@Test
78+
public void disposeTab() throws PartInitException {
79+
FormEditorMock.hook = FormEditorMock.DEFAULT_HOOK;
80+
FormEditorMock subject = (FormEditorMock) WORKBENCH.getActiveWorkbenchWindow().getActivePage().openEditor(input,
81+
FormEditorMock.ID);
82+
dispatch(subject);
83+
CTabItem[] tabs = subject.leakContainer().getItems();
84+
assertEquals(1, tabs.length);
85+
FormPage page1 = addPage(subject, "page1");
86+
assertSame(page1, subject.findPage("page1"));
87+
tabs = subject.leakContainer().getItems();
88+
assertEquals(2, tabs.length);
89+
tabs[tabs.length - 1].dispose();
90+
dispatch(subject);
91+
tabs = subject.leakContainer().getItems();
92+
assertEquals(1, tabs.length);
93+
// BUG https://github.com/eclipse-platform/eclipse.platform.ui/issues/3766
94+
// assertNull(subject.findPage("page1"));
95+
}
96+
97+
@Test
98+
public void maintainIntegrityOnPageClose() throws PartInitException {
99+
FormEditorMock.hook = new Hook() {
100+
@Override
101+
public void createContainer(FormEditorMock subject, CTabFolder container) {
102+
Hook.super.createContainer(subject, container);
103+
container.setUnselectedCloseVisible(true);
104+
}
105+
106+
@Override
107+
public void createItem(FormEditorMock subject, CTabItem item) {
108+
Hook.super.createItem(subject, item);
109+
item.setShowClose(true);
110+
}
111+
};
112+
FormEditorMock subject = (FormEditorMock) WORKBENCH.getActiveWorkbenchWindow().getActivePage().openEditor(input,
113+
FormEditorMock.ID);
114+
FormPage page1 = addPage(subject, "page1");
115+
CTabFolder tabFolder = subject.leakContainer();
116+
CTabItem tab = tabFolder.getItem(1);
117+
assertTrue(tab.getShowClose());
118+
assertSame(page1, subject.findPage("page1"));
119+
Event event = new Event();
120+
event.type = SWT.MouseDown;
121+
event.button = 1;
122+
event.x = tab.getBounds().x + tab.getBounds().width - 9;
123+
event.y = tab.getBounds().y + tab.getBounds().height/2;
124+
tabFolder.notifyListeners(event.type, event);
125+
dispatch(subject);
126+
event.type = SWT.MouseUp;
127+
tabFolder.notifyListeners(event.type, event);
128+
dispatch(subject);
129+
assertEquals(1, tabFolder.getItems().length);
130+
// BUG https://github.com/eclipse-platform/eclipse.platform.ui/issues/3766
131+
// assertNull(subject.findPage("page1"));
132+
}
133+
134+
@Test
135+
public void anEditorIsActiveOnStart() throws PartInitException {
136+
FormEditorMock.hook = FormEditorMock.DEFAULT_HOOK;
137+
FormEditorMock subject = (FormEditorMock) WORKBENCH.getActiveWorkbenchWindow().getActivePage().openEditor(input,
138+
FormEditorMock.ID);
139+
dispatch(subject);
140+
// BUG https://github.com/eclipse-platform/eclipse.platform.ui/issues/3764
141+
// assertNotNull(subject.getActiveEditor());
142+
}
143+
144+
@Test
145+
public void activateEditors() throws PartInitException {
146+
FormEditorMock.hook = FormEditorMock.DEFAULT_HOOK;
147+
FormEditorMock subject = (FormEditorMock) WORKBENCH.getActiveWorkbenchWindow().getActivePage().openEditor(input,
148+
FormEditorMock.ID);
149+
FormPage page1 = addPage(subject, "page1");
150+
// BUG https://github.com/eclipse-platform/eclipse.platform.ui/issues/3764
151+
// assertEveryTabCanBeActive(subject);
152+
}
153+
154+
private void assertEveryTabCanBeActive(FormEditorMock subject) {
155+
dispatch(subject);
156+
for (IEditorPart part : subject.leakPages()) {
157+
subject.setActiveEditor(part);
158+
dispatch(subject);
159+
assertSame(part, subject.getActiveEditor());
160+
}
161+
}
162+
163+
private void dispatch(FormEditorMock subject) {
164+
while (subject.leakContainer().getDisplay().readAndDispatch()) {
165+
}
166+
}
167+
168+
private FormPage addPage(FormEditorMock subject, String id) throws PartInitException {
169+
FormPage page1 = new FormPage(subject, id, id);
170+
subject.addPage(page1);
171+
dispatch(subject);
172+
return page1;
173+
}
174+
175+
}

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)