Andriy Gordiychuk
Andriy Gordiychuk

Reputation: 6272

Tap method not working in Today View when performing XCUITest

I have an app with a widget, and I need to automate its screenshot creation.

However, I am struggling to do it as I cannot click the "Edit" button in Today View. If there are no widgets installed, the button is easily clickable. However, after Simulator reset there are widgets present (Maps, Reminders, Shortcuts etc) and the button is no longer clickable. What's worse is that 'isHittable' returns true :(

The code which I am trying to run is:

let app = XCUIApplication()
app.launch()
app.activate()

// Open Notification Center by swiping down
let bottomPoint = app.coordinate(withNormalizedOffset: CGVector(dx: 0, dy: 2))
app.coordinate(withNormalizedOffset: CGVector(dx: 0, dy: 0)).press(forDuration: 0.1, thenDragTo: bottomPoint)
sleep(1)

// now swipe to reveal Today View (uses custom method)
let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
springboard.scrollViews.firstMatch.swipeRight()
sleep(1)

// To make sure Edit button is visible, swipeUP
springboard.scrollViews.firstMatch.swipeUp()
sleep(2)

// Now tap the edit button (DOESN"T WORK)
springboard.buttons["Edit"].press(forDuration: 1)
sleep(2)

I have created a simple project to illustrate the bug which is located here.

To see the bug for yourself, open iPhone 11 Pro Max and add the following widgets to Today View:

  1. Reminders
  2. Calendar
  3. Maps Destinations
  4. Shortcuts
  5. News

Then, try running the testExample test from XCUITestCrashUITests. If it succeeds, at the end the Edit button should click, and you should see the Edit screen. However, it is never clicked :(

If anyone could help me find a solution that would be great. I have already tried everything that I could come up with, but it doesn't work...

Upvotes: 4

Views: 1421

Answers (1)

Roman Zakharov
Roman Zakharov

Reputation: 2273

Sometimes tap() fails or does nothing. A common solution is to tap the coordinates of the element instead of the element itself.

extension XCUIElement {
    func tapUnhittable() {
        XCTContext.runActivity(named: "Tap \(self) by coordinate") { _ in
            coordinate(withNormalizedOffset: CGVector(dx: 0.0, dy: 0.0)).tap()
        }
    }
}

Here is the code that works

import XCTest

class XCUITestCrashUITests: XCTestCase {
    func testExample() throws {
        let app = XCUIApplication()
        app.launch()
        let bottomPoint = app.coordinate(withNormalizedOffset: CGVector(dx: 0, dy: 2))
        app.coordinate(withNormalizedOffset: CGVector(dx: 0, dy: 0)).press(forDuration: 0.1, thenDragTo: bottomPoint)
        
        let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
        springboard.swipeRight()
        springboard.swipeUp()
        springboard.buttons["Edit"].tapUnhittable()
    }
}

Upvotes: 3

Related Questions