In my test I have a text field with a pre-existing text. I want to delete the content and type a new string.
let textField = app.textFields
textField.tap()
// delete "Old value"
textField.typeText("New value")
When deleting string with hardware keyboard Recording generated for me nothing. After doing the same with software keyboard I got:
let key = app.keys["Usuń"] // Polish name for the key
key.tap()
key.tap()
... // x times
or
app.keys["Usuń"].pressForDuration(1.5)
I was worried that my test is language-dependent so I have created something like this for my supported languages:
extension XCUIElementQuery {
var deleteKey: XCUIElement {
get {
// Polish name for the key
if self["Usuń"].exists {
return self["Usuń"]
} else {
return self["Delete"]
}
}
}
}
It looks nicer in code:
app.keys.deleteKey.pressForDuration(1.5)
but it is very fragile. After quitting from Simulator Toggle software keyboard
was reset and I've got a failing test. My solution doesn't work well with CI testing. How can this be solved to be more universal?
I wrote an extension method to do this for me and it's pretty fast:
extension XCUIElement {
/**
Removes any current text in the field before typing in the new value
- Parameter text: the text to enter into the field
*/
func clearAndEnterText(text: String) {
guard let stringValue = self.value as? String else {
XCTFail("Tried to clear and enter text into a non string value")
return
}
self.tap()
let deleteString = String(repeating: XCUIKeyboardKey.delete.rawValue, count: stringValue.count)
self.typeText(deleteString)
self.typeText(text)
}
}
This is then used pretty easily: app.textFields["Email"].clearAndEnterText("[email protected]")
Since you fixed your localized delete key name problem in the comments of your questions, I'll assume you can access the delete key by just calling it "Delete".
The code below will allow you to reliably delete the contents of your field:
while (textField.value as! String).characters.count > 0 {
app.keys["Delete"].tap()
}
or Swift 4+:
while !(textView.value as! String).isEmpty {
app.keys["Delete"].tap()
}
But at the same time, your issue might indicate the need to solve this more elegantly to improve the usability of your app. On the text field you can also add a Clear button
with which a user can immediately empty the text field;
Open the storyboard and select the text field, under the attributes inspector find "Clear button" and set it to the desired option (e.g. is always visible).
Now users can clear the field with a simple tap on the cross at the right of the text field:
Or in your UI test:
textField.buttons["Clear text"].tap()
this will work for textfield and textview
for SWIFT 3
extension XCUIElement {
func clearText() {
guard let stringValue = self.value as? String else {
return
}
var deleteString = String()
for _ in stringValue {
deleteString += XCUIKeyboardKeyDelete
}
self.typeText(deleteString)
}
}
for SWIFT 4, SWIFT 5
extension XCUIElement {
func clearText() {
guard let stringValue = self.value as? String else {
return
}
var deleteString = String()
for _ in stringValue {
deleteString += XCUIKeyboardKey.delete.rawValue
}
typeText(deleteString)
}
}
UPDATE XCODE 9
There is an apple bug where if the textfield is empty, value and placeholderValue are equal
extension XCUIElement {
func clearText() {
guard let stringValue = self.value as? String else {
return
}
// workaround for apple bug
if let placeholderString = self.placeholderValue, placeholderString == stringValue {
return
}
var deleteString = String()
for _ in stringValue {
deleteString += XCUIKeyboardKey.delete.rawValue
}
typeText(deleteString)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With