Index: /trunk/src/org/openstreetmap/josm/data/validation/OsmValidator.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/validation/OsmValidator.java	(revision 18648)
+++ /trunk/src/org/openstreetmap/josm/data/validation/OsmValidator.java	(revision 18649)
@@ -467,5 +467,5 @@
                 if (tr("Ignore list").equals(description))
                     description = "";
-                if (!key.matches("^[0-9]+(_.*|$)")) {
+                if (!key.matches("^-?[0-9]+(_.*|$)")) {
                     description = key;
                     key = "";
@@ -480,5 +480,5 @@
                     // single element
                     entry = key + ":" + item;
-                } else if (item.matches("^[0-9]+(_.*|)$")) {
+                } else if (item.matches("^-?[0-9]+(_.*|)$")) {
                     // no element ids
                     entry = item;
Index: /trunk/test/data/META-INF/services/org.junit.jupiter.api.extension.Extension
===================================================================
--- /trunk/test/data/META-INF/services/org.junit.jupiter.api.extension.Extension	(revision 18649)
+++ /trunk/test/data/META-INF/services/org.junit.jupiter.api.extension.Extension	(revision 18649)
@@ -0,0 +1,1 @@
+org.openstreetmap.josm.testutils.annotations.LayerManager$LayerManagerExtension
Index: /trunk/test/unit/org/openstreetmap/josm/data/validation/TestErrorTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/data/validation/TestErrorTest.java	(revision 18648)
+++ /trunk/test/unit/org/openstreetmap/josm/data/validation/TestErrorTest.java	(revision 18649)
@@ -18,8 +18,15 @@
 import org.junit.jupiter.params.provider.MethodSource;
 import org.openstreetmap.josm.TestUtils;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.validation.tests.InternetTags;
+import org.openstreetmap.josm.data.validation.tests.UnconnectedWays;
+import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
 import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
+import org.openstreetmap.josm.testutils.annotations.Projection;
 
 /**
@@ -27,8 +34,15 @@
  */
 @BasicPreferences
+@Projection
 class TestErrorTest {
     static Stream<Arguments> testCodeCompatibility() {
         return Stream.of(Arguments.of(InternetTags.class, 3301, 1166507262, false, Collections.singletonList(TestUtils.newNode("url=invalid"))),
-                Arguments.of(InternetTags.class, 3301, 1166507262, true, Collections.singletonList(TestUtils.newNode("url=invalid"))));
+                Arguments.of(InternetTags.class, 3301, 1166507262, true, Collections.singletonList(TestUtils.newNode("url=invalid"))),
+                Arguments.of(UnconnectedWays.UnconnectedHighways.class, 1311, -1765317246, true,
+                        Arrays.asList(TestUtils.newWay("highway=residential", new Node(LatLon.ZERO), new Node(LatLon.NORTH_POLE)),
+                                TestUtils.newWay("highway=residential", new Node(LatLon.ZERO), new Node(LatLon.SOUTH_POLE)))),
+        Arguments.of(UnconnectedWays.UnconnectedHighways.class, 1311, -1765317246, false,
+                Arrays.asList(TestUtils.newWay("highway=residential", new Node(LatLon.ZERO), new Node(LatLon.NORTH_POLE)),
+                        TestUtils.newWay("highway=residential", new Node(LatLon.ZERO), new Node(LatLon.SOUTH_POLE)))));
     }
 
@@ -47,4 +61,14 @@
     void testCodeCompatibility(Class<? extends Test> testClass, int originalCode, int expectedCode,
                                boolean switchOver, List<OsmPrimitive> primitiveCollection) throws ReflectiveOperationException {
+        // Create the data layer and add it to the layer manager -- needed if the test looks for an active dataset
+        final DataSet ds = new DataSet();
+        primitiveCollection.forEach(ds::addPrimitiveRecursive);
+        for (OsmPrimitive primitive : ds.allPrimitives()) {
+            if (primitive.isNew()) {
+                primitive.setOsmId(-primitive.getUniqueId(), 1);
+            }
+        }
+        final OsmDataLayer layer = new OsmDataLayer(ds, "testCodeCompatibility", null);
+        MainApplication.getLayerManager().addLayer(layer);
         // Ensure that this test always works
         TestError.setUpdateErrorCodes(switchOver);
@@ -56,5 +80,13 @@
         test.endTest();
         assertFalse(test.getErrors().isEmpty());
-        assertEquals(1, test.getErrors().size());
+        final int expectedIssues;
+        if (InternetTags.class.equals(testClass)) {
+            expectedIssues = 1;
+        } else if (UnconnectedWays.UnconnectedHighways.class.equals(testClass)) {
+            expectedIssues = 2;
+        } else {
+            expectedIssues = Integer.MIN_VALUE;
+        }
+        assertEquals(expectedIssues, test.getErrors().size());
         final TestError testError = test.getErrors().get(0);
         final String ignoreGroup = testError.getIgnoreGroup();
@@ -80,4 +112,5 @@
             OsmValidator.clearIgnoredErrors();
             OsmValidator.addIgnoredError(ignore);
+            OsmValidator.saveIgnoredErrors();
             // Add the ignored error
             assertTrue(testError.updateIgnored());
Index: /trunk/test/unit/org/openstreetmap/josm/testutils/annotations/LayerManager.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/testutils/annotations/LayerManager.java	(revision 18649)
+++ /trunk/test/unit/org/openstreetmap/josm/testutils/annotations/LayerManager.java	(revision 18649)
@@ -0,0 +1,38 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.testutils.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.junit.jupiter.api.extension.AfterEachCallback;
+import org.junit.jupiter.api.extension.BeforeEachCallback;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+
+/**
+ * Clear the main {@link org.openstreetmap.josm.gui.layer.LayerManager} between tests.
+ * <br />
+ * You shouldn't have to register this -- it should be run automatically by the JUnit 5 test environment.
+ * See <a href="https://junit.org/junit5/docs/current/user-guide/#extensions-registration-automatic">
+ *     Automatic Extension Registration
+ * </a> for more information.
+ */
+@Target({ElementType.TYPE, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@ExtendWith(LayerManager.LayerManagerExtension.class)
+public @interface LayerManager {
+    class LayerManagerExtension implements BeforeEachCallback, AfterEachCallback {
+        @Override
+        public void afterEach(ExtensionContext context) {
+            JOSMTestRules.cleanLayerEnvironment();
+        }
+
+        @Override
+        public void beforeEach(ExtensionContext context) {
+            this.afterEach(context);
+        }
+    }
+}
Index: /trunk/test/unit/org/openstreetmap/josm/testutils/annotations/Projection.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/testutils/annotations/Projection.java	(revision 18649)
+++ /trunk/test/unit/org/openstreetmap/josm/testutils/annotations/Projection.java	(revision 18649)
@@ -0,0 +1,71 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.testutils.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.Optional;
+
+import org.junit.jupiter.api.extension.AfterAllCallback;
+import org.junit.jupiter.api.extension.BeforeAllCallback;
+import org.junit.jupiter.api.extension.BeforeEachCallback;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.platform.commons.support.AnnotationSupport;
+import org.openstreetmap.josm.data.projection.ProjectionRegistry;
+import org.openstreetmap.josm.data.projection.Projections;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+
+/**
+ * Use projections in tests (Mercator).
+ *
+ * @author Taylor Smock
+ * @see JOSMTestRules#projection()
+ *
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.METHOD, ElementType.TYPE })
+@ExtendWith(Projection.ProjectionExtension.class)
+public @interface Projection {
+    /**
+     * The value to use for the projection. Defaults to EPSG:3857 (Mercator).
+     *
+     * @return The value to use to get the projection from
+     *         {@link Projections#getProjectionByCode}.
+     */
+    String projectionCode() default "EPSG:3857";
+
+    /**
+     * Use projections in tests.
+     *
+     * @author Taylor Smock
+     *
+     */
+    class ProjectionExtension implements BeforeEachCallback, BeforeAllCallback, AfterAllCallback {
+        @Override
+        public void afterAll(ExtensionContext context) throws Exception {
+            ProjectionRegistry.clearProjectionChangeListeners();
+            AnnotationUtils.resetStaticClass(ProjectionRegistry.class);
+        }
+
+        @Override
+        public void beforeAll(ExtensionContext context) throws Exception {
+            // Needed in order to run prior to @Territories
+            beforeEach(context);
+        }
+
+        @Override
+        public void beforeEach(ExtensionContext context) throws Exception {
+            Optional<Projection> annotation = AnnotationSupport.findAnnotation(context.getElement(), Projection.class);
+            if (annotation.isPresent()) {
+                ProjectionRegistry.setProjection(Projections.getProjectionByCode(annotation.get().projectionCode()));
+            } else {
+                ProjectionRegistry.setProjection(Projections.getProjectionByCode("EPSG:3857")); // Mercator
+            }
+        }
+
+    }
+}
