Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImageTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImageTest.java	(revision 36194)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImageTest.java	(revision 36228)
@@ -2,27 +2,124 @@
 package org.openstreetmap.josm.plugins.streetside;
 
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
+import java.text.MessageFormat;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
-import org.openstreetmap.josm.data.coor.LatLon;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.openstreetmap.josm.plugins.streetside.cubemap.CubemapUtils;
+import org.openstreetmap.josm.plugins.streetside.utils.TestUtil;
 
 class StreetsideAbstractImageTest {
+    private StreetsideImage image;
+    private String imageUrlBase;
+
+    @BeforeEach
+    void setup() {
+        this.image = TestUtil.generateImage("1013203010232123", 39.065321, -108.553035);
+        this.imageUrlBase = "https://ecn.t0.tiles.virtualearth.net/tiles/hs1013203010232123{0}?"
+                + "g=14336&key=Arzdiw4nlOJzRwOz__qailc8NiR31Tt51dN2D7cm57NrnceZnCpgOkmJhNpGoppU";
+    }
+
     @Test
-    void testIsModified() {
-        StreetsideImage img = new StreetsideImage("key___________________", new LatLon(0, 0), 0);
-        assertFalse(img.isModified());
-        img.turn(1e-4);
-        img.stopMoving();
-        assertTrue(img.isModified());
-        img.turn(-1e-4);
-        img.stopMoving();
-        assertFalse(img.isModified());
-        img.move(1e-4, 1e-4);
-        img.stopMoving();
-        assertTrue(img.isModified());
-        img.move(-1e-4, -1e-4);
-        img.stopMoving();
-        assertFalse(img.isModified());
+    void testThumbnail() {
+        assertEquals(MessageFormat.format(this.imageUrlBase, "01"), this.image.getThumbnail());
+    }
+
+    private static CubeMapTileXY frontCube(int x, int y) {
+        return new CubeMapTileXY(CubemapUtils.CubemapFaces.FRONT, x, y);
+    }
+
+    @Test
+    void testTilesZoom1() {
+        // 2x2 (4 total tiles)
+        final var z1 = image.getFaceTiles(CubemapUtils.CubemapFaces.FRONT, 1)
+                .collect(Collectors.toMap(p -> p.a, p -> p.b));
+        assertEquals(MessageFormat.format(this.imageUrlBase, "010"), z1.get(frontCube(0, 0)));
+        assertEquals(MessageFormat.format(this.imageUrlBase, "011"), z1.get(frontCube(1, 0)));
+        assertEquals(MessageFormat.format(this.imageUrlBase, "012"), z1.get(frontCube(0, 1)));
+        assertEquals(MessageFormat.format(this.imageUrlBase, "013"), z1.get(frontCube(1, 1)));
+        assertEquals(4, z1.size());
+    }
+
+    @Test
+    void testTilesZoom2() {
+        // 4x4 (16 total tiles)
+        final var z2 = image.getFaceTiles(CubemapUtils.CubemapFaces.FRONT, 2)
+                .collect(Collectors.toMap(p -> p.a, p -> p.b));
+        assertEquals(MessageFormat.format(this.imageUrlBase, "0100"), z2.get(frontCube(0, 0)));
+        assertEquals(MessageFormat.format(this.imageUrlBase, "0101"), z2.get(frontCube(1, 0)));
+        assertEquals(MessageFormat.format(this.imageUrlBase, "0102"), z2.get(frontCube(0, 1)));
+        assertEquals(MessageFormat.format(this.imageUrlBase, "0103"), z2.get(frontCube(1, 1)));
+        assertEquals(MessageFormat.format(this.imageUrlBase, "0110"), z2.get(frontCube(2, 0)));
+        assertEquals(MessageFormat.format(this.imageUrlBase, "0111"), z2.get(frontCube(3, 0)));
+        assertEquals(MessageFormat.format(this.imageUrlBase, "0112"), z2.get(frontCube(2, 1)));
+        assertEquals(MessageFormat.format(this.imageUrlBase, "0113"), z2.get(frontCube(3, 1)));
+        assertEquals(MessageFormat.format(this.imageUrlBase, "0120"), z2.get(frontCube(0, 2)));
+        assertEquals(MessageFormat.format(this.imageUrlBase, "0121"), z2.get(frontCube(1, 2)));
+        assertEquals(MessageFormat.format(this.imageUrlBase, "0122"), z2.get(frontCube(0, 3)));
+        assertEquals(MessageFormat.format(this.imageUrlBase, "0123"), z2.get(frontCube(1, 3)));
+        assertEquals(MessageFormat.format(this.imageUrlBase, "0130"), z2.get(frontCube(2, 2)));
+        assertEquals(MessageFormat.format(this.imageUrlBase, "0131"), z2.get(frontCube(3, 2)));
+        assertEquals(MessageFormat.format(this.imageUrlBase, "0132"), z2.get(frontCube(2, 3)));
+        assertEquals(MessageFormat.format(this.imageUrlBase, "0133"), z2.get(frontCube(3, 3)));
+        assertEquals(16, z2.size());
+    }
+
+    @Test
+    void testTilesZoom3() {
+        // 8x8 (64 total tiles)
+        final var z3 = image.getFaceTiles(CubemapUtils.CubemapFaces.FRONT, 3)
+                .collect(Collectors.toMap(p -> p.a, p -> p.b));
+        // Just check the first row to keep test size smallish
+        assertEquals(MessageFormat.format(this.imageUrlBase, "01000"), z3.get(frontCube(0, 0)));
+        assertEquals(MessageFormat.format(this.imageUrlBase, "01001"), z3.get(frontCube(1, 0)));
+        assertEquals(MessageFormat.format(this.imageUrlBase, "01010"), z3.get(frontCube(2, 0)));
+        assertEquals(MessageFormat.format(this.imageUrlBase, "01011"), z3.get(frontCube(3, 0)));
+        assertEquals(MessageFormat.format(this.imageUrlBase, "01100"), z3.get(frontCube(4, 0)));
+        assertEquals(MessageFormat.format(this.imageUrlBase, "01101"), z3.get(frontCube(5, 0)));
+        assertEquals(MessageFormat.format(this.imageUrlBase, "01110"), z3.get(frontCube(6, 0)));
+        assertEquals(MessageFormat.format(this.imageUrlBase, "01111"), z3.get(frontCube(7, 0)));
+        assertEquals(64, z3.size());
+    }
+
+    static Stream<Arguments> testQuadKeyToXY() {
+        final Stream.Builder<Arguments> builder = Stream.builder();
+        // 2x2
+        builder.add(Arguments.of("0", 0, 0));
+        builder.add(Arguments.of("1", 1, 0));
+        builder.add(Arguments.of("2", 0, 1));
+        builder.add(Arguments.of("3", 1, 1));
+        // 4x4
+        builder.add(Arguments.of("00", 0, 0));
+        builder.add(Arguments.of("01", 1, 0));
+        builder.add(Arguments.of("02", 0, 1));
+        builder.add(Arguments.of("03", 1, 1));
+        builder.add(Arguments.of("10", 2, 0));
+        builder.add(Arguments.of("11", 3, 0));
+        builder.add(Arguments.of("12", 2, 1));
+        builder.add(Arguments.of("13", 3, 1));
+        builder.add(Arguments.of("20", 0, 2));
+        builder.add(Arguments.of("21", 1, 2));
+        builder.add(Arguments.of("22", 0, 3));
+        builder.add(Arguments.of("23", 1, 3));
+        builder.add(Arguments.of("30", 2, 2));
+        builder.add(Arguments.of("31", 3, 2));
+        builder.add(Arguments.of("32", 2, 3));
+        builder.add(Arguments.of("33", 3, 3));
+        return builder.build();
+    }
+
+    @ParameterizedTest
+    @MethodSource
+    void testQuadKeyToXY(String quadKey, int x, int y) {
+        final var xy = StreetsideAbstractImage.quadKeyToTile(quadKey);
+        assertAll(() -> assertEquals(x, xy.getXIndex(), "x"), () -> assertEquals(y, xy.getYIndex(), "y"));
     }
 }
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/StreetsideDataTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/StreetsideDataTest.java	(revision 36194)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/StreetsideDataTest.java	(revision 36228)
@@ -12,5 +12,5 @@
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
-import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.plugins.streetside.utils.TestUtil;
 import org.openstreetmap.josm.testutils.annotations.Main;
 
@@ -31,19 +31,16 @@
 
     /**
-     * Creates a sample {@link StreetsideData} objects, 4 {@link StreetsideImage}
-     * objects and a {@link StreetsideSequence} object.
+     * Creates a sample {@link StreetsideData} object and 4 {@link StreetsideImage}
+     * objects.
      */
     @BeforeEach
     public void setUp() {
-        img1 = new StreetsideImage("id1__________________", new LatLon(0.1, 0.1), 90);
-        img2 = new StreetsideImage("id2__________________", new LatLon(0.2, 0.2), 90);
-        img3 = new StreetsideImage("id3__________________", new LatLon(0.3, 0.3), 90);
-        img4 = new StreetsideImage("id4__________________", new LatLon(0.4, 0.4), 90);
-        final StreetsideSequence seq = new StreetsideSequence();
-
-        seq.add(Arrays.asList(img1, img2, img3, img4));
+        img1 = TestUtil.generateImage("1", 0.1, 0.1);
+        img2 = TestUtil.generateImage("2", 0.2, 0.2);
+        img3 = TestUtil.generateImage("3", 0.3, 0.3);
+        img4 = TestUtil.generateImage("4", 0.4, 0.4);
 
         data = new StreetsideData();
-        data.addAll(new ConcurrentSkipListSet<>(seq.getImages()));
+        data.addAll(Arrays.asList(img1, img2, img3, img4));
     }
 
@@ -72,10 +69,10 @@
     void testSize() {
         assertEquals(4, data.getImages().size());
-        data.add(new StreetsideImage("id5__________________", new LatLon(0.1, 0.1), 90));
+        data.add(TestUtil.generateImage("5", 0.1, 0.1));
         assertEquals(5, data.getImages().size());
     }
 
     /**
-     * Test the {@link StreetsideData#setHighlightedImage(StreetsideAbstractImage)}
+     * Test the {@link StreetsideData#setHighlightedImage(StreetsideImage)}
      * and {@link StreetsideData#getHighlightedImage()} methods.
      */
@@ -137,19 +134,3 @@
         assertThrows(IllegalStateException.class, data::selectPrevious);
     }
