"Neither element nor any descendant has keyboard focus" when running XCTestCase in a real iPhone - iphone

I'm trying to run a UI test case where there are two input fields exists. Following is my code
let usernameTextField = app.webViews.otherElements["Identity Server"].textFields["Username"]
let passwordField = app.webViews.otherElements["Identity Server"].secureTextFields["Password"]
_ = usernameTextField.waitForExistence(timeout: 8)
usernameTextField.tap()
usernameTextField.typeText("TEST") // Breakpoint line
app.typeText("\n")
passwordField.tap()
passwordField.typeText("test")
When I run the test case normally it is failing with the error given in the question title. But if I add a breakpoint to the commented line, it will run without any error.
I tried to use following code snippets after the breakpoint line, separately.
sleep(8)
_ = passwordField.waitForExistence(timeout: 8)
But non of those work. As for further information, this is a Auth process scenario where those input fields resides in a web view.

I decided to answer myself rather than closing the question. I'll tell what went wrong in my code. The main mistake I have done was continueAfterFailure set as true. Because of that, the error shown in the wrong line not the actual error throwing line.
So the solution is,
continueAfterFailure = false
and
usernameTextField.tap()
sleep(2)
usernameTextField.typeText("TEST")
There should be a small waiting time till keyboard appears in the web view before type text.

Send the \n on the end of the string you send to the username text field:
usernameTextField.typeText("TEST\n")

Related

Try-catch like feature for uncertain code block in Swift 4

I am writing a test in XCUITest. There is an introductory banner which may or may not come on the mobile screen while my test is in progress. I want to write my case in such a way that, if the banner is present, I have to verify certain elements on that banner and click on the "Continue" button on it, and if it is not present, I have to proceed with my test case.
I know in Java, we write such code inside a try-catch block, so that even if the banner is not found and the code fails, the pointer goes into the catch block and the remaining program continues.
When I searched on the internet, i only found such feature for single statements and not for some chunk of code block.Do we have something similar in Swift, where I can write some code inside try-catch like code block?
Please have a look at my test case and the code to click in the banner.
class MyTestClass: BaseTest {
func testMapSearch() {
do {
let app = try XCUIApplication()
let element = try app.children(matching: .window).element(boundBy: 0).children(matching: .other).element.children(matching: .other).element(boundBy: 1).children(matching: .other).element(boundBy: 0)
element.buttons["Continue"].tap()
} catch let error {
print("Error: \(error)")
}
let logInButton = app.scrollViews.otherElements.buttons["Log In"]
checkLoginPage(login: logInButton)
logInButton.tap()
}
}
The do block is written to click on the "Continue" button on a banner which is not sure to be displayed on the screen. The do block is followed by more code. If the banner is not displayed, the code written in the do block fails and the test case throws an error. I want to write a case such that the login button code should get executed irrespective of the banner is displayed or not.
The problem with your code is that the two lines of code marked try are not failable (they don't throw), so you cannot mark them try in the first place.
The entire attempt to turn this situation into a try/catch is wrong-headed. What you want to do here is simply add a condition to check whether the desired element exists and is tappable, and proceed differently if it doesn't (i.e. don't attempt to tap it). That is what if is for.
(Of course one might argue that if the test is not intended to fail if it is impossible to tap this element, then the test itself is incorrectly constructed — you should just omit the tap line altogether.)

Timestamped Event Matching Error: Failed to find matching element

I'm trying to generate a UItest in Xcode. When I try to swipe UIview I get
an error:
Timestamped Event Matching Error: Failed to find matching element
error window
This also happens if I try to tap UIView.
You should verify that the 'Accessibility' option is enabled for the UIView object you are swiping from, for example:
Usually this issue is observed when the parent element of the element yo want to record is set to isAccessibilityElement = true. In general, you have to have the parent element set to false to access the child element.
For example: if you have a UILabel inside a view, the accessibility should be set to false for the view and set to true for the UILabel.
For recording a new test, I don't think there's a solution yet. But, if you use an extension forcing tap with a test that already exists, works.
Example of use:
extension XCUIElement {
func forceTapElement() {
if self.hittable {
self.tap()
}
else {
let coordinate: XCUICoordinate = self.coordinateWithNormalizedOffset(CGVectorMake(0.0, 0.0))
coordinate.tap()
}
}
}
func testSomethingWithCells() {
let app = XCUIApplication()
let cells = app.tables.cells
sleep(1)
cells.elementBoundByIndex(0).forceTapElement()
}
You can check the original post here:
Xcode UI test - UI Testing Failure - Failed to scroll to visible (by AX action) when tap on Search field "Cancel' button
I've been occasionally running into this problem. Delete the app's directory from DerivedData seems to help.
In Xcode 9.3, where this is apparently still a problem, what I did was:
Quit Xcode
Reset the Simulator's settings (Hardware -> Erase all
contents and settings)
Quit the Simulator
Delete the derived data for the current app
Restart Xcode
Try recording again - it worked this time for me.
A solution that worked for myself was to identify the object differently.
In Xcode 8 I was able to use the following:
XCUIApplication().tables.cells["Camera Roll"].buttons["Camera Roll"].tap()
With Xcode 9 I got the error mentioned in this question. Ended up using the following, which worked (al beit more flakey than the original option)
XCUIApplication().cells.element(boundBy: 1).tap()
Even if you have Accessibility enabled for the element, you have to make sure that it has a unique accessibility identifier. In my case, I had copied & pasted a UISwitch and assigned a different outlet to it, but it kept the same accessibility ID as the original one.

