How to correctly UITest an application with UIImagePickerController (or any other native VC)

793 Views Asked by At

I'm trying to automate creating screenshots of my application using Snapshot, and all goes well, until I want to navigate through a UIImagePickerController which has set allowsEditing to true.

The weird thing is that in the iPhone 4s, 5s and 6s simulators this goes just fine, but in the iPhone 6(s) Plus the test can't seem to tap the "Choose" ("Kies" in Dutch) button in the cropper view.

My first attempt didn't work in any version:

app.buttons.elementBoundByIndex(2).tap()

And resulted in the following error:

file:///%3Cunknown%3E: test failure: -[MyAppSnapshots testExample()] failed: UI Testing Failure - Failed to scroll to visible (by AX action) Button 0x7f82d450ae30: traits: 8589934593, {{327.0, 613.5}, {35.0, 34.0}}, label: 'Kies', error: Error -25204 performing AXAction 2003

Then from this answer I grabbed the solution of forceTapElement, which does work on all but iPhone 6(s) Plus.

app.buttons.elementBoundByIndex(2).forceTapElement()

Then I tried tapping on a coordinate;

let window = app.windows.elementBoundByIndex(0)
let rightBottom = window.coordinateWithNormalizedOffset(CGVectorMake(
  CGRectGetWidth(window.frame) - 20,
  CGRectGetHeight(window.frame) - 20
))
rightBottom.tap()

But that again didn't work on any of the devices.

So how do I test these native interfaces? Or should I just add some kind of switch to my code so that the UIImagePickerController is replaced by something non-interactive.

1

There are 1 best solutions below

0
On

Looks like working approach:

func waitForElementToAppear(element: XCUIElement,
                            timeout seconds: TimeInterval = 5,
                            file: String = #file,
                            line: UInt = #line) {
    let existsPredicate = NSPredicate(format: "exists == true")
    let expectation = expectation(for: existsPredicate, evaluatedWith: element, handler: nil)
    XCTWaiter().wait(for: [expectation], timeout: seconds)
    XCTAssert(element.exists, "Element \(element.identifier) not found")
}

func tapAtPosition(position: CGPoint,
                   file: String = #file,
                   line: UInt = #line) {
    let cooridnate = app.coordinate(withNormalizedOffset: CGVector(dx: 0, dy: 0)).withOffset(CGVector(dx: position.x, dy: position.y))
    cooridnate.tap()
}

func selectPhotoFromGalary(index: Int = 0) {
    waitForElementToAppear(element: app.buttons["Photos"], timeout: 10)
    let position = app.images.containing(NSPredicate(format: "label BEGINSWITH 'Photo'")).element(boundBy: index).frame.origin
    tapAtPosition(position: position)
    let chooseButton = app.buttons["Choose"]
    waitForElementToAppear(element: chooseButton, timeout: 5)
    chooseButton.tap()
}