-
-    /**
-     * Test the multiselection of images. When a new image is selected, the
-     * multiselected List should reset.
-     */
-    @Disabled("The imgs have non-int identifiers while the code expects the identifiers to be int in string form")
-    @Test
-    void testMultiSelect() {
-        assertEquals(0, data.getMultiSelectedImages().size());
-        data.setSelectedImage(img1);
-        assertEquals(1, data.getMultiSelectedImages().size());
-        data.addMultiSelectedImage(img2);
-        assertEquals(2, data.getMultiSelectedImages().size());
-        data.setSelectedImage(img1);
-        assertEquals(1, data.getMultiSelectedImages().size());
-    }
 }
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/StreetsideLayerTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/StreetsideLayerTest.java	(revision 36194)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/StreetsideLayerTest.java	(revision 36228)
@@ -10,9 +10,7 @@
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.condition.DisabledIf;
-import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.imagery.ImageryInfo;
 import org.openstreetmap.josm.gui.layer.ImageryLayer;
 import org.openstreetmap.josm.gui.layer.Layer;
-import org.openstreetmap.josm.plugins.streetside.cubemap.CubemapUtils;
 import org.openstreetmap.josm.testutils.JOSMTestRules;
 import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
@@ -46,25 +44,4 @@
 
     @Test
