Dans mon test, j'ai un champ de texte avec un texte préexistant. Je veux supprimer le contenu et taper une nouvelle chaîne.
let textField = app.textFields
textField.tap()
// delete "Old value"
textField.typeText("New value")
Lors de la suppression d'une chaîne avec un clavier matériel L'enregistrement n'a généré rien pour moi. Après avoir fait la même chose avec le clavier logiciel, j'ai obtenu:
let key = app.keys["Usuń"] // Polish name for the key
key.tap()
key.tap()
... // x times
ou
app.keys["Usuń"].pressForDuration(1.5)
Je craignais que mon test dépende de la langue. J'ai donc créé quelque chose comme ceci pour les langues prises en charge:
extension XCUIElementQuery {
var deleteKey: XCUIElement {
get {
// Polish name for the key
if self["Usuń"].exists {
return self["Usuń"]
} else {
return self["Delete"]
}
}
}
}
C'est plus joli en code:
app.keys.deleteKey.pressForDuration(1.5)
mais c'est très fragile. Après avoir quitté Simulator, Toggle software keyboard
a été réinitialisé et le test a échoué. Ma solution ne fonctionne pas bien avec le test de CI. Comment cela peut-il être résolu pour être plus universel?
J'ai écrit une méthode d'extension pour le faire pour moi et c'est assez rapide:
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 = stringValue.characters.map { _ in XCUIKeyboardKeyDelete }.joined(separator: "")
self.typeText(deleteString)
self.typeText(text)
}
}
Ceci est alors utilisé assez facilement: app.textFields["Email"].clearAndEnterText("[email protected]")
Puisque vous avez résolu le problème de votre nom de clé de suppression localisée dans les commentaires de vos questions, je suppose que vous pouvez accéder à la clé de suppression en l'appelant simplement "Supprimer".
Le code ci-dessous vous permettra de supprimer de manière fiable le contenu de votre champ:
while (textField.value as! String).characters.count > 0 {
app.keys["Delete"].tap()
}
Mais en même temps, votre problème pourrait indiquer la nécessité de résoudre ce problème de manière plus élégante pour améliorer la convivialité de votre application. Sur le champ de texte, vous pouvez également ajouter un Clear button
avec lequel un utilisateur peut immédiatement vider le champ de texte;
Ouvrez le storyboard et sélectionnez le champ de texte. Sous l'inspecteur d'attributs, recherchez "Bouton Effacer" et réglez-le sur l'option souhaitée (par exemple, il est toujours visible).
Maintenant, les utilisateurs peuvent effacer le champ d'un simple tapotement sur la croix à droite du champ de texte:
Ou dans votre test d'interface utilisateur:
textField.buttons["Clear text"].tap()
J'ai trouvé la solution suivante:
let myTextView = app.textViews["some_selector"]
myTextView.pressForDuration(1.2)
app.menuItems["Select All"].tap()
app.typeText("New text you want to enter")
// or use app.keys["delete"].tap() if you have keyboard enabled
Lorsque vous maintenez le doigt appuyé sur le champ de texte, il ouvre un menu dans lequel vous pouvez appuyer sur le bouton "Tout sélectionner". Après cela, tout ce dont vous avez besoin est de supprimer ce texte avec le bouton "Supprimer" du clavier ou tout simplement d'entrer un nouveau texte. Cela écrasera l'ancien.
cela fonctionnera pour textfield et textview
pour 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)
}
}
pour Swift 4 à Swift 99
extension XCUIElement {
func clearText() {
guard let stringValue = self.value as? String else {
return
}
var deleteString = String()
for _ in stringValue {
deleteString += XCUIKeyboardKey.delete.rawValue
}
self.typeText(deleteString)
}
}
UPDATE XCODE 9
Il y a un bogue Apple où si le champ de texte est vide, value et placeholderValue sont égaux
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
}
self.typeText(deleteString)
}
}
Donc, je n'ai pas encore trouvé bien solution: /
Et je n'aime pas les solutions dépendantes de la localisation, comme ci-dessus avec une recherche explicite "Clear text".
Donc, je tape check, puis j'essaie de trouver un bouton vide dans le champ de texte Cela fonctionne bien, sauf si vous avez un champ de texte personnalisé avec plus d'un bouton
Mon meilleur maintenant est (je n'ai pas de champs de texte personnalisés avec plus de boutons):
class func clearTextField(textField : XCUIElement!) -> Bool {
guard textField.elementType != .TextField else {
return false
}
let TextFieldClearButton = textField.buttons.elementBoundByIndex(0)
guard TextFieldClearButton.exists else {
return false
}
TextFieldClearButton.tap()
return true
}
Xcode 9, Swift 4
J'ai essayé les solutions ci-dessus, mais aucune n'a fonctionné en raison d'un comportement étrange au toucher: le curseur a été déplacé au début du champ de texte ou à un point quelconque du texte. L’approche que j’ai utilisée correspond à celle décrite par @oliverfrost ici , mais j’ai ajouté quelques contacts pour contourner les problèmes et les combiner dans une extension ordonnée. J'espère que cela peut être utile pour quelqu'un.
extension XCUIElement {
func clearText(andReplaceWith newText:String? = nil) {
tap()
tap() //When there is some text, its parts can be selected on the first tap, the second tap clears the selection
press(forDuration: 1.0)
let selectAll = XCUIApplication().menuItems["Select All"]
//For empty fields there will be no "Select All", so we need to check
if selectAll.waitForExistence(timeout: 0.5), selectAll.exists {
selectAll.tap()
typeText(String(XCUIKeyboardKey.delete.rawValue))
}
if let newVal = newText { typeText(newVal) }
}
}
Usage:
let app = XCUIApplication()
//Just clear text
app.textFields["field1"].clearText()
//Replace text
app.secureTextFields["field2"].clearText(andReplaceWith: "Some Other Text")
Pour ceux qui utilisent encore Objective-C
@implementation XCUIElement (Extensions)
-(void)clearText{
if (!self){
return;
}
if (![self.value isKindOfClass:[NSString class]]){
return;
}
NSString* stringValue = (NSString*)self.value;
for (int i=0; i<stringValue.length ; i++) {
[self typeText:XCUIKeyboardKeyDelete];
}
}
@end
Maintenant, dans Swift 4.2
, vous devriez peut-être essayer le code suivant:
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()
for _ in 0..<stringValue.count {
self.typeText(XCUIKeyboardKey.delete.rawValue)
}
self.typeText(text)
}
}
J'ai eu quelques difficultés à faire en sorte que les solutions ci-dessus répondent à un problème similaire: le curseur se place avant le texte, puis à l'envers. De plus, je voulais vérifier que le champ de texte contenait du texte avant de le supprimer. Voici ma solution inspirée de l'extension https://stackoverflow.com/users/482361/bay-phillips wrote. Je devrais noter que le fait d'appuyer sur la touche Suppr peut prendre un certain temps et qu'il peut être remplacé par .pressForDuration
func clearAndEnterText(element: XCUIElement, text: String) -> Void
{
guard let stringValue = element.value as? String else {
XCTFail("Tried to clear and enter text into a non string value")
return
}
element.tap()
guard stringValue.characters.count > 0 else
{
app.typeText(text)
return
}
for _ in stringValue.characters
{
app.keys["delete"].tap()
}
app.typeText(text)
}
J'ai utilisé ce que @oliverfrost a décrit mais cela ne fonctionnait pas sur IPhone XR, je l'ai légèrement modifié pour mon usage
extension XCUIElement {
func clearText(andReplaceWith newText:String? = nil) {
tap()
tap() //When there is some text, its parts can be selected on the first tap, the second tap clears the selection
press(forDuration: 1.0)
let select = XCUIApplication().menuItems["Select"]
//For empty fields there will be no "Select All", so we need to check
if select.waitForExistence(timeout: 0.5), select.exists {
select.tap()
typeText(String(XCUIKeyboardKey.delete.rawValue))
}
if let newVal = newText { typeText(newVal) }
}
}
et comme @zysoft l'a dit, vous pouvez l'utiliser comme:
let app = XCUIApplication()
//Just clear text
app.textFields["field1"].clearText()
//Replace text
app.secureTextFields["field2"].clearText(andReplaceWith: "Some Other Text")
Faites ceci pour supprimer la valeur de chaîne actuelle dans une zone de texte sans utiliser le clavier virtuel.
// lit la valeur de votre zone de texte dans cette variable let textInTextField: String =
let characterCount: Int = textInTextField.count
for _ in 0..<characterCount {
textFields[0].typeText(XCUIKeyboardKey.delete.rawValue)
}
le bon côté de cette solution est qu’elle fonctionne, que le simulateur dispose d’un clavier virtuel ou non.
Je suis nouveau dans les tests d'interface utilisateur avec iOS, mais j'ai pu effacer les champs de texte avec cette solution de contournement simple. Travailler avec Xcode8 et planifier le refactoring très bientôt:
func testLoginWithCorrectUsernamePassword() {
//Usually this will be completed by Xcode
let app = XCUIApplication()
//Set the text field as a constant
let usernameTextField = app.textFields["User name"]
//Set the delete key to a constant
let deleteKey = app.keys["delete"]
//Tap the username text field to toggle the keyboard
usernameTextField.tap()
//Set the time to clear the field. generally 4 seconds works
deleteKey.press(forDuration: 4.0);
//Enter your code below...
}