Reputation: 1194
I'm trying to automate UI tests of an app on Apple TV (tvOS).
On the login screen I select the 'enter username' field. Then the screen with previously used logins appears. On the screen I would like to select 'clear all' cell.
To clarify: the "Previously Used" menu seems to be built-in in the tvOS and it might appear automatically whenever someone selects User name textfield in a login menu. I'm unsure about that, so still I need to confirm that information.
So I thought the code like this would be a solution:
if self.app.staticTexts["Previously Used"].exists {
let clearAllCell = self.app.cells.staticTexts["Clear All"]
while clearAllCell.hasFocus == false {
XCUIRemote.sharedRemote().pressButton(.Down)
sleep(1)
}
XCUIRemote.sharedRemote().pressButton(.Select)
}
however even in a state like this:
the properties hasFocus
and selected
of the cell seem to return false:
po self.app.cells.staticTexts["Clear All"].hasFocus
po self.app.cells.staticTexts["Clear All"].selected
How to find the "Clear All" cell when it has "focused state"?
UPDATE:
I've tried the solution proposed by @Oletha, but with no success. clearAllCell.hasFocus
unfortunately seems to return always false.
if self.app.staticTexts["Previously Used"].exists {
let clearAllCell = self.app.cells.staticTexts["Clear All"]
let predicateHasFocus = NSPredicate(format: "exists == true", argumentArray: nil)
expectationForPredicate(predicateHasFocus, evaluatedWithObject: clearAllCell, handler: { () -> Bool in
if clearAllCell.hasFocus {
return true
} else {
sleep(1)
XCUIRemote.sharedRemote().pressButton(.Down)
return false
}
})
waitForExpectationsWithTimeout(10, handler: nil)
XCUIRemote.sharedRemote().pressButton(.Select)
}
UPDATE:
A non-elegant solution at the moment is to:
if self.app.staticTexts["Previously Used"].exists {
var cellsCount = self.app.cells.count
// Select Clear All menu button, hack as it was not possible to detect "Clear All" cell in another way
while cellsCount > 0 {
sleep(1)
XCUIRemote.sharedRemote().pressButton(.Down)
cellsCount -= 1
}
sleep(1)
XCUIRemote.sharedRemote().pressButton(.Up)
sleep(1)
XCUIRemote.sharedRemote().pressButton(.Select)
}
Upvotes: 2
Views: 3475
Reputation: 115
first of all it's a native screen in tvOS So all the suggestions related to try and set accessibility ids are not relevant. Tryi to put a breakpoint when you reach that screen and print out which element is focused
I believe the answer will be. A position on screen. Or cell without identifier. I'm struggling with Same issues on Apple TV and would like to know about all the problems you have since I wonder how mature xcuitest is for tvOS
Upvotes: 0
Reputation: 3396
I had similar problems with my app and found 2 things helpful to write running UI tests:
Always make an 1 second delay after every remote button press, because the assert evaluation is often faster than the focus change and therefore returns false
XCUIRemote.sharedRemote().pressButton(.Down)
sleep(1)
Look up the the exact UI hierarchy position of your focused element. For example print(XCUIApplication().debugDescription)
will give you an detailed UI tree and makes it easy to access your element properly.
This assert has returned true:
XCTAssert(XCUIApplication().tabBars.buttons["Home"].hasFocus)
Upvotes: 2
Reputation: 7659
Use expectationForPredicate
and waitForExpectationsWithTimeout
to check if the cell has focus. Using expectations causes the accessibility hierarchy snapshot to be refreshed for each time the check occurs. Your while loop is checking against the same cached hierarchy snapshot every time, so the result won't change.
let app = XCUIApplication()
let clearAllCell = app.cells.staticTexts["Clear All"]
let focusedPredicate = NSPredicate(format: "exists == true")
let remote = XCUIRemote.sharedRemote()
expectationForPredicate(focusedPredicate, evaluatedWithObject: clearAllCell, handler: {() -> Bool in
// Check if the cell has focus
if clearAllCell.hasFocus {
// Fulfill the expectation
return true
} else {
// Move down one cell before the next check
remote.pressButton(.Down)
return false
}
})
waitForExpectationsWithTimeout(5, handler: nil)
remote.pressButton(.Select)
XCUIRemote.sharedRemote()
didn't actually work for me, but I'd guess this is working for you - I've not got an Apple TV app to test with.
Upvotes: 0