-    void testSetVisible() {
-        StreetsideLayer.getInstance().getData()
-                .add(new StreetsideImage(CubemapUtils.TEST_IMAGE_ID, new LatLon(0.0, 0.0), 0.0));
-        StreetsideLayer.getInstance().getData()
-                .add(new StreetsideImage(CubemapUtils.TEST_IMAGE_ID, new LatLon(0.0, 0.0), 0.0));
-        StreetsideImage invisibleImage = new StreetsideImage(CubemapUtils.TEST_IMAGE_ID, new LatLon(0.0, 0.0), 0.0);
-        invisibleImage.setVisible(false);
-        StreetsideLayer.getInstance().getData().add(invisibleImage);
-
-        StreetsideLayer.getInstance().setVisible(false);
-        for (StreetsideAbstractImage img : StreetsideLayer.getInstance().getData().getImages()) {
-            assertFalse(img.isVisible());
-        }
-
-        StreetsideLayer.getInstance().setVisible(true);
-        for (StreetsideAbstractImage img : StreetsideLayer.getInstance().getData().getImages()) {
-            assertTrue(img.isVisible());
-        }
-    }
-
-    @Test
     void testGetInfoComponent() {
         Object comp = StreetsideLayer.getInstance().getInfoComponent();
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/StreetsideSequenceTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/StreetsideSequenceTest.java	(revision 36194)
+++ 	(revision )
@@ -1,65 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.plugins.streetside;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-
-import java.util.Arrays;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.openstreetmap.josm.data.coor.LatLon;
-
-/**
- * Tests for the {@link StreetsideSequence} class.
- *
- * @author nokutu
- * @see StreetsideSequence
- */
-class StreetsideSequenceTest {
-
-    private final StreetsideImage img1 = new StreetsideImage("key1", new LatLon(0.1, 0.1), 90);
-    private final StreetsideImage img2 = new StreetsideImage("key2", new LatLon(0.2, 0.2), 90);
-    private final StreetsideImage img3 = new StreetsideImage("key3", new LatLon(0.3, 0.3), 90);
-    private final StreetsideImage img4 = new StreetsideImage("key4", new LatLon(0.4, 0.4), 90);
-    private final StreetsideImage imgWithoutSeq = new StreetsideImage("key5", new LatLon(0.5, 0.5), 90);
-    private final StreetsideSequence seq = new StreetsideSequence();
-
-    /**
-     * Creates 4 {@link StreetsideImage} objects and puts them in a
-     * {@link StreetsideSequence} object.
-     */
-    @BeforeEach
-    public void setUp() {
-        seq.add(Arrays.asList(img1, img2, img3, img4));
-    }
-
-    /**
-     * Tests the {@link StreetsideSequence#next(StreetsideAbstractImage)} and
-     * {@link StreetsideSequence#previous(StreetsideAbstractImage)}.
-     */
-    @Test
-    void testNextAndPrevious() {
-        assertEquals(img2, img1.next());
-        assertEquals(img1, img2.previous());
-        assertEquals(img3, img2.next());
-        assertEquals(img2, img3.previous());
-        assertEquals(img4, img3.next());
-        assertEquals(img3, img4.previous());
-
-        assertNull(img4.next());
-        assertNull(img1.previous());
-
-        assertNull(imgWithoutSeq.next());
-        assertNull(imgWithoutSeq.previous());
-
-        // Test IllegalArgumentException when asking for the next image of an image
-        // that is not in the sequence.
-        assertThrows(IllegalArgumentException.class, () -> seq.next(imgWithoutSeq));
-
-        // Test IllegalArgumentException when asking for the previous image of an
-        // image that is not in the sequence.
-        assertThrows(IllegalArgumentException.class, () -> seq.previous(imgWithoutSeq));
-    }
-}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/cache/StreetsideCacheTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/cache/StreetsideCacheTest.java	(revision 36194)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/cache/StreetsideCacheTest.java	(revision 36228)
@@ -4,8 +4,6 @@
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertNull;
 
 import org.junit.jupiter.api.Test;
-import org.openstreetmap.josm.plugins.streetside.cache.StreetsideCache.Type;
 import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
 
@@ -15,5 +13,5 @@
     @Test
     void testCache() {
-        StreetsideCache cache = new StreetsideCache("00000", Type.FULL_IMAGE);
+        StreetsideCache cache = new StreetsideCache("https://ecn.t0.tiles.virtualearth.net/tiles/hs101320223333223201");
         assertNotNull(cache.getUrl());
         assertNotNull(cache.getCacheKey());
@@ -21,11 +19,7 @@
         assertFalse(cache.isObjectLoadable());
 
-        cache = new StreetsideCache("00000", Type.THUMBNAIL);
+        cache = new StreetsideCache("https://ecn.t0.tiles.virtualearth.net/tiles/hs101320223333223201");
         assertNotNull(cache.getCacheKey());
         assertNotNull(cache.getUrl());
-
-        cache = new StreetsideCache(null, null);
-        assertNull(cache.getCacheKey());
-        assertNull(cache.getUrl());
     }
 }
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/cubemap/CubemapUtilsTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/cubemap/CubemapUtilsTest.java	(revision 36194)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/cubemap/CubemapUtilsTest.java	(revision 36228)
@@ -4,5 +4,4 @@
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
-import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 
@@ -28,74 +27,3 @@
         assertEquals("680931568", res);
     }
