summaryrefslogtreecommitdiff
path: root/platform/ios/Integration Tests/Annotation Tests/MGLAnnotationViewIntegrationTests.m
blob: ba63a9eff49d01c69a327e02a4cd09947908c97e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#import "MGLMapViewIntegrationTest.h"
#import "MGLTestUtility.h"
#import "MGLMapAccessibilityElement.h"

@interface MGLMapView (Tests)
- (MGLAnnotationTag)annotationTagAtPoint:(CGPoint)point persistingResults:(BOOL)persist;
@end

@interface MGLAnnotationViewIntegrationTests : MGLMapViewIntegrationTest
@end

@implementation MGLAnnotationViewIntegrationTests

- (void)testSelectingAnnotationWithCenterOffset {

    for (CGFloat dx = -100.0; dx <= 100.0; dx += 100.0 ) {
        for (CGFloat dy = -100.0; dy <= 100.0; dy += 100.0 ) {
            CGVector offset = CGVectorMake(dx, dy);
            [self internalTestSelectingAnnotationWithCenterOffsetWithOffset:offset];
        }
    }
}

- (void)internalTestSelectingAnnotationWithCenterOffsetWithOffset:(CGVector)offset {

    NSString * const MGLTestAnnotationReuseIdentifer = @"MGLTestAnnotationReuseIdentifer";

    CGFloat epsilon = 0.0000001;
    CGSize size = self.mapView.bounds.size;

    CGSize annotationSize = CGSizeMake(40.0, 40.0);

    self.viewForAnnotation = ^MGLAnnotationView*(MGLMapView *view, id<MGLAnnotation> annotation) {

        if (![annotation isKindOfClass:[MGLPointAnnotation class]]) {
            return nil;
        }

        // No dequeue
        MGLAnnotationView *annotationView = [[MGLAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:MGLTestAnnotationReuseIdentifer];
        annotationView.bounds             = (CGRect){ .origin = CGPointZero, .size = annotationSize };
        annotationView.backgroundColor    = UIColor.redColor;
        annotationView.enabled            = YES;
        annotationView.centerOffset       = offset;

        return annotationView;
    };

    MGLPointAnnotation *point = [[MGLPointAnnotation alloc] init];
    point.title = NSStringFromSelector(_cmd);
    point.coordinate = CLLocationCoordinate2DMake(0.0, 0.0);
    [self.mapView addAnnotation:point];

    // From https://github.com/mapbox/mapbox-gl-native/issues/12259#issuecomment-401414168
    //
    //      queryRenderedFeatures depends on collision detection having been run
    //      before it shows results [...]. Collision detection runs asynchronously
    //      (at least every 300ms, sometimes more often), and therefore the results
    //      of queryRenderedFeatures are similarly asynchronous.
    //
    // So, we need to wait before `annotationTagAtPoint:persistingResults:` will
    // return out newly added annotation

    [self waitForCollisionDetectionToRun];

    // Check that the annotation is in the center of the view
    CGPoint annotationPoint = [self.mapView convertCoordinate:point.coordinate toPointToView:self.mapView];
    XCTAssertEqualWithAccuracy(annotationPoint.x, size.width/2.0, epsilon);
    XCTAssertEqualWithAccuracy(annotationPoint.y, size.height/2.0, epsilon);

    // Now test taps around the annotation
    CGPoint tapPoint = CGPointMake(annotationPoint.x + offset.dx, annotationPoint.y + offset.dy);

    MGLAnnotationTag tagAtPoint = [self.mapView annotationTagAtPoint:tapPoint persistingResults:YES];
    XCTAssert(tagAtPoint != UINT32_MAX, @"Should have tapped on annotation");

    CGPoint testPoints[] = {
        { tapPoint.x - annotationSize.width, tapPoint.y },
        { tapPoint.x + annotationSize.width, tapPoint.y },
        { tapPoint.x, tapPoint.y - annotationSize.height },
        { tapPoint.x, tapPoint.y + annotationSize.height },
        CGPointZero
    };

    CGPoint *testPoint = testPoints;

    while (!CGPointEqualToPoint(*testPoint, CGPointZero)) {
        tagAtPoint = [self.mapView annotationTagAtPoint:*testPoints persistingResults:YES];
        XCTAssert(tagAtPoint == UINT32_MAX, @"Tap should to the side of the annotation");
        testPoint++;
    }
}

- (void)waitForCollisionDetectionToRun {
    XCTAssertNil(self.renderFinishedExpectation, @"Incorrect test setup");

    self.renderFinishedExpectation = [self expectationWithDescription:@"Map view should be rendered"];
    XCTestExpectation *timerExpired = [self expectationWithDescription:@"Timer expires"];

    // Wait 1/2 second
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(NSEC_PER_SEC >> 1)), dispatch_get_main_queue(), ^{
        [timerExpired fulfill];
    });

    [self waitForExpectations:@[timerExpired, self.renderFinishedExpectation] timeout:5];
}

@end