Index: /trunk/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetMenu.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetMenu.java	(revision 18682)
+++ /trunk/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetMenu.java	(revision 18683)
@@ -11,4 +11,5 @@
 import java.io.Serializable;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Comparator;
 import java.util.List;
@@ -21,6 +22,8 @@
 import javax.swing.JSeparator;
 
+import org.openstreetmap.josm.actions.JosmAction;
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.MainFrame;
+import org.openstreetmap.josm.gui.MainMenu;
 import org.openstreetmap.josm.tools.AlphanumComparator;
 import org.openstreetmap.josm.tools.Logging;
@@ -38,10 +41,14 @@
         @Override
         public int compare(JMenuItem o1, JMenuItem o2) {
-            if (MainApplication.getMenu().presetSearchAction.equals(o1.getAction()))
-                return -1;
-            else if (MainApplication.getMenu().presetSearchAction.equals(o2.getAction()))
-                return 1;
-            else
-                return AlphanumComparator.getInstance().compare(o1.getText(), o2.getText());
+            final MainMenu menu = MainApplication.getMenu();
+            // This is needed to keep the order of the search actions -> preferences
+            for (JosmAction action : Arrays.asList(menu.presetSearchAction, menu.presetSearchPrimitiveAction)) {
+                if (action.equals(o1.getAction())) {
+                    return -1;
+                } else if (action.equals(o2.getAction())) {
+                    return 1;
+                }
+            }
+            return AlphanumComparator.getInstance().compare(o1.getText(), o2.getText());
         }
     }
Index: /trunk/test/unit/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetsTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetsTest.java	(revision 18682)
+++ /trunk/test/unit/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetsTest.java	(revision 18683)
@@ -1,4 +1,8 @@
 // License: GPL. For details, see LICENSE file.
 package org.openstreetmap.josm.gui.tagging.presets;
+
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.util.Collection;
@@ -8,11 +12,18 @@
 import java.util.concurrent.TimeoutException;
 
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.RegisterExtension;
-import org.openstreetmap.josm.testutils.JOSMTestRules;
-import org.openstreetmap.josm.tools.Logging;
+import javax.swing.JMenu;
+import javax.swing.JSeparator;
 
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import net.trajano.commons.testing.UtilityClassTestUtil;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.openstreetmap.josm.actions.PreferencesAction;
+import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.gui.MainMenu;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+import org.openstreetmap.josm.tools.Logging;
 
 /**
@@ -26,5 +37,5 @@
     @RegisterExtension
     @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
-    public JOSMTestRules test = new JOSMTestRules();
+    public JOSMTestRules test = new JOSMTestRules().main();
 
     /**
@@ -35,4 +46,22 @@
     void testUtilityClass() throws ReflectiveOperationException {
         UtilityClassTestUtil.assertUtilityClassWellDefined(TaggingPresets.class);
+    }
+
+    /**
+     * Ensure that sorting the menu does <em>not</em> change the order of the first 3 actions.
+     * See {@link TaggingPresetMenu.PresetTextComparator} for the comparator to fix if this test
+     * fails <i>after</i> adding a new menu item.
+     */
+    @ParameterizedTest
+    @ValueSource(booleans = {true, false})
+    void testNonRegression22783(boolean sort) {
+        final MainMenu menu = MainApplication.getMenu();
+        TaggingPresets.SORT_MENU.put(sort);
+        TaggingPresets.initialize();
+        final JMenu presetsMenu = menu.presetsMenu;
+        assertAll(() -> assertSame(menu.presetSearchAction, presetsMenu.getItem(0).getAction()),
+                () -> assertSame(menu.presetSearchPrimitiveAction, presetsMenu.getItem(1).getAction()),
+                () -> assertTrue(presetsMenu.getItem(2).getAction() instanceof PreferencesAction),
+                () -> assertTrue(presetsMenu.getMenuComponent(3) instanceof JSeparator));
     }
 