-
-    @Disabled
-    @Test
-    void testGetFaceNumberForCount() {
-        String faceNrFront = CubemapUtils.getFaceNumberForCount(0);
-        String faceNrRight = CubemapUtils.getFaceNumberForCount(1);
-        String faceNrBack = CubemapUtils.getFaceNumberForCount(2);
-        String faceNrLeft = CubemapUtils.getFaceNumberForCount(3);
-        String faceNrUp = CubemapUtils.getFaceNumberForCount(4);
-        String faceNrDown = CubemapUtils.getFaceNumberForCount(5);
-        assertEquals(faceNrFront, "01");
-        assertEquals(faceNrRight, "02");
-        assertEquals(faceNrBack, "03");
-        assertEquals(faceNrLeft, "10");
-        assertEquals(faceNrUp, "11");
-        assertEquals(faceNrDown, "12");
-    }
-
-    @Disabled
-    @Test
-    void testGetCount4FaceNumber() {
-        int count4Front = CubemapUtils.getCount4FaceNumber("01");
-        int count4Right = CubemapUtils.getCount4FaceNumber("02");
-        int count4Back = CubemapUtils.getCount4FaceNumber("03");
-        int count4Left = CubemapUtils.getCount4FaceNumber("10");
-        int count4Up = CubemapUtils.getCount4FaceNumber("11");
-        int count4Down = CubemapUtils.getCount4FaceNumber("12");
-        assertEquals(count4Front, 0);
-        assertEquals(count4Right, 1);
-        assertEquals(count4Back, 2);
-        assertEquals(count4Left, 3);
-        assertEquals(count4Up, 4);
-        assertEquals(count4Down, 5);
-    }
-
-    @Test
-    void testConvertDoubleCountNrto16TileNr() {
-        String x0y0 = CubemapUtils.convertDoubleCountNrto16TileNr("00");
-        String x0y1 = CubemapUtils.convertDoubleCountNrto16TileNr("01");
-        String x0y2 = CubemapUtils.convertDoubleCountNrto16TileNr("02");
-        String x0y3 = CubemapUtils.convertDoubleCountNrto16TileNr("03");
-        String x1y0 = CubemapUtils.convertDoubleCountNrto16TileNr("10");
-        String x1y1 = CubemapUtils.convertDoubleCountNrto16TileNr("11");
-        String x1y2 = CubemapUtils.convertDoubleCountNrto16TileNr("12");
-        String x1y3 = CubemapUtils.convertDoubleCountNrto16TileNr("13");
-        String x2y0 = CubemapUtils.convertDoubleCountNrto16TileNr("20");
-        String x2y1 = CubemapUtils.convertDoubleCountNrto16TileNr("21");
-        String x2y2 = CubemapUtils.convertDoubleCountNrto16TileNr("22");
-        String x2y3 = CubemapUtils.convertDoubleCountNrto16TileNr("23");
-        String x3y0 = CubemapUtils.convertDoubleCountNrto16TileNr("30");
-        String x3y1 = CubemapUtils.convertDoubleCountNrto16TileNr("31");
-        String x3y2 = CubemapUtils.convertDoubleCountNrto16TileNr("32");
-        String x3y3 = CubemapUtils.convertDoubleCountNrto16TileNr("33");
-
-        assertEquals(x0y0, "00");
-        assertEquals(x0y1, "01");
-        assertEquals(x0y2, "10");
-        assertEquals(x0y3, "11");
-        assertEquals(x1y0, "02");
-        assertEquals(x1y1, "03");
-        assertEquals(x1y2, "12");
-        assertEquals(x1y3, "13");
-        assertEquals(x2y0, "20");
-        assertEquals(x2y1, "21");
-        assertEquals(x2y2, "30");
-        assertEquals(x2y3, "31");
-        assertEquals(x3y0, "22");
-        assertEquals(x3y1, "23");
-        assertEquals(x3y2, "32");
-        assertEquals(x3y3, "33");
-    }
 }
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/cubemap/TileDownloadingTaskTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/cubemap/TileDownloadingTaskTest.java	(revision 36194)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/cubemap/TileDownloadingTaskTest.java	(revision 36228)
@@ -7,4 +7,5 @@
 import java.util.List;
 import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -13,4 +14,6 @@
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
+import org.openstreetmap.josm.plugins.streetside.CubeMapTileXY;
+import org.openstreetmap.josm.plugins.streetside.utils.TestUtil;
 
 @Disabled
@@ -18,10 +21,12 @@
 
     @Test
-    final void testCall() throws InterruptedException {
-        ExecutorService pool = Executors.newFixedThreadPool(1);
-        List<Callable<List<String>>> tasks = new ArrayList<>(1);
-        tasks.add(new TileDownloadingTask("2202112030033001233"));
-        List<Future<List<String>>> results = pool.invokeAll(tasks);
-        assertEquals(results.get(0), "2202112030033001233");
+    final void testCall() throws InterruptedException, ExecutionException {
+        try (ExecutorService pool = Executors.newFixedThreadPool(1)) {
+            List<Callable<List<String>>> tasks = new ArrayList<>(1);
+            tasks.add(new TileDownloadingTask(TestUtil.generateImage("2202112030033001233", 0, 0),
+                    CubemapUtils.CubemapFaces.FRONT, new CubeMapTileXY(CubemapUtils.CubemapFaces.FRONT, 0, 0)));
+            List<Future<List<String>>> results = pool.invokeAll(tasks);
+            assertEquals("2202112030033001233", results.get(0).get().get(0));
+        }
     }
 }
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/gui/ImageDisplayTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/gui/ImageDisplayTest.java	(revision 36194)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/gui/ImageDisplayTest.java	(revision 36228)
@@ -25,5 +25,5 @@
     void testImagePersistence() {
         StreetsideImageDisplay display = new StreetsideImageDisplay();
-        display.setImage(DUMMY_IMAGE, null);
+        display.setImage(DUMMY_IMAGE);
         assertEquals(DUMMY_IMAGE, display.getImage());
     }
@@ -44,5 +44,5 @@
         display.getMouseWheelListeners()[0].mouseWheelMoved(dummyScroll);
 
-        display.setImage(DUMMY_IMAGE, null);
+        display.setImage(DUMMY_IMAGE);
 
         display.getMouseWheelListeners()[0].mouseWheelMoved(dummyScroll);
