I have UI tests which testing login functionality (and uses it to test other stuff), but sometimes when focus is changed from one field to another - the keyboard hides, and although the cursor is blinking in the field, I getting error on field.typeText
- no focused fields to fill
.
Somehow I realized, that clicking on a Hardware -> Keyboard -> toggle software keyboard
makes keyboard to persist on the screen, so test is works well. But I need to make it working on any testing device, on any developer machine, so I want to set this option programmatically without annoying "if test fails, go to … and set … by hand" in readme of the project.
Is it possible?
Tested in Xcode 10.3 & Xcode 11. The snippet below needs to be located in the app target (not the test bundle) — for instance, in AppDelegate.swift. It will disable any hardware keyboards from automatically connecting by setting any UIKeyboardInputMode
's automaticHardwareLayout
properties to nil
.
🔥 Does not depend on the settings of the Simulator.
📌 Note: This appears fixed in Simulator 11.0 (Xcode 11).
#if targetEnvironment(simulator)
// Disable hardware keyboards.
let setHardwareLayout = NSSelectorFromString("setHardwareLayout:")
UITextInputMode.activeInputModes
// Filter `UIKeyboardInputMode`s.
.filter({ $0.responds(to: setHardwareLayout) })
.forEach { $0.perform(setHardwareLayout, with: nil) }
#endif
Or Objective-C:
#if TARGET_IPHONE_SIMULATOR
SEL setHardwareLayout = NSSelectorFromString(@"setHardwareLayout:");
for (UITextInputMode *inputMode in [UITextInputMode activeInputModes]) {
if ([inputMode respondsToSelector:setHardwareLayout]) {
// Note: `performSelector:withObject:` will complain, so we have to use some black magic.
((void (*)(id, SEL, id))[inputMode methodForSelector:setHardwareLayout])(inputMode, setHardwareLayout, NULL);
}
}
#endif