diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5b6a42c..f20faea 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -22,6 +22,6 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - - uses: rymndhng/release-on-push-action@master + - uses: rymndhng/release-on-push-action@v0.28.0 with: - bump_version_scheme: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' && 'patch' || inputs.bump_version_scheme }} \ No newline at end of file + bump_version_scheme: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' && 'patch' || inputs.bump_version_scheme }} diff --git a/Package.resolved b/Package.resolved index 3776037..8f732c4 100644 --- a/Package.resolved +++ b/Package.resolved @@ -5,8 +5,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/maplibre/maplibre-gl-native-distribution.git", "state" : { - "revision" : "039ef525064a685c291db5118f6b5f6e8b090bb0", - "version" : "6.5.2" + "revision" : "a40e82162772e53180a2e0b1052e454db43a297d", + "version" : "6.5.1" } }, { @@ -23,8 +23,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/Kolos65/Mockable.git", "state" : { - "branch" : "main", - "revision" : "ccec0efd3e4a48b85b5407f788916de265c986dc" + "revision" : "81ccaead99a3c038c09345caa2888ae74b644ee9", + "version" : "0.0.9" } }, { diff --git a/Package.swift b/Package.swift index 23b5afd..7fc10eb 100644 --- a/Package.swift +++ b/Package.swift @@ -24,8 +24,8 @@ let package = Package( .package(url: "https://github.com/maplibre/maplibre-gl-native-distribution.git", from: "6.4.0"), .package(url: "https://github.com/stadiamaps/maplibre-swift-macros.git", from: "0.0.3"), // Testing - .package(url: "https://github.com/Kolos65/Mockable.git", branch: "main"), - .package(url: "https://github.com/pointfreeco/swift-snapshot-testing", from: "1.15.3"), + .package(url: "https://github.com/Kolos65/Mockable.git", exact: "0.0.9"), + .package(url: "https://github.com/pointfreeco/swift-snapshot-testing", from: "1.17.2"), ], targets: [ .target( diff --git a/Sources/MapLibreSwiftUI/StaticLocationManager.swift b/Sources/MapLibreSwiftUI/StaticLocationManager.swift index 1bbe6b6..b94ba51 100644 --- a/Sources/MapLibreSwiftUI/StaticLocationManager.swift +++ b/Sources/MapLibreSwiftUI/StaticLocationManager.swift @@ -10,7 +10,8 @@ import MapLibre /// /// You can provide a new location by setting the ``lastLocation`` property. /// -/// This class does not ever perform any authorization checks. That is the responsibility of the caller. +/// While this class is required to implement authorization status per the underlying protocol, +/// it does not ever actually check whether you have access to Core Location services. public final class StaticLocationManager: NSObject, @unchecked Sendable { public var delegate: (any MLNLocationManagerDelegate)? diff --git a/Tests/MapLibreSwiftUITests/MapViewCoordinator/MapViewCoordinatorCameraTests.swift b/Tests/MapLibreSwiftUITests/MapViewCoordinator/MapViewCoordinatorCameraTests.swift index 47efe30..59fb355 100644 --- a/Tests/MapLibreSwiftUITests/MapViewCoordinator/MapViewCoordinatorCameraTests.swift +++ b/Tests/MapLibreSwiftUITests/MapViewCoordinator/MapViewCoordinatorCameraTests.swift @@ -23,6 +23,13 @@ final class MapViewCoordinatorCameraTests: XCTestCase { @MainActor func testUnchangedCamera() { let camera: MapViewCamera = .default() + given(maplibreMapView) + .setCenter(.any, + zoomLevel: .any, + direction: .any, + animated: .any) + .willReturn() + coordinator.updateCamera(mapView: maplibreMapView, camera: camera, animated: false) // Run a second update. We're testing that the snapshotCamera correctly exits the function // when nothing changed. @@ -32,173 +39,192 @@ final class MapViewCoordinatorCameraTests: XCTestCase { // This verifies the comment above. verify(maplibreMapView) .userTrackingMode(newValue: .value(.none)) - .setterCalled(count: 1) + .setCalled(1) verify(maplibreMapView) .setCenter(.value(MapViewCamera.Defaults.coordinate), zoomLevel: .value(10), direction: .value(0), animated: .value(false)) - .called(count: 1) + .called(1) // Due to the .frame == .zero workaround, min/max pitch setting is called twice, once to set the // pitch, and then once to set the actual range. verify(maplibreMapView) .minimumPitch(newValue: .value(0)) - .setterCalled(count: 2) + .setCalled(2) verify(maplibreMapView) .maximumPitch(newValue: .value(0)) - .setterCalled(count: 1) + .setCalled(1) verify(maplibreMapView) .maximumPitch(newValue: .value(60)) - .setterCalled(count: 1) + .setCalled(1) verify(maplibreMapView) .setZoomLevel(.any, animated: .any) - .called(count: 0) + .called(0) } @MainActor func testCenterCameraUpdate() { let coordinate = CLLocationCoordinate2D(latitude: 12.3, longitude: 23.4) let newCamera: MapViewCamera = .center(coordinate, zoom: 13) + given(maplibreMapView) + .setCenter(.any, + zoomLevel: .any, + direction: .any, + animated: .any) + .willReturn() + coordinator.updateCamera(mapView: maplibreMapView, camera: newCamera, animated: false) verify(maplibreMapView) .userTrackingMode(newValue: .value(.none)) - .setterCalled(count: 1) + .setCalled(1) verify(maplibreMapView) .setCenter(.value(coordinate), zoomLevel: .value(13), direction: .value(0), animated: .value(false)) - .called(count: 1) + .called(1) // Due to the .frame == .zero workaround, min/max pitch setting is called twice, once to set the // pitch, and then once to set the actual range. verify(maplibreMapView) .minimumPitch(newValue: .value(0)) - .setterCalled(count: 2) + .setCalled(2) verify(maplibreMapView) .maximumPitch(newValue: .value(0)) - .setterCalled(count: 1) + .setCalled(1) verify(maplibreMapView) .maximumPitch(newValue: .value(60)) - .setterCalled(count: 1) + .setCalled(1) verify(maplibreMapView) .setZoomLevel(.any, animated: .any) - .called(count: 0) + .called(0) } @MainActor func testUserTrackingCameraUpdate() { let newCamera: MapViewCamera = .trackUserLocation() + given(maplibreMapView) + .setZoomLevel(.any, animated: .any) + .willReturn() + coordinator.updateCamera(mapView: maplibreMapView, camera: newCamera, animated: false) verify(maplibreMapView) .userTrackingMode(newValue: .value(.follow)) - .setterCalled(count: 1) + .setCalled(1) verify(maplibreMapView) .setCenter(.any, zoomLevel: .any, direction: .any, animated: .any) - .called(count: 0) + .called(0) // Due to the .frame == .zero workaround, min/max pitch setting is called twice, once to set the // pitch, and then once to set the actual range. verify(maplibreMapView) .minimumPitch(newValue: .value(0)) - .setterCalled(count: 2) + .setCalled(2) verify(maplibreMapView) .maximumPitch(newValue: .value(0)) - .setterCalled(count: 1) + .setCalled(1) verify(maplibreMapView) .maximumPitch(newValue: .value(60)) - .setterCalled(count: 1) + .setCalled(1) verify(maplibreMapView) .setZoomLevel(.value(10), animated: .value(false)) - .called(count: 1) + .called(1) } @MainActor func testUserTrackingWithCourseCameraUpdate() { let newCamera: MapViewCamera = .trackUserLocationWithCourse() + given(maplibreMapView) + .setZoomLevel(.any, animated: .any) + .willReturn() + coordinator.updateCamera(mapView: maplibreMapView, camera: newCamera, animated: false) verify(maplibreMapView) .userTrackingMode(newValue: .value(.followWithCourse)) - .setterCalled(count: 1) + .setCalled(1) verify(maplibreMapView) .setCenter(.any, zoomLevel: .any, direction: .any, animated: .any) - .called(count: 0) + .called(0) // Due to the .frame == .zero workaround, min/max pitch setting is called twice, once to set the // pitch, and then once to set the actual range. verify(maplibreMapView) .minimumPitch(newValue: .value(0)) - .setterCalled(count: 2) + .setCalled(2) verify(maplibreMapView) .maximumPitch(newValue: .value(0)) - .setterCalled(count: 1) + .setCalled(1) verify(maplibreMapView) .maximumPitch(newValue: .value(60)) - .setterCalled(count: 1) + .setCalled(1) verify(maplibreMapView) .setZoomLevel(.value(10), animated: .value(false)) - .called(count: 1) + .called(1) } @MainActor func testUserTrackingWithHeadingUpdate() { let newCamera: MapViewCamera = .trackUserLocationWithHeading() + given(maplibreMapView) + .setZoomLevel(.any, animated: .any) + .willReturn() + coordinator.updateCamera(mapView: maplibreMapView, camera: newCamera, animated: false) verify(maplibreMapView) .userTrackingMode(newValue: .value(.followWithHeading)) - .setterCalled(count: 1) + .setCalled(1) verify(maplibreMapView) .setCenter(.any, zoomLevel: .any, direction: .any, animated: .any) - .called(count: 0) + .called(0) // Due to the .frame == .zero workaround, min/max pitch setting is called twice, once to set the // pitch, and then once to set the actual range. verify(maplibreMapView) .minimumPitch(newValue: .value(0)) - .setterCalled(count: 2) + .setCalled(2) verify(maplibreMapView) .maximumPitch(newValue: .value(0)) - .setterCalled(count: 1) + .setCalled(1) verify(maplibreMapView) .maximumPitch(newValue: .value(60)) - .setterCalled(count: 1) + .setCalled(1) verify(maplibreMapView) .setZoomLevel(.value(10), animated: .value(false)) - .called(count: 1) + .called(1) } // TODO: Test Rect & Showcase once we build it! diff --git a/Tests/MapLibreSwiftUITests/Support/XCTestAssertView.swift b/Tests/MapLibreSwiftUITests/Support/XCTestAssertView.swift index 7ea9ff5..1f48166 100644 --- a/Tests/MapLibreSwiftUITests/Support/XCTestAssertView.swift +++ b/Tests/MapLibreSwiftUITests/Support/XCTestAssertView.swift @@ -3,7 +3,6 @@ import SnapshotTesting import SwiftUI import XCTest -// TODO: This is a WIP that needs some additional eyes extension XCTestCase { func assertView( named name: String? = nil, @@ -18,7 +17,7 @@ extension XCTestCase { let view = content() .frame(width: frame.width, height: frame.height) - assertSnapshot(matching: view, + assertSnapshot(of: view, as: .image(precision: 0.9, perceptualPrecision: 0.95), named: name, record: record,