@@ -72,5 +72,5 @@
             display.getMouseListeners()[0].mouseClicked(dummyClick);
 
-            display.setImage(DUMMY_IMAGE, null);
+            display.setImage(DUMMY_IMAGE);
 
             display.getMouseListeners()[0].mouseClicked(dummyClick);
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/gui/StreetsidePreferenceSettingTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/gui/StreetsidePreferenceSettingTest.java	(revision 36194)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/gui/StreetsidePreferenceSettingTest.java	(revision 36228)
@@ -6,4 +6,5 @@
 
 import java.awt.GraphicsEnvironment;
+import java.util.Objects;
 
 import javax.swing.JCheckBox;
@@ -99,11 +100,12 @@
             settings.ok();
             assertEquals(new StringProperty("streetside.download-mode", "default").get(),
-                    DOWNLOAD_MODE.fromLabel(((JComboBox<String>) getPrivateFieldValue(settings, "downloadModeComboBox"))
-                            .getSelectedItem().toString()).getPrefId());
+                    DOWNLOAD_MODE.fromLabel(Objects.requireNonNull(((JComboBox<String>) getPrivateFieldValue(settings, "downloadModeComboBox"))
+                            .getSelectedItem()).toString()).getPrefId());
         }
     }
 
     /**
-     * Checks, if a certain {@link BooleanProperty} (identified by the {@code propName} attribute) matches the selected-state of the given {@link JCheckBox}
+     * Checks, if a certain {@link BooleanProperty} (identified by the {@code propName} attribute)
+     * matches the selected-state of the given {@link JCheckBox}
      * @param cb the {@link JCheckBox}, which should be checked against the {@link BooleanProperty}
      * @param propName the name of the property against which the selected-state of the given {@link JCheckBox} should be checked
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/io/download/SequenceDownloadRunnableTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/io/download/SequenceDownloadRunnableTest.java	(revision 36194)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/io/download/SequenceDownloadRunnableTest.java	(revision 36228)
@@ -3,9 +3,4 @@
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import java.lang.reflect.Field;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.function.Function;
 
 import org.junit.jupiter.api.Disabled;
@@ -20,46 +15,34 @@
 class SequenceDownloadRunnableTest {
 
-    private static final Function<Bounds, URL> SEARCH_SEQUENCES_URL_GEN = b -> {
-        return SequenceDownloadRunnableTest.class.getResource("/api/v3/responses/searchSequences.json");
-    };
-    private Field urlGenField;
-
     @Test
-    void testRun1() throws IllegalArgumentException, IllegalAccessException {
-        testNumberOfDecodedImages(4, SEARCH_SEQUENCES_URL_GEN, new Bounds(7.246497, 16.432955, 7.249027, 16.432976));
+    void testRun1() throws IllegalArgumentException {
+        testNumberOfDecodedImages(4, new Bounds(7.246497, 16.432955, 7.249027, 16.432976));
     }
 
     @Test
-    void testRun2() throws IllegalArgumentException, IllegalAccessException {
-        testNumberOfDecodedImages(0, SEARCH_SEQUENCES_URL_GEN, new Bounds(0, 0, 0, 0));
+    void testRun2() throws IllegalArgumentException {
+        testNumberOfDecodedImages(0, new Bounds(0, 0, 0, 0));
     }
 
     @Test
-    void testRun3() throws IllegalArgumentException, IllegalAccessException {
-        testNumberOfDecodedImages(0, b -> {
-            try {
-                return new URL("https://streetside/nonexistentURL");
-            } catch (MalformedURLException e) {
-                return null;
-            }
-        }, new Bounds(0, 0, 0, 0));
+    void testRun3() throws IllegalArgumentException {
+        testNumberOfDecodedImages(0, new Bounds(0, 0, 0, 0));
     }
 
     @Test
-    void testRun4() throws IllegalArgumentException, IllegalAccessException {
+    void testRun4() throws IllegalArgumentException {
         StreetsideProperties.CUT_OFF_SEQUENCES_AT_BOUNDS.put(true);
-        testNumberOfDecodedImages(4, SEARCH_SEQUENCES_URL_GEN, new Bounds(7.246497, 16.432955, 7.249027, 16.432976));
+        testNumberOfDecodedImages(4, new Bounds(7.246497, 16.432955, 7.249027, 16.432976));
     }
 
     @Test
-    void testRun5() throws IllegalArgumentException, IllegalAccessException {
+    void testRun5() throws IllegalArgumentException {
         StreetsideProperties.CUT_OFF_SEQUENCES_AT_BOUNDS.put(true);
-        testNumberOfDecodedImages(0, SEARCH_SEQUENCES_URL_GEN, new Bounds(0, 0, 0, 0));
+        testNumberOfDecodedImages(0, new Bounds(0, 0, 0, 0));
     }
 
-    private void testNumberOfDecodedImages(int expectedNumImgs, Function<Bounds, URL> urlGen, Bounds bounds)
-            throws IllegalArgumentException, IllegalAccessException {
+    private void testNumberOfDecodedImages(int expectedNumImgs, Bounds bounds)
+            throws IllegalArgumentException {
         SequenceDownloadRunnable r = new SequenceDownloadRunnable(StreetsideLayer.getInstance().getData(), bounds);
-        urlGenField.set(null, urlGen);
         r.run();
         assertEquals(expectedNumImgs, StreetsideLayer.getInstance().getData().getImages().size());
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/GraphicsUtilsTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/GraphicsUtilsTest.java	(revision 36228)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/GraphicsUtilsTest.java	(revision 36228)
@@ -0,0 +1,42 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.openstreetmap.josm.plugins.streetside.CubeMapTileXY;
+import org.openstreetmap.josm.plugins.streetside.cubemap.CubemapUtils;
+
+class GraphicsUtilsTest {
+
+    static List<Arguments> testCubeMapTileToIndex() {
+        return Arrays.asList(Arguments.of(new CubeMapTileXY(CubemapUtils.CubemapFaces.FRONT, 0, 0), 3, 0),
+                Arguments.of(new CubeMapTileXY(CubemapUtils.CubemapFaces.FRONT, 1, 0), 3, 1),
+                Arguments.of(new CubeMapTileXY(CubemapUtils.CubemapFaces.FRONT, 2, 0), 3, 2),
+                Arguments.of(new CubeMapTileXY(CubemapUtils.CubemapFaces.FRONT, 3, 0), 3, 3),
+                Arguments.of(new CubeMapTileXY(CubemapUtils.CubemapFaces.FRONT, 4, 0), 3, 4),
+                Arguments.of(new CubeMapTileXY(CubemapUtils.CubemapFaces.FRONT, 5, 0), 3, 5),
+                Arguments.of(new CubeMapTileXY(CubemapUtils.CubemapFaces.FRONT, 6, 0), 3, 6),
+                Arguments.of(new CubeMapTileXY(CubemapUtils.CubemapFaces.FRONT, 7, 0), 3, 7),
+                Arguments.of(new CubeMapTileXY(CubemapUtils.CubemapFaces.FRONT, 0, 1), 3, 8),
+                Arguments.of(new CubeMapTileXY(CubemapUtils.CubemapFaces.FRONT, 1, 1), 3, 9),
+                Arguments.of(new CubeMapTileXY(CubemapUtils.CubemapFaces.FRONT, 2, 1), 3, 10),
+                Arguments.of(new CubeMapTileXY(CubemapUtils.CubemapFaces.FRONT, 3, 1), 3, 11),
+                Arguments.of(new CubeMapTileXY(CubemapUtils.CubemapFaces.FRONT, 4, 1), 3, 12),
+                Arguments.of(new CubeMapTileXY(CubemapUtils.CubemapFaces.FRONT, 5, 1), 3, 13),
+                Arguments.of(new CubeMapTileXY(CubemapUtils.CubemapFaces.FRONT, 6, 1), 3, 14),
+                Arguments.of(new CubeMapTileXY(CubemapUtils.CubemapFaces.FRONT, 7, 1), 3, 15),
+                Arguments.of(new CubeMapTileXY(CubemapUtils.CubemapFaces.FRONT, 0, 2), 3, 16));
+    }
+
+    @ParameterizedTest
+    @MethodSource
+    void testCubeMapTileToIndex(CubeMapTileXY tile, int zoom, int expectedIndex) {
+        assertEquals(expectedIndex, GraphicsUtils.cubeMapTileToIndex(tile, zoom));
+    }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/JsonUtil.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/JsonUtil.java	(revision 36194)
+++ 	(revision )
@@ -1,18 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.plugins.streetside.utils;
-
-import java.io.ByteArrayInputStream;
-import java.nio.charset.StandardCharsets;
-
-import jakarta.json.Json;
-import jakarta.json.JsonObject;
-
-public final class JsonUtil {
-    private JsonUtil() {
-        // Private constructor to avoid instantiation
-    }
-
-    public static JsonObject string2jsonObject(String s) {
-        return Json.createReader(new ByteArrayInputStream(s.getBytes(StandardCharsets.UTF_8))).readObject();
-    }
-}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/PluginStateTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/PluginStateTest.java	(revision 36194)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/PluginStateTest.java	(revision 36228)
@@ -2,13 +2,8 @@
 package org.openstreetmap.josm.plugins.streetside.utils;
 
-import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import javax.swing.JOptionPane;
-
 import org.junit.jupiter.api.Test;
-import org.openstreetmap.josm.TestUtils;
-import org.openstreetmap.josm.testutils.mockers.JOptionPaneSimpleMocker;
 
 /**
@@ -35,25 +30,3 @@
         assertFalse(PluginState.isDownloading());
     }
-
-    /**
-     * Tests the methods related to the upload.
-     */
-    @Test
-    void testUpload() {
-        TestUtils.assumeWorkingJMockit();
-        JOptionPaneSimpleMocker jopsMocker = new JOptionPaneSimpleMocker();
-        jopsMocker.getMockResultMap().put("You have successfully uploaded 2 images to Bing.com", JOptionPane.OK_OPTION);
-        assertFalse(PluginState.isUploading());
-        PluginState.addImagesToUpload(2);
-        assertEquals(2, PluginState.getImagesToUpload());
-        assertEquals(0, PluginState.getImagesUploaded());
-        assertTrue(PluginState.isUploading());
-        PluginState.imageUploaded();
-        assertEquals(1, PluginState.getImagesUploaded());
-        assertTrue(PluginState.isUploading());
-        PluginState.imageUploaded();
-        assertFalse(PluginState.isUploading());
-        assertEquals(2, PluginState.getImagesToUpload());
-        assertEquals(2, PluginState.getImagesUploaded());
-    }
 }
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/StreetsideURLTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/StreetsideURLTest.java	(revision 36194)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/StreetsideURLTest.java	(revision 36228)
@@ -5,9 +5,11 @@
 import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.fail;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.net.MalformedURLException;
