Search code examples
iosswiftios13xcode-ui-testing

Attempting to scroll a MapView during UITesting in Xcode 11


Simply put, I wish to have an automated test as part of my UI test suite that can scroll the map. I am not concerned about the location, I just need to move it from its original position.

Why?

Two reasons:

  1. The UI updates once the user interacts with the map. I wish to validate these changes
  2. While I can easily verify this on a device, I also want to include automated screenshots via fastlane. Having a test perform this makes that possible

What have I tested so far?

I found the following from a related issue and tested without success:

let map = app.maps.element
let start = map.coordinate(withNormalizedOffset: CGVector(dx: 200,
                                                          dy: 200))
let end = map.coordinate(withNormalizedOffset: CGVector(dx: 250,
                                                        dy: 250))
start.press(forDuration: 0.01, thenDragTo: end)

I can confirm that the map element is correctly set and contains the expected information. I can also confirm that the coordinates I am using fall within the bounds of the map on the screen. I have also tested with a wide range of other values just in case.

I'm not concerned about how it is moved, or where it is moved to. All I need is to replicate a user moving the map by 1 point.


Solution

  • coordinate(withNormalizedOffset:) works a bit differently. The Vektor is multiplied to the size of your object.

    From Apple's docs:

    The coordinate’s screen point is computed by adding normalizedOffset multiplied by the size of the element’s frame to the origin of the element’s frame.

    That means that if you want to start dragging an the center of your map and then drag the map a bit you have to use it like this:

    let map = app.maps.element
    let start = map.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5))
    let end = map.coordinate(withNormalizedOffset: CGVector(dx: 0.6, dy: 0.6))
    start.press(forDuration: 0.01, thenDragTo: end)
    

    This puts the start coordinate at 0.5 * map.frame.width and 0.5 * map.frame.height and the end coordinate at 0.6 * map.frame.width and 0.6 * map.frame.height

    When you run the UITest with this you'll see that it drags the map.

    With your parameters it puts the start coordinate at 200 * map.frame.width and 200 * map.frame.height which is waaaay outside the screen so no dragging occurs.