Swift2 UITest - Wait for element to appear without treating test as Failed in case element won't appear

I try to create UI test on the application where sometimes AD popup appears and if so I need to click on close button. I tried to use:
waitForExpectationsWithTimeout(timeout: NSTimeInterval, handler: XCWaitCompletionHandler?)
with
let existsPredicate = NSPredicate(format: "exists == true")
But the problem is that the method treats test as failed which is not acceptable for my case.
I tried to use .exists after custom sleep but from my observations it just always returns false even though element does appear on the screen.
Also plaid around with .hittable and it seems to be true even though the element didn't appear on the screen yet.
From my understanding it would be great if Apple gives control of whether waitForExpectationsWithTimeout treats test as fail or not, but I was not able to find anything.
Any advice would be greatly appreciated!
i can suggest you not to use handler XCWaitCompletionHandler in this case.
expectationForPredicate(predicate, evaluatedWithObject: evaluatedWithObject, handler: nil)
waitForExpectationsWithTimeout(TIMEOUT, handler: nil)
if (evaluatedWithObject.exist) {
//dosmth
}
so it is soft assert that smth appears. If element not found it just will wait time and go further
Unfortunately the only solution I've found is to do it manually: use a while loop and check for object.exists for a waiting period to prevent the expectation wait failure.

How to know any UI rendering is completed in automation code