-import java.net.URL;
+import java.net.URI;
+import java.net.URISyntaxException;
 
 import org.junit.jupiter.api.Assertions;
@@ -16,46 +18,22 @@
 
 class StreetsideURLTest {
-    // TODO: replace with Streetside URL @rrh
-    private static final String CLIENT_ID_QUERY_PART = "client_id=T1Fzd20xZjdtR0s1VDk5OFNIOXpYdzoxNDYyOGRkYzUyYTFiMzgz";
-
-    public static class APIv3 {
-
-        /*@Ignore
-        @Test
-        public void testSearchDetections() {
-          assertUrlEquals(StreetsideURL.APIv3.searchDetections(null), "https://a.streetside.com/v3/detections", CLIENT_ID_QUERY_PART);
-        }
-
-        @Ignore
-        @Test
-        public void testSearchImages() {
-          assertUrlEquals(StreetsideURL.APIv3.searchImages(null), "https://a.streetside.com/v3/images", CLIENT_ID_QUERY_PART);
-        }
-
-        @Ignore
-        @Test
-        public void testSubmitChangeset() throws MalformedURLException {
-          assertEquals(
-        new URL("https://a.streetside.com/v3/changesets?" + CLIENT_ID_QUERY_PART),
-        StreetsideURL.APIv3.submitChangeset()
-          );
-        }*/
+    @Test
+    void testParseNextFromHeaderValue() throws MalformedURLException {
+        String headerVal = "<https://a.streetside.com/v3/sequences?page=1&per_page=200"
+                + "&client_id=TG1sUUxGQlBiYWx2V05NM0pQNUVMQTo2NTU3NTBiNTk1NzM1Y2U2>; rel=\"first\", "
+                + "<https://a.streetside.com/v3/sequences?page=2&per_page=200"
+                + "&client_id=TG1sUUxGQlBiYWx2V05NM0pQNUVMQTo2NTU3NTBiNTk1NzM1Y2U2>; rel=\"prev\", "
+                + "<https://a.streetside.com/v3/sequences?page=4&per_page=200"
+                + "&client_id=TG1sUUxGQlBiYWx2V05NM0pQNUVMQTo2NTU3NTBiNTk1NzM1Y2U2>; rel=\"next\"";
+        assertEquals(URI.create(
+                "https://a.streetside.com/v3/sequences?page=4&per_page=200&client_id=TG1sUUxGQlBiYWx2V05NM0pQNUVMQTo2NTU3NTBiNTk1NzM1Y2U2")
+                .toURL(), StreetsideURL.APIv3.parseNextFromLinkHeaderValue(headerVal));
     }
 
     @Test
-    void testParseNextFromHeaderValue() throws MalformedURLException {
-        String headerVal = "<https://a.streetside.com/v3/sequences?page=1&per_page=200&client_id=TG1sUUxGQlBiYWx2V05NM0pQNUVMQTo2NTU3NTBiNTk1NzM1Y2U2>; rel=\"first\", "
-                + "<https://a.streetside.com/v3/sequences?page=2&per_page=200&client_id=TG1sUUxGQlBiYWx2V05NM0pQNUVMQTo2NTU3NTBiNTk1NzM1Y2U2>; rel=\"prev\", "
-                + "<https://a.streetside.com/v3/sequences?page=4&per_page=200&client_id=TG1sUUxGQlBiYWx2V05NM0pQNUVMQTo2NTU3NTBiNTk1NzM1Y2U2>; rel=\"next\"";
-        assertEquals(new URL(
-                "https://a.streetside.com/v3/sequences?page=4&per_page=200&client_id=TG1sUUxGQlBiYWx2V05NM0pQNUVMQTo2NTU3NTBiNTk1NzM1Y2U2"),
-                StreetsideURL.APIv3.parseNextFromLinkHeaderValue(headerVal));
-    }
-
-    @Test
-    void testParseNextFromHeaderValue2() throws MalformedURLException {
+    void testParseNextFromHeaderValue2() throws MalformedURLException, URISyntaxException {
         String headerVal = "<https://urlFirst>; rel=\"first\", " + "rel = \"next\" ; < ; , "
                 + "rel = \"next\" ; <https://urlNext> , " + "<https://urlPrev>; rel=\"prev\"";
-        assertEquals(new URL("https://urlNext"), StreetsideURL.APIv3.parseNextFromLinkHeaderValue(headerVal));
+        assertEquals(new URI("https://urlNext").toURL(), StreetsideURL.APIv3.parseNextFromLinkHeaderValue(headerVal));
     }
 
@@ -70,18 +48,10 @@
     }
 
-    /*public static class Cloudfront {
-    @Ignore
-    @Test
-    public void testThumbnail() {
-      assertUrlEquals(StreetsideURL.VirtualEarth.streetsideTile("arbitrary_key", true), "https://d1cuyjsrcm0gby.cloudfront.net/arbitrary_key/thumb-2048.jpg");
-      assertUrlEquals(StreetsideURL.VirtualEarth.streetsideTile("arbitrary_key2", false), "https://d1cuyjsrcm0gby.cloudfront.net/arbitrary_key2/thumb-320.jpg");
-    }
-    }*/
-
     @Disabled
     @Test
     void testBrowseImageURL() throws MalformedURLException {
-        assertEquals(new URL("https://www.streetside.com/map/im/1234567890123456789012"),
-                StreetsideURL.MainWebsite.browseImage("1234567890123456789012"));
+        fail("Needs editing for MS Streetside");
+        // assertEquals(new URL("https://www.streetside.com/map/im/1234567890123456789012"),
+        // StreetsideURL.MainWebsite.browseImage("1234567890123456789012"));
     }
 
@@ -91,51 +61,4 @@
     }
 
-    @Disabled
-    @Test
-    void testConnectURL() {
-        /*assertUrlEquals(
-        StreetsideURL.MainWebsite.connect("http://redirect-host/ä"),
-        "https://www.streetside.com/connect",
-        CLIENT_ID_QUERY_PART,
-        "scope=user%3Aread+public%3Aupload+public%3Awrite",
-        "response_type=token",
-        "redirect_uri=http%3A%2F%2Fredirect-host%2F%C3%A4"
-        );
-
-        assertUrlEquals(
-        StreetsideURL.MainWebsite.connect(null),
-        "https://www.streetside.com/connect",
-        CLIENT_ID_QUERY_PART,
-        "scope=user%3Aread+public%3Aupload+public%3Awrite",
-        "response_type=token"
-        );
-
-        assertUrlEquals(
-        StreetsideURL.MainWebsite.connect(""),
-        "https://www.streetside.com/connect",
-        CLIENT_ID_QUERY_PART,
-        "scope=user%3Aread+public%3Aupload+public%3Awrite",
-        "response_type=token"
-        );*/
-    }
-
-    @Disabled
-    @Test
-    void testUploadSecretsURL() throws MalformedURLException {
-        /*assertEquals(
-        new URL("https://a.streetside.com/v2/me/uploads/secrets?"+CLIENT_ID_QUERY_PART),
-        StreetsideURL.uploadSecretsURL()
-        );*/
-    }
-
-    @Disabled
-    @Test
-    void testUserURL() throws MalformedURLException {
-        /*assertEquals(
-        new URL("https://a.streetside.com/v3/me?"+CLIENT_ID_QUERY_PART),
-        StreetsideURL.APIv3.userURL()
-        );*/
-    }
-
     @Test
     void testString2MalformedURL() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException,
@@ -143,6 +66,8 @@
         Method method = StreetsideURL.class.getDeclaredMethod("string2URL", String[].class);
         method.setAccessible(true);
-        Assertions.assertNull(method.invoke(null, new Object[] { new String[] { "malformed URL" } })); // this simply invokes string2URL("malformed URL")
-        Assertions.assertNull(method.invoke(null, new Object[] { null })); // invokes string2URL(null)
+        // this simply invokes string2URL("malformed URL")
+        Assertions.assertNull(method.invoke(null, (Object) new String[] { "malformed URL" }));
+        // invokes string2URL(null)
+        Assertions.assertNull(method.invoke(null, (Object) null));
     }
 
