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

1

9

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.

Ragnar answered 9/2, 2016 at 14:8 Comment(3)
Were You able to fix this issue? As I am currently facing it too! I did try all the mentioned solutions, but nothing works on any of the devices, unless I did set the .allowsEditing = false.Dorcia
No, never found a solution. Although it now has been quite some time that I tried it.Ragnar
Thanks for your reply! In case you still need it (or anyone else), I were able to fix it by just putting sleep(1) before tapping the Choose button. Not sure if that should be the case for everyone.Dorcia
M
0

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()
}
Mcgovern answered 2/7, 2021 at 17:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.