diff options
author | Fabian Guerra Soto <fabian.guerra@mapbox.com> | 2019-10-04 17:13:00 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-10-04 17:13:00 -0700 |
commit | 5c565a5e51be8379ddc2ffb5c859d8cfebe2fcd5 (patch) | |
tree | dcd0ca7902546247d53b9fee402673b16d2a8fd9 /platform/ios/test | |
parent | 33a70100b839793311ecc73c873c063c7cf65e31 (diff) | |
download | qtlocation-mapboxgl-5c565a5e51be8379ddc2ffb5c859d8cfebe2fcd5.tar.gz |
[ios] Fixes an issue that caused the ornaments ignore contentInset property. (#15584)
* [ios] Add mapView content inset tests.
* [ios] Fix an issue that caused the ornaments ignore the contentInsets.
Fixed an issue that caused ornaments ignore the contentInset. Added a new property automaticallyAdjustContentInset that has the same purpose as UIViewController. automaticallyAdjustsScrollViewInsets. This was changed due to the latter being deprecated.
* [ios] Fix automaticallyAdjustsScrollViewInsets legacy behavior.
The property automaticallyAdjustsScrollViewInsets overrode automaticallyAdjustsScrollViewInsets which caused a breaking change. This is fixed to consider the legacy property when calculating the content insets and added tests for both cases.
* [ios] Fix the contentInset value after adding padding to the camera.
Fixed an issue that caused a discrepancy between the contentInset in MGLMapView and the padding in the transformation state.
When padding is passed through methods such as setCamera it’s persisted. This fix resets the contentInsets.
* [ios] Fix pinch test.
* [ios] Update automaticallyAdjustsScrollViewInsets name and documentation.
* [ios] Update changelog.
Diffstat (limited to 'platform/ios/test')
-rw-r--r-- | platform/ios/test/MGLMapViewContentInsetTests.m | 177 | ||||
-rw-r--r-- | platform/ios/test/MGLMapViewGestureRecognizerTests.mm | 280 | ||||
-rw-r--r-- | platform/ios/test/MGLMapViewPitchTests.m | 4 | ||||
-rw-r--r-- | platform/ios/test/MGLMockGestureRecognizers.h | 19 | ||||
-rw-r--r-- | platform/ios/test/MGLMockGestureRecognizers.m | 44 |
5 files changed, 524 insertions, 0 deletions
diff --git a/platform/ios/test/MGLMapViewContentInsetTests.m b/platform/ios/test/MGLMapViewContentInsetTests.m new file mode 100644 index 0000000000..185baf4a05 --- /dev/null +++ b/platform/ios/test/MGLMapViewContentInsetTests.m @@ -0,0 +1,177 @@ +#import <Mapbox/Mapbox.h> +#import <XCTest/XCTest.h> + +@interface MGLMapViewContentInsetTests : XCTestCase <MGLMapViewDelegate> + +@property (nonatomic) MGLMapView *mapView; +@property (nonatomic) UIWindow *window; +@property (nonatomic) UIViewController *viewController; +@property (nonatomic) XCTestExpectation *styleLoadingExpectation; +@property (assign) CGRect screenBounds; + +@end + +@implementation MGLMapViewContentInsetTests + +- (void)setUp { + [super setUp]; + + [MGLAccountManager setAccessToken:@"pk.feedcafedeadbeefbadebede"]; + NSURL *styleURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"one-liner" withExtension:@"json"]; + self.screenBounds = UIScreen.mainScreen.bounds; + self.mapView = [[MGLMapView alloc] initWithFrame:self.screenBounds styleURL:styleURL]; + self.mapView.zoomLevel = 16; + self.mapView.delegate = self; + + self.viewController = [[UIViewController alloc] init]; + self.viewController.view = [[UIView alloc] initWithFrame:self.screenBounds]; + [self.viewController.view addSubview:self.mapView]; + self.window = [[UIWindow alloc] initWithFrame:self.screenBounds]; + [self.window addSubview:self.viewController.view]; + [self.window makeKeyAndVisible]; + + if (!self.mapView.style) { + _styleLoadingExpectation = [self expectationWithDescription:@"Map view should finish loading style."]; + [self waitForExpectationsWithTimeout:10 handler:nil]; + } +} + +- (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style { + XCTAssertNotNil(mapView.style); + XCTAssertEqual(mapView.style, style); + + [_styleLoadingExpectation fulfill]; +} + +- (void)tearDown { + self.mapView = nil; + [MGLAccountManager setAccessToken:nil]; + [super tearDown]; +} + +- (void)testContentInsetCenter { + CLLocationCoordinate2D center = CLLocationCoordinate2DMake(1.0, 5.0); + self.mapView.centerCoordinate = center; + XCTAssertEqualWithAccuracy(self.mapView.centerCoordinate.latitude, center.latitude, 0.01); + XCTAssertEqualWithAccuracy(self.mapView.centerCoordinate.longitude, center.longitude, 0.01); + + CGPoint centerPoint = [self.mapView convertCoordinate:center toPointToView:self.mapView]; + + XCTAssertEqualWithAccuracy(centerPoint.x, self.screenBounds.size.width/2, 0.01); + XCTAssertEqualWithAccuracy(centerPoint.y, self.screenBounds.size.height/2, 0.01); + + // shifting contentInset should keep the same centerCoordinate but shift the screen + // center point accordingly + UIEdgeInsets contentInset = UIEdgeInsetsMake(50.0, 10.0, 10.0, 30.0); + self.mapView.contentInset = contentInset; + XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, contentInset)); + XCTAssertEqualWithAccuracy(self.mapView.centerCoordinate.latitude, center.latitude, 0.01); + XCTAssertEqualWithAccuracy(self.mapView.centerCoordinate.longitude, center.longitude, 0.01); + CGPoint shiftedPoint = [self.mapView convertCoordinate:center toPointToView:self.mapView]; + CGPoint expectedShiftedPoint = CGPointMake((self.screenBounds.size.width/2) + ((contentInset.left - contentInset.right) / 2 ), + (self.screenBounds.size.height/2) + ((contentInset.top - contentInset.bottom) / 2)); + XCTAssertEqualWithAccuracy(shiftedPoint.x, expectedShiftedPoint.x, 0.01); + XCTAssertEqualWithAccuracy(shiftedPoint.y, expectedShiftedPoint.y, 0.01); + + +} + +- (void)testContentInsetOrnaments { + CGFloat margin = 8; + self.mapView.contentInset = UIEdgeInsetsZero; + UIView *scaleBar = self.mapView.scaleBar; + CGPoint expectedScaleBarOrigin = CGPointMake(margin, margin); + XCTAssertTrue(CGPointEqualToPoint(scaleBar.frame.origin, expectedScaleBarOrigin)); + + UIView *compassView = self.mapView.compassView; + CGFloat x = self.screenBounds.size.width - compassView.bounds.size.width - margin; + CGPoint expectedCompassOrigin = CGPointMake(x, margin); + XCTAssertTrue(CGPointEqualToPoint(compassView.frame.origin, expectedCompassOrigin)); + + UIView *logoView = self.mapView.logoView; + CGFloat y = self.screenBounds.size.height - logoView.bounds.size.height - margin; + CGPoint expectedLogoOrigin = CGPointMake(margin, y); + XCTAssertTrue(CGPointEqualToPoint(logoView.frame.origin, expectedLogoOrigin)); + + UIView *attributionView = self.mapView.attributionButton; + x = self.screenBounds.size.width - attributionView.bounds.size.width - margin; + y = self.screenBounds.size.height - attributionView.bounds.size.height - margin; + CGPoint expectedAttributionOrigin = CGPointMake(x, y); + XCTAssertTrue(CGPointEqualToPoint(attributionView.frame.origin, expectedAttributionOrigin)); + + UIEdgeInsets insets = UIEdgeInsetsMake(15, 10, 20, 5); + self.viewController.automaticallyAdjustsScrollViewInsets = NO; + self.mapView.contentInset = insets; + + [self.mapView setNeedsLayout]; + [self.mapView layoutIfNeeded]; + + expectedScaleBarOrigin = CGPointMake(insets.left + self.mapView.scaleBarMargins.x, insets.top + self.mapView.scaleBarMargins.y); + XCTAssertTrue(CGPointEqualToPoint(scaleBar.frame.origin, expectedScaleBarOrigin)); + + x = self.screenBounds.size.width - compassView.bounds.size.width - insets.right - self.mapView.compassViewMargins.x; + expectedCompassOrigin = CGPointMake(x, insets.top + self.mapView.compassViewMargins.y); + XCTAssertTrue(CGPointEqualToPoint(compassView.frame.origin, expectedCompassOrigin)); + + y = self.screenBounds.size.height - logoView.bounds.size.height - insets.bottom - self.mapView.logoViewMargins.y; + expectedLogoOrigin = CGPointMake(insets.left + self.mapView.logoViewMargins.x, y); + XCTAssertTrue(CGPointEqualToPoint(logoView.frame.origin, expectedLogoOrigin)); + + x = self.screenBounds.size.width - attributionView.bounds.size.width - insets.right - self.mapView.attributionButtonMargins.x; + y = self.screenBounds.size.height - attributionView.bounds.size.height - insets.bottom - self.mapView.attributionButtonMargins.y; + expectedAttributionOrigin = CGPointMake(x, y); + XCTAssertTrue(CGPointEqualToPoint(attributionView.frame.origin, expectedAttributionOrigin)); + + // tests that passing negative values result in a 0 inset value + insets = UIEdgeInsetsMake(-100, -100, -100, -100); + self.mapView.contentInset = insets; + + [self.mapView setNeedsLayout]; + [self.mapView layoutIfNeeded]; + + expectedScaleBarOrigin = CGPointMake(margin, margin); + XCTAssertTrue(CGPointEqualToPoint(scaleBar.frame.origin, expectedScaleBarOrigin)); + + x = self.screenBounds.size.width - compassView.bounds.size.width - margin; + expectedCompassOrigin = CGPointMake(x, margin); + XCTAssertTrue(CGPointEqualToPoint(compassView.frame.origin, expectedCompassOrigin)); + + y = self.screenBounds.size.height - logoView.bounds.size.height - margin; + expectedLogoOrigin = CGPointMake(margin, y); + XCTAssertTrue(CGPointEqualToPoint(logoView.frame.origin, expectedLogoOrigin)); + + x = self.screenBounds.size.width - attributionView.bounds.size.width - margin; + y = self.screenBounds.size.height - attributionView.bounds.size.height - margin; + expectedAttributionOrigin = CGPointMake(x, y); + XCTAssertTrue(CGPointEqualToPoint(attributionView.frame.origin, expectedAttributionOrigin)); + + self.mapView.automaticallyAdjustsContentInset = YES; + insets = UIEdgeInsetsMake(100, 100, 100, 100); + self.mapView.contentInset = insets; + XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, insets)); + + [self.mapView setNeedsLayout]; + [self.mapView layoutIfNeeded]; + + // when automaticallyAdjustsContentInset = YES the content insets should be overwriten + XCTAssertFalse(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, insets)); + + expectedScaleBarOrigin = CGPointMake(margin, margin); + XCTAssertTrue(CGPointEqualToPoint(scaleBar.frame.origin, expectedScaleBarOrigin)); + + x = self.screenBounds.size.width - compassView.bounds.size.width - margin; + expectedCompassOrigin = CGPointMake(x, margin); + XCTAssertTrue(CGPointEqualToPoint(compassView.frame.origin, expectedCompassOrigin)); + + y = self.screenBounds.size.height - logoView.bounds.size.height - margin; + expectedLogoOrigin = CGPointMake(margin, y); + XCTAssertTrue(CGPointEqualToPoint(logoView.frame.origin, expectedLogoOrigin)); + + x = self.screenBounds.size.width - attributionView.bounds.size.width - margin; + y = self.screenBounds.size.height - attributionView.bounds.size.height - margin; + expectedAttributionOrigin = CGPointMake(x, y); + XCTAssertTrue(CGPointEqualToPoint(attributionView.frame.origin, expectedAttributionOrigin)); + +} + +@end diff --git a/platform/ios/test/MGLMapViewGestureRecognizerTests.mm b/platform/ios/test/MGLMapViewGestureRecognizerTests.mm new file mode 100644 index 0000000000..58fbf2d03b --- /dev/null +++ b/platform/ios/test/MGLMapViewGestureRecognizerTests.mm @@ -0,0 +1,280 @@ +#import <Mapbox/Mapbox.h> +#import <XCTest/XCTest.h> + +#import "../../darwin/src/MGLGeometry_Private.h" +#import "MGLMockGestureRecognizers.h" + +#include <mbgl/map/map.hpp> +#include <mbgl/map/camera.hpp> + +@interface MGLMapView (MGLMapViewGestureRecognizerTests) + +- (mbgl::Map &)mbglMap; + +- (void)handlePinchGesture:(UIPinchGestureRecognizer *)pinch; +- (void)handleRotateGesture:(UIRotationGestureRecognizer *)rotate; +- (void)handleDoubleTapGesture:(UITapGestureRecognizer *)doubleTap; +- (void)handleTwoFingerTapGesture:(UITapGestureRecognizer *)twoFingerTap; +- (void)handleQuickZoomGesture:(UILongPressGestureRecognizer *)quickZoom; +- (void)handleTwoFingerDragGesture:(UIPanGestureRecognizer *)twoFingerDrag; + +@end + +@interface MGLMapViewGestureRecognizerTests : XCTestCase <MGLMapViewDelegate> + +@property (nonatomic) MGLMapView *mapView; +@property (nonatomic) UIWindow *window; +@property (nonatomic) UIViewController *viewController; +@property (nonatomic) XCTestExpectation *styleLoadingExpectation; +@property (nonatomic) XCTestExpectation *twoFingerExpectation; +@property (nonatomic) XCTestExpectation *quickZoomExpectation; +@property (nonatomic) XCTestExpectation *doubleTapExpectation; +@property (nonatomic) XCTestExpectation *twoFingerDragExpectation; +@property (assign) CGRect screenBounds; + +@end + +@implementation MGLMapViewGestureRecognizerTests + +- (void)setUp { + [super setUp]; + + [MGLAccountManager setAccessToken:@"pk.feedcafedeadbeefbadebede"]; + NSURL *styleURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"one-liner" withExtension:@"json"]; + self.screenBounds = UIScreen.mainScreen.bounds; + self.mapView = [[MGLMapView alloc] initWithFrame:self.screenBounds styleURL:styleURL]; + self.mapView.zoomLevel = 16; + self.mapView.delegate = self; + + self.viewController = [[UIViewController alloc] init]; + self.viewController.view = [[UIView alloc] initWithFrame:self.screenBounds]; + [self.viewController.view addSubview:self.mapView]; + self.window = [[UIWindow alloc] initWithFrame:self.screenBounds]; + [self.window addSubview:self.viewController.view]; + [self.window makeKeyAndVisible]; + + if (!self.mapView.style) { + _styleLoadingExpectation = [self expectationWithDescription:@"Map view should finish loading style."]; + [self waitForExpectationsWithTimeout:10 handler:nil]; + } +} + +- (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style { + XCTAssertNotNil(mapView.style); + XCTAssertEqual(mapView.style, style); + + [_styleLoadingExpectation fulfill]; +} + +- (void)testHandlePinchGestureContentInset { + UIEdgeInsets contentInset = UIEdgeInsetsZero; + self.mapView.contentInset = contentInset; + mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(self.mapView.contentInset); + auto cameraPadding = self.mapView.mbglMap.getCameraOptions().padding; + XCTAssertEqual(padding, cameraPadding, @"MGLMapView's contentInset property should match camera's padding."); + XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, contentInset)); + + contentInset = UIEdgeInsetsMake(20, 20, 20, 20); + [self.mapView setCamera:self.mapView.camera withDuration:0.1 animationTimingFunction:nil edgePadding:contentInset completionHandler:nil]; + XCTAssertFalse(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, contentInset)); + + cameraPadding = self.mapView.mbglMap.getCameraOptions().padding; + XCTAssertNotEqual(padding, cameraPadding); + + UIPinchGestureRecognizerMock *pinchGesture = [[UIPinchGestureRecognizerMock alloc] initWithTarget:nil action:nil]; + pinchGesture.state = UIGestureRecognizerStateBegan; + pinchGesture.scale = 1.0; + [self.mapView handlePinchGesture:pinchGesture]; + XCTAssertNotEqual(padding, cameraPadding); + + pinchGesture.state = UIGestureRecognizerStateChanged; + [self.mapView handlePinchGesture:pinchGesture]; + cameraPadding = self.mapView.mbglMap.getCameraOptions().padding; + XCTAssertEqual(padding, cameraPadding, @"When a gesture recognizer is performed contentInsets and camera padding should match."); + + pinchGesture.state = UIGestureRecognizerStateEnded; + [self.mapView handlePinchGesture:pinchGesture]; + cameraPadding = self.mapView.mbglMap.getCameraOptions().padding; + XCTAssertEqual(padding, cameraPadding, @"When a gesture recognizer is performed contentInsets and camera padding should match."); + +} + +- (void)testHandleRotateGestureContentInset { + UIEdgeInsets contentInset = UIEdgeInsetsZero; + self.mapView.contentInset = contentInset; + mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(self.mapView.contentInset); + auto cameraPadding = self.mapView.mbglMap.getCameraOptions().padding; + XCTAssertEqual(padding, cameraPadding, @"MGLMapView's contentInset property should match camera's padding."); + XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, contentInset)); + + contentInset = UIEdgeInsetsMake(20, 20, 20, 20); + [self.mapView setCamera:self.mapView.camera withDuration:0.1 animationTimingFunction:nil edgePadding:contentInset completionHandler:nil]; + XCTAssertFalse(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, contentInset)); + + cameraPadding = self.mapView.mbglMap.getCameraOptions().padding; + XCTAssertNotEqual(padding, cameraPadding); + + UIRotationGestureRecognizerMock *rotateGesture = [[UIRotationGestureRecognizerMock alloc] initWithTarget:nil action:nil]; + rotateGesture.state = UIGestureRecognizerStateBegan; + rotateGesture.rotation = 1; + [self.mapView handleRotateGesture:rotateGesture]; + XCTAssertNotEqual(padding, cameraPadding); + + rotateGesture.state = UIGestureRecognizerStateChanged; + [self.mapView handleRotateGesture:rotateGesture]; + cameraPadding = self.mapView.mbglMap.getCameraOptions().padding; + XCTAssertEqual(padding, cameraPadding, @"When a gesture recognizer is performed contentInsets and camera padding should match."); + + rotateGesture.state = UIGestureRecognizerStateEnded; + [self.mapView handleRotateGesture:rotateGesture]; + cameraPadding = self.mapView.mbglMap.getCameraOptions().padding; + XCTAssertEqual(padding, cameraPadding, @"When a gesture recognizer is performed contentInsets and camera padding should match."); + +} + +- (void)testHandleDoubleTapGestureContentInset { + UIEdgeInsets contentInset = UIEdgeInsetsMake(1, 1, 1, 1); + self.mapView.contentInset = contentInset; + mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(self.mapView.contentInset); + auto cameraPadding = self.mapView.mbglMap.getCameraOptions().padding; + XCTAssertEqual(padding, cameraPadding, @"MGLMapView's contentInset property should match camera's padding."); + XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, contentInset)); + + contentInset = UIEdgeInsetsMake(20, 20, 20, 20); + [self.mapView setCamera:self.mapView.camera withDuration:0.1 animationTimingFunction:nil edgePadding:contentInset completionHandler:nil]; + XCTAssertFalse(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, contentInset)); + + cameraPadding = self.mapView.mbglMap.getCameraOptions().padding; + XCTAssertNotEqual(padding, cameraPadding); + + UITapGestureRecognizerMock *doubleTapGesture = [[UITapGestureRecognizerMock alloc] initWithTarget:nil action:nil]; + doubleTapGesture.mockTappedView = self.mapView; + doubleTapGesture.mockTappedPoint = CGPointMake(1.0, 1.0); + + [self.mapView handleDoubleTapGesture:doubleTapGesture]; + _doubleTapExpectation = [self expectationWithDescription:@"Double tap gesture animation."]; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [self->_doubleTapExpectation fulfill]; + }); + [self waitForExpectationsWithTimeout:10 handler:nil]; + + cameraPadding = self.mapView.mbglMap.getCameraOptions().padding; + XCTAssertEqual(padding, cameraPadding, @"When a gesture recognizer is performed contentInsets and camera padding should match."); + +} + +- (void)testHandleTwoFingerTapGesture { + UIEdgeInsets contentInset = UIEdgeInsetsZero; + self.mapView.contentInset = contentInset; + mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(self.mapView.contentInset); + auto cameraPadding = self.mapView.mbglMap.getCameraOptions().padding; + XCTAssertEqual(padding, cameraPadding, @"MGLMapView's contentInset property should match camera's padding."); + XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, contentInset)); + + contentInset = UIEdgeInsetsMake(20, 20, 20, 20); + [self.mapView setCamera:self.mapView.camera withDuration:0.1 animationTimingFunction:nil edgePadding:contentInset completionHandler:nil]; + XCTAssertFalse(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, contentInset)); + + cameraPadding = self.mapView.mbglMap.getCameraOptions().padding; + XCTAssertNotEqual(padding, cameraPadding); + + UITapGestureRecognizerMock *twoFingerTap = [[UITapGestureRecognizerMock alloc] initWithTarget:nil action:nil]; + twoFingerTap.mockTappedView = self.mapView; + twoFingerTap.mockTappedPoint = CGPointMake(1.0, 1.0); + + [self.mapView handleTwoFingerTapGesture:twoFingerTap]; + _twoFingerExpectation = [self expectationWithDescription:@"Two Finger tap gesture animation."]; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [self->_twoFingerExpectation fulfill]; + }); + [self waitForExpectationsWithTimeout:10 handler:nil]; + + cameraPadding = self.mapView.mbglMap.getCameraOptions().padding; + XCTAssertEqual(padding, cameraPadding, @"When a gesture recognizer is performed contentInsets and camera padding should match."); +} + +- (void)testHandleQuickZoomGesture { + UIEdgeInsets contentInset = UIEdgeInsetsZero; + self.mapView.contentInset = contentInset; + mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(self.mapView.contentInset); + auto cameraPadding = self.mapView.mbglMap.getCameraOptions().padding; + XCTAssertEqual(padding, cameraPadding, @"MGLMapView's contentInset property should match camera's padding."); + XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, contentInset)); + + contentInset = UIEdgeInsetsMake(20, 20, 20, 20); + [self.mapView setCamera:self.mapView.camera withDuration:0.1 animationTimingFunction:nil edgePadding:contentInset completionHandler:nil]; + XCTAssertFalse(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, contentInset)); + + cameraPadding = self.mapView.mbglMap.getCameraOptions().padding; + XCTAssertNotEqual(padding, cameraPadding); + + UILongPressGestureRecognizerMock *quickZoom = [[UILongPressGestureRecognizerMock alloc] initWithTarget:nil action:nil]; + quickZoom.state = UIGestureRecognizerStateBegan; + [self.mapView handleQuickZoomGesture:quickZoom]; + XCTAssertNotEqual(padding, cameraPadding); + + quickZoom.state = UIGestureRecognizerStateChanged; + quickZoom.mockTappedPoint = CGPointMake(self.mapView.frame.size.width / 2, self.mapView.frame.size.height / 2); + [self.mapView handleQuickZoomGesture:quickZoom]; + _quickZoomExpectation = [self expectationWithDescription:@"Quick zoom gesture animation."]; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [self->_quickZoomExpectation fulfill]; + }); + [self waitForExpectationsWithTimeout:10 handler:nil]; + + cameraPadding = self.mapView.mbglMap.getCameraOptions().padding; + XCTAssertEqual(padding, cameraPadding, @"When a gesture recognizer is performed contentInsets and camera padding should match."); + + quickZoom.state = UIGestureRecognizerStateEnded; + [self.mapView handleQuickZoomGesture:quickZoom]; + cameraPadding = self.mapView.mbglMap.getCameraOptions().padding; + XCTAssertEqual(padding, cameraPadding, @"When a gesture recognizer is performed contentInsets and camera padding should match."); +} + +- (void)testHandleTwoFingerDragGesture { + UIEdgeInsets contentInset = UIEdgeInsetsZero; + self.mapView.contentInset = contentInset; + mbgl::EdgeInsets padding = MGLEdgeInsetsFromNSEdgeInsets(self.mapView.contentInset); + auto cameraPadding = self.mapView.mbglMap.getCameraOptions().padding; + XCTAssertEqual(padding, cameraPadding, @"MGLMapView's contentInset property should match camera's padding."); + XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, contentInset)); + + contentInset = UIEdgeInsetsMake(20, 20, 20, 20); + [self.mapView setCamera:self.mapView.camera withDuration:0.1 animationTimingFunction:nil edgePadding:contentInset completionHandler:nil]; + XCTAssertFalse(UIEdgeInsetsEqualToEdgeInsets(self.mapView.contentInset, contentInset)); + + cameraPadding = self.mapView.mbglMap.getCameraOptions().padding; + XCTAssertNotEqual(padding, cameraPadding); + + UIPanGestureRecognizerMock *twoFingerDrag = [[UIPanGestureRecognizerMock alloc] initWithTarget:nil action:nil]; + twoFingerDrag.state = UIGestureRecognizerStateBegan; + twoFingerDrag.firstFingerPoint = CGPointMake(self.mapView.frame.size.width / 3, self.mapView.frame.size.height/2); + twoFingerDrag.secondFingerPoint = CGPointMake((self.mapView.frame.size.width / 2), self.mapView.frame.size.height/2); + twoFingerDrag.numberOfTouches = 2; + [self.mapView handleTwoFingerDragGesture:twoFingerDrag]; + XCTAssertNotEqual(padding, cameraPadding); + + twoFingerDrag.state = UIGestureRecognizerStateChanged; + twoFingerDrag.firstFingerPoint = CGPointMake(self.mapView.frame.size.width / 3, (self.mapView.frame.size.height/2)-10); + twoFingerDrag.secondFingerPoint = CGPointMake((self.mapView.frame.size.width / 2), (self.mapView.frame.size.height/2)-10); + [self.mapView handleTwoFingerDragGesture:twoFingerDrag]; + _twoFingerDragExpectation = [self expectationWithDescription:@"Quick zoom gesture animation."]; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [self->_twoFingerDragExpectation fulfill]; + }); + [self waitForExpectationsWithTimeout:10 handler:nil]; + + cameraPadding = self.mapView.mbglMap.getCameraOptions().padding; + XCTAssertEqual(padding, cameraPadding, @"When a gesture recognizer is performed contentInsets and camera padding should match."); + + twoFingerDrag.state = UIGestureRecognizerStateEnded; + [self.mapView handleTwoFingerDragGesture:twoFingerDrag]; + cameraPadding = self.mapView.mbglMap.getCameraOptions().padding; + XCTAssertEqual(padding, cameraPadding, @"When a gesture recognizer is performed contentInsets and camera padding should match."); +} + +@end diff --git a/platform/ios/test/MGLMapViewPitchTests.m b/platform/ios/test/MGLMapViewPitchTests.m index 3e9311dbd4..fa657eb994 100644 --- a/platform/ios/test/MGLMapViewPitchTests.m +++ b/platform/ios/test/MGLMapViewPitchTests.m @@ -2,6 +2,7 @@ #import <XCTest/XCTest.h> @interface MockUIPanGestureRecognizer : UIPanGestureRecognizer +@property(nonatomic, readwrite) UIGestureRecognizerState state; @property NSUInteger mbx_numberOfFingersForGesture; @property CGPoint mbx_middlePoint; @property CGPoint mbx_westPoint; @@ -9,6 +10,9 @@ @end @implementation MockUIPanGestureRecognizer + +@synthesize state; + - (instancetype)initWithTarget:(id)target action:(SEL)action { if (self = [super initWithTarget:target action:action]) { self.mbx_numberOfFingersForGesture = 2; diff --git a/platform/ios/test/MGLMockGestureRecognizers.h b/platform/ios/test/MGLMockGestureRecognizers.h index aa5fbec494..29889e39f4 100644 --- a/platform/ios/test/MGLMockGestureRecognizers.h +++ b/platform/ios/test/MGLMockGestureRecognizers.h @@ -4,7 +4,26 @@ @interface UIPinchGestureRecognizerMock : UIPinchGestureRecognizer @property (nonatomic, readwrite) CGFloat velocity; @property (nonatomic) CGPoint locationInViewOverride; +@property(nonatomic, readwrite) UIGestureRecognizerState state; @end @interface UIRotationGestureRecognizerMock : UIRotationGestureRecognizer +@property(nonatomic, readwrite) UIGestureRecognizerState state; +@end + +@interface UITapGestureRecognizerMock : UITapGestureRecognizer +@property (strong, nonatomic) UIView *mockTappedView; +@property (assign) CGPoint mockTappedPoint; +@end + +@interface UILongPressGestureRecognizerMock : UILongPressGestureRecognizer +@property(nonatomic, readwrite) UIGestureRecognizerState state; +@property (assign) CGPoint mockTappedPoint; +@end + +@interface UIPanGestureRecognizerMock : UIPanGestureRecognizer +@property(nonatomic, readwrite) UIGestureRecognizerState state; +@property (assign) CGPoint firstFingerPoint; +@property (assign) CGPoint secondFingerPoint; +@property(nonatomic, readwrite) NSUInteger numberOfTouches; @end diff --git a/platform/ios/test/MGLMockGestureRecognizers.m b/platform/ios/test/MGLMockGestureRecognizers.m index 89df6750a9..c818805174 100644 --- a/platform/ios/test/MGLMockGestureRecognizers.m +++ b/platform/ios/test/MGLMockGestureRecognizers.m @@ -1,11 +1,55 @@ #import "MGLMockGestureRecognizers.h" +#import "objc/runtime.h" @implementation UIPinchGestureRecognizerMock @synthesize velocity; +@synthesize state; - (CGPoint)locationInView:(nullable UIView *)view { return self.locationInViewOverride; } @end @implementation UIRotationGestureRecognizerMock - (CGPoint)locationInView:(nullable UIView*)view { return view.center; } +@synthesize state; +@end + +@implementation UITapGestureRecognizerMock + ++ (void)load { + method_exchangeImplementations(class_getInstanceMethod(self, @selector(state)), + class_getInstanceMethod(self, @selector(mockState))); +} + +- (UIGestureRecognizerState)mockState { + return UIGestureRecognizerStateRecognized; +} + +- (UIView *)view { + return self.mockTappedView; +} + +- (CGPoint)locationInView:(UIView *)view { + return self.mockTappedPoint; +} + +@end + +@implementation UILongPressGestureRecognizerMock +@synthesize state; + +- (CGPoint)locationInView:(UIView *)view { + return self.mockTappedPoint; +} +@end + +@implementation UIPanGestureRecognizerMock +@synthesize state; +@synthesize numberOfTouches; + +- (CGPoint)locationOfTouch:(NSUInteger)touchIndex inView:(UIView *)view { + if (touchIndex) { + return self.secondFingerPoint; + } + return self.firstFingerPoint; +} @end |