@@ -151,23 +76,5 @@
         TestUtil.testUtilityClass(StreetsideURL.class);
         TestUtil.testUtilityClass(StreetsideURL.APIv3.class);
-        TestUtil.testUtilityClass(StreetsideURL.VirtualEarth.class);
         TestUtil.testUtilityClass(StreetsideURL.MainWebsite.class);
     }
-
-    private static void assertUrlEquals(URL actualUrl, String expectedBaseUrl, String... expectedParams) {
-        final String actualUrlString = actualUrl.toString();
-        assertEquals(expectedBaseUrl,
-                actualUrlString.contains("?") ? actualUrlString.substring(0, actualUrlString.indexOf('?'))
-                        : actualUrlString);
-        String[] actualParams = actualUrl.getQuery() == null ? new String[0] : actualUrl.getQuery().split("&");
-        assertEquals(expectedParams.length, actualParams.length);
-        for (int exIndex = 0; exIndex < expectedParams.length; exIndex++) {
-            boolean parameterIsPresent = false;
-            for (int acIndex = 0; !parameterIsPresent && acIndex < actualParams.length; acIndex++) {
-                parameterIsPresent |= actualParams[acIndex].equals(expectedParams[exIndex]);
-            }
-            Assertions.assertTrue(parameterIsPresent, expectedParams[exIndex] + " was expected in the query string of "
-                    + actualUrl + " but wasn't there.");
-        }
-    }
 }
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/StreetsideUtilsTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/StreetsideUtilsTest.java	(revision 36194)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/StreetsideUtilsTest.java	(revision 36228)
@@ -2,8 +2,4 @@
 package org.openstreetmap.josm.plugins.streetside.utils;
 
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import org.apache.commons.imaging.common.RationalNumber;
-import org.apache.commons.imaging.formats.tiff.constants.GpsTagConstants;
 import org.junit.jupiter.api.Test;
 