I am wanting to know a button is rendered on main window UI or not. This button rendering is depending on server response result (written in Objective C). If server response comes perfectly it becomes render perfectly (VISIBLE) otherwise it is not present there (INVISIBLE). And whenever it becomes visible I always tap on it for further next process.
I wrote code
UIATarget.localTarget().pushTimeout(200);
//My code
UIATarget.localTarget().popTimeout();
By the above code I have to wait till 200 sec but my concern is I want to wait but whenever object is on screen I don't want keep me busy in WAITING MODE.
How will I write code in automation?
Thanks
Ok, this might give you idea how to follow-up:
For your view implement an accessibilityValue method which returns a JSON formatted value:
- (NSString *)accessibilityValue
{
return [NSString stringWithFormat:
#"{'MyButtonisVisible':%#}",
self.MyButton.isHidden ? #"false" : #"true"];
}
Then somehow you can access it from your test javascript:
var thisproperty = eval("(" + element.value() + ")");
if (thisproperty.MyButtonisVisible) {
UIATarget.localTarget().tap({"x":100, "y":100});
}
Hope that helps.
If you make the name different when you enable the button you can do this:
var awesomeButton = target.frontMostApp().mainWindow().buttons()[0];
UIATarget.localTarget().pushTimeout(200);
awesomeButton.withName("My Awesome Button");
if (awesomeButton.isVisible()) {
UIALogger.logError("Error no awesome button!");
}
UIATarget.localTarget().popTimeout();
withName will repeatedly test the name and control will return to your script once the name matches or when the time out is reached.
Per Apple's Doc
withName:
Tests if the name attribute of the element has the given string value. If the match fails, the test is retried until the current timeout expires.
Timeout Periods:
If the action completes during the timeout period, that line of code returns, and your script can proceed. If the action doesn’t complete during the timeout period, an exception is thrown.
https://developer.apple.com/library/etc/redirect/xcode/ios/e808aa/documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/UsingtheAutomationInstrument/UsingtheAutomationInstrument.html#//apple_ref/doc/uid/TP40004652-CH20

Ignore certain exceptions when using Xcode's All Exceptions breakpoint

I have an All Exceptions breakpoint configured in Xcode:
Sometimes Xcode will stop on a line like:
[managedObjectContext save:&error];
with the following backtrace:
but the program continues on as if nothing happened if you click Continue.
How can I ignore these "normal" exceptions, but still have the debugger stop on exceptions in my own code?
(I understand that this happens because Core Data internally throws and catches exceptions, and that Xcode is simply honoring my request to pause the program whenever an exception is thrown. However, I want to ignore these so I can get back to debugging my own code!)
Moderators: this is similar to "Xcode 4 exception breakpoint filtering", but I think that question takes too long to get around to the point and doesn't have any useful answers. Can they be linked?
For Core Data exceptions, what I typically do is remove the "All Exceptions" breakpoint from Xcode and instead:
Add a Symbolic Breakpoint on objc_exception_throw
Set a Condition on the Breakpoint to (BOOL)(! (BOOL)[[(NSException *)$x0 className] hasPrefix:#"_NSCoreData"])
The configured breakpoint should look something like this:
This will ignore any private Core Data exceptions (as determined by the class name being prefixed by _NSCoreData) that are used for control flow. Note that the appropriate register is going to be dependent on the target device / simulator that you are running in. Take a look at this table for reference.
Note that this technique can be adapted easily to other conditionals. The tricky part was in crafting the BOOL and NSException casts to get lldb happy with the condition.
I wrote an lldb script that lets you selectively ignore Objective-C exceptions with a much simpler syntax, and it handles both OS X, iOS Simulator, and both 32bit and 64bit ARM.
Installation
Put this script in ~/Library/lldb/ignore_specified_objc_exceptions.py or somewhere useful.
import lldb
import re
import shlex
# This script allows Xcode to selectively ignore Obj-C exceptions
# based on any selector on the NSException instance
def getRegister(target):
if target.triple.startswith('x86_64'):
return "rdi"
elif target.triple.startswith('i386'):
return "eax"
elif target.triple.startswith('arm64'):
return "x0"
else:
return "r0"
def callMethodOnException(frame, register, method):
return frame.EvaluateExpression("(NSString *)[(NSException *)${0} {1}]".format(register, method)).GetObjectDescription()
def filterException(debugger, user_input, result, unused):
target = debugger.GetSelectedTarget()
frame = target.GetProcess().GetSelectedThread().GetFrameAtIndex(0)
if frame.symbol.name != 'objc_exception_throw':
# We can't handle anything except objc_exception_throw
return None
filters = shlex.split(user_input)
register = getRegister(target)
for filter in filters:
method, regexp_str = filter.split(":", 1)
value = callMethodOnException(frame, register, method)
if value is None:
output = "Unable to grab exception from register {0} with method {1}; skipping...".format(register, method)
result.PutCString(output)
result.flush()
continue
regexp = re.compile(regexp_str)
if regexp.match(value):
output = "Skipping exception because exception's {0} ({1}) matches {2}".format(method, value, regexp_str)
result.PutCString(output)
result.flush()
# If we tell the debugger to continue before this script finishes,
# Xcode gets into a weird state where it won't refuse to quit LLDB,
# so we set async so the script terminates and hands control back to Xcode
debugger.SetAsync(True)
debugger.HandleCommand("continue")
return None
return None
def __lldb_init_module(debugger, unused):
debugger.HandleCommand('command script add --function ignore_specified_objc_exceptions.filterException ignore_specified_objc_exceptions')
Add the following to ~/.lldbinit:
command script import ~/Library/lldb/ignore_specified_objc_exceptions.py
replacing ~/Library/lldb/ignore_specified_objc_exceptions.py with the correct path if you saved it somewhere else.
Usage
In Xcode, add a breakpoint to catch all Objective-C exceptions
Edit the breakpoint and add a Debugger Command with the following command:
ignore_specified_objc_exceptions name:NSAccessibilityException className:NSSomeException
This will ignore exceptions where NSException -name matches NSAccessibilityException OR -className matches NSSomeException
It should look something like this:
In your case, you would use ignore_specified_objc_exceptions className:_NSCoreData
See http://chen.do/blog/2013/09/30/selectively-ignoring-objective-c-exceptions-in-xcode/ for the script and more details.
Here is an alternative quick answer for when you have a block of code e.g. a 3rd part library that throws multiple exceptions that you want to ignore:
Set two breakpoints, one before and one after the exception throwing block of code you want to ignore.
Run the program, until it stops at an exception, and type 'breakpoint list' into the debugger console, and find the number of the 'all exceptions' break point, it should look like this:
2: names = {'objc_exception_throw', '__cxa_throw'}, locations = 2
Options: disabled
2.1: where = libobjc.A.dylibobjc_exception_throw, address = 0x00007fff8f8da6b3, unresolved, hit count = 0
2.2: where = libc++abi.dylib__cxa_throw, address = 0x00007fff8d19fab7, unresolved, hit count = 0
This means it is breakpoint 2. Now in xcode, edit the first breakpoint (before the exception throwing code) and change the action to 'debugger command' and type in 'breakpoint disable 2' (and set 'automatically continue...' checkbox ).
Do the same for the break point after the offending line and have the command 'breakpoint enable 2'.
The all breakpoints exception will now turn on and off so it's only active when you need it.