@@ -21,22 +17,3 @@
     }
 
-    /**
-     * Test {@link StreetsideUtils#degMinSecToDouble(RationalNumber[], String)}
-     * method.
-     */
-    @Test
-    void testDegMinSecToDouble() {
-        RationalNumber[] num = new RationalNumber[3];
-        num[0] = new RationalNumber(1, 1);
-        num[1] = new RationalNumber(0, 1);
-        num[2] = new RationalNumber(0, 1);
-        String ref = GpsTagConstants.GPS_TAG_GPS_LATITUDE_REF_VALUE_NORTH;
-        assertEquals(1, StreetsideUtils.degMinSecToDouble(num, ref), 0.01);
-        ref = GpsTagConstants.GPS_TAG_GPS_LATITUDE_REF_VALUE_SOUTH;
-        assertEquals(-1, StreetsideUtils.degMinSecToDouble(num, ref), 0.01);
-        num[0] = new RationalNumber(180, 1);
-        assertEquals(-180, StreetsideUtils.degMinSecToDouble(num, ref), 0.01);
-        num[0] = new RationalNumber(190, 1);
-        assertEquals(170, StreetsideUtils.degMinSecToDouble(num, ref), 0.01);
-    }
 }
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/TestUtil.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/TestUtil.java	(revision 36194)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/TestUtil.java	(revision 36228)
@@ -10,5 +10,8 @@
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.time.Instant;
+import java.util.Arrays;
 
+import org.openstreetmap.josm.plugins.streetside.StreetsideImage;
 import org.openstreetmap.josm.tools.JosmRuntimeException;
 
@@ -76,3 +79,19 @@
         }
     }
+
+    /**
+     * Generate a valid image
+     * @param id The id of the image
+     * @param lat The latitude of the image
+     * @param lon The longitude of the image
+     * @return The new image
+     */
+    public static StreetsideImage generateImage(String id, double lat, double lon) {
+        return new StreetsideImage("https://ecn.{subdomain}.tiles.virtualearth.net/tiles/hs" + id
+                + "{faceId}{tileId}?g=14336&key=Arzdiw4nlOJzRwOz__qailc8NiR31Tt51dN2D7cm57NrnceZnCpgOkmJhNpGoppU", lat,
+                lon, 268.811, 1.395, -4.875, Instant.ofEpochMilli(1614556800000L), Instant.ofEpochMilli(1614643199999L),
+                "https://dev.virtualearth.net/Branding/logo_powered_by.png",
+                "Copyright © 2024 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.",
+                1, 3, 256, 256, Arrays.asList("t0", "t1", "t2", "t3"));
+    }
 }
